Skip to content

Commit

Permalink
Merge pull request #24 from ielali/multi-decompiler
Browse files Browse the repository at this point in the history
Multi decompiler + FernFlower
  • Loading branch information
krystian-panek-vmltech authored Feb 13, 2023
2 parents 9874e8a + 68a1855 commit e8c52a6
Show file tree
Hide file tree
Showing 28 changed files with 1,462 additions and 153 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ $RECYCLE.BIN/
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear

Expand Down
Binary file added jar-dependencies/fernflower-decompiler.jar
Binary file not shown.
67 changes: 46 additions & 21 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.neva.felix</groupId>
<artifactId>search-webconsole-plugin</artifactId>
<packaging>bundle</packaging>
<version>1.3.1-SNAPSHOT</version>
<version>1.3.1-jd-SNAPSHOT</version>
<name>search-webconsole-plugin</name>
<description>Search everywhere plugin for Apache Felix Web Console</description>
<inceptionYear>2017</inceptionYear>
Expand Down Expand Up @@ -63,6 +64,27 @@
</repository>
</distributionManagement>

<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>bintray</name>
<url>https://jcenter.bintray.com</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>bintray-plugins</name>
<url>https://jcenter.bintray.com</url>
</pluginRepository>
</pluginRepositories>

<build>
<resources>
<resource>
Expand All @@ -87,7 +109,7 @@
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<version>3.2.0</version>
<version>4.2.0</version>
<configuration>
<instructions>
<Bundle-Name>Apache Felix Web Console Search Plugin</Bundle-Name>
Expand All @@ -112,15 +134,17 @@
org.apache.commons.lang3.*
com.strobel.assembler.*;
com.strobel.decompiler.*;
org.benf.cfr.*;
org.jetbrains.java.decompiler.*;
</Private-Package>
<Embed-Dependency>
gson,
guava,
commons-lang3,
commons-io,
procyon-core,
procyon-reflection,
procyon-compilertools
jd-core,
cfr,
fernflower
</Embed-Dependency>
</instructions>
</configuration>
Expand All @@ -130,8 +154,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>7</source>
<target>7</target>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
Expand All @@ -158,6 +182,7 @@
</execution>
</executions>
<configuration>
<source>8</source>
<additionalJOption>-Xdoclint:none</additionalJOption>
</configuration>
</plugin>
Expand Down Expand Up @@ -207,23 +232,22 @@

<!-- Java decompiler -->
<dependency>
<groupId>org.bitbucket.mstrobel</groupId>
<artifactId>procyon-core</artifactId>
<version>${procyon.version}</version>
<groupId>org.jd</groupId>
<artifactId>jd-core</artifactId>
<version>${jd-core.version}</version>
</dependency>

<dependency>
<groupId>org.bitbucket.mstrobel</groupId>
<artifactId>procyon-reflection</artifactId>
<version>${procyon.version}</version>
<groupId>org.benf</groupId>
<artifactId>cfr</artifactId>
<version>${cfr.version}</version>
</dependency>

<dependency>
<groupId>org.bitbucket.mstrobel</groupId>
<artifactId>procyon-compilertools</artifactId>
<version>${procyon.version}</version>
<groupId>org.jetbrains.java.decompiler</groupId>
<artifactId>fernflower</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/jar-dependencies/fernflower-decompiler.jar</systemPath>
</dependency>

<!-- Embedded -->
<dependency>
<groupId>com.google.code.gson</groupId>
Expand Down Expand Up @@ -272,6 +296,7 @@
<felix.url>http://localhost:8080/system/console</felix.url>
<felix.user>admin</felix.user>
<felix.password>admin</felix.password>
<procyon.version>0.5.36</procyon.version>
<jd-core.version>1.1.3</jd-core.version>
<cfr.version>0.151</cfr.version>
</properties>
</project>
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.neva.felix.webconsole.plugins.search.core;

import com.google.common.collect.ImmutableMap;
import com.neva.felix.webconsole.plugins.search.rest.BundleClassesServlet;
import com.neva.felix.webconsole.plugins.search.rest.BundleDownloadServlet;
import com.neva.felix.webconsole.plugins.search.utils.BundleUtils;
import com.google.common.collect.ImmutableMap;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
Expand All @@ -13,38 +13,44 @@

public class BundleInfo implements Serializable {

private final String symbolicName;
private final String symbolicName;

private final String name;
private final String name;
private final String location;

private final long id;
private final long id;

private final Map<String, String> context;
private final Map<String, String> context;

public BundleInfo(Bundle bundle, BundleContext context) {
this.symbolicName = bundle.getSymbolicName();
this.name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME);
this.id = bundle.getBundleId();
this.context = ImmutableMap.of(
"consoleUrl", BundleUtils.consolePath(context, bundle),
"bundleDownloadUrl", BundleDownloadServlet.url(context, bundle),
"bundleClassesUrl", BundleClassesServlet.url(context, bundle)
);
}
public BundleInfo(Bundle bundle, BundleContext context) {
this.symbolicName = bundle.getSymbolicName();
this.name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME);
this.id = bundle.getBundleId();
this.location = bundle.getLocation();
this.context = ImmutableMap.of(
"consoleUrl", BundleUtils.consolePath(context, bundle),
"bundleDownloadUrl", BundleDownloadServlet.url(context, bundle),
"bundleClassesUrl", BundleClassesServlet.url(context, bundle)
);
}

public String getSymbolicName() {
return symbolicName;
}
public String getSymbolicName() {
return symbolicName;
}

public String getName() {
return name;
}
public String getName() {
return name;
}

public long getId() {
return id;
}

