| /******************************************************************************* |
| * 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.ArrayList; |
| 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.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.jobs.ISchedulingRule; |
| import org.eclipse.jem.java.JavaClass; |
| import org.eclipse.jem.util.logger.LogEntry; |
| import org.eclipse.jem.util.logger.proxy.Logger; |
| import org.eclipse.jst.j2ee.ejb.EJBJar; |
| import org.eclipse.jst.j2ee.ejb.EnterpriseBean; |
| import org.eclipse.jst.j2ee.ejb.Entity; |
| import org.eclipse.jst.j2ee.internal.J2EEConstants; |
| import org.eclipse.wst.validation.ValidationState; |
| import org.eclipse.wst.validation.internal.core.ValidationException; |
| import org.eclipse.wst.validation.internal.provisional.core.IMessage; |
| import org.eclipse.wst.validation.internal.provisional.core.IReporter; |
| import org.eclipse.wst.validation.internal.provisional.core.IValidationContext; |
| |
| /** |
| * @version 1.0 |
| * @author |
| */ |
| public class EJBValidator extends AbstractEJBValidator { |
| private static EJBValidator _inst = null; |
| private static TargetObjectPool _targetObjectPoolSingleton = null; |
| private LogEntry logEntry = null; |
| |
| |
| public EJBValidator() { |
| _inst = this; |
| } |
| |
| public static EJBValidator getValidator() { |
| return _inst; |
| } |
| |
| private LogEntry getLogEntry(){ |
| if(logEntry == null) |
| logEntry = new LogEntry(IEJBValidatorConstants.BUNDLE_NAME); |
| return logEntry; |
| } |
| |
| @Override |
| public String getBaseName() { |
| return "ejbvalidator"; //$NON-NLS-1$ |
| } |
| |
| public void commonValidate(IValidationContext helper, IReporter reporter) throws ValidationException { |
| long start = System.currentTimeMillis(); |
| Logger logger = Logger.getLogger(IEJBValidatorConstants.J2EE_CORE_PLUGIN); |
| if (logger != null && logger.isLoggingLevel(Level.FINER)) { |
| long end = System.currentTimeMillis(); |
| LogEntry entry = getLogEntry(); |
| entry.setSourceID("EJBValidator::validate"); //$NON-NLS-1$ |
| entry.setText("validate took " + (end - start) + " milliseconds."); //$NON-NLS-1$ //$NON-NLS-2$ |
| logger.write(Level.FINER, entry); |
| } |
| try { |
| EJBValidationContext vc = new EJBValidationContext(this, helper, reporter); |
| setValidationContext(vc); |
| if (isFullValidate(vc)) { |
| fullValidate(vc); |
| } else { |
| incrementalValidate(vc); |
| } |
| if (logger != null && logger.isLoggingLevel(Level.FINER)) { |
| long end = System.currentTimeMillis(); |
| LogEntry entry = getLogEntry(); |
| entry.setSourceID("EJBValidator::validate"); //$NON-NLS-1$ |
| entry.setText("validate took " + (end - start) + " milliseconds."); //$NON-NLS-1$ //$NON-NLS-2$ |
| logger.write(Level.FINER, entry); |
| } |
| } finally { |
| |
| } |
| } |
| |
| |
| @Override |
| public void validate(IValidationContext helper, IReporter reporter) throws ValidationException { |
| commonValidate(helper, reporter); |
| } |
| /* |
| * @see IValidator#validate(IValidationContext, IReporter, IFileDelta[]) |
| */ |
| @Override |
| public IStatus validateInJob(IValidationContext helper, IReporter reporter) throws ValidationException { |
| commonValidate(helper, reporter); |
| return status; |
| } |
| |
| public boolean isFullValidate(IEJBValidationContext vc) { |
| String[] fileURIs = vc.getURIs(); |
| if(fileURIs == null) { |
| return true; |
| } |
| if(fileURIs.length == 0) { |
| return true; |
| } |
| |
| for(int i=0; i<fileURIs.length; i++) { |
| String uri = fileURIs[i]; |
| if(uri.endsWith(J2EEConstants.EJBJAR_DD_SHORT_NAME)) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| public void runDependents(IEJBValidationContext vc, IValidationRule rule, Object targetParent, Object target) throws ValidationException { |
| // If a class is being run only because it depends on a rule which has changed, |
| // i.e., it's a dependent, then we don't want to run its dependents because the |
| // class itself hasn't changed. |
| Set dependents = rule.getDependents(); |
| if(dependents == null) { |
| return; |
| } |
| |
| Iterator iterator = dependents.iterator(); |
| while(iterator.hasNext()) { |
| try { |
| IValidationRule dRule = (IValidationRule)iterator.next(); |
| Object dRuleTarget = dRule.getTarget(targetParent, target); |
| if(dRuleTarget != null) { |
| run(dRule, targetParent, dRuleTarget); // false=not full validation |
| } |
| } |
| catch(ValidationCancelledException e) { |
| throw e; |
| } |
| catch(ValidationException e) { |
| throw e; |
| } |
| catch(Throwable exc) { |
| addInternalErrorMessage(getValidationContext(), exc); |
| } |
| finally { |
| EJBValidationRuleFactory.getFactory().release(rule); |
| } |
| } |
| } |
| |
| protected String internalErrorMessage() { |
| return IEJBValidatorMessageConstants.CHKJ2900; |
| } |
| |
| |
| |
| @Override |
| protected void logMissingRule(IEJBValidationContext vc, Object ruleId) { |
| Logger logger = vc.getMsgLogger(); |
| if (logger != null && logger.isLoggingLevel(Level.SEVERE)) { |
| logger.write(Level.SEVERE, ruleId + " = null"); //$NON-NLS-1$ |
| } |
| addInternalErrorMessage(vc); |
| } |
| |
| @Override |
| protected void preRemoveOldMessages(IEJBValidationContext vc, Map targets) throws ValidationException { |
| List validatedClasses = new ArrayList(); |
| |
| try { |
| String[] uris = vc.getURIs(); |
| for(int i=0; i<uris.length; i++) { |
| String uriInst = uris[i]; |
| if((uriInst == null) || (uriInst.length() == 0)) { |
| continue; |
| } |
| |
| Object id = EJBValidationRuleFactory.getFactory().getRuleId(vc, uriInst); |
| if(id == null) { |
| Object[] clazzAndBean = (Object[])vc.loadModel(uriInst, null); // Don't need a second parameter, but can't cast a RefObject to an Object[], so use the second load method. |
| if(clazzAndBean == null) { |
| // Log, add "Cannot validate" to task list, and return. |
| logMissingRule(vc, id); |
| continue; |
| } |
| |
| // In the clazzAndBean object array, the first entry is the JavaClass, |
| // and the rest of the entries are the EnterpriseBean instances which |
| // use the JavaClass. |
| JavaClass clazz = (JavaClass)clazzAndBean[0]; |
| List beans = (List)clazzAndBean[1]; |
| |
| // The validatedClass set keeps track of JavaClasses |
| // that have changed, and this set is used to determine |
| // whose children need to be found and validated. |
| // Validation is performed after all of the changed files |
| // are validated so that all of the children of all of |
| // the changed files can be searched for at once. Searching |
| // once on a group produces performance savings because |
| // the type hierarchy method takes a non-trivial amount |
| // of time when there's a large group of deltas. |
| validatedClasses.add(clazz); |
| |
| if((beans == null) || (beans.size() == 0)) { |
| // The JavaClass itself is not part of an enterprise bean, but one of its children may be. |
| } |
| else { |
| Iterator iterator = beans.iterator(); |
| while(iterator.hasNext()) { |
| EnterpriseBean bean = (EnterpriseBean)iterator.next(); |
| id = EJBValidationRuleFactory.getFactory().getRuleId(vc, clazz, bean); |
| |
| IValidationRule clazzRule = EJBValidationRuleFactory.getFactory().getRule(vc, id); |
| if(clazzRule == null) { |
| // This has already been logged by the AbstractEJBValidationRuleFactory (if it's |
| // an error - this is expected if the key is a primitive primary key). |
| continue; |
| } |
| |
| setValidated(clazzRule.getId(), bean, clazz); |
| } |
| } |
| |
| } |
| else { |
| EJBJar ejbJar = (EJBJar)vc.loadModel(EJBValidatorModelEnum.EJB_MODEL); |
| if(ejbJar == null) { |
| // Log, add "Cannot validate" to task list, and return. |
| continue; |
| } |
| |
| IValidationRule ejbExtRule = EJBValidationRuleFactory.getFactory().getRule(vc, id); |
| if(ejbExtRule == null) { |
| // This has already been logged by the AbstractEJBValidationRuleFactory, so just |
| // need to add "Cannot validate" to the task list. |
| continue; |
| } |
| |
| setValidated(ejbExtRule.getId(), null, ejbJar); |
| } |
| } // end for |
| |
| // Always validate ejb-jar.xml, because a change to one of the files it references |
| // may mean that it needs to be revalidated. |
| EJBJar ejbJar = (EJBJar)vc.loadModel(EJBValidatorModelEnum.EJB_MODEL); |
| if(ejbJar != null) { |
| Object id = EJBValidationRuleFactory.getFactory().getRuleId(vc, J2EEConstants.EJBJAR_DD_SHORT_NAME); |
| if(id == null) { |
| // Log, add "Cannot validate" to task list, and return. |
| logMissingRule(vc, id); |
| } |
| else { |
| IValidationRule ejbJarRule = EJBValidationRuleFactory.getFactory().getRule(vc, id); |
| if(ejbJarRule == null) { |
| logMissingRule(vc, id); |
| } else { |
| setValidated(ejbJarRule.getId(), null, ejbJar); |
| } |
| } |
| } |
| |
| if(validatedClasses.size() > 0) { |
| // Check the children of the changed classes. |
| // This check must be done before the dependents, because |
| // the dependents of the children classes must be checked |
| // as well. |
| |
| // Class never validated before, so check its children |
| for (int vC = 0; vC<validatedClasses.size(); vC++) { |
| List beans = (List)vc.loadModel(EJBValidatorModelEnum.EJB, new Object[]{validatedClasses.get(vC)}); |
| if((beans == null) || (beans.size() == 0)) { |
| // The class is not a member of an enterprise bean. |
| continue; |
| } |
| Set rootValidatedClass = new HashSet(); |
| rootValidatedClass.add(validatedClasses.get(vC)); |
| JavaClass[] children = (JavaClass[])vc.loadModel(EJBValidatorModelEnum.CHILDREN, new Object[]{vc.getReporter(), rootValidatedClass}); |
| if((children != null) && (children.length > 0)) { |
| Iterator bciterator = null; |
| Object id = null; |
| for(int c=0; c<children.length; c++) { |
| JavaClass child = children[c]; |
| beans = (List)vc.loadModel(EJBValidatorModelEnum.EJB, new Object[]{child}); |
| // The child is not a member of an enterprise bean. |
| if((beans == null) || (beans.size() == 0)) |
| continue; |
| bciterator = beans.iterator(); |
| while(bciterator.hasNext()) { |
| EnterpriseBean bean = (EnterpriseBean)bciterator.next(); |
| id = EJBValidationRuleFactory.getFactory().getRuleId(vc, child, bean); |
| IValidationRule clazzRule = EJBValidationRuleFactory.getFactory().getRule(vc, id); |
| // This has already been logged by the AbstractEJBValidationRuleFactory, so just need to add "Cannot validate" to the task list. |
| if(clazzRule == null) |
| continue; |
| setValidated(clazzRule.getId(), bean, child); |
| } |
| } |
| } |
| } |
| validatedClasses.clear(); // Don't need this cache any more; free the memory. |
| } |
| |
| // Now, validate the dependents. |
| targets.putAll(_validated); |
| Iterator iterator = targets.keySet().iterator(); |
| while(iterator.hasNext()) { |
| Object id = iterator.next(); |
| IValidationRule rule = EJBValidationRuleFactory.getFactory().getRule(vc, id); |
| if(rule == null) { |
| continue; |
| } |
| |
| Set contexts = (Set)targets.get(id); |
| if(contexts == null) { |
| continue; |
| } |
| |
| Iterator cIterator = contexts.iterator(); |
| while(cIterator.hasNext()) { |
| TargetObject to = (TargetObject)cIterator.next(); |
| Object targetParent = to.getTargetParent(); |
| Object target = to.getTarget(); |
| Set dependents = rule.getDependents(); |
| if(dependents == null) { |
| continue; |
| } |
| |
| Iterator dIterator = dependents.iterator(); |
| while(dIterator.hasNext()) { |
| try { |
| IValidationRule dRule = (IValidationRule)dIterator.next(); |
| Object dRuleTarget = dRule.getTarget(targetParent, target); |
| if(dRuleTarget != null) { |
| setValidated(dRule.getId(), targetParent, dRuleTarget); |
| } |
| } |
| catch(ValidationCancelledException e) { |
| throw e; |
| } |
| catch(Throwable exc) { |
| addInternalErrorMessage(getValidationContext(), exc); |
| } |
| finally { |
| EJBValidationRuleFactory.getFactory().release(rule); |
| } |
| } |
| } |
| } |
| } |
| finally { |
| // No matter what, clear the temporary caches. |
| targets.clear(); |
| validatedClasses.clear(); |
| |
| // Now put the "validated" results in "done", because they weren't |
| // really validated; it was just a tracking mechanism. |
| targets.putAll(_validated); |
| _validated.clear(); // Clear the "validated" cache because the targets weren't really validated; they were just tracked. |
| } |
| } |
| |
| @Override |
| protected String removeOldMessagesString() { |
| return EJBValidatorModelEnum.REMOVE_OLD_MESSAGES; |
| } |
| |
| public void fullValidate(IEJBValidationContext vc) throws ValidationException { |
| removeOldMessages(vc,null); // null == no IFileDelta, null = don't track targets |
| |
| |
| EJBJar ejbJar = (EJBJar)vc.loadModel(EJBValidatorModelEnum.EJB_MODEL); |
| if(ejbJar == null) { |
| // Log, add "Cannot validate" to task list, and return. |
| // EJBProjectResources will already have logged the problem. |
| |
| IMessage mssg = vc.getMessage(); |
| mssg.setId(IEJBValidatorMessageConstants.CHKJ2905); |
| vc.addMessage(mssg); |
| return; |
| } |
| |
| Object id = EJBValidationRuleFactory.getFactory().getRuleId(vc, J2EEConstants.EJBJAR_DD_SHORT_NAME); |
| if(id == null) { |
| // Log, add "Cannot validate" to task list, and return. |
| logMissingRule(vc, J2EEConstants.EJBJAR_DD_SHORT_NAME); |
| return; |
| } |
| IValidationRule ejbJarRule = EJBValidationRuleFactory.getFactory().getRule(vc, id); |
| if(ejbJarRule == null) { |
| logMissingRule(vc, id); |
| return; |
| } |
| run(ejbJarRule, null, ejbJar); // true= full validation |
| |
| List beans = ejbJar.getEnterpriseBeans(); |
| Iterator iterator = beans.iterator(); |
| id = null; |
| |
| while(iterator.hasNext()) { |
| EnterpriseBean bean = (EnterpriseBean)iterator.next(); |
| JavaClass[] classes = getJavaClass(bean); |
| for(int i=0; i<classes.length; i++) { |
| JavaClass clazz = classes[i]; |
| id = EJBValidationRuleFactory.getFactory().getRuleId(vc, clazz, bean); |
| |
| IValidationRule clazzRule = EJBValidationRuleFactory.getFactory().getRule(vc, id); |
| if(clazzRule == null) { |
| // This has already been logged by the AbstractEJBValidationRuleFactory (if it's |
| // an error - this is expected if the key is a primitive primary key). |
| continue; |
| } |
| |
| run(clazzRule, bean, clazz); // true = full validation |
| } |
| } |
| } |
| |
| protected JavaClass[] getJavaClass(EnterpriseBean bean) { |
| int count = 0; |
| JavaClass[] classes = new JavaClass[6]; |
| |
| JavaClass ejbClass = bean.getEjbClass(); |
| if((ejbClass != null) && (ejbClass.isExistingType())) { |
| classes[count++] = ejbClass; |
| } |
| |
| JavaClass remoteClass = bean.getRemoteInterface(); |
| if((remoteClass != null) && (remoteClass.isExistingType())) { |
| classes[count++] = remoteClass; |
| } |
| |
| JavaClass localClass = bean.getLocalInterface(); |
| if((localClass != null) && (localClass.isExistingType())) { |
| classes[count++] = localClass; |
| } |
| |
| JavaClass homeClass = bean.getHomeInterface(); |
| if((homeClass != null) && (homeClass.isExistingType())) { |
| classes[count++] = homeClass; |
| } |
| |
| JavaClass localHomeClass = bean.getLocalHomeInterface(); |
| if((localHomeClass != null) && (localHomeClass.isExistingType())) { |
| classes[count++] = localHomeClass; |
| } |
| |
| if(bean instanceof Entity) { |
| JavaClass key = ((Entity)bean).getPrimaryKey(); |
| if((key != null) && (key.isExistingType())) { |
| classes[count++] = key; |
| } |
| } |
| |
| if(count == 6) { |
| return classes; |
| } |
| |
| JavaClass[] result = new JavaClass[count]; |
| System.arraycopy(classes, 0, result, 0, count); |
| return result; |
| } |
| |
| public void incrementalValidate(IEJBValidationContext vc) throws ValidationException { |
| Map targets = new HashMap(); |
| try { |
| removeOldMessages(vc,targets); |
| |
| Iterator iterator = targets.keySet().iterator(); |
| while(iterator.hasNext()) { |
| Object id = iterator.next(); |
| IValidationRule rule = EJBValidationRuleFactory.getFactory().getRule(vc, id); |
| if(rule == null) { |
| continue; |
| } |
| |
| Set contexts = (Set)targets.get(id); |
| if(contexts == null) { |
| continue; |
| } |
| |
| Iterator cIterator = contexts.iterator(); |
| while(cIterator.hasNext()) { |
| TargetObject to = (TargetObject)cIterator.next(); |
| run(rule, to.getTargetParent(), to.getTarget()); |
| } |
| } |
| } |
| finally { |
| targets.clear(); |
| targets = null; |
| } |
| } |
| |
| @Override |
| protected TargetObjectPool getTargetObjectPool() { |
| if(_targetObjectPoolSingleton == null) { |
| _targetObjectPoolSingleton = new TargetObjectPool(100); |
| } |
| return _targetObjectPoolSingleton; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jst.j2ee.internal.model.validation.AbstractEJBValidator#releaseRules(org.eclipse.jst.j2ee.internal.model.validation.ejb.IValidationRule) |
| */ |
| @Override |
| protected void releaseRules(IValidationRule rule) { |
| EJBValidationRuleFactory.getFactory().release(rule); |
| |
| } |
| |
| public ISchedulingRule getSchedulingRule(IValidationContext helper) { |
| return null; |
| } |
| |
| @Override |
| public void cleanup(IReporter reporter){ |
| // clear the map when the ejb validator is done see bug 187286 |
| EJBValidationRuleFactory.getFactory().clearRuleMap(reporter); |
| } |
| |
| @Override |
| public void validationFinishing(IProject project, ValidationState state, IProgressMonitor monitor) { |
| HashMap helperMap = ValidationRuleUtility.getHelperMap(project); |
| helperMap.clear(); |
| ValidationRuleUtility.projectHelperMap.remove( helperMap ); |
| helperMap = null; |
| super.validationFinishing(project, state, monitor); |
| } |
| |
| } |