/******************************************************************************* * Copyright (c) 2007 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.seam.internal.core.validation; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.osgi.util.NLS; import org.eclipse.wst.validation.internal.core.ValidationException; import org.eclipse.wst.validation.internal.provisional.core.IReporter; import org.jboss.tools.common.el.core.resolver.TypeInfoCollector; import org.jboss.tools.common.java.IJavaSourceReference; import org.jboss.tools.common.model.XModelObject; import org.jboss.tools.common.model.util.EclipseResourceUtil; import org.jboss.tools.common.text.ITextSourceReference; import org.jboss.tools.common.validation.ContextValidationHelper; import org.jboss.tools.common.validation.IPreferenceInfo; import org.jboss.tools.common.validation.IProjectValidationContext; import org.jboss.tools.common.validation.IValidatingProjectSet; import org.jboss.tools.common.validation.IValidatingProjectTree; import org.jboss.tools.common.validation.IValidator; import org.jboss.tools.common.validation.PreferenceInfoManager; import org.jboss.tools.common.validation.ValidationUtil; import org.jboss.tools.common.validation.ValidatorManager; import org.jboss.tools.common.validation.internal.SimpleValidatingProjectTree; import org.jboss.tools.common.validation.internal.ValidatingProjectSet; import org.jboss.tools.jst.web.kb.IKbProject; import org.jboss.tools.jst.web.kb.KbProjectFactory; import org.jboss.tools.jst.web.kb.internal.KbProject; import org.jboss.tools.jst.web.kb.internal.validation.KBValidator; import org.jboss.tools.jst.web.model.project.ext.store.XMLValueInfo; import org.jboss.tools.seam.core.BijectedAttributeType; import org.jboss.tools.seam.core.IBijectedAttribute; import org.jboss.tools.seam.core.ISeamAnnotatedFactory; import org.jboss.tools.seam.core.ISeamComponent; import org.jboss.tools.seam.core.ISeamComponentDeclaration; import org.jboss.tools.seam.core.ISeamComponentMethod; import org.jboss.tools.seam.core.ISeamContextVariable; import org.jboss.tools.seam.core.ISeamFactory; import org.jboss.tools.seam.core.ISeamJavaComponentDeclaration; import org.jboss.tools.seam.core.ISeamProject; import org.jboss.tools.seam.core.ISeamProperty; import org.jboss.tools.seam.core.ISeamXmlComponentDeclaration; import org.jboss.tools.seam.core.ISeamXmlFactory; import org.jboss.tools.seam.core.ScopeType; import org.jboss.tools.seam.core.SeamComponentMethodType; import org.jboss.tools.seam.core.SeamCoreBuilder; import org.jboss.tools.seam.core.SeamCoreMessages; import org.jboss.tools.seam.core.SeamCorePlugin; import org.jboss.tools.seam.core.SeamPreferences; import org.jboss.tools.seam.core.SeamProjectsSet; import org.jboss.tools.seam.core.SeamUtil; import org.jboss.tools.seam.core.project.facet.SeamRuntime; import org.jboss.tools.seam.internal.core.DataModelSelectionAttribute; import org.jboss.tools.seam.internal.core.SeamComponentDeclaration; import org.jboss.tools.seam.internal.core.SeamProject; import org.jboss.tools.seam.internal.core.SeamTextSourceReference; import org.jboss.tools.seam.pages.xml.model.SeamPagesConstants; /** * Validator for Java and XML files. * @author Alexey Kazakov */ public class SeamCoreValidator extends SeamValidationErrorManager implements IValidator { public static final String ID = "org.jboss.tools.seam.core.CoreValidator"; //$NON-NLS-1$ public static final int NONUNIQUE_COMPONENT_NAME_MESSAGE_ID = 1; public static final int DUPLICATE_REMOVE_MESSAGE_ID = 2; public static final int DUPLICATE_DESTROY_MESSAGE_ID = 3; public static final int DUPLICATE_CREATE_MESSAGE_ID = 4; public static final int DUPLICATE_UNWRAP_MESSAGE_ID = 5; public static final int DESTROY_METHOD_BELONGS_TO_STATELESS_SESSION_BEAN_MESSAGE_ID = 6; public static final int CREATE_DOESNT_BELONG_TO_COMPONENT_MESSAGE_ID = 7; public static final int UNWRAP_DOESNT_BELONG_TO_COMPONENT_MESSAGE_ID = 8; public static final int OBSERVER_DOESNT_BELONG_TO_COMPONENT_MESSAGE_ID = 9; public static final int STATEFUL_COMPONENT_DOES_NOT_CONTAIN_REMOVE_ID = 10; public static final int STATEFUL_COMPONENT_DOES_NOT_CONTAIN_DESTROY_ID = 11; public static final int STATEFUL_COMPONENT_WRONG_SCOPE_ID = 12; public static final int ENTITY_COMPONENT_WRONG_SCOPE_ID = 13; public static final int UNKNOWN_COMPONENT_PROPERTY_ID = 14; private ISeamProject seamProject; private SeamProjectsSet set; private String projectName; /* * (non-Javadoc) * @see org.jboss.tools.jst.web.kb.validation.IValidator#getId() */ public String getId() { return ID; } public String getBuilderId() { return SeamCoreBuilder.BUILDER_ID; } /* * (non-Javadoc) * @see org.jboss.tools.jst.web.kb.validation.IValidator#getValidatingProjects(org.eclipse.core.resources.IProject) */ public IValidatingProjectTree getValidatingProjects(IProject project) { return getSeamValidatingProjects(project); } private static final String SHORT_ID = "jboss.seam.core"; //$NON-NLS-1$ public static IValidatingProjectTree getSeamValidatingProjects(IProject project) { SeamProjectsSet set = new SeamProjectsSet(project); IProject war = set.getWarProject(); IProjectValidationContext rootContext = null; if(war!=null && war.isAccessible()) { IKbProject kbProject = KbProjectFactory.getKbProject(war, false); if(kbProject!=null) { rootContext = kbProject.getValidationContext(); } else { KbProject.checkKBBuilderInstalled(war); ISeamProject seamProject = SeamCorePlugin.getSeamProject(war, false); if(seamProject!=null) { rootContext = seamProject.getValidationContext(); } } } if(rootContext==null) { ISeamProject seamProject = SeamCorePlugin.getSeamProject(project, false); if(seamProject!=null) { rootContext = seamProject.getValidationContext(); war = project; } } Set<IProject> projects = new HashSet<IProject>(); IProject[] array = set.getAllProjects(); for (int i = 0; i < array.length; i++) { if(array[i].isAccessible()) { projects.add(array[i]); } } IValidatingProjectSet projectSet = new ValidatingProjectSet(war, projects, rootContext); return new SimpleValidatingProjectTree(projectSet); } /* * (non-Javadoc) * @see org.jboss.tools.jst.web.kb.validation.IValidator#isEnabled(org.eclipse.core.resources.IProject) */ public boolean isEnabled(IProject project) { return SeamPreferences.isValidationEnabled(project); } /* * (non-Javadoc) * @see org.jboss.tools.jst.web.kb.validation.IValidator#shouldValidate(org.eclipse.core.resources.IProject) */ public boolean shouldValidate(IProject project) { try { return project != null && project.isAccessible() && project.hasNature(ISeamProject.NATURE_ID) && validateBuilderOrder(project) && isPreferencesEnabled(project); } catch (CoreException e) { SeamCorePlugin.getDefault().logError(e); } return false; } private boolean validateBuilderOrder(IProject project) throws CoreException { return KBValidator.validateBuilderOrder(project, getBuilderId(), getId(), SeamPreferences.getInstance()); } /* * (non-Javadoc) * @see org.jboss.tools.jst.web.kb.internal.validation.ValidationErrorManager#init(org.eclipse.core.resources.IProject, org.jboss.tools.jst.web.kb.internal.validation.ContextValidationHelper, org.jboss.tools.jst.web.kb.internal.validation.ValidatorManager, org.eclipse.wst.validation.internal.provisional.core.IReporter, org.jboss.tools.jst.web.kb.validation.IValidationContext) */ @Override public void init(IProject project, ContextValidationHelper validationHelper, IProjectValidationContext validationContext, org.eclipse.wst.validation.internal.provisional.core.IValidator manager, IReporter reporter) { super.init(project, validationHelper, validationContext, manager, reporter); set = new SeamProjectsSet(project); IProject warProject = set.getWarProject(); // Fix for JBIDE-7622: set these variables to null due to prevent wrong project validations --->>> seamProject = null; projectName = null; // <<<--- if(warProject.isAccessible()) { seamProject = SeamCorePlugin.getSeamProject(warProject, false); projectName = seamProject.getProject().getName(); } } private boolean isPreferencesEnabled(IProject project) { return isEnabled(project) && SeamPreferences.shouldValidateCore(project); } /* * (non-Javadoc) * @see org.jboss.tools.jst.web.kb.validation.IValidator#validate(java.util.Set, org.eclipse.core.resources.IProject, org.jboss.tools.jst.web.kb.internal.validation.ContextValidationHelper, org.jboss.tools.jst.web.kb.validation.IProjectValidationContext, org.jboss.tools.jst.web.kb.internal.validation.ValidatorManager, org.eclipse.wst.validation.internal.provisional.core.IReporter) */ public IStatus validate(Set<IFile> changedFiles, IProject project, ContextValidationHelper validationHelper, IProjectValidationContext context, ValidatorManager manager, IReporter reporter) throws ValidationException { init(project, validationHelper, context, manager, reporter); if(seamProject==null) { return OK_STATUS; } displaySubtask(SeamValidationMessages.SEARCHING_RESOURCES, new String[]{projectName}); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); Set<ISeamComponent> checkedComponents = new HashSet<ISeamComponent>(); Set<String> markedDuplicateFactoryNames = new HashSet<String>(); // Collect all resources which we must validate. Set<IPath> resources = new HashSet<IPath>(); // Resources which we have to validate. Set<IPath> newResources = new HashSet<IPath>(); // New (unlinked) resources file boolean validateUnnamedResources = false; for(IFile currentFile : changedFiles) { if(reporter.isCancelled()) { break; } if(!validateUnnamedResources) { String fileName = currentFile.getName().toLowerCase(); // We need to check only file names here. validateUnnamedResources = fileName.endsWith(".java") || fileName.endsWith(".properties") || fileName.equals("components.xml"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } if (ValidationUtil.checkFileExtensionForJavaAndXml(currentFile)) { resources.add(currentFile.getFullPath()); // Get new variable names from model Set<String> newVariableNamesOfChangedFile = getVariablesNameByResource(currentFile.getFullPath()); Set<String> oldDeclarationsOfChangedFile = validationContext.getVariableNamesByCoreResource(SHORT_ID, currentFile.getFullPath(), true); for (String newVariableName : newVariableNamesOfChangedFile) { // Collect resources with new variable name. Set<IPath> linkedResources = validationContext.getCoreResourcesByVariableName(SHORT_ID, newVariableName, false); if(linkedResources!=null) { resources.addAll(linkedResources); } resources.addAll(getAllResourceOfComponent(currentFile.getFullPath())); } // Get old variable names which were linked with this resource. Set<String> oldVariablesNamesOfChangedFile = validationContext.getVariableNamesByCoreResource(SHORT_ID, currentFile.getFullPath(), false); if(oldVariablesNamesOfChangedFile!=null) { for (String name : oldVariablesNamesOfChangedFile) { Set<IPath> linkedResources = validationContext.getCoreResourcesByVariableName(SHORT_ID, name, false); if(linkedResources!=null) { resources.addAll(linkedResources); } } } // Save old declarations for EL validation. We need to validate all EL resources which use this variable name but only if the variable has been changed. if(oldDeclarationsOfChangedFile!=null) { for (String name : oldDeclarationsOfChangedFile) { validationContext.addVariableNameForELValidation(SHORT_ID, name); } } newResources.add(currentFile.getFullPath()); } } // Validate all collected linked resources. // Remove all links between collected resources and variables names because they will be linked again during validation. validationContext.removeLinkedCoreResources(SHORT_ID, resources); Set<IFile> filesToValidate = new HashSet<IFile>(); // We have to remove markers from all collected source files first for (IPath linkedResource : resources) { IFile file = root.getFile(linkedResource); if(file!=null && shouldBeValidated(file)) { filesToValidate.add(file); removeAllMessagesFromResource(file); } } // Then we can validate them for (IFile file : filesToValidate) { validateComponent(file.getFullPath(), checkedComponents, newResources); validateFactory(file.getFullPath(), markedDuplicateFactoryNames); validatePageXML(file); validateXMLVersion(file); } // If changed files are *.java or component.xml then re-validate all unnamed resources. if(validateUnnamedResources) { Set<IPath> unnamedResources = validationContext.getUnnamedCoreResources(SHORT_ID); newResources.addAll(unnamedResources); for (IPath path : newResources) { IFile file = root.getFile(path); if(file!=null && file.isAccessible()) { if(!resources.contains(path)) { removeAllMessagesFromResource(file); } displaySubtask(SeamValidationMessages.VALIDATING_RESOURCE, new String[]{projectName, path.toString()}); Set<ISeamJavaComponentDeclaration> declarations = ((SeamProject)seamProject).findJavaDeclarations(path); for (ISeamJavaComponentDeclaration d : declarations) { validateMethodsOfUnknownComponent(d); } } } } return OK_STATUS; } /* * (non-Javadoc) * @see org.jboss.tools.jst.web.kb.validation.IValidator#validateAll(org.eclipse.core.resources.IProject, org.jboss.tools.jst.web.kb.internal.validation.ContextValidationHelper, org.jboss.tools.jst.web.kb.validation.IProjectValidationContext, org.jboss.tools.jst.web.kb.internal.validation.ValidatorManager, org.eclipse.wst.validation.internal.provisional.core.IReporter) */ public IStatus validateAll(IProject project, ContextValidationHelper validationHelper, IProjectValidationContext context, ValidatorManager manager, IReporter reporter) throws ValidationException { init(project, validationHelper, context, manager, reporter); if(seamProject==null) { return OK_STATUS; } for (IProject iProject : set.getAllProjects()) { removeAllMessagesFromResource(iProject); } ISeamComponent[] components = seamProject.getComponents(); for (ISeamComponent component : components) { if(reporter.isCancelled()) { return OK_STATUS; } Set<ISeamComponentDeclaration> declarations = component.getAllDeclarations(); for (ISeamComponentDeclaration seamComponentDeclaration : declarations) { validateComponent(component); break; } } ISeamFactory[] factories = seamProject.getFactories(); Set<String> markedDuplicateFactoryNames = new HashSet<String>(); for (ISeamFactory factory : factories) { if(reporter.isCancelled()) { return OK_STATUS; } validateFactory(factory, markedDuplicateFactoryNames); } ISeamJavaComponentDeclaration[] values = ((SeamProject)seamProject).getAllJavaComponentDeclarations(); for (ISeamJavaComponentDeclaration d : values) { if(reporter.isCancelled()) { return OK_STATUS; } displaySubtask(SeamValidationMessages.VALIDATING_CLASS, new String[]{projectName, d.getClassName()}); validateMethodsOfUnknownComponent(d); } IResource webContent = set.getViewsFolder(); if(webContent instanceof IContainer && webContent.isAccessible()) { validateAllPageXMLFiles((IContainer)webContent); } return OK_STATUS; } void validateAllPageXMLFiles(IContainer c) { if(c.isAccessible()) { IResource[] rs = null; try { rs = c.members(); } catch (CoreException e) { SeamCorePlugin.getDefault().logError(e); return; } for (int i = 0; i < rs.length; i++) { if(rs[i] instanceof IContainer) { validateAllPageXMLFiles((IContainer)rs[i]); } else if(rs[i] instanceof IFile) { validatePageXML((IFile)rs[i]); } } } } private void validateFactory(IPath sourceFilePath, Set<String> markedDuplicateFactoryNames) { Set<ISeamFactory> factories = seamProject.getFactoriesByPath(sourceFilePath); for (ISeamFactory factory : factories) { validateFactory(factory, markedDuplicateFactoryNames); } } private void validateFactory(ISeamFactory factory, Set<String> markedDuplicateFactoryNames) { if(SeamUtil.isJar(factory.getSourcePath())) { return; } String factoryName = factory.getName(); if(factoryName!=null) { displaySubtask(SeamValidationMessages.VALIDATING_FACTORY, new String[]{projectName, factoryName}); } if(factory instanceof ISeamAnnotatedFactory) { validateAnnotatedFactory((ISeamAnnotatedFactory)factory, markedDuplicateFactoryNames); } else { validateXmlFactory((ISeamXmlFactory)factory, markedDuplicateFactoryNames); } } private void validateXmlFactory(ISeamXmlFactory factory, Set<String> markedDuplicateFactoryNames) { String name = factory.getName(); if(name==null) { SeamCorePlugin.getDefault().logError(NLS.bind(SeamCoreMessages.SEAM_CORE_VALIDATOR_FACTORY_METHOD_MUST_HAVE_NAME,factory.getResource())); return; } validateFactoryName(factory, name, markedDuplicateFactoryNames, false); } private void validateAnnotatedFactory(ISeamAnnotatedFactory factory, Set<String> markedDuplicateFactoryNames) { IMember sourceMember = factory.getSourceMember(); if(sourceMember instanceof IMethod) { String factoryName = factory.getName(); if(factoryName==null) { // Unknown factory name SeamCorePlugin.getDefault().logError(NLS.bind(SeamCoreMessages.SEAM_CORE_VALIDATOR_FACTORY_METHOD_MUST_HAVE_NAME,factory.getResource())); return; } validateFactoryName(factory, factoryName, markedDuplicateFactoryNames, true); } else { // factory must be java method! // JDT should mark it. } } private void validateFactoryName(ISeamFactory factory, String factoryName, Set<String> markedDuplicateFactoryNames, boolean validateUnknownName) { ScopeType factoryScope = factory.getScope(); Set<ISeamContextVariable> variables = seamProject.getVariablesByName(factoryName); boolean unknownVariable = true; boolean firstDuplicateVariableWasMarked = false; for (ISeamContextVariable variable : variables) { if(variable instanceof ISeamFactory) { if(variable!=factory && !markedDuplicateFactoryNames.contains(factoryName) && (factoryScope == variable.getScope() || factoryScope.getPriority()>variable.getScope().getPriority())) { // Duplicate factory name. Mark it. // Save link to factory resource. ITextSourceReference location = null; if(!firstDuplicateVariableWasMarked) { firstDuplicateVariableWasMarked = true; // mark original factory validationContext.addLinkedCoreResource(SHORT_ID, factoryName, factory.getSourcePath(), true); location = SeamUtil.getLocationOfName(factory); this.addError(SeamValidationMessages.DUPLICATE_VARIABLE_NAME, SeamPreferences.DUPLICATE_VARIABLE_NAME, new String[]{factoryName}, location, factory.getResource()); } // Mark duplicate variable. if(!SeamUtil.isJar(variable.getSourcePath())) { IResource resource = SeamUtil.getComponentResourceWithName(variable); validationContext.addLinkedCoreResource(SHORT_ID, factoryName, resource.getFullPath(), true); location = SeamUtil.getLocationOfName(variable); this.addError(SeamValidationMessages.DUPLICATE_VARIABLE_NAME, SeamPreferences.DUPLICATE_VARIABLE_NAME, new String[]{factoryName}, location, resource); } } } else { // We know that variable name unknownVariable = false; } } if(firstDuplicateVariableWasMarked) { markedDuplicateFactoryNames.add(factoryName); } boolean voidReturnType = false; if(factory instanceof ISeamAnnotatedFactory) { IMember sourceMember = ((ISeamAnnotatedFactory)factory).getSourceMember(); if(sourceMember instanceof IMethod) { IMethod method = (IMethod)sourceMember; try { String returnType = method.getReturnType(); if("V".equals(returnType)) { //$NON-NLS-1$ // return type is void voidReturnType = true; } } catch (JavaModelException e) { SeamCorePlugin.getDefault().logError(SeamCoreMessages.SEAM_CORE_VALIDATOR_ERROR_VALIDATING_SEAM_CORE, e); } } } if(unknownVariable && validateUnknownName && voidReturnType) { // mark unknown factory name // save link to factory resource validationContext.addLinkedCoreResource(SHORT_ID, factoryName, factory.getSourcePath(), true); this.addError(SeamValidationMessages.UNKNOWN_FACTORY_NAME, SeamPreferences.UNKNOWN_FACTORY_NAME, new String[]{factoryName}, SeamUtil.getLocationOfName(factory), factory.getResource()); } } private void validateComponent(IPath sourceFilePath, Set<ISeamComponent> checkedComponents, Set<IPath> unnamedResources) { Set<ISeamComponent> components = seamProject.getComponentsByPath(sourceFilePath); if(components.isEmpty()) { unnamedResources.add(sourceFilePath); return; } for (ISeamComponent component : components) { // Don't validate one component twice. if(!checkedComponents.contains(component)) { validateComponent(component); checkedComponents.add(component); } } } /* * Returns set of variables which are linked with this resource */ private Set<String> getVariablesNameByResource(IPath resourcePath) { Set<ISeamContextVariable> variables = seamProject.getVariablesByPath(resourcePath); Set<String> result = new HashSet<String>(); if(variables!=null) { for (ISeamContextVariable variable : variables) { String name = variable.getName(); result.add(name); } } return result; } /* * Collect all resources of all declarations of all components which is declared in the source. */ private Set<IPath> getAllResourceOfComponent(IPath sourceComponentFilePath) { Set<IPath> result = new HashSet<IPath>(); Set<ISeamComponent> components = seamProject.getComponentsByPath(sourceComponentFilePath); for (ISeamComponent component : components) { Set<ISeamComponentDeclaration> declarations = component.getAllDeclarations(); for (ISeamComponentDeclaration seamComponentDeclaration : declarations) { result.add(seamComponentDeclaration.getResource().getFullPath()); } } return result; } /* * Validates the component */ private void validateComponent(ISeamComponent component) { ISeamJavaComponentDeclaration firstJavaDeclaration = component.getJavaDeclaration(); if(firstJavaDeclaration!=null) { String componentName = component.getName(); if(componentName!=null) { displaySubtask(SeamValidationMessages.VALIDATING_COMPONENT, new String[]{projectName, componentName}); } HashMap<Integer, ISeamJavaComponentDeclaration> usedPrecedences = new HashMap<Integer, ISeamJavaComponentDeclaration>(); Set<ISeamJavaComponentDeclaration> markedDeclarations = new HashSet<ISeamJavaComponentDeclaration>(); int firstJavaDeclarationPrecedence = firstJavaDeclaration.getPrecedence(); usedPrecedences.put(firstJavaDeclarationPrecedence, firstJavaDeclaration); Set<ISeamComponentDeclaration> declarations = component.getAllDeclarations(); for (ISeamComponentDeclaration declaration : declarations) { if(declaration instanceof ISeamJavaComponentDeclaration) { ISeamJavaComponentDeclaration jd = (ISeamJavaComponentDeclaration)declaration; //do not check files declared in another project // if(jd.getSeamProject() != seamProject) continue; IType type = (IType)jd.getSourceMember(); boolean sourceJavaDeclaration = !type.isBinary(); if(sourceJavaDeclaration) { // Save link between component name and java source file. validationContext.addLinkedCoreResource(SHORT_ID, componentName, declaration.getSourcePath(), true); // Save link between component name and all supers of java declaration. try { IType[] superTypes = TypeInfoCollector.getSuperTypes(type).getSuperTypes(); for (int i = 0; superTypes != null && i < superTypes.length; i++) { if(!superTypes[i].isBinary()) { IPath path = superTypes[i].getResource().getFullPath(); validationContext.addLinkedCoreResource(SHORT_ID, componentName, path, true); } } } catch (JavaModelException e) { SeamCorePlugin.getPluginLog().logError(e); } } if(declaration!=firstJavaDeclaration) { // Validate @Name // Component class with the same component name. Check precedence. ISeamJavaComponentDeclaration javaDeclaration = (ISeamJavaComponentDeclaration)declaration; int javaDeclarationPrecedence = javaDeclaration.getPrecedence(); ISeamJavaComponentDeclaration checkedDeclaration = usedPrecedences.get(javaDeclarationPrecedence); if(checkedDeclaration==null) { usedPrecedences.put(javaDeclarationPrecedence, javaDeclaration); } else if(sourceJavaDeclaration) { boolean sourceCheckedDeclaration = !((IType)checkedDeclaration.getSourceMember()).isBinary(); IResource javaDeclarationResource = javaDeclaration.getResource(); // Mark nonunique name. if(!markedDeclarations.contains(checkedDeclaration) && sourceCheckedDeclaration) { // Mark first wrong declaration with that name IResource checkedDeclarationResource = checkedDeclaration.getResource(); ITextSourceReference location = ((SeamComponentDeclaration)checkedDeclaration).getLocationFor(SeamComponentDeclaration.PATH_OF_NAME); if(!SeamUtil.isEmptyLocation(location)) { addError(SeamValidationMessages.NONUNIQUE_COMPONENT_NAME_MESSAGE, SeamPreferences.NONUNIQUE_COMPONENT_NAME, new String[]{componentName}, location, checkedDeclarationResource, NONUNIQUE_COMPONENT_NAME_MESSAGE_ID); } markedDeclarations.add(checkedDeclaration); } // Mark next wrong declaration with that name markedDeclarations.add(javaDeclaration); ITextSourceReference location = ((SeamComponentDeclaration)javaDeclaration).getLocationFor(SeamComponentDeclaration.PATH_OF_NAME); if(!SeamUtil.isEmptyLocation(location)) { addError(SeamValidationMessages.NONUNIQUE_COMPONENT_NAME_MESSAGE, SeamPreferences.NONUNIQUE_COMPONENT_NAME, new String[]{componentName}, location, javaDeclarationResource, NONUNIQUE_COMPONENT_NAME_MESSAGE_ID); } } } } } boolean source = !((IType)firstJavaDeclaration.getSourceMember()).isBinary(); if(source) { // Validate all elements in first java declaration but @Name. validateJavaDeclaration(component, firstJavaDeclaration); } } validateXmlComponentDeclarations(component); } private static final String BUILT_IN_COMPONENT_NAME_PREFIX = "org.jboss.seam."; private boolean isBuiltInComponentName(String componentName) { return componentName.startsWith(BUILT_IN_COMPONENT_NAME_PREFIX); } private void validateXmlComponentDeclarations(ISeamComponent component) { String componentName = component.getName(); if(componentName!=null) { HashMap<String, ISeamXmlComponentDeclaration> usedPrecedences = new HashMap<String, ISeamXmlComponentDeclaration>(); Set<ISeamXmlComponentDeclaration> markedDeclarations = new HashSet<ISeamXmlComponentDeclaration>(); Set<ISeamJavaComponentDeclaration> markedJavaDeclarations = new HashSet<ISeamJavaComponentDeclaration>(); Set<ISeamXmlComponentDeclaration> declarations = component.getXmlDeclarations(); ISeamXmlComponentDeclaration firstNamedDeclaration = null; for (ISeamXmlComponentDeclaration declaration : declarations) { if(SeamUtil.isJar(declaration)) { return; } //do not check files declared in another project // if(declaration.getSeamProject() != seamProject) continue; validationContext.addLinkedCoreResource(SHORT_ID, componentName, declaration.getSourcePath(), true); String precedence = declaration.getPrecedence(); if(firstNamedDeclaration == null && declaration.getName()!=null) { firstNamedDeclaration = declaration; usedPrecedences.put(precedence, declaration); } if(declaration.getName()!=null && firstNamedDeclaration!=declaration) { // Check precedence ISeamXmlComponentDeclaration checkedDeclaration = usedPrecedences.get(precedence); if(checkedDeclaration==null) { usedPrecedences.put(precedence, declaration); } else { // Mark not-unique name. if(!markedDeclarations.contains(checkedDeclaration)) { // Mark first wrong declaration with that name IResource checkedDeclarationResource = checkedDeclaration.getResource(); ITextSourceReference location = ((SeamComponentDeclaration)checkedDeclaration).getLocationFor(SeamComponentDeclaration.PATH_OF_NAME); if(!SeamUtil.isEmptyLocation(location)) { addError(SeamValidationMessages.NONUNIQUE_COMPONENT_NAME_MESSAGE, SeamPreferences.NONUNIQUE_COMPONENT_NAME, new String[]{componentName}, location, checkedDeclarationResource, NONUNIQUE_COMPONENT_NAME_MESSAGE_ID); } markedDeclarations.add(checkedDeclaration); } // Mark next wrong declaration with that name markedDeclarations.add(declaration); ITextSourceReference location = ((SeamComponentDeclaration)declaration).getLocationFor(SeamComponentDeclaration.PATH_OF_NAME); if(!SeamUtil.isEmptyLocation(location)) { addError(SeamValidationMessages.NONUNIQUE_COMPONENT_NAME_MESSAGE, SeamPreferences.NONUNIQUE_COMPONENT_NAME, new String[]{componentName}, location, declaration.getResource(), NONUNIQUE_COMPONENT_NAME_MESSAGE_ID); } } } // Check Java declarations with the same name Set<ISeamContextVariable> vars = seamProject.getVariablesByName(componentName); for (ISeamContextVariable variable : vars) { if(variable instanceof ISeamComponent) { ISeamComponent c = (ISeamComponent)variable; Set<ISeamComponentDeclaration> decls = c.getAllDeclarations(); for (ISeamComponentDeclaration dec : decls) { if(dec instanceof ISeamJavaComponentDeclaration) { ISeamJavaComponentDeclaration javaDec = (ISeamJavaComponentDeclaration)dec; // Check names if(declaration.getClassName()!=null && javaDec.getName()!=null && javaDec.getName().equals(declaration.getName())) { // Check precedences String javaPrecedence = "" + javaDec.getPrecedence(); if(javaPrecedence.equals(precedence) && !isBuiltInComponentName(componentName)) { if(!markedJavaDeclarations.contains(javaDec)) { markedJavaDeclarations.add(javaDec); ITextSourceReference location = ((SeamComponentDeclaration)javaDec).getLocationFor(SeamComponentDeclaration.PATH_OF_NAME); addError(SeamValidationMessages.NONUNIQUE_COMPONENT_NAME_MESSAGE, SeamPreferences.NONUNIQUE_COMPONENT_NAME, new String[]{componentName}, location, javaDec.getResource(), NONUNIQUE_COMPONENT_NAME_MESSAGE_ID); } if(!markedDeclarations.contains(declaration)) { markedDeclarations.add(declaration); ITextSourceReference location = ((SeamComponentDeclaration)declaration).getLocationFor(SeamComponentDeclaration.PATH_OF_NAME); addError(SeamValidationMessages.NONUNIQUE_COMPONENT_NAME_MESSAGE, SeamPreferences.NONUNIQUE_COMPONENT_NAME, new String[]{componentName}, location, declaration.getResource(), NONUNIQUE_COMPONENT_NAME_MESSAGE_ID); } } } } } } } String className = declaration.getClassName(); IType type = null; if(className!=null) { // validate class name try { IProject p = seamProject.getProject(); // type = EclipseJavaUtil.findType(EclipseResourceUtil.getJavaProject(p), className); IJavaProject javaProject = EclipseResourceUtil.getJavaProject(p); if(javaProject==null) { SeamCorePlugin.getDefault().logWarning("Can't get Java project for " + seamProject.getProject()!=null?seamProject.getProject().getName():"" + " Seam project."); return; } type = javaProject.findType(className); if(type==null) { // Mark wrong class name ITextSourceReference location = ((SeamComponentDeclaration)declaration).getLocationFor(ISeamXmlComponentDeclaration.CLASS); if(SeamUtil.isEmptyLocation(location)) { location = ((SeamComponentDeclaration)declaration).getLocationFor(ISeamXmlComponentDeclaration.NAME); } if(SeamUtil.isEmptyLocation(location)) { location = declaration; } if(!declaration.isClassNameGuessed()) { addError(SeamValidationMessages.UNKNOWN_COMPONENT_CLASS_NAME, SeamPreferences.UNKNOWN_COMPONENT_CLASS_NAME, new String[]{className}, location, declaration.getResource()); } else { addError(SeamValidationMessages.UNKNOWN_COMPONENT_CLASS_NAME, SeamPreferences.UNKNOWN_COMPONENT_CLASS_NAME_GUESS, new String[]{className}, location, declaration.getResource()); } } else if(!type.isBinary()) { validationContext.addLinkedCoreResource(SHORT_ID, componentName, type.getResource().getFullPath(), true); } } catch (JavaModelException e) { SeamCorePlugin.getDefault().logError(SeamCoreMessages.SEAM_CORE_VALIDATOR_ERROR_VALIDATING_SEAM_CORE, e); } } // validate properties Collection<ISeamProperty> properties = declaration.getProperties(); for (ISeamProperty property : properties) { if(SeamUtil.isJar(property)) { return; } String name = property.getName(); if(name==null) { return; } if(type==null && component.getJavaDeclaration()!=null) { IMember member = component.getJavaDeclaration().getSourceMember(); if(member instanceof IType) { type = (IType)member; } } if(type!=null) { boolean ok = type.isBinary() || SeamUtil.findProperty(type, name)!=null; if(!ok) { addError(SeamValidationMessages.UNKNOWN_COMPONENT_PROPERTY, SeamPreferences.UNKNOWN_COMPONENT_PROPERTY, new String[]{type.getElementName(), componentName, name}, property, declaration.getResource(), UNKNOWN_COMPONENT_PROPERTY_ID); } } } } } } private void validateEntityComponent(ISeamComponent component) { if(component.isEntity()) { ISeamJavaComponentDeclaration javaDeclaration = component.getJavaDeclaration(); ScopeType scope = component.getScope(); if(scope == ScopeType.STATELESS) { ITextSourceReference location = getScopeLocation(component); addError(SeamValidationMessages.ENTITY_COMPONENT_WRONG_SCOPE, SeamPreferences.ENTITY_COMPONENT_WRONG_SCOPE, new String[]{component.getName()}, location, javaDeclaration.getResource(), ENTITY_COMPONENT_WRONG_SCOPE_ID); } } } private ITextSourceReference getScopeLocation(ISeamComponent component) { ISeamJavaComponentDeclaration javaDeclaration = component.getJavaDeclaration(); ITextSourceReference location = ((SeamComponentDeclaration)javaDeclaration).getLocationFor(SeamComponentDeclaration.PATH_OF_SCOPE); if(SeamUtil.isEmptyLocation(location)) { location = getNameLocation(javaDeclaration); } return location; } private IJavaSourceReference getNameLocation(IJavaSourceReference source) { int length = 0; int offset = 0; try { length = source.getSourceMember().getNameRange().getLength(); offset = source.getSourceMember().getNameRange().getOffset(); } catch (JavaModelException e) { SeamCorePlugin.getDefault().logError(SeamCoreMessages.SEAM_CORE_VALIDATOR_ERROR_VALIDATING_SEAM_CORE, e); } return new SeamTextSourceReference(source.getSourceMember(), length, offset, source.getResource()); } private void validateStatefulComponent(ISeamComponent component) { if(component.isStateful()) { ISeamJavaComponentDeclaration javaDeclaration = component.getJavaDeclaration(); validateStatefulComponentMethods(SeamComponentMethodType.DESTROY, component, SeamValidationMessages.STATEFUL_COMPONENT_DOES_NOT_CONTAIN_DESTROY, SeamPreferences.STATEFUL_COMPONENT_DOES_NOT_CONTENT_DESTROY, STATEFUL_COMPONENT_DOES_NOT_CONTAIN_DESTROY_ID); validateStatefulComponentMethods(SeamComponentMethodType.REMOVE, component, SeamValidationMessages.STATEFUL_COMPONENT_DOES_NOT_CONTAIN_REMOVE, SeamPreferences.STATEFUL_COMPONENT_DOES_NOT_CONTENT_REMOVE, STATEFUL_COMPONENT_DOES_NOT_CONTAIN_REMOVE_ID); ScopeType scope = component.getScope(); if(scope == ScopeType.PAGE || scope == ScopeType.STATELESS) { ITextSourceReference location = getScopeLocation(component); addError(SeamValidationMessages.STATEFUL_COMPONENT_WRONG_SCOPE, SeamPreferences.STATEFUL_COMPONENT_WRONG_SCOPE, new String[]{component.getName()}, location, javaDeclaration.getResource(), STATEFUL_COMPONENT_WRONG_SCOPE_ID); } validateDuplicateComponentMethod(SeamComponentMethodType.REMOVE, component, SeamValidationMessages.DUPLICATE_REMOVE, SeamPreferences.DUPLICATE_REMOVE, DUPLICATE_REMOVE_MESSAGE_ID); } } private void validateStatefulComponentMethods(SeamComponentMethodType methodType, ISeamComponent component, String message, String preferenceKey, int id) { ISeamJavaComponentDeclaration javaDeclaration = component.getJavaDeclaration(); ITextSourceReference classNameLocation = getNameLocation(javaDeclaration); Set<ISeamComponentMethod> methods = javaDeclaration.getMethodsByType(methodType); if(methods==null || methods.isEmpty()) { addError(message, preferenceKey, new String[]{component.getName()}, classNameLocation, javaDeclaration.getResource(), id); } } private void validateDuplicateComponentMethods(ISeamComponent component) { validateDuplicateComponentMethod(SeamComponentMethodType.DESTROY, component, SeamValidationMessages.DUPLICATE_DESTROY, SeamPreferences.DUPLICATE_DESTROY, DUPLICATE_DESTROY_MESSAGE_ID); validateDuplicateComponentMethod(SeamComponentMethodType.CREATE, component, SeamValidationMessages.DUPLICATE_CREATE, SeamPreferences.DUPLICATE_CREATE, DUPLICATE_CREATE_MESSAGE_ID); validateDuplicateComponentMethod(SeamComponentMethodType.UNWRAP, component, SeamValidationMessages.DUPLICATE_UNWRAP, SeamPreferences.DUPLICATE_UNWRAP, DUPLICATE_UNWRAP_MESSAGE_ID); } private void validateDuplicateComponentMethod(SeamComponentMethodType methodType, ISeamComponent component, String message, String preferenceKey, int message_id) { ISeamJavaComponentDeclaration javaDeclaration = component.getJavaDeclaration(); Set<ISeamComponentMethod> methods = javaDeclaration.getMethodsByType(methodType); if(methods!=null && methods.size()>1) { for (ISeamComponentMethod method : methods) { if(javaDeclaration.getSourcePath().equals(method.getSourcePath())) { IMethod javaMethod = (IMethod)method.getSourceMember(); String methodName = javaMethod.getElementName(); ITextSourceReference methodNameLocation = getNameLocation(method); addError(message, preferenceKey, new String[]{methodName}, methodNameLocation, javaDeclaration.getResource(), message_id); } } } } private void validateJavaDeclaration(ISeamComponent component, ISeamJavaComponentDeclaration declaration) { validateBijections(declaration); validateStatefulComponent(component); validateDuplicateComponentMethods(component); validateEntityComponent(component); validateDestroyMethod(component); } private void validateBijections(ISeamJavaComponentDeclaration declaration) { Set<IBijectedAttribute> bijections = declaration.getBijectedAttributes(); if(bijections==null) { return; } for (IBijectedAttribute bijection : bijections) { if(bijection.isOfType(BijectedAttributeType.DATA_MODEL_SELECTION) || bijection.isOfType(BijectedAttributeType.DATA_MODEL_SELECTION_INDEX)) { validateDataModelSelection(declaration, bijection); } else { validateInAndOut(declaration, bijection); } } } private void validateInAndOut(ISeamJavaComponentDeclaration declaration, IBijectedAttribute bijection) { String name = bijection.getName(); if(name==null || name.startsWith("#{") || name.startsWith("${")) { //$NON-NLS-1$ //$NON-NLS-2$ return; } // Validate @In if(bijection.isOfType(BijectedAttributeType.IN)) { // save link between java source and variable name validationContext.addLinkedCoreResource(SHORT_ID, name, declaration.getSourcePath(), false); Set<ISeamContextVariable> variables = declaration.getVariablesByName(name); if(variables == null || variables.isEmpty()) variables = seamProject.getVariablesByName(name); if(variables == null || variables.isEmpty()) { ISeamProject parentProject = seamProject.getParentProject(); if(parentProject != null) { variables = parentProject.getVariablesByName(name); } } if(variables==null || variables.size()<1) { // Injection has unknown name. Mark it. IResource declarationResource = declaration.getResource(); ITextSourceReference nameRef = getNameLocation(bijection); if(nameRef == null) { nameRef = bijection; } addError(SeamValidationMessages.UNKNOWN_VARIABLE_NAME, SeamPreferences.UNKNOWN_VARIABLE_NAME, new String[]{name}, nameRef, declarationResource); } } else { // save link between java source and variable name validationContext.addLinkedCoreResource(SHORT_ID, name, declaration.getSourcePath(), true); } } private void validateDataModelSelection(ISeamJavaComponentDeclaration declaration, IBijectedAttribute bijection) { String dataModelName = bijection.getValue(); String selectionName = bijection.getName(); // save link between java source and variable name validationContext.addLinkedCoreResource(SHORT_ID, selectionName, declaration.getSourcePath(), false); if(dataModelName==null) { // here must be the only one @DataModel in the component Set<IBijectedAttribute> dataBinders = declaration.getBijectedAttributesByType(BijectedAttributeType.DATA_BINDER); ITextSourceReference location = null; if(dataBinders!=null && dataBinders.size()>1) { for (IBijectedAttribute dataBinder : dataBinders) { location = dataBinder.getLocationFor(SeamComponentDeclaration.PATH_OF_NAME); addError(SeamValidationMessages.MULTIPLE_DATA_BINDER, SeamPreferences.MULTIPLE_DATA_BINDER, location, declaration.getResource()); } } } else { // save link between java source and Data Model name validationContext.addLinkedCoreResource(SHORT_ID, dataModelName, declaration.getSourcePath(), true); Set<IBijectedAttribute> dataBinders = declaration.getBijectedAttributesByName(dataModelName); if(dataBinders!=null) { for (IBijectedAttribute dataBinder : dataBinders) { if(dataBinder.isOfType(BijectedAttributeType.DATA_BINDER) || dataBinder.isOfType(BijectedAttributeType.OUT)) { return; } } } addError(SeamValidationMessages.UNKNOWN_DATA_MODEL, SeamPreferences.UNKNOWN_DATA_MODEL, new String[]{dataModelName}, SeamUtil.getLocationOfAttribute(bijection, DataModelSelectionAttribute.VALUE), declaration.getResource()); } } /* * Validates methods of java classes. They must belong components. */ private void validateMethodsOfUnknownComponent(ISeamJavaComponentDeclaration declaration) { if(seamProject.getComponentsByPath(declaration.getSourcePath()).isEmpty()) { IMember member = declaration.getSourceMember(); try { if(member!=null && !Flags.isAbstract(member.getFlags())) { validateMethodOfUnknownComponent(SeamComponentMethodType.CREATE, declaration, SeamValidationMessages.CREATE_DOESNT_BELONG_TO_COMPONENT, SeamPreferences.CREATE_DOESNT_BELONG_TO_COMPONENT, CREATE_DOESNT_BELONG_TO_COMPONENT_MESSAGE_ID); validateMethodOfUnknownComponent(SeamComponentMethodType.UNWRAP, declaration, SeamValidationMessages.UNWRAP_DOESNT_BELONG_TO_COMPONENT, SeamPreferences.UNWRAP_DOESNT_BELONG_TO_COMPONENT, UNWRAP_DOESNT_BELONG_TO_COMPONENT_MESSAGE_ID); validateMethodOfUnknownComponent(SeamComponentMethodType.OBSERVER, declaration, SeamValidationMessages.OBSERVER_DOESNT_BELONG_TO_COMPONENT, SeamPreferences.OBSERVER_DOESNT_BELONG_TO_COMPONENT, OBSERVER_DOESNT_BELONG_TO_COMPONENT_MESSAGE_ID); } } catch (JavaModelException e) { SeamCorePlugin.getPluginLog().logError(e); } } validationContext.removeUnnamedCoreResource(SHORT_ID, declaration.getSourcePath()); } private void validateDestroyMethod(ISeamComponent component) { if(component.isStateless()) { ISeamJavaComponentDeclaration javaDeclaration = component.getJavaDeclaration(); Set<ISeamComponentMethod> methods = javaDeclaration.getMethodsByType(SeamComponentMethodType.DESTROY); if(methods==null) { return; } for (ISeamComponentMethod method : methods) { IMethod javaMethod = (IMethod)method.getSourceMember(); String methodName = javaMethod.getElementName(); if(javaDeclaration.getSourcePath().equals(javaMethod.getPath())) { validationContext.addLinkedCoreResource(SHORT_ID, component.getName(), javaDeclaration.getSourcePath(), true); ITextSourceReference methodNameLocation = getNameLocation(method); addError(SeamValidationMessages.DESTROY_METHOD_BELONGS_TO_STATELESS_SESSION_BEAN, SeamPreferences.DESTROY_METHOD_BELONGS_TO_STATELESS_SESSION_BEAN, new String[]{methodName}, methodNameLocation, method.getResource(), DESTROY_METHOD_BELONGS_TO_STATELESS_SESSION_BEAN_MESSAGE_ID); } } } } private void validateMethodOfUnknownComponent(SeamComponentMethodType methodType, ISeamJavaComponentDeclaration declaration, String message, String preferenceKey, int message_id) { Set<ISeamComponentMethod> methods = declaration.getMethodsByType(methodType); if(methods!=null && !methods.isEmpty()) { for (ISeamComponentMethod method : methods) { IMethod javaMethod = (IMethod)method.getSourceMember(); String methodName = javaMethod.getElementName(); if(declaration.getSourcePath().equals(javaMethod.getPath())) { ITextSourceReference methodNameLocation = getNameLocation(method); addError(message, preferenceKey, new String[]{methodName}, methodNameLocation, method.getResource(), message_id); validationContext.addUnnamedCoreResource(SHORT_ID, declaration.getSourcePath()); } } } else { validationContext.removeUnnamedCoreResource(SHORT_ID, declaration.getSourcePath()); } } private void validateXMLVersion(IFile file) { String ext = file.getFileExtension(); if(!"xml".equals(ext)) return; XModelObject o = EclipseResourceUtil.createObjectForResource(file); if(o == null) return; if(!o.getModelEntity().getName().startsWith("FileSeamComponent")) return; Set<String> vs = getXMLVersions(o); SeamRuntime runtime = seamProject.getRuntime(); if(runtime == null) return; String version = runtime.getVersion().toString(); String wrongVersion = null; for (String v: vs) { if(!v.startsWith(version)) { wrongVersion = v; break; } } if(wrongVersion != null) { addError( SeamValidationMessages.INVALID_XML_VERSION, SeamPreferences.INVALID_XML_VERSION, new String[]{wrongVersion, version}, file); } } private Set<String> getXMLVersions(XModelObject o) { Set<String> result = new HashSet<String>(); if(o.getModelEntity().getName().endsWith("11")) { result.add("1.1"); return result; } String sl = o.getAttributeValue("xsi:schemaLocation"); int i = 0; while(i >= 0 && i < sl.length()) { int j = sl.indexOf('-', i); if(j < 0) break; int k = sl.indexOf(".xsd", j); if(k < 0) break; String v = sl.substring(j + 1, k); if(isVersion(v)) result.add(v); i = k; } return result; } private boolean isVersion(String s) { if(s.length() == 0) return false; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if(c != '.' && !Character.isDigit(c)) return false; } return true; } private void validatePageXML(IFile f) { if(f.isAccessible() && (f.getName().equals("pages.xml") || f.getName().endsWith(".page.xml"))) { XModelObject object = EclipseResourceUtil.createObjectForResource(f); if(object == null) return; if(object.getModelEntity().getName().startsWith(SeamPagesConstants.ENT_FILE_SEAM_PAGE)) { validatePageViewIds(object, f); } } } private void validatePageViewIds(XModelObject o, IFile f) { String entity = o.getModelEntity().getName(); validatePageViewId(o, f); if(entity.startsWith(SeamPagesConstants.ENT_REDIRECT) || entity.startsWith(SeamPagesConstants.ENT_RENDER)) { } else { XModelObject[] cs = o.getChildren(); for (XModelObject c: cs) { validatePageViewIds(c, f); } } } static String ATTR_NO_CONVERSATION_VIEW_ID = "no conversation view id"; static String ATTR_LOGIN_VIEW_ID = "login view id"; private void validatePageViewId(XModelObject object, IFile f) { validatePageViewId(object, f, SeamPagesConstants.ATTR_VIEW_ID); validatePageViewId(object, f, ATTR_NO_CONVERSATION_VIEW_ID); validatePageViewId(object, f, ATTR_LOGIN_VIEW_ID); } private void validatePageViewId(XModelObject object, IFile f, String attr) { if(object.getModelEntity().getAttribute(attr) == null) return; String path = object.getAttributeValue(attr); if(path == null || path.length() == 0 || path.indexOf('*') >= 0) return; path = path.replace('\\', '/'); if(path.indexOf('?') >= 0) { path = path.substring(0, path.indexOf('?')); } XModelObject target = object.getModel().getByPath(path); if(target == null) { XMLValueInfo i = new XMLValueInfo(object, attr); addError(NLS.bind(SeamValidationMessages.UNRESOLVED_VIEW_ID, path), SeamPreferences.UNRESOLVED_VIEW_ID, i, f); } } public IMarker addError(String message, String preferenceKey, String[] messageArguments, ITextSourceReference location, IResource target, int messageId) { IMarker marker = addError(message, preferenceKey, messageArguments, location, target); try{ if(marker!=null) { marker.setAttribute(MESSAGE_ID_ATTRIBUTE_NAME, new Integer(messageId)); } }catch(CoreException ex){ SeamCorePlugin.getDefault().logError(ex); } return marker; } @Override public void registerPreferenceInfo() { PreferenceInfoManager.register(getProblemType(), new SeamPreferenceInfo()); } class SeamPreferenceInfo implements IPreferenceInfo{ @Override public String getPreferencePageId() { return PREFERENCE_PAGE_ID; } @Override public String getPropertyPageId() { return PROPERTY_PAGE_ID; } @Override public String getPluginId() { return SeamCorePlugin.PLUGIN_ID; } } }