2012-02-16 32 views
9

Belirli bir jar dosyasında derlenmiş sınıfların, arabirimlerin ve enumların sayısını programlı olarak saymam gerekiyor (bu nedenle üç ayrı numaraya ihtiyacım var). Hangi API bana yardımcı olur? (Üçüncü taraf kitaplıklarını kullanamıyorum.)jar dosyasını program aracılığıyla analiz edin

Her zaman doğru olmayan oldukça zor bir düzeni denedim. Yani, her bir ZipEntry'yi bir bayt [] olarak okudum ve daha sonra sonucu, CalssLoader standardını genişleten ve bu bayt [] 'ı ClassLoader.defineClass'a gönderen özel sınıf yükleyicime besliyorum (bu, koruma kodudur ve doğrudan uygulama kodundan çağrılmaz.). Tam kod on the Pastebin.

+0

ZipEntry.getName() 'ı arayabilir ve bir' .class' dosyası olup olmadığını görebilir misiniz? Veya sınıfları ve arayüzleri (ve enumlar?) Ayrı ayrı saymanız mı gerekiyor? – DNA

+0

Bunları ayrı ayrı saymam gerekiyor (ek olarak .class dosyalarının hepsinin doğru bayt kodu içermediği biliniyor). –

+0

Hatalı bayt koduna sahip .class dosyaları saymamak. –

cevap

10

Bir jar dosyası belirli bir desene sahip bir zip dosyasıdır. ZipFile ve ZipEntry veya çocuklarını JarFile ve JarEntry sınıflarında kullanabilirsiniz.

Bu kod (özel bir sınıf yükleyicinin bir yöntemi), ihtiyacınız olan her "sınıf" türünün dizilerini içeren bir Harita döndürür.

public Map<String, List<Class<?>>> loadAndScanJar(File jarFile) 
     throws ClassNotFoundException, ZipException, IOException { 

    // Load the jar file into the JVM 
    // You can remove this if the jar file already loaded. 
    super.addURL(jarFile.toURI().toURL()); 

    Map<String, List<Class<?>>> classes = new HashMap<String, List<Class<?>>>(); 

    List<Class<?>> interfaces = new ArrayList<Class<?>>(); 
    List<Class<?>> clazzes = new ArrayList<Class<?>>(); 
    List<Class<?>> enums = new ArrayList<Class<?>>(); 
    List<Class<?>> annotations = new ArrayList<Class<?>>(); 

    classes.put("interfaces", interfaces); 
    classes.put("classes", clazzes); 
    classes.put("annotations", annotations); 
    classes.put("enums", enums); 

    // Count the classes loaded 
    int count = 0; 

    // Your jar file 
    JarFile jar = new JarFile(jarFile); 
    // Getting the files into the jar 
    Enumeration<? extends JarEntry> enumeration = jar.entries(); 

    // Iterates into the files in the jar file 
    while (enumeration.hasMoreElements()) { 
     ZipEntry zipEntry = enumeration.nextElement(); 

     // Is this a class? 
     if (zipEntry.getName().endsWith(".class")) { 

      // Relative path of file into the jar. 
      String className = zipEntry.getName(); 

      // Complete class name 
      className = className.replace(".class", "").replace("/", "."); 
      // Load class definition from JVM 
      Class<?> clazz = this.loadClass(className); 

      try { 
       // Verify the type of the "class" 
       if (clazz.isInterface()) { 
        interfaces.add(clazz); 
       } else if (clazz.isAnnotation()) { 
        annotations.add(clazz); 
       } else if (clazz.isEnum()) { 
        enums.add(clazz); 
       } else { 
        clazzes.add(clazz); 
       } 

       count++; 
      } catch (ClassCastException e) { 

      } 
     } 
    } 

    System.out.println("Total: " + count); 

    return classes; 
} 
+0

Çok teşekkürler, neredeyse mükemmel çalışıyor. Bazı küçük ayrıntılar: 'super.addURL' işlevini kullanabilmek için 'URLClassLoader' sadece 'ClassLoader' değil. Ve sonra 'süper' çağrıları dizisi ile adlandırılan kurucu tanımlamanız gerekir. Keşke onu null ile besleyebildim, ama bir istisna var. Bu yüzden, bir URL'ye sahip ve jarma karşılık gelen bir dizi oluşturdum. –

+1

Boş bir diziden geçebilirsiniz ... Bu iyi çalışıyor ... Süper sınıf hakkında yanlış anlaşıldığım için üzgünüm, bu bir UrlClassloader ... – Eldius

İlgili konular