Skip to content

Commit e8c52a6

Browse files
Merge pull request #24 from ielali/multi-decompiler
Multi decompiler + FernFlower
2 parents 9874e8a + 68a1855 commit e8c52a6

28 files changed

+1462
-153
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ $RECYCLE.BIN/
5757
.mtj.tmp/
5858

5959
# Package Files #
60-
*.jar
6160
*.war
6261
*.ear
6362

1.4 MB
Binary file not shown.

pom.xml

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717
specific language governing permissions and limitations
1818
under the License.
1919
-->
20-
<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">
20+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
2122
<modelVersion>4.0.0</modelVersion>
2223
<groupId>com.neva.felix</groupId>
2324
<artifactId>search-webconsole-plugin</artifactId>
2425
<packaging>bundle</packaging>
25-
<version>1.3.1-SNAPSHOT</version>
26+
<version>1.3.1-jd-SNAPSHOT</version>
2627
<name>search-webconsole-plugin</name>
2728
<description>Search everywhere plugin for Apache Felix Web Console</description>
2829
<inceptionYear>2017</inceptionYear>
@@ -63,6 +64,27 @@
6364
</repository>
6465
</distributionManagement>
6566

67+
<repositories>
68+
<repository>
69+
<snapshots>
70+
<enabled>false</enabled>
71+
</snapshots>
72+
<id>central</id>
73+
<name>bintray</name>
74+
<url>https://jcenter.bintray.com</url>
75+
</repository>
76+
</repositories>
77+
<pluginRepositories>
78+
<pluginRepository>
79+
<snapshots>
80+
<enabled>false</enabled>
81+
</snapshots>
82+
<id>central</id>
83+
<name>bintray-plugins</name>
84+
<url>https://jcenter.bintray.com</url>
85+
</pluginRepository>
86+
</pluginRepositories>
87+
6688
<build>
6789
<resources>
6890
<resource>
@@ -87,7 +109,7 @@
87109
<groupId>org.apache.felix</groupId>
88110
<artifactId>maven-bundle-plugin</artifactId>
89111
<extensions>true</extensions>
90-
<version>3.2.0</version>
112+
<version>4.2.0</version>
91113
<configuration>
92114
<instructions>
93115
<Bundle-Name>Apache Felix Web Console Search Plugin</Bundle-Name>
@@ -112,15 +134,17 @@
112134
org.apache.commons.lang3.*
113135
com.strobel.assembler.*;
114136
com.strobel.decompiler.*;
137+
org.benf.cfr.*;
138+
org.jetbrains.java.decompiler.*;
115139
</Private-Package>
116140
<Embed-Dependency>
117141
gson,
118142
guava,
119143
commons-lang3,
120144
commons-io,
121-
procyon-core,
122-
procyon-reflection,
123-
procyon-compilertools
145+
jd-core,
146+
cfr,
147+
fernflower
124148
</Embed-Dependency>
125149
</instructions>
126150
</configuration>
@@ -130,8 +154,8 @@
130154
<artifactId>maven-compiler-plugin</artifactId>
131155
<version>3.3</version>
132156
<configuration>
133-
<source>7</source>
134-
<target>7</target>
157+
<source>8</source>
158+
<target>8</target>
135159
</configuration>
136160
</plugin>
137161
<plugin>
@@ -158,6 +182,7 @@
158182
</execution>
159183
</executions>
160184
<configuration>
185+
<source>8</source>
161186
<additionalJOption>-Xdoclint:none</additionalJOption>
162187
</configuration>
163188
</plugin>
@@ -207,23 +232,22 @@
207232

208233
<!-- Java decompiler -->
209234
<dependency>
210-
<groupId>org.bitbucket.mstrobel</groupId>
211-
<artifactId>procyon-core</artifactId>
212-
<version>${procyon.version}</version>
235+
<groupId>org.jd</groupId>
236+
<artifactId>jd-core</artifactId>
237+
<version>${jd-core.version}</version>
213238
</dependency>
214-
215239
<dependency>
216-
<groupId>org.bitbucket.mstrobel</groupId>
217-
<artifactId>procyon-reflection</artifactId>
218-
<version>${procyon.version}</version>
240+
<groupId>org.benf</groupId>
241+
<artifactId>cfr</artifactId>
242+
<version>${cfr.version}</version>
219243
</dependency>
220-
221244
<dependency>
222-
<groupId>org.bitbucket.mstrobel</groupId>
223-
<artifactId>procyon-compilertools</artifactId>
224-
<version>${procyon.version}</version>
245+
<groupId>org.jetbrains.java.decompiler</groupId>
246+
<artifactId>fernflower</artifactId>
247+
<version>1.0</version>
248+
<scope>system</scope>
249+
<systemPath>${project.basedir}/jar-dependencies/fernflower-decompiler.jar</systemPath>
225250
</dependency>
226-
227251
<!-- Embedded -->
228252
<dependency>
229253
<groupId>com.google.code.gson</groupId>
@@ -272,6 +296,7 @@
272296
<felix.url>http://localhost:8080/system/console</felix.url>
273297
<felix.user>admin</felix.user>
274298
<felix.password>admin</felix.password>
275-
<procyon.version>0.5.36</procyon.version>
299+
<jd-core.version>1.1.3</jd-core.version>
300+
<cfr.version>0.151</cfr.version>
276301
</properties>
277302
</project>
Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package com.neva.felix.webconsole.plugins.search.core;
22

