FileDocCategorySizeDatePackage
TransformerFactory.javaAPI DocGlassfish v2 API19810Tue May 22 16:54:44 BST 2007oracle.toplink.essentials.internal.weaving

TransformerFactory

public class TransformerFactory extends Object
INTERNAL: This class creates a ClassFileTransformer that is used for dynamic bytecode weaving. It is called by {@link oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl#predeploy}

Note: The Session's Project is is scanned to ensure that weaving is supported and is modified to suit (set the {@link ObjectChangePolicy} for the Descriptor).

Fields Summary
public static final String
WEAVER_NULL_PROJECT
public static final String
WEAVER_DISABLE_BY_SYSPROP
public static final String
WEAVER_ADDING_EMBEDDABLE
public static final String
WEAVER_FOUND_FIELD_LOCK
public static final String
WEAVER_CLASS_NOT_IN_PROJECT
public static final String
WEAVER_PROCESSING_CLASS
protected Session
session
protected Collection
entityClasses
protected List
embeddableClasses
protected Map
classDetailsMap
protected ClassLoader
classLoader
Constructors Summary
public TransformerFactory(Session session, Collection entityClasses, ClassLoader classLoader)

        this.session = session;
        this.entityClasses = entityClasses;
        this.classLoader = classLoader;
        embeddableClasses = new ArrayList();
        classDetailsMap = new HashMap(); 
    
Methods Summary
public voidaddClassDetailsForMappedSuperClasses(java.lang.Class clz, oracle.toplink.essentials.descriptors.ClassDescriptor initialDescriptor, oracle.toplink.essentials.internal.weaving.ClassDetails classDetails, java.util.Map classDetailsMap, java.util.List unMappedAttributes)
INTERNAL: Look higher in the hierarchy for the mappings listed in the unMappedAttribute list. We assume that if a mapping exists, the attribute must either be mapped from the owninig class or from a superclass.

        // This class has inheritance to a mapped entity rather than a MappedSuperClass
        if (initialDescriptor.getInheritancePolicyOrNull() != null && initialDescriptor.getInheritancePolicyOrNull().getParentClass() != null){
            return;
        }
        if (unMappedAttributes.isEmpty()){
            return;
        }
        Class superClz = clz.getSuperclass();
        if (superClz == null || superClz == java.lang.Object.class){
            return;
        }
        
        boolean weaveValueHolders = canWeaveValueHolders(superClz, unMappedAttributes);
        List stillUnMappedMappings = null;
        ClassDetails superClassDetails = createClassDetails(superClz, weaveValueHolders);
        superClassDetails.setIsMappedSuperClass(true);
        if (!classDetailsMap.containsKey(superClassDetails.getClassName())){
            stillUnMappedMappings = storeAttributeMappings(superClz, superClassDetails, unMappedAttributes, weaveValueHolders);
            classDetailsMap.put(superClassDetails.getClassName() ,superClassDetails);
        }
       
        if (stillUnMappedMappings != null && !stillUnMappedMappings.isEmpty()){
            addClassDetailsForMappedSuperClasses(superClz, initialDescriptor, classDetails, classDetailsMap, stillUnMappedMappings);
        }
        
        
    
public voidbuildClassDetailsAndModifyProject()
Build a list ClassDetails instance that contains a ClassDetails for each class in our entities list.

        if (entityClasses != null && entityClasses.size() > 0) {
            
            // scan thru list building details of persistent classes

            // do @Entity's next
            for (Iterator i = entityClasses.iterator(); i.hasNext();) {
                Class clz = (Class)i.next();
                
                // check to ensure that class is present in project
                ClassDescriptor descriptor = findDescriptor(session.getProject(), clz.getName());
                if (descriptor == null) {

                    log(SessionLog.FINER, WEAVER_CLASS_NOT_IN_PROJECT,
                        new Object[]{clz.getName()});
                } else {
                    log(SessionLog.FINER, WEAVER_PROCESSING_CLASS,
                        new Object[]{clz.getName()});

                    boolean weaveValueHolders = canWeaveValueHolders(clz, descriptor.getMappings());
                    
                    if (weaveValueHolders) {
                        ClassDetails classDetails = createClassDetails(clz, weaveValueHolders);                       
                        List unMappedAttributes = storeAttributeMappings(clz, classDetails, descriptor.getMappings(), weaveValueHolders);
                        classDetailsMap.put(classDetails.getClassName() ,classDetails);

                        if (!unMappedAttributes.isEmpty()){
                            addClassDetailsForMappedSuperClasses(clz, descriptor, classDetails, classDetailsMap, unMappedAttributes);
                        }
                        if (classDetails.getLazyOneToOneMappings() != null){
                            Iterator iterator = classDetails.getLazyOneToOneMappings().iterator();
                            while(iterator.hasNext()){
                                OneToOneMapping mapping = (OneToOneMapping)iterator.next();
                                mapping.setGetMethodName("_toplink_get" + mapping.getAttributeName() + "_vh");
                                mapping.setSetMethodName("_toplink_set" + mapping.getAttributeName() + "_vh");
                            }
                        }
                    }
                }
            }
            // hookup superClassDetails
            for (Iterator i = classDetailsMap.values().iterator(); i.hasNext();) {
                ClassDetails classDetails = (ClassDetails)i.next();
                ClassDetails superClassDetails =
                    (ClassDetails)classDetailsMap.get(
                        classDetails.getSuperClassName());
                if (superClassDetails != null) {
                    classDetails.setSuperClassDetails(superClassDetails);
                }
            }
        // combine lists: add entities to end of embeddables,
        // then clear entities and re-populate from embeddables.
        embeddableClasses.addAll(entityClasses);
        entityClasses.clear();
        entityClasses.addAll(embeddableClasses);
        }
    
public javax.persistence.spi.ClassTransformerbuildTopLinkWeaver()

        return new TopLinkWeaver(session, classDetailsMap);
    
protected booleancanWeaveValueHolders(java.lang.Class clz, java.util.List mappings)


        // we intend to change to fetch=LAZY 1:1 attributes to ValueHolders
        boolean weaveValueHolders = true; 
        boolean foundOTOM = false;
        for (Iterator j = mappings.iterator(); j.hasNext();) {
            DatabaseMapping dm = (DatabaseMapping)j.next();
            String attributeName = dm.getAttributeName();
            if (dm.isOneToOneMapping()) {
                OneToOneMapping otom = (OneToOneMapping)dm;
                Class typeClz = getAttributeTypeFromClass(clz, attributeName, dm, true);
                if (otom.getIndirectionPolicy().usesIndirection() &&
                    typeClz != null  && !typeClz.isAssignableFrom(
                    ValueHolderInterface.class)) {
                    foundOTOM = true;
                    weaveValueHolders = true;
                 }
             }
        }

        // did we actually <b>find</b> any attributes to change?
        return weaveValueHolders & foundOTOM;
    
private oracle.toplink.essentials.internal.weaving.ClassDetailscreateClassDetails(java.lang.Class clz, boolean weaveValueHolders)

        // compose className in JVM 'slash' format
        // instead of regular Java 'dotted' format
        String className = clz.getName().replace('.",'/");
        String superClassName = clz.getSuperclass().getName().replace('.",'/");
        ClassDetails classDetails = new ClassDetails();
        classDetails.setClassName(className);
        classDetails.setSuperClassName(superClassName);
        classDetails.weaveValueHolders(weaveValueHolders);
        return classDetails;
    
public static javax.persistence.spi.ClassTransformercreateTransformerAndModifyProject(oracle.toplink.essentials.sessions.Session session, java.util.Collection entityClasses, java.lang.ClassLoader classLoader)

    
        
            
        if (session == null) {
            throw new IllegalArgumentException("Weaver session cannot be null");
        }
        if (session.getProject() == null) {
            ((oracle.toplink.essentials.internal.sessions.AbstractSession)session).log(
                SessionLog.SEVERE, SessionLog.WEAVER, WEAVER_NULL_PROJECT, null);
            throw new IllegalArgumentException("Weaver session's project cannot be null");
        }
        TransformerFactory tf = new TransformerFactory(session, entityClasses, classLoader);
        tf.buildClassDetailsAndModifyProject();
        return tf.buildTopLinkWeaver();
    
protected oracle.toplink.essentials.descriptors.ClassDescriptorfindDescriptor(oracle.toplink.essentials.sessions.Project project, java.lang.String className)
Find a descriptor by name in the given project used to avoid referring to descriptors by class. This avoids having to construct a project by class facilitating weaving

        Iterator iterator = project.getOrderedDescriptors().iterator();
        while (iterator.hasNext()){
            ClassDescriptor descriptor = (ClassDescriptor)iterator.next();
            if (descriptor.getJavaClassName().equals(className)){
                return descriptor;
            }
        }
        return null;
    
private java.lang.ClassgetAttributeTypeFromClass(java.lang.Class clz, java.lang.String attributeName, oracle.toplink.essentials.mappings.DatabaseMapping mapping, boolean checkSuperclass)
Use the database mapping for an attribute to find it's type. The type returned will either be the field type of the field in the object or the type returned by the getter method.

       
        String getterMethod = mapping.getGetMethodName();
        if (mapping != null && getterMethod != null){
            try{
                Method method = null;
                if (checkSuperclass){
                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                        try {
                            method = (Method)AccessController.doPrivileged(new PrivilegedGetMethod(clz, getterMethod, null, false));
                        } catch (PrivilegedActionException exception) {
                        }
                    } else {
                        method = PrivilegedAccessHelper.getMethod(clz, getterMethod, null, false);
                    }
                } else {
                    method = null;
                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                        try {
                            method = (Method)AccessController.doPrivileged(new PrivilegedGetDeclaredMethod(clz, getterMethod, null));
                        } catch (PrivilegedActionException exception) {
                        }
                    } else {
                        method = PrivilegedAccessHelper.getDeclaredMethod(clz, getterMethod, null);
                    }
                }
                if (method != null){
                    return method.getReturnType();
                }
            }  catch (Exception e) {  }
        } else {
            try {
                Class typeClz = null;
                if (checkSuperclass){
                    Field field = null;
                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                        try {
                            field = (Field)AccessController.doPrivileged(new PrivilegedGetField(clz, attributeName, false));
                        } catch (PrivilegedActionException exception) {
                        }
                    } else {
                        field = PrivilegedAccessHelper.getField(clz, attributeName, false);
                    }
                    typeClz = field.getType();                     
                } else {
                    Field field = null;
                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                        try {
                            field = (Field)AccessController.doPrivileged(new PrivilegedGetDeclaredField(clz, attributeName, false));
                        } catch (PrivilegedActionException exception) {
                        }
                    } else {
                        field = PrivilegedAccessHelper.getDeclaredField(clz, attributeName, false);
                    }
                    typeClz = field.getType();  
                }
                if (typeClz != null){
                    return typeClz;
                }
            }  catch (Exception e) {  }
        }

        return null;
    
