1 28 29 package org.jibx.binding.classes; 30 31 import java.io.File ; 32 import java.util.HashMap ; 33 34 import org.apache.bcel.Constants; 35 import org.apache.bcel.classfile.Utility; 36 import org.apache.bcel.generic.Type; 37 38 import org.jibx.binding.def.BindingDefinition; 39 import org.jibx.runtime.JiBXException; 40 41 48 49 public class BoundClass 50 { 51 54 55 private static final String GENERIC_MUNGE_CLASS = 56 BindingDefinition.GENERATE_PREFIX + "MungeAdapter"; 57 58 59 private static final String ACCESS_PREFIX = 60 BindingDefinition.GENERATE_PREFIX + "access_"; 61 62 63 private static final Type[] EMPTY_TYPE_ARGS = {}; 64 65 68 70 private static HashMap s_nameMap; 71 72 73 private static String s_modifyPackage; 74 75 76 private static File s_modifyRoot; 77 78 79 private static MungedClass s_genericMunge; 80 81 84 85 private final ClassFile m_boundClass; 86 87 88 private final MungedClass m_mungedClass; 89 90 92 private HashMap m_loadMap; 93 94 96 private HashMap m_storeMap; 97 98 104 105 private BoundClass(ClassFile bound, MungedClass munge) { 106 m_boundClass = bound; 107 m_mungedClass = munge; 108 } 109 110 115 116 public ClassFile getClassFile() { 117 return m_boundClass; 118 } 119 120 125 126 public String getClassName() { 127 return m_boundClass.getName(); 128 } 129 130 135 136 public ClassFile getMungedFile() { 137 return m_mungedClass.getClassFile(); 138 } 139 140 146 147 public boolean isDirectAccess() { 148 return m_boundClass == m_mungedClass.getClassFile(); 149 } 150 151 164 165 public ClassItem getLoadMethod(ClassItem item, ClassFile from) 166 throws JiBXException { 167 168 if (m_loadMap == null) { 170 m_loadMap = new HashMap (); 171 } 172 173 BindingMethod method = (BindingMethod)m_loadMap.get(item); 175 if (method == null) { 176 177 String name = ACCESS_PREFIX + "load_" + item.getName(); 179 ClassFile cf = item.getClassFile(); 180 Type type = Type.getType(Utility.getSignature(item.getTypeName())); 181 MethodBuilder mb = new ExceptionMethodBuilder(name, type, 182 EMPTY_TYPE_ARGS, cf, (short)0); 183 184 mb.appendLoadLocal(0); 186 if (item.isMethod()) { 187 mb.addMethodExceptions(item); 188 mb.appendCall(item); 189 } else { 190 mb.appendGetField(item); 191 } 192 mb.appendReturn(type); 193 194 method = m_mungedClass.getUniqueMethod(mb, true); 196 m_loadMap.put(item, method); 197 } 198 199 method.makeAccessible(from); 201 return method.getItem(); 202 } 203 204 217 218 public ClassItem getStoreMethod(ClassItem item, ClassFile from) 219 throws JiBXException { 220 221 if (m_storeMap == null) { 223 m_storeMap = new HashMap (); 224 } 225 226 BindingMethod method = (BindingMethod)m_storeMap.get(item); 228 if (method == null) { 229 230 String name = ACCESS_PREFIX + "store_" + item.getName(); 232 ClassFile cf = item.getClassFile(); 233 Type type; 234 if (item.isMethod()) { 235 String sig = item.getSignature(); 236 int start = sig.indexOf('('); 237 int end = sig.indexOf(')'); 238 type = Type.getType(sig.substring(start+1, end)); 239 } else { 240 type = Type.getType(Utility.getSignature(item.getTypeName())); 241 } 242 MethodBuilder mb = new ExceptionMethodBuilder(name, Type.VOID, 243 new Type[] {type}, cf, (short)0); 244 245 mb.appendLoadLocal(0); 247 mb.appendLoadLocal(1); 248 if (item.isMethod()) { 249 mb.addMethodExceptions(item); 250 mb.appendCall(item); 251 } else { 252 mb.appendPutField(item); 253 } 254 mb.appendReturn(); 255 256 method = m_mungedClass.getUniqueMethod(mb, true); 258 m_storeMap.put(item, method); 259 } 260 261 method.makeAccessible(from); 263 return method.getItem(); 264 } 265 266 274 275 public BindingMethod getUniqueMethod(MethodBuilder builder) 276 throws JiBXException { 277 return m_mungedClass.getUniqueMethod(builder, true); 278 } 279 280 288 289 public BindingMethod getUniqueNamed(MethodBuilder builder) 290 throws JiBXException { 291 return m_mungedClass.getUniqueMethod(builder, false); 292 } 293 294 300 301 public void addFactory(String fact) { 302 if (isDirectAccess()) { 303 m_mungedClass.addFactory(fact); 304 } else { 305 throw new IllegalStateException 306 ("Internal error: not directly modifiable class"); 307 } 308 } 309 310 316 317 public void setFactoryList() throws JiBXException { 318 if (isDirectAccess()) { 319 m_mungedClass.setFactoryList(); 320 } else { 321 throw new IllegalStateException 322 ("Internal error: not directly modifiable class"); 323 } 324 } 325 326 338 339 private static BoundClass createInstance(String key, ClassFile bound, 340 MungedClass munge) { 341 BoundClass inst = new BoundClass(bound, munge); 342 s_nameMap.put(key, inst); 343 return inst; 344 } 345 346 355 356 private static BoundClass findOrCreateInstance(ClassFile bound, 357 MungedClass munge) { 358 String key = bound.getName()+ ':' + munge.getClassFile().getName(); 359 BoundClass inst = (BoundClass)s_nameMap.get(key); 360 if (inst == null) { 361 inst = createInstance(key, bound, munge); 362 } 363 return inst; 364 } 365 366 383 384 public static BoundClass getInstance(ClassFile cf, BoundClass context) 385 throws JiBXException { 386 387 BoundClass inst = (BoundClass)s_nameMap.get(cf.getName()); 389 if (inst == null) { 390 391 if (!cf.isInterface() && cf.isModifiable()) { 393 394 inst = createInstance(cf.getName(), cf, 396 MungedClass.getInstance(cf)); 397 398 } else { 399 400 if (context != null && 402 context.getClassFile().isSuperclass(cf.getName())) { 403 404 inst = findOrCreateInstance(cf, context.m_mungedClass); 406 407 } else { 408 409 if (s_genericMunge == null) { 411 String mname = (s_modifyPackage == null) ? 412 GENERIC_MUNGE_CLASS : 413 s_modifyPackage + '.' + GENERIC_MUNGE_CLASS; 414 ClassFile base = ClassCache. 415 getClassFile("java.lang.Object"); 416 int acc = Constants.ACC_PUBLIC|Constants.ACC_ABSTRACT; 417 ClassFile gen = new ClassFile(mname, 418 s_modifyRoot, base, acc, new String [0]); 419 gen.addDefaultConstructor(); 420 s_genericMunge = MungedClass.getInstance(gen); 421 MungedClass.delayedAddUnique(gen); 422 } 423 inst = findOrCreateInstance(cf, s_genericMunge); 424 425 } 426 } 427 } 428 return inst; 429 } 430 431 443 444 public static BoundClass getInstance(String name, BoundClass context) 445 throws JiBXException { 446 447 BoundClass inst = (BoundClass)s_nameMap.get(name); 449 if (inst == null) { 450 ClassFile cf = ClassCache.getClassFile(name); 451 return getInstance(cf, context); 452 } 453 return inst; 454 } 455 456 460 461 public static void reset() { 462 s_nameMap = new HashMap (); 463 s_modifyPackage = null; 464 s_modifyRoot = null; 465 s_genericMunge = null; 466 } 467 468 472 473 public static void setModify(File root, String pkg) { 474 s_modifyRoot = root; 475 s_modifyPackage = pkg; 476 if (s_modifyPackage.length() == 0) { 477 s_modifyPackage = null; 478 } 479 } 480 } | Popular Tags |