3+
import com.google.common.collect.ImmutableMap;
34
import com.neva.felix.webconsole.plugins.search.rest.BundleClassesServlet;
45
import com.neva.felix.webconsole.plugins.search.rest.BundleDownloadServlet;
56
import com.neva.felix.webconsole.plugins.search.utils.BundleUtils;
6-
import com.google.common.collect.ImmutableMap;
77
import org.osgi.framework.Bundle;
88
import org.osgi.framework.BundleContext;
99
import org.osgi.framework.Constants;
@@ -13,38 +13,44 @@
1313

1414
public class BundleInfo implements Serializable {
1515

16-
private final String symbolicName;
16+
private final String symbolicName;
1717

18-
private final String name;
18+
private final String name;
19+
private final String location;
1920

20-
private final long id;
21+
private final long id;
2122

22-
private final Map<String, String> context;
23+
private final Map<String, String> context;
2324

24-
public BundleInfo(Bundle bundle, BundleContext context) {
25-
this.symbolicName = bundle.getSymbolicName();
26-
this.name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME);
27-
this.id = bundle.getBundleId();
28-
this.context = ImmutableMap.of(
29-
"consoleUrl", BundleUtils.consolePath(context, bundle),
30-
"bundleDownloadUrl", BundleDownloadServlet.url(context, bundle),
31-
"bundleClassesUrl", BundleClassesServlet.url(context, bundle)
32-
);
33-
}
25+
public BundleInfo(Bundle bundle, BundleContext context) {
26+
this.symbolicName = bundle.getSymbolicName();
27+
this.name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME);
28+
this.id = bundle.getBundleId();
29+
this.location = bundle.getLocation();
30+
this.context = ImmutableMap.of(
31+
"consoleUrl", BundleUtils.consolePath(context, bundle),
32+
"bundleDownloadUrl", BundleDownloadServlet.url(context, bundle),
33+
"bundleClassesUrl", BundleClassesServlet.url(context, bundle)
34+
);
35+
}
3436

35-
public String getSymbolicName() {
36-
return symbolicName;
37-
}
37+
public String getSymbolicName() {
38+
return symbolicName;
39+
}
3840

39-
public String getName() {
40-
return name;
41-
}
41+
public String getName() {
42+
return name;
43+
}
44+
45+
public long getId() {
46+
return id;
47+
}
4248

43-
public long getId() {
44-
return id;
49+
public String getLocation() {
50+
return location;
4551
}
4652

4753
public Map<String, String> getContext() {
48-
return context;
49-
}
54+
return context;
55+
}
5056
}

src/main/java/com/neva/felix/webconsole/plugins/search/core/OsgiExplorer.java

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@
99
import com.google.common.collect.Lists;
1010
import com.google.common.collect.Sets;
1111
import com.google.common.primitives.Longs;
12-
import com.strobel.assembler.metadata.JarTypeLoader;
13-
import com.strobel.decompiler.Decompiler;
14-
import com.strobel.decompiler.DecompilerSettings;
15-
import com.strobel.decompiler.PlainTextOutput;
12+
import com.neva.felix.webconsole.plugins.search.decompiler.DecompilerFactory;
13+
import com.neva.felix.webconsole.plugins.search.decompiler.Decompilers;
1614
import org.apache.commons.io.FileUtils;
1715
import org.apache.commons.io.FilenameUtils;
1816
import org.apache.commons.lang3.StringUtils;
@@ -25,16 +23,11 @@
2523
import org.slf4j.Logger;
2624
import org.slf4j.LoggerFactory;
2725

28-
import java.io.ByteArrayOutputStream;
2926
import java.io.File;
3027
import java.io.IOException;
31-
import java.io.OutputStreamWriter;
32-
import java.nio.charset.Charset;
3328
import java.util.Collections;
34-
import java.util.Comparator;
3529
import java.util.List;
3630
import java.util.Set;
37-
import java.util.jar.JarFile;
3831

