1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/classfile/ClassTranslator.java Tue Jun 03 13:26:47 2008 -0700 1.3 @@ -0,0 +1,368 @@ 1.4 +/* 1.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Sun designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Sun in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.26 + * have any questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.classfile; 1.30 + 1.31 +import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; 1.32 +import com.sun.tools.classfile.ConstantPool.CONSTANT_Double_info; 1.33 +import com.sun.tools.classfile.ConstantPool.CONSTANT_Fieldref_info; 1.34 +import com.sun.tools.classfile.ConstantPool.CONSTANT_Float_info; 1.35 +import com.sun.tools.classfile.ConstantPool.CONSTANT_Integer_info; 1.36 +import com.sun.tools.classfile.ConstantPool.CONSTANT_InterfaceMethodref_info; 1.37 +import com.sun.tools.classfile.ConstantPool.CONSTANT_Long_info; 1.38 +import com.sun.tools.classfile.ConstantPool.CONSTANT_Methodref_info; 1.39 +import com.sun.tools.classfile.ConstantPool.CONSTANT_NameAndType_info; 1.40 +import com.sun.tools.classfile.ConstantPool.CONSTANT_String_info; 1.41 +import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info; 1.42 +import com.sun.tools.classfile.ConstantPool.CPInfo; 1.43 +import java.util.Map; 1.44 + 1.45 +/** 1.46 + * Rewrites a class file using a map of translations. 1.47 + * 1.48 + * <p><b>This is NOT part of any API supported by Sun Microsystems. If 1.49 + * you write code that depends on this, you do so at your own risk. 1.50 + * This code and its internal interfaces are subject to change or 1.51 + * deletion without notice.</b> 1.52 + */ 1.53 +public class ClassTranslator 1.54 + implements ConstantPool.Visitor<ConstantPool.CPInfo,Map<Object,Object>> { 1.55 + /** 1.56 + * Create a new ClassFile from {@code cf}, such that for all entries 1.57 + * {@code k -\> v} in {@code translations}, 1.58 + * each occurrence of {@code k} in {@code cf} will be replaced by {@code v}. 1.59 + * in 1.60 + * @param cf the class file to be processed 1.61 + * @param translations the set of translations to be applied 1.62 + * @return a copy of {@code} with the values in {@code translations} substituted 1.63 + */ 1.64 + public ClassFile translate(ClassFile cf, Map<Object,Object> translations) { 1.65 + ClassFile cf2 = (ClassFile) translations.get(cf); 1.66 + if (cf2 == null) { 1.67 + ConstantPool constant_pool2 = translate(cf.constant_pool, translations); 1.68 + Field[] fields2 = translate(cf.fields, cf.constant_pool, translations); 1.69 + Method[] methods2 = translateMethods(cf.methods, cf.constant_pool, translations); 1.70 + Attributes attributes2 = translateAttributes(cf.attributes, cf.constant_pool, 1.71 + translations); 1.72 + 1.73 + if (constant_pool2 == cf.constant_pool && 1.74 + fields2 == cf.fields && 1.75 + methods2 == cf.methods && 1.76 + attributes2 == cf.attributes) 1.77 + cf2 = cf; 1.78 + else 1.79 + cf2 = new ClassFile( 1.80 + cf.magic, 1.81 + cf.minor_version, 1.82 + cf.major_version, 1.83 + constant_pool2, 1.84 + cf.access_flags, 1.85 + cf.this_class, 1.86 + cf.super_class, 1.87 + cf.interfaces, 1.88 + fields2, 1.89 + methods2, 1.90 + attributes2); 1.91 + translations.put(cf, cf2); 1.92 + } 1.93 + return cf2; 1.94 + } 1.95 + 1.96 + ConstantPool translate(ConstantPool cp, Map<Object,Object> translations) { 1.97 + ConstantPool cp2 = (ConstantPool) translations.get(cp); 1.98 + if (cp2 == null) { 1.99 + ConstantPool.CPInfo[] pool2 = new ConstantPool.CPInfo[cp.size()]; 1.100 + boolean eq = true; 1.101 + for (int i = 0; i < cp.size(); i++) { 1.102 + ConstantPool.CPInfo cpInfo; 1.103 + try { 1.104 + cpInfo = cp.get(i); 1.105 + } catch (ConstantPool.InvalidIndex e) { 1.106 + throw new IllegalStateException(e); 1.107 + } 1.108 + ConstantPool.CPInfo cpInfo2 = translate(cpInfo, translations); 1.109 + eq &= (cpInfo == cpInfo2); 1.110 + pool2[i] = cpInfo2; 1.111 + if (cpInfo.getTag() != cpInfo2.getTag()) 1.112 + throw new IllegalStateException(); 1.113 + switch (cpInfo.getTag()) { 1.114 + case ConstantPool.CONSTANT_Double: 1.115 + case ConstantPool.CONSTANT_Long: 1.116 + i += 1; 1.117 + } 1.118 + } 1.119 + 1.120 + if (eq) 1.121 + cp2 = cp; 1.122 + else 1.123 + cp2 = new ConstantPool(pool2); 1.124 + 1.125 + translations.put(cp, cp2); 1.126 + } 1.127 + return cp2; 1.128 + } 1.129 + 1.130 + ConstantPool.CPInfo translate(ConstantPool.CPInfo cpInfo, Map<Object,Object> translations) { 1.131 + ConstantPool.CPInfo cpInfo2 = (ConstantPool.CPInfo) translations.get(cpInfo); 1.132 + if (cpInfo2 == null) { 1.133 + cpInfo2 = cpInfo.accept(this, translations); 1.134 + translations.put(cpInfo, cpInfo2); 1.135 + } 1.136 + return cpInfo2; 1.137 + } 1.138 + 1.139 + Field[] translate(Field[] fields, ConstantPool constant_pool, Map<Object,Object> translations) { 1.140 + Field[] fields2 = (Field[]) translations.get(fields); 1.141 + if (fields2 == null) { 1.142 + fields2 = new Field[fields.length]; 1.143 + for (int i = 0; i < fields.length; i++) 1.144 + fields2[i] = translate(fields[i], constant_pool, translations); 1.145 + if (equal(fields, fields2)) 1.146 + fields2 = fields; 1.147 + translations.put(fields, fields2); 1.148 + } 1.149 + return fields2; 1.150 + } 1.151 + 1.152 + Field translate(Field field, ConstantPool constant_pool, Map<Object,Object> translations) { 1.153 + Field field2 = (Field) translations.get(field); 1.154 + if (field2 == null) { 1.155 + Attributes attributes2 = translateAttributes(field.attributes, constant_pool, 1.156 + translations); 1.157 + 1.158 + if (attributes2 == field.attributes) 1.159 + field2 = field; 1.160 + else 1.161 + field2 = new Field( 1.162 + field.access_flags, 1.163 + field.name_index, 1.164 + field.descriptor, 1.165 + attributes2); 1.166 + translations.put(field, field2); 1.167 + } 1.168 + return field2; 1.169 + } 1.170 + 1.171 + Method[] translateMethods(Method[] methods, ConstantPool constant_pool, Map<Object,Object> translations) { 1.172 + Method[] methods2 = (Method[]) translations.get(methods); 1.173 + if (methods2 == null) { 1.174 + methods2 = new Method[methods.length]; 1.175 + for (int i = 0; i < methods.length; i++) 1.176 + methods2[i] = translate(methods[i], constant_pool, translations); 1.177 + if (equal(methods, methods2)) 1.178 + methods2 = methods; 1.179 + translations.put(methods, methods2); 1.180 + } 1.181 + return methods2; 1.182 + } 1.183 + 1.184 + Method translate(Method method, ConstantPool constant_pool, Map<Object,Object> translations) { 1.185 + Method method2 = (Method) translations.get(method); 1.186 + if (method2 == null) { 1.187 + Attributes attributes2 = translateAttributes(method.attributes, constant_pool, 1.188 + translations); 1.189 + 1.190 + if (attributes2 == method.attributes) 1.191 + method2 = method; 1.192 + else 1.193 + method2 = new Method( 1.194 + method.access_flags, 1.195 + method.name_index, 1.196 + method.descriptor, 1.197 + attributes2); 1.198 + translations.put(method, method2); 1.199 + } 1.200 + return method2; 1.201 + } 1.202 + 1.203 + Attributes translateAttributes(Attributes attributes, 1.204 + ConstantPool constant_pool, Map<Object,Object> translations) { 1.205 + Attributes attributes2 = (Attributes) translations.get(attributes); 1.206 + if (attributes2 == null) { 1.207 + Attribute[] attrArray2 = new Attribute[attributes.size()]; 1.208 + ConstantPool constant_pool2 = translate(constant_pool, translations); 1.209 + boolean attrsEqual = true; 1.210 + for (int i = 0; i < attributes.size(); i++) { 1.211 + Attribute attr = attributes.get(i); 1.212 + Attribute attr2 = translate(attr, translations); 1.213 + if (attr2 != attr) 1.214 + attrsEqual = false; 1.215 + attrArray2[i] = attr2; 1.216 + } 1.217 + if ((constant_pool2 == constant_pool) && attrsEqual) 1.218 + attributes2 = attributes; 1.219 + else 1.220 + attributes2 = new Attributes(constant_pool2, attrArray2); 1.221 + translations.put(attributes, attributes2); 1.222 + } 1.223 + return attributes2; 1.224 + } 1.225 + 1.226 + Attribute translate(Attribute attribute, Map<Object,Object> translations) { 1.227 + Attribute attribute2 = (Attribute) translations.get(attribute); 1.228 + if (attribute2 == null) { 1.229 + attribute2 = attribute; // don't support translation within attributes yet 1.230 + // (what about Code attribute) 1.231 + translations.put(attribute, attribute2); 1.232 + } 1.233 + return attribute2; 1.234 + } 1.235 + 1.236 + private static <T> boolean equal(T[] a1, T[] a2) { 1.237 + if (a1 == null || a2 == null) 1.238 + return (a1 == a2); 1.239 + if (a1.length != a2.length) 1.240 + return false; 1.241 + for (int i = 0; i < a1.length; i++) { 1.242 + if (a1[i] != a2[i]) 1.243 + return false; 1.244 + } 1.245 + return true; 1.246 + } 1.247 + 1.248 + public CPInfo visitClass(CONSTANT_Class_info info, Map<Object, Object> translations) { 1.249 + CONSTANT_Class_info info2 = (CONSTANT_Class_info) translations.get(info); 1.250 + if (info2 == null) { 1.251 + ConstantPool cp2 = translate(info.cp, translations); 1.252 + if (cp2 == info.cp) 1.253 + info2 = info; 1.254 + else 1.255 + info2 = new CONSTANT_Class_info(cp2, info.name_index); 1.256 + translations.put(info, info2); 1.257 + } 1.258 + return info; 1.259 + } 1.260 + 1.261 + public CPInfo visitDouble(CONSTANT_Double_info info, Map<Object, Object> translations) { 1.262 + CONSTANT_Double_info info2 = (CONSTANT_Double_info) translations.get(info); 1.263 + if (info2 == null) { 1.264 + info2 = info; 1.265 + translations.put(info, info2); 1.266 + } 1.267 + return info; 1.268 + } 1.269 + 1.270 + public CPInfo visitFieldref(CONSTANT_Fieldref_info info, Map<Object, Object> translations) { 1.271 + CONSTANT_Fieldref_info info2 = (CONSTANT_Fieldref_info) translations.get(info); 1.272 + if (info2 == null) { 1.273 + ConstantPool cp2 = translate(info.cp, translations); 1.274 + if (cp2 == info.cp) 1.275 + info2 = info; 1.276 + else 1.277 + info2 = new CONSTANT_Fieldref_info(cp2, info.class_index, info.name_and_type_index); 1.278 + translations.put(info, info2); 1.279 + } 1.280 + return info; 1.281 + } 1.282 + 1.283 + public CPInfo visitFloat(CONSTANT_Float_info info, Map<Object, Object> translations) { 1.284 + CONSTANT_Float_info info2 = (CONSTANT_Float_info) translations.get(info); 1.285 + if (info2 == null) { 1.286 + info2 = info; 1.287 + translations.put(info, info2); 1.288 + } 1.289 + return info; 1.290 + } 1.291 + 1.292 + public CPInfo visitInteger(CONSTANT_Integer_info info, Map<Object, Object> translations) { 1.293 + CONSTANT_Integer_info info2 = (CONSTANT_Integer_info) translations.get(info); 1.294 + if (info2 == null) { 1.295 + info2 = info; 1.296 + translations.put(info, info2); 1.297 + } 1.298 + return info; 1.299 + } 1.300 + 1.301 + public CPInfo visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Map<Object, Object> translations) { 1.302 + CONSTANT_InterfaceMethodref_info info2 = (CONSTANT_InterfaceMethodref_info) translations.get(info); 1.303 + if (info2 == null) { 1.304 + ConstantPool cp2 = translate(info.cp, translations); 1.305 + if (cp2 == info.cp) 1.306 + info2 = info; 1.307 + else 1.308 + info2 = new CONSTANT_InterfaceMethodref_info(cp2, info.class_index, info.name_and_type_index); 1.309 + translations.put(info, info2); 1.310 + } 1.311 + return info; 1.312 + } 1.313 + 1.314 + public CPInfo visitLong(CONSTANT_Long_info info, Map<Object, Object> translations) { 1.315 + CONSTANT_Long_info info2 = (CONSTANT_Long_info) translations.get(info); 1.316 + if (info2 == null) { 1.317 + info2 = info; 1.318 + translations.put(info, info2); 1.319 + } 1.320 + return info; 1.321 + } 1.322 + 1.323 + public CPInfo visitNameAndType(CONSTANT_NameAndType_info info, Map<Object, Object> translations) { 1.324 + CONSTANT_NameAndType_info info2 = (CONSTANT_NameAndType_info) translations.get(info); 1.325 + if (info2 == null) { 1.326 + ConstantPool cp2 = translate(info.cp, translations); 1.327 + if (cp2 == info.cp) 1.328 + info2 = info; 1.329 + else 1.330 + info2 = new CONSTANT_NameAndType_info(cp2, info.name_index, info.type_index); 1.331 + translations.put(info, info2); 1.332 + } 1.333 + return info; 1.334 + } 1.335 + 1.336 + public CPInfo visitMethodref(CONSTANT_Methodref_info info, Map<Object, Object> translations) { 1.337 + CONSTANT_Methodref_info info2 = (CONSTANT_Methodref_info) translations.get(info); 1.338 + if (info2 == null) { 1.339 + ConstantPool cp2 = translate(info.cp, translations); 1.340 + if (cp2 == info.cp) 1.341 + info2 = info; 1.342 + else 1.343 + info2 = new CONSTANT_Methodref_info(cp2, info.class_index, info.name_and_type_index); 1.344 + translations.put(info, info2); 1.345 + } 1.346 + return info; 1.347 + } 1.348 + 1.349 + public CPInfo visitString(CONSTANT_String_info info, Map<Object, Object> translations) { 1.350 + CONSTANT_String_info info2 = (CONSTANT_String_info) translations.get(info); 1.351 + if (info2 == null) { 1.352 + ConstantPool cp2 = translate(info.cp, translations); 1.353 + if (cp2 == info.cp) 1.354 + info2 = info; 1.355 + else 1.356 + info2 = new CONSTANT_String_info(cp2, info.string_index); 1.357 + translations.put(info, info2); 1.358 + } 1.359 + return info; 1.360 + } 1.361 + 1.362 + public CPInfo visitUtf8(CONSTANT_Utf8_info info, Map<Object, Object> translations) { 1.363 + CONSTANT_Utf8_info info2 = (CONSTANT_Utf8_info) translations.get(info); 1.364 + if (info2 == null) { 1.365 + info2 = info; 1.366 + translations.put(info, info2); 1.367 + } 1.368 + return info; 1.369 + } 1.370 + 1.371 +}