blob: aa87da80ea8c636d32863b0ab7ee0facfb3dbf0a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.jst.jsp.core.internal.validation;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
import org.eclipse.jst.jsp.core.internal.Logger;
import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
import org.eclipse.jst.jsp.core.taglib.ITaglibRecord;
import org.eclipse.jst.jsp.core.taglib.TaglibIndex;
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.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.utils.StringUtils;
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;
/**
* Checks for: - duplicate taglib prefix values and reserved taglib prefix
* values in the same file
*
*/
public class JSPDirectiveValidator extends JSPValidator {
private HashMap fReservedPrefixes = new HashMap();
private HashMap fTaglibPrefixesInUse = new HashMap();
private HashMap fTextRegionToDocumentRegionMap = new HashMap();
public JSPDirectiveValidator() {
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$
}
public void cleanup(IReporter reporter) {
super.cleanup(reporter);
fTaglibPrefixesInUse.clear();
fTextRegionToDocumentRegionMap.clear();
}
private void collectPrefix(IStructuredDocumentRegion documentRegion, ITextRegion valueRegion, String taglibPrefix) {
fTextRegionToDocumentRegionMap.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);
}
}
private boolean isReservedPrefix(String name) {
return fReservedPrefixes.get(name) != null;
}
private void processDirective(IReporter reporter, IFile file, IStructuredDocument sDoc, IStructuredDocumentRegion documentRegion) {
String directiveName = getDirectiveName(documentRegion);
// we only care about taglib directive
if (directiveName.equals("taglib")) { //$NON-NLS-1$
ITextRegion valueRegion = null;
if (file != null) {
valueRegion = getAttributeValueRegion(documentRegion, JSP11Namespace.ATTR_NAME_URI);
String uri = documentRegion.getText(valueRegion);
uri = StringUtils.stripQuotes(uri);
ITaglibRecord tld = TaglibIndex.resolve(file.getFullPath().toString(), uri, false);
if (tld == null) {
String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_1, uri);
int sev = IMessage.HIGH_SEVERITY;
LocalizedMessage message = new LocalizedMessage(sev, msgText, file);
int start = documentRegion.getStartOffset(valueRegion);
int length = valueRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(this, message);
}
}
valueRegion = getAttributeValueRegion(documentRegion, JSP11Namespace.ATTR_NAME_PREFIX);
if (valueRegion == null)
return;
String taglibPrefix = documentRegion.getText(valueRegion);
taglibPrefix = StringUtils.stripQuotes(taglibPrefix);
collectPrefix(documentRegion, valueRegion, taglibPrefix);
// check for the use of reserved prefixes
if (isReservedPrefix(taglibPrefix)) {
String msgText = JSPCoreMessages.JSPDirectiveValidator_0 + taglibPrefix + "'"; //$NON-NLS-2$ //$NON-NLS-1$
int sev = IMessage.HIGH_SEVERITY;
LocalizedMessage message = (file == null ? new LocalizedMessage(sev, msgText) : new LocalizedMessage(sev, msgText, file));
int start = documentRegion.getStartOffset(valueRegion);
int length = valueRegion.getTextLength();
int lineNo = sDoc.getLineOfOffset(start);
message.setLineNo(lineNo);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(this, message);
}
}
}
private void reportDuplicatePrefixes(IFile file, IReporter reporter, IStructuredDocument document) {
String[] prefixes = (String[]) fTaglibPrefixesInUse.keySet().toArray(new String[0]);
for (int prefixNumber = 0; prefixNumber < prefixes.length; prefixNumber++) {
Object o = fTaglibPrefixesInUse.get(prefixes[prefixNumber]);
/*
* Only care if it's a List (because there was more than one
* directive with that prefix)
*/
if (o instanceof List) {
List valueRegions = (List) o;
int sev = IMessage.HIGH_SEVERITY;
String msgText = 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) fTextRegionToDocumentRegionMap.get(valueRegion);
LocalizedMessage message = (file == null ? new LocalizedMessage(sev, msgText) : new LocalizedMessage(sev, msgText, file));
message = (file == null ? new LocalizedMessage(sev, msgText) : new LocalizedMessage(sev, msgText, file));
// if there's a message, there was an error found
if (message != null) {
int start = documentRegion.getStartOffset(valueRegion);
int length = valueRegion.getTextLength();
int lineNo = document.getLineOfOffset(start);
message.setLineNo(lineNo);
message.setOffset(start);
message.setLength(length);
reporter.addMessage(this, message);
}
}
}
}
}
public void validate(IValidationContext helper, IReporter reporter) throws ValidationException {
reporter.removeAllMessages(this);
super.validate(helper, reporter);
}
/**
* batch validation call
*/
protected void validateFile(IFile f, IReporter reporter) {
/*
* when validating an entire file (or multiple files), need to clear
* dupes or else you're comparing between files
*/
fTaglibPrefixesInUse.clear();
fTextRegionToDocumentRegionMap.clear();
// for batch validation
IStructuredModel sModel = null;
try {
sModel = StructuredModelManager.getModelManager().getModelForRead(f);
if (sModel != null) {
IStructuredDocument structuredDocument = sModel.getStructuredDocument();
// iterate all document regions
IStructuredDocumentRegion region = structuredDocument.getFirstStructuredDocumentRegion();
while (region != null && !reporter.isCancelled()) {
// only checking directives
if (region.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
processDirective(reporter, f, structuredDocument, region);
}
region = region.getNext();
}
if (!reporter.isCancelled()) {
reportDuplicatePrefixes(f, reporter, structuredDocument);
}
}
}
catch (IOException e) {
Logger.logException(e);
}
catch (CoreException e) {
Logger.logException(e);
}
finally {
if (sModel != null)
sModel.releaseFromRead();
}
}
}