-
Notifications
You must be signed in to change notification settings - Fork 667
/
Copy pathFernflower.java
134 lines (115 loc) · 4.83 KB
/
Fernflower.java
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.main;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.extern.*;
import org.jetbrains.java.decompiler.modules.renamer.ConverterHelper;
import org.jetbrains.java.decompiler.modules.renamer.IdentifierConverter;
import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor;
import org.jetbrains.java.decompiler.struct.IDecompiledData;
import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.StructContext;
import org.jetbrains.java.decompiler.struct.lazy.LazyLoader;
import org.jetbrains.java.decompiler.util.TextBuffer;
import java.io.File;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class Fernflower implements IDecompiledData {
private final StructContext structContext;
private final ClassesProcessor classProcessor;
private final IIdentifierRenamer helper;
private final IdentifierConverter converter;
public Fernflower(IBytecodeProvider provider,
IResultSaver saver,
@Nullable Map<String, Object> customProperties,
IFernflowerLogger logger,
@Nullable CancellationManager cancellationManager) {
Map<String, Object> properties = new HashMap<>(IFernflowerPreferences.DEFAULTS);
if (customProperties != null) {
properties.putAll(customProperties);
}
String level = (String)properties.get(IFernflowerPreferences.LOG_LEVEL);
if (level != null) {
try {
logger.setSeverity(IFernflowerLogger.Severity.valueOf(level.toUpperCase(Locale.ENGLISH)));
}
catch (IllegalArgumentException ignore) { }
}
structContext = new StructContext(saver, this, new LazyLoader(provider));
classProcessor = new ClassesProcessor(structContext);
PoolInterceptor interceptor = null;
if ("1".equals(properties.get(IFernflowerPreferences.RENAME_ENTITIES))) {
helper = loadHelper((String)properties.get(IFernflowerPreferences.USER_RENAMER_CLASS), logger);
interceptor = new PoolInterceptor();
converter = new IdentifierConverter(structContext, helper, interceptor);
}
else {
helper = null;
converter = null;
}
DecompilerContext context = new DecompilerContext(properties, logger, structContext, classProcessor, interceptor, cancellationManager);
DecompilerContext.setCurrentContext(context);
}
public Fernflower(IBytecodeProvider provider, IResultSaver saver, Map<String, Object> customProperties, IFernflowerLogger logger) {
this(provider, saver, customProperties, logger, null);
}
private static IIdentifierRenamer loadHelper(String className, IFernflowerLogger logger) {
if (className != null) {
try {
Class<?> renamerClass = Fernflower.class.getClassLoader().loadClass(className);
return (IIdentifierRenamer) renamerClass.getDeclaredConstructor().newInstance();
}
catch (Exception e) {
logger.writeMessage("Cannot load renamer '" + className + "'", IFernflowerLogger.Severity.WARN, e);
}
}
return new ConverterHelper();
}
public void addSource(File source) {
structContext.addSpace(source, true);
}
public void addLibrary(File library) {
structContext.addSpace(library, false);
}
public void decompileContext() {
if (converter != null) {
converter.rename();
}
classProcessor.loadClasses(helper);
structContext.saveContext();
}
public void clearContext() {
DecompilerContext.setCurrentContext(null);
}
@Override
public String getClassEntryName(StructClass cl, String entryName) {
ClassNode node = classProcessor.getMapRootClasses().get(cl.qualifiedName);
if (node.type != ClassNode.CLASS_ROOT) {
return null;
}
else if (converter != null) {
String simpleClassName = cl.qualifiedName.substring(cl.qualifiedName.lastIndexOf('/') + 1);
return entryName.substring(0, entryName.lastIndexOf('/') + 1) + simpleClassName + ".java";
}
else {
return entryName.substring(0, entryName.lastIndexOf(".class")) + ".java";
}
}
@Override
public String getClassContent(StructClass cl) {
try {
TextBuffer buffer = new TextBuffer(ClassesProcessor.AVERAGE_CLASS_SIZE);
buffer.append(DecompilerContext.getProperty(IFernflowerPreferences.BANNER).toString());
classProcessor.writeClass(cl, buffer);
return buffer.toString();
}
catch (CancellationManager.CanceledException e) {
throw e;
}
catch (Throwable t) {
DecompilerContext.getLogger().writeMessage("Class " + cl.qualifiedName + " couldn't be fully decompiled.", t);
return null;
}
}
}