2013-01-03 100 views
0

我想從jar中提取一個類文件(如果它在jar中)並將其保存到目標文件夾中。通過classname從類路徑中的jar中提取類文件

這是我現在有:

Class Myclass = Thread.currentThread().getContextClassLoader().loadClass(className); 
String pathJar = classs.getProtectionDomain().getCodeSource().getLocation().getPath(); 

pathJar保存路徑與類的罐子。

現在,我如何從那裏提取類?

+0

當您構建它時,在Jar中的已知位置包含資源列表。閱讀它然後迭代列表並加載每個資源。 –

回答

0

下面的代碼,它是活的,通過ivy依賴性報告的XML文件解析,並從罐中提取的所有文件,我希望你能有所幫助:

private void extract(String path2, String outPath) { 
       JarFile zf = null; 
       try { 
         zf = new JarFile(path2); 
       } catch (IOException e4) { 
         // according to http://stackoverflow.com/a/470492/783412, set the 
         // logger to log these events 
         System.setProperty("java.util.logging.ConsoleHandler.level", 
             "FINER"); 
         logger.throwing(
             Thread.currentThread().getStackTrace()[1].getClassName(), 
             Thread.currentThread().getStackTrace()[1].getMethodName(), 
             e4); 

         // according to 
         // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, 
         // the default logging level is INFO 
         System.setProperty("java.util.logging.ConsoleHandler.level", "INFO"); 
       } 
       if (zf == null) { 
         System.err.println(path2 + " is an invalid jar, skipping"); 
         return; 
       } 
       Enumeration<JarEntry> ze = (Enumeration<JarEntry>) zf.entries(); 
       while (ze.hasMoreElements()) { 
         JarEntry thisEntry = ze.nextElement(); 
         System.err.println(thisEntry.getName()); 
         if (thisEntry.isDirectory()) { 
           new File(outPath + File.separator + thisEntry.getName()) 
               .mkdirs(); 
         } else { 
           String filename = thisEntry.getName(); 
           if (filename.endsWith("RSA") || filename.endsWith("DSA") || filename.endsWith("SF")) continue; 
           FileOutputStream fos = null; 
           try { 
             fos = new FileOutputStream(outPath + File.separator 
                 + filename); 
           } catch (FileNotFoundException e3) { 
             // according to http://stackoverflow.com/a/470492/783412, 
             // set the logger to log these events 
             System.setProperty(
                 "java.util.logging.ConsoleHandler.level", "FINER"); 
             logger.throwing(Thread.currentThread().getStackTrace()[1] 
                 .getClassName(), Thread.currentThread() 
                 .getStackTrace()[1].getMethodName(), e3); 

             // according to 
             // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, 
             // the default logging level is INFO 
             System.setProperty(
                 "java.util.logging.ConsoleHandler.level", "INFO"); 
           } 
           BufferedInputStream zis = null; 
           try { 
             zis = new BufferedInputStream(zf.getInputStream(thisEntry)); 
           } catch (IOException e2) { 
             // according to http://stackoverflow.com/a/470492/783412, 
             // set the logger to log these events 
             System.setProperty(
                 "java.util.logging.ConsoleHandler.level", "FINER"); 
             logger.throwing(Thread.currentThread().getStackTrace()[1] 
                 .getClassName(), Thread.currentThread() 
                 .getStackTrace()[1].getMethodName(), e2); 

             // according to 
             // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, 
             // the default logging level is INFO 
             System.setProperty(
                 "java.util.logging.ConsoleHandler.level", "INFO"); 
           } 
           try { 
             fos = new FileOutputStream(outPath + File.separator 
                 + thisEntry.getName()); 
           } catch (FileNotFoundException e1) { 
             // according to http://stackoverflow.com/a/470492/783412, 
             // set the logger to log these events 
             System.setProperty(
                 "java.util.logging.ConsoleHandler.level", "FINER"); 
             logger.throwing(Thread.currentThread().getStackTrace()[1] 
                 .getClassName(), Thread.currentThread() 
                 .getStackTrace()[1].getMethodName(), e1); 

             // according to 
             // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, 
             // the default logging level is INFO 
             System.setProperty(
                 "java.util.logging.ConsoleHandler.level", "INFO"); 
           } 
           byte[] b = new byte[new Long(thisEntry.getSize()).intValue()]; 
           try { 
             zis.read(b); 
           } catch (IOException e1) { 
             // according to http://stackoverflow.com/a/470492/783412, set the logger to log these events 
             System.setProperty("java.util.logging.ConsoleHandler.level","FINER"); 
             logger.throwing(Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName(), e1); 

             // according to http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, the default logging level is INFO 
             System.setProperty("java.util.logging.ConsoleHandler.level", "INFO");   
           } 
           try { 
                 .getClassName(), Thread.currentThread() 
                 .getStackTrace()[1].getMethodName(), e1); 

             // according to 
             // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, 
             // the default logging level is INFO 
             System.setProperty(
                 "java.util.logging.ConsoleHandler.level", "INFO"); 
           } 
           byte[] b = new byte[new Long(thisEntry.getSize()).intValue()]; 
           try { 
             zis.read(b); 
           } catch (IOException e1) { 
             // according to http://stackoverflow.com/a/470492/783412, set the logger to log these events 
             System.setProperty("java.util.logging.ConsoleHandler.level","FINER"); 
             logger.throwing(Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName(), e1); 

             // according to http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, the default logging level is INFO 
             System.setProperty("java.util.logging.ConsoleHandler.level", "INFO");   
           } 
           try { 
             fos.write(b); 
           } catch (IOException e1) { 
             // according to http://stackoverflow.com/a/470492/783412, set the logger to log these events 
             System.setProperty("java.util.logging.ConsoleHandler.level","FINER"); 
             logger.throwing(Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName(), e1); 
             // according to http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, the default logging level is INFO 
             System.setProperty("java.util.logging.ConsoleHandler.level", "INFO");   
           } 
           try { 
             fos.close(); 
           } catch (IOException e) { 
             // according to http://stackoverflow.com/a/470492/783412, 
             // set the logger to log these events 
             System.setProperty(
                 "java.util.logging.ConsoleHandler.level", "FINER"); 
             logger.throwing(Thread.currentThread().getStackTrace()[1] 
                 .getClassName(), Thread.currentThread() 
                 .getStackTrace()[1].getMethodName(), e); 

             // according to 
             // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, 
             // the default logging level is INFO 
             System.setProperty(
                 "java.util.logging.ConsoleHandler.level", "INFO"); 
           } 
         } 
       } 
     } 
0

檢查,如果你可以利用ASM爲你的要求。還有其他幾個選項,如BCEL

0

當你的類路徑中有你的類時,你應該能夠直接從內存中提取你的類以及它的所有內部類。至少在Oracle 1.8 JVM上,內部類將以$分隔。

import java.io.IOException; 
import java.io.InputStream; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 

public class ExtractClass { 
    public static void main(String... args) throws ClassNotFoundException, IOException { 
     final String name = args[0]; 

     extractClass(name, Paths.get(name)); 
    } 

    private static void extractClass(final String name, final Path path) throws IOException, ClassNotFoundException { 
     final Class<?> clazz = Class.forName(name); 

     try (InputStream inputStream = Object.class.getResourceAsStream("/" + name.replace(".", "/") + ".class")) { 
      Files.copy(inputStream, Paths.get(name)); 
     } 

     // Retrieve all inner classes 
     for (final Class<?> innerClass : clazz.getDeclaredClasses()) { 
      extractClass(innerClass.getName(), Paths.get(innerClass.getName())); 
     } 
    } 
}