summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/analysis/JarClassIterator.java
diff options
context:
space:
mode:
authorGravatar jeff2014-08-15 01:43:48 -0400
committerGravatar jeff2014-08-15 01:43:48 -0400
commit37467e4a7b5e05e4da413a1e06e597fa806b72e4 (patch)
tree4c76a76aa3379fc236977646af48ec63dcf1712e /src/cuchaz/enigma/analysis/JarClassIterator.java
parentAdded tag v0.1 beta for changeset 7beed0616320 (diff)
downloadenigma-fork-37467e4a7b5e05e4da413a1e06e597fa806b72e4.tar.gz
enigma-fork-37467e4a7b5e05e4da413a1e06e597fa806b72e4.tar.xz
enigma-fork-37467e4a7b5e05e4da413a1e06e597fa806b72e4.zip
trying to get inner/anonymous classes working... I have a working heuristic in place to detect anonymous classes, but I can't seem to get Procyon to decompile them correctly. I'm writing the InnerClasses attribute and translating all the inner class names, but there must be something else I'm missing...
Diffstat (limited to 'src/cuchaz/enigma/analysis/JarClassIterator.java')
-rw-r--r--src/cuchaz/enigma/analysis/JarClassIterator.java134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/analysis/JarClassIterator.java b/src/cuchaz/enigma/analysis/JarClassIterator.java
new file mode 100644
index 0000000..cf6df80
--- /dev/null
+++ b/src/cuchaz/enigma/analysis/JarClassIterator.java
@@ -0,0 +1,134 @@
1/*******************************************************************************
2 * Copyright (c) 2014 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Public License v3.0
5 * which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/gpl.html
7 *
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.analysis;
12
13import java.io.ByteArrayOutputStream;
14import java.io.IOException;
15import java.io.InputStream;
16import java.util.Enumeration;
17import java.util.Iterator;
18import java.util.List;
19import java.util.jar.JarEntry;
20import java.util.jar.JarFile;
21
22import javassist.ByteArrayClassPath;
23import javassist.ClassPool;
24import javassist.CtClass;
25import javassist.NotFoundException;
26import javassist.bytecode.Descriptor;
27
28import com.beust.jcommander.internal.Lists;
29
30import cuchaz.enigma.Constants;
31
32public class JarClassIterator implements Iterator<CtClass>
33{
34 private JarFile m_jar;
35 private Iterator<JarEntry> m_iter;
36
37 public JarClassIterator( JarFile jar )
38 {
39 this( jar, getClassEntries( jar ) );
40 }
41
42 public JarClassIterator( JarFile jar, List<JarEntry> entries )
43 {
44 m_jar = jar;
45 m_iter = entries.iterator();
46 }
47
48 @Override
49 public boolean hasNext( )
50 {
51 return m_iter.hasNext();
52 }
53
54 @Override
55 public CtClass next( )
56 {
57 JarEntry entry = m_iter.next();
58 try
59 {
60 // read the class into a buffer
61 ByteArrayOutputStream bos = new ByteArrayOutputStream();
62 byte[] buf = new byte[Constants.KiB];
63 int totalNumBytesRead = 0;
64 InputStream in = m_jar.getInputStream( entry );
65 while( in.available() > 0 )
66 {
67 int numBytesRead = in.read( buf );
68 if( numBytesRead < 0 )
69 {
70 break;
71 }
72 bos.write( buf, 0, numBytesRead );
73
74 // sanity checking
75 totalNumBytesRead += numBytesRead;
76 if( totalNumBytesRead > Constants.MiB )
77 {
78 throw new Error( "Class file " + entry.getName() + " larger than 1 MiB! Something is wrong!" );
79 }
80 }
81
82 // determine the class name (ie chop off the ".class")
83 String className = Descriptor.toJavaName( entry.getName().substring( 0, entry.getName().length() - ".class".length() ) );
84
85 // get a javassist handle for the class
86 ClassPool classPool = new ClassPool();
87 classPool.insertClassPath( new ByteArrayClassPath( className, bos.toByteArray() ) );
88 return classPool.get( className );
89 }
90 catch( IOException ex )
91 {
92 throw new Error( "Unable to read class: " + entry.getName() );
93 }
94 catch( NotFoundException ex )
95 {
96 throw new Error( "Unable to load class: " + entry.getName() );
97 }
98 }
99
100 @Override
101 public void remove( )
102 {
103 throw new UnsupportedOperationException();
104 }
105
106 public static List<JarEntry> getClassEntries( JarFile jar )
107 {
108 List<JarEntry> classes = Lists.newArrayList();
109 Enumeration<JarEntry> entries = jar.entries();
110 while( entries.hasMoreElements() )
111 {
112 JarEntry entry = entries.nextElement();
113
114 // is this a class file?
115 if( !entry.isDirectory() && entry.getName().endsWith( ".class" ) )
116 {
117 classes.add( entry );
118 }
119 }
120 return classes;
121 }
122
123 public static Iterable<CtClass> classes( final JarFile jar )
124 {
125 return new Iterable<CtClass>( )
126 {
127 @Override
128 public Iterator<CtClass> iterator( )
129 {
130 return new JarClassIterator( jar );
131 }
132 };
133 }
134}