1 21 package oracle.toplink.essentials.internal.weaving; 23 24 import java.lang.reflect.*; 26 import java.security.AccessController ; 27 import java.security.PrivilegedActionException ; 28 import java.util.*; 29 30 import oracle.toplink.libraries.asm.Type; 32 33 import oracle.toplink.essentials.indirection.ValueHolderInterface; 35 import oracle.toplink.essentials.logging.SessionLog; 36 import oracle.toplink.essentials.mappings.*; 37 import oracle.toplink.essentials.descriptors.ClassDescriptor; 38 import oracle.toplink.essentials.sessions.Session; 39 import oracle.toplink.essentials.sessions.Project; 40 import oracle.toplink.essentials.internal.security.PrivilegedAccessHelper; 41 import oracle.toplink.essentials.internal.security.PrivilegedGetDeclaredField; 42 import oracle.toplink.essentials.internal.security.PrivilegedGetDeclaredMethod; 43 import oracle.toplink.essentials.internal.security.PrivilegedGetMethod; 44 import oracle.toplink.essentials.internal.security.PrivilegedGetField; 45 46 import javax.persistence.spi.ClassTransformer; 47 48 59 public class TransformerFactory { 60 61 public static final String WEAVER_NULL_PROJECT = 62 "weaver_null_project"; 63 public static final String WEAVER_DISABLE_BY_SYSPROP = 64 "weaver_disable_by_system_property"; 65 public static final String WEAVER_ADDING_EMBEDDABLE = 66 "weaver_adding_embeddable_class"; 67 public static final String WEAVER_FOUND_FIELD_LOCK = 68 "weaver_found_field_lock"; 69 public static final String WEAVER_CLASS_NOT_IN_PROJECT = 70 "weaver_class_not_in_project"; 71 public static final String WEAVER_PROCESSING_CLASS = 72 "weaver_processing_class"; 73 74 public static ClassTransformer createTransformerAndModifyProject(Session session, 75 Collection entityClasses, ClassLoader classLoader) { 76 if (session == null) { 77 throw new IllegalArgumentException ("Weaver session cannot be null"); 78 } 79 if (session.getProject() == null) { 80 ((oracle.toplink.essentials.internal.sessions.AbstractSession)session).log( 81 SessionLog.SEVERE, SessionLog.WEAVER, WEAVER_NULL_PROJECT, null); 82 throw new IllegalArgumentException ("Weaver session's project cannot be null"); 83 } 84 TransformerFactory tf = new TransformerFactory(session, entityClasses, classLoader); 85 tf.buildClassDetailsAndModifyProject(); 86 return tf.buildTopLinkWeaver(); 87 } 88 89 protected Session session; 90 protected Collection entityClasses; 91 protected List embeddableClasses; 92 protected Map classDetailsMap; 93 protected ClassLoader classLoader; 94 95 public TransformerFactory(Session session, Collection entityClasses, ClassLoader classLoader) { 96 this.session = session; 97 this.entityClasses = entityClasses; 98 this.classLoader = classLoader; 99 embeddableClasses = new ArrayList(); 100 classDetailsMap = new HashMap(); 101 } 102 103 110 public void addClassDetailsForMappedSuperClasses(Class clz, ClassDescriptor initialDescriptor, ClassDetails classDetails, Map classDetailsMap, List unMappedAttributes){ 111 if (initialDescriptor.getInheritancePolicyOrNull() != null && initialDescriptor.getInheritancePolicyOrNull().getParentClass() != null){ 113 return; 114 } 115 if (unMappedAttributes.isEmpty()){ 116 return; 117 } 118 Class superClz = clz.getSuperclass(); 119 if (superClz == null || superClz == java.lang.Object .class){ 120 return; 121 } 122 123 boolean weaveValueHolders = canWeaveValueHolders(superClz, unMappedAttributes); 124 List stillUnMappedMappings = null; 125 ClassDetails superClassDetails = createClassDetails(superClz, weaveValueHolders); 126 superClassDetails.setIsMappedSuperClass(true); 127 if (!classDetailsMap.containsKey(superClassDetails.getClassName())){ 128 stillUnMappedMappings = storeAttributeMappings(superClz, superClassDetails, unMappedAttributes, weaveValueHolders); 129 classDetailsMap.put(superClassDetails.getClassName() ,superClassDetails); 130 } 131 132 if (stillUnMappedMappings != null && !stillUnMappedMappings.isEmpty()){ 133 addClassDetailsForMappedSuperClasses(superClz, initialDescriptor, classDetails, classDetailsMap, stillUnMappedMappings); 134 } 135 136 137 } 138 139 public ClassTransformer buildTopLinkWeaver() { 140 return new TopLinkWeaver(session, classDetailsMap); 141 } 142 143 147 public void buildClassDetailsAndModifyProject() { 148 if (entityClasses != null && entityClasses.size() > 0) { 149 150 152 for (Iterator i = entityClasses.iterator(); i.hasNext();) { 154 Class clz = (Class )i.next(); 155 156 ClassDescriptor descriptor = findDescriptor(session.getProject(), clz.getName()); 158 if (descriptor == null) { 159 160 log(SessionLog.FINER, WEAVER_CLASS_NOT_IN_PROJECT, 161 new Object []{clz.getName()}); 162 } else { 163 log(SessionLog.FINER, WEAVER_PROCESSING_CLASS, 164 new Object []{clz.getName()}); 165 166 boolean weaveValueHolders = canWeaveValueHolders(clz, descriptor.getMappings()); 167 168 if (weaveValueHolders) { 169 ClassDetails classDetails = createClassDetails(clz, weaveValueHolders); 170 List unMappedAttributes = storeAttributeMappings(clz, classDetails, descriptor.getMappings(), weaveValueHolders); 171 classDetailsMap.put(classDetails.getClassName() ,classDetails); 172 173 if (!unMappedAttributes.isEmpty()){ 174 addClassDetailsForMappedSuperClasses(clz, descriptor, classDetails, classDetailsMap, unMappedAttributes); 175 } 176 if (classDetails.getLazyOneToOneMappings() != null){ 177 Iterator iterator = classDetails.getLazyOneToOneMappings().iterator(); 178 while(iterator.hasNext()){ 179 OneToOneMapping mapping = (OneToOneMapping)iterator.next(); 180 mapping.setGetMethodName("_toplink_get" + mapping.getAttributeName() + "_vh"); 181 mapping.setSetMethodName("_toplink_set" + mapping.getAttributeName() + "_vh"); 182 } 183 } 184 } 185 } 186 } 187 for (Iterator i = classDetailsMap.values().iterator(); i.hasNext();) { 189 ClassDetails classDetails = (ClassDetails)i.next(); 190 ClassDetails superClassDetails = 191 (ClassDetails)classDetailsMap.get( 192 classDetails.getSuperClassName()); 193 if (superClassDetails != null) { 194 classDetails.setSuperClassDetails(superClassDetails); 195 } 196 } 197 embeddableClasses.addAll(entityClasses); 200 entityClasses.clear(); 201 entityClasses.addAll(embeddableClasses); 202 } 203 } 204 205 protected boolean canWeaveValueHolders(Class clz, List mappings) { 206 207 boolean weaveValueHolders = true; 209 boolean foundOTOM = false; 210 for (Iterator j = mappings.iterator(); j.hasNext();) { 211 DatabaseMapping dm = (DatabaseMapping)j.next(); 212 String attributeName = dm.getAttributeName(); 213 if (dm.isOneToOneMapping()) { 214 OneToOneMapping otom = (OneToOneMapping)dm; 215 Class typeClz = getAttributeTypeFromClass(clz, attributeName, dm, true); 216 if (otom.getIndirectionPolicy().usesIndirection() && 217 typeClz != null && !typeClz.isAssignableFrom( 218 ValueHolderInterface.class)) { 219 foundOTOM = true; 220 weaveValueHolders = true; 221 } 222 } 223 } 224 225 return weaveValueHolders & foundOTOM; 227 } 228 229 private ClassDetails createClassDetails(Class clz, boolean weaveValueHolders){ 230 String className = clz.getName().replace('.','/'); 233 String superClassName = clz.getSuperclass().getName().replace('.','/'); 234 ClassDetails classDetails = new ClassDetails(); 235 classDetails.setClassName(className); 236 classDetails.setSuperClassName(superClassName); 237 classDetails.weaveValueHolders(weaveValueHolders); 238 return classDetails; 239 } 240 241 247 protected List storeAttributeMappings(Class clz, ClassDetails classDetails, List mappings, boolean weaveValueHolders) { 248 List unMappedAttributes = new Vector(); 249 Map attributesMap = new HashMap(); 250 Map settersMap = new HashMap(); 251 Map gettersMap = new HashMap(); 252 List lazyMappings = new Vector(); 253 for (Iterator j = mappings.iterator(); j.hasNext();) { 254 DatabaseMapping dm = (DatabaseMapping)j.next(); 255 String attribute = dm.getAttributeName(); 256 AttributeDetails attributeDetails = new AttributeDetails(attribute); 257 Class typeClz = getAttributeTypeFromClass(clz, attribute, dm, false); 258 if (typeClz == null){ 259 attributeDetails.setAttributeOnSuperClass(true); 260 if (dm.isOneToOneMapping()){ 261 unMappedAttributes.add(dm); 262 } 263 } 264 if (dm.isCollectionMapping()) { 265 attributeDetails.setCollectionMapping(true); 266 } else if (dm.isOneToOneMapping()) { 267 OneToOneMapping otom = (OneToOneMapping)dm; 268 attributeDetails.referenceClass = otom.getReferenceClassName(); 269 attributeDetails.weaveVH(weaveValueHolders, otom); 270 if (otom.getGetMethodName() != null){ 271 gettersMap.put(otom.getGetMethodName(), attributeDetails); 272 if (otom.getSetMethodName() != null){ 273 settersMap.put(otom.getSetMethodName(), attributeDetails); 274 } 275 } else { 276 attributeDetails.setIsMappedWithAttributeAccess(true); 277 } 278 if (typeClz == null){ 279 typeClz = getAttributeTypeFromClass(clz, attribute, dm, true); 280 } 281 if (weaveValueHolders && otom.getIndirectionPolicy().usesIndirection() && 282 typeClz != null && !typeClz.isAssignableFrom(ValueHolderInterface.class)) { 283 lazyMappings.add(otom); 284 } 285 286 } 287 attributesMap.put(attribute, attributeDetails); 288 } 289 classDetails.setAttributesMap(attributesMap); 290 classDetails.setGetterMethodToAttributeDetails(gettersMap); 291 classDetails.setSetterMethodToAttributeDetails(settersMap); 292 classDetails.setLazyOneToOneMappings(lazyMappings); 293 return unMappedAttributes; 294 } 295 296 301 protected ClassDescriptor findDescriptor(Project project, String className){ 302 Iterator iterator = project.getOrderedDescriptors().iterator(); 303 while (iterator.hasNext()){ 304 ClassDescriptor descriptor = (ClassDescriptor)iterator.next(); 305 if (descriptor.getJavaClassName().equals(className)){ 306 return descriptor; 307 } 308 } 309 return null; 310 } 311 312 316 private Class getAttributeTypeFromClass(Class clz, String attributeName, DatabaseMapping mapping, boolean checkSuperclass){ 317 String getterMethod = mapping.getGetMethodName(); 318 if (mapping != null && getterMethod != null){ 319 try{ 320 Method method = null; 321 if (checkSuperclass){ 322 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ 323 try { 324 method = (Method)AccessController.doPrivileged(new PrivilegedGetMethod(clz, getterMethod, null, false)); 325 } catch (PrivilegedActionException exception) { 326 } 327 } else { 328 method = PrivilegedAccessHelper.getMethod(clz, getterMethod, null, false); 329 } 330 } else { 331 method = null; 332 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ 333 try { 334 method = (Method)AccessController.doPrivileged(new PrivilegedGetDeclaredMethod(clz, getterMethod, null)); 335 } catch (PrivilegedActionException exception) { 336 } 337 } else { 338 method = PrivilegedAccessHelper.getDeclaredMethod(clz, getterMethod, null); 339 } 340 } 341 if (method != null){ 342 return method.getReturnType(); 343 } 344 } catch (Exception e) { } 345 } else { 346 try { 347 Class typeClz = null; 348 if (checkSuperclass){ 349 Field field = null; 350 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ 351 try { 352 field = (Field)AccessController.doPrivileged(new PrivilegedGetField(clz, attributeName, false)); 353 } catch (PrivilegedActionException exception) { 354 } 355 } else { 356 field = PrivilegedAccessHelper.getField(clz, attributeName, false); 357 } 358 typeClz = field.getType(); 359 } else { 360 Field field = null; 361 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ 362 try { 363 field = (Field)AccessController.doPrivileged(new PrivilegedGetDeclaredField(clz, attributeName, false)); 364 } catch (PrivilegedActionException exception) { 365 } 366 } else { 367 field = PrivilegedAccessHelper.getDeclaredField(clz, attributeName, false); 368 } 369 typeClz = field.getType(); 370 } 371 if (typeClz != null){ 372 return typeClz; 373 } 374 } catch (Exception e) { } 375 } 376 377 return null; 378 } 379 380 protected static boolean hasField(Class clz, String fieldName) { 381 382 if ("java.lang.Object".equals(clz.getName())) { 383 return false; 384 } 385 else { 386 boolean hasField = false; 387 try { 390 Field f = null; 391 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ 392 try { 393 f = (Field)AccessController.doPrivileged(new PrivilegedGetDeclaredField(clz, fieldName, false)); 394 } catch (PrivilegedActionException exception) { 395 } 396 } else { 397 f = PrivilegedAccessHelper.getDeclaredField(clz, fieldName, false); 398 } 399 hasField = true; 400 } 401 catch (Exception e) { } 402 return hasField ? hasField : hasField(clz.getSuperclass(), fieldName); 403 } 404 } 405 406 protected void log(int level, String msg, Object [] params) { 407 ((oracle.toplink.essentials.internal.sessions.AbstractSession)session).log(level, 408 SessionLog.WEAVER, msg, params); 409 } 410 } 411 | Popular Tags |