1 5 package com.tc.object.config; 6 7 import com.tc.asm.ClassVisitor; 8 import com.tc.aspectwerkz.reflect.ClassInfo; 9 import com.tc.object.bytecode.ByteCodeUtil; 10 import com.tc.object.bytecode.ClassAdapterBase; 11 import com.tc.object.bytecode.ClassAdapterFactory; 12 import com.tc.object.bytecode.DateMethodAdapter; 13 import com.tc.object.bytecode.DistributedMethodCallAdapter; 14 import com.tc.object.bytecode.LogicalMethodAdapter; 15 import com.tc.object.bytecode.ManagerHelper; 16 import com.tc.object.bytecode.MethodAdapter; 17 import com.tc.object.bytecode.MethodCreator; 18 import com.tc.object.config.schema.IncludeOnLoad; 19 import com.tc.object.logging.InstrumentationLogger; 20 21 import java.lang.reflect.Modifier ; 22 import java.util.Collections ; 23 import java.util.HashMap ; 24 import java.util.HashSet ; 25 import java.util.Iterator ; 26 import java.util.LinkedList ; 27 import java.util.List ; 28 import java.util.Map ; 29 import java.util.Set ; 30 31 34 public class TransparencyClassSpec { 35 private static final Object HONOR_TRANSIENT_KEY = "honor-transient"; 36 private static final Object HONOR_VOLATILE_KEY = "honor-volatile"; 37 38 public static final byte NOT_SET = 0x00; 39 public static final byte NOT_ADAPTABLE = 0x01; 40 public static final byte ADAPTABLE = 0x02; 41 public static final byte PORTABLE = 0x03; 42 43 private final DSOClientConfigHelper configuration; 44 private final String className; 45 private final List supportMethodCreators = new LinkedList (); 46 private final Map methodAdapters = new HashMap (); 47 private final Map flags = new HashMap (); 48 private final Set transients = new HashSet (); 49 private final Map codeSpecs = new HashMap (); 50 private final Set nonInstrumentedMethods = Collections.synchronizedSet(new HashSet ()); 51 private String changeApplicatorClassName; 52 private ChangeApplicatorSpec changeApplicatorSpec; 53 private boolean isLogical; 54 private final IncludeOnLoad onLoad = new IncludeOnLoad(); 55 private boolean preInstrumented; 56 57 private boolean useNonDefaultConstructor = false; 58 private boolean generateNonStaticTCFields = true; 59 private boolean honorJDKSubVersionSpecific = false; 60 61 private byte instrumentationAction = NOT_SET; 62 63 private String postCreateMethod = null; 64 private String logicalExtendingClassName = null; 65 private ClassAdapterFactory customClassAdapter = null; 66 67 public TransparencyClassSpec(String className, DSOClientConfigHelper configuration, String changeApplicatorClassName) { 68 this.configuration = configuration; 69 this.className = className; 70 this.changeApplicatorClassName = changeApplicatorClassName; 71 this.changeApplicatorSpec = new DSOChangeApplicatorSpec(changeApplicatorClassName); 72 this.isLogical = true; 73 } 74 75 public TransparencyClassSpec(String className, DSOClientConfigHelper configuration) { 76 this.className = className; 77 this.configuration = configuration; 78 this.isLogical = false; 79 this.changeApplicatorClassName = null; 80 this.changeApplicatorSpec = null; 81 this.changeApplicatorSpec = null; 82 } 83 84 public TransparencyClassSpec getClassSpec(String clazzName) { 85 String name = clazzName.replace('/', '.'); 86 return configuration.getSpec(name); 87 } 88 89 public boolean hasPhysicallyPortableSpecs(ClassInfo classInfo) { 90 String name = classInfo.getName(); 91 return configuration.shouldBeAdapted(classInfo) && !configuration.isLogical(name) 92 && (configuration.getSpec(name) != null) 93 && (configuration.getSpec(name).getInstrumentationAction() != ADAPTABLE); 94 } 95 96 public TransparencyClassSpec addRoot(String variableName, String rootName) { 97 configuration.addRoot(className, variableName, rootName, false); 98 return this; 99 } 100 101 public TransparencyClassSpec addRoot(String variableName, String rootName, boolean dsoFinal) { 102 configuration.addRoot(className, variableName, rootName, dsoFinal, false); 103 return this; 104 } 105 106 public void addDoNotInstrument(String methodName) { 107 nonInstrumentedMethods.add(methodName); 108 } 109 110 public boolean doNotInstrument(String methodName) { 111 return nonInstrumentedMethods.contains(methodName); 112 } 113 114 public TransparencyClassSpec markPreInstrumented() { 115 preInstrumented = true; 116 return this; 117 } 118 119 public boolean isPreInstrumented() { 120 return preInstrumented; 121 } 122 123 public synchronized LockDefinition[] lockDefinitionsFor(int modifiers, String methodName, String desc, 124 String [] exceptions) { 125 return configuration.lockDefinitionsFor(modifiers, className, methodName, desc, exceptions); 126 } 127 128 public synchronized LockDefinition autolockDefinitionFor(int access, String methodName, String description, 129 String [] exceptions) { 130 LockDefinition[] lds = lockDefinitionsFor(access, methodName, description, exceptions); 131 for (int i = 0; i < lds.length; i++) { 132 if (lds[i].isAutolock()) { return lds[i]; } 133 } 134 throw new AssertionError ("Can't be an autolock and not have an autolock def:" + methodName + " className:" 135 + className); 136 } 137 138 141 public LockDefinition getAutolockDefinition(LockDefinition lds[]) { 142 if (lds == null) return null; 143 for (int i = 0; i < lds.length; i++) { 144 if (lds[i].isAutolock()) { return lds[i]; } 145 } 146 return null; 147 } 148 149 public LockDefinition getNonAutoLockDefinition(LockDefinition lds[]) { 150 if (lds == null) return null; 151 for (int i = 0; i < lds.length; i++) { 152 if (!lds[i].isAutolock()) { return lds[i]; } 153 } 154 return null; 155 } 156 157 public TransparencyClassSpec addSupportMethodCreator(MethodCreator creator) { 158 supportMethodCreators.add(creator); 159 return this; 160 } 161 162 public TransparencyClassSpec addDistributedMethodCall(String methodName, String description, boolean runOnAllNodes) { 163 if ("<init>".equals(methodName) || "<clinit>".equals(methodName)) { throw new AssertionError ( 164 "Initializers of class " 165 + className 166 + " cannot be participated in distrbuted method call and are ignored."); } 167 StringBuffer sb = new StringBuffer ("* "); 168 sb.append(className); 169 sb.append("."); 170 sb.append(methodName); 171 String arguments = ByteCodeUtil.methodDescriptionToMethodArgument(description); 172 sb.append(arguments); 173 final DistributedMethodSpec dms = new DistributedMethodSpec(sb.toString(), runOnAllNodes); 174 configuration.addDistributedMethodCall(dms); 175 return this; 176 } 177 178 public TransparencyClassSpec addTransient(String variableName) { 179 transients.add(variableName); 180 return this; 181 } 182 183 public TransparencyClassSpec addMethodAdapter(String method, MethodAdapter adapter) { 184 methodAdapters.put(method, adapter); 185 return this; 186 } 187 188 public String getClassName() { 189 return className; 190 } 191 192 public void createClassSupportMethods(ClassVisitor classVisitor) { 193 for (Iterator i = supportMethodCreators.iterator(); i.hasNext();) { 194 MethodCreator mc = (MethodCreator) i.next(); 195 mc.createMethods(classVisitor); 196 } 197 } 198 199 public boolean isLogical() { 200 return isLogical; 201 } 202 203 public boolean isPhysical() { 204 return !isLogical; 205 } 206 207 public boolean ignoreChecks() { 208 return TransparencyClassSpecUtil.ignoreChecks(className); 209 } 210 211 public boolean isRootInThisClass(String fieldName) { 212 return configuration.isRoot(className, fieldName); 213 } 214 215 public boolean isRoot(String classname, String fieldName) { 216 return configuration.isRoot(classname, fieldName); 217 } 218 219 public boolean isRootDSOFinal(String fieldName, boolean isPrimitive) { 220 return configuration.isRootDSOFinal(className, fieldName, isPrimitive); 221 } 222 223 public boolean isTransient(int access, String fieldName) { 224 if (ClassAdapterBase.isDelegateFieldName(fieldName)) { return false; } 225 if (transients.contains(fieldName)) return true; 226 return configuration.isTransient(access, className, fieldName); 227 } 228 229 public boolean isVolatile(int access, String fieldName) { 230 return configuration.isVolatile(access, className, fieldName); 231 } 232 233 public String rootNameFor(String fieldName) { 234 return configuration.rootNameFor(className, fieldName); 235 } 236 237 public boolean isLockMethod(int access, String methodName, String description, String [] exceptions) { 238 return configuration.isLockMethod(access, className, methodName, description, exceptions); 239 } 240 241 244 public LockDefinition getLockMethodLockDefinition(int access, LockDefinition lds[]) { 245 if (lds == null) return null; 246 for (int i = 0; i < lds.length; i++) { 247 if ((lds[i].isAutolock() && Modifier.isSynchronized(access) && !Modifier.isStatic(access)) 248 || !lds[i].isAutolock()) { return lds[i]; } 249 } 250 return null; 251 } 252 253 public boolean hasCustomMethodAdapter(int access, String methodName, String description, String [] exceptions) { 254 return getMethodAdapter(access, methodName, description, exceptions) != null; 255 } 256 257 public MethodAdapter customMethodAdapterFor(ManagerHelper managerHelper, int access, String methodName, 258 String origMethodName, String description, String signature, 259 String [] exceptions, InstrumentationLogger logger) { 260 MethodAdapter ma = getMethodAdapter(access, origMethodName, description, exceptions); 261 ma.initialize(managerHelper, access, className, methodName, origMethodName, description, signature, exceptions, 262 logger); 263 return ma; 264 } 265 266 private MethodAdapter getMethodAdapter(int access, String methodName, String description, String [] exceptions) { 267 DistributedMethodSpec dms = configuration.getDmiSpec(access, className, methodName, description, exceptions); 268 if (dms == null) return (MethodAdapter) methodAdapters.get(methodName + description); 269 return new DistributedMethodCallAdapter(dms.runOnAllNodes()); 270 } 271 272 public ChangeApplicatorSpec getChangeApplicatorSpec() { 273 return changeApplicatorSpec; 274 } 275 276 public String getLogicalExtendingClassName() { 277 return this.logicalExtendingClassName; 278 } 279 280 public void moveToLogical(TransparencyClassSpec superClassSpec) { 281 this.isLogical = true; 282 String superClassLogicalExtendingClassName = superClassSpec.getLogicalExtendingClassName(); 283 if (superClassLogicalExtendingClassName == null) { 284 superClassLogicalExtendingClassName = superClassSpec.getClassName(); 285 } 286 this.changeApplicatorClassName = superClassSpec.changeApplicatorClassName; 287 this.changeApplicatorSpec = new DSOChangeApplicatorSpec(superClassSpec.changeApplicatorClassName); 288 this.logicalExtendingClassName = superClassLogicalExtendingClassName; 289 } 290 291 public void addAlwaysLogSpec(String name) { 292 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.ALWAYS_LOG)); 293 } 294 295 public void addIfTrueLogSpec(String name) { 296 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.IF_TRUE_LOG)); 297 } 298 299 public void addSetIteratorWrapperSpec(String name) { 300 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.SET_ITERATOR_WRAPPER_LOG)); 301 } 302 303 public void addViewSetWrapperSpec(String name) { 304 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.SORTED_SET_VIEW_WRAPPER_LOG)); 305 } 306 307 public void addEntrySetWrapperSpec(String name) { 308 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.ENTRY_SET_WRAPPER_LOG)); 309 } 310 311 public void addKeySetWrapperSpec(String name) { 312 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.KEY_SET_WRAPPER_LOG)); 313 } 314 315 public void addValuesWrapperSpec(String name) { 316 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.VALUES_WRAPPER_LOG)); 317 } 318 319 public void addHashMapPutLogSpec(String name) { 320 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.HASHMAP_PUT_LOG)); 321 } 322 323 public void addHashtablePutLogSpec(String name) { 324 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.HASHTABLE_PUT_LOG)); 325 } 326 327 public void addTHashMapPutLogSpec(String name) { 328 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.THASHMAP_PUT_LOG)); 329 } 330 331 public void addTHashSetAddLogSpec(String name) { 332 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.THASHSET_ADD_LOG)); 333 } 334 335 public void addTHashRemoveAtLogSpec(String name) { 336 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.THASH_REMOVE_AT_LOG)); 337 } 338 339 public void addTHashSetRemoveAtLogSpec(String name) { 340 } 342 343 public void addHashtableClearLogSpec(String name) { 344 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.HASHTABLE_CLEAR_LOG)); 345 } 346 347 public void addHashtableRemoveLogSpec(String name) { 348 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.HASHTABLE_REMOVE_LOG)); 349 } 350 351 public void addHashMapRemoveLogSpec(String name) { 352 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.HASHMAP_REMOVE_LOG)); 353 } 354 355 public void addListRemoveLogSpec(String name) { 356 methodAdapters.put(name, new LogicalMethodAdapter(name, MethodSpec.LIST_REMOVE_LOG)); 357 } 358 359 public void addArrayCopyMethodCodeSpec(String name) { 360 TransparencyCodeSpec codeSpec = new TransparencyCodeSpec(); 361 codeSpec.setArraycopyInstrumentationReq(true); 362 codeSpec.setArrayOperatorInstrumentationReq(true); 363 codeSpecs.put(name, codeSpec); 364 } 365 366 public void disableWaitNotifyCodeSpec(String name) { 367 TransparencyCodeSpec codeSpec = TransparencyCodeSpec.getDefaultPhysicalCodeSpec(); 368 codeSpec.setWaitNotifyInstrumentationReq(false); 369 codeSpecs.put(name, codeSpec); 370 } 371 372 public void addDateMethodLogSpec(String name) { 373 methodAdapters.put(name, new DateMethodAdapter(name, MethodSpec.DATE_ADD_SET_TIME_WRAPPER_LOG)); 374 } 375 376 public void addDateMethodLogSpec(String name, int methodSpec) { 377 methodAdapters.put(name, new DateMethodAdapter(name, methodSpec)); 378 } 379 380 public void addMethodCodeSpec(String name, TransparencyCodeSpec codeSpec) { 381 codeSpecs.put(name, codeSpec); 382 } 383 384 public TransparencyClassSpec setHonorVolatile(boolean b) { 385 flags.put(HONOR_VOLATILE_KEY, new Boolean (b)); 386 return this; 387 } 388 389 public boolean isHonorVolatileSet() { 390 return flags.containsKey(HONOR_VOLATILE_KEY); 391 } 392 393 public boolean isHonorVolatile() { 394 Object flag = flags.get(HONOR_VOLATILE_KEY); 395 if (flag == null) return false; 396 return ((Boolean ) flag).booleanValue(); 397 } 398 399 public TransparencyClassSpec setHonorTransient(boolean b) { 400 flags.put(HONOR_TRANSIENT_KEY, new Boolean (b)); 401 return this; 402 } 403 404 public TransparencyClassSpec setCallConstructorOnLoad(boolean b) { 405 onLoad.setToCallConstructorOnLoad(b); 406 return this; 407 } 408 409 public TransparencyClassSpec setExecuteScriptOnLoad(String script) { 410 onLoad.setExecuteScriptOnLoad(script); 411 return this; 412 } 413 414 public TransparencyClassSpec setCallMethodOnLoad(String method) { 415 onLoad.setMethodCallOnLoad(method); 416 return this; 417 } 418 419 private boolean basicIsHonorJavaTransient() { 420 return ((Boolean ) flags.get(HONOR_TRANSIENT_KEY)).booleanValue(); 421 } 422 423 public boolean isCallConstructorSet() { 424 return onLoad.isCallConstructorOnLoadType(); 425 } 426 427 public boolean isHonorJavaTransient() { 428 return basicIsHonorJavaTransient(); 429 } 430 431 public boolean isCallConstructorOnLoad() { 432 return onLoad.isCallConstructorOnLoad(); 433 } 434 435 public boolean isHonorTransientSet() { 436 return flags.containsKey(HONOR_TRANSIENT_KEY); 437 } 438 439 public TransparencyCodeSpec getCodeSpec(String methodName, String description, boolean isAutolock) { 440 Object o = codeSpecs.get(methodName + description); 441 if (o == null) { return TransparencyCodeSpec.getDefaultCodeSpec(className, isLogical, isAutolock); } 442 return (TransparencyCodeSpec) o; 443 } 444 445 public boolean isExecuteScriptOnLoadSet() { 446 return onLoad.isExecuteScriptOnLoadType(); 447 } 448 449 public boolean isCallMethodOnLoadSet() { 450 return onLoad.isCallMethodOnLoadType(); 451 } 452 453 public String getOnLoadMethod() { 454 return onLoad.getMethod(); 455 } 456 457 public String getOnLoadExecuteScript() { 458 return onLoad.getExecuteScript(); 459 } 460 461 public boolean isUseNonDefaultConstructor() { 462 return this.useNonDefaultConstructor; 463 } 464 465 public void setUseNonDefaultConstructor(boolean useNonDefaultConstructor) { 466 this.useNonDefaultConstructor = useNonDefaultConstructor; 467 } 468 469 public void generateNonStaticTCFields(boolean b) { 470 this.generateNonStaticTCFields = b; 471 } 472 473 public boolean generateNonStaticTCFields() { 474 return this.generateNonStaticTCFields; 475 } 476 477 public void setInstrumentationAction(byte action) { 478 this.instrumentationAction = action; 479 } 480 481 public byte getInstrumentationAction() { 482 return this.instrumentationAction; 483 } 484 485 public boolean isHonorJDKSubVersionSpecific() { 486 return honorJDKSubVersionSpecific; 487 } 488 489 public void setHonorJDKSubVersionSpecific(boolean honorJDKSubVersionSpecific) { 490 this.honorJDKSubVersionSpecific = honorJDKSubVersionSpecific; 491 } 492 493 public boolean isPostCreateMethodSet() { 494 return postCreateMethod != null; 495 } 496 497 public String getPostCreateMethod() { 498 return postCreateMethod; 499 } 500 501 public void setPostCreateMethod(String postCreateMethod) { 502 this.postCreateMethod = postCreateMethod; 503 } 504 505 public void setCustomClassAdapter(ClassAdapterFactory customClassAdapter) { 506 this.customClassAdapter = customClassAdapter; 507 } 508 509 public ClassAdapterFactory getCustomClassAdapter() { 510 return customClassAdapter; 511 } 512 } 513 | Popular Tags |