jd-cli

16:37:21.552 INFO  jd.cli.Main - Decompiling jd-cli.jar
package jd.cli;

import ch.qos.logback.classic.Level;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.converters.FileConverter;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import jd.core.options.DecompilerOptions;

public class CLIArguments
  implements DecompilerOptions
{
  @Parameter(description="[Files to decompile]")
  private final List<String> files = new ArrayList();
  @Parameter(names={"--help", "-h"}, description="shows this help", help=true)
  private boolean help;
  @Parameter(names={"--outputZipFile", "-oz"}, description="takes a [zipFilePath] as a parameter and configures ZIP output for this path", converter=FileConverter.class)
  private File zipOutFile;
  @Parameter(names={"--outputDir", "-od"}, description="takes a [directoryPath] as a parameter and configures DIR output for this path", converter=FileConverter.class)
  private File dirOutFile;
  @Parameter(names={"--outputConsole", "-oc"}, description="enables output to system output stream")
  private boolean consoleOut;
  @Parameter(names={"--skipResources", "-sr"}, description="skips processing resources")
  private boolean skipResources;
  @Parameter(names={"--displayLineNumbers", "-n"}, description="displays line numbers in decompiled classes")
  private boolean displayLineNumbers;
  @Parameter(names={"--skipMetadata", "-sm"}, description="skips metadata in decompiled classes")
  private boolean skipMetadata;
  @Parameter(names={"--showLocation", "-l"}, description="displays Location info in decompiled classes metadata part")
  private boolean showLocation;
  @Parameter(names={"--escapeUnicodeCharacters", "-eu"}, description="escape unicode characters in decompiled classes")
  private boolean escapeUnicodeCharacters;
  @Parameter(names={"--showPrefixThis", "-st"}, description="prefix with 'this' where possible in decompiled classes")
  private boolean showPrefixThis;
  @Parameter(names={"--realignLineNumbers", "-rn"}, description="realign line numbers in decompiled classes")
  private boolean realignLineNumbers;
  @Parameter(names={"--showDefaultConstructor", "-dc"}, description="show default constructor in decompiled classes")
  private boolean showDefaultConstructor;
  @Parameter(names={"--dontMergeEmptyLines", "-dm"}, description="disables merging multiple empty lines into one in the decompiled classes")
  private boolean dontMergeEmptyLines;
  @Parameter(names={"--logLevel", "-g"}, description="takes [level] as parameter and sets it as the CLI log level. Possible values are: ALL, TRACE, DEBUG, INFO, WARN, ERROR, OFF", converter=LogLevelConverter.class)
  private final Level logLevel = Level.INFO;
  
  public List<String> getFiles()
  {
    return files;
  }
  
  public boolean isHelp()
  {
    return help;
  }
  
  public File getZipOutFile()
  {
    return zipOutFile;
  }
  
  public File getDirOutFile()
  {
    return dirOutFile;
  }
  
  public boolean isConsoleOut()
  {
    return consoleOut;
  }
  
  public boolean isSkipResources()
  {
    return skipResources;
  }
  
  public boolean isDisplayLineNumbers()
  {
    return displayLineNumbers;
  }
  
  public boolean isDisplayMetadata()
  {
    return !skipMetadata;
  }
  
  public boolean isDiscardLocation()
  {
    return !showLocation;
  }
  
  public boolean isEscapeUnicodeCharacters()
  {
    return escapeUnicodeCharacters;
  }
  
  public boolean isShowPrefixThis()
  {
    return showPrefixThis;
  }
  
  public boolean isRealignLineNumbers()
  {
    return realignLineNumbers;
  }
  
  public boolean isShowDefaultConstructor()
  {
    return showDefaultConstructor;
  }
  
  public boolean isMergeEmptyLines()
  {
    return !dontMergeEmptyLines;
  }
  
  public Level getLogLevel()
  {
    return logLevel;
  }
  
  public boolean isOutputPluginSpecified()
  {
    return (consoleOut) || (zipOutFile != null) || (dirOutFile != null);
  }
}

