/** {@inheritDoc} */ public VirtualFile decompile(DecompilationDescriptor descriptor, DecompilationContext context) throws DecompilationException { LOG.debug("About to decompile"); VirtualFile decompiledFile = null; try { boolean prepared = classPreparers.get(descriptor.getClassPathType()).execute(context, descriptor); if (prepared) { ConsoleContext consoleContext = context.getConsoleContext(); File targetClass = descriptor.getSourceFile(context.getTargetDirectory()); StringBuilder command = new StringBuilder(context.getCommand()); String path = targetClass.getAbsolutePath(); if (path.indexOf(' ') != -1) { path = "\"" + path + "\""; } command.append(path); consoleContext.addMessage( ConsoleEntryType.DECOMPILATION_OPERATION, "message.executing-jad", command.toString()); try { OperationStatus status = setup(descriptor, context); if (status == OperationStatus.CONTINUE) { ByteArrayOutputStream output = new ByteArrayOutputStream(); ByteArrayOutputStream err = new ByteArrayOutputStream(); ResultType resultType = runExternalDecompiler(command.toString(), context, output, err); // occasionally the result will be empty - there's no point in endlessly // decompiling, so it gives a couple of more chances int count = 0; while (output.size() == 0 && count++ < 3) { consoleContext.addMessage( ConsoleEntryType.DECOMPILATION_OPERATION, "message.reexecuting-jad", command.toString()); resultType = runExternalDecompiler(command.toString(), context, output, err); } decompiledFile = getDecompilationAftermathHandler(resultType) .execute(context, descriptor, targetClass, output, err); } } catch (IOException e) { throw new DecompilationException(e); } catch (InterruptedException e) { throw new DecompilationException(e); } } } finally { FileUtil.delete(context.getTargetDirectory()); } return decompiledFile; }
@Override public byte[] getData(DecompilationContext dc) { ByteSerializer ser = new ByteSerializer(true); ser.addByte(OPCODE); ser.addShort(this.label.getPosition() - dc.getPosition()); return ser.getBytes(); }
/** * Reformats the content of the file to match the preferred code style. * * @param context the decompilation context * @param file the file to reformat */ protected void reformatToStyle( @NotNull final DecompilationContext context, @NotNull final MemoryVF file) { Config config = context.getConfig(); switch (CodeStyle.getByName(config.getReformatStyle())) { case DEBUGGABLE_STYLE: SourceReorganiser.reorganise(context, file); break; case PREFERRED_STYLE: default: StyleReformatter.reformat(context, file.asVirtualFile()); } }
/** * Extract the class files from the library to the target directory. * * @param jarFile the library containing the class files * @param context the context * @param decompilationDescriptor the decompilation descriptor * @throws DecompilationException if an error occurs extracting the class files */ private void extractClassFiles( VirtualFile jarFile, DecompilationContext context, DecompilationDescriptor decompilationDescriptor) throws DecompilationException { try { JarFile lib = JarFileSystem.getInstance().getJarFile(jarFile); context .getConsoleContext() .addMessage(ConsoleEntryType.JAR_OPERATION, "message.examining", jarFile.getPath()); JarExtractor jarExtractor = new JarExtractor(); jarExtractor.extract( context, lib, decompilationDescriptor.getPackageNameAsPath(), decompilationDescriptor.getClassName()); } catch (IOException e) { throw new DecompilationException(e); } }
@Override public void setData(byte[] data, DecompilationContext dc) { int addr = (int) ByteToolkit.getSignedLong(data, 1, 2, true) + dc.getPosition(); this.label = new Label(addr); }