diff options
Diffstat (limited to 'src/org/jetbrains/java/decompiler/main')
16 files changed, 318 insertions, 441 deletions
diff --git a/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/src/org/jetbrains/java/decompiler/main/ClassWriter.java index 29307e5..63f60ba 100644 --- a/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -630,7 +630,7 @@ public class ClassWriter { if (isEnum && init) actualParams -= 2; if (actualParams != descriptor.params.size()) { String message = "Inconsistent generic signature in method " + mt.getName() + " " + mt.getDescriptor(); - DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.WARNING); + DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN); descriptor = null; } } diff --git a/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java b/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java index 74c86d0..6faad08 100644 --- a/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java +++ b/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java @@ -113,7 +113,7 @@ public class ClassesProcessor { else { if (!InterpreterUtil.equalObjectArrays(arrold, arr)) { DecompilerContext.getLogger() - .writeMessage("Inconsistent inner class entries for " + innername + "!", IFernflowerLogger.WARNING); + .writeMessage("Inconsistent inner class entries for " + innername + "!", IFernflowerLogger.Severity.WARN); } } @@ -178,7 +178,8 @@ public class ClassesProcessor { ClassNode nestednode = mapRootClasses.get(nestedClass); if (nestednode == null) { - DecompilerContext.getLogger().writeMessage("Nested class " + nestedClass + " missing!", IFernflowerLogger.WARNING); + DecompilerContext.getLogger().writeMessage("Nested class " + nestedClass + " missing!", + IFernflowerLogger.Severity.WARN); continue; } @@ -204,7 +205,7 @@ public class ClassesProcessor { if (interfaces.length > 0) { if (interfaces.length > 1) { DecompilerContext.getLogger() - .writeMessage("Inconsistent anonymous class definition: " + cl.qualifiedName, IFernflowerLogger.WARNING); + .writeMessage("Inconsistent anonymous class definition: " + cl.qualifiedName, IFernflowerLogger.Severity.WARN); } nestednode.anonimousClassType = new VarType(cl.getInterface(0), true); } diff --git a/src/org/jetbrains/java/decompiler/main/DecompilerContext.java b/src/org/jetbrains/java/decompiler/main/DecompilerContext.java index 54c426b..b600250 100644 --- a/src/org/jetbrains/java/decompiler/main/DecompilerContext.java +++ b/src/org/jetbrains/java/decompiler/main/DecompilerContext.java @@ -132,12 +132,12 @@ public class DecompilerContext { public static void setLogger(IFernflowerLogger logger) { if (logger != null) { - String severity = (String)getProperty(IFernflowerPreferences.LOG_LEVEL); - if (severity != null) { - Integer iSeverity = IFernflowerLogger.mapLogLevel.get(severity.toUpperCase(Locale.US)); - if (iSeverity != null) { - logger.setSeverity(iSeverity); + String level = (String)getProperty(IFernflowerPreferences.LOG_LEVEL); + if (level != null) { + try { + logger.setSeverity(IFernflowerLogger.Severity.valueOf(level.toUpperCase(Locale.US))); } + catch (IllegalArgumentException ignore) { } } } getCurrentContext().logger = logger; diff --git a/src/org/jetbrains/java/decompiler/main/Fernflower.java b/src/org/jetbrains/java/decompiler/main/Fernflower.java index 34f9196..62b8ee4 100644 --- a/src/org/jetbrains/java/decompiler/main/Fernflower.java +++ b/src/org/jetbrains/java/decompiler/main/Fernflower.java @@ -18,7 +18,8 @@ package org.jetbrains.java.decompiler.main; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider; -import org.jetbrains.java.decompiler.main.extern.IDecompilatSaver; +import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; +import org.jetbrains.java.decompiler.main.extern.IResultSaver; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.modules.renamer.IdentifierConverter; import org.jetbrains.java.decompiler.struct.IDecompiledData; @@ -28,16 +29,16 @@ import org.jetbrains.java.decompiler.struct.lazy.LazyLoader; import java.util.Map; - public class Fernflower implements IDecompiledData { private StructContext structContext; private ClassesProcessor classesProcessor; - public Fernflower(IBytecodeProvider provider, IDecompilatSaver saver, Map<String, Object> propertiesCustom) { + public Fernflower(IBytecodeProvider provider, IResultSaver saver, Map<String, Object> options, IFernflowerLogger logger) { structContext = new StructContext(saver, this, new LazyLoader(provider)); - DecompilerContext.initContext(propertiesCustom); + DecompilerContext.initContext(options); DecompilerContext.setCounterContainer(new CounterContainer()); + DecompilerContext.setLogger(logger); } public void decompileContext() { @@ -57,6 +58,11 @@ public class Fernflower implements IDecompiledData { DecompilerContext.setCurrentContext(null); } + public StructContext getStructContext() { + return structContext; + } + + @Override public String getClassEntryName(StructClass cl, String entryName) { ClassNode node = classesProcessor.getMapRootClasses().get(cl.qualifiedName); if (node.type != ClassNode.CLASS_ROOT) { @@ -73,10 +79,7 @@ public class Fernflower implements IDecompiledData { } } - public StructContext getStructContext() { - return structContext; - } - + @Override public String getClassContent(StructClass cl) { try { StringBuilder buffer = new StringBuilder(); diff --git a/src/org/jetbrains/java/decompiler/main/decompiler/IdeDecompiler.java b/src/org/jetbrains/java/decompiler/main/decompiler/BaseDecompiler.java index 212a8bd..07b8578 100644 --- a/src/org/jetbrains/java/decompiler/main/decompiler/IdeDecompiler.java +++ b/src/org/jetbrains/java/decompiler/main/decompiler/BaseDecompiler.java @@ -15,28 +15,21 @@ */ package org.jetbrains.java.decompiler.main.decompiler; -import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.Fernflower; import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider; -import org.jetbrains.java.decompiler.main.extern.IDecompilatSaver; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; +import org.jetbrains.java.decompiler.main.extern.IResultSaver; import java.io.File; import java.io.IOException; -import java.util.HashMap; +import java.util.Map; +public class BaseDecompiler { -public class IdeDecompiler { + private final Fernflower fernflower; - private Fernflower fernflower; - - public IdeDecompiler(IBytecodeProvider provider, - IDecompilatSaver saver, IFernflowerLogger logger, - HashMap<String, Object> propertiesCustom) { - - fernflower = new Fernflower(provider, saver, propertiesCustom); - - DecompilerContext.setLogger(logger); + public BaseDecompiler(IBytecodeProvider provider, IResultSaver saver, Map<String, Object> options, IFernflowerLogger logger) { + fernflower = new Fernflower(provider, saver, options, logger); } public void addSpace(File file, boolean isOwn) throws IOException { diff --git a/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java b/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java index d499324..a486d9f 100644 --- a/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java +++ b/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java @@ -17,10 +17,9 @@ package org.jetbrains.java.decompiler.main.decompiler; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.Fernflower; -import org.jetbrains.java.decompiler.main.decompiler.helper.PrintStreamLogger; import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider; -import org.jetbrains.java.decompiler.main.extern.IDecompilatSaver; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; +import org.jetbrains.java.decompiler.main.extern.IResultSaver; import org.jetbrains.java.decompiler.util.InterpreterUtil; import java.io.*; @@ -31,108 +30,97 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; -@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace"}) -public class ConsoleDecompiler implements IBytecodeProvider, IDecompilatSaver { +public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver { - private File root; + @SuppressWarnings("UseOfSystemOutOrSystemErr") + public static void main(String[] args) { + if (args.length < 2) { + System.out.println( + "Usage: java -jar fernflower.jar [-<option>=<value>]* [<source>]+ <destination>\n" + + "Example: java -jar fernflower.jar -dgs=true c:\\my\\source\\ c:\\my.jar d:\\decompiled\\"); + return; + } - private Fernflower fernflower; + Map<String, Object> mapOptions = new HashMap<String, Object>(); + List<String> lstSources = new ArrayList<String>(); + List<String> lstLibraries = new ArrayList<String>(); - private HashMap<String, ZipOutputStream> mapArchiveStreams = new HashMap<String, ZipOutputStream>(); + boolean isOption = true; + for (int i = 0; i < args.length - 1; ++i) { // last parameter - destination + String arg = args[i]; - private HashMap<String, HashSet<String>> mapArchiveEntries = new HashMap<String, HashSet<String>>(); + if (isOption && arg.startsWith("-") && + arg.length() > 5 && arg.charAt(4) == '=') { + String value = arg.substring(5).toUpperCase(Locale.US); + if ("TRUE".equals(value)) { + value = "1"; + } + else if ("FALSE".equals(value)) { + value = "0"; + } - public ConsoleDecompiler() { - this(null); - } + mapOptions.put(arg.substring(1, 4), value); + } + else { + isOption = false; - public ConsoleDecompiler(HashMap<String, Object> propertiesCustom) { - this(new PrintStreamLogger(IFernflowerLogger.WARNING, System.out), propertiesCustom); - } + if (arg.startsWith("-e=")) { + lstLibraries.add(arg.substring(3)); + } + else { + lstSources.add(arg); + } + } + } - protected ConsoleDecompiler(IFernflowerLogger logger, HashMap<String, Object> propertiesCustom) { - fernflower = new Fernflower(this, this, propertiesCustom); - DecompilerContext.setLogger(logger); - } + if (lstSources.isEmpty()) { + System.out.println("error: no sources given"); + return; + } - public static void main(String[] args) { + File destination = new File(args[args.length - 1]); + if (!destination.isDirectory()) { + System.out.println("error: destination '" + destination + "' is not a directory"); + return; + } - try { + PrintStreamLogger logger = new PrintStreamLogger(System.out); + ConsoleDecompiler decompiler = new ConsoleDecompiler(destination, mapOptions, logger); - if (args != null && args.length > 1) { - - HashMap<String, Object> mapOptions = new HashMap<String, Object>(); - - List<String> lstSources = new ArrayList<String>(); - List<String> lstLibraries = new ArrayList<String>(); - - boolean isOption = true; - for (int i = 0; i < args.length - 1; ++i) { // last parameter - destination - String arg = args[i]; - - if (isOption && arg.startsWith("-") && - arg.length() > 5 && arg.charAt(4) == '=') { - String value = arg.substring(5).toUpperCase(Locale.US); - if ("TRUE".equals(value)) { - value = "1"; - } - else if ("FALSE".equals(value)) { - value = "0"; - } - - mapOptions.put(arg.substring(1, 4), value); - } - else { - isOption = false; - - if (arg.startsWith("-e=")) { - lstLibraries.add(arg.substring(3)); - } - else { - lstSources.add(arg); - } - } - } + for (String source : lstSources) { + decompiler.addSpace(new File(source), true); + } + for (String library : lstLibraries) { + decompiler.addSpace(new File(library), false); + } - if (lstSources.isEmpty()) { - printHelp(); - } - else { - ConsoleDecompiler decompiler = new ConsoleDecompiler( - new PrintStreamLogger(IFernflowerLogger.INFO, System.out), - mapOptions); + decompiler.decompileContext(); + } - for (String source : lstSources) { - decompiler.addSpace(new File(source), true); - } + // ******************************************************************* + // Implementation + // ******************************************************************* - for (String library : lstLibraries) { - decompiler.addSpace(new File(library), false); - } + private final File root; + private final Fernflower fernflower; + private Map<String, ZipOutputStream> mapArchiveStreams = new HashMap<String, ZipOutputStream>(); + private Map<String, Set<String>> mapArchiveEntries = new HashMap<String, Set<String>>(); - decompiler.decompileContext(new File(args[args.length - 1])); - } - } - else { - printHelp(); - } - } - catch (Exception ex) { - ex.printStackTrace(); - } + @SuppressWarnings("UseOfSystemOutOrSystemErr") + public ConsoleDecompiler(File destination, Map<String, Object> options) { + this(destination, options, new PrintStreamLogger(System.out)); } - private static void printHelp() { - System.out.println("Usage: java ConsoleDecompiler ( -<option>=<value>)* (<source>)+ <destination>"); - System.out.println("Example: java ConsoleDecompiler -dgs=true c:\\mysource\\ c:\\my.jar d:\\decompiled\\"); + protected ConsoleDecompiler(File destination, Map<String, Object> options, IFernflowerLogger logger) { + root = destination; + fernflower = new Fernflower(this, this, options, logger); } - public void addSpace(File file, boolean isOwn) throws IOException { + public void addSpace(File file, boolean isOwn) { fernflower.getStructContext().addSpace(file, isOwn); } - public void decompileContext(File root) { - this.root = root; + public void decompileContext() { try { fernflower.decompileContext(); } @@ -145,183 +133,167 @@ public class ConsoleDecompiler implements IBytecodeProvider, IDecompilatSaver { // Interface IBytecodeProvider // ******************************************************************* - public InputStream getBytecodeStream(String externPath, String internPath) { - - try { - File file = new File(externPath); - - if (internPath == null) { - return new FileInputStream(file); - } - else { // archive file - ZipFile archive = new ZipFile(file); - - Enumeration<? extends ZipEntry> en = archive.entries(); - while (en.hasMoreElements()) { - ZipEntry entr = en.nextElement(); - - if (entr.getName().equals(internPath)) { - return archive.getInputStream(entr); - } + @Override + public byte[] getBytecode(String externalPath, String internalPath) throws IOException { + File file = new File(externalPath); + if (internalPath == null) { + return InterpreterUtil.getBytes(file); + } + else { + ZipFile archive = new ZipFile(file); + try { + ZipEntry entry = archive.getEntry(internalPath); + if (entry == null) { + throw new IOException("Entry not found: " + internalPath); } + return InterpreterUtil.getBytes(archive, entry); + } + finally { + archive.close(); } } - catch (IOException ex) { - ex.printStackTrace(); - } - - return null; } // ******************************************************************* - // Interface IDecompilatSaver + // Interface IResultSaver // ******************************************************************* private String getAbsolutePath(String path) { return new File(root, path).getAbsolutePath(); } - private boolean addEntryName(String filename, String entry) { - HashSet<String> set = mapArchiveEntries.get(filename); - if (set == null) { - mapArchiveEntries.put(filename, set = new HashSet<String>()); + @Override + public void saveFolder(String path) { + File dir = new File(getAbsolutePath(path)); + if (!(dir.mkdirs() || dir.isDirectory())) { + throw new RuntimeException("Cannot create directory " + dir); } - - return set.add(entry); } - public void copyEntry(String source, String destpath, String archivename, String entryName) { - + @Override + public void copyFile(String source, String path, String entryName) { try { - String filename = new File(getAbsolutePath(destpath), archivename).getAbsolutePath(); - - if (!addEntryName(filename, entryName)) { - DecompilerContext.getLogger().writeMessage("Zip entry already exists: " + - destpath + "," + archivename + "," + entryName, IFernflowerLogger.WARNING); - return; - } - - ZipFile srcarchive = new ZipFile(new File(source)); - - Enumeration<? extends ZipEntry> en = srcarchive.entries(); - while (en.hasMoreElements()) { - ZipEntry entr = en.nextElement(); - - if (entr.getName().equals(entryName)) { - InputStream in = srcarchive.getInputStream(entr); - - ZipOutputStream out = mapArchiveStreams.get(filename); - out.putNextEntry(new ZipEntry(entryName)); - - InterpreterUtil.copyStream(in, out); - in.close(); - } - } - - srcarchive.close(); + InterpreterUtil.copyFile(new File(source), new File(getAbsolutePath(path), entryName)); } catch (IOException ex) { - DecompilerContext.getLogger() - .writeMessage("Error copying zip file entry: " + source + "," + destpath + "," + archivename + "," + entryName, - IFernflowerLogger.WARNING); - ex.printStackTrace(); + DecompilerContext.getLogger().writeMessage("Cannot copy " + source + " to " + entryName, ex); } } - public void copyFile(String source, String destpath, String destfilename) { + @Override + public void saveClassFile(String path, String qualifiedName, String entryName, String content) { + File file = new File(getAbsolutePath(path), entryName); try { - InterpreterUtil.copyFile(new File(source), new File(destfilename)); + Writer out = new OutputStreamWriter(new FileOutputStream(file), "UTF8"); + try { + out.write(content); + } + finally { + out.close(); + } } catch (IOException ex) { - ex.printStackTrace(); + DecompilerContext.getLogger().writeMessage("Cannot write class file " + file, ex); } } - public void saveFile(String path, String filename, String content) { + @Override + public void createArchive(String path, String archiveName, Manifest manifest) { + File file = new File(getAbsolutePath(path), archiveName); try { - BufferedWriter out = - new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(getAbsolutePath(path), filename)), "UTF8")); - out.write(content); - out.flush(); - out.close(); + if (!(file.createNewFile() || file.isFile())) { + throw new IOException("Cannot create file " + file); + } + + FileOutputStream fileStream = new FileOutputStream(file); + @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") + ZipOutputStream zipStream = manifest != null ? new JarOutputStream(fileStream, manifest) : new ZipOutputStream(fileStream); + mapArchiveStreams.put(file.getPath(), zipStream); } catch (IOException ex) { - ex.printStackTrace(); + DecompilerContext.getLogger().writeMessage("Cannot create archive " + file, ex); } } - public void createArchive(String path, String archivename, Manifest manifest) { + @Override + public void saveDirEntry(String path, String archiveName, String entryName) { + saveClassEntry(path, archiveName, null, entryName, null); + } - try { - File file = new File(getAbsolutePath(path), archivename); - file.createNewFile(); + @Override + public void copyEntry(String source, String path, String archiveName, String entryName) { + String file = new File(getAbsolutePath(path), archiveName).getPath(); + + if (!checkEntry(entryName, file)) { + return; + } - ZipOutputStream out; - if (manifest != null) { // jar - out = new JarOutputStream(new FileOutputStream(file), manifest); + try { + ZipFile srcArchive = new ZipFile(new File(source)); + try { + ZipEntry entry = srcArchive.getEntry(entryName); + if (entry != null) { + InputStream in = srcArchive.getInputStream(entry); + ZipOutputStream out = mapArchiveStreams.get(file); + out.putNextEntry(new ZipEntry(entryName)); + InterpreterUtil.copyStream(in, out); + in.close(); + } } - else { - out = new ZipOutputStream(new FileOutputStream(file)); + finally { + srcArchive.close(); } - mapArchiveStreams.put(file.getAbsolutePath(), out); } catch (IOException ex) { - ex.printStackTrace(); + String message = "Cannot copy entry " + entryName + " from " + source + " to " + file; + DecompilerContext.getLogger().writeMessage(message, ex); } } - public void saveClassEntry(String path, String archivename, - String qualifiedName, String entryName, String content) { - saveEntry(path, archivename, entryName, content); - } + @Override + public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) { + String file = new File(getAbsolutePath(path), archiveName).getPath(); - public void saveClassFile(String path, String qualifiedName, String entryName, String content) { - saveFile(path, entryName, content); - } - - public void saveEntry(String path, String archivename, String entryName, - String content) { + if (!checkEntry(entryName, file)) { + return; + } try { - String filename = new File(getAbsolutePath(path), archivename).getAbsolutePath(); - - if (!addEntryName(filename, entryName)) { - DecompilerContext.getLogger().writeMessage("Zip entry already exists: " + - path + "," + archivename + "," + entryName, IFernflowerLogger.WARNING); - return; - } - - ZipOutputStream out = mapArchiveStreams.get(filename); + ZipOutputStream out = mapArchiveStreams.get(file); out.putNextEntry(new ZipEntry(entryName)); - if (content != null) { - BufferedWriter outwriter = new BufferedWriter(new OutputStreamWriter(out, "UTF8")); - outwriter.write(content); - outwriter.flush(); + out.write(content.getBytes("UTF-8")); } } catch (IOException ex) { - ex.printStackTrace(); + String message = "Cannot write entry " + entryName + " to " + file; + DecompilerContext.getLogger().writeMessage(message, ex); } } - public void saveFolder(String path) { - File f = new File(getAbsolutePath(path)); - f.mkdirs(); - } + private boolean checkEntry(String entryName, String file) { + Set<String> set = mapArchiveEntries.get(file); + if (set == null) { + mapArchiveEntries.put(file, set = new HashSet<String>()); + } + boolean added = set.add(entryName); + if (!added) { + String message = "Zip entry " + entryName + " already exists in " + file; + DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN); + } + return added; + } - public void closeArchive(String path, String archivename) { + @Override + public void closeArchive(String path, String archiveName) { + String file = new File(getAbsolutePath(path), archiveName).getPath(); try { - String filename = new File(getAbsolutePath(path), archivename).getAbsolutePath(); - - mapArchiveEntries.remove(filename); - OutputStream out = mapArchiveStreams.remove(filename); - out.flush(); - out.close(); + mapArchiveEntries.remove(file); + mapArchiveStreams.remove(file).close(); } catch (IOException ex) { - ex.printStackTrace(); + DecompilerContext.getLogger().writeMessage("Cannot close " + file, IFernflowerLogger.Severity.WARN); } } } diff --git a/src/org/jetbrains/java/decompiler/main/decompiler/PrintStreamLogger.java b/src/org/jetbrains/java/decompiler/main/decompiler/PrintStreamLogger.java new file mode 100644 index 0000000..7bbcc19 --- /dev/null +++ b/src/org/jetbrains/java/decompiler/main/decompiler/PrintStreamLogger.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.java.decompiler.main.decompiler; + +import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; +import org.jetbrains.java.decompiler.util.InterpreterUtil; + +import java.io.PrintStream; + +public class PrintStreamLogger extends IFernflowerLogger { + + private final PrintStream stream; + private int indent; + + public PrintStreamLogger(PrintStream printStream) { + stream = printStream; + indent = 0; + } + + @Override + public void writeMessage(String message, Severity severity) { + if (accepts(severity)) { + stream.println(InterpreterUtil.getIndentString(indent) + severity.name() + ": " + message); + } + } + + @Override + public void writeMessage(String message, Throwable t) { + writeMessage(message, Severity.ERROR); + if (accepts(Severity.ERROR)) { + t.printStackTrace(stream); + } + } + + @Override + public void startClass(String className) { + writeMessage("Processing class " + className + " ...", Severity.INFO); + ++indent; + } + + @Override + public void endClass() { + --indent; + writeMessage("... proceeded.", Severity.INFO); + } + + @Override + public void startWriteClass(String className) { + writeMessage("Writing class " + className + " ...", Severity.INFO); + ++indent; + } + + @Override + public void endWriteClass() { + --indent; + writeMessage("... written.", Severity.INFO); + } + + @Override + public void startMethod(String methodName) { + writeMessage("Processing method " + methodName + " ...", Severity.INFO); + } + + public void endMethod() { + writeMessage("... proceeded.", Severity.INFO); + } +} diff --git a/src/org/jetbrains/java/decompiler/main/decompiler/WebDecompiler.java b/src/org/jetbrains/java/decompiler/main/decompiler/WebDecompiler.java deleted file mode 100644 index 06e4c6f..0000000 --- a/src/org/jetbrains/java/decompiler/main/decompiler/WebDecompiler.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.java.decompiler.main.decompiler; - -import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; - -import java.io.File; -import java.util.HashMap; -import java.util.HashSet; - - -public class WebDecompiler extends ConsoleDecompiler { - - private HashMap<String, File> mapInputFilenames = new HashMap<String, File>(); - - private HashSet<String> setClassFiles = new HashSet<String>(); - - private File root; - - public WebDecompiler(IFernflowerLogger logger, HashMap<String, Object> propertiesCustom) { - super(logger, propertiesCustom); - } - - @Override - public void decompileContext(File root) { - this.root = root; - super.decompileContext(root); - } - - @Override - public void copyFile(String source, String destpath, String destfilename) { - super.copyFile(source, destpath, destfilename); - mapInputFilenames.put(destfilename, new File(getAbsolutePath(destpath), destfilename)); - } - - @Override - public void saveFile(String path, String filename, String content) { - super.saveFile(path, filename, content); - - mapInputFilenames.put(setClassFiles.contains(filename) ? - filename.substring(0, filename.lastIndexOf(".java")) + ".class" : - filename, new File(getAbsolutePath(path), filename)); - } - - @Override - public void saveClassFile(String path, String qualifiedName, String entryName, String content) { - setClassFiles.add(entryName); - saveFile(path, entryName, content); - } - - @Override - public void closeArchive(String path, String archivename) { - super.closeArchive(path, archivename); - mapInputFilenames.put(archivename, new File(getAbsolutePath(path), archivename)); - } - - private String getAbsolutePath(String path) { - return new File(root, path).getAbsolutePath(); - } - - public HashMap<String, File> getMapInputFilenames() { - return mapInputFilenames; - } -} - diff --git a/src/org/jetbrains/java/decompiler/main/decompiler/helper/PrintStreamLogger.java b/src/org/jetbrains/java/decompiler/main/decompiler/helper/PrintStreamLogger.java deleted file mode 100644 index 3a6c7e8..0000000 --- a/src/org/jetbrains/java/decompiler/main/decompiler/helper/PrintStreamLogger.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.java.decompiler.main.decompiler.helper; - -import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; -import org.jetbrains.java.decompiler.util.InterpreterUtil; - -import java.io.PrintStream; - -public class PrintStreamLogger implements IFernflowerLogger { - - private int severity; - - private int indent; - - private PrintStream stream; - - public PrintStreamLogger(int severity, PrintStream stream) { - this.severity = severity; - this.indent = 0; - this.stream = stream; - } - - - public void writeMessage(String message, int severity) { - if (severity >= this.severity) { - stream.println(InterpreterUtil.getIndentString(indent) + names[severity] + ": " + message); - } - } - - public void writeMessage(String message, Throwable t) { - t.printStackTrace(stream); - writeMessage(message, ERROR); - } - - public void startClass(String classname) { - stream.println(InterpreterUtil.getIndentString(indent++) + "Processing class " + classname + " ..."); - } - - public void endClass() { - stream.println(InterpreterUtil.getIndentString(--indent) + "... proceeded."); - } - - public void startWriteClass(String classname) { - stream.println(InterpreterUtil.getIndentString(indent++) + "Writing class " + classname + " ..."); - } - - public void endWriteClass() { - stream.println(InterpreterUtil.getIndentString(--indent) + "... written."); - } - - public void startMethod(String method) { - if (severity <= INFO) { - stream.println(InterpreterUtil.getIndentString(indent) + "Processing method " + method + " ..."); - } - } - - public void endMethod() { - if (severity <= INFO) { - stream.println(InterpreterUtil.getIndentString(indent) + "... proceeded."); - } - } - - public int getSeverity() { - return severity; - } - - public void setSeverity(int severity) { - this.severity = severity; - } -} diff --git a/src/org/jetbrains/java/decompiler/main/extern/IBytecodeProvider.java b/src/org/jetbrains/java/decompiler/main/extern/IBytecodeProvider.java index 8fe0b31..adf3270 100644 --- a/src/org/jetbrains/java/decompiler/main/extern/IBytecodeProvider.java +++ b/src/org/jetbrains/java/decompiler/main/extern/IBytecodeProvider.java @@ -15,9 +15,8 @@ */ package org.jetbrains.java.decompiler.main.extern; -import java.io.InputStream; +import java.io.IOException; public interface IBytecodeProvider { - - InputStream getBytecodeStream(String externPath, String internPath); + byte[] getBytecode(String externalPath, String internalPath) throws IOException; } diff --git a/src/org/jetbrains/java/decompiler/main/extern/IFernflowerLogger.java b/src/org/jetbrains/java/decompiler/main/extern/IFernflowerLogger.java index d9c8f74..65b2c6d 100644 --- a/src/org/jetbrains/java/decompiler/main/extern/IFernflowerLogger.java +++ b/src/org/jetbrains/java/decompiler/main/extern/IFernflowerLogger.java @@ -15,43 +15,35 @@ */ package org.jetbrains.java.decompiler.main.extern; -import java.util.HashMap; +public abstract class IFernflowerLogger { -public interface IFernflowerLogger { + public enum Severity { + TRACE, INFO, WARN, ERROR + } - int TRACE = 1; - int INFO = 2; - int WARNING = 3; - int ERROR = 4; - int IMMEDIATE = 5; + private Severity severity = Severity.INFO; - HashMap<String, Integer> mapLogLevel = new HashMap<String, Integer>() {{ - put("TRACE", 1); - put("INFO", 2); - put("WARN", 3); - put("ERROR", 4); - put("IMME", 5); - }}; + public boolean accepts(Severity severity) { + return severity.ordinal() >= this.severity.ordinal(); + } - String[] names = new String[]{""/*DUMMY ENTRY*/, "TRACE", "INFO", "WARNING", "ERROR", ""/*IMMEDIATE*/}; + public void setSeverity(Severity severity) { + this.severity = severity; + } - void writeMessage(String message, int severity); + public abstract void writeMessage(String message, Severity severity); - void writeMessage(String message, Throwable t); + public abstract void writeMessage(String message, Throwable t); - void startClass(String classname); + public void startClass(String className) { } - void endClass(); + public void endClass() { } - void startWriteClass(String classname); + public void startWriteClass(String className) { } - void endWriteClass(); + public void endWriteClass() { } - void startMethod(String method); + public void startMethod(String methodName) { } - void endMethod(); - - int getSeverity(); - - void setSeverity(int severity); + public void endMethod() { } } diff --git a/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java b/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java index c942bad..69dd218 100644 --- a/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java +++ b/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java @@ -77,6 +77,7 @@ public interface IFernflowerPreferences { put(IDEA_NOT_NULL_ANNOTATION, "1"); put(LAMBDA_TO_ANONYMOUS_CLASS, "0"); + put(LOG_LEVEL, IFernflowerLogger.Severity.INFO.name()); put(MAX_PROCESSING_METHOD, "0"); put(RENAME_ENTITIES, "0"); put(NEW_LINE_SEPARATOR, (InterpreterUtil.IS_WINDOWS ? "0" : "1")); diff --git a/src/org/jetbrains/java/decompiler/main/extern/IDecompilatSaver.java b/src/org/jetbrains/java/decompiler/main/extern/IResultSaver.java index 9cbac0c..1e6a7d4 100644 --- a/src/org/jetbrains/java/decompiler/main/extern/IDecompilatSaver.java +++ b/src/org/jetbrains/java/decompiler/main/extern/IResultSaver.java @@ -17,23 +17,20 @@ package org.jetbrains.java.decompiler.main.extern; import java.util.jar.Manifest; -public interface IDecompilatSaver { - - void copyFile(String source, String destpath, String destfilename); - +public interface IResultSaver { void saveFolder(String path); - void saveClassFile(String path, String qualifiedName, String entryName, String content); + void copyFile(String source, String path, String entryName); - void saveFile(String path, String filename, String content); + void saveClassFile(String path, String qualifiedName, String entryName, String content); - void createArchive(String path, String archivename, Manifest manifest); + void createArchive(String path, String archiveName, Manifest manifest); - void saveClassEntry(String path, String archivename, String qualifiedName, String entryName, String content); + void saveDirEntry(String path, String archiveName, String entryName); - void saveEntry(String path, String archivename, String entryName, String content); + void copyEntry(String source, String path, String archiveName, String entry); - void copyEntry(String source, String destpath, String archivename, String entry); + void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content); - void closeArchive(String path, String archivename); + void closeArchive(String path, String archiveName); } diff --git a/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java b/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java index ae251b9..4a32179 100644 --- a/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java +++ b/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java @@ -106,7 +106,7 @@ public class ClassWrapper { if (System.currentTimeMillis() >= stopAt) { String message = "Processing time limit exceeded for method " + mt.getName() + ", execution interrupted."; - DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.ERROR); + DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.ERROR); killThread(mtthread); isError = true; break; diff --git a/src/org/jetbrains/java/decompiler/main/rels/MethodProcessorThread.java b/src/org/jetbrains/java/decompiler/main/rels/MethodProcessorThread.java index 426f143..2f98cf8 100644 --- a/src/org/jetbrains/java/decompiler/main/rels/MethodProcessorThread.java +++ b/src/org/jetbrains/java/decompiler/main/rels/MethodProcessorThread.java @@ -130,7 +130,7 @@ public class MethodProcessorThread implements Runnable { //System.out.println(graph.toString()); if (ExceptionDeobfuscator.hasObfuscatedExceptions(graph)) { - DecompilerContext.getLogger().writeMessage("Heavily obfuscated exception ranges found!", IFernflowerLogger.WARNING); + DecompilerContext.getLogger().writeMessage("Heavily obfuscated exception ranges found!", IFernflowerLogger.Severity.WARN); } RootStatement root = DomHelper.parseGraph(graph); diff --git a/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java b/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java index 684864d..2e83946 100644 --- a/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java +++ b/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java @@ -75,7 +75,8 @@ public class NestedClassProcessor { child.simpleName = "SyntheticClass_" + (++synthetics); } else { - DecompilerContext.getLogger().writeMessage("Nameless local or member class " + cl.qualifiedName + "!", IFernflowerLogger.WARNING); + DecompilerContext.getLogger().writeMessage("Nameless local or member class " + cl.qualifiedName + "!", + IFernflowerLogger.Severity.WARN); child.simpleName = "NamelessClass_" + (++nameless); } } @@ -221,11 +222,11 @@ public class NestedClassProcessor { if (!hasEnclosing) { if (child.type == ClassNode.CLASS_ANONYMOUS) { DecompilerContext.getLogger() - .writeMessage("Unreferenced anonymous class " + child.classStruct.qualifiedName + "!", IFernflowerLogger.WARNING); + .writeMessage("Unreferenced anonymous class " + child.classStruct.qualifiedName + "!", IFernflowerLogger.Severity.WARN); } else if (child.type == ClassNode.CLASS_LOCAL) { DecompilerContext.getLogger() - .writeMessage("Unreferenced local class " + child.classStruct.qualifiedName + "!", IFernflowerLogger.WARNING); + .writeMessage("Unreferenced local class " + child.classStruct.qualifiedName + "!", IFernflowerLogger.Severity.WARN); } } } @@ -275,7 +276,7 @@ public class NestedClassProcessor { HashMap<String, List<VarFieldPair>> mask = getMaskLocalVars(nd.wrapper); if (mask.isEmpty()) { DecompilerContext.getLogger() - .writeMessage("Nested class " + nd.classStruct.qualifiedName + " has no constructor!", IFernflowerLogger.WARNING); + .writeMessage("Nested class " + nd.classStruct.qualifiedName + " has no constructor!", IFernflowerLogger.Severity.WARN); } else { mapVarMasks.put(nd.classStruct.qualifiedName, mask); |