/******************************************************************************* * 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.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.logging.Level; 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.common.CommonPackage; import org.eclipse.jst.j2ee.common.SecurityRole; import org.eclipse.jst.j2ee.ejb.AssemblyDescriptor; import org.eclipse.jst.j2ee.ejb.CMRField; import org.eclipse.jst.j2ee.ejb.ContainerManagedEntity; import org.eclipse.jst.j2ee.ejb.EJBJar; import org.eclipse.jst.j2ee.ejb.EJBRelation; import org.eclipse.jst.j2ee.ejb.EJBRelationshipRole; import org.eclipse.jst.j2ee.ejb.EjbPackage; import org.eclipse.jst.j2ee.ejb.EnterpriseBean; import org.eclipse.jst.j2ee.ejb.Entity; import org.eclipse.jst.j2ee.ejb.MethodElement; import org.eclipse.jst.j2ee.ejb.MethodPermission; import org.eclipse.jst.j2ee.ejb.MethodTransaction; import org.eclipse.jst.j2ee.ejb.MultiplicityKind; import org.eclipse.jst.j2ee.ejb.Relationships; import org.eclipse.jst.j2ee.ejb.RoleSource; import org.eclipse.jst.j2ee.internal.J2EEConstants; import org.eclipse.jst.j2ee.internal.J2EEVersionConstants; import org.eclipse.wst.validation.internal.core.ValidationException; import org.eclipse.wst.validation.internal.provisional.core.IMessage; /** * @version 1.0 * @author */ public class EJBJar20VRule extends AValidationRule implements IMessagePrefixEjb20Constants { private static final Map MESSAGE_IDS; private DuplicatesTable _ejbName = null; private DuplicatesTable _asName = null; private DuplicatesTable _relationshipName = null; private DuplicatesTable _relationshipRoleName = null; private static final Object[] DEPENDS_ON = new Object[]{IValidationRuleList.EJB20_STATELESS_SESSION_BEANCLASS, IValidationRuleList.EJB20_STATELESS_SESSION_REMOTE, IValidationRuleList.EJB20_STATELESS_SESSION_HOME, IValidationRuleList.EJB20_STATELESS_SESSION_LOCAL, IValidationRuleList.EJB20_STATELESS_SESSION_LOCALHOME, IValidationRuleList.EJB20_STATEFUL_SESSION_BEANCLASS, IValidationRuleList.EJB20_STATEFUL_SESSION_REMOTE, IValidationRuleList.EJB20_STATEFUL_SESSION_HOME, IValidationRuleList.EJB20_STATEFUL_SESSION_LOCAL, IValidationRuleList.EJB20_STATEFUL_SESSION_LOCALHOME, IValidationRuleList.EJB20_CMP_BEANCLASS, IValidationRuleList.EJB20_CMP_REMOTE, IValidationRuleList.EJB20_CMP_HOME, IValidationRuleList.EJB20_CMP_LOCAL, IValidationRuleList.EJB20_CMP_LOCALHOME, IValidationRuleList.EJB20_CMP_KEYCLASS, IValidationRuleList.EJB20_BMP_BEANCLASS, IValidationRuleList.EJB20_BMP_REMOTE, IValidationRuleList.EJB20_BMP_HOME, IValidationRuleList.EJB20_BMP_LOCAL, IValidationRuleList.EJB20_BMP_LOCALHOME, IValidationRuleList.EJB20_BMP_KEYCLASS, IValidationRuleList.EJB20_MESSAGE_BEANCLASS, IValidationRuleList.EJB20_EJBEXT}; static { MESSAGE_IDS = new HashMap(); MESSAGE_IDS.put(CHKJ2800_NAMED, new String[]{CHKJ2800_NAMED+SPEC}); MESSAGE_IDS.put(CHKJ2800_UNNAMED, new String[]{CHKJ2800_UNNAMED+SPEC}); MESSAGE_IDS.put(CHKJ2802_NAMED, new String[]{CHKJ2802_NAMED+SPEC}); MESSAGE_IDS.put(CHKJ2802_UNNAMED, new String[]{CHKJ2802_UNNAMED+SPEC}); MESSAGE_IDS.put(CHKJ2803_NAMED, new String[]{CHKJ2803_NAMED+SPEC}); MESSAGE_IDS.put(CHKJ2803_UNNAMED, new String[]{CHKJ2803_UNNAMED+SPEC}); MESSAGE_IDS.put(CHKJ2804_NAMED, new String[]{CHKJ2804_NAMED+SPEC}); MESSAGE_IDS.put(CHKJ2804_UNNAMED, new String[]{CHKJ2804_UNNAMED+SPEC}); MESSAGE_IDS.put(CHKJ2805_NAMED, new String[]{CHKJ2805_NAMED+SPEC}); MESSAGE_IDS.put(CHKJ2805_UNNAMED, new String[]{CHKJ2805_UNNAMED+SPEC}); MESSAGE_IDS.put(CHKJ2806, new String[]{CHKJ2806+SPEC}); MESSAGE_IDS.put(CHKJ2807, new String[]{CHKJ2807+SPEC}); MESSAGE_IDS.put(CHKJ2808, new String[]{CHKJ2808+SPEC}); MESSAGE_IDS.put(CHKJ2809, new String[]{CHKJ2809+SPEC}); MESSAGE_IDS.put(CHKJ2810_NAMED, new String[]{CHKJ2810_NAMED+SPEC}); MESSAGE_IDS.put(CHKJ2810_UNNAMED, new String[]{CHKJ2810_UNNAMED+SPEC}); MESSAGE_IDS.put(CHKJ2811_NAMED, new String[]{CHKJ2811_NAMED+SPEC}); MESSAGE_IDS.put(CHKJ2814, new String[]{CHKJ2814+SPEC}); MESSAGE_IDS.put(CHKJ2816, new String[]{CHKJ2816+SPEC}); MESSAGE_IDS.put(CHKJ2817, new String[]{CHKJ2817+SPEC}); MESSAGE_IDS.put(CHKJ2818, new String[]{CHKJ2818+SPEC}); MESSAGE_IDS.put(CHKJ2820, new String[]{CHKJ2820+SPEC}); MESSAGE_IDS.put(CHKJ2821, new String[]{CHKJ2821+SPEC}); MESSAGE_IDS.put(CHKJ2822, new String[]{CHKJ2822+SPEC}); MESSAGE_IDS.put(CHKJ2823, new String[]{CHKJ2823+SPEC}); MESSAGE_IDS.put(CHKJ2824, new String[]{CHKJ2824+SPEC}); MESSAGE_IDS.put(CHKJ2825, new String[]{CHKJ2825+SPEC}); MESSAGE_IDS.put(CHKJ2826, new String[]{CHKJ2826+SPEC}); MESSAGE_IDS.put(CHKJ2827, new String[]{CHKJ2827+SPEC}); MESSAGE_IDS.put(CHKJ2828, new String[]{CHKJ2828+SPEC}); MESSAGE_IDS.put(CHKJ2829, new String[]{CHKJ2829+SPEC}); MESSAGE_IDS.put(CHKJ2830, new String[]{CHKJ2830+SPEC}); MESSAGE_IDS.put(CHKJ2831, new String[]{CHKJ2831+SPEC}); MESSAGE_IDS.put(CHKJ2832, new String[]{CHKJ2832+SPEC}); MESSAGE_IDS.put(CHKJ2833, new String[]{CHKJ2833+SPEC}); MESSAGE_IDS.put(CHKJ2834, new String[]{CHKJ2834+SPEC}); MESSAGE_IDS.put(CHKJ2835, new String[]{CHKJ2835+SPEC}); MESSAGE_IDS.put(CHKJ2836, new String[]{CHKJ2836+SPEC}); MESSAGE_IDS.put(CHKJ2837, new String[]{CHKJ2837+SPEC}); MESSAGE_IDS.put(CHKJ2838, new String[]{CHKJ2838+SPEC}); MESSAGE_IDS.put(CHKJ2839, new String[]{CHKJ2839+SPEC}); MESSAGE_IDS.put(CHKJ2841, new String[]{CHKJ2841+SPEC}); MESSAGE_IDS.put(CHKJ2842, new String[]{CHKJ2842+SPEC}); MESSAGE_IDS.put(CHKJ2843, new String[]{CHKJ2843+SPEC}); MESSAGE_IDS.put(CHKJ2844, new String[]{CHKJ2844+SPEC}); MESSAGE_IDS.put(CHKJ2845, new String[]{CHKJ2845+SPEC}); MESSAGE_IDS.put(CHKJ2846, new String[]{CHKJ2846+SPEC}); MESSAGE_IDS.put(CHKJ2847, new String[]{CHKJ2847+SPEC}); MESSAGE_IDS.put(CHKJ2848, new String[]{CHKJ2848+SPEC}); MESSAGE_IDS.put(CHKJ2850, new String[]{CHKJ2850+SPEC}); MESSAGE_IDS.put(CHKJ2854, new String[]{CHKJ2854+SPEC}); MESSAGE_IDS.put(CHKJ2855, new String[]{CHKJ2855+SPEC}); MESSAGE_IDS.put(CHKJ2856, new String[]{CHKJ2856+SPEC}); MESSAGE_IDS.put(CHKJ2857, new String[]{CHKJ2857+SPEC}); MESSAGE_IDS.put(CHKJ2858, new String[]{CHKJ2858+SPEC}); MESSAGE_IDS.put(CHKJ2859, new String[]{CHKJ2859+SPEC}); MESSAGE_IDS.put(CHKJ2860, new String[]{CHKJ2860+SPEC}); MESSAGE_IDS.put(CHKJ2866, new String[]{CHKJ2866+SPEC}); MESSAGE_IDS.put(CHKJ2867, new String[]{CHKJ2867+SPEC}); MESSAGE_IDS.put(CHKJ2868, new String[]{CHKJ2868+SPEC}); MESSAGE_IDS.put(CHKJ2869, new String[]{CHKJ2869+SPEC}); MESSAGE_IDS.put(CHKJ2871, new String[]{CHKJ2871+SPEC}); MESSAGE_IDS.put(CHKJ2872, new String[]{CHKJ2872+SPEC}); MESSAGE_IDS.put(CHKJ2873, new String[]{CHKJ2873+SPEC}); MESSAGE_IDS.put(CHKJ2874, new String[]{CHKJ2874+SPEC}); MESSAGE_IDS.put(CHKJ2875, new String[]{CHKJ2875 + SPEC}); MESSAGE_IDS.put(CHKJ2895, new String[]{CHKJ2895+SPEC}); MESSAGE_IDS.put(CHKJ2852, new String[]{CHKJ2852}); MESSAGE_IDS.put(CHKJ2907, new String[]{CHKJ2907}); } public EJBJar20VRule() { _ejbName = new DuplicatesTable(); _asName = new DuplicatesTable(); _relationshipName = new DuplicatesTable(); _relationshipRoleName = new DuplicatesTable(); } public Object[] getDependsOn() { // EJBJar doesn't depend on anything else return DEPENDS_ON; } public Object getId() { return IValidationRuleList.EJB20_EJBJAR; } public Map getMessageIds() { return MESSAGE_IDS; } public Object getTarget(Object parent, Object clazz) { // Since this rule doesn't depend on another rule, this // method (which is called on a dependent rule) will never // be called. return null; } /* * @see IValidationRule#reset() */ @Override public void reset() { super.reset(); _ejbName.clear(); _asName.clear(); _relationshipName.clear(); _relationshipRoleName.clear(); } protected void addInternalErrorMessage(IEJBValidationContext vc, Throwable exc) { IMessage mssg = vc.getMessage(); mssg.setId(IEJBValidatorMessageConstants.CHKJ2900); vc.addMessage(mssg); if(exc != null) { Logger logger = vc.getMsgLogger(); if (logger != null && logger.isLoggingLevel(Level.SEVERE)) { logger.write(Level.SEVERE, exc); } } } protected void logMissingRule(IEJBValidationContext vc, Object ruleId) { log(vc, ruleId + " = null"); //$NON-NLS-1$ addInternalErrorMessage(vc, null); } protected void log(IEJBValidationContext vc, String message) { Logger logger = vc.getMsgLogger(); if (logger != null && logger.isLoggingLevel(Level.SEVERE)) { logger.write(Level.SEVERE, message); } } /* * @see IValidationRule#validate(IEJBValidationContext, Object, Object) */ public void validate(IEJBValidationContext vc, Object targetParent, Object target) throws ValidationCancelledException, ValidationException { Logger logger = vc.getMsgLogger(); if(logger != null && logger.isLoggingLevel(Level.FINEST)) { LogEntry entry = vc.getLogEntry(); entry.setSourceID("EJBJar20VRule - validate"); //$NON-NLS-1$ entry.setText(getClass().getName() + "::validate(" + targetParent + ", " + target); //$NON-NLS-1$ //$NON-NLS-2$ logger.write(Level.FINEST, entry); } EJBJar ejbJar = (EJBJar) target; List beans = ejbJar.getEnterpriseBeans(); Iterator iterator = beans.iterator(); EnterpriseBean bean = null; while (iterator.hasNext()) { try { bean = (EnterpriseBean) iterator.next(); register(vc, ejbJar, bean); Object id = null; switch(bean.getVersionID()) { case J2EEVersionConstants.EJB_1_0_ID: case J2EEVersionConstants.EJB_1_1_ID: id = IValidationRuleList.EJB11_ENTERPRISEBEAN; break; case J2EEVersionConstants.EJB_2_0_ID: case J2EEVersionConstants.EJB_2_1_ID: id = IValidationRuleList.EJB20_ENTERPRISEBEAN; break; default: // What version is it then? if(bean instanceof ContainerManagedEntity) { validateCMPVersionElement(vc, ejbJar, (ContainerManagedEntity)bean); } else { // log log(vc, "!bean.isVersion1_X() && !bean.isVersion2_X()"); //$NON-NLS-1$ } continue; } IValidationRule vRule = EJBValidationRuleFactory.getFactory().getRule(vc, id); if(vRule == null) { logMissingRule(vc, id); continue; } try { vRule.preValidate(vc, ejbJar, bean); vRule.validate(vc, ejbJar, bean); vRule.postValidate(vc, ejbJar, bean); } catch(ValidationCancelledException exc) { // Clean up the messages which are on the task list? Or is it nicer to leave them behind? throw exc; } catch(ValidationException e) { throw e; } catch(Throwable exc) { addInternalErrorMessage(vc, exc); } finally { EJBValidationRuleFactory.getFactory().release(vRule); } } catch(ValidationCancelledException e) { throw e; } catch(ValidationException exc) { // something goes wrong, just proceed with the next bean IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2852, IEJBValidationContext.WARNING, bean, new String[]{J2EEConstants.EJBJAR_DD_SHORT_NAME, bean.getName()}, this); vc.addMessage(message); if (logger != null && logger.isLoggingLevel(Level.SEVERE)) { logger.write(Level.SEVERE, exc); } } catch (Throwable exc) { if(bean != null){ IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2852, IEJBValidationContext.WARNING, bean, new String[]{J2EEConstants.EJBJAR_DD_SHORT_NAME, bean.getName()}, this); vc.addMessage(message); if (logger != null && logger.isLoggingLevel(Level.SEVERE)) { logger.write(Level.SEVERE, exc); } } } } // Since the assembly descriptor is not specific to a bean, validate it once, after all bean processing is complete. validateAssemblyDescriptorElement(vc, ejbJar); //TODO The Datasource validation will be done by the extensions validateUniqueEjbNames(vc, ejbJar); validateUniqueAbstractSchemaNames(vc, ejbJar); validateRelationships(vc, ejbJar); validateClientJAR(vc, ejbJar); } protected void register(IEJBValidationContext vc, EJBJar ejbJar, EnterpriseBean bean) { // To check if every bean name is unique, need to build a list _ejbName.add(new EjbNameWrapper(bean)); if((bean instanceof ContainerManagedEntity) && bean.getVersionID() >= J2EEVersionConstants.EJB_2_0_ID) { // To check if every bean name is unique, need to build a list _asName.add(new ASNameWrapper((ContainerManagedEntity)bean)); } } protected void validateCMPVersionElement(IEJBValidationContext vc, EJBJar ejbJar, ContainerManagedEntity cmp) { if(cmp.eIsSet(EjbPackage.eINSTANCE.getContainerManagedEntity_Version())) { String version = cmp.getVersion(); if(! (ContainerManagedEntity.VERSION_1_X.equals(version) || ContainerManagedEntity.VERSION_2_X.equals(version))) { IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2872, IEJBValidationContext.ERROR, cmp, this); vc.addMessage(message); } } } protected void validateAssemblyDescriptorElement(IEJBValidationContext vc, EJBJar ejbJar) { vc.terminateIfCancelled(); // Validate the security roles, if they're defined in the assembly-descriptor. if (ejbJar == null) { // nothing to validate return; } /** * Need to build up a list of duplicate role names, but the validation message * needs to be registered against the duplicate SecurityRole instance. * (Without the instance, we cannot get line numbers.) * * This class wrappers the SecurityRol instance so that the wrapper's * implemention of equals compares the names, but the validation message will * still be able to get the ref from the duplicate name. */ class RoleWrapper { private SecurityRole _role = null; public RoleWrapper(SecurityRole role) { _role = role; } @Override public boolean equals(Object o) { if (o instanceof RoleWrapper) { RoleWrapper other = (RoleWrapper) o; return _role.getRoleName().equals(other.getRole().getRoleName()); } return false; } @Override public int hashCode() { return super.hashCode() + _role.getRoleName().hashCode(); } public SecurityRole getRole() { return _role; } } AssemblyDescriptor assemblyDescriptor = ejbJar.getAssemblyDescriptor(); if (assemblyDescriptor == null) { // nothing to validate return; } List roles = assemblyDescriptor.getSecurityRoles(); if (roles != null) { DuplicatesTable roleNames = new DuplicatesTable(); SecurityRole role = null; Iterator roleIt = roles.iterator(); while (roleIt.hasNext()) { vc.terminateIfCancelled(); // Check that the role-name element has been set role = (SecurityRole) roleIt.next(); if ((role == null) || (!role.eIsSet(CommonPackage.eINSTANCE.getSecurityRole_RoleName())) || (role.getRoleName().equals(""))) { //$NON-NLS-1$ // role-name not set if(role == null) { IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2825, IEJBValidationContext.WARNING, role, this); vc.addMessage(message); } else { IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2825, IEJBValidationContext.WARNING, assemblyDescriptor, this); vc.addMessage(message); } } else { // Build up hashtable to check for duplicate role-names. roleNames.add(new RoleWrapper(role)); } } // Check that there are no duplicate role-names. (15.3.1) if (roleNames.containsDuplicates()) { List duplicates = roleNames.getDuplicates(); Iterator iterator = duplicates.iterator(); while (iterator.hasNext()) { IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2826, IEJBValidationContext.WARNING, ((RoleWrapper) iterator.next()).getRole(), this); vc.addMessage(message); } } roleNames.clear(); } List methTrans = assemblyDescriptor.getMethodTransactions(); MethodTransaction mt = null; Iterator iterator = methTrans.iterator(); while (iterator.hasNext()) { vc.terminateIfCancelled(); try { mt = (MethodTransaction) iterator.next(); } catch (Throwable exc) { Logger logger = vc.getMsgLogger(); if (logger != null && logger.isLoggingLevel(Level.FINER)) { logger.write(Level.FINER, exc); } mt = null; } if (mt == null) { Logger logger = vc.getMsgLogger(); if (logger != null && logger.isLoggingLevel(Level.FINEST)) { LogEntry entry = vc.getLogEntry(); entry.setSourceID("EJBJar20VRule.validateAssemblyDescriptorElement"); //$NON-NLS-1$ entry.setText("mt is null"); //$NON-NLS-1$ logger.write(Level.FINEST, entry); } continue; } boolean hasValidMethod = validateMethodElements(vc, ejbJar, mt.getMethodElements()); if (!hasValidMethod) { IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2847, IEJBValidationContext.WARNING, mt, this); vc.addMessage(message); } } List methodPermissions = assemblyDescriptor.getMethodPermissions(); iterator = methodPermissions.iterator(); while (iterator.hasNext()) { MethodPermission mp = (MethodPermission) iterator.next(); boolean hasValidMethod = validateMethodElements(vc, ejbJar, mp.getMethodElements()); if (!hasValidMethod) { // 15.3.2, p. 229, a <method-permission> must have at least one method listed (and that method must be found) IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2846, IEJBValidationContext.WARNING, mp, this); vc.addMessage(message); } // at least one security-role must be defined List mproles = mp.getRoles(); if (((mproles == null) || (mproles.size() == 0)) && (!mp.isSetUnchecked())) { IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2845, IEJBValidationContext.WARNING, mp, this); vc.addMessage(message); } } } protected void validateUniqueAbstractSchemaNames(IEJBValidationContext vc, EJBJar ejbJar) { List names = _asName.getDuplicates(); if(names.size() == 0) { return; } Iterator iterator = names.iterator(); while(iterator.hasNext()) { ASNameWrapper wrapper = (ASNameWrapper)iterator.next(); IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2854, IEJBValidationContext.ERROR, wrapper.getBean(), new String[]{wrapper.getBean().getAbstractSchemaName()}, this); vc.addMessage(message); } } protected void validateUniqueEjbNames(IEJBValidationContext vc, EJBJar ejbJar) { List names = _ejbName.getDuplicates(); if(names.size() == 0) { return; } Iterator iterator = names.iterator(); while(iterator.hasNext()) { EjbNameWrapper wrapper = (EjbNameWrapper)iterator.next(); IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2895, IEJBValidationContext.WARNING, wrapper.getBean(), new String[]{wrapper.getBean().getName()}, this); vc.addMessage(message); } } protected void validateRelationships(IEJBValidationContext vc, EJBJar ejbJar) { Relationships relationships = ejbJar.getRelationshipList(); if(relationships == null) { return; } List ejbRelationList = relationships.getEjbRelations(); Iterator iterator = ejbRelationList.iterator(); while(iterator.hasNext()) { EJBRelation relation = (EJBRelation)iterator.next(); _relationshipName.add(new EJBRelationNameWrapper(relation)); boolean atLeastOneCmrFieldExists = false; List roles = relation.getRelationshipRoles(); Iterator roleIterator = roles.iterator(); while(roleIterator.hasNext()) { EJBRelationshipRole role = (EJBRelationshipRole)roleIterator.next(); _relationshipRoleName.add(new EJBRelationshipRoleNameWrapper(role)); boolean validMultiplicity = role.isSetMultiplicity(); if(!validMultiplicity) { IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2818, IEJBValidationContext.INFO, role, this); vc.addMessage(message); } // 10.3.4.2 // The cascade-delete element can only be specified for an ejb-relationship-role // element contained in an ejb-relation element if the *other* ejb-relationship-role // element in the same ejb-relation element specifies a multiplicity of One. EJBRelationshipRole oppositeRole = role.getOpposite(); if(role.isSetCascadeDelete()) { boolean isOtherMultiplicityOne = ((oppositeRole.isSetMultiplicity()) && (oppositeRole.getMultiplicity().getValue() == MultiplicityKind.ONE)); if(!isOtherMultiplicityOne) { IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2848, IEJBValidationContext.INFO, role, this); vc.addMessage(message); } } CMRField cmrField = role.getCmrField(); if(cmrField != null) { atLeastOneCmrFieldExists = true; if(cmrField.eIsSet(EjbPackage.eINSTANCE.getCMRField_CollectionType())) { String cmrFieldType = cmrField.getCollectionTypeName(); if((!ITypeConstants.CLASSNAME_JAVA_UTIL_COLLECTION.equals(cmrFieldType)) && (!ITypeConstants.CLASSNAME_JAVA_UTIL_SET.equals(cmrFieldType))) { // CHKJ2868: The value of the <cmr-field-type> element must be either "java.util.Collection" or "java.util.Set" (EJB 2.0: 10.3.13, 22.5). IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2868, IEJBValidationContext.INFO, role, this); vc.addMessage(message); } } } RoleSource sourceRoleSource = role.getSource(); if(sourceRoleSource == null) { IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2821, IEJBValidationContext.INFO, role, new String[]{role.getName()}, this); vc.addMessage(message); continue; } Entity sourceEntity = sourceRoleSource.getEntityBean(); if(sourceEntity == null) { IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2821, IEJBValidationContext.INFO, role, new String[]{role.getName()}, this); vc.addMessage(message); } else if(sourceEntity.isContainerManagedEntity()) { // CHKJ2866: <cmr-field> {0} must be defined on {1} (EJB 2.0: 22.5). if(cmrField != null) { ContainerManagedEntity cmp = (ContainerManagedEntity)sourceEntity; List cmrFields = cmp.getCMRFields(); boolean found_cmrField = false; if((cmrFields != null) && (cmrFields.size() > 0)) { found_cmrField = cmrFields.contains(cmrField); } if(!found_cmrField) { IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2866, IEJBValidationContext.INFO, role, new String[]{cmrField.getName(), sourceEntity.getName()}, this); vc.addMessage(message); } } } else { // CHKJ2871: <ejb-name> {0} must refer to a CMP bean (EJB 2.0: 10.3.2, 10.3.13). IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2871, IEJBValidationContext.INFO, role, new String[]{sourceEntity.getName()}, this); vc.addMessage(message); } if( oppositeRole == null ) continue; RoleSource oppositeRoleSource = oppositeRole.getSource(); if(oppositeRoleSource == null) { // Do not emit an error message - when we iterate to the role where // this is the source, this error will be detected. continue; } Entity targetEntity = oppositeRoleSource.getEntityBean(); if(targetEntity == null) { // Do not emit an error message - when we iterate to the role where // this is the source, this error will be detected. } else if(targetEntity.getLocalInterface() == null) { // Does the target of this role have a local interface? // CHKJ2867: This bean can have only unidirectional relationships to other beans (EJB 2.0: 10.3.2). IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2867, IEJBValidationContext.INFO, oppositeRole, this); vc.addMessage(message); } } // Verify unique role names within the <ejb-relation> validateUniqueRelationshipRoleNames(vc, ejbJar); _relationshipRoleName.clear(); if(!atLeastOneCmrFieldExists) { // CHKJ2869I: At least one <ejb-relationship-role> must define a <cmr-field> (EJB 2.0: 10.3.2, 10.3.13, 22.5). IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2869, IEJBValidationContext.INFO, relation, this); vc.addMessage(message); } } validateUniqueRelationNames(vc, ejbJar); } protected void validateUniqueRelationNames(IEJBValidationContext vc, EJBJar ejbJar) { List names = _relationshipName.getDuplicates(); if(names.size() == 0) { return; } Iterator iterator = names.iterator(); while(iterator.hasNext()) { EJBRelationNameWrapper wrapper = (EJBRelationNameWrapper)iterator.next(); IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2816, IEJBValidationContext.INFO, wrapper.getRelation(), new String[]{wrapper.getRelation().getName()}, this); vc.addMessage(message); } } protected void validateUniqueRelationshipRoleNames(IEJBValidationContext vc, EJBJar ejbJar) { List names = _relationshipRoleName.getDuplicates(); if(names.size() == 0) { return; } Iterator iterator = names.iterator(); while(iterator.hasNext()) { EJBRelationshipRoleNameWrapper wrapper = (EJBRelationshipRoleNameWrapper)iterator.next(); IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2817, IEJBValidationContext.INFO, wrapper.getRelationshipRole(), new String[]{wrapper.getRelationshipRole().getName()}, this); vc.addMessage(message); } } /** * Both section 11.4.1 and 15.3.2 need the <method> element. Also refer * to 16.5 for syntax. * * Return true if at least one of the methods referenced by this list of * MethodElement can be found. */ protected boolean validateMethodElements(IEJBValidationContext vc, EJBJar ejbJar, List elements) { if ((elements == null) || (elements.size() == 0)) { return false; } boolean hasValidMethod = false; Iterator iterator = elements.iterator(); while (iterator.hasNext()) { vc.terminateIfCancelled(); MethodElement element = (MethodElement) iterator.next(); EnterpriseBean bean = element.getEnterpriseBean(); if (bean == null) { IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2814, IEJBValidationContext.WARNING, element, this); vc.addMessage(message); continue; } if (element.getName() != null) { String name = element.getName(); Method[] methods = element.getMethods(); // get all methods which will be retrieved for the given method-permission boolean hasMethods = ((methods != null) && (methods.length > 0)); if (!hasMethods) { // warning IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2843, IEJBValidationContext.WARNING, element, new String[] { bean.getName()}, this); vc.addMessage(message); } else { hasValidMethod = true; // a <method-permission> must have at least one method (15.3.2, p.229) if (name.equals("*")) { //$NON-NLS-1$ List params = element.getMethodParams(); if ((params != null) && (params.size() > 0)) { // warning IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2842, IEJBValidationContext.WARNING, element, this); vc.addMessage(message); } } } } else { // error IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2844, IEJBValidationContext.WARNING, element, this); vc.addMessage(message); } } return hasValidMethod; } protected void validateClientJAR(IEJBValidationContext vc, EJBJar ejbJar) { String clientJARName = ejbJar.getEjbClientJar(); if(clientJARName == null) { // No client JAR specified; everything's okay. return; } Boolean exists = (Boolean)vc.loadModel(EJBValidatorModelEnum.EJB_CLIENTJAR, new Object[]{clientJARName}); if(exists == null) { // Helper doesn't support load model. WAS? // Can't perform this check, so just return. return; } if(!exists.booleanValue()) { IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2875, IEJBValidationContext.ERROR, ejbJar, new String[]{clientJARName}, this); vc.addMessage(message); } } class ASNameWrapper { private ContainerManagedEntity _bean = null; public ASNameWrapper(ContainerManagedEntity bean) { _bean = bean; } @Override public boolean equals(Object o) { if (o instanceof ASNameWrapper) { ASNameWrapper other = (ASNameWrapper)o; if((_bean.getAbstractSchemaName() == null) && (other.getBean().getAbstractSchemaName() == null)) { return true; } else if(_bean.getAbstractSchemaName() == null) { return false; } else if(other.getBean().getAbstractSchemaName() == null) { return false; } return _bean.getAbstractSchemaName().equals(other.getBean().getAbstractSchemaName()); } return false; } @Override public int hashCode() { if((getBean() != null) && (getBean().getAbstractSchemaName() != null)) { return getBean().getAbstractSchemaName().hashCode(); } return super.hashCode(); } public ContainerManagedEntity getBean() { return _bean; } } /** * Need to build up a list of duplicate EJB names, but the validation message * needs to be registered against the duplicate EnterpriseBean instance. * (Without the instance, we cannot get line numbers.) * * This class wrappers the EnterpriseBean instance so that the wrapper's * implemention of equals compares the names, but the validation message will * still be able to get the ref from the duplicate name. */ class EjbNameWrapper { private EnterpriseBean _bean = null; public EjbNameWrapper(EnterpriseBean bean) { _bean = bean; } @Override public boolean equals(Object o) { if (o instanceof EjbNameWrapper) { EjbNameWrapper other = (EjbNameWrapper)o; if((_bean.getName() == null) && (other.getBean().getName() == null)) { return true; } else if(_bean.getName() == null) { return false; } else if(other.getBean().getName() == null) { return false; } return _bean.getName().equals(other.getBean().getName()); } return false; } @Override public int hashCode() { if((getBean() != null) && (getBean().getName() != null)) { return getBean().getName().hashCode(); } return super.hashCode(); } public EnterpriseBean getBean() { return _bean; } } /** * Need to build up a list of duplicate relation names, but the validation message * needs to be registered against the duplicate EnterpriseBean instance. * (Without the instance, we cannot get line numbers.) * * This class wrappers the EnterpriseBean instance so that the wrapper's * implemention of equals compares the names, but the validation message will * still be able to get the ref from the duplicate name. */ class EJBRelationNameWrapper { private EJBRelation _relation = null; public EJBRelationNameWrapper(EJBRelation rel) { _relation = rel; } @Override public boolean equals(Object o) { if (o instanceof EJBRelationNameWrapper) { EJBRelationNameWrapper other = (EJBRelationNameWrapper)o; if((_relation.getName() == null) && (other.getRelation().getName() == null)) { return true; } else if(_relation.getName() == null) { return false; } else if(other.getRelation().getName() == null) { return false; } return _relation.getName().equals(other.getRelation().getName()); } return false; } @Override public int hashCode() { if((getRelation() != null) && (getRelation().getName() != null)) { return getRelation().getName().hashCode(); } return super.hashCode(); } public EJBRelation getRelation() { return _relation; } } /** * Need to build up a list of duplicate relation names, but the validation message * needs to be registered against the duplicate EnterpriseBean instance. * (Without the instance, we cannot get line numbers.) * * This class wrappers the EnterpriseBean instance so that the wrapper's * implemention of equals compares the names, but the validation message will * still be able to get the ref from the duplicate name. */ class EJBRelationshipRoleNameWrapper { private EJBRelationshipRole _relationshipRole = null; public EJBRelationshipRoleNameWrapper(EJBRelationshipRole role) { _relationshipRole = role; } @Override public boolean equals(Object o) { if (o instanceof EJBRelationshipRoleNameWrapper) { EJBRelationshipRoleNameWrapper other = (EJBRelationshipRoleNameWrapper)o; if((_relationshipRole.getRoleName() == null) && (other.getRelationshipRole().getRoleName() == null)) { return true; } else if(_relationshipRole.getRoleName() == null) { return false; } else if(other.getRelationshipRole().getRoleName() == null) { return false; } return _relationshipRole.getRoleName().equals(other.getRelationshipRole().getRoleName()); } return false; } @Override public int hashCode() { if((getRelationshipRole() != null) && (getRelationshipRole().getRoleName() != null)) { return getRelationshipRole().getRoleName().hashCode(); } return super.hashCode(); } public EJBRelationshipRole getRelationshipRole() { return _relationshipRole; } } }