Skip to main content

This CGIT instance is deprecated, and repositories have been moved to Gitlab or Github. See the repository descriptions for specific locations.

summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoramywu2007-04-23 19:44:08 +0000
committeramywu2007-04-23 19:44:08 +0000
commit2c6a31d051828a7b4e2b89219cf758ddaac4146f (patch)
treef1675227da95e23718f554a0314e39d63913e7da /bundles/org.eclipse.jst.jsp.core/src/org
parent3cc25db33973ff92b72827331cdb99526a007cfc (diff)
downloadwebtools.sourceediting-2c6a31d051828a7b4e2b89219cf758ddaac4146f.tar.gz
webtools.sourceediting-2c6a31d051828a7b4e2b89219cf758ddaac4146f.tar.xz
webtools.sourceediting-2c6a31d051828a7b4e2b89219cf758ddaac4146f.zip
[160548] JSP validator does not mark the non-existing attribute or the missing required attribute
Diffstat (limited to 'bundles/org.eclipse.jst.jsp.core/src/org')
-rw-r--r--bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCoreMessages.java2
-rw-r--r--bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCorePluginResources.properties2
-rw-r--r--bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPActionValidator.java269
-rw-r--r--bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPBatchValidator.java11
4 files changed, 281 insertions, 3 deletions
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 03fcf134db..3d74cb709f 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 class JSPCoreMessages extends NLS {
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 d40799b854..1129ea115e 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_1=Cannot find the tag library descriptor for {0}
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 0000000000..04450e31fb
--- /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 f4b5ba5cfa..63357a3fff 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 @@ public final class JSPBatchValidator implements IValidatorJob, IExecutableExtens
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 @@ public final class JSPBatchValidator implements IValidatorJob, IExecutableExtens
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 @@ public final class JSPBatchValidator implements IValidatorJob, IExecutableExtens
// 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 @@ public final class JSPBatchValidator implements IValidatorJob, IExecutableExtens
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 @@ public final class JSPBatchValidator implements IValidatorJob, IExecutableExtens
fJSPDirectiveValidator.performValidation(f, reporter, model.getStructuredDocument());
if (!reporter.isCancelled())
fJSPELValidator.performValidation(f, reporter, model.getStructuredDocument());
+ if (!reporter.isCancelled())
+ fJSPActionValidator.performValidation(f, reporter, model);
}
/**

Back to the top