summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/analysis/Ancestries.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/analysis/Ancestries.java')
-rw-r--r--src/cuchaz/enigma/analysis/Ancestries.java145
1 files changed, 0 insertions, 145 deletions
diff --git a/src/cuchaz/enigma/analysis/Ancestries.java b/src/cuchaz/enigma/analysis/Ancestries.java
index e6c8bbf..83c239c 100644
--- a/src/cuchaz/enigma/analysis/Ancestries.java
+++ b/src/cuchaz/enigma/analysis/Ancestries.java
@@ -10,110 +10,27 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.analysis; 11package cuchaz.enigma.analysis;
12 12
13import java.io.ByteArrayOutputStream;
14import java.io.IOException;
15import java.io.InputStream;
16import java.io.Serializable; 13import java.io.Serializable;
17import java.util.ArrayList; 14import java.util.ArrayList;
18import java.util.Collection;
19import java.util.List; 15import java.util.List;
20import java.util.Map; 16import java.util.Map;
21import java.util.zip.ZipEntry;
22import java.util.zip.ZipInputStream;
23 17
24import javassist.ByteArrayClassPath;
25import javassist.ClassPool;
26import javassist.CtClass;
27import javassist.NotFoundException;
28import javassist.bytecode.Descriptor; 18import javassist.bytecode.Descriptor;
29import javassist.bytecode.MethodInfo;
30 19
31import com.google.common.collect.HashMultimap;
32import com.google.common.collect.Lists; 20import com.google.common.collect.Lists;
33import com.google.common.collect.Maps; 21import com.google.common.collect.Maps;
34import com.google.common.collect.Multimap;
35
36import cuchaz.enigma.Constants;
37import cuchaz.enigma.mapping.ClassEntry;
38import cuchaz.enigma.mapping.MethodEntry;
39import cuchaz.enigma.mapping.Translator;
40 22
41public class Ancestries implements Serializable 23public class Ancestries implements Serializable
42{ 24{
43 private static final long serialVersionUID = 738687982126844179L; 25 private static final long serialVersionUID = 738687982126844179L;
44 26
45 private Map<String,String> m_superclasses; 27 private Map<String,String> m_superclasses;
46 private Multimap<String,String> m_methodImplementations;
47 28
48 public Ancestries( ) 29 public Ancestries( )
49 { 30 {
50 m_superclasses = Maps.newHashMap(); 31 m_superclasses = Maps.newHashMap();
51 m_methodImplementations = HashMultimap.create();
52 } 32 }
53 33
54 @SuppressWarnings( "unchecked" )
55 public void readFromJar( InputStream in )
56 throws IOException
57 {
58 ClassPool classPool = new ClassPool();
59
60 ZipInputStream zin = new ZipInputStream( in );
61 ZipEntry entry;
62 while( ( entry = zin.getNextEntry() ) != null )
63 {
64 // filter out non-classes
65 if( entry.isDirectory() || !entry.getName().endsWith( ".class" ) )
66 {
67 continue;
68 }
69
70 // read the class into a buffer
71 ByteArrayOutputStream bos = new ByteArrayOutputStream();
72 byte[] buf = new byte[Constants.KiB];
73 int totalNumBytesRead = 0;
74 while( zin.available() > 0 )
75 {
76 int numBytesRead = zin.read( buf );
77 if( numBytesRead < 0 )
78 {
79 break;
80 }
81 bos.write( buf, 0, numBytesRead );
82
83 // sanity checking
84 totalNumBytesRead += numBytesRead;
85 if( totalNumBytesRead > Constants.MiB )
86 {
87 throw new Error( "Class file " + entry.getName() + " larger than 1 MiB! Something is wrong!" );
88 }
89 }
90
91 // determine the class name (ie chop off the ".class")
92 String className = Descriptor.toJavaName( entry.getName().substring( 0, entry.getName().length() - ".class".length() ) );
93
94 // get a javassist handle for the class
95 classPool.insertClassPath( new ByteArrayClassPath( className, bos.toByteArray() ) );
96 try
97 {
98 CtClass c = classPool.get( className );
99 addSuperclass( c.getName(), c.getClassFile().getSuperclass() );
100 addMethodImplementations( c.getName(), (List<MethodInfo>)c.getClassFile().getMethods() );
101 }
102 catch( NotFoundException ex )
103 {
104 throw new Error( "Unable to load class: " + className );
105 }
106 }
107 }
108
109 private void addMethodImplementations( String name, List<MethodInfo> methods )
110 {
111 for( MethodInfo method : methods )
112 {
113 m_methodImplementations.put( name, getMethodKey( method.getName(), method.getDescriptor() ) );
114 }
115 }
116
117 public void addSuperclass( String className, String superclassName ) 34 public void addSuperclass( String className, String superclassName )
118 { 35 {
119 className = Descriptor.toJvmName( className ); 36 className = Descriptor.toJvmName( className );
@@ -165,71 +82,9 @@ public class Ancestries implements Serializable
165 return subclasses; 82 return subclasses;
166 } 83 }
167 84
168 public boolean isMethodImplemented( MethodEntry methodEntry )
169 {
170 return isMethodImplemented( methodEntry.getClassName(), methodEntry.getName(), methodEntry.getSignature() );
171 }
172
173 public boolean isMethodImplemented( String className, String methodName, String methodSignature )
174 {
175 Collection<String> implementations = m_methodImplementations.get( className );
176 if( implementations == null )
177 {
178 return false;
179 }
180 return implementations.contains( getMethodKey( methodName, methodSignature ) );
181 }
182
183 public ClassInheritanceTreeNode getClassInheritance( Translator deobfuscatingTranslator, ClassEntry obfClassEntry )
184 {
185 // get the root node
186 List<String> ancestry = getAncestry( obfClassEntry.getName() );
187 ClassInheritanceTreeNode rootNode = new ClassInheritanceTreeNode( deobfuscatingTranslator, ancestry.get( ancestry.size() - 1 ) );
188
189 // expand all children recursively
190 rootNode.load( this, true );
191
192 return rootNode;
193 }
194
195 public MethodInheritanceTreeNode getMethodInheritance( Translator deobfuscatingTranslator, MethodEntry obfMethodEntry )
196 {
197 // travel to the ancestor implementation
198 String baseImplementationClassName = obfMethodEntry.getClassName();
199 for( String ancestorClassName : getAncestry( obfMethodEntry.getClassName() ) )
200 {
201 if( isMethodImplemented( ancestorClassName, obfMethodEntry.getName(), obfMethodEntry.getSignature() ) )
202 {
203 baseImplementationClassName = ancestorClassName;
204 }
205 }
206
207 // make a root node at the base
208 MethodEntry methodEntry = new MethodEntry(
209 new ClassEntry( baseImplementationClassName ),
210 obfMethodEntry.getName(),
211 obfMethodEntry.getSignature()
212 );
213 MethodInheritanceTreeNode rootNode = new MethodInheritanceTreeNode(
214 deobfuscatingTranslator,
215 methodEntry,
216 isMethodImplemented( methodEntry )
217 );
218
219 // expand the full tree
220 rootNode.load( this, true );
221
222 return rootNode;
223 }
224
225 private boolean isJre( String className ) 85 private boolean isJre( String className )
226 { 86 {
227 return className.startsWith( "java/" ) 87 return className.startsWith( "java/" )
228 || className.startsWith( "javax/" ); 88 || className.startsWith( "javax/" );
229 } 89 }
230
231 private String getMethodKey( String name, String signature )
232 {
233 return name + signature;
234 }
235} 90}