blob: 098cbc3372446e5382449783c6158347e58b77bd [file] [log] [blame]
/*******************************************************************************
* 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.contenttype;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jst.jsp.core.internal.Logger;
import org.eclipse.jst.jsp.core.internal.util.CommonXML;
import org.eclipse.jst.jsp.core.internal.util.FacetModuleCoreSupport;
import org.eclipse.jst.jsp.core.internal.util.FileContentCache;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* A cache fo property group information stored in web.xml files. Information
* is not persisted.
*/
public final class DeploymentDescriptorPropertyCache {
private static final PropertyGroup[] NO_PROPERTY_GROUPS = new PropertyGroup[0];
private static class DeploymentDescriptor {
PropertyGroup[] groups;
long modificationStamp;
Float version = new Float(defaultWebAppVersion);
}
/**
* Representation of the JSP 2.0 property-group definitions from a servlet
* deployment descriptor.
*/
public static final class PropertyGroup {
static PropertyGroup createFrom(IPath path, Node propertyGroupNode, int groupNumber) {
PropertyGroup group = new PropertyGroup(path, groupNumber);
Node propertyGroupID = propertyGroupNode.getAttributes().getNamedItem(ID);
if (propertyGroupID != null) {
group.setId(propertyGroupID.getNodeValue());
}
Node node = propertyGroupNode.getFirstChild();
while (node != null) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
String name = node.getLocalName();
if (name == null) {
name = node.getNodeName();
}
if (IS_XML.equals(name)) {
group.setIsXML(getContainedText(node));
}
else if (EL_IGNORED.equals(name)) {
group.setElignored(getContainedText(node));
}
else if (INCLUDE_CODA.equals(name)) {
group.addCoda(getContainedText(node));
}
else if (INCLUDE_PRELUDE.equals(name)) {
group.addPrelude(getContainedText(node));
}
else if (SCRIPTING_INVALID.equals(name)) {
group.setScriptingInvalid(getContainedText(node));
}
else if (PAGE_ENCODING.equals(name)) {
group.setPageEncoding(getContainedText(node));
}
else if (URL_PATTERN.equals(name)) {
group.setUrlPattern(getContainedText(node));
}
}
node = node.getNextSibling();
}
return group;
}
private boolean el_ignored;
private String id;
private IPath[] include_coda = new IPath[0];
private IPath[] include_prelude = new IPath[0];
private boolean is_xml;
private StringMatcher matcher;
private String page_encoding;
private boolean scripting_invalid;
String url_pattern;
private IPath webxmlPath;
int number;
private PropertyGroup(IPath path, int number) {
super();
this.webxmlPath = path;
this.number = number;
}
private void addCoda(String containedText) {
if (containedText.length() > 0) {
IPath[] codas = new IPath[include_coda.length + 1];
System.arraycopy(include_coda, 0, codas, 0, include_coda.length);
codas[include_coda.length] = webxmlPath.removeLastSegments(2).append(containedText);
include_coda = codas;
}
}
private void addPrelude(String containedText) {
if (containedText.length() > 0) {
IPath[] preludes = new IPath[include_prelude.length + 1];
System.arraycopy(include_prelude, 0, preludes, 0, include_prelude.length);
preludes[include_prelude.length] = webxmlPath.removeLastSegments(2).append(containedText);
include_prelude = preludes;
}
}
public String getId() {
return id;
}
public IPath[] getIncludeCoda() {
return include_coda;
}
public IPath[] getIncludePrelude() {
return include_prelude;
}
public String getPageEncoding() {
return page_encoding;
}
public String getUrlPattern() {
return url_pattern;
}
public boolean isELignored() {
return el_ignored;
}
public boolean isIsXML() {
return is_xml;
}
public boolean isScriptingInvalid() {
return scripting_invalid;
}
boolean matches(String pattern, boolean optimistic) {
if (matcher == null)
return optimistic;
return matcher.match(pattern);
}
private void setElignored(String el_ignored) {
this.el_ignored = Boolean.valueOf(el_ignored).booleanValue();
}
private void setId(String id) {
this.id = id;
}
private void setIsXML(String is_xml) {
this.is_xml = Boolean.valueOf(is_xml).booleanValue();
}
private void setPageEncoding(String page_encoding) {
this.page_encoding = page_encoding;
}
private void setScriptingInvalid(String scripting_invalid) {
this.scripting_invalid = Boolean.valueOf(scripting_invalid).booleanValue();
}
private void setUrlPattern(String url_pattern) {
this.url_pattern = url_pattern;
if (url_pattern != null && url_pattern.length() > 0) {
this.matcher = new StringMatcher(url_pattern);
}
}
public String toString() {
return number + ":" + url_pattern;
}
}
private static class ResourceChangeListener implements IResourceChangeListener {
public void resourceChanged(IResourceChangeEvent event) {
IResourceDelta delta = event.getDelta();
if (event.getType() != IResourceChangeEvent.POST_CHANGE)
return;
if (delta.getKind() == IResourceDelta.CHANGED && (delta.getFlags() == IResourceDelta.ENCODING || delta.getFlags() == IResourceDelta.MARKERS))
return;
IResourceDeltaVisitor visitor = new IResourceDeltaVisitor() {
public boolean visit(IResourceDelta delta) {
IResource resource = delta.getResource();
if (resource.getType() == IResource.FILE) {
if (delta.getKind() == IResourceDelta.CHANGED && (delta.getFlags() == IResourceDelta.ENCODING || delta.getFlags() == IResourceDelta.MARKERS))
return false;
IPath path = resource.getFullPath();
int segmentCount = path.segmentCount();
if (segmentCount > 1 && path.lastSegment().equals(WEB_XML) && path.segment(segmentCount - 2).equals(WEB_INF)) {
getInstance().deploymentDescriptorChanged(path);
}
}
else if (resource.getType() == IResource.PROJECT) {
String name = resource.getName();
if(_debugResolutionCache) {
System.out.println("Removing DeploymentDescriptorPropertyCache resolution cache for project " + name); //$NON-NLS-1$
}
getInstance().resolvedMap.remove(name);
}
return true;
}
};
try {
delta.accept(visitor);
}
catch (CoreException e) {
Logger.logException(e);
}
}
}
private static class ResourceErrorHandler implements ErrorHandler {
private boolean fDoLogExceptions = false;
private IPath fPath;
ResourceErrorHandler(boolean logExceptions) {
super();
fDoLogExceptions = logExceptions;
}
public void error(SAXParseException exception) throws SAXException {
if (fDoLogExceptions)
Logger.log(Logger.WARNING, "SAXParseException with " + fPath + " (error) while reading descriptor: " + exception.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public void fatalError(SAXParseException exception) throws SAXException {
if (fDoLogExceptions)
Logger.log(Logger.WARNING, "SAXParseException with " + fPath + " (fatalError) while reading descriptor: " + exception.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public void setPath(IPath path) {
fPath = path;
}
public void warning(SAXParseException exception) throws SAXException {
if (fDoLogExceptions)
Logger.log(Logger.WARNING, "SAXParseException with " + fPath + " (warning) while reading descriptor: " + exception.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
/**
* Copied from org.eclipse.core.internal.propertytester.StringMatcher, but
* should be replaced with a more accurate implementation of the rules in
* Servlet spec SRV.11.2
*/
private static class StringMatcher {
private static final char SINGLE_WILD_CARD = '\u0000';
/**
* Boundary value beyond which we don't need to search in the text
*/
private int bound = 0;
private boolean hasLeadingStar;
private boolean hasTrailingStar;
private final String pattern;
private final int patternLength;
/**
* The pattern split into segments separated by *
*/
private String segments[];
/**
* StringMatcher constructor takes in a String object that is a simple
* pattern which may contain '*' for 0 and many characters and '?' for
* exactly one character.
*
* Literal '*' and '?' characters must be escaped in the pattern e.g.,
* "\*" means literal "*", etc.
*
* Escaping any other character (including the escape character
* itself), just results in that character in the pattern. e.g., "\a"
* means "a" and "\\" means "\"
*
* If invoking the StringMatcher with string literals in Java, don't
* forget escape characters are represented by "\\".
*
* @param pattern
* the pattern to match text against
*/
StringMatcher(String pattern) {
if (pattern == null)
throw new IllegalArgumentException();
this.pattern = pattern;
patternLength = pattern.length();
parseWildCards();
}
/**
* @param text
* a simple regular expression that may only contain '?'(s)
* @param start
* the starting index in the text for search, inclusive
* @param end
* the stopping point of search, exclusive
* @param p
* a simple regular expression that may contain '?'
* @return the starting index in the text of the pattern , or -1 if
* not found
*/
private int findPosition(String text, int start, int end, String p) {
boolean hasWildCard = p.indexOf(SINGLE_WILD_CARD) >= 0;
int plen = p.length();
for (int i = start, max = end - plen; i <= max; ++i) {
if (hasWildCard) {
if (regExpRegionMatches(text, i, p, 0, plen))
return i;
}
else {
if (text.regionMatches(true, i, p, 0, plen))
return i;
}
}
return -1;
}
/**
* Given the starting (inclusive) and the ending (exclusive) positions
* in the <code>text</code>, determine if the given substring
* matches with aPattern
*
* @return true if the specified portion of the text matches the
* pattern
* @param text
* a String object that contains the substring to match
*/
public boolean match(String text) {
if (text == null)
return false;
final int end = text.length();
final int segmentCount = segments.length;
if (segmentCount == 0 && (hasLeadingStar || hasTrailingStar)) // pattern
// contains
// only
// '*'(s)
return true;
if (end == 0)
return patternLength == 0;
if (patternLength == 0)
return false;
int currentTextPosition = 0;
if ((end - bound) < 0)
return false;
int segmentIndex = 0;
String current = segments[segmentIndex];
/* process first segment */
if (!hasLeadingStar) {
int currentLength = current.length();
if (!regExpRegionMatches(text, 0, current, 0, currentLength))
return false;
segmentIndex++;
currentTextPosition = currentTextPosition + currentLength;
}
if ((segmentCount == 1) && (!hasLeadingStar) && (!hasTrailingStar)) {
// only one segment to match, no wild cards specified
return currentTextPosition == end;
}
/* process middle segments */
while (segmentIndex < segmentCount) {
current = segments[segmentIndex];
int currentMatch = findPosition(text, currentTextPosition, end, current);
if (currentMatch < 0)
return false;
currentTextPosition = currentMatch + current.length();
segmentIndex++;
}
/* process final segment */
if (!hasTrailingStar && currentTextPosition != end) {
int currentLength = current.length();
return regExpRegionMatches(text, end - currentLength, current, 0, currentLength);
}
return segmentIndex == segmentCount;
}
/**
* Parses the pattern into segments separated by wildcard '*'
* characters.
*/
private void parseWildCards() {
if (pattern.startsWith("*"))//$NON-NLS-1$
hasLeadingStar = true;
if (pattern.endsWith("*")) {//$NON-NLS-1$
/* make sure it's not an escaped wildcard */
if (patternLength > 1 && pattern.charAt(patternLength - 2) != '\\') {
hasTrailingStar = true;
}
}
ArrayList temp = new ArrayList();
int pos = 0;
StringBuffer buf = new StringBuffer();
while (pos < patternLength) {
char c = pattern.charAt(pos++);
switch (c) {
case '\\' :
if (pos >= patternLength) {
buf.append(c);
}
else {
char next = pattern.charAt(pos++);
/* if it's an escape sequence */
if (next == '*' || next == '?' || next == '\\') {
buf.append(next);
}
else {
/*
* not an escape sequence, just insert
* literally
*/
buf.append(c);
buf.append(next);
}
}
break;
case '*' :
if (buf.length() > 0) {
/* new segment */
temp.add(buf.toString());
bound += buf.length();
buf.setLength(0);
}
break;
case '?' :
/*
* append special character representing single match
* wildcard
*/
buf.append(SINGLE_WILD_CARD);
break;
default :
buf.append(c);
}
}
/* add last buffer to segment list */
if (buf.length() > 0) {
temp.add(buf.toString());
bound += buf.length();
}
segments = (String[]) temp.toArray(new String[temp.size()]);
}
/**
*
* @return boolean
* @param text
* a String to match
* @param tStart
* the starting index of match, inclusive
* @param p
* a simple regular expression that may contain '?'
* @param pStart
* The start position in the pattern
* @param plen
* The length of the pattern
*/
private boolean regExpRegionMatches(String text, int tStart, String p, int pStart, int plen) {
while (plen-- > 0) {
char tchar = text.charAt(tStart++);
char pchar = p.charAt(pStart++);
// process wild cards, skipping single wild cards
if (pchar == SINGLE_WILD_CARD)
continue;
if (pchar == tchar)
continue;
if (Character.toUpperCase(tchar) == Character.toUpperCase(pchar))
continue;
// comparing after converting to upper case doesn't handle all
// cases;
// also compare after converting to lower case
if (Character.toLowerCase(tchar) == Character.toLowerCase(pchar))
continue;
return false;
}
return true;
}
}
private static DeploymentDescriptorPropertyCache _instance = new DeploymentDescriptorPropertyCache();
private static final boolean _debugResolutionCache = false;
private static final float defaultWebAppVersion = 2.4f;
private static String EL_IGNORED = "el-ignored";
private static String ID = "id";
private static String INCLUDE_CODA = "include-coda";
private static String INCLUDE_PRELUDE = "include-prelude";
private static String IS_XML = "is-xml";
private static String JSP_PROPERTY_GROUP = "jsp-property-group";
private static String PAGE_ENCODING = "page-encoding";
private static String SCRIPTING_INVALID = "scripting-invalid";
private static String URL_PATTERN = "url-pattern";
private static final String WEB_APP_ELEMENT_LOCAL_NAME = ":web-app";
private static final String WEB_APP_ELEMENT_NAME = "web-app";
private static final String WEB_APP_VERSION_NAME = "version";
private static final String WEB_INF = "WEB-INF";
private static final String WEB_XML = "web.xml";
// private static final String WEB_INF_WEB_XML = WEB_INF + IPath.SEPARATOR
// + WEB_XML;
private static final String SLASH_WEB_INF_WEB_XML = Path.ROOT.toString() + WEB_INF + IPath.SEPARATOR + WEB_XML;
static String getContainedText(Node parent) {
NodeList children = parent.getChildNodes();
if (children.getLength() == 1) {
return children.item(0).getNodeValue().trim();
}
StringBuffer s = new StringBuffer();
Node child = parent.getFirstChild();
while (child != null) {
if (child.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
String reference = ((EntityReference) child).getNodeValue();
if (reference == null && child.getNodeName() != null) {
reference = "&" + child.getNodeName() + ";"; //$NON-NLS-1$ //$NON-NLS-2$
}
if (reference != null) {
s.append(reference.trim());
}
}
else {
s.append(child.getNodeValue().trim());
}
child = child.getNextSibling();
}
return s.toString().trim();
}
public static DeploymentDescriptorPropertyCache getInstance() {
return _instance;
}
/**
* This method is not meant to be called by clients.
*/
public static void start() {
ResourcesPlugin.getWorkspace().addResourceChangeListener(getInstance().fResourceChangeListener, IResourceChangeEvent.POST_CHANGE);
}
/**
* This method is not meant to be called by clients.
*/
public static void stop() {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(getInstance().fResourceChangeListener);
}
private ResourceErrorHandler errorHandler;
private Map fDeploymentDescriptors = new Hashtable();
private IResourceChangeListener fResourceChangeListener = new ResourceChangeListener();
// for use when reading TLDs
private EntityResolver resolver;
Map resolvedMap = new HashMap();
private DeploymentDescriptorPropertyCache() {
super();
}
private void _parseDocument(IPath path, Float[] version, List groupList, SubProgressMonitor subMonitor, Document document) {
Element webapp = document.getDocumentElement();
if (webapp != null) {
if (webapp.getTagName().equals(WEB_APP_ELEMENT_NAME) || webapp.getNodeName().endsWith(WEB_APP_ELEMENT_LOCAL_NAME)) {
String versionValue = webapp.getAttribute(WEB_APP_VERSION_NAME);
if (versionValue != null) {
try {
version[0] = Float.valueOf(versionValue);
}
catch (NumberFormatException e) {
// doesn't matter
}
}
}
}
NodeList propertyGroupElements = document.getElementsByTagName(JSP_PROPERTY_GROUP);
int length = propertyGroupElements.getLength();
subMonitor.beginTask("Reading Property Groups", length);
for (int i = 0; i < length; i++) {
PropertyGroup group = PropertyGroup.createFrom(path, propertyGroupElements.item(i), i);
subMonitor.worked(1);
if (group != null) {
groupList.add(group);
}
}
}
/**
* Convert the SRV spec version to the JSP spec version
*/
private float convertSpecVersions(float version) {
if (version > 0) {
if (version == 2.5f)
return 2.1f;
else if (version == 2.4f)
return 2.0f;
else if (version == 2.3f)
return 1.2f;
else if (version == 2.2f)
return 1.1f;
else if (version == 2.1f)
return 1.0f;
}
return convertSpecVersions(defaultWebAppVersion);
}
void deploymentDescriptorChanged(final IPath fullPath) {
if (fDeploymentDescriptors.containsKey(fullPath.makeAbsolute())) {
updateCacheEntry(fullPath);
}
}
/**
* parse the specified resource using Xerces, and if that fails, use the
* SSE XML parser to find the property groups.
*/
private DeploymentDescriptor fetchDescriptor(IPath path, IProgressMonitor monitor) {
monitor.beginTask("Reading Deployment Descriptor", 3);
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
PropertyGroup groups[] = null;
IStructuredModel model = null;
List groupList = new ArrayList();
Float[] version = new Float[1];
SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 2);
DocumentBuilder builder = CommonXML.getDocumentBuilder(false);
builder.setEntityResolver(getEntityResolver());
builder.setErrorHandler(getErrorHandler(path));
try {
InputSource inputSource = new InputSource();
String s = FileContentCache.getInstance().getContents(path);
inputSource.setCharacterStream(new StringReader(s));
inputSource.setSystemId(path.toString());
Document document = builder.parse(inputSource);
_parseDocument(path, version, groupList, subMonitor, document);
}
catch (SAXException e1) {
/* encountered a fatal parsing error, try our own parser */
try {
/**
* Chiefly because the web.xml file itself is editable, use
* SSE to get the DOM Document because it is more fault
* tolerant.
*/
model = StructuredModelManager.getModelManager().getModelForRead(file);
monitor.worked(1);
if (model instanceof IDOMModel) {
IDOMDocument document = ((IDOMModel) model).getDocument();
_parseDocument(path, version, groupList, subMonitor, document);
}
}
catch (Exception e) {
Logger.logException(e);
}
finally {
if (model != null) {
model.releaseFromRead();
}
}
}
catch (IOException e1) {
/* file is unreadable, create no property groups */
}
finally {
groups = (PropertyGroup[]) groupList.toArray(new PropertyGroup[groupList.size()]);
subMonitor.done();
}
if (groups == null) {
groups = NO_PROPERTY_GROUPS;
}
DeploymentDescriptor deploymentDescriptor = new DeploymentDescriptor();
deploymentDescriptor.modificationStamp = file.getModificationStamp();
deploymentDescriptor.groups = groups;
deploymentDescriptor.version = version[0];
monitor.done();
fDeploymentDescriptors.put(path, new SoftReference(deploymentDescriptor));
return deploymentDescriptor;
}
private EntityResolver getEntityResolver() {
if (resolver == null) {
resolver = new EntityResolver() {
public InputSource resolveEntity(String publicID, String systemID) throws SAXException, IOException {
InputSource result = new InputSource(new ByteArrayInputStream(new byte[0]));
result.setPublicId(publicID);
result.setSystemId(systemID != null ? systemID : "/_" + getClass().getName()); //$NON-NLS-1$
return result;
}
};
}
return resolver;
}
/**
* Returns an ErrorHandler that will not stop the parser on reported
* errors
*/
private ErrorHandler getErrorHandler(IPath path) {
if (errorHandler == null) {
errorHandler = new ResourceErrorHandler(false);
}
errorHandler.setPath(path);
return errorHandler;
}
/**
* @param fullPath
* @return the JSP version supported by the web application containing the
* path. A value stated within a web.xml file takes priority.
*/
public float getJSPVersion(IPath fullPath) {
float version = defaultWebAppVersion;
/* try applicable web.xml file first */
IPath webxmlPath = getWebXMLPath(fullPath);
if (webxmlPath != null) {
IFile webxmlFile = ResourcesPlugin.getWorkspace().getRoot().getFile(webxmlPath);
if (webxmlFile.isAccessible()) {
Reference descriptorHolder = (Reference) fDeploymentDescriptors.get(webxmlPath);
DeploymentDescriptor descriptor = null;
if (descriptorHolder == null || ((descriptor = (DeploymentDescriptor) descriptorHolder.get()) == null) || (descriptor.modificationStamp == IResource.NULL_STAMP) || (descriptor.modificationStamp != webxmlFile.getModificationStamp())) {
descriptor = fetchDescriptor(webxmlPath, new NullProgressMonitor());
}
if (descriptor.version != null) {
version = descriptor.version.floatValue();
return convertSpecVersions(version);
}
}
}
/* check facet settings */
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(fullPath.segment(0));
version = FacetModuleCoreSupport.getDynamicWebProjectVersion(project);
return convertSpecVersions(version);
}
/**
* @param jspFilePath
* @return PropertyGroups matching the file at the given path or an empty
* array if no web.xml file exists or no matching property group
* was defined. A returned PropertyGroup object should be
* considered short-lived and not saved for later use.
*/
public PropertyGroup[] getPropertyGroups(IPath jspFilePath) {
List matchingGroups = new ArrayList(1);
IPath webxmlPath = getWebXMLPath(jspFilePath);
if (webxmlPath == null)
return NO_PROPERTY_GROUPS;
IFile webxmlFile = ResourcesPlugin.getWorkspace().getRoot().getFile(webxmlPath);
if (!webxmlFile.isAccessible())
return NO_PROPERTY_GROUPS;
Reference descriptorHolder = (Reference) fDeploymentDescriptors.get(webxmlPath);
DeploymentDescriptor descriptor = null;
if (descriptorHolder == null || ((descriptor = (DeploymentDescriptor) descriptorHolder.get()) == null) || (descriptor.modificationStamp == IResource.NULL_STAMP) || (descriptor.modificationStamp != webxmlFile.getModificationStamp())) {
descriptor = fetchDescriptor(webxmlPath, new NullProgressMonitor());
}
for (int i = 0; i < descriptor.groups.length; i++) {
if (descriptor.groups[i].matches(FacetModuleCoreSupport.getRuntimePath(jspFilePath).toString(), false)) {
matchingGroups.add(descriptor.groups[i]);
}
}
if (matchingGroups.isEmpty()) {
for (int i = 0; i < descriptor.groups.length; i++) {
if (descriptor.groups[i].matches(FacetModuleCoreSupport.getRuntimePath(jspFilePath).toString(), true)) {
matchingGroups.add(descriptor.groups[i]);
}
}
}
return (PropertyGroup[]) matchingGroups.toArray(new PropertyGroup[matchingGroups.size()]);
}
private IPath getWebXMLPath(IPath fullPath) {
/*
* It can take the better part of a full second to do this, so cache
* the result.
*/
IPath resolved = null;
Map mapForProject = null;
mapForProject = (Map) resolvedMap.get(fullPath.segment(0));
if (mapForProject != null) {
resolved = (IPath) mapForProject.get(fullPath);
}
else {
mapForProject = new HashMap();
resolvedMap.put(fullPath.segment(0), mapForProject);
}
if (resolved != null) {
if (_debugResolutionCache) {
System.out.println("DeploymentDescriptorPropertyCache resolution cache hit for " + fullPath); //$NON-NLS-1$
}
}
else {
if (_debugResolutionCache) {
System.out.println("DeploymentDescriptorPropertyCache resolution cache miss for " + fullPath); //$NON-NLS-1$
}
resolved = FacetModuleCoreSupport.resolve(fullPath, SLASH_WEB_INF_WEB_XML);
mapForProject.put(fullPath, resolved);
}
return resolved;
}
public IFile getWebXML(IPath fullPath) {
IPath webxmlPath = getWebXMLPath(fullPath);
IFile webxmlFile = null;
if (webxmlPath != null) {
webxmlFile = ResourcesPlugin.getWorkspace().getRoot().getFile(webxmlPath);
}
return webxmlFile;
}
private void updateCacheEntry(IPath fullPath) {
/* don't update right now; remove and wait for another query to update */
fDeploymentDescriptors.remove(fullPath);
}
}