| /******************************************************************************* |
| * Copyright (c) 2001, 2005 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.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.jem.java.Field; |
| import org.eclipse.jem.java.JavaClass; |
| import org.eclipse.jem.java.Method; |
| import org.eclipse.jst.j2ee.ejb.CMPAttribute; |
| import org.eclipse.jst.j2ee.ejb.ContainerManagedEntity; |
| import org.eclipse.jst.j2ee.ejb.EnterpriseBean; |
| import org.eclipse.wst.validation.internal.core.ValidationException; |
| import org.eclipse.wst.validation.internal.provisional.core.IMessage; |
| |
| |
| /** |
| * @version 1.0 |
| * @author |
| */ |
| public final class CMPKeyClassVRule extends AKeyClassVRule implements IRemoteType, IMessagePrefixEjb20Constants { |
| private static final Object ID = IValidationRuleList.EJB20_CMP_KEYCLASS; |
| private static final Object[] DEPENDS_ON = new Object[]{IValidationRuleList.EJB20_CMP_BEANCLASS}; |
| private static final Map MESSAGE_IDS; |
| |
| private static final String MSSGID = ".kc"; // In messages, to identify which message version belongs to the BMP bean class, this id is used. //$NON-NLS-1$ |
| private static final String EXT = MSSGID + SPEC; // Extension to be used on non-method, non-field messages |
| private static final String BEXT = MSSGID + ON_BASE + SPEC; // Extension to be used on a method/field message when the method/field is inherited from a base type |
| private static final String MEXT = MSSGID + ON_THIS + SPEC; // Extension to be used on a method/field message when the method/field is implemented on the current type |
| |
| private final long[] SUPERTYPES = null; |
| private final long[] SHOULD_NOT_BE_SUPERTYPES = null; |
| |
| private final long[] METHODS_WHICH_MUST_EXIST = new long[]{HASHCODE_NOPARM, EQUALS, CONSTRUCTOR_NOPARM}; |
| private final long[] METHODS_WHICH_MUST_NOT_EXIST = null; |
| |
| private final long[] KNOWN_METHOD_TYPES = new long[]{CLINIT, HASHCODE_NOPARM, EQUALS, CONSTRUCTOR_NOPARM, CONSTRUCTOR}; |
| |
| private Set _keyFields = null; |
| |
| static { |
| MESSAGE_IDS = new HashMap(); |
| |
| MESSAGE_IDS.put(CHKJ2050_constr, new String[]{CHKJ2050_constr+EXT}); |
| MESSAGE_IDS.put(CHKJ2050_hashCode, new String[]{CHKJ2050_hashCode+EXT}); |
| MESSAGE_IDS.put(CHKJ2050_equals, new String[]{CHKJ2050_equals+EXT}); |
| MESSAGE_IDS.put(CHKJ2022, new String[]{CHKJ2022+EXT}); |
| |
| MESSAGE_IDS.put(CHKJ2019, new String[]{CHKJ2019+EXT}); |
| |
| MESSAGE_IDS.put(CHKJ2205, new String[]{CHKJ2205+BEXT, CHKJ2205+MEXT}); |
| MESSAGE_IDS.put(CHKJ2206, new String[]{CHKJ2206+BEXT, CHKJ2206+MEXT}); |
| |
| MESSAGE_IDS.put(CHKJ2404, new String[]{CHKJ2404+ON_BASE_SPEC, CHKJ2404+ON_THIS_SPEC}); // special case (shared by all types) |
| MESSAGE_IDS.put(CHKJ2416, new String[]{CHKJ2416+ON_BASE_SPEC, CHKJ2416+ON_THIS_SPEC}); // special case (shared by all types) |
| |
| MESSAGE_IDS.put(CHKJ2433, new String[]{CHKJ2433}); |
| MESSAGE_IDS.put(CHKJ2829, new String[]{CHKJ2829+SPEC}); |
| MESSAGE_IDS.put(CHKJ2907, new String[]{CHKJ2907}); |
| } |
| |
| public final Map getMessageIds() { |
| return MESSAGE_IDS; |
| } |
| |
| @Override |
| public final int getMessageRemoteExceptionSeverity() { |
| // Key methods are not checked for RemoteException, but to be consistent with the other VRules... |
| return MESSAGE_REMOTE_EXCEPTION_SEVERITY; |
| } |
| |
| public final Object[] getDependsOn() { |
| return DEPENDS_ON; |
| } |
| |
| public final Object getId() { |
| return ID; |
| } |
| |
| public final long[] getSupertypes() { |
| return SUPERTYPES; |
| } |
| |
| public final long[] getShouldNotBeSupertypes() { |
| return SHOULD_NOT_BE_SUPERTYPES; |
| } |
| |
| public final int isRemote() { |
| return IS_REMOTE; |
| } |
| |
| public final long[] getMethodsWhichMustExist() { |
| return METHODS_WHICH_MUST_EXIST; |
| } |
| |
| |
| public final long[] getMethodsWhichMustNotExist() { |
| return METHODS_WHICH_MUST_NOT_EXIST; |
| } |
| |
| public Object getTarget(Object parent, Object clazz) { |
| if(parent == null) { |
| return null; |
| } |
| |
| ContainerManagedEntity cmp = (ContainerManagedEntity)parent; |
| if(ValidationRuleUtility.isPrimitivePrimaryKey(cmp)) { |
| return null; // do not validate a primitive primary key |
| } |
| |
| return cmp.getPrimaryKey(); |
| } |
| |
| |
| /* |
| * @see IClassVRule#validate(IEJBValidationContext, EnterpriseBean, JavaClass, Method) |
| */ |
| public final void validate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, List[] methodsExtendedLists) throws ValidationCancelledException, InvalidInputException, ValidationException { |
| // Nothing to do. |
| } |
| |
| @Override |
| public final void validate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) throws ValidationCancelledException, InvalidInputException, ValidationException { |
| super.validate(vc, bean, clazz); |
| |
| // IWAD4251 = This class must be public. Read section 10.8.2 of the EJB 2.0 specification. |
| if(!clazz.isPublic()) { |
| IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2022, IEJBValidationContext.INFO, bean, clazz, this); |
| vc.addMessage(message); |
| } |
| |
| ContainerManagedEntity cmp = (ContainerManagedEntity)bean; |
| if(!ValidationRuleUtility.usesUnknownPrimaryKey(cmp)) { |
| // primary key must map to at least one field on the bean |
| // But if it's an unknown key, there's no point checking java.lang.Object |
| List primKeyFields = cmp.getKeyAttributes(); |
| if ((primKeyFields == null) || (primKeyFields.size() == 0)) { |
| JavaClass primaryKey = cmp.getPrimaryKey(); // don't need to check ValidationRuleUtility.isValidType(primaryKey), because it's already been called in the validateDeploymentDescriptor method |
| String beanName = (cmp.getName() == null) ? "null" : cmp.getName(); //$NON-NLS-1$ |
| IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2829, IEJBValidationContext.ERROR, cmp, primaryKey, new String[] { primaryKey.getName(), beanName }, this); |
| vc.addMessage(message); |
| } |
| } |
| } |
| |
| private Set getKeyFields(ContainerManagedEntity cmp) { |
| if(_keyFields == null) { |
| // Know that the traversal of the fields and methods is done sequentially. |
| // i.e., that a class is validated according to one bean at at time. |
| // Thus, we can cache the key field information to speed up subsequent calls. |
| List fields = cmp.getKeyAttributes(); |
| Iterator iterator = fields.iterator(); |
| _keyFields = new HashSet(); |
| while(iterator.hasNext()) { |
| CMPAttribute attrib = (CMPAttribute)iterator.next(); |
| _keyFields.add(attrib.getName()); |
| } |
| } |
| return _keyFields; |
| } |
| |
| /* |
| * @see IClassVRule#validate(IEJBValidationContext, EnterpriseBean, JavaClass, Field) |
| */ |
| public final void validate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field, List[] fieldExtendedLists) throws ValidationCancelledException, InvalidInputException, ValidationException { |
| long fieldType = MethodUtility.getUtility().getFieldTypeId(bean, clazz, field, this); |
| if((fieldType & IMethodAndFieldConstants.SERIALVERSIONUID) == IMethodAndFieldConstants.SERIALVERSIONUID) { |
| validateSerialVersionUID(vc, bean, clazz, field); |
| } |
| else { |
| // IWAD4253 = This field must be public. Read section 10.8.1 of the EJB 2.0 specification. |
| if(!ValidationRuleUtility.isPublic(field)) { |
| IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2205, IEJBValidationContext.WARNING, bean, clazz, field, this); |
| vc.addMessage(message); |
| } |
| |
| Set keyFields = getKeyFields((ContainerManagedEntity)bean); |
| if(!keyFields.contains(field.getName())) { |
| // IWAD4254 = This field is not a <cmp-field>. Read section 10.8.1 of the EJB 2.0 specification. |
| IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2206, IEJBValidationContext.WARNING, bean, clazz, field, this); |
| vc.addMessage(message); |
| } |
| } |
| } |
| |
| public final long[] getKnownMethodTypes() { |
| return KNOWN_METHOD_TYPES; |
| } |
| |
| /* |
| * @see IValidationRule#reset() |
| */ |
| @Override |
| public void reset() { |
| super.reset(); |
| if(_keyFields != null) { |
| _keyFields.clear(); |
| _keyFields = null; // in this case, clearing the Set isn't enough. |
| } |
| } |
| } |