blob: 9519c62492e7406eb74ed37b4eff4a0e1d76b45c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2010 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
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.jst.jsp.core.internal.validation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
import org.eclipse.jst.jsp.core.internal.Logger;
import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache;
import org.eclipse.jst.jsp.core.internal.preferences.JSPCorePreferenceNames;
import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
import org.eclipse.jst.jsp.core.internal.util.FacetModuleCoreSupport;
import org.eclipse.jst.jsp.core.taglib.IJarRecord;
import org.eclipse.jst.jsp.core.taglib.ITLDRecord;
import org.eclipse.jst.jsp.core.taglib.ITagDirRecord;
import org.eclipse.jst.jsp.core.taglib.ITaglibRecord;
import org.eclipse.jst.jsp.core.taglib.IURLRecord;
import org.eclipse.jst.jsp.core.taglib.TaglibIndex;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.html.core.internal.contentmodel.JSP20Namespace;
import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
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.text.IRegionComparible;
import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
import org.eclipse.wst.sse.core.utils.StringUtils;
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.IValidator;
import com.ibm.icu.text.Collator;
/**
* Checks for: - duplicate taglib prefix values and reserved taglib prefix
* values in the same file
*/
public class JSPDirectiveValidator extends JSPValidator {
/**
*
*/
private static final String PREFERENCE_NODE_QUALIFIER = JSPCorePlugin.getDefault().getBundle().getSymbolicName();
private static Collator collator = Collator.getInstance(Locale.US);
private static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jspvalidator")).booleanValue(); //$NON-NLS-1$
private IValidator fMessageOriginator;
private IEclipsePreferences fPreferences = null;
private IPreferencesService fPreferencesService = null;
private HashMap fPrefixValueRegionToDocumentRegionMap = new HashMap();
private IJavaProject fProject = null;
private HashMap fReservedPrefixes = new HashMap();
private IScopeContext[] fScopes = null;
private int fSeverityIncludeFileMissing = -1;
private int fSeverityIncludeFileNotSpecified = -1;
private int fSeveritySuperClassNotFound = -1;
private int fSeverityTagdirUnresolvableURI = -1;
private int fSeverityTaglibDuplicatePrefixWithDifferentURIs = -1;
private int fSeverityTaglibDuplicatePrefixWithSameURIs = -1;
private int fSeverityTaglibMissingPrefix = -1;
private int fSeverityTaglibMissingURI = -1;
private int fSeverityTaglibUnresolvableURI = -1;
private HashMap fTaglibPrefixesInUse = new HashMap();
public JSPDirectiveValidator() {
initReservedPrefixes();
fMessageOriginator = this;
}
public JSPDirectiveValidator(IValidator validator) {
initReservedPrefixes();
this.fMessageOriginator = validator;
}
/**
* Record that the currently validating resource depends on the given
* file. Only possible during batch (not source) validation.
*
* @param file
*/
void addDependsOn(IResource file) {
if (fMessageOriginator instanceof JSPBatchValidator) {
((JSPBatchValidator) fMessageOriginator).addDependsOn(file);
}
}
public void cleanup(IReporter reporter) {
super.cleanup(reporter);
fTaglibPrefixesInUse.clear();
fPrefixValueRegionToDocumentRegionMap.clear();
}
private void collectTaglibPrefix(IStructuredDocumentRegion documentRegion, ITextRegion valueRegion, String taglibPrefix) {
fPrefixValueRegionToDocumentRegionMap.put(valueRegion, documentRegion);
Object o = fTaglibPrefixesInUse.get(taglibPrefix);
if (o == null) {
// prefix doesn't exist, remember it
fTaglibPrefixesInUse.put(taglibPrefix, valueRegion);
}
else {
List regionList = null;
// already a List
if (o instanceof List) {
regionList = (List) o;
}
/*
* a single value region, create a new List and add previous
* valueRegion
*/
else {
regionList = new ArrayList();
regionList.add(o);
fTaglibPrefixesInUse.put(taglibPrefix, regionList);
}
regionList.add(valueRegion);
}
}
int getMessageSeverity(String key) {
int sev = fPreferencesService.getInt(PREFERENCE_NODE_QUALIFIER, key, IMessage.NORMAL_SEVERITY, fScopes);
switch (sev) {
case ValidationMessage.ERROR :
return IMessage.HIGH_SEVERITY;
case ValidationMessage.WARNING :
return IMessage.NORMAL_SEVERITY;
case ValidationMessage.INFORMATION :
return IMessage.LOW_SEVERITY;
case ValidationMessage.IGNORE :
return ValidationMessage.IGNORE;
}
return IMessage.NORMAL_SEVERITY;
}
private void initReservedPrefixes() {
fReservedPrefixes.put("jsp", ""); //$NON-NLS-1$ //$NON-NLS-2$
fReservedPrefixes.put("jspx", ""); //$NON-NLS-1$ //$NON-NLS-2$
fReservedPrefixes.put("java", ""); //$NON-NLS-1$ //$NON-NLS-2$
fReservedPrefixes.put("javax", ""); //$NON-NLS-1$ //$NON-NLS-2$
fReservedPrefixes.put("servlet", ""); //$NON-NLS-1$ //$NON-NLS-2$
fReservedPrefixes.put("sun", ""); //$NON-NLS-1$ //$NON-NLS-2$
fReservedPrefixes.put("sunw", ""); //$NON-NLS-1$ //$NON-NLS-2$
}
private boolean isReservedTaglibPrefix(String name) {
return fReservedPrefixes.get(name) != null;
}
private void loadPreferences(IFile file) {
fScopes = new IScopeContext[]{new InstanceScope(), new DefaultScope()};
fPreferencesService = Platform.getPreferencesService();
if (file != null && file.isAccessible()) {
ProjectScope projectScope = new ProjectScope(file.getProject());
if (projectScope.getNode(PREFERENCE_NODE_QUALIFIER).getBoolean(JSPCorePreferenceNames.VALIDATION_USE_PROJECT_SETTINGS, false)) {
fScopes = new IScopeContext[]{projectScope, new InstanceScope(), new DefaultScope()};
}
}
fSeverityIncludeFileMissing = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_INCLUDE_FILE_NOT_FOUND);
fSeverityIncludeFileNotSpecified = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_INCLUDE_NO_FILE_SPECIFIED);
fSeverityTaglibDuplicatePrefixWithDifferentURIs = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_DUPLICATE_PREFIXES_DIFFERENT_URIS);
fSeverityTaglibDuplicatePrefixWithSameURIs = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_DUPLICATE_PREFIXES_SAME_URIS);
fSeverityTaglibMissingPrefix = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_MISSING_PREFIX);
fSeverityTaglibMissingURI = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_MISSING_URI_OR_TAGDIR);
fSeverityTaglibUnresolvableURI = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_UNRESOLVABLE_URI_OR_TAGDIR);
fSeverityTagdirUnresolvableURI = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_UNRESOLVABLE_URI_OR_TAGDIR);
fSeveritySuperClassNotFound = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_PAGE_SUPERCLASS_NOT_FOUND);
}
protected void performValidation(IFile f, IReporter reporter, IStructuredDocument sDoc) {
loadPreferences(f);
setProject(f.getProject());
/*
* when validating an entire file need to clear dupes or else you're
* comparing between files
*/
fPrefixValueRegionToDocumentRegionMap.clear();
fTaglibPrefixesInUse.clear();
IRegionComparible comparer = null;
if (sDoc instanceof IRegionComparible)
comparer = (IRegionComparible) sDoc;
// iterate all document regions
IStructuredDocumentRegion region = sDoc.getFirstStructuredDocumentRegion();
while (region != null && !reporter.isCancelled()) {
// only checking directives
if (region.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
processDirective(reporter, f, sDoc, region);
}
// requires tag name, attribute, equals, and value
else if (comparer != null && region.getNumberOfRegions() > 4) {
ITextRegion nameRegion = region.getRegions().get(1);
if (comparer.regionMatches(region.getStartOffset(nameRegion), nameRegion.getTextLength(), "jsp:include")) { //$NON-NLS-1$
processInclude(reporter, f, sDoc, region, JSP11Namespace.ATTR_NAME_PAGE);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=295950
else if (comparer.regionMatches(region.getStartOffset(nameRegion), 14, "jsp:directive.")) { //$NON-NLS-1$
processDirective(reporter, f, sDoc, region);
}
}
region = region.getNext();
}
if (!reporter.isCancelled()) {
reportTaglibDuplicatePrefixes(f, reporter, sDoc);
}
fPrefixValueRegionToDocumentRegionMap.clear();
fTaglibPrefixesInUse.clear();
setProject(null);
unloadPreferences();
}
private void processDirective(IReporter reporter, IFile file, IStructuredDocument sDoc, IStructuredDocumentRegion documentRegion) {
String directiveName = getDirectiveName(documentRegion);
if (directiveName.endsWith("taglib")) { //$NON-NLS-1$
processTaglibDirective(reporter, file, sDoc, documentRegion);
}
else if (directiveName.equals("jsp:include")) { //$NON-NLS-1$
processInclude(reporter, file, sDoc, documentRegion, JSP11Namespace.ATTR_NAME_PAGE);
}
else if (directiveName.endsWith("include")) { //$NON-NLS-1$
processInclude(reporter, file, sDoc, documentRegion, JSP11Namespace.ATTR_NAME_FILE);
}
else if (directiveName.endsWith("page")) { //$NON-NLS-1$
processPageDirective(reporter, file, sDoc, documentRegion);
}
}
private void processInclude(IReporter reporter, IFile file, IStructuredDocument sDoc, IStructuredDocumentRegion documentRegion, String attrName) {
ITextRegion fileValueRegion = getAttributeValueRegion(documentRegion, attrName);
// There is a file and it isn't a nested region which could contain a JSP expression
if (fileValueRegion != null && !hasNestedRegion(fileValueRegion)) {
// file specified
String fileValue = documentRegion.getText(fileValueRegion);
fileValue = StringUtils.stripQuotes(fileValue);
if (fileValue.length() == 0 && fSeverityIncludeFileNotSpecified != ValidationMessage.IGNORE) {
// file value is specified but empty
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, attrName);
LocalizedMessage message = new LocalizedMessage(fSeverityIncludeFileNotSpecified, msgText, file);
int start = documentRegion.getStartOffset(fileValueRegion);
int length = fileValueRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
else if (DeploymentDescriptorPropertyCache.getInstance().getURLMapping(file.getFullPath(), fileValue) == null) {
IPath testPath = FacetModuleCoreSupport.resolve(file.getFullPath(), fileValue);
if (testPath.segmentCount() > 1) {
IFile testFile = file.getWorkspace().getRoot().getFile(testPath);
addDependsOn(testFile);
if (!testFile.isAccessible()) {
if (fSeverityIncludeFileMissing != ValidationMessage.IGNORE) {
// File not found
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_4, new String[]{fileValue, testPath.toString()});
LocalizedMessage message = new LocalizedMessage(fSeverityIncludeFileMissing, msgText, file);
int start = documentRegion.getStartOffset(fileValueRegion);
int length = fileValueRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
}
}
}
}
else if (fileValueRegion == null && fSeverityIncludeFileNotSpecified != ValidationMessage.IGNORE) {
// file is not specified at all
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, attrName);
LocalizedMessage message = new LocalizedMessage(fSeverityIncludeFileNotSpecified, msgText, file);
int start = documentRegion.getStartOffset();
int length = documentRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
}
/**
* @param reporter
* @param file
* @param doc
* @param documentRegion
*/
private void processPageDirective(IReporter reporter, IFile file, IStructuredDocument doc, IStructuredDocumentRegion documentRegion) {
ITextRegion superclassValueRegion = getAttributeValueRegion(documentRegion, JSP11Namespace.ATTR_NAME_EXTENDS);
if (superclassValueRegion != null) {
// file specified
String superclassName = documentRegion.getText(superclassValueRegion);
superclassName = StringUtils.stripQuotes(superclassName);
IType superClass = null;
if (superclassName != null && superclassName.length() > 0 && fProject != null && fProject.exists()) {
try {
superClass = fProject.findType(superclassName.trim(), new NullProgressMonitor());
}
catch (JavaModelException e) {
Logger.logException(e);
}
}
if (superClass == null && fSeveritySuperClassNotFound != ValidationMessage.IGNORE) {
// superclass not found
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_8, superclassName);
LocalizedMessage message = new LocalizedMessage(fSeveritySuperClassNotFound, msgText, file);
int start = documentRegion.getStartOffset(superclassValueRegion);
int length = superclassValueRegion.getTextLength();
int lineNo = doc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
}
}
private void processTaglibDirective(IReporter reporter, IFile file, IStructuredDocument sDoc, IStructuredDocumentRegion documentRegion) {
ITextRegion prefixValueRegion = null;
ITextRegion uriValueRegion = getAttributeValueRegion(documentRegion, JSP11Namespace.ATTR_NAME_URI);
ITextRegion tagdirValueRegion = getAttributeValueRegion(documentRegion, JSP20Namespace.ATTR_NAME_TAGDIR);
if (uriValueRegion != null) {
// URI is specified
String uri = documentRegion.getText(uriValueRegion);
if (file != null) {
uri = StringUtils.stripQuotes(uri);
if (uri.length() > 0) {
ITaglibRecord reference = TaglibIndex.resolve(file.getFullPath().toString(), uri, false);
if (reference != null) {
switch (reference.getRecordType()) {
case (ITaglibRecord.TLD) : {
ITLDRecord record = (ITLDRecord) reference;
IResource tldfile = ResourcesPlugin.getWorkspace().getRoot().getFile(record.getPath());
addDependsOn(tldfile);
}
break;
case (ITaglibRecord.JAR) : {
IJarRecord record = (IJarRecord) reference;
IFile[] foundFilesForLocation = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(record.getLocation());
for (int i = 0; i < foundFilesForLocation.length; i++) {
addDependsOn(foundFilesForLocation[i]);
}
}
break;
case (ITaglibRecord.TAGDIR) : {
ITagDirRecord record = (ITagDirRecord) reference;
IPath path = record.getPath();
IResource found = ResourcesPlugin.getWorkspace().getRoot().findMember(path, false);
try {
found.accept(new IResourceVisitor() {
public boolean visit(IResource resource) throws CoreException {
if (resource.getType() == IResource.FILE) {
addDependsOn(resource);
}
return true;
}
});
}
catch (CoreException e) {
Logger.logException(e);
}
}
break;
case (ITaglibRecord.URL) : {
IURLRecord record = (IURLRecord) reference;
String baseLocation = record.getBaseLocation();
if (baseLocation != null && baseLocation.indexOf("://") < 0) {
IResource found = ResourcesPlugin.getWorkspace().getRoot().findMember(baseLocation, false);
if (found != null) {
try {
found.accept(new IResourceVisitor() {
public boolean visit(IResource resource) throws CoreException {
if (resource.getType() == IResource.FILE) {
addDependsOn(resource);
}
return true;
}
});
}
catch (CoreException e) {
Logger.logException(e);
}
}
else {
IFile externalJar = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(baseLocation));
if (externalJar != null) {
addDependsOn(externalJar);
}
}
}
}
break;
}
}
if (reference == null && fSeverityTaglibUnresolvableURI != ValidationMessage.IGNORE) {
// URI specified but does not resolve
String msgText = null;
// provide better messages for typical "http:*" URIs
if (uri.startsWith("http:") && DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(file.getFullPath()) < 1.2) { //$NON-NLS-1$
if (FacetModuleCoreSupport.isDynamicWebProject(file.getProject())) {
msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_9, uri);
}
else {
msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_10, uri);
}
}
else {
msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_1, uri);
}
LocalizedMessage message = new LocalizedMessage(fSeverityTaglibUnresolvableURI, msgText, file);
int start = documentRegion.getStartOffset(uriValueRegion);
int length = uriValueRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
message.setAttribute("PROBLEM_ID", new Integer(611)); //$NON-NLS-1$
reporter.addMessage(fMessageOriginator, message);
}
}
else if (fSeverityTaglibMissingURI != ValidationMessage.IGNORE) {
// URI specified but empty string
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, JSP11Namespace.ATTR_NAME_URI);
LocalizedMessage message = new LocalizedMessage(fSeverityTaglibMissingURI, msgText, file);
int start = documentRegion.getStartOffset(uriValueRegion);
int length = uriValueRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
}
}
else if (tagdirValueRegion != null) {
// URI is specified
String tagdir = documentRegion.getText(tagdirValueRegion);
if (file != null) {
tagdir = StringUtils.stripQuotes(tagdir);
if (tagdir.length() <= 0 && fSeverityTaglibMissingURI != ValidationMessage.IGNORE) {
// tagdir specified but empty string
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, JSP20Namespace.ATTR_NAME_TAGDIR);
LocalizedMessage message = new LocalizedMessage(fSeverityTaglibMissingURI, msgText, file);
int start = documentRegion.getStartOffset(tagdirValueRegion);
int length = tagdirValueRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
else if (TaglibIndex.resolve(file.getFullPath().toString(), tagdir, false) == null && fSeverityTagdirUnresolvableURI != ValidationMessage.IGNORE) {
// URI specified but does not resolve
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_11, tagdir);
LocalizedMessage message = new LocalizedMessage(fSeverityTaglibUnresolvableURI, msgText, file);
int start = documentRegion.getStartOffset(tagdirValueRegion);
int length = tagdirValueRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
}
}
else if (fSeverityTaglibMissingURI != ValidationMessage.IGNORE) {
// URI not specified or empty string
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_7, new String[]{JSP20Namespace.ATTR_NAME_TAGDIR, JSP11Namespace.ATTR_NAME_URI});
LocalizedMessage message = new LocalizedMessage(fSeverityTaglibMissingURI, msgText, file);
int start = documentRegion.getStartOffset();
int length = documentRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
prefixValueRegion = getAttributeValueRegion(documentRegion, JSP11Namespace.ATTR_NAME_PREFIX);
if (prefixValueRegion != null) {
// prefix specified
String taglibPrefix = documentRegion.getText(prefixValueRegion);
taglibPrefix = StringUtils.stripQuotes(taglibPrefix);
collectTaglibPrefix(documentRegion, prefixValueRegion, taglibPrefix);
if (isReservedTaglibPrefix(taglibPrefix)) {
// prefix is a reserved prefix
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_0, taglibPrefix);
int sev = IMessage.HIGH_SEVERITY;
LocalizedMessage message = (file == null ? new LocalizedMessage(sev, msgText) : new LocalizedMessage(sev, msgText, file));
int start = documentRegion.getStartOffset(prefixValueRegion);
int length = prefixValueRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
if (taglibPrefix.length() == 0 && fSeverityTaglibMissingPrefix != ValidationMessage.IGNORE) {
// prefix is specified but empty
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, JSP11Namespace.ATTR_NAME_PREFIX);
LocalizedMessage message = new LocalizedMessage(fSeverityTaglibMissingPrefix, msgText, file);
int start = documentRegion.getStartOffset(prefixValueRegion);
int length = prefixValueRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
}
else if (fSeverityTaglibMissingPrefix != ValidationMessage.IGNORE) {
// prefix is not specified
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, JSP11Namespace.ATTR_NAME_PREFIX);
LocalizedMessage message = new LocalizedMessage(fSeverityTaglibMissingPrefix, msgText, file);
int start = documentRegion.getStartOffset();
int length = documentRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
}
private void reportTaglibDuplicatePrefixes(IFile file, IReporter reporter, IStructuredDocument document) {
if (fSeverityTaglibDuplicatePrefixWithDifferentURIs == ValidationMessage.IGNORE && fSeverityTaglibDuplicatePrefixWithSameURIs == ValidationMessage.IGNORE)
return;
String[] prefixes = (String[]) fTaglibPrefixesInUse.keySet().toArray(new String[0]);
for (int prefixNumber = 0; prefixNumber < prefixes.length; prefixNumber++) {
int severity = fSeverityTaglibDuplicatePrefixWithSameURIs;
Object o = fTaglibPrefixesInUse.get(prefixes[prefixNumber]);
/*
* Only care if it's a List (because there was more than one
* directive with that prefix) and if we're supposed to report
* duplicates
*/
if (o instanceof List) {
List valueRegions = (List) o;
String uri = null;
for (int regionNumber = 0; regionNumber < valueRegions.size(); regionNumber++) {
IStructuredDocumentRegion documentRegion = (IStructuredDocumentRegion) fPrefixValueRegionToDocumentRegionMap.get(valueRegions.get(regionNumber));
ITextRegion uriValueRegion = getAttributeValueRegion(documentRegion, JSP11Namespace.ATTR_NAME_URI);
if (uriValueRegion == null) {
uriValueRegion = getAttributeValueRegion(documentRegion, JSP20Namespace.ATTR_NAME_TAGDIR);
}
if (uriValueRegion != null) {
String uri2 = StringUtils.stripQuotes(documentRegion.getText(uriValueRegion));
if (uri == null) {
uri = uri2;
}
else {
if (collator.compare(uri, uri2) != 0) {
severity = fSeverityTaglibDuplicatePrefixWithDifferentURIs;
}
}
}
}
if (severity != ValidationMessage.IGNORE) {
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_2, prefixes[prefixNumber]); //$NON-NLS-2$ //$NON-NLS-1$
// Report an error in all directives using this prefix
for (int regionNumber = 0; regionNumber < valueRegions.size(); regionNumber++) {
ITextRegion valueRegion = (ITextRegion) valueRegions.get(regionNumber);
IStructuredDocumentRegion documentRegion = (IStructuredDocumentRegion) fPrefixValueRegionToDocumentRegionMap.get(valueRegion);
LocalizedMessage message = (file == null ? new LocalizedMessage(severity, msgText) : new LocalizedMessage(severity, msgText, file));
// if there's a message, there was an error found
int start = documentRegion.getStartOffset(valueRegion);
int length = valueRegion.getTextLength();
int lineNo = document.getLineOfOffset(start);
message.setLineNo(lineNo + 1);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(fMessageOriginator, message);
}
}
}
}
}
/**
* @param project
*/
private void setProject(IProject project) {
boolean useProject = false;
if (project != null) {
fProject = JavaCore.create(project);
fPreferences = new ProjectScope(fProject.getProject()).getNode(PREFERENCE_NODE_QUALIFIER);
useProject = fPreferences.getBoolean(HTMLCorePreferenceNames.USE_PROJECT_SETTINGS, false);
}
else {
fProject = null;
}
if (!useProject) {
fPreferences = new InstanceScope().getNode(PREFERENCE_NODE_QUALIFIER);
}
}
private void unloadPreferences() {
fPreferencesService = null;
fScopes = null;
}
/**
* True if container has nested regions, meaning container is probably too
* complicated (like JSP expressions or EL) to validate with this validator.
*/
private boolean hasNestedRegion(ITextRegion container) {
return (container instanceof ITextRegionContainer && ((ITextRegionContainer) container).getRegions() != null);
}
/**
* batch validation call
*/
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.getStructuredDocument());
}
}
catch (Exception e) {
Logger.logException(e);
}
finally {
if (sModel != null)
sModel.releaseFromRead();
}
}
}