public long getId() {
return id;
public String getLocation() {
return location;
}

public Map<String, String> getContext() {
return context;
}
return context;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.primitives.Longs;
import com.strobel.assembler.metadata.JarTypeLoader;
import com.strobel.decompiler.Decompiler;
import com.strobel.decompiler.DecompilerSettings;
import com.strobel.decompiler.PlainTextOutput;
import com.neva.felix.webconsole.plugins.search.decompiler.DecompilerFactory;
import com.neva.felix.webconsole.plugins.search.decompiler.Decompilers;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -25,16 +23,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.jar.JarFile;

public class OsgiExplorer {

Expand Down Expand Up @@ -76,22 +69,20 @@ public File findJar(String bundleId) {
}

public File findJar(Long bundleId) {
return findJar(findDir(bundleId));
File jar = findJar(findDir(bundleId));
if (jar == null) {
//If jar not found through storage dir, try to resolve bundle location (Sling starter sources jars from maven repository)
Bundle bundle = findBundle(bundleId);
return new File(StringUtils.replace(bundle.getLocation(), "reference:file:", ""));
}
return jar;
}

public File findJar(File bundleDir) {
if (bundleDir.exists()) {
List<File> files = FluentIterable.from(FileUtils.listFiles(bundleDir, new String[]{JAR_EXT}, true)).filter(new Predicate<File>() {
@Override
public boolean apply(File file) {
return file.getName().equalsIgnoreCase(BUNDLE_JAR_FILE);
}
}).toSortedList(new Comparator<File>() {
@Override
public int compare(File f1, File f2) {
return f2.getAbsolutePath().compareTo(f1.getAbsolutePath());
}
});
List<File> files = FluentIterable.from(FileUtils.listFiles(bundleDir, new String[]{JAR_EXT}, true))
.filter(file -> file.getName().equalsIgnoreCase(BUNDLE_JAR_FILE))
.toSortedList((f1, f2) -> f2.getAbsolutePath().compareTo(f1.getAbsolutePath()));

return Iterables.getFirst(files, null);
}
Expand Down Expand Up @@ -145,38 +136,31 @@ public String proposeJarName(String bundleId) {
return result;
}

public String decompileClass(BundleClass clazz) {
return decompileClass(clazz.getBundle().getBundleId(), clazz.getClassName());
public String decompileClass(Decompilers type, BundleClass clazz) {
return decompileClass(type, clazz.getBundle().getBundleId(), clazz.getClassName());
}

public String decompileClass(Long bundleId, String className) {
return decompileClass(findJar(bundleId), className);
public String decompileClass(Decompilers type, Long bundleId, String className) {
return decompileClass(type, findJar(bundleId), className);
}

public String decompileClass(File jar, String className) {
public String decompileClass(Decompilers type, File jar, String className) {
String source = StringUtils.EMPTY;
String path = StringUtils.replace(className, ".", "/");

try {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
try (OutputStreamWriter writer = new OutputStreamWriter(stream)) {
DecompilerSettings settings = DecompilerSettings.javaDefaults();
settings.setTypeLoader(new JarTypeLoader(new JarFile(jar)));
settings.setForceExplicitImports(true);
settings.setForceExplicitTypeArguments(true);

Decompiler.decompile(path, new PlainTextOutput(writer), settings);
stream.flush();
}
} finally {
stream.close();
source = new String(stream.toByteArray(), Charset.defaultCharset());
}
} catch (final IOException e) {
// handle error
source = DecompilerFactory.get(type).decompile(jar, className, false);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
return source;
}

public String decompileClass(Decompilers type, boolean showLineNumbers, File jar, String className) {
String source = StringUtils.EMPTY;
try {
source = DecompilerFactory.get(type).decompile(jar, className, showLineNumbers);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
return source;
}

Expand Down Expand Up @@ -272,9 +256,11 @@ private BundleClass obtainClassMetadata(BundleClass clazz, String classPid) {
}

public Bundle findBundle(String id) {
final Long longId = Longs.tryParse(id);
return findBundle(Longs.tryParse(id));
}

return longId != null ? context.getBundle(longId) : null;
public Bundle findBundle(Long id) {
return id != null ? context.getBundle(id) : null;
}

public Iterable<Bundle> findBundles(List<String> ids) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.neva.felix.webconsole.plugins.search.core.OsgiExplorer;
import com.neva.felix.webconsole.plugins.search.core.SearchJob;
import com.neva.felix.webconsole.plugins.search.core.SearchUtils;
import com.neva.felix.webconsole.plugins.search.decompiler.Decompilers;

import java.util.Collections;
import java.util.List;
Expand All @@ -18,15 +19,17 @@ public class ClassSearchJob extends SearchJob {

private final String phrase;

private final Decompilers type;

private int contextLineCount = 5;

private List<ClassSearchResult> partialResults = Collections.emptyList();

public ClassSearchJob(OsgiExplorer osgiExplorer, String phrase, Set<BundleClass> classes) {
public ClassSearchJob(OsgiExplorer osgiExplorer, Decompilers type, String phrase, Set<BundleClass> classes) {
super(osgiExplorer);
this.phrase = phrase;
this.classes = classes;

this.type= type;
this.step = "Gathering";
}

Expand All @@ -36,7 +39,7 @@ public void perform() {
step = "Searching";

for (BundleClass clazz : classes) {
final String source = osgiExplorer.decompileClass(clazz);
final String source = osgiExplorer.decompileClass(type, clazz);
final List<String> contexts = SearchUtils.findContexts(phrase, source, contextLineCount);

if (!contexts.isEmpty()) {
Expand Down
Loading

0 comments on commit e8c52a6

Please sign in to comment.