blob: 4a6c197d428a2d391f9439e24ba72bdfdd68eb55 [file] [log] [blame]
/*******************************************************************************
* 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.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import org.eclipse.jem.java.Field;
import org.eclipse.jem.java.JavaClass;
import org.eclipse.jem.java.JavaParameter;
import org.eclipse.jem.java.Method;
import org.eclipse.jem.util.logger.LogEntry;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jst.j2ee.ejb.EnterpriseBean;
import org.eclipse.wst.validation.internal.core.ValidationException;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
/**
* Insert the type's description here.
* Creation date: (1/5/01 11:51:09 AM)
* @author: Administrator
*/
public abstract class AValidateEJB extends AValidationRule {
private List roleMethodNames;
public void reset() {
super.reset();
if(roleMethodNames != null) {
roleMethodNames.clear();
roleMethodNames = null; // in this case, clearing the list isn't enough, because it is legal to have zero role names. Must be null or we'll keep trying to reload the role names just because there are zero role names.
}
}
/**
* Insert the method's description here.
* Creation date: (9/5/2001 12:36:39 PM)
* @return java.util.List
*/
protected List getRoleMethodNames(IEJBValidationContext vc, EnterpriseBean bean) {
try {
if (roleMethodNames == null && bean != null) {
roleMethodNames = getRoleMethodNamesExtended(bean);
}
return roleMethodNames;
}
catch (Throwable exc) {
Logger logger = vc.getMsgLogger();
if (logger != null && logger.isLoggingLevel(Level.FINER)) {
logger.write(Level.FINER, exc);
}
return Collections.EMPTY_LIST;
}
}
protected boolean isEjbRelationshipRoleMethod(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) {
if (method == null)
return false;
List aRoleMethodNames = getRoleMethodNames(vc, bean);
if(aRoleMethodNames != null && !aRoleMethodNames.isEmpty())
return aRoleMethodNames.contains(method.getName());
return false;
}
/**
* Return true if the field can, and should, be validated.
* Filter out faulty fields (i.e., null), and fields which
* belong to the base type, whatever that is. (e.g. java.lang.Object)
*/
protected boolean isValid(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field, List[] fieldsExtendedLists) throws InvalidInputException {
// The following call checks if the type reflected properly
ValidationRuleUtility.isValidType(ValidationRuleUtility.getType(field));
if (field.getName().equals(IMethodAndFieldConstants.FIELDNAME_SERIALVERSIONUID)) {
return false;
}
return true;
}
/**
* Return true if the method can, and should, be validated.
* Filter out faulty methods (i.e., null), and methods which
* belong to the base type, whatever that is. (e.g. java.lang.Object)
*/
protected boolean isValid(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, List[] methodsExtendedList) throws InvalidInputException {
if (method == null) {
throw new InvalidInputException();
}
return true;
}
/**
* This method actually does the validation. Since many of the classes do
* not validate fields now, implement this method as a no-op so that the
* classes compile.
*/
public void primValidate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field) throws InvalidInputException {
//Default
}
/**
* This method actually does the validation.
*/
public abstract void primValidate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method ejbMethod) throws InvalidInputException;
/**
* This method does the actual checking (if ejbMethod exists).
*/
protected abstract void primValidateExistence(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method ejbMethod) throws InvalidInputException;
protected abstract List[] getMethodsExtended(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz);
protected abstract List[] getFieldsExtended(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz);
protected final void reflectionError(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) {
vc.removeMessages(clazz);
IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2907, IEJBValidationContext.ERROR, bean, clazz, new String[]{clazz.getQualifiedName()}, this);
vc.addMessage(message);
}
protected final void reflectionWarning(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field, InvalidInputException e) {
// One of two cases where we care if the type is on this class or not (i.e., not leaving it up to MessageUtility)
String[] msgParm = null;
String javaClassName = (e.getJavaClass() == null) ? "?" : e.getJavaClass().getQualifiedName(); //$NON-NLS-1$
if(ValidationRuleUtility.onClass(clazz, field)) {
msgParm = new String[] {String.valueOf(field.getName()), String.valueOf(javaClassName)};
}
else {
msgParm = new String[] {javaClassName}; // MessageUtility will substitute in the name of the field
}
IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2433, IEJBValidationContext.WARNING, bean, clazz, field, msgParm, this);
vc.addMessage(message);
}
protected final void reflectionWarning(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, InvalidInputException e) {
// One of two cases where we care if the type is on this class or not (i.e., not leaving it up to MessageUtility)
String[] msgParm = null;
String javaClassName = (e.getJavaClass() == null) ? "?" : e.getJavaClass().getQualifiedName(); //$NON-NLS-1$
if(ValidationRuleUtility.onClass(clazz, method)) {
msgParm = new String[] {method.getMethodElementSignature(), javaClassName};
}
else {
msgParm = new String[] {javaClassName}; // MessageUtility will substitute in the name of the field
}
IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2433, IEJBValidationContext.WARNING, bean, clazz, method, msgParm, this);
vc.addMessage(message);
}
public final void validate(IEJBValidationContext vc, Object targetParent, Object target) throws ValidationException {
vc.terminateIfCancelled();
EnterpriseBean bean = (EnterpriseBean)targetParent;
JavaClass clazz = (JavaClass)target;
try {
// check if all of the types in the bean reflected properly
ValidationRuleUtility.isValidTypeHierarchy(bean, clazz);
vc.subtask(IEJBValidatorConstants.STATUS_VALIDATING, new String[]{clazz.getQualifiedName()});
validateClass(vc, bean, clazz);
validateMethods(vc, bean, clazz);
validateFields(vc, bean, clazz);
}
catch(InvalidInputException e) {
reflectionError(vc, bean, clazz);
return;
}
catch(ValidationCancelledException e) {
throw e;
}
}
/**
* This method should be called to avoid validating a Field more
* than once. This is not used for checking the existence of a field.
*/
public final void validate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field, List[] fieldsExtendedList) throws InvalidInputException {
if (isValid(vc, bean, clazz, field, fieldsExtendedList)) {
primValidate(vc, bean, clazz, field);
}
}
/**
* This method should be called to avoid validating a Method more
* than once. This is not used for checking the existence of a method.
*/
public final void validate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method ejbMethod, List[] methodsExtendedList) throws InvalidInputException {
if (isValid(vc, bean, clazz, ejbMethod, methodsExtendedList)) {
primValidate(vc, bean, clazz, ejbMethod);
}
}
/**
* Checks to see if @ejbMethod is one of the required methods.
*/
protected final void validateExistence(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method ejbMethod, List[] methodsExtendedList) throws InvalidInputException {
if (isValid(vc, bean, clazz, ejbMethod, methodsExtendedList)) {
primValidateExistence(vc, bean, clazz, ejbMethod);
}
}
public void validateClass(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) throws InvalidInputException {
//Default
}
public final void validateFields(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) throws ValidationCancelledException, InvalidInputException, ValidationException {
vc.terminateIfCancelled();
// Whenever looping over an entire list, always use an
// iterator instead of a for loop, for performance reasons.
// If the list is an instance of a linked list, for example,
// the get(i) call can take a long time.
List fields = clazz.getFieldsExtended();
Iterator iterator = fields.iterator();
Field field = null;
List[] fieldsExtendedList = getFieldsExtended(vc, bean, clazz);
while (iterator.hasNext()) {
vc.terminateIfCancelled();
field = (Field) iterator.next();
if (field == null) {
Logger logger = vc.getMsgLogger();
if (logger != null && logger.isLoggingLevel(Level.FINEST)) {
LogEntry entry = vc.getLogEntry();
entry.setSourceID("AValidateEJB.validateFields()"); //$NON-NLS-1$
entry.setText("A field is null on " + clazz); //$NON-NLS-1$
logger.write(Level.FINEST, entry);
}
continue;
}
try {
validate(vc, bean, clazz, field, fieldsExtendedList);
}
catch (InvalidInputException e) {
reflectionWarning(vc, bean, clazz, field, e);
}
}
vc.terminateIfCancelled();
}
/**
* Verifies that a given method is RMI legal.
* This means that their argument and return values must be of valid types
* for RMI/IIOP, and their throws clause must include the java.rmi.RemoteException.
*/
public final void validateLegalRMIMethod(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
vc.terminateIfCancelled();
validateLegalRMIMethodWithoutExceptions(vc, bean, clazz, method);
validateLegalRMIMethodExceptions(vc, bean, clazz, method);
}
/**
* Verifies that a given method is RMI legal.
* This means that their argument and return values must be of valid types
* for RMI/IIOP, and their throws clause must include the java.rmi.RemoteException.
*/
public final void validateLegalRMIMethodArguments(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
vc.terminateIfCancelled();
if (method == null) {
return;
}
JavaParameter[] args = method.listParametersWithoutReturn();
for (int i = 0; i < args.length; i++) {
vc.terminateIfCancelled();
if (!ValidationRuleUtility.isLegalRMI_IIOPType(bean, args[i].getJavaType())) {
IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2413, IEJBValidationContext.INFO, bean, clazz, method, new String[]{args[i].getQualifiedName()}, this);
vc.addMessage(message);
}
}
}
/**
* Verifies that a given method is RMI legal.
* This means that their argument and return values must be of valid types
* for RMI/IIOP, and their throws clause must include the java.rmi.RemoteException.
*/
public final void validateLegalRMIMethodExceptions(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
vc.terminateIfCancelled();
if (method == null) {
return;
}
if (!ValidationRuleUtility.throwsRemoteExceptionOrParent(bean, method)) {
IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2414, IEJBValidationContext.ERROR, bean, clazz, method, new String[]{ITypeConstants.CLASSNAME_JAVA_RMI_REMOTEEXCEPTION}, this);
vc.addMessage(message);
}
}
/**
* Verifies that a given method is RMI legal, but doesn't check the exceptions.
* This means that the method's argument and return values must be of valid types
* for RMI/IIOP.
*/
public final void validateLegalRMIMethodReturnType(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
vc.terminateIfCancelled();
if (method == null) {
return;
}
if (!ValidationRuleUtility.isLegalRMI_IIOPType(bean, method.getReturnType())) {
IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2412, IEJBValidationContext.INFO, bean, clazz, method, this);
vc.addMessage(message);
}
}
/**
* Verifies that a given method is RMI legal, but doesn't check the exceptions.
* This means that the method's argument and return values must be of valid types
* for RMI/IIOP.
*/
public final void validateLegalRMIMethodWithoutExceptions(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
vc.terminateIfCancelled();
validateLegalRMIMethodArguments(vc, bean, clazz, method);
validateLegalRMIMethodReturnType(vc, bean, clazz, method);
}
/**
* Final check to see if required methods were detected.
*/
protected abstract void validateMethodExists(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) throws InvalidInputException;
public final void validateMethods(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) throws ValidationCancelledException, InvalidInputException, ValidationException {
vc.terminateIfCancelled();
// Whenever looping over an entire list, always use an
// iterator instead of a for loop, for performance reasons.
// If the list is an instance of a linked list, for example,
// the get(i) call can take a long time.
Method[] ejbMethods = clazz.listMethodExtended();
Method method = null;
List[] methodsExtendedList = getMethodsExtended(vc, bean, clazz);
for(int i=0; i<ejbMethods.length; i++) {
vc.terminateIfCancelled();
method = ejbMethods[i];
if (method == null) {
// No point adding a validation message, because the user can't do anything.
// Log this condition.
Logger logger = vc.getMsgLogger();
if (logger != null && logger.isLoggingLevel(Level.FINEST)) {
LogEntry entry = vc.getLogEntry();
entry.setSourceID("AValidateEJB.validateMethods()"); //$NON-NLS-1$
entry.setText("On " + clazz + ", there is a null method."); //$NON-NLS-1$ //$NON-NLS-2$
logger.write(Level.FINEST, entry);
}
continue;
}
try {
validateExistence(vc, bean, clazz, method, methodsExtendedList);
validate(vc, bean, clazz, method, methodsExtendedList);
}
catch (InvalidInputException e) {
reflectionWarning(vc, bean, clazz, method, e);
}
}
validateMethodExists(vc, bean, clazz);
vc.terminateIfCancelled();
}
}