/* Location:
 * Qualified Name:     jd.cli.CLIArguments
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.cli;

import ch.qos.logback.classic.Level;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import jd.core.IOUtils;
import jd.core.JavaDecompiler;
import jd.core.input.ClassFileInput;
import jd.core.input.DirInput;
import jd.core.input.JDInput;
import jd.core.input.ZipFileInput;
import jd.core.options.OptionsManager;
import jd.core.output.DirOutput;
import jd.core.output.JDOutput;
import jd.core.output.MultiOutput;
import jd.core.output.PrintStreamOutput;
import jd.core.output.ZipOutput;
import org.slf4j.LoggerFactory;

public class Main
{
  private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Main.class);
  
  public static void main(String[] args)
  {
    CLIArguments cliArguments = new CLIArguments();
    ExtCommander jCmd = new ExtCommander(cliArguments, args);
    jCmd.setProgramName("java -jar jd-cli.jar");
    jCmd.setUsageHead("jd-cli version 0.9.1.Final - Copyright (C) 2015 Josef Cacek\n\nThe jd-cli is a command line interface for the Java Decompiler (http://jd.benow.ca/), it decompile classes, zip archives (.zip, .jar, .war, ...) and directories containing classes. Each supported input type has configured corresponding default output type (class->screen, zip->zip, directory->directory). Man can simply override the output type by specifying a command line parameter (-oc, -od, -oz). Multiple output type parameters can be used at once.");
    
    jCmd.setUsageTail("Examples:\n\n$ java -jar jd-cli.jar HelloWorld.class\n Shows decompiled class on a screen\n\n$ java -jar jd-cli.jar --skipResources -n -g ALL app.jar\n Decompiles app.jar to app.src.jar; It doesn't copy resources to the output jar, the decompiled classes contain line numbers as comments and the jd-cli prints the most verbose debug information about decompilation\n\n$ java -jar jd-cli.jar myapp.jar -od decompiled -oc\n Decompiles content of myapp.jar to directory named 'decompiled' and also on a screen\n\nThis program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under GPLv3 conditions.");
    
    setLoggingLevel(cliArguments.getLogLevel());
    if (cliArguments.getFiles().isEmpty())
    {
      jCmd.usage();
      System.exit(1);
    }
    OptionsManager.setOptions(cliArguments);
    
    JDOutput outputPlugin = null;
    File dir;
    if (cliArguments.isOutputPluginSpecified())
    {
      List<JDOutput> outPlugins = new ArrayList();
      if (cliArguments.isConsoleOut()) {
        outPlugins.add(new PrintStreamOutput(System.out));
      }
      File zipFile = cliArguments.getZipOutFile();
      if (zipFile != null) {
        try
        {
          outPlugins.add(new ZipOutput(zipFile));
        }
        catch (Exception e)
        {
          LOGGER.warn("Unable to create zip output", e);
        }
      }
      dir = cliArguments.getDirOutFile();
      if (dir != null) {
        try
        {
          outPlugins.add(new DirOutput(dir));
        }
        catch (Exception e)
        {
          LOGGER.warn("Unable to create directory output", e);
        }
      }
      if (outPlugins.size() > 0) {
        outputPlugin = new MultiOutput(outPlugins);
      }
    }
    JavaDecompiler javaDecompiler = new JavaDecompiler();
    
    boolean decompiled = false;
    for (String path : cliArguments.getFiles())
    {
      LOGGER.info("Decompiling {}", path);
      File file = new File(path);
      if (file.exists()) {
        try
        {
          InputOutputPair inOut = getInOutPlugins(file, outputPlugin);
          inOut.getJdInput().decompile(javaDecompiler, inOut.getJdOutput());
          decompiled = true;
        }
        catch (Exception e)
        {
          LOGGER.warn("Problem occured during instantiating plugins", e);
        }
      } else {
        LOGGER.warn("Input file {} doesn't exist", file);
      }
    }
    if (!decompiled)
    {
      jCmd.usage();
      System.exit(2);
    }
  }
  
  public static InputOutputPair getInOutPlugins(File inputFile, JDOutput outPlugin)
    throws NullPointerException, IOException
  {
    JDInput jdIn = null;
    JDOutput jdOut = null;
    if (inputFile.isDirectory())
    {
      jdIn = new DirInput(inputFile.getPath());
      jdOut = new DirOutput(new File(inputFile.getName() + ".src"));
    }
    else
    {
      DataInputStream dis = new DataInputStream(new FileInputStream(inputFile));
      int magic = 0;
      try
      {
        magic = dis.readInt();
      }
      finally
      {
        IOUtils.closeQuietly(dis);
      }
      switch (magic)
      {
      case -889275714: 
        jdIn = new ClassFileInput(inputFile.getPath());
        jdOut = new PrintStreamOutput(System.out);
        break;
      case 1347093252: 
        jdIn = new ZipFileInput(inputFile.getPath());
        String decompiledZipName = inputFile.getName();
        int suffixPos = decompiledZipName.lastIndexOf(".");
        if (suffixPos >= 0) {
          decompiledZipName = decompiledZipName.substring(0, suffixPos) + ".src" + decompiledZipName.substring(suffixPos);
        } else {
          decompiledZipName = decompiledZipName + ".src";
        }
        jdOut = new ZipOutput(new File(decompiledZipName));
        break;
      default: 
        throw new IllegalArgumentException("File type of was not recognized: " + inputFile);
      }
    }
    return new InputOutputPair(jdIn, outPlugin, jdOut);
  }
  
  private static void setLoggingLevel(Level level)
  {
    ((ch.qos.logback.classic.Logger)LoggerFactory.getLogger("ROOT")).setLevel(level);
  }
}

/* Location:
 * Qualified Name:     jd.cli.Main
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.cli;

import jd.core.input.JDInput;
import jd.core.output.JDOutput;

public class InputOutputPair
{
  private final JDInput jdInput;
  private final JDOutput jdOutput;
  
  public InputOutputPair(JDInput jdIn, JDOutput jdOut, JDOutput jdOutFallback)
  {
    jdInput = jdIn;
    jdOutput = (jdOut != null ? jdOut : jdOutFallback);
  }
  
  public JDInput getJdInput()
  {
    return jdInput;
  }
  
  public JDOutput getJdOutput()
  {
    return jdOutput;
  }
}

/* Location:
 * Qualified Name:     jd.cli.InputOutputPair
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.cli;

import com.beust.jcommander.JCommander;
import java.util.ResourceBundle;

public class ExtCommander
  extends JCommander
{
  private String usageHead;
  private String usageTail;
  
  public ExtCommander() {}
  
  public ExtCommander(Object object, ResourceBundle bundle, String... args)
  {
    super(object, bundle, args);
  }
  
  public ExtCommander(Object object, ResourceBundle bundle)
  {
    super(object, bundle);
  }
  
  public ExtCommander(Object object, String... args)
  {
    super(object, args);
  }
  
  public ExtCommander(Object object)
  {
    super(object);
  }
  
  public void usage(StringBuilder out, String indent)
  {
    int indentCount = indent.length();
    if (usageHead != null) {
      out.append(wrap(indentCount, usageHead)).append("\n");
    }
    super.usage(out, indent);
    if (usageTail != null) {
      out.append("\n").append(wrap(indentCount, usageTail));
    }
  }
  
  private String getIndent(int count)
  {
    StringBuilder result = new StringBuilder();
    for (int i = 0; i < count; i++) {
      result.append(" ");
    }
    return result.toString();
  }
  
  protected String wrap(int indent, String text)
  {
    int max = getColumnSize();
    String[] lines = text.split("\n", -1);
    String indentStr = getIndent(indent);
    
    StringBuilder sb = new StringBuilder();
    for (String line : lines)
    {
      String[] words = line.split(" ", -1);
      StringBuilder lineSb = new StringBuilder();
      for (String word : words)
      {
        int lineLength = lineSb.length();
        if (lineLength > 0) {
          if (indent + lineLength + word.length() > max)
          {
            sb.append(indentStr).append(lineSb).append("\n");
            lineSb.delete(0, lineSb.length());
          }
          else
          {
            lineSb.append(" ");
          }
        }
        lineSb.append(word);
      }
      sb.append(lineSb);
      sb.append("\n");
    }
    return sb.toString();
  }
  
  public String getUsageHead()
  {
    return usageHead;
  }
  
  public void setUsageHead(String usageHead)
  {
    this.usageHead = usageHead;
  }
  
  public String getUsageTail()
  {
    return usageTail;
  }
  
  public void setUsageTail(String usageTail)
  {
    this.usageTail = usageTail;
  }
}

/* Location:
 * Qualified Name:     jd.cli.ExtCommander
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.cli;

import ch.qos.logback.classic.Level;
import com.beust.jcommander.IStringConverter;

public class LogLevelConverter
  implements IStringConverter<Level>
{
  public Level convert(String value)
  {
    return Level.toLevel(value, Level.INFO);
  }
}

/* Location:
 * Qualified Name:     jd.cli.LogLevelConverter
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core;

public class JavaDecompilerConstants$SystemProperties
{
  public static final String LINE_NUMBERS = "jd.lineNumbers";
  public static final boolean LINE_NUMBERS_DEFAULT = false;
  public static final String METADATA = "jd.metadata";
  public static final boolean METADATA_DEFAULT = true;
  public static final String DISCARD_LOCATION = "jd.discardLocation";
  public static final boolean DISCARD_LOCATION_DEFAULT = true;
  public static final String SKIP_RESOURCES = "jd.skipResources";
  public static final boolean SKIP_RESOURCES_DEFAULT = false;
  public static final String ESCAPE_UNICODE_CHARACTERS = "jd.escapeUnicodeCharacters";
  public static final boolean ESCAPE_UNICODE_CHARACTERS_DEFAULT = false;
  public static final String SHOW_PREFIX_THIS = "jd.showPrefixThis";
  public static final boolean SHOW_PREFIX_THIS_DEFAULT = false;
  public static final String REALIGN_LINE_NUMBERS = "jd.realignLineNumbers";
  public static final boolean REALIGN_LINE_NUMBERS_DEFAULT = false;
  public static final String SHOW_DEFAULT_CONSTRUCTOR = "jd.showDefaultConstructor";
  public static final boolean SHOW_DEFAULT_CONSTRUCTOR_DEFAULT = false;
  public static final String MERGE_EMPTY_LINES = "jd.mergeEmptyLines";
  public static final boolean MERGE_EMPTY_LINES_DEFAULT = true;
}

/* Location:
 * Qualified Name:     jd.core.JavaDecompilerConstants.SystemProperties
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core;

public final class JavaDecompilerConstants
{
  public static final String VERSION = "0.9.1.Final";
  public static final String TMP_DIR = System.getProperty("java.io.tmpdir");
  public static final String UTF_8 = "UTF-8";
  public static final String CLASS_SUFFIX = ".class";
  public static final int CLASS_SUFFIX_LEN = ".class".length();
  public static final String JAVA_SUFFIX = ".java";
  public static final int MAGIC_NR_CLASS_FILE = -889275714;
  public static final int MAGIC_NR_ZIP_FILE = 1347093252;
  
  public static class SystemProperties
  {
    public static final String LINE_NUMBERS = "jd.lineNumbers";
    public static final boolean LINE_NUMBERS_DEFAULT = false;
    public static final String METADATA = "jd.metadata";
    public static final boolean METADATA_DEFAULT = true;
    public static final String DISCARD_LOCATION = "jd.discardLocation";
    public static final boolean DISCARD_LOCATION_DEFAULT = true;
    public static final String SKIP_RESOURCES = "jd.skipResources";
    public static final boolean SKIP_RESOURCES_DEFAULT = false;
    public static final String ESCAPE_UNICODE_CHARACTERS = "jd.escapeUnicodeCharacters";
    public static final boolean ESCAPE_UNICODE_CHARACTERS_DEFAULT = false;
    public static final String SHOW_PREFIX_THIS = "jd.showPrefixThis";
    public static final boolean SHOW_PREFIX_THIS_DEFAULT = false;
    public static final String REALIGN_LINE_NUMBERS = "jd.realignLineNumbers";
    public static final boolean REALIGN_LINE_NUMBERS_DEFAULT = false;
    public static final String SHOW_DEFAULT_CONSTRUCTOR = "jd.showDefaultConstructor";
    public static final boolean SHOW_DEFAULT_CONSTRUCTOR_DEFAULT = false;
    public static final String MERGE_EMPTY_LINES = "jd.mergeEmptyLines";
    public static final boolean MERGE_EMPTY_LINES_DEFAULT = true;
  }
}

/* Location:
 * Qualified Name:     jd.core.JavaDecompilerConstants
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.parser;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class SimpleClassParser
{
  private static final Logger LOGGER = LoggerFactory.getLogger(SimpleClassParser.class);
  private static final byte CONSTTYPE_UTF8 = 1;
  private static final byte CONSTTYPE_INTEGER = 3;
  private static final byte CONSTTYPE_FLOAT = 4;
  private static final byte CONSTTYPE_LONG = 5;
  private static final byte CONSTTYPE_DOUBLE = 6;
  private static final byte CONSTTYPE_CLASS = 7;
  private static final byte CONSTTYPE_FIELDREF = 9;
  private static final byte CONSTTYPE_STRING = 8;
  private static final byte CONSTTYPE_METHODREF = 10;
  private static final byte CONSTTYPE_INTERFACEMETHODREF = 11;
  private static final byte CONSTTYPE_NAMEANDTYPE = 12;
  private final int major;
  private final int minor;
  private final String className;
  
  public SimpleClassParser(InputStream is)
    throws IOException, ClassFormatException
  {
    LOGGER.trace("Parsing class from an InputStream");
    DataInputStream dataInputStream;
    DataInputStream dataInputStream;
    if ((is instanceof DataInputStream)) {
      dataInputStream = (DataInputStream)is;
    } else {
      dataInputStream = new DataInputStream(new BufferedInputStream(is));
    }
    if (dataInputStream.readInt() != -889275714) {
      throw new ClassFormatException("Magic number doesn't match a class file.");
    }
    minor = dataInputStream.readUnsignedShort();
    major = dataInputStream.readUnsignedShort();
    LOGGER.trace("Class version: {}.{}", Integer.valueOf(major), Integer.valueOf(minor));
    
    int constantPoolSize = dataInputStream.readUnsignedShort();
    Object[] constantPool = new Object[constantPoolSize];
    for (int i = 1; i < constantPoolSize; i++)
    {
      byte tag = dataInputStream.readByte();
      switch (tag)
      {
      case 9: 
      case 10: 
      case 11: 
      case 12: 
        dataInputStream.readUnsignedShort();
      case 8: 
        dataInputStream.readUnsignedShort();
        break;
      case 3: 
        dataInputStream.readInt();
        break;
      case 4: 
        dataInputStream.readFloat();
        break;
      case 7: 
        constantPool[i] = Integer.valueOf(dataInputStream.readUnsignedShort());
        break;
      case 5: 
        dataInputStream.readLong();
        i++;
        break;
      case 6: 
        dataInputStream.readDouble();
        i++;
        break;
      case 1: 
        constantPool[i] = dataInputStream.readUTF();
        break;
      case 2: 
      default: 
        throw new ClassFormatException("Invalid byte tag in constant pool: " + tag);
      }
    }
    dataInputStream.readUnsignedShort();
    int classIdx = dataInputStream.readUnsignedShort();
    LOGGER.trace("Parsed class index in constant pool: {}", Integer.valueOf(classIdx));
    if ((classIdx < 1) || (classIdx >= constantPoolSize) || (!(constantPool[classIdx] instanceof Integer))) {
      throw new ClassFormatException("Wrong class type index.");
    }
    int classNameIdx = ((Integer)constantPool[classIdx]).intValue();
    LOGGER.trace("Parsed class name index in constant pool: {}", Integer.valueOf(classNameIdx));
    if ((classNameIdx < 1) || (classNameIdx >= constantPoolSize) || (!(constantPool[classNameIdx] instanceof String))) {
      throw new ClassFormatException("Wrong class name index.");
    }
    className = ((String)constantPool[classNameIdx]);
    LOGGER.trace("Parsed class name: {}", className);
  }
  
  public int getMajor()
  {
    return major;
  }
  
  public int getMinor()
  {
    return minor;
  }
  
  public String getClassName()
  {
    return className;
  }
  
  public String getVersionString()
  {
    return major + "." + minor + " (Java 1." + (major - 44) + ")";
  }
}

/* Location:
 * Qualified Name:     jd.core.parser.SimpleClassParser
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.parser;

public class ClassFormatException
  extends Exception
{
  private static final long serialVersionUID = 1L;
  
  public ClassFormatException() {}
  
  public ClassFormatException(String message)
  {
    super(message);
  }
  
  public ClassFormatException(Throwable cause)
  {
    super(cause);
  }
  
  public ClassFormatException(String message, Throwable cause)
  {
    super(message, cause);
  }
}

/* Location:
 * Qualified Name:     jd.core.parser.ClassFormatException
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.options;

public abstract interface DecompilerOptions
{
  public abstract boolean isSkipResources();
  
  public abstract boolean isDisplayLineNumbers();
  
  public abstract boolean isDisplayMetadata();
  
  public abstract boolean isDiscardLocation();
  
  public abstract boolean isEscapeUnicodeCharacters();
  
  public abstract boolean isShowPrefixThis();
  
  public abstract boolean isRealignLineNumbers();
  
  public abstract boolean isShowDefaultConstructor();
  
  public abstract boolean isMergeEmptyLines();
}

/* Location:
 * Qualified Name:     jd.core.options.DecompilerOptions
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.options;

final class OptionsManager$1
  extends ThreadLocal<DecompilerOptions>
{
  private final DecompilerOptions INITIAL = new SystemPropertiesOptions();
  
  protected DecompilerOptions initialValue()
  {
    return INITIAL;
  }
}

/* Location:
 * Qualified Name:     jd.core.options.OptionsManager.1
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.options;

public class OptionsManager
{
  private static final ThreadLocal<DecompilerOptions> LOCAL_OPTIONS = new ThreadLocal()
  {
    private final DecompilerOptions INITIAL = new SystemPropertiesOptions();
    
    protected DecompilerOptions initialValue()
    {
      return INITIAL;
    }
  };
  
  public static void setOptions(DecompilerOptions options)
  {
    if (options != null) {
      LOCAL_OPTIONS.set(options);
    } else {
      LOCAL_OPTIONS.remove();
    }
  }
  
  public static DecompilerOptions getOptions()
  {
    return (DecompilerOptions)LOCAL_OPTIONS.get();
  }
}

/* Location:
 * Qualified Name:     jd.core.options.OptionsManager
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.options;

import jd.core.IOUtils;

public class SystemPropertiesOptions
  implements DecompilerOptions
{
  public boolean isDisplayLineNumbers()
  {
    return IOUtils.getBoolean("jd.lineNumbers", false);
  }
  
  public boolean isDisplayMetadata()
  {
    return IOUtils.getBoolean("jd.metadata", true);
  }
  
  public boolean isDiscardLocation()
  {
    return IOUtils.getBoolean("jd.discardLocation", true);
  }
  
  public boolean isSkipResources()
  {
    return IOUtils.getBoolean("jd.skipResources", false);
  }
  
  public boolean isEscapeUnicodeCharacters()
  {
    return IOUtils.getBoolean("jd.escapeUnicodeCharacters", false);
  }
  
  public boolean isShowPrefixThis()
  {
    return IOUtils.getBoolean("jd.showPrefixThis", false);
  }
  
  public boolean isRealignLineNumbers()
  {
    return IOUtils.getBoolean("jd.realignLineNumbers", false);
  }
  
  public boolean isShowDefaultConstructor()
  {
    return IOUtils.getBoolean("jd.showDefaultConstructor", false);
  }
  
  public boolean isMergeEmptyLines()
  {
    return IOUtils.getBoolean("jd.mergeEmptyLines", true);
  }
}

/* Location:
 * Qualified Name:     jd.core.options.SystemPropertiesOptions
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class IOUtils
{
  private static final Logger LOGGER = LoggerFactory.getLogger(IOUtils.class);
  
  public static long copy(InputStream is, OutputStream os)
    throws IOException
  {
    LOGGER.trace("Copying inputStream to outputStream");
    byte[] buffer = new byte['?'];
    long count = 0L;
    int n = 0;
    while (-1 != (n = is.read(buffer)))
    {
      os.write(buffer, 0, n);
      count += n;
    }
    LOGGER.trace("{} bytes copied from IS to OS", Long.valueOf(count));
    return count;
  }
  
  public static void closeQuietly(InputStream is)
  {
    try
    {
      if (is != null) {
        is.close();
      }
    }
    catch (IOException ioe)
    {
      LOGGER.debug("Closing InputStream failed.", ioe);
    }
  }
  
  public static void closeQuietly(OutputStream os)
  {
    try
    {
      if (os != null) {
        os.close();
      }
    }
    catch (IOException ioe)
    {
      LOGGER.debug("Closing OutputStream failed.", ioe);
    }
  }
  
  public static boolean getBoolean(String propName, boolean defaultVal)
  {
    boolean result = Boolean.parseBoolean(System.getProperty(propName, Boolean.toString(defaultVal)));
    LOGGER.trace("Reading boolean value for system property {} with default {}. Result: {}", new Object[] { propName, Boolean.valueOf(defaultVal), 
      Boolean.valueOf(result) });
    return result;
  }
}

/* Location:
 * Qualified Name:     jd.core.IOUtils
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.input;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import jd.core.IOUtils;
import jd.core.JavaDecompiler;
import jd.core.options.DecompilerOptions;
import jd.core.options.OptionsManager;
import jd.core.output.JDOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DirInput
  extends AbstractFileJDInput
{
  private static final Logger LOGGER = LoggerFactory.getLogger(DirInput.class);
  
  public DirInput(String path)
  {
    super(path);
    if (!file.isDirectory()) {
      throw new IllegalArgumentException("Path doesn't denote a directory.");
    }
  }
  
  public void decompile(JavaDecompiler javaDecompiler, JDOutput jdOutput)
  {
    if ((javaDecompiler == null) || (jdOutput == null))
    {
      LOGGER.warn("Decompiler or JDOutput are null");
      return;
    }
    LOGGER.debug("Initializing decompilation of directory {}", file);
    jdOutput.init(file.getPath());
    for (File f : file.listFiles()) {
      processFile(javaDecompiler, jdOutput, "", f);
    }
    jdOutput.commit();
  }
  
  private void processFile(JavaDecompiler javaDecompiler, JDOutput jdOutput, String pathPrefix, File nextFile)
  {
    String fileName = nextFile.getName();
    String nameWithPath = pathPrefix + fileName;
    if (nextFile.isDirectory())
    {
      LOGGER.trace("Processing directory {}", nextFile);
      for (File f : nextFile.listFiles()) {
        processFile(javaDecompiler, jdOutput, pathPrefix + fileName + "/", f);
      }
    }
    else if (isClassFile(fileName))
    {
      if (isInnerClass(fileName))
      {
        LOGGER.trace("Skipping inner class {}", nextFile);
        return;
      }
      LOGGER.debug("Decompiling {}", nextFile);
      jdOutput.processClass(cutClassSuffix(nameWithPath), javaDecompiler
        .decompileClass(file.getPath(), nameWithPath));
    }
    else if (!OptionsManager.getOptions().isSkipResources())
    {
      LOGGER.debug("Processing resource file {}", nextFile);
      FileInputStream fis = null;
      try
      {
        fis = new FileInputStream(nextFile);
        jdOutput.processResource(nameWithPath, fis);
      }
      catch (IOException ioe)
      {
        LOGGER.error("Resource processing failed for {}", nextFile, ioe);
      }
      finally
      {
        IOUtils.closeQuietly(fis);
      }
    }
  }
}

/* Location:
 * Qualified Name:     jd.core.input.DirInput
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.input;

import java.io.File;
import java.util.Locale;
import jd.core.JavaDecompilerConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractFileJDInput
  implements JDInput
{
  private static final Logger LOGGER = LoggerFactory.getLogger(AbstractFileJDInput.class);
  protected final File file;
  
  public AbstractFileJDInput(String filePath)
    throws IllegalArgumentException
  {
    LOGGER.trace("Creating JDInput instance for file {}", filePath);
    file = new File(filePath);
    if (!file.exists()) {
      throw new IllegalArgumentException("Path doesn't denote an existing file.");
    }
  }
  
  protected boolean isClassFile(String filePath)
  {
    return filePath.toLowerCase(Locale.ENGLISH).endsWith(".class");
  }
  
  protected boolean isInnerClass(String filePath)
  {
    return filePath.toLowerCase(Locale.ENGLISH).matches("\\$.*\\.class$");
  }
  
  protected String cutClassSuffix(String classFilePath)
  {
    return classFilePath.substring(0, classFilePath.length() - JavaDecompilerConstants.CLASS_SUFFIX_LEN);
  }
}

/* Location:
 * Qualified Name:     jd.core.input.AbstractFileJDInput
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.input;

import jd.core.JavaDecompiler;
import jd.core.output.JDOutput;

public abstract interface JDInput
{
  public abstract void decompile(JavaDecompiler paramJavaDecompiler, JDOutput paramJDOutput);
}

/* Location:
 * Qualified Name:     jd.core.input.JDInput
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.input;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import jd.core.IOUtils;
import jd.core.JavaDecompiler;
import jd.core.options.DecompilerOptions;
import jd.core.options.OptionsManager;
import jd.core.output.JDOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ZipFileInput
  extends AbstractFileJDInput
{
  private static final Logger LOGGER = LoggerFactory.getLogger(ZipFileInput.class);
  
  public ZipFileInput(String path)
  {
    super(path);
  }
  
  public void decompile(JavaDecompiler javaDecompiler, JDOutput jdOutput)
  {
    if ((javaDecompiler == null) || (jdOutput == null))
    {
      LOGGER.warn("Decompiler or JDOutput are null");
      return;
    }
    DecompilerOptions options = OptionsManager.getOptions();
    boolean skipResources = options.isSkipResources();
    
    LOGGER.debug("Initializing decompilation of a zip file {}", file);
    
    jdOutput.init(file.getPath());
    ZipInputStream zis = null;
    try
    {
      zis = new ZipInputStream(new FileInputStream(file));
      ZipEntry entry = null;
      while ((entry = zis.getNextEntry()) != null) {
        if (!entry.isDirectory())
        {
          String entryName = entry.getName();
          if (isClassFile(entryName))
          {
            if (isInnerClass(entryName))
            {
              LOGGER.trace("Skipping inner class {}", entryName);
              return;
            }
            LOGGER.debug("Decompiling {}", entryName);
            jdOutput.processClass(cutClassSuffix(entryName), javaDecompiler
              .decompileClass(file.getPath(), entryName));
          }
          else if (!skipResources)
          {
            LOGGER.debug("Processing resource file {}", entryName);
            jdOutput.processResource(entryName, zis);
          }
        }
      }
    }
    catch (IOException e)
    {
      LOGGER.error("IOException occured", e);
    }
    finally
    {
      IOUtils.closeQuietly(zis);
    }
    jdOutput.commit();
  }
}

/* Location:
 * Qualified Name:     jd.core.input.ZipFileInput
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.input;

import java.io.File;
import jd.core.JavaDecompiler;
import jd.core.output.JDOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ClassFileInput
  extends AbstractFileJDInput
{
  private static final Logger LOGGER = LoggerFactory.getLogger(ClassFileInput.class);
  
  public ClassFileInput(String path)
  {
    super(path);
  }
  
  public void decompile(JavaDecompiler javaDecompiler, JDOutput jdOutput)
  {
    if ((javaDecompiler == null) || (jdOutput == null))
    {
      LOGGER.warn("Decompiler or JDOutput are null");
      return;
    }
    jdOutput.init("");
    String name = file.getName();
    LOGGER.debug("Decompiling single class file {}", name);
    jdOutput.processClass(cutClassSuffix(name), javaDecompiler
      .decompileClass(file.getAbsoluteFile().getParent(), name));
    jdOutput.commit();
  }
}

/* Location:
 * Qualified Name:     jd.core.input.ClassFileInput
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import jd.commonide.IdeDecompiler;
import jd.commonide.preferences.IdePreferences;
import jd.core.options.DecompilerOptions;
import jd.core.options.OptionsManager;
import jd.core.parser.SimpleClassParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JavaDecompiler
{
  private static final Logger LOGGER = LoggerFactory.getLogger(JavaDecompiler.class);
  
  public String decompileClass(String basePath, String className)
  {
    LOGGER.debug("Decompiling class {} from base path {}", className, basePath);
    if ((className == null) || (basePath == null))
    {
      LOGGER.warn("Classname or basename was null");
      return null;
    }
    String src = decompile(basePath, className);
    String LS = System.getProperty("line.separator");
    if ((src == null) || (src.startsWith("class " + LS + "{")))
    {
      File baseFile = new File(basePath);
      if (baseFile.isDirectory())
      {
        File classFile = new File(baseFile, className);
        if (!classFile.isFile()) {
          return null;
        }
        FileInputStream fis = null;
        try
        {
          fis = new FileInputStream(classFile);
          SimpleClassParser simpleClassParser = new SimpleClassParser(fis);
          correctPath = simpleClassParser.getClassName() + ".class";
          File tempJar = createTempJar(classFile, correctPath);
          if (tempJar == null) {
            return null;
          }
          src = decompile(tempJar.getPath(), correctPath);
          tempJar.delete();
        }
        catch (Exception e)
        {
          String correctPath;
          LOGGER.error("Exception occured during decompilation", e);
          return null;
        }
        finally
        {
          IOUtils.closeQuietly(fis);
        }
      }
    }
    DecompilerOptions options = OptionsManager.getOptions();
    if ((src != null) && (options.isDisplayMetadata()) && (options.isDiscardLocation())) {
      src = src.replaceFirst("(/\\* Location:).*", "$1");
    }
    return src;
  }
  
  public String decompile(String basePath, String internalTypeName)
  {
    DecompilerOptions options = OptionsManager.getOptions();
    
    boolean showDefaultConstructor = options.isShowDefaultConstructor();
    boolean realignmentLineNumber = options.isRealignLineNumbers();
    boolean showPrefixThis = options.isShowPrefixThis();
    boolean mergeEmptyLines = options.isMergeEmptyLines();
    boolean unicodeEscape = options.isEscapeUnicodeCharacters();
    boolean showLineNumbers = options.isDisplayLineNumbers();
    boolean showMetadata = options.isDisplayMetadata();
    
    IdePreferences preferences = new IdePreferences(showDefaultConstructor, realignmentLineNumber, showPrefixThis, mergeEmptyLines, unicodeEscape, showLineNumbers, showMetadata);
    
    return IdeDecompiler.decompile(preferences, basePath, internalTypeName);
  }
  
  private File createTempJar(File classFile, String correctPath)
  {
    LOGGER.trace("Creating temporary JAR file for {} with correct path: {}", classFile, correctPath);
    ZipOutputStream zos = null;
    File tempJar = null;
    FileInputStream fis = null;
    try
    {
      tempJar = File.createTempFile("jdTemp-", ".jar");
      zos = new ZipOutputStream(new FileOutputStream(tempJar));
      zos.putNextEntry(new ZipEntry(correctPath));
      fis = new FileInputStream(classFile);
      IOUtils.copy(fis, zos);
      zos.closeEntry();
    }
    catch (IOException e)
    {
      LOGGER.error("Temporary JAR creation failed", e);
    }
    finally
    {
      IOUtils.closeQuietly(fis);
      IOUtils.closeQuietly(zos);
    }
    return tempJar;
  }
}

/* Location:
 * Qualified Name:     jd.core.JavaDecompiler
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.output;

import java.io.InputStream;

public abstract interface JDOutput
{
  public abstract void init(String paramString);
  
  public abstract void processClass(String paramString1, String paramString2);
  
  public abstract void processResource(String paramString, InputStream paramInputStream);
  
  public abstract void commit();
}

/* Location:
 * Qualified Name:     jd.core.output.JDOutput
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package jd.core.output;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import jd.core.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DirOutput
  extends AbstractJDOutput
{
  private static final Logger LOGGER = LoggerFactory.getLogger(DirOutput.class);
  private int countClasses;
  private int countResources;
  private final File dir;
  
  public DirOutput(File outputDir)
  {
    if (outputDir == null) {
      throw new NullPointerException("Null directory given");
    }
    dir = outputDir;
  }
  
  public void init(String basePath)
  {
    super.init(basePath);
    countClasses = 0;
    countResources = 0;
    LOGGER.info("Directory output will be initialized for path {}", dir);
    if (!dir.exists()) {
      dir.mkdirs();
    }
    if (!dir.isDirectory()) {
      LOGGER.error("Provided path is either not a directory or mkdirs() command failed: {}", dir);
    }
  }
  
  public void processClass(String className, String src)
  {
    if ((className == null) || (src == null))
    {
      LOGGER.warn("Class name or java source is null");
      return;
    }
    File decompiledFile = new File(dir, className + ".java");
    LOGGER.trace("Writing decompiled class to {}", decompiledFile);
    createDir(decompiledFile.getParentFile());
    FileOutputStream fos = null;
    try
    {
      fos = new FileOutputStream(decompiledFile);
      fos.write(src.getBytes("UTF-8"));
      countClasses += 1;
    }
    catch (IOException e)
    {
      LOGGER.error("Writing decompiled class to file {} failed.", decompiledFile, e);
    }
    finally
    {
      IOUtils.closeQuietly(fos);
    }
  }
  
  public void processResource(String fileName, InputStream is)
  {
    if ((skipResources) || (fileName == null) || (is == null))
    {
      LOGGER.trace("Skipping resource {}", fileName);
      return;
    }
    File tmpFile = new File(dir, fileName);
    LOGGER.trace("Storing resource {}", tmpFile);
    createDir(tmpFile.getParentFile());
    FileOutputStream fos = null;
    try
    {
      fos = new FileOutputStream(tmpFile);
      IOUtils.copy(is, fos);
      countResources += 1;
    }
    catch (IOException e)
    {
      LOGGER.error("Writing resource to file {} failed.", tmpFile, e
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2017. Infinite Loop Ltd