/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. 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.html
* or glassfish/bootstrap/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 glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [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 java.io.*;
import java.util.*;
import java.util.logging.*;
import java.lang.reflect.*;
import com.sun.enterprise.util.TypeUtil;
import com.sun.enterprise.util.*;
import com.sun.enterprise.deployment.xml.*;
import com.sun.enterprise.deployment.interfaces.QueryParser;
import com.sun.enterprise.deployment.runtime.*;
import com.sun.enterprise.deployment.util.LogDomains;
/**
* This class contains information about EJB1.1 and EJB2.0 CMP EntityBeans.
*/
public class IASEjbCMPEntityDescriptor extends EjbCMPEntityDescriptor {
private transient Class ejbClass = null;
private String pcImplClassName = null;
private String concreteImplClassName = null;
private String ejbImplClassName = null;
private String mappingProperties;
private transient ClassLoader jcl = null;
private String uniqueName = null;
private String moduleDir = null;
// for i18N
private static LocalStringManagerImpl localStrings =
new LocalStringManagerImpl(IASEjbCMPEntityDescriptor.class);
private static final Logger _logger = LogDomains.getLogger(LogDomains.DPL_LOGGER);
// Standard String and Character variables.
private static final char DOT = '.'; // NOI18N
private static final char LIST_START = '(';// NOI18N
private static final char LIST_END = ')'; // NOI18N
private static final char LIST_SEPARATOR = ','; // NOI18N
private static final char NAME_PART_SEPARATOR = '_'; // NOI18N
private static final char NAME_CONCATENATOR = ' '; // NOI18N
private static final String FIND = "find"; // NOI18N
private static final String EJB_SELECT = "ejbSelect"; // NOI18N
private static final String JDOSTATE = "_JDOState"; // NOI18N
private static final String CONCRETE_IMPL = "_ConcreteImpl"; // NOI18N
private static final String MAPPINGEXT = DOT + "mapping"; // NOI18N
private transient Collection finders = null;
private transient Collection selectors = null;
private QueryParser queryParser = null;
private PrefetchDisabledDescriptor prefetchDisabledDescriptor = null;
private static final Map conversionTable = createConversionTable();
private Map oneOneFinders = new HashMap();
private List arrOneOneFinders = new ArrayList();
private void addAllInterfaceMethodsIn(Collection methodDescriptors, Class c) {
Method[] methods = c.getMethods();
for (int i=0; i<methods.length; i++) {
methodDescriptors.add(methods[i]);
}
}
private void addAllUniqueInterfaceMethodsIn(Collection methodDescriptors, Class c) {
Method[] methods = c.getMethods();
for (int i=0; i<methods.length; i++) {
if(findEquivalentMethod(methodDescriptors, methods[i]) == null)
methodDescriptors.add(methods[i]);
}
}
public Collection getAllUniqueMethods() {
HashSet methods = new HashSet();
try {
if (isRemoteInterfacesSupported()) {
addAllUniqueInterfaceMethodsIn(methods, jcl.loadClass(getHomeClassName()));
addAllUniqueInterfaceMethodsIn(methods, jcl.loadClass(getRemoteClassName()));
}
if (isLocalInterfacesSupported()) {
addAllUniqueInterfaceMethodsIn(methods, jcl.loadClass(getLocalHomeClassName()));
addAllUniqueInterfaceMethodsIn(methods, jcl.loadClass(getLocalClassName()));
}
} catch (Throwable t) {
_logger.log( Level.WARNING,
"enterprise.deployment_error_loading_class_excp", t ); // NOI18N
throw new RuntimeException(t.getMessage());
}
return methods;
}
public Collection getAllMethods() {
HashSet methods = new HashSet();
try {
if (isRemoteInterfacesSupported()) {
addAllInterfaceMethodsIn(methods, jcl.loadClass(getHomeClassName()));
addAllInterfaceMethodsIn(methods, jcl.loadClass(getRemoteClassName()));
}
if (isLocalInterfacesSupported()) {
addAllInterfaceMethodsIn(methods, jcl.loadClass(getLocalHomeClassName()));
addAllInterfaceMethodsIn(methods, jcl.loadClass(getLocalClassName()));
}
} catch (Throwable t) {
_logger.log( Level.WARNING,
"enterprise.deployment_error_loading_class_excp", t ); // NOI18N
throw new RuntimeException(t.getMessage());
}
return methods;
}
private Method findEquivalentMethod(Collection methods,
Method methodToMatch) {
if(methods == null)
return null;
Method matchedMethod = null;
for(Iterator iter = methods.iterator(); iter.hasNext();) {
Method next = (Method) iter.next();
// 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;
}
/**
* The method returns the class instance for the ejb class.
* @return ejb class
*/
private Class getEjbClass() {
if (ejbClass == null) {
String ejbClassName = getEjbClassName();
if(_logger.isLoggable(Level.FINE))
_logger.fine("@@@@@@ Ejb name is "+ ejbClassName); //NOI18N
if (jcl == null) {
String msg = localStrings.getLocalString(
"enterprise.deployment.error_missing_classloader", //NOI18N
"IASEjbCMPEntityDescriptor.getEjbClass"); //NOI18N
_logger.log(Level.WARNING, msg);
throw new RuntimeException(msg);
}
try {
ejbClass=Class.forName(ejbClassName, true, jcl);
} catch(ClassNotFoundException e) {
String msg = localStrings.getLocalString(
"enterprise.deployment.error_cannot_find_ejbclass", //NOI18N
ejbClassName);
_logger.log(Level.WARNING, msg);
throw new RuntimeException(msg);
}
}
return ejbClass;
}
/**
* Returns a collection of finder method instances.
*/
public Collection getFinders() {
if (finders == null) {
String ejbClassName = getEjbClassName();
Class ejbClass = getEjbClass();
if ( super.isRemoteInterfacesSupported() ) {
Class remoteHomeIntf = null;
if(_logger.isLoggable(Level.FINE))
_logger.fine("@@@@@@ " + ejbClassName + //NOI18N
" : Remote Interface is supported "); //NOI18N
try {
remoteHomeIntf = ejbClass.getClassLoader().loadClass(
super.getHomeClassName());
} catch (ClassNotFoundException ex) {
_logger.log( Level.WARNING,
"enterprise.deployment_class_not_found", ex ); //NOI18N
return null;
}
finders = getFinders(remoteHomeIntf);
if(_logger.isLoggable(Level.FINE)) {
for(Iterator iter = finders.iterator(); iter.hasNext();) {
Method remoteHomeMethod=(Method)iter.next();
_logger.fine("@@@@ adding Remote interface method " + //NOI18N
remoteHomeMethod.getName() );
}
}
} //end of isRemoteInterfaceSupported
if ( super.isLocalInterfacesSupported() ) {
Class localHomeIntf = null;
if(_logger.isLoggable(Level.FINE))
_logger.fine("@@@@@@ " + ejbClassName + ": Local Interface is supported "); //NOI18N
try {
localHomeIntf = ejbClass.getClassLoader().loadClass(
super.getLocalHomeClassName());
} catch (ClassNotFoundException ex) {
_logger.log( Level.WARNING,
"enterprise.deployment_class_not_found", ex ); //NOI18N
return null;
}
Collection localFinders = getFinders(localHomeIntf);
if(finders == null) {
// if there were no finders specified in the remote
// home, the local finders are the finders
finders = localFinders;
} else if(localFinders != null) {
// Remove the Common Elements from the collections
// and keep only unique methods
if(_logger.isLoggable(Level.FINE))
_logger.fine("@@@@@@ Trying to remove the Common Elements from HashSet....... "); //NOI18N
for(Iterator iter = localFinders.iterator(); iter.hasNext();) {
Method localHomeMethod=(Method)iter.next();
if(findEquivalentMethod(finders, localHomeMethod) == null) {
if(_logger.isLoggable(Level.FINE))
_logger.fine("@@@@ adding local interface method " + //NOI18N
localHomeMethod.getName() );
finders.add(localHomeMethod);
}
}
}
} //end of isLocalInterfaceSupported
if (finders == null)
// still not initialized => empty set
finders = new HashSet();
}
return finders;
}
/**
* Returns a collection of finder methods declared by the home
* interface given by a class object.
*/
public Collection getFinders(Class homeIntf) {
Method[] methods = homeIntf.getMethods();
Collection finders = new HashSet();
for(int i=0; i<methods.length; i++) {
if(methods[i].getName().startsWith(FIND)) {
finders.add(methods[i]);
}
}
return finders;
}
public void setClassLoader(ClassLoader jcl) {
this.jcl = jcl;
}
public ClassLoader getClassLoader() {
return jcl;
}
public Collection getAllPersistentFields() {
PersistenceDescriptor pers = getPersistenceDescriptor();
PersistentFieldInfo[] persFields = pers.getPersistentFieldInfo();
PersistentFieldInfo[] pkeyFields = pers.getPkeyFieldInfo();
HashMap fields = new HashMap();
for(int i=0; i<persFields.length; i++) {
fields.put(persFields[i].name, persFields[i]);
}
for(int i=0; i<pkeyFields.length; i++) {
fields.put(pkeyFields[i].name, pkeyFields[i]);
}
return fields.values();
}
public Collection getPersistentFields() {
PersistenceDescriptor pers = getPersistenceDescriptor();
PersistentFieldInfo[] persFields = pers.getPersistentFieldInfo();
HashMap fields = new HashMap();
for(int i=0; i<persFields.length; i++) {
fields.put(persFields[i].name, persFields[i]);
}
return fields.values();
}
public Collection getPrimaryKeyFields() {
PersistenceDescriptor pers = getPersistenceDescriptor();
PersistentFieldInfo[] pkeyFields = pers.getPkeyFieldInfo();
HashMap pkey = new HashMap();
for(int i=0; i<pkeyFields.length; i++) {
pkey.put(pkeyFields[i].name, pkeyFields[i]);
}
return pkey.values();
}
/**
* Returns a collection of selector methods.
*/
public Collection getSelectors() {
if (selectors == null) {
selectors = new HashSet();
Class ejbClass = getEjbClass();
Method[] methods = ejbClass.getMethods();
for(int i=0; i<methods.length; i++) {
if(methods[i].getName().startsWith(EJB_SELECT)) { //NOI18N
selectors.add(methods[i]);
}
}
}
return selectors;
}
public String getBaseName(String className) {
if (className == null)
return null;
int dot = className.lastIndexOf(DOT);
if (dot == -1)
return className;
return className.substring(dot+1);
}
public IASEjbCMPEntityDescriptor() {
}
/**
* The copy constructor.Hopefully we wont need it;)
*/
public IASEjbCMPEntityDescriptor(EjbDescriptor other) {
super(other);
setPersistenceType(CONTAINER_PERSISTENCE);
if ( other instanceof EjbCMPEntityDescriptor ) {
EjbCMPEntityDescriptor entity = (EjbCMPEntityDescriptor)other;
}
}
/**
* Sets the State class implementation classname.
*/
public void setPcImplClassName(String name) {
pcImplClassName = name;
}
public String getUniqueName() {
if(uniqueName == null) {
BundleDescriptor bundle = getEjbBundleDescriptor();
Application application = bundle.getApplication();
// Add ejb name and application name.
StringBuffer rc = new StringBuffer().
append(getName()).
append(NAME_CONCATENATOR).
append(application.getRegistrationName());
// If it's not just a module, add a module name.
if (!application.isVirtual()) {
rc.append(NAME_CONCATENATOR).
append(bundle.getModuleDescriptor().getArchiveUri());
}
uniqueName = getBaseName(getEjbClassName())
+ getUniqueNumber(rc.toString());
}
return uniqueName;
}
public String getUniqueNumber(String num) {
//Modified to decrease the possibility of collision
String newNum= "" + num.hashCode(); // NOI18N
newNum = newNum.replace('-', NAME_PART_SEPARATOR); // NOI18N
return newNum;
}
public String getPcImplClassName() {
if (pcImplClassName == null) {
// Check for Null added
pcImplClassName = getUniqueName() + JDOSTATE;
String packageName = getPackageName(getEjbClassName());
if(packageName != null)
pcImplClassName = packageName + DOT + pcImplClassName;
if(_logger.isLoggable(Level.FINE))
_logger.fine("##### PCImplClass Name is " + pcImplClassName); // NOI18N
}
return pcImplClassName;
}
/**
* Sets the State class implementation classname.
*/
public void setConcreteImplClassName(String name) {
concreteImplClassName = name;
}
public String getPackageName(String className) {
int dot = className.lastIndexOf(DOT);
if (dot == -1)
return null;
return className.substring(0, dot);
}
/** IASRI 4725194
* Returns the Execution class, which is sam as the user-specified class
* in case of Message, Session and Bean Managed Persistence Entity Beans
* but is different for Container Mananged Persistence Entity Bean
* Therefore, the implementation in the base class is to return
* getEjbClassName() and the method is redefined in IASEjbCMPDescriptor.
*
*/
public String getEjbImplClassName() {
if (ejbImplClassName == null) {
String packageName = getPackageName(getEjbClassName());
ejbImplClassName = getConcreteImplClassName();
if(packageName != null)
ejbImplClassName = packageName + DOT + ejbImplClassName;
}
return ejbImplClassName;
}
/**
* Returns the classname of the State class impl.
*/
public String getConcreteImplClassName() {
if (concreteImplClassName == null) {
/** The Ear may contain two jar files with beans with same ejb names
*/
concreteImplClassName = getUniqueName() + CONCRETE_IMPL;
}
return concreteImplClassName;
}
public void setModuleDir(String moduleRootDir) {
moduleDir = moduleRootDir;
}
/**
* Returns the Module root of this module.
*/
public String getModuleDir() {
//FIXME:this needs to be changed when the API is available.
if(moduleDir != null)
return moduleDir;
else
return null;
}
public void setMappingProperties(String mappingProperties) {
this.mappingProperties = mappingProperties;
}
/**
* Returns the classname of the State class impl.
*/
public String getMappingProperties() {
return mappingProperties;
}
/**
* Called from EjbBundleDescriptor/EjbBundleArchivist
* when some classes in this bean are updated.
*/
public boolean classesChanged() {
/** No Implementation Yet
boolean superChanged = super.classesChanged();
boolean persChanged = pers.classesChanged();
// Send changed event only if parent didn't already do it.
if( !superChanged && persChanged ) {
changed();
}
return (superChanged || persChanged);
*/
return false;
}
/**
* This method sets the parser which would be used to parse the query
* parameter declaration given in sun-ejb-jar.xml.
* This method is called from JDOCodenerator class 's generate() method.
*/
public void setQueryParser(QueryParser inParser) {
queryParser = inParser;
}
/**
* Returns the query parser object
*/
public QueryParser getQueryParser() {
return queryParser;
}
/**
* This method returns the conversion table which maps the unqualified
* name (e.g., String) of the java.lang classes to their fully qualified
* name (e.g., java.lang.String)
*/
private static Map createConversionTable () {
HashMap conversionTable = new HashMap();
conversionTable.put("Boolean", "java.lang.Boolean"); //NOI18N
conversionTable.put("Byte", "java.lang.Byte"); //NOI18N
conversionTable.put("Character", "java.lang.Character"); //NOI18N
conversionTable.put("Double", "java.lang.Double"); //NOI18N
conversionTable.put("Float", "java.lang.Float"); //NOI18N
conversionTable.put("Integer", "java.lang.Integer"); //NOI18N
conversionTable.put("Long", "java.lang.Long"); //NOI18N
conversionTable.put("Number", "java.lang.Number"); //NOI18N
conversionTable.put("Short", "java.lang.Short"); //NOI18N
conversionTable.put("String", "java.lang.String"); //NOI18N
conversionTable.put("Object", "java.lang.Object"); //NOI18N
return conversionTable;
}
private String getFullyQualifiedType(String type) {
String knownType=(String)conversionTable.get(type);
return knownType == null ? type : knownType;
}
/**
* Getter for prefetch-disabled
* @return Value of prefetchDisabledDescriptor
*/
public PrefetchDisabledDescriptor getPrefetchDisabledDescriptor() {
return prefetchDisabledDescriptor;
}
/**
* Setter for prefetch-disabled
* @param prefetchDisabledDescriptor
* New value of prefetchDisabledDescriptor.
*/
public void setPrefetchDisabledDescriptor(
PrefetchDisabledDescriptor prefetchDisabledDescriptor) {
this.prefetchDisabledDescriptor = prefetchDisabledDescriptor;
}
/*
* Adds the given OneOneFinder to the HashMap
* @Param finder represents the EJB 1.1 Finder
*/
public void addOneOneFinder (IASEjbCMPFinder finder) {
arrOneOneFinders.add(finder);
}
/**
* Returns a Map which maps between a method signature and the
* corresponding IASEjbCMPFinder instance. The key is the method
* signature as a string and consists of methodName(type1, type2.....).
*/
public Map getOneOneFinders() {
// update the oneOneFinders map if there are any entries pending in
// the array arrOneOneFinders.
if (!arrOneOneFinders.isEmpty()) {
if (queryParser == null) {
String msg = localStrings.getLocalString(
"enterprise.deployment.error_missing_queryparser", //NOI18N
"IASEjbCMPEntityDescriptor.getOneOneFinders"); //NOI18N
_logger.log(Level.WARNING, msg);
throw new RuntimeException(msg);
}
//parse the query declaration parameter and store the query object
for ( Iterator i = arrOneOneFinders.iterator(); i.hasNext(); ) {
IASEjbCMPFinder finder = ( IASEjbCMPFinder )i.next();
String key = generateKey(finder, queryParser);
oneOneFinders.put(key, finder);
}
arrOneOneFinders.clear();
}
return oneOneFinders;
}
/*
* @returns the key used to store 1.1 Finder Object.
* the key is methodName(param0, param1.....)
* @param finder is the object which represents the EJB 1.1 Finder
*/
private String generateKey(IASEjbCMPFinder finder, QueryParser parser) {
StringBuffer key = new StringBuffer();
key.append(finder.getMethodName()).append(LIST_START);
String queryParams = finder.getQueryParameterDeclaration();
Iterator iter = parser.parameterTypeIterator(queryParams);
while ( iter.hasNext() ) {
String type = ( String ) iter.next() ;
key.append(getFullyQualifiedType(type)) ;
if( iter.hasNext() ) {
key.append(LIST_SEPARATOR);
}
}
key.append(LIST_END);
return key.toString().intern();
}
/*
* @returns The finder object for the particular Method object.
* @param method object for which the Finder Object needs to be found
*/
public IASEjbCMPFinder getIASEjbCMPFinder(Method method) {
//Checks if the given method is present in the interfaces.
if(findEquivalentMethod(getFinders(), method) == null ) {
return null;
}
String methodName = method.getName();
//key is of the form methodName(param0, param1, ....)
StringBuffer key = new StringBuffer();
key.append(methodName);
key.append(LIST_START);
Class paramList[] = method.getParameterTypes();
for (int index = 0 ; index < paramList.length ; index++ ) {
if(index>0) {
key.append(LIST_SEPARATOR);
}
key.append(paramList[index].getName());
}
key.append(LIST_END);
return (IASEjbCMPFinder)getOneOneFinders().get(key.toString());
}
}
|