1 5 package com.tc.object; 6 7 import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap; 8 9 import com.tc.aspectwerkz.reflect.impl.java.JavaClassInfo; 10 import com.tc.object.bytecode.TransparentAccess; 11 import com.tc.object.config.DSOClientConfigHelper; 12 import com.tc.util.Assert; 13 import com.tc.util.ClassUtils; 14 import com.tc.util.NonPortableReason; 15 16 import java.lang.reflect.Proxy ; 17 import java.util.ArrayList ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 22 public class PortabilityImpl implements Portability { 23 24 private static final Class OBJECT_CLASS = Object .class; 25 private static final List nonInstrumentedClass = new ArrayList (); 26 27 static { 28 nonInstrumentedClass.add("java.lang.Object"); 29 nonInstrumentedClass.add("java.lang.Number"); 30 nonInstrumentedClass.add("java.util.AbstractList"); 31 nonInstrumentedClass.add("java.util.AbstractCollection"); 32 nonInstrumentedClass.add("java.lang.Enum"); 33 nonInstrumentedClass.add("java.lang.reflect.AccessibleObject"); 34 nonInstrumentedClass.add("java.util.concurrent.locks.AbstractQueuedSynchronizer"); 35 nonInstrumentedClass.add("java.util.concurrent.locks.AbstractQueuedSynchronizer$Node"); 36 } 37 38 private final LiteralValues literalValues = new LiteralValues(); 39 private final Map portableCache = new ConcurrentHashMap(); 40 private final Map physicalCache = new ConcurrentHashMap(); 41 private final DSOClientConfigHelper config; 42 43 public PortabilityImpl(DSOClientConfigHelper config) { 44 this.config = config; 45 } 46 47 private List getHierarchy(Class start) { 48 List classes = new ArrayList (); 49 while (start != null && start != OBJECT_CLASS) { 50 classes.add(start); 51 start = start.getSuperclass(); 52 } 53 return classes; 54 } 55 56 public NonPortableReason getNonPortableReason(final Class topLevelClass) { 57 final List classes = getHierarchy(topLevelClass); 58 59 for (Iterator i = classes.iterator(); i.hasNext();) { 61 Class class2Inspect = (Class ) i.next(); 62 if (config.isNeverAdaptable(JavaClassInfo.getClassInfo(class2Inspect))) { 63 if (class2Inspect == topLevelClass) { 64 return new NonPortableReason(topLevelClass, NonPortableReason.CLASS_NOT_ADAPTABLE); 65 } else { 66 NonPortableReason reason = new NonPortableReason(topLevelClass, NonPortableReason.SUPER_CLASS_NOT_ADAPTABLE); 67 reason.addErroneousSuperClass(class2Inspect); 68 return reason; 69 } 70 } 71 } 72 73 for (Iterator i = classes.iterator(); i.hasNext();) { 75 Class class2Inspect = (Class ) i.next(); 76 77 if (class2Inspect == topLevelClass) { 78 continue; 79 } 80 81 if (!config.shouldBeAdapted(JavaClassInfo.getClassInfo(class2Inspect))) { 83 break; 84 } 85 86 if (config.isLogical(class2Inspect.getName())) { 87 NonPortableReason reason = new NonPortableReason(topLevelClass, 88 NonPortableReason.SUBCLASS_OF_LOGICALLY_MANAGED_CLASS); 89 reason.addErroneousSuperClass(class2Inspect); 90 return reason; 91 } 92 } 93 94 byte reasonCode = NonPortableReason.UNDEFINED; 96 List uninstrumentedSupers = new ArrayList (); 97 for (Iterator i = classes.iterator(); i.hasNext();) { 98 Class class2Inspect = (Class ) i.next(); 99 if (class2Inspect == topLevelClass) { 100 if (!isPortableClass(class2Inspect)) { 101 Assert.assertTrue(reasonCode == NonPortableReason.UNDEFINED); 102 if (class2Inspect.getClassLoader() == null) { 103 reasonCode = NonPortableReason.CLASS_NOT_IN_BOOT_JAR; 104 } else { 105 reasonCode = NonPortableReason.CLASS_NOT_INCLUDED_IN_CONFIG; 106 } 107 } 108 } else { 109 if (reasonCode == NonPortableReason.UNDEFINED) { 110 reasonCode = NonPortableReason.SUPER_CLASS_NOT_INSTRUMENTED; 111 } 112 if (!isPortableClass(class2Inspect)) { 113 uninstrumentedSupers.add(class2Inspect); 114 } 115 } 116 } 117 118 if (reasonCode == NonPortableReason.UNDEFINED) { 119 throw new AssertionError ("Could not determine non-portable reason for type hierarchy: " + classes); 121 } 122 123 NonPortableReason reason = new NonPortableReason(topLevelClass, reasonCode); 124 for (Iterator i = uninstrumentedSupers.iterator(); i.hasNext();) { 125 reason.addErroneousSuperClass((Class ) i.next()); 126 } 127 return reason; 128 } 129 130 134 public boolean isPortableClass(Class clazz) { 135 String clazzName = clazz.getName(); 136 Boolean isPortable = (Boolean ) portableCache.get(clazzName); 137 if (isPortable != null) { return isPortable.booleanValue(); } 138 139 boolean bool = literalValues.isLiteral(clazzName) || config.isLogical(clazzName) || clazz.isArray() 140 || Proxy.isProxyClass(clazz) || ClassUtils.isEnum(clazz) || isClassPhysicallyInstrumented(clazz) 141 || isInstrumentationNotNeeded(clazzName) || ClassUtils.isPortableReflectionClass(clazz) 142 || config.isPortableModuleClass(clazz); 143 portableCache.put(clazzName, Boolean.valueOf(bool)); 144 return bool; 145 } 146 147 public boolean isInstrumentationNotNeeded(String clazzName) { 148 return nonInstrumentedClass.contains(clazzName); 149 } 150 151 public boolean isClassPhysicallyInstrumented(Class clazz) { 152 156 String clazzName = clazz.getName(); 157 Boolean isPhysicalAdapted = (Boolean ) physicalCache.get(clazzName); 158 if (isPhysicalAdapted != null) { return isPhysicalAdapted.booleanValue(); } 159 160 boolean rv = false; 161 Class interfaces[] = clazz.getInterfaces(); 162 if (interfaces == null || interfaces.length == 0) return false; 163 for (int i = 0; i < interfaces.length; i++) { 164 if (interfaces[i] == TransparentAccess.class) { 165 rv = true; 166 break; 167 } 168 } 169 170 physicalCache.put(clazzName, Boolean.valueOf(rv)); 171 return rv; 172 } 173 174 public boolean isPortableInstance(Object obj) { 175 if (obj == null) return true; 176 return isPortableClass(obj.getClass()); 177 } 178 179 } 180 | Popular Tags |