summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/bytecode/ConstPoolEditor.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/bytecode/ConstPoolEditor.java')
-rw-r--r--src/cuchaz/enigma/bytecode/ConstPoolEditor.java295
1 files changed, 121 insertions, 174 deletions
diff --git a/src/cuchaz/enigma/bytecode/ConstPoolEditor.java b/src/cuchaz/enigma/bytecode/ConstPoolEditor.java
index aa6149c..2dec3b7 100644
--- a/src/cuchaz/enigma/bytecode/ConstPoolEditor.java
+++ b/src/cuchaz/enigma/bytecode/ConstPoolEditor.java
@@ -23,8 +23,8 @@ import cuchaz.enigma.bytecode.accessors.ClassInfoAccessor;
23import cuchaz.enigma.bytecode.accessors.ConstInfoAccessor; 23import cuchaz.enigma.bytecode.accessors.ConstInfoAccessor;
24import cuchaz.enigma.bytecode.accessors.MemberRefInfoAccessor; 24import cuchaz.enigma.bytecode.accessors.MemberRefInfoAccessor;
25 25
26public class ConstPoolEditor 26public class ConstPoolEditor {
27{ 27
28 private static Method m_getItem; 28 private static Method m_getItem;
29 private static Method m_addItem; 29 private static Method m_addItem;
30 private static Method m_addItem0; 30 private static Method m_addItem0;
@@ -36,264 +36,213 @@ public class ConstPoolEditor
36 private static Method m_methodWritePool; 36 private static Method m_methodWritePool;
37 private static Constructor<ConstPool> m_constructorPool; 37 private static Constructor<ConstPool> m_constructorPool;
38 38
39 static 39 static {
40 { 40 try {
41 try 41 m_getItem = ConstPool.class.getDeclaredMethod("getItem", int.class);
42 { 42 m_getItem.setAccessible(true);
43 m_getItem = ConstPool.class.getDeclaredMethod( "getItem", int.class );
44 m_getItem.setAccessible( true );
45 43
46 m_addItem = ConstPool.class.getDeclaredMethod( "addItem", Class.forName( "javassist.bytecode.ConstInfo" ) ); 44 m_addItem = ConstPool.class.getDeclaredMethod("addItem", Class.forName("javassist.bytecode.ConstInfo"));
47 m_addItem.setAccessible( true ); 45 m_addItem.setAccessible(true);
48 46
49 m_addItem0 = ConstPool.class.getDeclaredMethod( "addItem0", Class.forName( "javassist.bytecode.ConstInfo" ) ); 47 m_addItem0 = ConstPool.class.getDeclaredMethod("addItem0", Class.forName("javassist.bytecode.ConstInfo"));
50 m_addItem0.setAccessible( true ); 48 m_addItem0.setAccessible(true);
51 49
52 m_items = ConstPool.class.getDeclaredField( "items" ); 50 m_items = ConstPool.class.getDeclaredField("items");
53 m_items.setAccessible( true ); 51 m_items.setAccessible(true);
54 52
55 m_cache = ConstPool.class.getDeclaredField( "itemsCache" ); 53 m_cache = ConstPool.class.getDeclaredField("itemsCache");
56 m_cache.setAccessible( true ); 54 m_cache.setAccessible(true);
57 55
58 m_numItems = ConstPool.class.getDeclaredField( "numOfItems" ); 56 m_numItems = ConstPool.class.getDeclaredField("numOfItems");
59 m_numItems.setAccessible( true ); 57 m_numItems.setAccessible(true);
60 58
61 m_objects = Class.forName( "javassist.bytecode.LongVector" ).getDeclaredField( "objects" ); 59 m_objects = Class.forName("javassist.bytecode.LongVector").getDeclaredField("objects");
62 m_objects.setAccessible( true ); 60 m_objects.setAccessible(true);
63 61
64 m_elements = Class.forName( "javassist.bytecode.LongVector" ).getDeclaredField( "elements" ); 62 m_elements = Class.forName("javassist.bytecode.LongVector").getDeclaredField("elements");
65 m_elements.setAccessible( true ); 63 m_elements.setAccessible(true);
66 64
67 m_methodWritePool = ConstPool.class.getDeclaredMethod( "write", DataOutputStream.class ); 65 m_methodWritePool = ConstPool.class.getDeclaredMethod("write", DataOutputStream.class);
68 m_methodWritePool.setAccessible( true ); 66 m_methodWritePool.setAccessible(true);
69 67
70 m_constructorPool = ConstPool.class.getDeclaredConstructor( DataInputStream.class ); 68 m_constructorPool = ConstPool.class.getDeclaredConstructor(DataInputStream.class);
71 m_constructorPool.setAccessible( true ); 69 m_constructorPool.setAccessible(true);
72 } 70 } catch (Exception ex) {
73 catch( Exception ex ) 71 throw new Error(ex);
74 {
75 throw new Error( ex );
76 } 72 }
77 } 73 }
78 74
79 private ConstPool m_pool; 75 private ConstPool m_pool;
80 76
81 public ConstPoolEditor( ConstPool pool ) 77 public ConstPoolEditor(ConstPool pool) {
82 {
83 m_pool = pool; 78 m_pool = pool;
84 } 79 }
85 80
86 public void writePool( DataOutputStream out ) 81 public void writePool(DataOutputStream out) {
87 { 82 try {
88 try 83 m_methodWritePool.invoke(m_pool, out);
89 { 84 } catch (Exception ex) {
90 m_methodWritePool.invoke( m_pool, out ); 85 throw new Error(ex);
91 }
92 catch( Exception ex )
93 {
94 throw new Error( ex );
95 } 86 }
96 } 87 }
97 88
98 public static ConstPool readPool( DataInputStream in ) 89 public static ConstPool readPool(DataInputStream in) {
99 { 90 try {
100 try 91 return m_constructorPool.newInstance(in);
101 { 92 } catch (Exception ex) {
102 return m_constructorPool.newInstance( in ); 93 throw new Error(ex);
103 }
104 catch( Exception ex )
105 {
106 throw new Error( ex );
107 } 94 }
108 } 95 }
109 96
110 public String getMemberrefClassname( int memberrefIndex ) 97 public String getMemberrefClassname(int memberrefIndex) {
111 { 98 return Descriptor.toJvmName(m_pool.getClassInfo(m_pool.getMemberClass(memberrefIndex)));
112 return Descriptor.toJvmName( m_pool.getClassInfo( m_pool.getMemberClass( memberrefIndex ) ) );
113 } 99 }
114 100
115 public String getMemberrefName( int memberrefIndex ) 101 public String getMemberrefName(int memberrefIndex) {
116 { 102 return m_pool.getUtf8Info(m_pool.getNameAndTypeName(m_pool.getMemberNameAndType(memberrefIndex)));
117 return m_pool.getUtf8Info( m_pool.getNameAndTypeName( m_pool.getMemberNameAndType( memberrefIndex ) ) );
118 } 103 }
119 104
120 public String getMemberrefType( int memberrefIndex ) 105 public String getMemberrefType(int memberrefIndex) {
121 { 106 return m_pool.getUtf8Info(m_pool.getNameAndTypeDescriptor(m_pool.getMemberNameAndType(memberrefIndex)));
122 return m_pool.getUtf8Info( m_pool.getNameAndTypeDescriptor( m_pool.getMemberNameAndType( memberrefIndex ) ) );
123 } 107 }
124 108
125 public ConstInfoAccessor getItem( int index ) 109 public ConstInfoAccessor getItem(int index) {
126 { 110 try {
127 try 111 Object entry = m_getItem.invoke(m_pool, index);
128 { 112 if (entry == null) {
129 Object entry = m_getItem.invoke( m_pool, index );
130 if( entry == null )
131 {
132 return null; 113 return null;
133 } 114 }
134 return new ConstInfoAccessor( entry ); 115 return new ConstInfoAccessor(entry);
135 } 116 } catch (Exception ex) {
136 catch( Exception ex ) 117 throw new Error(ex);
137 {
138 throw new Error( ex );
139 } 118 }
140 } 119 }
141 120
142 public int addItem( Object item ) 121 public int addItem(Object item) {
143 { 122 try {
144 try 123 return (Integer)m_addItem.invoke(m_pool, item);
145 { 124 } catch (Exception ex) {
146 return (Integer)m_addItem.invoke( m_pool, item ); 125 throw new Error(ex);
147 }
148 catch( Exception ex )
149 {
150 throw new Error( ex );
151 } 126 }
152 } 127 }
153 128
154 public int addItemForceNew( Object item ) 129 public int addItemForceNew(Object item) {
155 { 130 try {
156 try 131 return (Integer)m_addItem0.invoke(m_pool, item);
157 { 132 } catch (Exception ex) {
158 return (Integer)m_addItem0.invoke( m_pool, item ); 133 throw new Error(ex);
159 }
160 catch( Exception ex )
161 {
162 throw new Error( ex );
163 } 134 }
164 } 135 }
165 @SuppressWarnings( "rawtypes" ) 136
166 public void removeLastItem( ) 137 @SuppressWarnings("rawtypes")
167 { 138 public void removeLastItem() {
168 try 139 try {
169 {
170 // remove the item from the cache 140 // remove the item from the cache
171 HashMap cache = getCache(); 141 HashMap cache = getCache();
172 if( cache != null ) 142 if (cache != null) {
173 { 143 Object item = getItem(m_pool.getSize() - 1);
174 Object item = getItem( m_pool.getSize() - 1 ); 144 cache.remove(item);
175 cache.remove( item );
176 } 145 }
177 146
178 // remove the actual item 147 // remove the actual item
179 // based off of LongVector.addElement() 148 // based off of LongVector.addElement()
180 Object items = m_items.get( m_pool ); 149 Object items = m_items.get(m_pool);
181 Object[][] objects = (Object[][])m_objects.get( items ); 150 Object[][] objects = (Object[][])m_objects.get(items);
182 int numElements = (Integer)m_elements.get( items ) - 1; 151 int numElements = (Integer)m_elements.get(items) - 1;
183 int nth = numElements >> 7; 152 int nth = numElements >> 7;
184 int offset = numElements & (128 - 1); 153 int offset = numElements & (128 - 1);
185 objects[nth][offset] = null; 154 objects[nth][offset] = null;
186 155
187 // decrement the number of items 156 // decrement the number of items
188 m_elements.set( items, numElements ); 157 m_elements.set(items, numElements);
189 m_numItems.set( m_pool, (Integer)m_numItems.get( m_pool ) - 1 ); 158 m_numItems.set(m_pool, (Integer)m_numItems.get(m_pool) - 1);
190 } 159 } catch (Exception ex) {
191 catch( Exception ex ) 160 throw new Error(ex);
192 {
193 throw new Error( ex );
194 } 161 }
195 } 162 }
196 163
197 @SuppressWarnings( "rawtypes" ) 164 @SuppressWarnings("rawtypes")
198 /* TEMP */public HashMap getCache( ) 165 public HashMap getCache() {
199 { 166 try {
200 try 167 return (HashMap)m_cache.get(m_pool);
201 { 168 } catch (Exception ex) {
202 return (HashMap)m_cache.get( m_pool ); 169 throw new Error(ex);
203 }
204 catch( Exception ex )
205 {
206 throw new Error( ex );
207 } 170 }
208 } 171 }
209 172
210 @SuppressWarnings( { "rawtypes", "unchecked" } ) 173 @SuppressWarnings({ "rawtypes", "unchecked" })
211 public void changeMemberrefNameAndType( int memberrefIndex, String newName, String newType ) 174 public void changeMemberrefNameAndType(int memberrefIndex, String newName, String newType) {
212 {
213 // NOTE: when changing values, we always need to copy-on-write 175 // NOTE: when changing values, we always need to copy-on-write
214 try 176 try {
215 {
216 // get the memberref item 177 // get the memberref item
217 Object item = getItem( memberrefIndex ).getItem(); 178 Object item = getItem(memberrefIndex).getItem();
218 179
219 // update the cache 180 // update the cache
220 HashMap cache = getCache(); 181 HashMap cache = getCache();
221 if( cache != null ) 182 if (cache != null) {
222 { 183 cache.remove(item);
223 cache.remove( item );
224 } 184 }
225 185
226 new MemberRefInfoAccessor( item ).setNameAndTypeIndex( m_pool.addNameAndTypeInfo( newName, newType ) ); 186 new MemberRefInfoAccessor(item).setNameAndTypeIndex(m_pool.addNameAndTypeInfo(newName, newType));
227 187
228 // update the cache 188 // update the cache
229 if( cache != null ) 189 if (cache != null) {
230 { 190 cache.put(item, item);
231 cache.put( item, item );
232 } 191 }
233 } 192 } catch (Exception ex) {
234 catch( Exception ex ) 193 throw new Error(ex);
235 {
236 throw new Error( ex );
237 } 194 }
238 195
239 // make sure the change worked 196 // make sure the change worked
240 assert( newName.equals( getMemberrefName( memberrefIndex ) ) ); 197 assert (newName.equals(getMemberrefName(memberrefIndex)));
241 assert( newType.equals( getMemberrefType( memberrefIndex ) ) ); 198 assert (newType.equals(getMemberrefType(memberrefIndex)));
242 } 199 }
243 200
244 @SuppressWarnings( { "rawtypes", "unchecked" } ) 201 @SuppressWarnings({ "rawtypes", "unchecked" })
245 public void changeClassName( int classNameIndex, String newName ) 202 public void changeClassName(int classNameIndex, String newName) {
246 {
247 // NOTE: when changing values, we always need to copy-on-write 203 // NOTE: when changing values, we always need to copy-on-write
248 try 204 try {
249 {
250 // get the class item 205 // get the class item
251 Object item = getItem( classNameIndex ).getItem(); 206 Object item = getItem(classNameIndex).getItem();
252 207
253 // update the cache 208 // update the cache
254 HashMap cache = getCache(); 209 HashMap cache = getCache();
255 if( cache != null ) 210 if (cache != null) {
256 { 211 cache.remove(item);
257 cache.remove( item );
258 } 212 }
259 213
260 // add the new name and repoint the name-and-type to it 214 // add the new name and repoint the name-and-type to it
261 new ClassInfoAccessor( item ).setNameIndex( m_pool.addUtf8Info( newName ) ); 215 new ClassInfoAccessor(item).setNameIndex(m_pool.addUtf8Info(newName));
262 216
263 // update the cache 217 // update the cache
264 if( cache != null ) 218 if (cache != null) {
265 { 219 cache.put(item, item);
266 cache.put( item, item );
267 } 220 }
268 } 221 } catch (Exception ex) {
269 catch( Exception ex ) 222 throw new Error(ex);
270 {
271 throw new Error( ex );
272 } 223 }
273 } 224 }
274 225
275 public static ConstPool newConstPool( ) 226 public static ConstPool newConstPool() {
276 {
277 // const pool expects the name of a class to initialize itself 227 // const pool expects the name of a class to initialize itself
278 // but we want an empty pool 228 // but we want an empty pool
279 // so give it a bogus name, and then clear the entries afterwards 229 // so give it a bogus name, and then clear the entries afterwards
280 ConstPool pool = new ConstPool( "a" ); 230 ConstPool pool = new ConstPool("a");
281 231
282 ConstPoolEditor editor = new ConstPoolEditor( pool ); 232 ConstPoolEditor editor = new ConstPoolEditor(pool);
283 int size = pool.getSize(); 233 int size = pool.getSize();
284 for( int i=0; i<size-1; i++ ) 234 for (int i = 0; i < size - 1; i++) {
285 {
286 editor.removeLastItem(); 235 editor.removeLastItem();
287 } 236 }
288 237
289 // make sure the pool is actually empty 238 // make sure the pool is actually empty
290 // although, in this case "empty" means one thing in it 239 // although, in this case "empty" means one thing in it
291 // the JVM spec says index 0 should be reserved 240 // the JVM spec says index 0 should be reserved
292 assert( pool.getSize() == 1 ); 241 assert (pool.getSize() == 1);
293 assert( editor.getItem( 0 ) == null ); 242 assert (editor.getItem(0) == null);
294 assert( editor.getItem( 1 ) == null ); 243 assert (editor.getItem(1) == null);
295 assert( editor.getItem( 2 ) == null ); 244 assert (editor.getItem(2) == null);
296 assert( editor.getItem( 3 ) == null ); 245 assert (editor.getItem(3) == null);
297 246
298 // also, clear the cache 247 // also, clear the cache
299 editor.getCache().clear(); 248 editor.getCache().clear();
@@ -301,15 +250,13 @@ public class ConstPoolEditor
301 return pool; 250 return pool;
302 } 251 }
303 252
304 public String dump( ) 253 public String dump() {
305 {
306 StringBuilder buf = new StringBuilder(); 254 StringBuilder buf = new StringBuilder();
307 for( int i=1; i<m_pool.getSize(); i++ ) 255 for (int i = 1; i < m_pool.getSize(); i++) {
308 { 256 buf.append(String.format("%4d", i));
309 buf.append( String.format( "%4d", i ) ); 257 buf.append(" ");
310 buf.append( " " ); 258 buf.append(getItem(i).toString());
311 buf.append( getItem( i ).toString() ); 259 buf.append("\n");
312 buf.append( "\n" );
313 } 260 }
314 return buf.toString(); 261 return buf.toString();
315 } 262 }