| /******************************************************************************* |
| * Copyright (c) 2001, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.j2ee.model.internal.validation; |
| |
| import java.text.MessageFormat; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.logging.Level; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.jem.java.ArrayType; |
| import org.eclipse.jem.java.Field; |
| import org.eclipse.jem.java.JavaClass; |
| import org.eclipse.jem.java.JavaHelpers; |
| import org.eclipse.jem.java.JavaPackage; |
| import org.eclipse.jem.java.JavaParameter; |
| import org.eclipse.jem.java.JavaRefFactory; |
| import org.eclipse.jem.java.JavaVisibilityKind; |
| import org.eclipse.jem.java.Method; |
| import org.eclipse.jem.util.emf.workbench.ProjectResourceSet; |
| import org.eclipse.jem.util.logger.LogEntry; |
| import org.eclipse.jem.util.logger.proxy.Logger; |
| import org.eclipse.jst.j2ee.core.internal.plugin.J2EECorePlugin; |
| import org.eclipse.jst.j2ee.ejb.CMPAttribute; |
| import org.eclipse.jst.j2ee.ejb.CMRField; |
| import org.eclipse.jst.j2ee.ejb.CommonRelationshipRole; |
| import org.eclipse.jst.j2ee.ejb.ContainerManagedEntity; |
| import org.eclipse.jst.j2ee.ejb.EJBRelationshipRole; |
| import org.eclipse.jst.j2ee.ejb.EnterpriseBean; |
| import org.eclipse.jst.j2ee.ejb.Entity; |
| import org.eclipse.jst.j2ee.ejb.Query; |
| import org.eclipse.jst.j2ee.ejb.QueryMethod; |
| import org.eclipse.jst.j2ee.ejb.Session; |
| import org.eclipse.jst.j2ee.ejb.SessionType; |
| import org.eclipse.jst.j2ee.ejb.TransactionType; |
| import org.eclipse.jst.j2ee.ejb.internal.impl.LocalModelledPersistentAttributeFilter; |
| import org.eclipse.jst.j2ee.internal.J2EEVersionConstants; |
| import org.eclipse.jst.j2ee.model.internal.validation.EARValidationMessageResourceHandler; |
| |
| /** |
| * @version 1.0 |
| * @author |
| */ |
| public final class ValidationRuleUtility { |
| public static long method_and_field_counter = 0x1; // used by IMethodAndFieldConstants.java |
| private static final String[] _reservedWords = new String[]{"SELECT", "FROM", "WHERE", "DISTINCT", "OBJECT", "NULL", "TRUE", "FALSE", "NOT", "AND", "OR", "BETWEEN", "LIKE", "IN", "AS", "UNKNOWN", "EMPTY", "MEMBER", "OF", "IS"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$ //$NON-NLS-14$ //$NON-NLS-15$ //$NON-NLS-16$ //$NON-NLS-17$ //$NON-NLS-18$ //$NON-NLS-19$ //$NON-NLS-20$ |
| private static final String COMMA = ", "; //$NON-NLS-1$ |
| |
| private static LogEntry logEntry = null; |
| private static Logger logger = null; |
| |
| public static HashMap helperMap = null; |
| public static Map projectHelperMap = Collections.synchronizedMap( new HashMap() ); |
| private static HashSet commonClassNames = null; |
| |
| public static JavaClass getCMRFieldType(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, CMRField field) { |
| CommonRelationshipRole role = field.getRole(); |
| if(!role.isMany()) { |
| ContainerManagedEntity cmp = role.getTypeEntity(); |
| if(cmp == null) { |
| return null; |
| } |
| |
| JavaClass local = cmp.getLocalInterface(); |
| // If the user has made a mistake in ejb-jar.xml, and they are trying to make |
| // a relationship to a cmp which does not have a local interface, an InvalidInputException |
| // will be thrown. Let the DD validation catch that error; just return |
| // when this happens. |
| try { |
| ValidationRuleUtility.isValidTypeHierarchy(cmp, local); |
| } |
| catch(InvalidInputException e) { |
| return null; |
| } |
| return local; |
| } |
| // <cmr-field-type> is either a java.util.Collection or a java.util.Set (p. 464) |
| return field.getCollectionType(); |
| } |
| |
| |
| |
| |
| public static final boolean followsFinderExceptionRules(EnterpriseBean bean, Method method) throws InvalidInputException { |
| return ValidationRuleUtility.throwsFinderException(bean, method); |
| } |
| |
| public static final boolean followsObjectNotFoundExceptionRules(EnterpriseBean bean, Method method) throws InvalidInputException { |
| JavaHelpers javaUtilEnumeration = ValidationRuleUtility.getType(ITypeConstants.CLASSNAME_JAVA_UTIL_ENUMERATION, bean); |
| if(ValidationRuleUtility.isAssignableFrom(method.getReturnType(), javaUtilEnumeration)) { |
| // Only single object finder and select methods may throw this exception |
| return !ValidationRuleUtility.throwsObjectNotFoundException(bean, method); |
| } |
| |
| JavaHelpers javaUtilCollection = ValidationRuleUtility.getType(ITypeConstants.CLASSNAME_JAVA_UTIL_COLLECTION, bean); |
| if(ValidationRuleUtility.isAssignableFrom(method.getReturnType(), javaUtilCollection)) { |
| // Only single object finder and select methods may throw this exception |
| return !ValidationRuleUtility.throwsObjectNotFoundException(bean, method); |
| } |
| |
| // It's a single finder/select method, so it can throw the exception, though it is not required to. |
| return true; |
| } |
| |
| /** |
| * If it exists, return the Method from the method list which has the given |
| * name and parameter types (in the same order as the array elements). |
| * |
| * This method is a duplicate of getMethodExtended(String, String[]). |
| * For performance reasons, the code was duplicated instead of converting the |
| * JavaParameter[] into a String[]. |
| */ |
| private static Method getMethod(String name, JavaParameter[] parameterTypes, List methodList) { |
| if(methodList == null) { |
| return null; |
| } |
| |
| Method method = null; |
| JavaParameter[] params = null; |
| boolean found = false; |
| |
| Iterator iterator = methodList.iterator(); |
| while(iterator.hasNext()) { |
| method = (Method)iterator.next(); |
| |
| if (method.getName().equals(name)) { |
| params = method.listParametersWithoutReturn(); |
| |
| if (params.length == parameterTypes.length) { |
| found = true; //Maybe; we need more info |
| |
| for (int j = 0; j < params.length; j++) { |
| //if any one of the parameters doesn't match then flip back to false |
| JavaHelpers parm = ((JavaHelpers)params[j].getEType()); |
| JavaHelpers type = ((JavaHelpers)parameterTypes[j].getEType()); |
| if(!isSameType(parm, type)) { |
| found = false; |
| break; |
| } |
| } |
| |
| if (found) { |
| return method; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| private static Method getMethod(String name, JavaHelpers[] parameterTypes, List methodList) { |
| if(methodList == null) { |
| return null; |
| } |
| |
| Method method = null; |
| JavaParameter[] params = null; |
| boolean found = false; |
| |
| Iterator iterator = methodList.iterator(); |
| while(iterator.hasNext()) { |
| method = (Method)iterator.next(); |
| |
| if (method.getName().equals(name)) { |
| params = method.listParametersWithoutReturn(); |
| |
| if (params.length == parameterTypes.length) { |
| found = true; //Maybe; we need more info |
| |
| for (int j = 0; j < params.length; j++) { |
| //if any one of the parameters doesn't match then flip back to false |
| JavaHelpers parm = ((JavaHelpers)params[j].getEType()); |
| JavaHelpers type = parameterTypes[j]; |
| if(!isSameType(parm, type)) { |
| found = false; |
| break; |
| } |
| } |
| |
| if (found) { |
| return method; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * From JavaClass clazz, return a method, named methodNameToFind, |
| * which has exactly the same arguments as methodToMatch. |
| * |
| * If no method exists with that name and argument list, return null. |
| * |
| * This method does not check the exceptions or return type. |
| */ |
| public static Method getMethod(Method methodToMatch, String methodNameToFind, List methodsExtendedList) { |
| if(methodsExtendedList == null) { |
| // It is not invalid to call this method with a null List. A null List |
| // means that a type whose methods need to be searched doesn't exist, |
| // such as searching a local view, but the bean has only a remote view. |
| return null; |
| } |
| return getMethod(methodNameToFind, methodToMatch.listParametersWithoutReturn(), methodsExtendedList); |
| } |
| |
| /** |
| * From JavaClass clazz, return a method, named methodNameToFind, |
| * which has exactly the same arguments as methodToMatch. |
| * |
| * If no method exists with that name and argument list, return null. |
| * |
| * This method does not check the exceptions or return type. |
| */ |
| public static Method getMethodExtended(JavaClass clazz, Method methodToMatch, String methodNameToFind) throws InvalidInputException { |
| if ((clazz == null) || (methodToMatch == null) || (methodNameToFind == null)) { |
| return null; |
| } |
| |
| return getMethodExtended(clazz, methodNameToFind, methodToMatch.listParametersWithoutReturn()); |
| } |
| |
| /** |
| * Get the method of this name and these parameters. It will look up the supertype hierarchy. |
| * |
| * This method is a duplicate of getMethodExtended(String, String[]). |
| * For performance reasons, the code was duplicated instead of converting the |
| * JavaParameter[] into a String[]. |
| */ |
| public static Method getMethodExtended(JavaClass clazz, String methodName, JavaParameter[] parameterTypes) { |
| if (clazz.isInterface()) { |
| // Check the current class first. If the method has been overriden, |
| // don't want to return the parent's method instead of the child's. |
| return getMethodInterfaceExtended(clazz, methodName, parameterTypes); |
| } |
| // Check the current class first. If the method has been overriden, |
| // don't want to return the parent's method instead of the child's. |
| Method method = null; |
| List methods = null; |
| do { |
| methods = clazz.getMethods(); |
| method = getMethod(methodName, parameterTypes, methods); |
| if (method != null) { |
| return method; |
| } |
| |
| // else, search the parent |
| clazz = clazz.getSupertype(); |
| } |
| while (clazz != null); |
| |
| return null; |
| } |
| |
| /** |
| * Get the method of this name and these parameters. It will look up the supertype hierarchy. |
| * |
| * This method is a duplicate of getMethodExtended(String, JavaParameter[]). |
| * For performance reasons, the code was duplicated instead of converting the |
| * JavaHelpers[] into a JavaParameter[]. |
| */ |
| public static Method getMethodExtended(JavaClass clazz, String methodName, JavaHelpers[] parameterTypes) { |
| return getMethodExtended(clazz, methodName, parameterTypes, null); |
| } |
| |
| /** |
| * Get the method of this name and these parameters. It will look up the supertype hierarchy. |
| * |
| * This method is a duplicate of getMethodExtended(String, JavaParameter[]). |
| * For performance reasons, the code was duplicated instead of converting the |
| * JavaHelpers[] into a JavaParameter[]. |
| * |
| * If retType is null it means that the return type of the method doesn't need to be checked. |
| * Otherwise, check that the return type matches too. |
| */ |
| public static Method getMethodExtended(JavaClass clazz, String methodName, JavaHelpers[] parameterTypes, JavaHelpers retType) { |
| if (clazz.isInterface()) { |
| // Check the current class first. If the method has been overriden, |
| // don't want to return the parent's method instead of the child's. |
| return getMethodInterfaceExtended(clazz, methodName, parameterTypes); |
| } |
| // Check the current class first. If the method has been overriden, |
| // don't want to return the parent's method instead of the child's. |
| Method method = null; |
| List methods = null; |
| do { |
| methods = clazz.getMethods(); |
| method = getMethod(methodName, parameterTypes, methods); |
| if (method != null) { |
| if(retType != null) { |
| JavaHelpers methRetType = method.getReturnType(); |
| if(isAssignableFrom(methRetType, retType)) { |
| return method; |
| } |
| } |
| else { |
| return method; |
| } |
| } |
| |
| // else, search the parent |
| clazz = clazz.getSupertype(); |
| } |
| while ((method == null) && (clazz != null)); |
| |
| return null; |
| } |
| |
| /** |
| * Get the method of this name and these parameters. It will look up the supertype hierarchy. |
| * |
| * |
| * If retType is null it means that the return type of the method doesn't need to be checked. |
| * Otherwise, check that the return type matches too. |
| */ |
| public static Method getMethodExtended(JavaClass clazz, String methodName, JavaParameter[] parameterTypes, JavaHelpers retType) { |
| if (clazz.isInterface()) { |
| // Check the current class first. If the method has been overriden, |
| // don't want to return the parent's method instead of the child's. |
| return getMethodInterfaceExtended(clazz, methodName, parameterTypes); |
| } |
| // Check the current class first. If the method has been overriden, |
| // don't want to return the parent's method instead of the child's. |
| Method method = null; |
| List methods = null; |
| do { |
| methods = clazz.getMethods(); |
| method = getMethod(methodName, parameterTypes, methods); |
| if (method != null) { |
| if(retType != null) { |
| JavaHelpers methRetType = method.getReturnType(); |
| if(isAssignableFrom(methRetType, retType)) { |
| return method; |
| } |
| } |
| else { |
| return method; |
| } |
| } |
| |
| // else, search the parent |
| clazz = clazz.getSupertype(); |
| } |
| while ((method == null) && (clazz != null)); |
| |
| return null; |
| } |
| |
| /** |
| * Get the method of this name and these parameters. It will look up the supertype hierarchy. |
| * |
| * This method is a duplicate of getMethodInterfaceExtended(String, String[], JavaClass). |
| * For performance reasons, the code was duplicated instead of converting the |
| * JavaParameter[] into a String[]. |
| */ |
| public static Method getMethodInterfaceExtended(JavaClass clazz, String methodName, JavaParameter[] parameterTypes) { |
| if (clazz == null) { |
| return null; |
| } |
| |
| // Check the current class first. If the method has been overriden, |
| // don't want to return the parent's method instead of the child's. |
| Method method = getMethod(methodName, parameterTypes, clazz.getMethods()); |
| if (method != null) { |
| return method; |
| } |
| // check parents |
| List classesToCheck = clazz.getImplementsInterfaces(); |
| Iterator clazzIterator = classesToCheck.iterator(); |
| while (clazzIterator.hasNext()) { |
| clazz = (JavaClass) clazzIterator.next(); |
| method = getMethodInterfaceExtended(clazz, methodName, parameterTypes); |
| if (method != null) { |
| return method; |
| } |
| } |
| |
| return null; |
| } |
| |
| public static Method getMethodInterfaceExtended(JavaClass clazz, String methodName, JavaHelpers[] parameterTypes) { |
| if (clazz == null) { |
| return null; |
| } |
| |
| // Check the current class first. If the method has been overriden, |
| // don't want to return the parent's method instead of the child's. |
| Method method = getMethod(methodName, parameterTypes, clazz.getMethods()); |
| if (method != null) { |
| return method; |
| } |
| // check parents |
| List classesToCheck = clazz.getImplementsInterfaces(); |
| Iterator clazzIterator = classesToCheck.iterator(); |
| while (clazzIterator.hasNext()) { |
| clazz = (JavaClass) clazzIterator.next(); |
| method = getMethodInterfaceExtended(clazz, methodName, parameterTypes); |
| if (method != null) { |
| return method; |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Return an array of the exceptions thrown by method but not methodToMatch. |
| * If there are no such exceptions, return null. (Check the list of exceptions |
| * in the method for each exception, or a parent of the exception.) |
| */ |
| public static final Set getNotSubsetExceptions(EnterpriseBean bean, Method method, Method methodToMatch) { |
| if((methodToMatch == null) || (method == null)) { |
| return Collections.EMPTY_SET; |
| } |
| |
| // All the exceptions defined in the throws clause of a method of the |
| // entity bean class must be included in the throws clause of the matching |
| // method of the home interface. |
| // |
| // Section 12.2.2 |
| // [15] A checked exception is one that is not a subclass of java.lang.RuntimeException |
| // "Note that the javax.ejb.EJBException is a subclass of the java.lang.RuntimeException, |
| // and therefore it does not have to be listed in the throws clauses of the business |
| // methods." |
| HashSet exceptions = new HashSet(); |
| List methToMatchExceptions = methodToMatch.getJavaExceptions(); |
| List foundMethExceptions = method.getJavaExceptions(); |
| for( int i = 0; i < foundMethExceptions.size(); i++ ) { |
| JavaClass exc = (JavaClass)foundMethExceptions.get(i); |
| if ( !isRuntimeException(exc, bean) && !isRemoteException(exc, bean) && !isExceptionInList(exc, methToMatchExceptions) ) { |
| exceptions.add(exc); |
| } |
| } |
| |
| return exceptions; |
| } |
| |
| /** |
| * Return an array of the exceptions thrown by method but not methodToMatch. |
| * If there are no such exceptions, return null. (Check the list of exceptions |
| * in the method for each exception, or a child of the exception.) |
| */ |
| public static final Set getNotSubsetSubtypeExceptions(EnterpriseBean bean, Method method, Method methodToMatch) { |
| if((methodToMatch == null) || (method == null)) { |
| return Collections.EMPTY_SET; |
| } |
| |
| // All the exceptions defined in the throws clause of a method of the |
| // entity bean class must be included in the throws clause of the matching |
| // method of the home interface. |
| // |
| // Section 12.2.2 |
| // [15] A checked exception is one that is not a subclass of java.lang.RuntimeException |
| // "Note that the javax.ejb.EJBException is a subclass of the java.lang.RuntimeException, |
| // and therefore it does not have to be listed in the throws clauses of the business |
| // methods." |
| HashSet exceptions = new HashSet(); |
| List methToMatchExceptions = methodToMatch.getJavaExceptions(); |
| List foundMethExceptions = method.getJavaExceptions(); |
| for( int i = 0; i < foundMethExceptions.size(); i++ ) { |
| JavaClass exc = (JavaClass)foundMethExceptions.get(i); |
| if ( !isRuntimeException(exc, bean) && !isRemoteException(exc, bean) && !isSubtypeExceptionInList(exc, methToMatchExceptions) ) { |
| exceptions.add(exc); |
| } |
| } |
| |
| return exceptions; |
| } |
| |
| /** |
| * Exclude root home interface methods |
| */ |
| public static boolean isEJBHomeMethod(EnterpriseBean bean, Method method) { |
| return isSameType(bean, method.getContainingJavaClass(), ITypeConstants.CLASSNAME_JAVAX_EJB_EJBHOME); |
| } |
| |
| /** |
| * Exclude root remote interface methods |
| */ |
| public static boolean isEJBObjectMethod(EnterpriseBean bean, Method method) { |
| return isSameType(bean, method.getContainingJavaClass(), ITypeConstants.CLASSNAME_JAVAX_EJB_EJBOBJECT); |
| } |
| |
| /** |
| * Return true if the exception, or a parent of the exception, is in the list of exceptions. |
| */ |
| public static final boolean isExceptionInList(JavaClass exc, List exceptionList) { |
| if((exc == null) || (exceptionList == null)) { |
| return false; |
| } |
| |
| if(!exc.isExistingType()) { |
| return false; |
| } |
| |
| Iterator iterator = exceptionList.iterator(); |
| while(iterator.hasNext()) { |
| JavaClass exception = (JavaClass)iterator.next(); |
| if(isAssignableFrom(exc, exception)) { |
| // If there is a reflection problem, do not swallow the exception or a |
| // faulty message may appear. (i.e., "exc" is not thrown by "foo" when it |
| // really is but one of foo's exceptions wasn't reflected. |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Return true if the exception, or a child of the exception, is in the list of exceptions. |
| */ |
| public static final boolean isSubtypeExceptionInList(JavaClass exc, List exceptionList) { |
| if((exc == null) || (exceptionList == null)) { |
| return false; |
| } |
| |
| if(!exc.isExistingType()) { |
| return false; |
| } |
| |
| Iterator iterator = exceptionList.iterator(); |
| while(iterator.hasNext()) { |
| JavaClass exception = (JavaClass)iterator.next(); |
| if(isAssignableFrom(exception, exc)) { |
| // If there is a reflection problem, do not swallow the exception or a |
| // faulty message may appear. (i.e., "exc" is not thrown by "foo" when it |
| // really is but one of foo's exceptions wasn't reflected. |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Often, for validation messages, the validation message contains |
| * the name of a class. But, sometimes, the validation message is |
| * being generated because a class is null when it shouldn't be. |
| * This method is a helper method which makes the construction of |
| * the validation message a little less cluttered (i.e., instead |
| * of checking if the class is null before constructing the |
| * message, just call this method.) |
| */ |
| public static final String getQualifiedName(JavaHelpers helper) { |
| if(helper == null) { |
| return ""; //$NON-NLS-1$ |
| } |
| return helper.getJavaName(); |
| } |
| |
| /** |
| * Return the method's parameters in a displayable format. e.g., if |
| * the method signature is "public Integer foo(String a, String b, String c)" |
| * then this method returns "String, String, String". |
| */ |
| public static final String getParmsAsString(Method method) { |
| if(method == null) { |
| return ""; //$NON-NLS-1$ |
| } |
| |
| return getParmsAsString(method.listParametersWithoutReturn()); |
| } |
| |
| /** |
| * Return the parameters in a displayable format. |
| * @see getParmsAsString(Method) |
| */ |
| public static final String getParmsAsString(JavaParameter[] parm) { |
| if(parm.length == 0) { |
| return ""; //$NON-NLS-1$ |
| } |
| |
| StringBuffer buffer = new StringBuffer(); |
| for(int i=0; i<parm.length; i++) { |
| JavaHelpers type = parm[i].getJavaType(); |
| buffer.append(((type == null) ? "null" : type.getJavaName())); //$NON-NLS-1$ |
| buffer.append(COMMA); |
| } |
| return buffer.substring(0, buffer.length() - 2); // since "COMMA" is 2 char long, and the last COMMA isn't needed at the end, return everything up to but excluding the last COMMA |
| } |
| |
| /** |
| * Return the parameters in a displayable format. |
| * @see getParmsAsString(Method) |
| */ |
| public static final String getParmsAsString(JavaHelpers[] parm) { |
| if(parm.length == 0) { |
| return ""; //$NON-NLS-1$ |
| } |
| |
| StringBuffer buffer = new StringBuffer(); |
| for(int i=0; i<parm.length; i++) { |
| JavaHelpers type = parm[i]; |
| buffer.append(((type == null) ? "null" : type.getJavaName())); //$NON-NLS-1$ |
| buffer.append(COMMA); |
| } |
| return buffer.substring(0, buffer.length() - 2); // since "COMMA" is 2 char long, and the last COMMA isn't needed at the end, return everything up to but excluding the last COMMA |
| } |
| |
| /** |
| * Returns the name of the type, e.g. "com.ibm.foo.MyFoo" |
| * If the type is an array, the array type will be returned. |
| * e.g. if the type is java.lang.String[], java.lang.String[] will |
| * be returned, not the java.lang.String type. |
| */ |
| public static final JavaHelpers getType(EClassifier classifier) { |
| if(classifier == null) { |
| return null; |
| } |
| |
| JavaHelpers type = ((JavaHelpers)classifier); |
| |
| return type; |
| } |
| |
| /** |
| * javaClassName must be fully qualified |
| */ |
| public static JavaHelpers getType(String javaClassName, EnterpriseBean ejb) throws InvalidInputException { |
| if ((javaClassName == null) || (javaClassName.equals("") || (ejb == null))) //$NON-NLS-1$ |
| throw new InvalidInputException(); |
| |
| Resource resource = ejb.eResource(); |
| if (resource == null) { |
| throw new InvalidInputException(); |
| } |
| |
| JavaHelpers helper = null; |
| if(commonClassNames == null) { |
| initializeCommonClassNames(); |
| } |
| if (commonClassNames.contains(javaClassName)) { |
| ResourceSet rSet = resource.getResourceSet(); |
| IProject project = null; |
| if (rSet instanceof ProjectResourceSet){ |
| project = ((ProjectResourceSet) rSet).getProject(); |
| } |
| |
| //helperMap = getHelperMap(rSet); |
| //Object obj = getHelperMap(rSet).get(javaClassName); |
| Object obj = getHelperMap(project).get(javaClassName); |
| if (obj != null) |
| return (JavaHelpers) obj; |
| else { |
| helper = getType(javaClassName,rSet); |
| //getHelperMap(rSet).put(javaClassName, helper); |
| getHelperMap(project).put(javaClassName, helper); |
| } |
| } else |
| helper = getType(javaClassName, resource.getResourceSet()); |
| return helper; |
| } |
| |
| protected static HashMap getHelperMap(IProject project){ |
| HashMap mapHelper = (HashMap)projectHelperMap.get( project ); |
| if( mapHelper == null ){ |
| mapHelper = new HashMap(); |
| projectHelperMap.put(project, mapHelper); |
| } |
| helperMap = mapHelper; |
| return mapHelper; |
| } |
| |
| private synchronized static void initializeCommonClassNames() { |
| if (commonClassNames != null) return; |
| HashSet names = new HashSet(); |
| names.add(ITypeConstants.CLASSNAME_JAVA_IO_IOEXCEPTION); |
| names.add(ITypeConstants.CLASSNAME_JAVA_IO_SERIALIZABLE); |
| names.add(ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT); |
| names.add(ITypeConstants.CLASSNAME_JAVA_LANG_EXCEPTION); |
| names.add(ITypeConstants.CLASSNAME_JAVA_LANG_RUNTIMEEXCEPTION); |
| names.add(ITypeConstants.CLASSNAME_JAVA_RMI_REMOTE); |
| names.add(ITypeConstants.CLASSNAME_JAVA_RMI_REMOTEEXCEPTION); |
| names.add(ITypeConstants.CLASSNAME_JAVA_UTIL_COLLECTION); |
| names.add(ITypeConstants.CLASSNAME_JAVA_UTIL_ENUMERATION); |
| names.add(ITypeConstants.CLASSNAME_JAVA_UTIL_SET); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_CREATEEXCEPTION); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_ENTITYBEAN); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBEXCEPTION); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBHOME); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBLOCALHOME); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBOBJECT); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBLOCALOBJECT); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_ENTITYCONTEXT); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_FINDEREXCEPTION); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_MESSAGEDRIVENBEAN); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_OBJECTNOTFOUNDEXCEPTION); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_SESSIONBEAN); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_SESSIONCONTEXT); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_EJB_SESSIONSYNCHRONIZATION); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_JMS_MESSAGE); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_JMS_MESSAGELISTENER); |
| names.add(ITypeConstants.CLASSNAME_JAVAX_TRANSACTION_USERTRANSACTION); |
| commonClassNames = names; |
| } |
| |
| /** |
| * javaClassName must be fully qualified |
| */ |
| public static JavaHelpers getType(String javaClassName, ResourceSet resourceSet) throws InvalidInputException { |
| return getType(javaClassName, resourceSet, true); |
| } |
| |
| /** |
| * javaClassName must be fully qualified |
| */ |
| public static JavaHelpers getType(String javaClassName, ResourceSet resourceSet, boolean throwExcIfNotValid) throws InvalidInputException { |
| if((javaClassName == null) || (javaClassName.equals("") || (resourceSet == null))) { //$NON-NLS-1$ |
| Logger aLogger = getMsgLogger(); |
| if(aLogger.isLoggingLevel(Level.FINEST)) { |
| LogEntry entry = getLogEntry(); |
| entry.setSourceID("ValidationRuleUtility.getType(String, ResourceSet, boolean)"); //$NON-NLS-1$ |
| String text = EARValidationMessageResourceHandler.ValidationRuleUtility_invalid_parameter_javaClassName_; |
| //entry.setText("invalid parameter; javaClassName = {0} and resourceSet = {1}"); //$NON-NLS-1$ |
| //entry.setTokens(new String[]{javaClassName, String.valueOf(resourceSet)}); |
| String result = MessageFormat.format(text, |
| new Object[]{javaClassName, String.valueOf(resourceSet)}); |
| entry.setText(result); |
| |
| entry.appendStackTrace(); |
| aLogger.write(Level.FINEST, entry); |
| } |
| throw new InvalidInputException(); |
| } |
| |
| // If the class doesn't exist, it will be reflected |
| JavaHelpers helper = JavaRefFactory.eINSTANCE.reflectType(javaClassName, resourceSet); |
| if(throwExcIfNotValid) { |
| isValidType(helper); // check that the type has been reflected properly |
| } |
| |
| return helper; |
| } |
| |
| /** |
| * @return |
| */ |
| private static LogEntry getLogEntry() { |
| if(logEntry == null) { |
| logEntry = new LogEntry(IEJBValidatorConstants.BUNDLE_NAME); |
| } |
| logEntry.reset(); // reset the values so that we're not logging stale data |
| return logEntry; |
| } |
| |
| /** |
| * @return |
| */ |
| private static Logger getMsgLogger() { |
| if(logger == null) |
| logger = J2EECorePlugin.getPlugin().getMsgLogger(); |
| return logger; |
| } |
| |
| public static final JavaHelpers getType(Field field) { |
| if(field == null) { |
| return null; |
| } |
| |
| return (JavaHelpers)field.getEType(); |
| } |
| |
| /** |
| * Return true if the JavaClass passed in has the Method defined |
| * on it. Return false if the Method is defined on a supertype or |
| * is not defined on the class at all. |
| */ |
| public static final boolean onClass(JavaClass clazz, Method method) { |
| if((clazz == null) || (method == null)) { |
| return false; |
| } |
| |
| return clazz.equals(method.getJavaClass()); |
| } |
| |
| /** |
| * Return true if the JavaClass passed in has the Field defined |
| * on it. Return false if the Field is defined on a supertype or |
| * is not defined on the class at all. |
| */ |
| public static final boolean onClass(JavaClass clazz, Field field) { |
| if((clazz == null) || (field == null)) { |
| return false; |
| } |
| |
| return clazz.equals(field.getJavaClass()); |
| } |
| |
| public static final boolean isApplicationException(JavaClass exception, EnterpriseBean bean) { |
| if(exception == null) { |
| return false; |
| } |
| |
| // Exempt EJBException from the application exception check because it'll drive users crazy to see |
| // it flagged as an application exception. |
| try { |
| if(ValidationRuleUtility.isSameType(exception, getType(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBEXCEPTION, bean))) { |
| return false; |
| } |
| } |
| catch(InvalidInputException e) { |
| // logged in getType() |
| // if EJBException can't be found, then there's probably a system JAR missing |
| } |
| |
| // 18.1.1 Application exceptions |
| // An application exception is an exception defined in the throws clause of a method of the enterprise |
| // Bean's home and component interfaces, other than the java.rmi.RemoteException. |
| return !isRemoteException(exception, bean); |
| } |
| |
| public static final boolean isRemoteMethod(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) { |
| try { |
| JavaHelpers javaRmiRemote = ValidationRuleUtility.getType(ITypeConstants.CLASSNAME_JAVA_RMI_REMOTE, bean); |
| if(isAssignableFrom(clazz, javaRmiRemote)) { |
| return true; |
| } |
| } |
| catch(InvalidInputException e) { |
| return false; |
| } |
| |
| return false; |
| } |
| |
| public static final boolean isReservedWord(String name) { |
| if(name == null) { |
| return false; |
| } |
| |
| String upperName = name.toUpperCase(); |
| for(int i=0; i<_reservedWords.length; i++) { |
| if(upperName.equals(_reservedWords[i])) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public static final boolean isRuntimeException(JavaClass clazz, EnterpriseBean bean) { |
| if(clazz == null) { |
| return false; |
| } |
| |
| try { |
| JavaHelpers runtimeExc = getType(ITypeConstants.CLASSNAME_JAVA_LANG_RUNTIMEEXCEPTION, bean); |
| return isException(clazz, runtimeExc.getWrapper()); |
| } |
| catch(InvalidInputException e) { |
| return false; |
| } |
| } |
| |
| public static final boolean isRemoteException(JavaClass clazz, EnterpriseBean bean) { |
| if(clazz == null) { |
| return false; |
| } |
| |
| try { |
| JavaHelpers remoteExc = getType(ITypeConstants.CLASSNAME_JAVA_RMI_REMOTEEXCEPTION, bean); |
| return isException(clazz, remoteExc.getWrapper()); |
| } |
| catch(InvalidInputException e) { |
| return false; |
| } |
| } |
| |
| /** |
| * Return true if the clazz is an instance of the exception. |
| */ |
| public static final boolean isException(JavaClass clazz, JavaClass exception) { |
| if((clazz == null) || (exception == null)) { |
| return false; |
| } |
| |
| return isAssignableFrom(clazz, exception); |
| } |
| |
| /** |
| * Return true if the type is either java.util.Collection, or a type which inherits/extends java.util.Collection. |
| * The bean is needed to retrieve the java.util.Collection type. |
| */ |
| public static boolean isAssignableFromCollection(JavaHelpers type, EnterpriseBean bean) throws InvalidInputException { |
| JavaHelpers javaUtilCollection = getType(ITypeConstants.CLASSNAME_JAVA_UTIL_COLLECTION, bean); |
| return isAssignableFrom(type, javaUtilCollection); |
| } |
| |
| /** |
| * Return true if the type is either java.util.Enumeration, or a type which inherits/extends java.util.Enumeration. |
| * The bean is needed to retrieve the java.util.Enumeration type. |
| */ |
| public static boolean isAssignableFromEnumeration(JavaHelpers type, EnterpriseBean bean) throws InvalidInputException { |
| JavaHelpers javaUtilEnumeration = getType(ITypeConstants.CLASSNAME_JAVA_UTIL_ENUMERATION, bean); |
| return isAssignableFrom(type, javaUtilEnumeration); |
| } |
| |
| /** |
| * Return true if the type is either java.util.Set, or a type which inherits/extends java.util.Set. |
| * The bean is needed to retrieve the java.util.Set type. |
| */ |
| public static boolean isAssignableFromSet(JavaHelpers type, EnterpriseBean bean) throws InvalidInputException { |
| JavaHelpers javaUtilSet = getType(ITypeConstants.CLASSNAME_JAVA_UTIL_SET, bean); |
| return isAssignableFrom(type, javaUtilSet); |
| } |
| |
| /** |
| * Returns true if the type is either the compare type, or inherits/extends the compare type. |
| */ |
| public static boolean isAssignableFrom(JavaHelpers type, JavaHelpers compareType) { |
| if((type == null) || (compareType == null)) { |
| return false; |
| } |
| |
| if(type.isPrimitive() || compareType.isPrimitive()) { |
| if(type.isPrimitive() && compareType.isPrimitive()) { |
| return type.getPrimitive().equals(compareType.getPrimitive()); |
| } |
| return false; |
| } |
| else if(type.isArray() && compareType.isArray()) { |
| JavaClass classType = type.getWrapper(); |
| JavaClass classCompareType = compareType.getWrapper(); |
| if((classType == null)) { |
| return false; |
| } |
| JavaHelpers finalType = ((ArrayType)classType).getFinalComponentType(); |
| JavaHelpers finalCompareType = ((ArrayType)classCompareType).getFinalComponentType(); |
| return isAssignableFrom(finalType, finalCompareType); |
| } |
| else { |
| return compareType.getWrapper().isAssignableFrom(type.getWrapper()); |
| } |
| } |
| |
| /** |
| * Returns the JavaClass for the JavaHelper type |
| */ |
| public static JavaClass getJavaClass(JavaHelpers type) { |
| if (type == null) { |
| return null; |
| } |
| |
| if (!type.isPrimitive()) { |
| if(type.isArray()) { |
| JavaClass classType = type.getWrapper(); |
| if (classType == null) { |
| return null; |
| } |
| JavaHelpers finalType = ((ArrayType)classType).getFinalComponentType(); |
| return getJavaClass(finalType); |
| } |
| else { |
| return type.getWrapper(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Return true if the given method is associated with a query element in ejb-jar.xml. |
| */ |
| public static final boolean isAssociatedWithQuery(ContainerManagedEntity cmp, Method method) { |
| // Check method is associated with a query element in ejb-jar.xml. |
| List queries = cmp.getQueries(); |
| Iterator iterator = queries.iterator(); |
| boolean found = false; |
| while(iterator.hasNext()) { |
| Query query = (Query)iterator.next(); |
| QueryMethod queryMethod = query.getQueryMethod(); |
| if(queryMethod == null) { |
| // Let the EJBJarVRule report this |
| continue; |
| } |
| |
| if((queryMethod.getName() == null) || queryMethod.getName().equals("")) { //$NON-NLS-1$ |
| // Let the EJBJarVRule report this |
| continue; |
| } |
| |
| if(queryMethod.getName().equals(method.getName())) { |
| found = true; |
| break; |
| } |
| } |
| |
| return found; |
| } |
| |
| public static final boolean isBeanManagedSession(EnterpriseBean bean) { |
| if(bean == null) { |
| return false; |
| } |
| |
| if(bean.isEntity()) { |
| return false; |
| } |
| |
| return (((Session)bean).getTransactionType().getValue() == TransactionType.BEAN); |
| } |
| |
| /** |
| * Return true if this method is the static initializer used for interfaces ("<clinit>") |
| */ |
| public static boolean isClinitMethod(EnterpriseBean bean, Method method) { |
| if (method == null) { |
| return false; |
| } |
| |
| return method.getName().equals("<clinit>"); //$NON-NLS-1$ |
| } |
| |
| public static final boolean isJNDINamingContext(Field field) { |
| return true; |
| } |
| |
| /** |
| * Return true if the field is defined on java.lang.Object. |
| */ |
| public static boolean isJavaLangObjectField(EnterpriseBean bean, Field field) { |
| return isSameType(bean, field.getContainingJavaClass(), ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT); |
| } |
| |
| /** |
| * Return true if the method is defined on named class. |
| */ |
| public static boolean isOwnedBy(EnterpriseBean bean, Method method, String className) { |
| return isSameType(bean, method.getContainingJavaClass(), className); |
| } |
| |
| /** |
| * Return true if given class is the same as the named class. |
| */ |
| public static boolean isSameType(EnterpriseBean bean, JavaClass owner, String className) { |
| try { |
| JavaHelpers helper = getType(className, bean); |
| if(helper == null) { |
| return false; |
| } |
| |
| JavaClass object = helper.getWrapper(); |
| |
| return isSameType(owner, object); |
| } |
| catch(InvalidInputException e) { |
| return false; |
| } |
| } |
| |
| /** |
| * Return true if given class is the same as the named class. |
| */ |
| public static boolean isSameType(JavaHelpers owner, JavaHelpers object) { |
| if(owner == null) { |
| return false; |
| } |
| |
| if(object == null) { |
| return false; |
| } |
| |
| if(owner.isPrimitive() && object.isPrimitive()) { |
| // Both are JavaDataType |
| return owner.getPrimitive().equals(object.getPrimitive()); |
| } |
| else if(owner.isArray() && object.isArray()) { |
| // Both are ArrayType |
| ArrayType ownerArray = (ArrayType)owner; |
| ArrayType objectArray = (ArrayType)object; |
| return isSameType(ownerArray.getFinalComponentType(), objectArray.getFinalComponentType()); |
| } |
| else if((owner.getWrapper() != null) && (object.getWrapper() != null)) { |
| // Both are JavaClass |
| return owner.getWrapper().equals(object.getWrapper()); |
| } |
| else { |
| // mismatching JavaHelpers type |
| return false; |
| } |
| } |
| |
| /** |
| * Return true if the method is defined on java.lang.Object. |
| */ |
| public static boolean isJavaLangObjectMethod(EnterpriseBean bean, Method method) { |
| return isSameType(bean, method.getContainingJavaClass(), ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT); |
| } |
| |
| public static final boolean isLegalRMI_IIOPInheritance(JavaClass clazz) { |
| return true; |
| } |
| |
| public static final boolean isLegalRMI_IIOPType(EnterpriseBean bean, JavaHelpers helper) throws InvalidInputException { |
| if(helper == null) { |
| return false; |
| } |
| |
| return isSerializable(helper, bean); |
| } |
| |
| public static final boolean isLocalType(EnterpriseBean bean, JavaHelpers type) { |
| try { |
| if(isSameType(type, getType(ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT, bean))) { |
| // If there's an undefined primary key (java.lang.Object), don't flag it as a local type. |
| return false; |
| } |
| } |
| catch(InvalidInputException e) { |
| // Let the DD validation report this. |
| return false; |
| } |
| |
| if(isAssignableFrom(bean.getLocalInterface(), type)) { |
| return true; |
| } |
| |
| if(isAssignableFrom(bean.getLocalHomeInterface(), type)) { |
| return true; |
| } |
| |
| // Bit of a performance hack here. |
| // Don't want to load and parse the entire EJBJar just to check if |
| // this type is local, so assume that if the extends |
| // javax.ejb.EJBLocalHome or javax.ejb.EJBLocalObject, then it's local. |
| try { |
| JavaHelpers ejbLocalHome = getType(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBLOCALHOME, bean); |
| if(isAssignableFrom(ejbLocalHome, type)) { |
| return true; |
| } |
| } |
| catch(InvalidInputException exc) { |
| // ignore and try other type |
| } |
| |
| try { |
| JavaHelpers ejbLocalObject = getType(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBLOCALOBJECT, bean); |
| if(isAssignableFrom(ejbLocalObject, type)) { |
| return true; |
| } |
| } |
| catch(InvalidInputException exc) { |
| // ignore |
| } |
| |
| return false; |
| } |
| |
| |
| |
| public static final boolean usesUnknownPrimaryKey(EnterpriseBean bean) { |
| if(bean.isContainerManagedEntity()) { |
| return usesUnknownPrimaryKey((ContainerManagedEntity)bean); |
| } |
| return false; |
| } |
| |
| public static final boolean usesUnknownPrimaryKey(ContainerManagedEntity cmp) { |
| if(cmp == null) { |
| return false; |
| } |
| |
| try { |
| if(isSameType(cmp.getPrimaryKey(), getType(ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT, cmp))) { |
| return true; |
| } |
| } |
| catch(InvalidInputException e) { |
| // If java.lang.Object can't be found, there's bigger problems than validating |
| // it mistakenly |
| return false; |
| } |
| |
| if(cmp.getVersionID() == J2EEVersionConstants.EJB_2_0_ID) { |
| List cmpFields = cmp.getFilteredFeatures(LocalModelledPersistentAttributeFilter.singleton()); |
| if(cmpFields != null && !cmpFields.isEmpty()) { |
| Iterator iterator = cmpFields.iterator(); |
| while(iterator.hasNext()) { |
| CMPAttribute attrib = (CMPAttribute)iterator.next(); |
| if(isUnknownPrimaryKey(attrib)) { |
| return true; |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| public static final boolean isUnidirectionalRelationship(IEJBValidationContext vc, EJBRelationshipRole role) { |
| // Page 131 of EJB 2.0: |
| // A unidirectional relationship is implemented with a cmr-field on the entity bean instance from which |
| // navigation can take place, and no related cmr-field on the entity bean instance that is the target of the |
| // relationship. Unidirectional relationships are typically used when the Bean Provider wishes to restrict |
| // the visibility of a relationship. |
| Entity sourceEntity = role.getSource().getEntityBean(); |
| if(sourceEntity == null) { |
| return false; |
| } |
| |
| if(!sourceEntity.isContainerManagedEntity()) { |
| return false; |
| } |
| |
| CMRField sourceCMRField = role.getCmrField(); |
| if(sourceCMRField == null) { |
| return false; |
| } |
| |
| EJBRelationshipRole opposite = role.getOpposite(); |
| if(opposite == null) { |
| return false; |
| } |
| |
| CMRField oppositeCMRField = opposite.getCmrField(); |
| if(oppositeCMRField != null) { |
| return false; |
| } |
| |
| return true; |
| |
| } |
| |
| |
| |
| public static final boolean isUnknownPrimaryKey(CMPAttribute attrib) { |
| if(attrib == null) { |
| return false; |
| } |
| |
| // Section 10.8.3 |
| // By definition, the deployer's generated CMP field's name is defined in the |
| // ContainerManagedEntity.WAS_GENERATED_STRING_FIELD constant. |
| return ContainerManagedEntity.WAS_GENERATED_STRING_FIELD.equals(attrib.getName()); |
| } |
| |
| public static final boolean isPrimitivePrimaryKey(ContainerManagedEntity cmp) { |
| if(cmp == null) { |
| return false; |
| } |
| |
| if((cmp.getPrimKeyField() != null) && !cmp.getPrimKeyField().eIsProxy()) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| public static final boolean isPublic(Field field) { |
| if ( field == null ) |
| return false; |
| |
| return (JavaVisibilityKind.PUBLIC_LITERAL == field.getJavaVisibility()); |
| } |
| |
| public static final boolean isPublic( Method method ) { |
| if ( method == null ) |
| return false; |
| |
| return (JavaVisibilityKind.PUBLIC_LITERAL == method.getJavaVisibility()); |
| } |
| |
| /** |
| * Verifies that a given Class type is serializable. |
| * |
| * RMI 1.3 specification |
| * 2.6 Parameter Passing in Remote Method Invocation |
| * An argument to, or a return value from, a remote object can be any object that |
| * is serializable. This includes primitive types, remote objects, and non-remote |
| * objects that implement the java.io.Serializable interface. |
| */ |
| public static final boolean isSerializable(JavaHelpers cl, EnterpriseBean bean) throws InvalidInputException { |
| if(cl == null) { |
| // assume it's void |
| return true; |
| } |
| |
| // Check if the type reflected properly |
| isValidType(cl); |
| |
| if ( cl.isPrimitive() ) { |
| // JavaHelpers is a JavaDataType |
| return true; |
| } |
| else if(cl.isArray()) { |
| ArrayType array = (ArrayType)cl; |
| if(array.isPrimitiveArray()) { |
| return true; |
| } |
| // else, not primitive, so check its contents |
| cl = array.getFinalComponentType(); |
| } |
| |
| JavaHelpers remote = getType(ITypeConstants.CLASSNAME_JAVA_RMI_REMOTE, bean); |
| if(isAssignableFrom(cl, remote)) { |
| return true; |
| } |
| |
| JavaHelpers serial = getType(ITypeConstants.CLASSNAME_JAVA_IO_SERIALIZABLE, bean); |
| return isAssignableFrom(cl, serial); |
| } |
| |
| public static final boolean isStateful(EnterpriseBean bean) { |
| if(bean == null) { |
| return false; |
| } |
| |
| if(bean.isEntity()) { |
| return false; |
| } |
| |
| return (((Session)bean).getSessionType().getValue() == SessionType.STATEFUL); |
| } |
| |
| public static final boolean isStateless(EnterpriseBean bean) { |
| if(bean == null) { |
| return false; |
| } |
| |
| if(bean.isEntity()) { |
| return false; |
| } |
| |
| return (((Session)bean).getSessionType().getValue() == SessionType.STATELESS); |
| } |
| |
| public static boolean isUnnamedPackage(JavaPackage pkg) { |
| if(pkg == null) { |
| return true; |
| } |
| |
| String pkgName = pkg.getName(); |
| return ((pkgName == null) || (pkgName.equals(""))); //$NON-NLS-1$ |
| } |
| |
| public static final boolean isValidJavaIdentifier(String name) { |
| if(name == null) { |
| return false; |
| } |
| |
| char[] nameChar = name.toCharArray(); |
| if(nameChar.length < 1) { |
| return false; |
| } |
| |
| if(!Character.isJavaIdentifierStart(nameChar[0])) { |
| return false; |
| } |
| boolean isValidJavaIdentifier = true; |
| for(int i=1; i<nameChar.length; i++) { |
| if(!Character.isJavaIdentifierPart(nameChar[i])) { |
| isValidJavaIdentifier = false; |
| break; |
| } |
| } |
| return isValidJavaIdentifier; |
| } |
| |
| /** |
| * 6.5.3 The optional SessionSynchronization interface |
| *... |
| * Only a stateful Session bean with container-managed transaction demarcation may |
| * implement the SessionSynchronization interface. |
| *... |
| * There is no need for a Session bean with bean-managed transaction to rely on the |
| * synchronization call backs because the bean is in control of the commit the bean |
| * knows when the transaction is about to be committed and it knows the outcome of the |
| * transaction commit. |
| *... |
| */ |
| public static final boolean isValidSessionTypeElement(Session session) { |
| if(session == null) { |
| return false; |
| } |
| |
| // check syntax |
| if(!session.isSetSessionType()) { |
| return false; |
| } |
| |
| if(session.getSessionType() == null) { |
| return false; |
| } |
| |
| if(session.getSessionType().getValue() == SessionType.STATEFUL) { |
| return true; |
| } |
| |
| if(session.getSessionType().getValue() == SessionType.STATELESS) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| public static final boolean isValidTransactionTypeElement(Session sessionBean) { |
| if(sessionBean == null) { |
| return false; |
| } |
| |
| if(!sessionBean.isSetTransactionType()) { |
| return false; |
| } |
| |
| if(sessionBean.getTransactionType() == null) { |
| return false; |
| } |
| |
| if(sessionBean.getTransactionType().getValue() == TransactionType.BEAN) { |
| return true; |
| } |
| |
| if(sessionBean.getTransactionType().getValue() == TransactionType.CONTAINER) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** |
| * If the type is not reflected properly, throw an InvalidInputException. |
| */ |
| public static final void isValidType(JavaHelpers type) throws InvalidInputException { |
| if(type == null) { |
| // Cheating here. Should technically access the MsgLogger from the IEJBValidationContext |
| // type, but when I started changing this method and the isValidTypeHierarchy method, |
| // I ended up changing 42 files because these two methods are called directly or |
| // indirectly from almost everywhere. That was too much change, so I cheated. |
| Logger aLogger = getMsgLogger(); |
| if(aLogger.isLoggingLevel(Level.FINEST)) { |
| LogEntry entry = getLogEntry(); |
| entry.setSourceID("ValidationRuleUtility.isValidType"); //$NON-NLS-1$ |
| entry.setText("type is null"); //$NON-NLS-1$ |
| entry.appendStackTrace(); |
| aLogger.write(Level.FINEST, entry); |
| } |
| throw new InvalidInputException(); |
| } |
| |
| if(type.getWrapper() != null) { |
| // check if the type reflected properly. If there's any compile errors, or references to unresolved |
| // classes, can output some mistaken error messages. |
| // e.g. class is not serializable |
| JavaClass wrapper = type.getWrapper(); |
| if(type.isArray()) { |
| ArrayType array = (ArrayType)type; |
| isValidType(array.getFinalComponentType()); |
| } |
| else { |
| if(!wrapper.isExistingType()) { |
| Logger aLogger = getMsgLogger(); |
| if(aLogger.isLoggingLevel(Level.FINEST)) { |
| LogEntry entry = getLogEntry(); |
| entry.setSourceID("ValidationRuleUtility.isValidType"); //$NON-NLS-1$ |
| entry.setText("!wrapper.isExistingType(); type is " + wrapper.getJavaName()); //$NON-NLS-1$ |
| aLogger.write(Level.FINEST, entry); |
| } |
| throw new InvalidInputException(wrapper); |
| } |
| } |
| } |
| } |
| |
| /** |
| * If the type is not reflected properly, throw an InvalidInputException. |
| * This method, unlike isValidType, also checks every interface and class |
| * parent of the passed-in type. |
| */ |
| public static final void isValidTypeHierarchy(EnterpriseBean bean, JavaHelpers type) throws InvalidInputException { |
| if(type == null) { |
| // Cheating here. Should technically access the MsgLogger from the IEJBValidationContext |
| // type, but when I started changing this method and the isValidType method, |
| // I ended up changing 42 files because these two methods are called directly or |
| // indirectly from almost everywhere. That was too much change, so I cheated. |
| Logger aLogger = getMsgLogger(); |
| if(aLogger.isLoggingLevel(Level.FINEST)) { |
| LogEntry entry = getLogEntry(); |
| entry.setSourceID("ValidationRuleUtility.isValidTypeHierarchy"); //$NON-NLS-1$ |
| entry.setText("type is null"); //$NON-NLS-1$ |
| entry.appendStackTrace(); |
| aLogger.write(Level.FINEST, entry); |
| } |
| throw new InvalidInputException(); |
| } |
| |
| // First, check this helper itself. |
| isValidType(type); |
| JavaHelpers javaLangObject = getType(ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT, bean); |
| if(isSameType(type, javaLangObject)) { |
| return; |
| } |
| |
| // If this helper exists, and is not java.lang.Object, then check every supertype. |
| JavaClass classType = type.getWrapper(); |
| if(classType == null) { |
| Logger aLogger = getMsgLogger(); |
| if(aLogger.isLoggingLevel(Level.FINEST)) { |
| LogEntry entry = getLogEntry(); |
| entry.setSourceID("ValidationRuleUtility.isValidTypeHierarchy"); //$NON-NLS-1$ |
| entry.setText("type.getWrapper() returns null; type is " + type.getJavaName()); //$NON-NLS-1$ |
| aLogger.write(Level.FINEST, entry); |
| } |
| throw new InvalidInputException(); |
| } |
| |
| // Check the superclass. Since type is not java.lang.Object, there is at least |
| // the java.lang.Object superclass. |
| if(!classType.isInterface()) { |
| JavaClass superType = classType.getSupertype(); |
| isValidTypeHierarchy(bean, superType); |
| } |
| |
| // Check the superinterfaces, if they exist. |
| List superInterfaces = classType.getImplementsInterfaces(); |
| if(superInterfaces != null) { |
| Iterator iterator = superInterfaces.iterator(); |
| while(iterator.hasNext()) { |
| JavaClass superIntf = (JavaClass)iterator.next(); |
| isValidTypeHierarchy(bean, superIntf); |
| } |
| } |
| } |
| |
| /** |
| * RMI 1.3 page 6 section 2.4.1, |
| * A remote method declaration must include the exception java.rmi.RemoteException (or one |
| * of its upserclasses such as java.io.IOException or java.lang.Exception) in its throws |
| * clause, in addition to any application-specific exceptions (note that application |
| * specific exceptions do not have to extend java.rmi.RemoteException). |
| */ |
| public static final boolean throwsRemoteExceptionOrParent(EnterpriseBean bean, Method method) throws InvalidInputException { |
| return throwsExceptionOrParent(bean, method, ITypeConstants.CLASSNAME_JAVA_RMI_REMOTEEXCEPTION); |
| } |
| |
| /** |
| * Convenience method which checks if RemoteException (exactly, not Exception or IOException) |
| * is in the method signature. |
| */ |
| public static final boolean doesNotThrowRemoteException(EnterpriseBean bean, Method method) throws InvalidInputException { |
| return !throwsException(bean, method, ITypeConstants.CLASSNAME_JAVA_RMI_REMOTEEXCEPTION); |
| } |
| |
| public static final boolean throwsObjectNotFoundException(EnterpriseBean bean, Method method) throws InvalidInputException { |
| return throwsException(bean, method, ITypeConstants.CLASSNAME_JAVAX_EJB_OBJECTNOTFOUNDEXCEPTION); |
| } |
| |
| public static final boolean throwsFinderException(EnterpriseBean bean, Method method) throws InvalidInputException { |
| return throwsException(bean, method, ITypeConstants.CLASSNAME_JAVAX_EJB_FINDEREXCEPTION); |
| } |
| |
| public static final boolean throwsCreateException(EnterpriseBean bean, Method method) throws InvalidInputException { |
| return throwsException(bean, method, ITypeConstants.CLASSNAME_JAVAX_EJB_CREATEEXCEPTION); |
| } |
| |
| public static final boolean throwsApplicationException(Method method, EnterpriseBean bean) { |
| List exceptions = method.getJavaExceptions(); |
| if(exceptions.size() == 0) { |
| return false; |
| } |
| |
| // CHKJ2419 = {0} must be a subclass of java.lang.Exception. Read section 18.1.1, 18.2.1 of the EJB 2.0 specification. |
| Iterator iterator = exceptions.iterator(); |
| while(iterator.hasNext()) { |
| JavaClass exception = (JavaClass)iterator.next(); |
| |
| if(isApplicationException(exception, bean)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Return true if the given method throws the named exception or a class which extends the named exception. |
| */ |
| public static final boolean throwsException(EnterpriseBean bean, Method method, String exceptionName) throws InvalidInputException { |
| if(method == null) { |
| return false; |
| } |
| |
| List exceptions = method.getJavaExceptions(); |
| Iterator iterator = exceptions.iterator(); |
| JavaClass exception = getType(exceptionName, bean).getWrapper(); |
| while(iterator.hasNext()) { |
| JavaClass exc = (JavaClass)iterator.next(); |
| if(isAssignableFrom(exc, exception)) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Return true if the method returns the named exception, an exception which extends the named exception, or one of the parents of the named exception (e.g. java.lang.Exception). |
| * Use this method if it needs to be detected that an exception can be thrown either directly or through something generic like java.lang.Exception. |
| */ |
| public static final boolean throwsExceptionOrParent(EnterpriseBean bean, Method method, String exceptionName) throws InvalidInputException { |
| if(method == null) { |
| return false; |
| } |
| |
| JavaClass exception = getType(exceptionName, bean).getWrapper(); |
| |
| List exceptions = method.getJavaExceptions(); |
| Iterator iterator = exceptions.iterator(); |
| while(iterator.hasNext()) { |
| JavaClass exc = (JavaClass)iterator.next(); |
| if(isAssignableFrom(exc, exception)) { |
| // Assignable from the named exception, e.g. RemoteException or a child of RemoteException |
| return true; |
| } |
| |
| if(isAssignableFrom(exception, exc)) { |
| // The named exception is assignable from the method exception, e.g. java.lang.Exception |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| public static final boolean usesCollectionClass(EnterpriseBean bean, Method method) { |
| if((bean == null) || (method == null)) { |
| return false; |
| } |
| |
| JavaParameter[] parms = method.listParametersWithoutReturn(); |
| if(parms != null) { |
| for(int i=0; i<parms.length; i++) { |
| JavaParameter parm = parms[i]; |
| try { |
| if(isAssignableFromCollection(parm.getJavaType(), bean)) { |
| return true; |
| } |
| } |
| catch(InvalidInputException e) { |
| // ignore and test next parm |
| continue; |
| } |
| } |
| } |
| |
| // Now check the return type |
| try { |
| if(isAssignableFromCollection(method.getReturnType(), bean)) { |
| return true; |
| } |
| } |
| catch(InvalidInputException e) { |
| // ignore |
| } |
| |
| return false; |
| } |
| |
| public static final boolean usesLocalTypes(EnterpriseBean bean, Method method) { |
| if((bean == null) || (method == null)) { |
| return false; |
| } |
| |
| JavaParameter[] parms = method.listParametersWithoutReturn(); |
| if(parms != null) { |
| for(int i=0; i<parms.length; i++) { |
| JavaParameter parm = parms[i]; |
| if(isLocalType(bean, parm.getJavaType())) { |
| return true; |
| } |
| } |
| } |
| |
| // Now check the return type |
| if(isLocalType(bean, method.getReturnType())) { |
| return true; |
| } |
| |
| return false; |
| } |
| } |
| |