[160548] JSP validator does not mark the non-existing attribute or the missing required attribute
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCoreMessages.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCoreMessages.java
index 03fcf13..3d74cb7 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCoreMessages.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCoreMessages.java
@@ -25,6 +25,8 @@
public static String JSPDirectiveValidator_2;
public static String JSPDirectiveValidator_3;
public static String JSPDirectiveValidator_4;
+ public static String JSPDirectiveValidator_5;
+ public static String JSPDirectiveValidator_6;
public static String JSPIndexManager_0;
public static String JSPIndexManager_2;
public static String JSP_Search;
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCorePluginResources.properties b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCorePluginResources.properties
index d40799b..1129ea1 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCorePluginResources.properties
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCorePluginResources.properties
@@ -22,4 +22,6 @@
JSPDirectiveValidator_2=The prefix {0} is used more than once
JSPDirectiveValidator_3=A {0} value is required in this directive
JSPDirectiveValidator_4=Fragment {0} was not be found at expected path {1}
+JSPDirectiveValidator_5=Missing required attribute "{0}"
+JSPDirectiveValidator_6=Undefined attribute name ({0})
JSPBatchValidator_0=Gathering files in {0}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPActionValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPActionValidator.java
new file mode 100644
index 0000000..04450e3
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPActionValidator.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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.jsp.core.internal.validation;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.contentmodel.TaglibController;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TaglibTracker;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+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;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.NamedNodeMap;
+
+/**
+ * Checks for: - missing required attributes & undefined attributes in jsp
+ * action tags such as jsp directives and jsp custom tags
+ */
+public class JSPActionValidator extends JSPValidator {
+ private int fSeverityMissingRequiredAttribute = IMessage.HIGH_SEVERITY;
+ private int fSeverityUnknownAttribute = IMessage.NORMAL_SEVERITY;
+ private IValidator fMessageOriginator;
+ private HashSet fTaglibPrefixes = new HashSet();
+
+ public JSPActionValidator() {
+ this.fMessageOriginator = this;
+ }
+
+ public JSPActionValidator(IValidator validator) {
+ this.fMessageOriginator = validator;
+ }
+
+ private void checkRequiredAttributes(IDOMElement element, CMNamedNodeMap attrMap, IReporter reporter, IFile file, IStructuredDocument document, IStructuredDocumentRegion documentRegion) {
+ Iterator it = attrMap.iterator();
+ CMAttributeDeclaration attr = null;
+ while (it.hasNext()) {
+ attr = (CMAttributeDeclaration) it.next();
+ if (attr.getUsage() == CMAttributeDeclaration.REQUIRED) {
+ Attr a = element.getAttributeNode(attr.getAttrName());
+ if (a == null) {
+ String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_5, attr.getAttrName());
+ LocalizedMessage message = new LocalizedMessage(fSeverityMissingRequiredAttribute, msgText, file);
+ int start = element.getStartOffset();
+ int length = element.getStartEndOffset() - start;
+ int lineNo = document.getLineOfOffset(start);
+ message.setLineNo(lineNo);
+ message.setOffset(start);
+ message.setLength(length);
+
+ reporter.addMessage(fMessageOriginator, message);
+ }
+ }
+ }
+ }
+
+ private boolean checkUnknownAttributes(IDOMElement element, CMNamedNodeMap cmAttrs, IReporter reporter, IFile file, IStructuredDocument document, IStructuredDocumentRegion documentRegion) {
+ boolean foundjspattribute = false;
+
+ NamedNodeMap attrs = element.getAttributes();
+ for (int i = 0; i < attrs.getLength(); i++) {
+ Attr a = (Attr) attrs.item(i);
+ CMAttributeDeclaration adec = (CMAttributeDeclaration) cmAttrs.getNamedItem(a.getName());
+ if (adec == null) {
+ // No attr declaration was found. That is, the attr name is
+ // undefined.
+ // but not regard it as undefined name if it includes JSP
+ if (!hasJSPRegion(((IDOMNode) a).getNameRegion())) {
+ String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_6, a.getName());
+ LocalizedMessage message = new LocalizedMessage(fSeverityUnknownAttribute, msgText, file);
+ int start = ((IDOMAttr) a).getNameRegionStartOffset();
+ int length = ((IDOMAttr) a).getNameRegionEndOffset() - start;
+ int lineNo = document.getLineOfOffset(start);
+ message.setLineNo(lineNo);
+ message.setOffset(start);
+ message.setLength(length);
+
+ reporter.addMessage(fMessageOriginator, message);
+ }
+ else {
+ foundjspattribute = true;
+ }
+ }
+ }
+ return foundjspattribute;
+ }
+
+ public void cleanup(IReporter reporter) {
+ super.cleanup(reporter);
+ fTaglibPrefixes.clear();
+ }
+
+ private String getStartTagName(IStructuredDocumentRegion sdr) {
+ String name = new String();
+ ITextRegionList subRegions = sdr.getRegions();
+ if (subRegions.size() > 2) {
+ ITextRegion subRegion = subRegions.get(0);
+ if (subRegion.getType() == DOMRegionContext.XML_TAG_OPEN) {
+ subRegion = subRegions.get(1);
+ if (subRegion.getType() == DOMRegionContext.XML_TAG_NAME) {
+ name = sdr.getText(subRegion);
+ }
+ }
+ }
+ return name;
+ }
+
+ private HashSet getTaglibPrefixes(IStructuredDocument document) {
+ if (fTaglibPrefixes.isEmpty()) {
+ // add all reserved prefixes
+ fTaglibPrefixes.add("jsp"); //$NON-NLS-1$
+ fTaglibPrefixes.add("jspx"); //$NON-NLS-1$
+ fTaglibPrefixes.add("java"); //$NON-NLS-1$
+ fTaglibPrefixes.add("javax"); //$NON-NLS-1$
+ fTaglibPrefixes.add("servlet"); //$NON-NLS-1$
+ fTaglibPrefixes.add("sun"); //$NON-NLS-1$
+ fTaglibPrefixes.add("sunw"); //$NON-NLS-1$
+
+ // add all taglib prefixes
+ TLDCMDocumentManager manager = TaglibController.getTLDCMDocumentManager(document);
+ List trackers = manager.getTaglibTrackers();
+ for (Iterator it = trackers.iterator(); it.hasNext();) {
+ TaglibTracker tracker = (TaglibTracker) it.next();
+ String prefix = tracker.getPrefix();
+ fTaglibPrefixes.add(prefix);
+ }
+ }
+ return fTaglibPrefixes;
+ }
+
+ private boolean hasJSPRegion(ITextRegion container) {
+ if (!(container instanceof ITextRegionContainer))
+ return false;
+ ITextRegionList regions = ((ITextRegionContainer) container).getRegions();
+ if (regions == null)
+ return false;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ if (region == null)
+ continue;
+ String regionType = region.getType();
+ if (regionType == DOMRegionContext.XML_TAG_OPEN || (isNestedTagName(regionType)))
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isNestedTagName(String regionType) {
+ boolean result = regionType.equals(DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN) || regionType.equals(DOMJSPRegionContexts.JSP_EXPRESSION_OPEN) || regionType.equals(DOMJSPRegionContexts.JSP_DECLARATION_OPEN) || regionType.equals(DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN);
+ return result;
+ }
+
+ void performValidation(IFile f, IReporter reporter, IStructuredModel model) {
+ fTaglibPrefixes.clear();
+ int length = model.getStructuredDocument().getLength();
+ performValidation(f, reporter, model, new Region(0, length));
+ }
+
+ protected void performValidation(IFile f, IReporter reporter, IStructuredModel model, IRegion validateRegion) {
+ IStructuredDocument sDoc = model.getStructuredDocument();
+
+ // iterate all document regions
+ IStructuredDocumentRegion region = sDoc.getRegionAtCharacterOffset(validateRegion.getOffset());
+ while (region != null && !reporter.isCancelled() && (region.getStartOffset() <= (validateRegion.getOffset() + validateRegion.getLength()))) {
+ if (region.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
+ // only checking directives
+ processDirective(reporter, f, model, region);
+ fTaglibPrefixes.clear();
+ }
+ else if (region.getType() == DOMRegionContext.XML_TAG_NAME) {
+ // and jsp tags
+ String tagName = getStartTagName(region);
+ int colonPosition = tagName.indexOf(':');
+ if (colonPosition > -1) {
+ // get tag's prefix and check if it's really a jsp action
+ // tag
+ String prefix = tagName.substring(0, colonPosition);
+ if (getTaglibPrefixes(sDoc).contains(prefix))
+ processDirective(reporter, f, model, region);
+ }
+ }
+ region = region.getNext();
+ }
+ }
+
+ private void processDirective(IReporter reporter, IFile file, IStructuredModel model, IStructuredDocumentRegion documentRegion) {
+ IndexedRegion ir = model.getIndexedRegion(documentRegion.getStartOffset());
+ if (ir instanceof IDOMElement) {
+ IDOMElement element = (IDOMElement) ir;
+ ModelQuery query = ModelQueryUtil.getModelQuery(model);
+ if (query != null) {
+ CMElementDeclaration cmElement = query.getCMElementDeclaration(element);
+ if (cmElement != null) {
+ CMNamedNodeMap cmAttributes = cmElement.getAttributes();
+
+ boolean foundjspattribute = checkUnknownAttributes(element, cmAttributes, reporter, file, model.getStructuredDocument(), documentRegion);
+ // required attributes could be hidden in jsp regions in
+ // tags, so if jsp regions were detected, do not check for
+ // missing required attributes
+ if (!foundjspattribute)
+ checkRequiredAttributes(element, cmAttributes, reporter, file, model.getStructuredDocument(), documentRegion);
+ }
+ }
+ }
+ }
+
+ public void validate(IValidationContext helper, IReporter reporter) throws ValidationException {
+ reporter.removeAllMessages(this);
+ super.validate(helper, reporter);
+ }
+
+ protected void validateFile(IFile f, IReporter reporter) {
+ if (DEBUG) {
+ Logger.log(Logger.INFO, getClass().getName() + " validating: " + f); //$NON-NLS-1$
+ }
+
+ IStructuredModel sModel = null;
+ try {
+ sModel = StructuredModelManager.getModelManager().getModelForRead(f);
+ if (sModel != null && !reporter.isCancelled()) {
+ performValidation(f, reporter, sModel);
+ }
+ }
+ catch (Exception e) {
+ Logger.logException(e);
+ }
+ finally {
+ if (sModel != null)
+ sModel.releaseFromRead();
+ }
+ }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPBatchValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPBatchValidator.java
index f4b5ba5..63357a3 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPBatchValidator.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPBatchValidator.java
@@ -163,11 +163,14 @@
private JSPJavaValidator fJSPJavaValidator = new JSPJavaValidator(this);
+ private JSPActionValidator fJSPActionValidator = new JSPActionValidator(this);
+
public void cleanup(IReporter reporter) {
fJSPDirectiveValidator.cleanup(reporter);
fJSPELValidator.cleanup(reporter);
fJSPJavaValidator.cleanup(reporter);
+ fJSPActionValidator.cleanup(reporter);
}
@@ -182,7 +185,7 @@
currentFile = wsRoot.getFile(new Path(uris[i]));
if (currentFile != null && currentFile.exists()) {
if (shouldValidate(currentFile) && fragmentCheck(currentFile)) {
- Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, "" + (i+1) + "/" + uris.length + " - " + currentFile.getFullPath().toString().substring(1));
+ Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, "" + (i + 1) + "/" + uris.length + " - " + currentFile.getFullPath().toString().substring(1));
reporter.displaySubtask(this, message);
validateFile(currentFile, reporter);
}
@@ -195,7 +198,7 @@
// if uris[] length 0 -> validate() gets called for each project
if (helper instanceof IWorkbenchContext) {
IProject project = ((IWorkbenchContext) helper).getProject();
-
+
Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, NLS.bind(JSPCoreMessages.JSPBatchValidator_0, project.getFullPath()));
reporter.displaySubtask(this, message);
@@ -212,7 +215,7 @@
for (int i = 0; i < files.length && !reporter.isCancelled(); i++) {
if (shouldValidate(files[i]) && fragmentCheck(files[i])) {
- message = new LocalizedMessage(IMessage.LOW_SEVERITY, "" + (i+1) + "/" + files.length + " - " + files[i].getFullPath().toString().substring(1));
+ message = new LocalizedMessage(IMessage.LOW_SEVERITY, "" + (i + 1) + "/" + files.length + " - " + files[i].getFullPath().toString().substring(1));
reporter.displaySubtask(this, message);
validateFile(files[i], reporter);
@@ -370,6 +373,8 @@
fJSPDirectiveValidator.performValidation(f, reporter, model.getStructuredDocument());
if (!reporter.isCancelled())
fJSPELValidator.performValidation(f, reporter, model.getStructuredDocument());
+ if (!reporter.isCancelled())
+ fJSPActionValidator.performValidation(f, reporter, model);
}
/**
diff --git a/bundles/org.eclipse.jst.jsp.ui/plugin.xml b/bundles/org.eclipse.jst.jsp.ui/plugin.xml
index 782dc7f..eca333b 100644
--- a/bundles/org.eclipse.jst.jsp.ui/plugin.xml
+++ b/bundles/org.eclipse.jst.jsp.ui/plugin.xml
@@ -118,6 +118,23 @@
</validator>
</extension>
<!--======================================================================================-->
+ <!-- source (as you type) validation for JSP action tags -->
+ <!--======================================================================================-->
+ <extension point="org.eclipse.wst.sse.ui.sourcevalidation">
+ <validator
+ scope="partial"
+ class="org.eclipse.jst.jsp.ui.internal.validation.JSPActionSourceValidator"
+ id="org.eclipse.jst.jsp.ui.internal.validation.jspactionvalidator">
+ <contentTypeIdentifier
+ id="org.eclipse.jst.jsp.core.jspsource">
+ <partitionType id="org.eclipse.jst.jsp.DEFAULT_JSP">
+ </partitionType>
+ <partitionType id="org.eclipse.jst.jsp.JSP_DIRECTIVE">
+ </partitionType>
+ </contentTypeIdentifier>
+ </validator>
+ </extension>
+ <!--======================================================================================-->
<!-- custom XML source (as you type) validation -->
<!--======================================================================================-->
<extension point="org.eclipse.wst.sse.ui.sourcevalidation">
diff --git a/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/validation/JSPActionSourceValidator.java b/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/validation/JSPActionSourceValidator.java
new file mode 100644
index 0000000..0ab20f9
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/validation/JSPActionSourceValidator.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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.jsp.ui.internal.validation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jst.jsp.core.internal.contentproperties.JSPFContentProperties;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+import org.eclipse.jst.jsp.core.internal.validation.JSPActionValidator;
+import org.eclipse.jst.jsp.core.internal.validation.JSPContentValidator;
+import org.eclipse.jst.jsp.ui.internal.Logger;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.FileBufferModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator;
+import org.eclipse.wst.validation.internal.ConfigurationManager;
+import org.eclipse.wst.validation.internal.ProjectConfiguration;
+import org.eclipse.wst.validation.internal.ValidationConfiguration;
+import org.eclipse.wst.validation.internal.ValidationRegistryReader;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
+
+/**
+ * Source validator (able to check partial document) that checks for: -
+ * missing required attributes & undefined attributes in jsp action tags such
+ * as jsp directives and jsp custom tags
+ */
+public class JSPActionSourceValidator extends JSPActionValidator implements ISourceValidator {
+ private IDocument fDocument;
+ private boolean fEnableSourceValidation;
+ private IContentType fJSPFContentType = null;
+
+ public void connect(IDocument document) {
+ fDocument = document;
+
+ // special checks to see source validation should really execute
+ IFile file = null;
+ IStructuredModel model = null;
+ try {
+ model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
+ if (model != null) {
+ String baseLocation = model.getBaseLocation();
+ // The baseLocation may be a path on disk or relative to the
+ // workspace root. Don't translate on-disk paths to
+ // in-workspace resources.
+ IPath basePath = new Path(baseLocation);
+ if (basePath.segmentCount() > 1) {
+ file = ResourcesPlugin.getWorkspace().getRoot().getFile(basePath);
+ /*
+ * If the IFile doesn't exist, make sure it's not returned
+ */
+ if (!file.exists())
+ file = null;
+ }
+ }
+ }
+ finally {
+ if (model != null) {
+ model.releaseFromRead();
+ }
+ }
+ fEnableSourceValidation = (file != null && isBatchValidatorPreferenceEnabled(file) && shouldValidate(file) && fragmentCheck(file));
+ }
+
+ public void disconnect(IDocument document) {
+ fDocument = null;
+ }
+
+ public void validate(IRegion dirtyRegion, IValidationContext helper, IReporter reporter) {
+ if (helper == null || fDocument == null || !fEnableSourceValidation)
+ return;
+
+ if ((reporter != null) && (reporter.isCancelled() == true)) {
+ throw new OperationCanceledException();
+ }
+
+ IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForRead(fDocument);
+ if (model == null)
+ return;
+
+ try {
+ ITextFileBuffer fb = FileBufferModelManager.getInstance().getBuffer(fDocument);
+ if (fb == null)
+ return;
+ IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(fb.getLocation());
+ if (file == null || !file.exists())
+ return;
+ performValidation(file, reporter, model, dirtyRegion);
+ }
+ finally {
+ if (model != null)
+ model.releaseFromRead();
+ }
+ }
+
+ /**
+ * Gets current validation configuration based on current project (which
+ * is based on current document) or global configuration if project does
+ * not override
+ *
+ * @return ValidationConfiguration
+ */
+ private ValidationConfiguration getValidationConfiguration(IFile file) {
+ ValidationConfiguration configuration = null;
+ if (file != null) {
+ IProject project = file.getProject();
+ if (project != null) {
+ try {
+ ProjectConfiguration projectConfiguration = ConfigurationManager.getManager().getProjectConfiguration(project);
+ configuration = projectConfiguration;
+ if (projectConfiguration == null || projectConfiguration.useGlobalPreference()) {
+ configuration = ConfigurationManager.getManager().getGlobalConfiguration();
+ }
+ }
+ catch (InvocationTargetException e) {
+ Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+ }
+ }
+ }
+
+ return configuration;
+ }
+
+ /**
+ * Checks if validator is enabled according in Validation preferences
+ *
+ * @param vmd
+ * @return
+ */
+ private boolean isBatchValidatorPreferenceEnabled(IFile file) {
+ if (file == null) {
+ return true;
+ }
+
+ boolean enabled = true;
+ ValidationConfiguration configuration = getValidationConfiguration(file);
+ if (configuration != null) {
+ org.eclipse.wst.validation.internal.ValidatorMetaData metadata = ValidationRegistryReader.getReader().getValidatorMetaData(JSPContentValidator.class.getName());
+ if (metadata != null) {
+ if (!configuration.isBuildEnabled(metadata) && !configuration.isManualEnabled(metadata))
+ enabled = false;
+ }
+ }
+ return enabled;
+ }
+
+ /**
+ * Checks if file is a jsp fragment or not. If so, check if the fragment
+ * should be validated or not.
+ *
+ * @param file
+ * Assumes shouldValidate was already called on file so it
+ * should not be null and does exist
+ * @return false if file is a fragment and it should not be validated,
+ * true otherwise
+ */
+ private boolean fragmentCheck(IFile file) {
+ // copied from JSPValidator
+ boolean shouldValidate = true;
+ // quick check to see if this is possibly a jsp fragment
+ if (getJSPFContentType().isAssociatedWith(file.getName())) {
+ // get preference for validate jsp fragments
+ boolean shouldValidateFragments = Boolean.valueOf(JSPFContentProperties.getProperty(JSPFContentProperties.VALIDATE_FRAGMENTS, file, true)).booleanValue();
+ /*
+ * if jsp fragments should not be validated, check if file is
+ * really jsp fragment
+ */
+ if (!shouldValidateFragments) {
+ boolean isFragment = isFragment(file);
+ shouldValidate = !isFragment;
+ }
+ }
+ return shouldValidate;
+ }
+
+ /**
+ * Determines if file is jsp fragment or not (does a deep, indepth check,
+ * looking into contents of file)
+ *
+ * @param file
+ * assumes file is not null and exists
+ * @return true if file is jsp fragment, false otherwise
+ */
+ private boolean isFragment(IFile file) {
+ // copied from JSPValidator
+ boolean isFragment = false;
+ InputStream is = null;
+ try {
+ IContentDescription contentDescription = file.getContentDescription();
+ // it can be null
+ if (contentDescription == null) {
+ is = file.getContents();
+ contentDescription = Platform.getContentTypeManager().getDescriptionFor(is, file.getName(), new QualifiedName[]{IContentDescription.CHARSET});
+ }
+ if (contentDescription != null) {
+ String fileCtId = contentDescription.getContentType().getId();
+ isFragment = (fileCtId != null && ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT.equals(fileCtId));
+ }
+ }
+ catch (IOException e) {
+ // ignore, assume it's invalid JSP
+ }
+ catch (CoreException e) {
+ // ignore, assume it's invalid JSP
+ }
+ finally {
+ // must close input stream in case others need it
+ if (is != null)
+ try {
+ is.close();
+ }
+ catch (Exception e) {
+ // not sure how to recover at this point
+ }
+ }
+ return isFragment;
+ }
+
+ private boolean shouldValidate(IFile file) {
+ // copied from JSPValidator
+ IResource resource = file;
+ do {
+ if (resource.isDerived() || resource.isTeamPrivateMember() || !resource.isAccessible() || resource.getName().charAt(0) == '.') {
+ return false;
+ }
+ resource = resource.getParent();
+ }
+ while ((resource.getType() & IResource.PROJECT) == 0);
+ return true;
+ }
+
+ /**
+ * Returns JSP fragment content type
+ *
+ * @return jspf content type
+ */
+ private IContentType getJSPFContentType() {
+ // copied from JSPValidator
+ if (fJSPFContentType == null) {
+ fJSPFContentType = Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT);
+ }
+ return fJSPFContentType;
+ }
+}