3932
public class OsgiExplorer {
4033

@@ -76,22 +69,20 @@ public File findJar(String bundleId) {
7669
}
7770

7871
public File findJar(Long bundleId) {
79-
return findJar(findDir(bundleId));
72+
File jar = findJar(findDir(bundleId));
73+
if (jar == null) {
74+
//If jar not found through storage dir, try to resolve bundle location (Sling starter sources jars from maven repository)
75+
Bundle bundle = findBundle(bundleId);
76+
return new File(StringUtils.replace(bundle.getLocation(), "reference:file:", ""));
77+
}
78+
return jar;
8079
}
8180

8281
public File findJar(File bundleDir) {
8382
if (bundleDir.exists()) {
84-
List<File> files = FluentIterable.from(FileUtils.listFiles(bundleDir, new String[]{JAR_EXT}, true)).filter(new Predicate<File>() {
85-
@Override
86-
public boolean apply(File file) {
87-
return file.getName().equalsIgnoreCase(BUNDLE_JAR_FILE);
88-
}
89-
}).toSortedList(new Comparator<File>() {
90-
@Override
91-
public int compare(File f1, File f2) {
92-
return f2.getAbsolutePath().compareTo(f1.getAbsolutePath());
93-
}
94-
});
83+
List<File> files = FluentIterable.from(FileUtils.listFiles(bundleDir, new String[]{JAR_EXT}, true))
84+
.filter(file -> file.getName().equalsIgnoreCase(BUNDLE_JAR_FILE))
85+
.toSortedList((f1, f2) -> f2.getAbsolutePath().compareTo(f1.getAbsolutePath()));
9586

9687
return Iterables.getFirst(files, null);
9788
}
@@ -145,38 +136,31 @@ public String proposeJarName(String bundleId) {
145136
return result;
146137
}
147138

148-
public String decompileClass(BundleClass clazz) {
149-
return decompileClass(clazz.getBundle().getBundleId(), clazz.getClassName());
139+
public String decompileClass(Decompilers type, BundleClass clazz) {
140+
return decompileClass(type, clazz.getBundle().getBundleId(), clazz.getClassName());
150141
}
151142

152-
public String decompileClass(Long bundleId, String className) {
153-
return decompileClass(findJar(bundleId), className);
143+
public String decompileClass(Decompilers type, Long bundleId, String className) {
144+
return decompileClass(type, findJar(bundleId), className);
154145
}
155146

156-
public String decompileClass(File jar, String className) {
147+
public String decompileClass(Decompilers type, File jar, String className) {
157148
String source = StringUtils.EMPTY;
158-
String path = StringUtils.replace(className, ".", "/");
159-
160149
try {
161-
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
162-
try {
163-
try (OutputStreamWriter writer = new OutputStreamWriter(stream)) {
164-
DecompilerSettings settings = DecompilerSettings.javaDefaults();
165-
settings.setTypeLoader(new JarTypeLoader(new JarFile(jar)));
166-
settings.setForceExplicitImports(true);
167-
settings.setForceExplicitTypeArguments(true);
168-
169-
Decompiler.decompile(path, new PlainTextOutput(writer), settings);
170-
stream.flush();
171-
}
172-
} finally {
173-
stream.close();
174-
source = new String(stream.toByteArray(), Charset.defaultCharset());
175-
}
176-
} catch (final IOException e) {
177-
// handle error
150+
source = DecompilerFactory.get(type).decompile(jar, className, false);
151+
} catch (Exception e) {
152+
LOG.error(e.getMessage(), e);
178153
}
154+
return source;
155+
}
179156

157+
public String decompileClass(Decompilers type, boolean showLineNumbers, File jar, String className) {
158+
String source = StringUtils.EMPTY;
159+
try {
160+
source = DecompilerFactory.get(type).decompile(jar, className, showLineNumbers);
161+
} catch (Exception e) {
162+
LOG.error(e.getMessage(), e);
163+
}
180164
return source;
181165
}
182166

@@ -272,9 +256,11 @@ private BundleClass obtainClassMetadata(BundleClass clazz, String classPid) {
272256
}
273257

274258
public Bundle findBundle(String id) {
275-
final Long longId = Longs.tryParse(id);
259+
return findBundle(Longs.tryParse(id));
260+
}
276261

277-
return longId != null ? context.getBundle(longId) : null;
262+
public Bundle findBundle(Long id) {
263+
return id != null ? context.getBundle(id) : null;
278264
}
279265

280266
public Iterable<Bundle> findBundles(List<String> ids) {

src/main/java/com/neva/felix/webconsole/plugins/search/core/classsearch/ClassSearchJob.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.neva.felix.webconsole.plugins.search.core.OsgiExplorer;
66
import com.neva.felix.webconsole.plugins.search.core.SearchJob;
77
import com.neva.felix.webconsole.plugins.search.core.SearchUtils;
8+
import com.neva.felix.webconsole.plugins.search.decompiler.Decompilers;
89

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

1920
private final String phrase;
2021

22+
private final Decompilers type;
23+
2124
private int contextLineCount = 5;
2225

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

25-
public ClassSearchJob(OsgiExplorer osgiExplorer, String phrase, Set<BundleClass> classes) {
28+
public ClassSearchJob(OsgiExplorer osgiExplorer, Decompilers type, String phrase, Set<BundleClass> classes) {
2629
super(osgiExplorer);
2730
this.phrase = phrase;
2831
this.classes = classes;
29-
32+
this.type= type;
3033
this.step = "Gathering";
3134
}
3235

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

3841
for (BundleClass clazz : classes) {
39-
final String source = osgiExplorer.decompileClass(clazz);
42+
final String source = osgiExplorer.decompileClass(type, clazz);
4043
final List<String> contexts = SearchUtils.findContexts(phrase, source, contextLineCount);
4144

4245
if (!contexts.isEmpty()) {

0 commit comments

Comments
 (0)