2015-07-02 30 views
2

我有一個任務來檢查一組來自classpath的未知類的條件。我想掃描它的類,加載他們每個人,並執行我的檢查。現在,我有一組URL用於類文件,並嘗試使用URLClassLoader。但要加載一個類,我需要指定一個完全限定的類名,但我沒有它們(我只有文件路徑)。我不認爲從類文件路徑構建類名是可以解決的,它是一個更好的方法嗎?從一組文件中加載類

謝謝!

+0

爲什麼從類文件路徑構建類名稱不可靠?我覺得是這樣的。我看到的唯一問題是內部類(一個類文件中有多個類)。那就是問題所在。 – Aleksandar

+0

我的Win桌面上有類似於C:\ Projects \ my_project_trunk \ module \ target \ classes \ com \ a \ b \ c \ d \ e \ f \ Smth.class和/ home/user/teamcity/agent1 /.../a/b/c/d/e/f/Smth.class在構建服務器,所以我的解析器應該找到'類'部分,構建包名等。有趣的是,爲什麼我們不能從類文件中獲取類名,它應該在那裏... – dbf

+1

我只是解析類文件的開始,尋找「包」關鍵字和第一次出現的「類」關鍵字。然後,當你結合這兩個(packageName +「。」+ className)時,它應該產生一個合適的類名。 – PiotrSliwa

回答

3

我只是解析類文件的開始,尋找「包」關鍵字和第一次出現的「類」關鍵字。然後,當你結合這兩個(packageName + "." + className)時,它應該導致適當的類名稱。

+0

PiotrSliwa,感謝您的想法。最後,我使用commons-bcel庫來解析.class文件,它有點簡單。 – dbf

1

我啓動了一個項目,一旦自動測試運行時異常的類路徑中找到類,通過調用構造函數和方法與反思狡猾的參數,像null01-1""

該項目有一個叫Finder至極類做了大概你需要:

static List<Class<?>> findClassesForPackage(String packagename, Report report) throws ClassNotFoundException { 
      // 'classes' will hold a list of directories matching the package name. 
      // There may be more than one if a package is split over multiple 
      // jars/paths 
      List<Class<?>> classes = new ArrayList<Class<?>>(); 
      List<File> directories = new ArrayList<File>(); 
      try { 
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 
        if (classLoader == null) { 
          throw new ClassNotFoundException("Can't get class loader."); 
        } 
        // Ask for all resources for the path 
        String path = packagename.replace('.', '/'); 
        Enumeration<URL> resources = classLoader.getResources(path); 
        while (resources.hasMoreElements()) { 
          URL res = resources.nextElement(); 
          if (res.getProtocol().equalsIgnoreCase("jar")) { 
            JarURLConnection conn = (JarURLConnection) res.openConnection(); 
            JarFile jar = conn.getJarFile(); 
            for (JarEntry entry : Collections.list(jar.entries())) { 
              if (entry.getName().startsWith(path) && entry.getName().endsWith(".class") 
                  && !entry.getName().contains("$")) { 
                String className = entry.getName().replace("/", ".").substring(0, 
                    entry.getName().length() - 6); 
                LOG.debug("Adding JAR className " + className); 
                try { 
                  Class<?> clazz = Class.forName(className); 
                  classes.add(clazz); 
                  report.addClass(className); 
                } catch (Throwable throwable) { 
                  ParamSet params = new ParamSet(); 
                  params.addParamValue(new ParamValue(className, "fully qualified classname")); 
                  report.addError(className, new Error("Class.forName()", params, throwable)); 
                } 
              } 
            } 
          } else 
            directories.add(new File(URLDecoder.decode(res.getPath(), "UTF-8"))); 
        } 
      } catch (NullPointerException e) { 
        throw new ClassNotFoundException(String.format("%s does not appear to be a valid package", packagename), e); 
      } catch (UnsupportedEncodingException e) { 
        throw new ClassNotFoundException(String.format("%s does not appear to be a valid package", packagename), e); 
      } catch (IOException e) { 
        throw new ClassNotFoundException(String.format("Could not get all resources for %s", packagename), e); 
      } 
      List<String> subPackages = new ArrayList<String>(); 
      // For every directory identified capture all the .class files 
      for (File directory : directories) { 
        if (directory.exists()) { 
          // Get the list of the files contained in the package 
          File[] files = directory.listFiles(); 
          for (File file : files) { 
            // add .class files to results 
            String fileName = file.getName(); 
            if (file.isFile() && fileName.endsWith(".class")) { 
              // removes the .class extension 
              String className = packagename + '.' + fileName.substring(0, fileName.length() - 6); 
              LOG.debug("Adding FILE className " + className); 
              try { 
                Class<?> clazz = Class.forName(className); 
                classes.add(clazz); 
                report.addClass(className); 
              } catch (Throwable throwable) { 
                ParamSet params = new ParamSet(); 
                params.addParamValue(new ParamValue(className, "fully qualified classname")); 
                report.addError(className, new Error("Class.forName()", params, throwable)); 
              } 
            } 
            // keep track of subdirectories 
            if (file.isDirectory()) { 
              subPackages.add(packagename + "." + fileName); 
            } 
          } 
        } else { 
          throw new ClassNotFoundException(String.format("%s (%s) does not appear to be a valid package", 
              packagename, directory.getPath())); 
        } 
      } 
      // check all potential subpackages 
      for (String subPackage : subPackages) { 
        classes.addAll(findClassesForPackage(subPackage, report)); 
      } 
      return classes; 
    } 

你可能不得不剝離一些代碼,並報告等