alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (PersistenceDescriptor.java)

This example Glassfish source code file (PersistenceDescriptor.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

class, class, cmrfieldinfo, deploymentexception, fielddescriptor, log, logging, method, method, methoddescriptor, persistentfieldinfo, persistentfieldinfo, querydescriptor, reflection, set, string, string, util

The Glassfish PersistenceDescriptor.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.enterprise.deployment;

import com.sun.enterprise.deployment.util.DOLUtils;
import com.sun.enterprise.deployment.util.TypeUtil;
import com.sun.enterprise.util.LocalStringManagerImpl;
import org.glassfish.deployment.common.DeploymentException;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.logging.Level;

/** 
 * This class contains information about the persistent state
 * (abstract persistence schema)
 * for EJB2.0 CMP EntityBeans and Join Objects.
 *
 * @author Sanjeev Krishnan
 */

public final class PersistenceDescriptor extends Descriptor {
    
    private Set cmpFields = new HashSet();

    // there can be 0 or more pkey fields 
    // This set contains FieldDescriptors for fields from bean or pkey class 
    private Set pkeyFields = new HashSet(); 

    // true if primkey-field is set or for container-generated pk field
    private boolean pkeyIsOneField = false;

    // false for beans with no primkey-field and pk class = Object
    private boolean pkeyFieldSpecified = true; 

    private String primaryKeyClassName;
    private boolean pkeyStuffInitialized = false;

    // true for beans whose primary fields are all primitive fields
    private boolean pkeyFieldsAllPrimitive = false;
	
    private static LocalStringManagerImpl localStrings =
	    new LocalStringManagerImpl(PersistenceDescriptor.class);

    private EjbCMPEntityDescriptor parentDesc; //the bean whose persistence I describe

    private transient Class persistentClass; // the bean class
    private transient Class stateClass; // the class which holds persistent fields
    private transient Class primaryKeyClass;

    private PersistentFieldInfo[] persFieldInfo;
    private PersistentFieldInfo[] persNoPkeyFieldInfo;
    private PersistentFieldInfo[] pkeyFieldInfo;
    private boolean fieldInfoInitialized=false;
    private PersistentFieldInfo[] fkeyFields;

    private CMRFieldInfo[] cmrFieldInfo;

    private transient Field[] pkeyClassPkeyFields; // fields in primary key class

    private Hashtable queries = new Hashtable();
    private HashSet allQueriedMethods;

    public PersistenceDescriptor() {
    }
    
    /** 
     * The copy constructor.
     */
    public PersistenceDescriptor(PersistenceDescriptor pers) {
	super(pers);

	this.getCMPFields().addAll(pers.getCMPFields());
	//this.primaryKeyFieldDesc = pers.primaryKeyFieldDesc;
    }

    public String getCMRFieldReturnType(String field) {
        String returnType = "java.util.Collection";
        try {
            if( !field.trim().equals("") ) {
                Class persClass = getPersistentClass();
                String methodName = "get" + field.substring(0,1).toUpperCase() 
                    + field.substring(1);
                Method method = TypeUtil.getMethod
                    (persClass, persClass.getClassLoader(), methodName,
                     new String[] {});
                returnType = method.getReturnType().getName();
            }
        } catch(Throwable t) {
            if(DOLUtils.getDefaultLogger().isLoggable(Level.FINE)) {            
                DOLUtils.getDefaultLogger().log(Level.FINE, t.toString(), t);
            }
        }
        
        return returnType;
    }

    /**     
     * Called from EjbCMPEntityDescriptor
     * when some classes in this object are updated.
     */         
    public boolean classesChanged() {

        // XXX Remove any fields marked as persistent that no longer exist
	// in bean class as getter/setter.
        persistentClass = null;
        stateClass = null;
        Class persClass = getPersistentClass();

        Vector fieldDescriptors = parentDesc.getFieldDescriptors();

        // Remove obsolete cmp fields
        if( this.cmpFields != null ) {
            for(Iterator iter = cmpFields.iterator(); iter.hasNext();) {
                FieldDescriptor next = (FieldDescriptor) iter.next();
                if( !fieldDescriptors.contains(next) ) {
                    iter.remove();
                }
            }
        }

        // Remove obsolete pkey fields
        if( this.pkeyFields != null ) {
            for(Iterator iter = pkeyFields.iterator(); iter.hasNext();) {
                FieldDescriptor next = (FieldDescriptor) iter.next();
                if( !fieldDescriptors.contains(next) ) {
                    iter.remove();
                }
            }
        }

        FieldDescriptor primKeyFieldDesc = parentDesc.getPrimaryKeyFieldDesc();
        if( (primKeyFieldDesc != null) && 
            !fieldDescriptors.contains(primKeyFieldDesc) ) {
            parentDesc.setPrimaryKeyFieldDesc(null);
        }


        // CMP 2.x
        // Remove queries for methods no longer in allQueriedMethods

        // First clone old set of queries
        Hashtable queriesClone = (Hashtable) queries.clone();
        
        queries = new Hashtable();
        initializeAllQueriedMethods();

        Iterator it = queriesClone.keySet().iterator();
        while ( it.hasNext() ) {
            Method oldMethod = (Method)it.next();
            Method newMethod = findEquivalentMethod(allQueriedMethods, 
                                                    oldMethod);
            if( newMethod != null ) {
                QueryDescriptor oldQuery = (QueryDescriptor)
                    queriesClone.get(oldMethod);
                QueryDescriptor newQuery = 
                    new QueryDescriptor(oldQuery, newMethod);
                // Only add to list of methods having queries if
                // it's still in the class.
                queries.put(newMethod, newQuery);
            } 
        }

        // Force the persistence descriptor to regenerate its
        // derived info.
        invalidate();

        return false;
    }

    /**
     * Search for a matching method in a list of methods
     * that might have been loaded with a different classloader.
     * Because of this possibility, we can't use 
     * java.lang.reflect.Method.equals().  
     * @return matched method or NULL
     */
    private Method findEquivalentMethod(Collection methods,
                                        Method methodToMatch) {
        Method matchedMethod = null;
        for(Iterator iter = methods.iterator(); iter.hasNext();) {
            Object o = iter.next();
            Method next;
            if (o instanceof Method) {
                next = (Method) o;
            } else {
                next = ((MethodDescriptor) o).getMethod(parentDesc);
                if (next==null) {
                    return null;
                }
            }
            // Compare methods, ignoring declaring class.
            if( methodsEqual(next, methodToMatch, false) ) {
                matchedMethod = next;
                break;
            }
        }
        return matchedMethod;
    }

    /**
     * Checks whether two methods that might have been loaded by
     * different class loaders are equal.  
     * @param compareDeclaringClass if true, declaring class will
     * be considered as part of equality test.  
     */
    private boolean methodsEqual(Method m1, Method m2, 
                                 boolean compareDeclaringClass) {
        boolean equal = false;

        do {

            String m1Name = m1.getName();
            String m2Name = m2.getName();

            if( !m1Name.equals(m2Name) ) { break; }

            String m1DeclaringClass = m1.getDeclaringClass().getName();
            String m2DeclaringClass = m2.getDeclaringClass().getName();

            if( compareDeclaringClass ) {
                if( !m1DeclaringClass.equals(m2DeclaringClass) ) { break; }
            }

            Class[] m1ParamTypes = m1.getParameterTypes();
            Class[] m2ParamTypes = m2.getParameterTypes();
            
            if( m1ParamTypes.length != m2ParamTypes.length ) { break; }

            equal = true;
            for(int pIndex = 0; pIndex < m1ParamTypes.length; pIndex++) {
                String m1ParamClass = m1ParamTypes[pIndex].getName();
                String m2ParamClass = m2ParamTypes[pIndex].getName();
                if( !m1ParamClass.equals(m2ParamClass) ) {
                    equal = false;
                    break;
                }
            } 

        } while(false);

        return equal;
    }

    /**
     * Checks whether two methods that might have been loaded by
     * different class loaders are equal.  
     * @param compareDeclaringClass if true, declaring class will
     * be considered as part of equality test.  
     */
    private boolean methodsEqual(MethodDescriptor m1, Method m2, 
                                 boolean compareDeclaringClass) {
                                     
        Method m = m1.getMethod(parentDesc);
        return methodsEqual(m, m2, compareDeclaringClass);
        
    }    
    
    public void setParentDescriptor(Descriptor parentDesc)
    {
	this.parentDesc = (EjbCMPEntityDescriptor)parentDesc;
    }

    public Descriptor getParentDescriptor()
    {
	return parentDesc;
    }
   
    public EjbBundleDescriptor getEjbBundleDescriptor() 
    {
	 return parentDesc.getEjbBundleDescriptor();
    }

    /**
     * Get all CMR fields of this bean.  All relationships
     * are stored in EjbBundleDescriptor to avoid the complexity of
     * keeping the two sets consistent.  NOTE : To add or remove
     * a relationship use EjbBundleDescriptor.
     */
    public Set getRelationships()
    {
        Set allRelationships = getEjbBundleDescriptor().getRelationships();
        Set myRelationships  = new HashSet();
        for(Iterator iter = allRelationships.iterator(); iter.hasNext();) {
            RelationshipDescriptor next = (RelationshipDescriptor) iter.next();
            if( next.hasParticipant(parentDesc) ) {
                myRelationships.add(next);
            }
        }
        return myRelationships;
    }

    /**
     * Return array of CMRFieldInfo objects for all CMR fields.
     */
    public CMRFieldInfo[] getCMRFieldInfo() 
    {
	if ( cmrFieldInfo == null ) {
	    try {
		initCMRFieldStuff();
	    } catch ( Exception ex ) {
                DOLUtils.getDefaultLogger().log(Level.SEVERE, "enterprise.deployment.backend.invalidDescriptorMappingFailure",
                    new Object[] {ex.toString()});
		throw new DeploymentException(ex);
	    }
	}
	return cmrFieldInfo;
    }

    /** 
     * Return the CMRFieldInfo object for the given CMR field
     */
    public CMRFieldInfo getCMRFieldInfoByName(String fieldName)
    {
	CMRFieldInfo[] cmrf = this.getCMRFieldInfo();
	for ( int i=0; i<cmrf.length; i++ ) {
	    if ( cmrf[i].name.equals(fieldName) )
		return cmrf[i];
	}
	throw new DeploymentException("CMRFieldInfo not found for field "+fieldName);
    }

    /**
     * Ensures that persistence descriptor will regenerate its
     * derived information after changes have been made to 
     * persistent characteristics.
     */
    public void invalidate() {
        cmrFieldInfo = null;
	persFieldInfo = null;
        fieldInfoInitialized = false;
        pkeyStuffInitialized = false;
    }

    private void initCMRFieldStuff()
	throws Exception
    {
	if ( !fieldInfoInitialized )
	    initializeFieldInfo();

        Set relationships = getRelationships();
	Iterator it = relationships.iterator();
        // set to the biggest possible size when all relationships
        // are self-referencing
	CMRFieldInfo[] cmrFieldInfo2 = 
            new CMRFieldInfo[relationships.size() * 2];
	int count = 0;
	while ( it.hasNext() ) { 
	    RelationshipDescriptor rd = (RelationshipDescriptor)it.next();
	    RelationRoleDescriptor source = rd.getSource();
	    RelationRoleDescriptor sink = rd.getSink();
	    RelationRoleDescriptor myroles[];
            // if this is a self-referencing relationship, initialize 
            // both source and sink cmr fields
	    if ( source.getPersistenceDescriptor() ==  
                sink.getPersistenceDescriptor() ) {
                myroles = new RelationRoleDescriptor[2];
                myroles[0] = source;
                myroles[1] = sink;
            } else {
                myroles = new RelationRoleDescriptor[1];
                if ( source.getPersistenceDescriptor() == this ) {
                    myroles[0] = source;
                } else { 
                    myroles[0] = sink;
                }
            }
            
            // for all relation role elements in myroles, initialize
            // their cmr fields and put them in cmrFieldInfo2
            for (int ii = 0; ii < myroles.length; ii++) {
	        CMRFieldInfo finfo = new CMRFieldInfo();
	        cmrFieldInfo2[count++] = finfo;

	        PersistenceDescriptor partnerPers = 
		    myroles[ii].getPartner().getPersistenceDescriptor();

	        // Check if partner has a local interface
	        EjbCMPEntityDescriptor partner = 
                    myroles[ii].getPartner().getOwner();
                if ( !partner.isLocalInterfacesSupported() &&
		    myroles[ii].getCMRField() != null ) {
      		    throw new RuntimeException(
                        "No local interface for target bean of CMR field");
	        }

	        String type; 
	        if ( myroles[ii].getPartner().getIsMany() == false ) {
	      	    // 1-1 and many-1
                    if ( partner.isLocalInterfacesSupported() )
		        type = partner.getLocalClassName();
	       	    else 
                        // a unidirectional relation, partner is 
                        // remote-only bean
		        type = partner.getPrimaryKeyClassName();
	        }
	        else {
	      	    // 1-many and many-many
		    type = myroles[ii].getCMRFieldType();
      		    if ( type == null ) { 
		        // A unidirectional relationship from partner 
                        // to this obj
		        type = "java.util.Collection";
    		    }
	        }
	        finfo.type = getClass(type);

	        finfo.name = myroles[ii].getCMRField();
	        if ( finfo.name == null ) {
	       	    // A unidirectional relationship from partner to this obj.
	      	    // We need to maintain a pointer to partner anyway. 
       		    finfo.name = myroles[ii].composeReverseCmrFieldName();
	        }
	        finfo.role = myroles[ii];
	        myroles[ii].setCMRFieldInfo(finfo);

	        if ( rd.isOneOne() && fkeyFields != null ) {
	    	    // set foreign key fields corresponding to this CMR field
		    PersistentFieldInfo[] cmrFkeyFields;
      		    PersistentFieldInfo[] partnerPkeyFields =
					    partnerPers.getPkeyFieldInfo();
		    cmrFkeyFields = 
			new PersistentFieldInfo[partnerPkeyFields.length];
		    for ( int i=0; i<partnerPkeyFields.length; i++ ) {
		        String fkeyName = "_" + finfo.name + "_" 
					    + partnerPkeyFields[i].name;
		        for ( int j=0; j<fkeyFields.length; j++ ) {
		    	    if ( fkeyFields[j].name.equals(fkeyName) )
			        cmrFkeyFields[i] = fkeyFields[j];
		        }
		    }
		    finfo.fkeyFields = cmrFkeyFields;
	        }	
            }
        }

        // initialize the cmrFieldInfo array with the actual size
        // and copy the non-null values of cmrFieldInfo2 to it
        cmrFieldInfo = new CMRFieldInfo[count];
        System.arraycopy(cmrFieldInfo2, 0, cmrFieldInfo, 0, count);

	// Sort cmrFieldInfo in alphabetical order of CMR field name
        for ( int i=cmrFieldInfo.length-1; i>0; i-- ) {
            for ( int j=0; j<i; j++ ) {
                if ( cmrFieldInfo[j].name.compareTo(cmrFieldInfo[j+1].name) 
									> 0 ) {
                    CMRFieldInfo tmp = cmrFieldInfo[j];
                    cmrFieldInfo[j] = cmrFieldInfo[j+1];
                    cmrFieldInfo[j+1] = tmp;
                }
            }
        }
    }

    public void clearCMPFields() {
        this.cmpFields.clear();
        setCMPFields(this.cmpFields);
    }

    public void addCMPField(String field) {
        addCMPField(new FieldDescriptor(field));
    }

    public void addCMPField(FieldDescriptor fieldDesc) {
        this.cmpFields.add(fieldDesc);
        setCMPFields(this.cmpFields);
    }

    public void removeCMPField(String field) {
        removeCMPField(new FieldDescriptor(field));
    }

    public void removeCMPField(FieldDescriptor fieldDesc) {
        this.cmpFields.remove(fieldDesc);
        setCMPFields(this.cmpFields);
    }

    /**
     * Set the FieldDescriptor objects that the EJB container will persist 
     * for this bean.
     */
    public void setCMPFields(Set cmpFields) {
	this.cmpFields = cmpFields;
	persFieldInfo = null;
	fieldInfoInitialized = false;

    }
    
    /**
     * Has the supplied field object been deemed persistent. 
     */
    public boolean isCMPField(String field) {
	return this.getCMPFields().contains(new FieldDescriptor(field));
    }

	
    /** 
     * Return the Set of fields deemed persistent.
     * The elements of this Set are FieldDescriptor objects.
     * This Set should be modified by calling addCMPField, removeCMPField
     */
    public Set getCMPFields() {
	return this.cmpFields;
    }

    /**
    public void clearPkeyFields() {
        this.pkeyFields.clear();
        setPkeyFields(this.pkeyFields);
    }

    public void addPkeyField(String field) {
        addPkeyField(new FieldDescriptor(field));
    }
    
    public void addPkeyField(FieldDescriptor fieldDesc) {
        this.pkeyFields.add(fieldDesc);
        setPkeyFields(this.pkeyFields);
    }

    public void removePkeyField(String field) {
        removePkeyField(new FieldDescriptor(field));
    }
    
    public void removePkeyField(FieldDescriptor fieldDesc) {
        this.pkeyFields.remove(fieldDesc);
        setPkeyFields(this.pkeyFields);
    }
    **/

    /**
     * Set the FieldDescriptor objects for primary key fields
     * for this bean.
     */
    public void setPkeyFields(Set pkeyFields) {
	this.pkeyFields = pkeyFields;
	fieldInfoInitialized = false;
	persFieldInfo = null;
	pkeyStuffInitialized = false;

    }
    
    /** 
     * Return the Set of primary key fields.
     * The elements of this Set are FieldDescriptor objects.
     * This Set can be modified by calling addPkeyField, removePkeyField
     */
    public Set getPkeyFields() {
	if ( !pkeyStuffInitialized )
	    initPkeyInfo();
	return pkeyFields;
    }

    /**
     * Is the supplied field object one of the pkey fields.
     */
    public boolean isPkeyField(String field) {
        return isPkeyField(new FieldDescriptor(field));
    }

    public boolean isPkeyField(FieldDescriptor fieldDesc) {
        return this.getPkeyFields().contains(fieldDesc);
    }

    /**
     * Initialize pkeyFields, pkeyIsOneField, primaryKeyClassName
     * Must be called after this PersistenceDescriptor has been attached
     * to the Ejb/JoinDescriptor which has been
     * attached to the EjbBundleDescriptor.
     */
    private void initPkeyInfo()
    {
	try {
	    pkeyIsOneField = false;
            pkeyFieldSpecified = true;
	    primaryKeyClassName = parentDesc.getPrimaryKeyClassName();
    
	    FieldDescriptor fd = parentDesc.getPrimaryKeyFieldDesc();
	    if ( pkeyFields == null || pkeyFields.size() == 0 ) {
	        pkeyFields = new HashSet();

	        if ( fd != null ) // primkey-field was set
		    pkeyFields.add(fd);

	        else if (!primaryKeyClassName.equals("java.lang.Object")) {
		    // get fields of primaryKeyClass
		    primaryKeyClass = getClass(primaryKeyClassName);
		    Field[] fields = primaryKeyClass.getFields();
		    pkeyFieldsAllPrimitive = true;
		    for ( int i=0; i<fields.length; i++ ) {
		        // ignore static or final fields
		        int m = fields[i].getModifiers();
		        if ( Modifier.isStatic(m) || Modifier.isFinal(m) )
			    continue;
		        if ( !fields[i].getType().isPrimitive() )
			    pkeyFieldsAllPrimitive = false;
		        pkeyFields.add(new FieldDescriptor(
						    fields[i].getName()));
		    }
	        }
	        else {
		    // Will use PM-generated primary key
		    primaryKeyClass = getClass(primaryKeyClassName);
                       pkeyIsOneField = true;
                       pkeyFieldSpecified = false;
	        }
	    }
	    if ( fd != null )
	        pkeyIsOneField = true;

	    pkeyStuffInitialized = true;
	}
	catch ( Exception ex ) {
            DOLUtils.getDefaultLogger().log(Level.SEVERE, "enterprise.deployment.backend.invalidDescriptorMappingFailure", 
                new Object[] {ex.toString()});
            throw new DeploymentException(ex);
	}
    }

    /**
     * @return true if the primary key of this object is one field
     * in its class and the type of the field is not a primitive type.
     * True for EJBs if the primkey-field deployment descriptor element
     * is specified, or if a container-inserted pk field is used.
     */
    public boolean primaryKeyIsOneField() 
    {
	if ( !pkeyStuffInitialized )
	    initPkeyInfo();
	return pkeyIsOneField;
    }


    /**
     * @return false if the primkey-field is not specified and pk class = Object
     */
    public boolean primaryKeyIsSpecified() 
    {
        if( !pkeyStuffInitialized )
            initPkeyInfo();
	return pkeyFieldSpecified;
    }


    /**
     * @return true if the primkey-field is not specified all fields of
     * pkey class are Java primitive types.
     */
    public boolean primaryKeyFieldsAllPrimitive() 
    {
        if( !pkeyStuffInitialized )
            initPkeyInfo();
	return pkeyFieldsAllPrimitive;
    }



    /**
     * Get this bean's primary key class.
     * For EJBs, this is EjbEntityDescriptor.getPrimaryKeyClassName(),
     */
    public Class getPrimaryKeyClass()
    {
	if ( !pkeyStuffInitialized )
	    initPkeyInfo();
	return primaryKeyClass;
    }
   

    // May return null for Join objects when called at/before deployment
    public Class getPersistentClass()
    {
	if ( persistentClass == null ) {
	    persistentClass = getClass(parentDesc.getEjbClassName());
	}
	return persistentClass;
    }

    public Class getStateClass()
    {
	if ( stateClass == null ) {
	    stateClass = getPersistentClass();
	    if ( parentDesc.isEJB20() ) {
		if( !Modifier.isAbstract(stateClass.getModifiers()) ) {
	            throw new DeploymentException("2.x CMP bean class "
                        + stateClass.getName() + " must be decleared abstract "
                        + "or cmp-version for the corresponding bean must be set to 1.x.");
                }
	        String stateClassName = parentDesc.getStateImplClassName();
	        stateClass = getClass(stateClassName);
	    }
	}
	return stateClass;
    }



    private Class getClass(String className)
    {            
	try {
	    return getEjbBundleDescriptor().getClassLoader().loadClass(className);
	} catch ( Exception ex ) {
	    throw new DeploymentException(ex);
	}
    }


    /**
     * Set the array of PersistentFieldInfo objects representing the 
     * foreign key fields of this bean.
     */
    public void setFkeyFields(PersistentFieldInfo[] fkeyFields) {
	this.fkeyFields = fkeyFields;
	fieldInfoInitialized = false;
	persFieldInfo = null;

    }
    
	
    /** 
     * Return the array of PersistentFieldInfo objects for the 
     * foreign key fields of this bean.
     */
    public PersistentFieldInfo[] getFkeyFields() {
	if ( !fieldInfoInitialized )
	    initializeFieldInfo();
	return this.fkeyFields;
    }


    /** 
     * Return the array of PersistentFieldInfo objects for the 
     * CMP + foreign key fields
     */
    public PersistentFieldInfo[] getPersistentFieldInfo()
    {
	if ( !fieldInfoInitialized )
	    initializeFieldInfo();
	return persFieldInfo;
    }


    /** 
     * Return the PersistentFieldInfo object for the given CMP/fkey field
     */
    public PersistentFieldInfo getPersistentFieldInfoByName(String fieldName)
    {
	if ( !fieldInfoInitialized )
	    initializeFieldInfo();
	for ( int i=0; i<persFieldInfo.length; i++ ) {
	    if ( persFieldInfo[i].name.equals(fieldName) )
		return persFieldInfo[i];
	}
	throw new DeploymentException("PersistentFieldInfo not found for field "+fieldName);
    }


    /** 
     * Return the array of PersistentFieldInfo objects for the CMP fields
     * which are not primary keys + foreign key fields.
     */
    public PersistentFieldInfo[] getNonPkeyPersFieldInfo()
    {
	if ( !fieldInfoInitialized )
	    initializeFieldInfo();
	return persNoPkeyFieldInfo;
    }


    /** 
     * Return the array of PersistentFieldInfo objects for the pkey fields.
     */
    public PersistentFieldInfo[] getPkeyFieldInfo()
    {
	if ( !fieldInfoInitialized )
	    initializeFieldInfo();
	return pkeyFieldInfo;
    }

    /** 
     * Return PersistentFieldInfo object for the given pkey field.
     */
    public PersistentFieldInfo getPkeyFieldInfoByName(String fieldName)
    {
	if ( !fieldInfoInitialized )
	    initializeFieldInfo();
	for ( int i=0; i<pkeyFieldInfo.length; i++ ) {
	    if ( pkeyFieldInfo[i].name.equals(fieldName) )
		return pkeyFieldInfo[i];
	}
	throw new DeploymentException("PersistentFieldInfo not found for pkey field "+fieldName);
    }



    /**
     * @return an array of all Field objects in the primary key class.
     * Returns null if primaryKeyIsOneField() == true.
     */
    public Field[] getPkeyClassFields()
    {
	if ( !fieldInfoInitialized )
	    initializeFieldInfo();
	return pkeyClassPkeyFields;
    }


    // Initialize persFieldInfo, pkeyFieldInfo, persNoPkeyFieldInfo, 
    // pkeyClassPkeyFields
    private void initializeFieldInfo()
    {
	if ( !pkeyStuffInitialized )
	    initPkeyInfo();

	int cmpFieldCount = cmpFields.size();
        if (cmpFieldCount==0) {
            throw new DeploymentException("No cmp field defined for CMP EJB " + parentDesc.getName());
        }

	int fkeyCount = 0;
	if ( fkeyFields != null )
	    fkeyCount = fkeyFields.length;

	persFieldInfo = new PersistentFieldInfo[cmpFieldCount + fkeyCount];
	// Add CMP fields
	int fcount = 0;
	Iterator itr = cmpFields.iterator();
	while ( itr.hasNext() ) {
	    persFieldInfo[fcount] = new PersistentFieldInfo();
	    persFieldInfo[fcount].name =((FieldDescriptor)itr.next()).getName();
	    fcount++;
	}
	// Add foreign key fields
	if ( fkeyFields != null ) {
	    for ( int i=0; i<fkeyFields.length; i++ ) {
		persFieldInfo[fcount] = fkeyFields[i];
		fcount++;
	    }
	}

	// sort persFieldInfo in alphabetical order
        for ( int i=persFieldInfo.length-1; i>0; i-- ) {
            for ( int j=0; j<i; j++ ) {
                if ( persFieldInfo[j].name.compareTo(persFieldInfo[j+1].name) 
									> 0 ) {
                    PersistentFieldInfo tmp = persFieldInfo[j];
                    persFieldInfo[j] = persFieldInfo[j+1];
                    persFieldInfo[j+1] = tmp;
                }
            }
        }

        // Initialize pkeyFieldInfo[] and persNoPkeyFieldInfo[] 
	// They contain the same PersistentFieldInfo objects as persFieldInfo.
        pkeyFieldInfo = new PersistentFieldInfo[pkeyFields.size()];
	if ( pkeyFieldSpecified ) {

            // check if PK class has public non-persistent fields
            StringBuffer nonPersFieldsInPK = new StringBuffer();
            for ( Iterator it=pkeyFields.iterator(); it.hasNext(); ) {
                FieldDescriptor fd = (FieldDescriptor)it.next();
                boolean isPersistent = false;
                for ( int i=0; i<persFieldInfo.length; i++ ) {
                    if ( fd.getName().equals(persFieldInfo[i].name) ) {
                        isPersistent = true;
                        break;
                    }
                }
                if ( !isPersistent ) {
                    // if not the first non-persistent field
                    if ( nonPersFieldsInPK.length() != 0 ) {
                        nonPersFieldsInPK.append(", ");
                    }
                    nonPersFieldsInPK.append(fd.getName());
                }
            }
            if ( nonPersFieldsInPK.length() != 0 ) {
                throw new DeploymentException(localStrings.getLocalString(
                "enterprise.deployment.pkhasnopersistentfields",
                "CMP bean [{0}], primary key class [{1}] has " + 
                "public non-persistent field(s) [{2}].",
                new Object[] {getParentDescriptor().getName(),
                primaryKeyClassName,
                nonPersFieldsInPK.toString()}));
            }

	    persNoPkeyFieldInfo = new PersistentFieldInfo[persFieldInfo.length -
							  pkeyFieldInfo.length];
	    int pkeyCount = 0;
	    int noPkeyCount = 0;
	    for ( int i=0; i<persFieldInfo.length; i++ ) {
		boolean isPkey = false;
		for ( Iterator it=pkeyFields.iterator(); it.hasNext(); ) {
		    FieldDescriptor fd = (FieldDescriptor)it.next();
		    if ( fd.getName().equals(persFieldInfo[i].name) ) {
			isPkey = true;
			break;
		    }
		}
		if ( isPkey ) 
		    pkeyFieldInfo[pkeyCount++] = persFieldInfo[i];
		else
		    persNoPkeyFieldInfo[noPkeyCount++] = persFieldInfo[i];
	    }
	}

	if ( pkeyIsOneField  && pkeyFieldSpecified) {
	    // Initialize pkey field type. This is needed for
	    // beans with no pkey field (i.e. PM-generated pkey)
	    // because they wont have get/set for the pkey in the bean class
	    // so the getCMPFieldType() below will bomb if type is not set.
	    // Note: pkeyFieldInfo and persFieldInfo arrays share the same
	    // PersistentFieldInfo objects.
	    pkeyFieldInfo[0].type = getPrimaryKeyClass();
	}

	// Initialize Java types in persFieldInfo
	for ( int i=0; i<persFieldInfo.length; i++ ) {
	    // fill type for CMP fields if not there 
	    // (fkey types will already be filled)
	    if ( persFieldInfo[i].type == null )
	        persFieldInfo[i].type = getCMPFieldType(persFieldInfo[i].name);
        }

        // When called from Deploytool, the bean class is abstract,
        // and doesnt have the CMP fields: they will be in the generated 
        // code after deployment. So all the java.lang.reflect.Field 
	// values in PersistentFieldInfo can only be initialized at runtime.
	try {
	    if ( persistentClass != null 
		 && !Modifier.isAbstract(persistentClass.getModifiers()) ) {
		for ( int i=0; i<persFieldInfo.length; i++ ) {
		    persFieldInfo[i].field = getField(getStateClass(), 
						      persFieldInfo[i].name);
		}
	    }

	    // Initialize pkeyClassPkeyFields
	    if ( !pkeyIsOneField && primaryKeyClass != null 
                 && !Modifier.isAbstract(primaryKeyClass.getModifiers()) ) {
		pkeyClassPkeyFields = new Field[pkeyFieldInfo.length];
		for ( int i=0; i<pkeyFieldInfo.length; i++ ) {
		    pkeyClassPkeyFields[i] = primaryKeyClass.getField(
							pkeyFieldInfo[i].name); 
		}
	    } 
	} catch ( NoSuchFieldException ex ) {
            if(DOLUtils.getDefaultLogger().isLoggable(Level.FINE)) {            
                DOLUtils.getDefaultLogger().log(Level.FINE, ex.toString(), ex);
            }
	    throw new DeploymentException(ex);
	}

        fieldInfoInitialized = true;
    }

    private Field getField(final Class c, final String name)
        throws NoSuchFieldException
    {
        // This privileged block is needed because this code can be
        // called when application code is on the stack, which is not
        // allowed to reflect on private members of classes.
        Field field = (Field)java.security.AccessController.doPrivileged(
            new java.security.PrivilegedAction() {
                public Object run()  {
                    try {
                        // this is needed for EJB2.0 CMP beans whose 
                        // generated fields are private.
                        return c.getDeclaredField(name);
                    }
                    catch ( NoSuchFieldException ex ) {
                        return null;
                    }
                }
            }
        );

        if ( field == null )
            field = c.getField(name);
        return field;
    }

    /**
     * @return the Class object corresponding to the type of the given
     *         CMP field.
     */
    public Class getTypeFor(String field)
    {
	return getCMPFieldType(field);
    }

    private Class getCMPFieldType(String field)
    {
	Class pclass = getPersistentClass();
	if ( Modifier.isAbstract(pclass.getModifiers()) ) {
	    // An EJB2.0 CMP bean : field is a virtual field 
	    String javaBeanName = capitalize(field);
	    String getter = "get"+javaBeanName;
	    try {
		Method method = pclass.getMethod(getter, (Class[]) null);
		return method.getReturnType();
	    } catch ( Exception ex ) {
		throw new RuntimeException("Cannot find accessor " + getter + " for CMP field "+field);
	    }
	}
	else {
	    // field is a Java field in state class
	    try {
		Field f = getField(getStateClass(), field);
		return f.getType();
	    } catch ( NoSuchFieldException ex ) {
		throw new RuntimeException("Cant find CMP field "+field+" in class "+getStateClass().getName());
	    }
	}
    }


    // called from CMPClassGenerator too
    public static String capitalize(String name)
    {
	// EJB2.0 proposed final draft says that CMP/CMR field names
	// must begin with a lower case letter.
	if ( Character.isUpperCase(name.charAt(0)) ) {
	    throw new DeploymentException("CMP/CMR field "+name+" must start with a lower case character.");
	}
	else {
	    char chars[] = name.toCharArray();
	    chars[0] = Character.toUpperCase(chars[0]);
	    return new String(chars);
	}
    }

    public void setQueryFor(MethodDescriptor method, QueryDescriptor query)
    {
		queries.put(method, query);
    }


    public QueryDescriptor getQueryFor(MethodDescriptor method)
    {
	return (QueryDescriptor)queries.get(method);
    }

    public void  removeQueryFor(MethodDescriptor method)
    {           
	queries.remove(method);
    }       

    public void setQueryFor(Method method, QueryDescriptor query)
    {
        // Use our own method equality check. This prevents problems
        // when a different classloader was used to load the input
        // method.  Also note that two methods with the same name and
        // signature on *different* interfaces are considered EQUAL.
        // This matches the spec requirement that the same finder
        // method defined on the LocalHome and RemoteHome has only
        // ONE query-method declaration in the deployment descriptor.
        // 
        MethodDescriptor md = new MethodDescriptor(method,"");
        setQueryFor(md, query);
    }

    public QueryDescriptor getQueryFor(Method method)
    {
        // Use our own method equality check. See setQueryFor comment
        // for more details.
        MethodDescriptor md = new MethodDescriptor(method,"");
        return (QueryDescriptor) queries.get(md);
    }
    
    /**
     * Get all methods for which setQueryFor was done 
     * @return a Set of Methods
     */
    public Set getQueriedMethods()
    {
	return queries.keySet();
    }

    /**
     * Get all HomeIntf.find* and EJBClass.ejbSelect* methods
     * for which an EJB-QL query could possibly be set.
     * @return a Set of Methods
     */
    public Set getAllPossibleQueriedMethods()
    {
	if ( allQueriedMethods == null ) 
	    initializeAllQueriedMethods();

	return allQueriedMethods;
    }

    private void initializeAllQueriedMethods() 
    {
	allQueriedMethods = new HashSet();	    

	// add all ejbSelect* methods in persistentClass
	Method[] beanMethods = getPersistentClass().getMethods();
	for ( int i=0; i<beanMethods.length; i++ ) {
	    if ( beanMethods[i].getName().startsWith("ejbSelect") ) {
		allQueriedMethods.add(new MethodDescriptor(beanMethods[i], MethodDescriptor.EJB_BEAN));
	    }
	}

        // add all finders in Home/LocalHome intf, findByPrimaryKey too
        if ( parentDesc.isRemoteInterfacesSupported() ) {
	    Class homeIntf = getClass(parentDesc.getHomeClassName());
    
	    Method[] homeMethods = homeIntf.getMethods();
	    for ( int i=0; i<homeMethods.length; i++ ) {
	        String name = homeMethods[i].getName();
	        if ( name.startsWith("find") 
		        && !name.equals("findByPrimaryKey") ) {
		    allQueriedMethods.add(new MethodDescriptor(homeMethods[i], MethodDescriptor.EJB_HOME));
	        }
	    }
        }
        if ( parentDesc.isLocalInterfacesSupported() ) {
	    Class homeIntf = getClass(parentDesc.getLocalHomeClassName());
    
	    Method[] homeMethods = homeIntf.getMethods();
	    for ( int i=0; i<homeMethods.length; i++ ) {
	        String name = homeMethods[i].getName();
	        if ( name.startsWith("find") 
		        && !name.equals("findByPrimaryKey") ) {
		    allQueriedMethods.add(new MethodDescriptor(homeMethods[i], MethodDescriptor.EJB_LOCALHOME));
	        }
	    }
        }
    }

    /**
    * Return my formatted string representation.
    */
    public void print(StringBuffer toStringBuffer) {
	super.print(toStringBuffer);
	toStringBuffer.append("\n Entity descriptor");
	toStringBuffer.append("\n cmpFields ").append(cmpFields);
    }
}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish PersistenceDescriptor.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.