diff --git a/org.sf.feeling.decompiler/src/org/sf/feeling/decompiler/util/JarClassExtractor.java b/org.sf.feeling.decompiler/src/org/sf/feeling/decompiler/util/JarClassExtractor.java index 9407d65a..e1303471 100644 --- a/org.sf.feeling.decompiler/src/org/sf/feeling/decompiler/util/JarClassExtractor.java +++ b/org.sf.feeling.decompiler/src/org/sf/feeling/decompiler/util/JarClassExtractor.java @@ -9,6 +9,7 @@ package org.sf.feeling.decompiler.util; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -19,15 +20,76 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.util.JRTUtil; + public class JarClassExtractor { /** - * extracts class files from jar/zip archive to specified path. See - * IDecompiler documentation for the format of pareameters. + * extracts class files from jar/zip archive or modules to specified path. + * See IDecompiler documentation for the format of pareameters. */ public static void extract( String archivePath, String packege, String className, boolean inner, String to ) throws IOException + { + if ( isClassInJrt( archivePath ) ) + { + extractClassFromJrt( archivePath, packege, className, to ); + } + else + { + extractClassesFromJar( archivePath, packege, className, inner, to ); + } + } + + private static boolean isClassInJrt( String archivePath ) + { + try + { + return archivePath.endsWith( JRTUtil.JRT_FS_JAR ); + } + catch ( NoClassDefFoundError e ) + { + // Compatible with pre-Oxygen Eclipse, where JRTUtil does not exist + return false; + } + } + + private static void extractClassFromJrt( String archivePath, String packege, String className, String to ) + throws IOException, FileNotFoundException + { + File outputFile = new File( to + File.separatorChar + className ); + try (FileOutputStream outputStream = new FileOutputStream( outputFile )) + { + File jrtPath = new File( archivePath ); + List modules = JRTUtil.getModulesDeclaringPackage( jrtPath, packege, null ); + String moduleRelativePath = packege + "/" + className; + byte[] content = findModuleWithFile( jrtPath, modules, moduleRelativePath ); + outputStream.write( content ); + } + catch ( ClassFormatException e ) + { + throw new RuntimeException( "Unable to read JRT file", e ); + } + } + + private static byte[] findModuleWithFile( File jrtPath, List modules, String moduleRelativeClassPath ) + throws IOException, ClassFormatException + { + for ( String module : modules ) + { + byte[] content = JRTUtil.getClassfileContent( jrtPath, moduleRelativeClassPath, module ); + if ( content != null ) + { + return content; + } + } + throw new RuntimeException( "No module in JRT contains class " + moduleRelativeClassPath ); + } + + private static void extractClassesFromJar( String archivePath, String packege, String className, boolean inner, + String to ) throws IOException, FileNotFoundException { ZipFile archive = new ZipFile( archivePath ); List entries = findRelevant( archive, packege, className, inner ); @@ -65,7 +127,6 @@ public static void extract( String archivePath, String packege, String className out.close( ); } } - } private static List findRelevant( ZipFile archive, String packege, String className, boolean inner ) diff --git a/pom.xml b/pom.xml index 175fd690..0075c988 100644 --- a/pom.xml +++ b/pom.xml @@ -103,9 +103,9 @@ - eclipse-juno + eclipse-oxygen p2 - http://download.eclipse.org/releases/juno + http://download.eclipse.org/releases/oxygen