protected static booleanhasField(java.lang.Class clz, java.lang.String fieldName)

        
        if ("java.lang.Object".equals(clz.getName())) {
            return false;
        }
        else {
            boolean hasField = false;
            // check to see if the mapping's attribute exists as a field on the
            // class; failing that, recurse up super-class(es).
            try {
                Field f = null;
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        f = (Field)AccessController.doPrivileged(new PrivilegedGetDeclaredField(clz, fieldName, false));
                    } catch (PrivilegedActionException exception) {
                    }
                } else {
                    f = PrivilegedAccessHelper.getDeclaredField(clz, fieldName, false);
                }
                hasField = true;
            }
            catch (Exception e) { /* ignore */ }
            return hasField ? hasField : hasField(clz.getSuperclass(), fieldName);
        }
    
protected voidlog(int level, java.lang.String msg, java.lang.Object[] params)

        ((oracle.toplink.essentials.internal.sessions.AbstractSession)session).log(level,
            SessionLog.WEAVER, msg, params);
    
protected java.util.ListstoreAttributeMappings(java.lang.Class clz, oracle.toplink.essentials.internal.weaving.ClassDetails classDetails, java.util.List mappings, boolean weaveValueHolders)
INTERNAL: Store a set of attribute mappings on the given ClassDetails taht correspont to the given class. Return the list of mappings that is not specifically found on the given class. These attributes will be found on MappedSuperclasses

      
        List unMappedAttributes = new Vector();
        Map attributesMap = new HashMap();
        Map settersMap = new HashMap();
        Map gettersMap = new HashMap();
        List lazyMappings = new Vector();
        for (Iterator j = mappings.iterator(); j.hasNext();) {
            DatabaseMapping dm = (DatabaseMapping)j.next();
            String attribute = dm.getAttributeName();
            AttributeDetails attributeDetails = new AttributeDetails(attribute);
            Class typeClz = getAttributeTypeFromClass(clz, attribute, dm, false);
            if (typeClz == null){
                attributeDetails.setAttributeOnSuperClass(true);
                if (dm.isOneToOneMapping()){
                    unMappedAttributes.add(dm);
                }
            }
            if (dm.isCollectionMapping()) {
                attributeDetails.setCollectionMapping(true);
            } else if (dm.isOneToOneMapping()) {
                OneToOneMapping otom = (OneToOneMapping)dm;
                attributeDetails.referenceClass = otom.getReferenceClassName();
                attributeDetails.weaveVH(weaveValueHolders, otom);
                if (otom.getGetMethodName() != null){
                    gettersMap.put(otom.getGetMethodName(), attributeDetails);
                    if (otom.getSetMethodName() != null){
                        settersMap.put(otom.getSetMethodName(), attributeDetails);
                    }
                } else {
                    attributeDetails.setIsMappedWithAttributeAccess(true);
                }
                if (typeClz == null){
                    typeClz = getAttributeTypeFromClass(clz, attribute, dm, true);
                }
                if (weaveValueHolders && otom.getIndirectionPolicy().usesIndirection() &&
                    typeClz != null  && !typeClz.isAssignableFrom(ValueHolderInterface.class)) {
                    lazyMappings.add(otom);
                }

            }
            attributesMap.put(attribute, attributeDetails);    
         }
        classDetails.setAttributesMap(attributesMap);
        classDetails.setGetterMethodToAttributeDetails(gettersMap);
        classDetails.setSetterMethodToAttributeDetails(settersMap);
        classDetails.setLazyOneToOneMappings(lazyMappings);
        return unMappedAttributes;