/*******************************************************************************
 * Copyright (c) 2005, 2008 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.taglib;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jst.jsp.core.internal.Logger;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP11TLDNames;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP12TLDNames;
import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache;
import org.eclipse.jst.jsp.core.internal.java.ArrayMap;
import org.eclipse.jst.jsp.core.internal.util.DocumentProvider;
import org.eclipse.jst.jsp.core.internal.util.FacetModuleCoreSupport;
import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
import org.eclipse.wst.sse.core.internal.util.JarUtilities;
import org.eclipse.wst.sse.core.internal.util.Sorter;
import org.eclipse.wst.sse.core.utils.StringUtils;
import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
import org.w3c.dom.Document;
import org.w3c.dom.EntityReference;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.ibm.icu.text.Collator;
import com.ibm.icu.util.StringTokenizer;

/**
 * Contains the tag library information for a single project.
 * 
 *  * <p>
 * This class is neither intended to be instantiated nor accessed by clients.
 * </p>
 *
 */
class ProjectDescription {

	class DeltaVisitor implements IResourceDeltaVisitor {
		public boolean visit(IResourceDelta delta) throws CoreException {
			IResource resource = delta.getResource();
			if (resource.getType() == IResource.FILE) {
				if (delta.getKind() == IResourceDelta.CHANGED && (delta.getFlags() == IResourceDelta.ENCODING || delta.getFlags() == IResourceDelta.MARKERS))
					return true;
				if (resource.getName().endsWith(".tld")) { //$NON-NLS-1$
					if (delta.getKind() == IResourceDelta.REMOVED) {
						removeTLD(resource);
					}
					else {
						updateTLD(resource, delta.getKind());
					}
				}
				else if (resource.getName().endsWith(".jar")) { //$NON-NLS-1$
					if (delta.getKind() == IResourceDelta.REMOVED) {
						removeJAR(resource);
					}
					else {
						updateJAR(resource, delta.getKind());
					}
				}
				else if ("tag".equalsIgnoreCase(resource.getFileExtension()) || "tagx".equalsIgnoreCase(resource.getFileExtension())) { //$NON-NLS-1$ //$NON-NLS-2$
					if (delta.getKind() == IResourceDelta.REMOVED) {
						removeTag(resource);
					}
					else {
						updateTag(resource, delta.getKind());
					}
				}
				else if (resource.getName().equals(WEB_XML) && resource.getParent().getName().equals(WEB_INF)) {
					if (delta.getKind() == IResourceDelta.REMOVED) {
						removeWebXML(resource);
					}
					else {
						updateWebXML(resource, delta.getKind());
					}
				}
			}
			return resource.getName().length() != 0 && resource.getName().charAt(0) != '.';
		}
	}

	class Indexer implements IResourceProxyVisitor {
		public boolean visit(IResourceProxy proxy) throws CoreException {
			boolean visitMembers = true;
			if (proxy.getType() == IResource.FILE) {
				if (proxy.getName().endsWith(".tld")) { //$NON-NLS-1$
					updateTLD(proxy.requestResource(), ITaglibIndexDelta.ADDED);
				}
				else if (proxy.getName().endsWith(".jar")) { //$NON-NLS-1$
					updateJAR(proxy.requestResource(), ITaglibIndexDelta.ADDED);
				}
				else if (proxy.getName().endsWith(".tag") || proxy.getName().endsWith(".tagx")) { //$NON-NLS-1$ //$NON-NLS-2$
					updateTagDir(proxy.requestResource().getParent(), ITaglibIndexDelta.ADDED);
					// any folder with these files will create a record for
					// that folder in one pass
					visitMembers = false;
				}
				else if (proxy.getName().equals(WEB_XML) && proxy.requestResource().getParent().getName().equals(WEB_INF)) {
					updateWebXML(proxy.requestResource(), ITaglibIndexDelta.ADDED);
				}
			}
			String name = proxy.getName();
			return name.length() != 0 && name.charAt(0) != '.' && visitMembers;
		}
	}

	static class JarRecord implements IJarRecord {
		boolean has11TLD;
		TaglibInfo info;

		boolean isExported = true;
		boolean isMappedInWebXML;
		IPath location;
		List urlRecords;

		public boolean equals(Object obj) {
			if (!(obj instanceof JarRecord))
				return false;
			return ((JarRecord) obj).location.equals(location) && ((JarRecord) obj).has11TLD == has11TLD && ((JarRecord) obj).info.equals(info);
		}

		public ITaglibDescriptor getDescriptor() {
			return info != null ? info : new TaglibInfo();
		}

		/**
		 * @return Returns the location.
		 */
		public IPath getLocation() {
			return location;
		}

		public int getRecordType() {
			return ITaglibRecord.JAR;
		}

		/**
		 * @return Returns the recommended/default prefix if one was given.
		 */
		public String getShortName() {
			if (info == null)
				return null;
			return info.shortName;
		}

		/**
		 * @return Returns the uri.
		 */
		public String getURI() {
			if (info == null)
				return null;
			return info.uri;
		}

		public List getURLRecords() {
			return urlRecords;
		}

		public String toString() {
			StringBuffer s = new StringBuffer("JarRecord: ");//$NON-NLS-1$ 
			s.append(location);
			if (urlRecords.size() > 0) {
				s.append('\n');//$NON-NLS-1$ 
				for (int i = 0; i < urlRecords.size(); i++) {
					s.append(urlRecords.get(i));
					s.append('\n');//$NON-NLS-1$ 
				}
			}
			return s.toString();
		}
	}

	static class TagDirRecord implements ITagDirRecord {
		TaglibInfo info;
		IPath path;
		// a List holding Strings of .tag and .tagx filenames relative to the
		// tagdir's location
		List tags = new ArrayList(0);

		public boolean equals(Object obj) {
			if (!(obj instanceof TagDirRecord))
				return false;
			return ((TagDirRecord) obj).path.equals(path) && ((TagDirRecord) obj).info.equals(info);
		}

		public ITaglibDescriptor getDescriptor() {
			return info != null ? info : (info = new TaglibInfo());
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jst.jsp.core.taglib.ITagDirRecord#getPath()
		 */
		public IPath getPath() {
			return path;
		}

		public int getRecordType() {
			return ITaglibRecord.TAGDIR;
		}

		/**
		 * @return Returns the tags.
		 */
		public String[] getTagFilenames() {
			return (String[]) tags.toArray(new String[tags.size()]);
		}

		public String toString() {
			return "TagdirRecord: " + path + " <-> " + info.shortName; //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/**
	 * A brief representation of the information in a TLD.
	 */
	static class TaglibInfo implements ITaglibDescriptor {
		// extract only when asked?
		String description = "";
		String displayName = "";
		String jspVersion = "";
		String largeIcon = "";
		String shortName = "";
		String smallIcon = "";
		String tlibVersion = "";
		String uri = "";

		public TaglibInfo() {
			super();
		}

		public boolean equals(Object obj) {
			if (!(obj instanceof TaglibInfo))
				return false;
			return ((TaglibInfo) obj).jspVersion == jspVersion && ((TaglibInfo) obj).description.equals(description) && ((TaglibInfo) obj).largeIcon.equals(largeIcon) && ((TaglibInfo) obj).shortName.equals(shortName) && ((TaglibInfo) obj).smallIcon.equals(smallIcon) && ((TaglibInfo) obj).tlibVersion.equals(tlibVersion) && ((TaglibInfo) obj).uri.equals(uri);
		}

		public String getDescription() {
			return description;
		}

		public String getDisplayName() {
			return displayName;
		}

		public String getJSPVersion() {
			return jspVersion;
		}

		public String getLargeIcon() {
			return largeIcon;
		}

		public String getShortName() {
			return shortName;
		}

		public String getSmallIcon() {
			return smallIcon;
		}

		public String getTlibVersion() {
			return tlibVersion;
		}

		public String getURI() {
			return uri;
		}

		public String toString() {
			return "TaglibInfo|" + shortName + "|" + tlibVersion + "|" + smallIcon + "|" + largeIcon + "|" + jspVersion + "|" + uri + "|" + description; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
		}
	}

	static class TLDRecord implements ITLDRecord {
		TaglibInfo info;
		IPath path;

		public boolean equals(Object obj) {
			if (!(obj instanceof TLDRecord))
				return false;
			return ((TLDRecord) obj).path.equals(path) && ((TLDRecord) obj).getURI().equals(getURI()) && ((TLDRecord) obj).info.equals(info);
		}

		public ITaglibDescriptor getDescriptor() {
			return info != null ? info : new TaglibInfo();
		}

		public IPath getPath() {
			return path;
		}

		public int getRecordType() {
			return ITaglibRecord.TLD;
		}

		public String getShortName() {
			if (info == null)
				return null;
			return info.shortName;
		}

		/**
		 * @return Returns the uri.
		 */
		public String getURI() {
			if (info == null)
				return null;
			return info.uri;
		}

		public String toString() {
			return "TLDRecord: " + getURI() + " <-> " + path; //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	static class URLRecord implements IURLRecord {
		String baseLocation;
		TaglibInfo info;
		boolean isExported = true;
		URL url;

		public URLRecord() {
			super();
		}

		public boolean equals(Object obj) {
			if (!(obj instanceof URLRecord))
				return false;
			return ((URLRecord) obj).baseLocation.equals(baseLocation) && ((URLRecord) obj).url.equals(url) && ((URLRecord) obj).info.equals(info);
		}

		public String getBaseLocation() {
			return baseLocation;
		}

		public ITaglibDescriptor getDescriptor() {
			return info != null ? info : new TaglibInfo();
		}

		public int getRecordType() {
			return ITaglibRecord.URL;
		}

		/**
		 * @return Returns the recommended/default prefix if one was given.
		 */
		public String getShortName() {
			if (info == null)
				return null;
			return info.shortName;
		}

		/**
		 * @return Returns the uri.
		 */
		public String getURI() {
			if (info == null)
				return ""; //$NON-NLS-1$
			return info.uri;
		}

		/**
		 * @return Returns the URL.
		 */
		public URL getURL() {
			return url;
		}

		public String toString() {
			return "URLRecord: (exported=" + isExported + ") " + baseLocation + " <-> " + getURI(); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	static class WebXMLRecord {
		TaglibInfo info;
		IPath path;
		List tldRecords = new ArrayList(0);

		public boolean equals(Object obj) {
			if (!(obj instanceof WebXMLRecord))
				return false;
			return ((WebXMLRecord) obj).path.equals(path) && ((WebXMLRecord) obj).info.equals(info);
		}

		/**
		 * @return Returns the recommended/default prefix if one was given.
		 */
		public String getPrefix() {
			if (info == null)
				return null;
			return info.shortName;
		}

		/**
		 * 
		 */
		public List getTLDRecords() {
			return tldRecords;
		}

		/**
		 * @return Returns the webxml.
		 */
		public IPath getWebXML() {
			return path;
		}

		public String toString() {
			StringBuffer s = new StringBuffer("WebXMLRecord: ");//$NON-NLS-1$ 
			s.append(path);
			if (tldRecords.size() > 0) {
				s.append('\n');//$NON-NLS-1$ 
				for (int i = 0; i < tldRecords.size(); i++) {
					s.append(tldRecords.get(i));
					s.append('\n');//$NON-NLS-1$ 
				}
			}
			return s.toString();
		}
	}
	
	private class TaglibSorter extends Sorter {
		Collator collator = Collator.getInstance();

		public boolean compare(Object elementOne, Object elementTwo) {
			/**
			 * Returns true if elementTwo is 'greater than' elementOne This is
			 * the 'ordering' method of the sort operation. Each subclass
			 * overides this method with the particular implementation of the
			 * 'greater than' concept for the objects being sorted.
			 */
			
			return (collator.compare(getTaglibPath((ITaglibRecord) elementOne), getTaglibPath((ITaglibRecord) elementTwo))) < 0;
		}
		
		private String getTaglibPath(ITaglibRecord record) {
			switch(record.getRecordType()) {
				case ITaglibRecord.JAR:
					return ((JarRecord) record).getLocation().toString();
				case ITaglibRecord.TAGDIR:
					return ((TagDirRecord) record).getPath().toString();
				case ITaglibRecord.TLD:
					return ((TLDRecord) record).getPath().toString();
				case ITaglibRecord.URL:
					return ((URLRecord) record).getBaseLocation();
				default:
					return ""; //$NON-NLS-1$
			}
		}
	}

	static boolean _debugIndexCreation = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/indexcreation")); //$NON-NLS-1$ //$NON-NLS-2$
	static boolean _debugIndexTime = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/indextime")); //$NON-NLS-1$ //$NON-NLS-2$

	private static final String BUILDPATH_DIRTY = "BUILDPATH_DIRTY"; //$NON-NLS-1$
	private static final String BUILDPATH_ENTRIES = "BUILDPATH_ENTRIES"; //$NON-NLS-1$
	private static final String BUILDPATH_PROJECT = "BUILDPATH_PROJECT"; //$NON-NLS-1$
	private static final String SAVE_FORMAT_VERSION = "Tag Library Index 1.0.3"; //$NON-NLS-1$
	private static final String WEB_INF = "WEB-INF"; //$NON-NLS-1$
	private static final IPath WEB_INF_PATH = new Path(WEB_INF);
	private static final String WEB_XML = "web.xml"; //$NON-NLS-1$

	/**
	 * Notes that the build path information is stale. Some operations can now
	 * be skipped until a resolve/getAvailable call is made.
	 */
	boolean fBuildPathIsDirty = false;

	/**
	 * Count of entries on the build path. Primary use case is for classpath
	 * containers that add an entry. Without notification (3.3), we can only
	 * check after-the-fact.
	 */
	int fBuildPathEntryCount = 0;

	/**
	 * A cached copy of all of the records createable from the XMLCatalog.
	 */
	private Collection fCatalogRecords;

	/*
	 * Records active JARs on the classpath. Taglib descriptors should be
	 * usable, but the jars by themselves are not.
	 */
	Hashtable fClasspathJars;

	/**
	 * A set of the projects that are in this project's build path.
	 * Lookups/enumerations will be redirected to the corresponding
	 * ProjectDescription instances
	 */
	Set fClasspathProjects = null;

	// holds references by URI to JARs
	Hashtable fClasspathReferences;

	/*
	 * this table is special in that it holds tables of references according
	 * to local roots
	 */
	Hashtable fImplicitReferences;

	Hashtable fJARReferences;

	IProject fProject;

	private String fSaveStateFilename;

	Hashtable fTagDirReferences;

	Hashtable fTLDReferences;

	IResourceDeltaVisitor fVisitor;
	Hashtable fWebXMLReferences;

	ILock LOCK = Job.getJobManager().newLock();

	private long time0;
	
	private TaglibSorter fTaglibSorter = new TaglibSorter();

	ProjectDescription(IProject project, String saveStateFile) {
		super();
		fProject = project;
		fSaveStateFilename = saveStateFile;

		fClasspathJars = new Hashtable(0);
		fJARReferences = new Hashtable(0);
		fTagDirReferences = new Hashtable(0);
		fTLDReferences = new Hashtable(0);
		fWebXMLReferences = new Hashtable(0);
		fImplicitReferences = new Hashtable(0);
		fClasspathReferences = new Hashtable(0);
		fClasspathProjects = new HashSet();

		restoreReferences();
	}

	private Collection _getJSP11AndWebXMLJarReferences(Collection allJARs) {
		List collection = new ArrayList(allJARs.size());
		Iterator i = allJARs.iterator();
		while (i.hasNext()) {
			JarRecord record = (JarRecord) i.next();
			if (record.has11TLD || record.isMappedInWebXML) {
				collection.add(record);
			}
		}
		return collection;
	}

	/**
	 * Adds the list of known references from this project's build path to the
	 * map, appending any processed projects into the list to avoid
	 * build-path-cycles.
	 * 
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=142408
	 * 
	 * @param references -
	 *            the map of references to ITaglibRecords
	 * @param projectsProcessed -
	 *            the list of projects already considered
	 * @param exportedOnly -
	 *            Whether to only add references derived from exported build
	 *            path containers. This method calls itself recursively with
	 *            this parameter as false.
	 */
	void addBuildPathReferences(Map references, List projectsProcessed, boolean exportedOnly) {
		ensureUpTodate();

		// Add the build path references that are exported from this project
		Enumeration keys = fClasspathReferences.keys();
		while (keys.hasMoreElements()) {
			Object key = keys.nextElement();
			URLRecord urlRecord = (URLRecord) fClasspathReferences.get(key);
			if (exportedOnly) {
				if (urlRecord.isExported) {
					references.put(key, urlRecord);
				}
			}
			else {
				references.put(key, urlRecord);
			}
		}
		IProject[] buildpathProjects = (IProject[]) fClasspathProjects.toArray(new IProject[fClasspathProjects.size()]);
		for (int i = 0; i < buildpathProjects.length; i++) {
			if (!projectsProcessed.contains(buildpathProjects[i]) && buildpathProjects[i].isAccessible()) {
				projectsProcessed.add(buildpathProjects[i]);
				ProjectDescription description = TaglibIndex.getInstance().createDescription(buildpathProjects[i]);
				description.addBuildPathReferences(references, projectsProcessed, true);

				/*
				 * 199843 (183756) - JSP Validation Cannot Find Tag Library
				 * Descriptor in Referenced Projects
				 * 
				 * Add any TLD records having URI values from projects on the
				 * build path
				 */
				Map[] rootReferences = (Map[]) description.fImplicitReferences.values().toArray(new Map[description.fImplicitReferences.size()]);
				for (int j = 0; j < rootReferences.length; j++) {
					Iterator implicitRecords = rootReferences[j].values().iterator();
					while (implicitRecords.hasNext()) {
						ITaglibRecord record = (ITaglibRecord) implicitRecords.next();
						if (record.getRecordType() == ITaglibRecord.TLD && ((ITLDRecord) record).getURI() != null) {
							references.put(((ITLDRecord) record).getURI(), record);
						}
					}
				}
			}
		}
	}

	/**
	 * Erases all known tables
	 */
	void clear() {
		fClasspathJars = new Hashtable(0);
		fJARReferences = new Hashtable(0);
		fTagDirReferences = new Hashtable(0);
		fTLDReferences = new Hashtable(0);
		fWebXMLReferences = new Hashtable(0);
		fImplicitReferences = new Hashtable(0);
		fClasspathReferences = new Hashtable(0);
	}

	private void closeJarFile(ZipFile file) {
		if (file == null)
			return;
		try {
			file.close();
		}
		catch (IOException ioe) {
			// no cleanup can be done
			Logger.logException("TaglibIndex: Could not close zip file " + file.getName(), ioe); //$NON-NLS-1$
		}
	}

	/**
	 * @param catalogEntry
	 *            a XML catalog entry pointing to a .jar or .tld file
	 * @return a ITaglibRecord describing a TLD contributed to the XMLCatalog
	 *         if one was found at the given location, null otherwise
	 */
	private ITaglibRecord createCatalogRecord(ICatalogEntry catalogEntry) {
		return createCatalogRecord(catalogEntry.getKey(), catalogEntry.getURI());
	}

	/**
	 * @param uri -
	 *            the key value that will become the returned record's "URI"
	 * @param urlString -
	 *            the string indicating where the TLD really is
	 * @return a ITaglibRecord describing a TLD contributed to the XMLCatalog
	 *         if one was found at the given location, null otherwise
	 */
	private ITaglibRecord createCatalogRecord(String uri, String urlString) {
		ITaglibRecord record = null;
		// handle "file:" URLs that point to a .jar file on disk (1.1 mode)
		if (urlString.toLowerCase(Locale.US).endsWith((".jar")) && urlString.startsWith("file:")) { //$NON-NLS-1$ //$NON-NLS-2$
			String fileLocation = null;
			try {
				URL url = new URL(urlString);
				fileLocation = url.getFile();
			}
			catch (MalformedURLException e) {
				// not worth reporting
			}
			if (fileLocation != null) {
				JarRecord jarRecord = createJARRecord(fileLocation);
				String[] entries = JarUtilities.getEntryNames(fileLocation);
				for (int jEntry = 0; jEntry < entries.length; jEntry++) {
					if (entries[jEntry].endsWith(".tld")) { //$NON-NLS-1$
						if (entries[jEntry].equals(JarUtilities.JSP11_TAGLIB)) {
							jarRecord.has11TLD = true;
							InputStream contents = JarUtilities.getInputStream(fileLocation, entries[jEntry]);
							if (contents != null) {
								TaglibInfo info = extractInfo(fileLocation, contents);
								/*
								 * the record's reported URI should match the
								 * catalog entry's "key" so replace the
								 * detected value
								 */
								info.uri = uri;
								jarRecord.info = info;
							}
							try {
								contents.close();
							}
							catch (IOException e) {
							}
						}
					}
				}
				if (jarRecord.has11TLD) {
					if (_debugIndexCreation)
						Logger.log(Logger.INFO, "created catalog record for " + urlString + "@" + jarRecord.getLocation()); //$NON-NLS-1$ //$NON-NLS-2$
					record = jarRecord;
				}

			}
		}
		// The rest are URLs into a plug-in...somewhere
		else {
			URL url = null;
			ByteArrayInputStream cachedContents = null;
			InputStream tldStream = null;
			try {
				url = new URL(urlString);
				URLConnection connection = url.openConnection();
				connection.setDefaultUseCaches(false);
				tldStream = connection.getInputStream();
			}
			catch (Exception e1) {
				Logger.logException("Exception reading TLD contributed to the XML Catalog", e1);
			}

			if (tldStream != null) {
				int c;
				ByteArrayOutputStream buffer = new ByteArrayOutputStream();
				// array dim restriction?
				byte bytes[] = new byte[2048];
				try {
					while ((c = tldStream.read(bytes)) >= 0) {
						buffer.write(bytes, 0, c);
					}
					cachedContents = new ByteArrayInputStream(buffer.toByteArray());
				}
				catch (IOException ioe) {
					// no cleanup can be done
				}
				finally {
					try {
						tldStream.close();
					}
					catch (IOException e) {
					}
				}

				URLRecord urlRecord = null;
				TaglibInfo info = extractInfo(urlString, cachedContents);
				if (info != null) {
					/*
					 * the record's reported URI should match the catalog
					 * entry's "key" so replace the detected value
					 */
					info.uri = uri;
					urlRecord = new URLRecord();
					urlRecord.info = info;
					urlRecord.baseLocation = urlString;
					urlRecord.url = url; //$NON-NLS-1$ //$NON-NLS-2$
				}
				try {
					cachedContents.close();
				}
				catch (IOException e) {
				}
				record = urlRecord;
			}
		}
		return record;
	}

	/**
	 * @param resource
	 * @return
	 */
	private JarRecord createJARRecord(IResource jar) {
		IPath location = jar.getLocation();
		JarRecord jarRecord = null;
		if (location != null) {
			jarRecord = createJARRecord(location.toString());
		}
		else if (jar.getLocationURI() != null) {
			jarRecord = createJARRecord(jar.getLocationURI().toString());
		}
		return jarRecord;
	}

	private JarRecord createJARRecord(String fileLocation) {
		JarRecord record = new JarRecord();
		record.info = new TaglibInfo();
		record.location = new Path(fileLocation);
		record.urlRecords = new ArrayList(0);
		return record;
	}

	/**
	 * @return
	 */
	private TagDirRecord createTagdirRecord(IFolder tagdir) {
		IPath tagdirPath = tagdir.getFullPath();
		TagDirRecord record = new TagDirRecord();
		record.path = tagdir.getFullPath();
		record.info = new TaglibInfo();
		// 8.4.3
		if (tagdir.getName().equals("tags")) //$NON-NLS-1$
			record.info.shortName = "tags"; //$NON-NLS-1$
		else {
			boolean determined = false;
			IPath path = tagdirPath;
			String[] segments = path.segments();
			for (int i = 1; i < segments.length; i++) {
				if (segments[i - 1].equals("WEB-INF") && segments[i].equals("tags")) { //$NON-NLS-1$ //$NON-NLS-2$
					IPath tagdirLocalPath = path.removeFirstSegments(i + 1);
					record.info.shortName = StringUtils.replace(tagdirLocalPath.toString(), "/", "-");
					determined = true;
				}
			}
			if (!determined) {
				record.info.shortName = StringUtils.replace(tagdirPath.toString(), "/", "-");
			}
		}
		// 8.4.3
		record.info.tlibVersion = "1.0";
		record.info.description = "";
		record.info.displayName = "";
		record.info.smallIcon = "";
		record.info.largeIcon = "";

		try {
			IResource[] tagfiles = tagdir.members();
			for (int i = 0; i < tagfiles.length; i++) {
				if (tagfiles[i].getType() != IResource.FILE)
					continue;
				String extension = tagfiles[i].getFileExtension();
				if (extension != null && (extension.equals("tag") || extension.equals("tagx"))) {
					record.tags.add(tagfiles[i].getName());
				}
			}
		}
		catch (CoreException e) {
			Logger.logException(e);
		}

		return record;
	}

	/**
	 * @param resource
	 * @return
	 */
	private TLDRecord createTLDRecord(IResource tld) {
		TLDRecord record = new TLDRecord();
		record.path = tld.getFullPath();
		InputStream contents = null;
		try {
			if (tld.isAccessible()) {
				contents = ((IFile) tld).getContents(true);
				String basePath = tld.getFullPath().toString();
				TaglibInfo info = extractInfo(basePath, contents);
				if (info != null) {
					record.info = info;
				}
			}
		}
		catch (CoreException e) {
			Logger.logException(e);
		}
		finally {
			try {
				if (contents != null) {
					contents.close();
				}
			}
			catch (IOException e) {
				// ignore
			}
		}
		return record;
	}

	private void ensureUpTodate() {
		IClasspathEntry[] entries = null;
			try {
				/*
				 * If the Java nature isn't present (or something else is
				 * wrong), don't check the build path.
				 */
				IJavaProject jproject = JavaCore.create(fProject);
				if (jproject != null && jproject.exists()) {
					entries = jproject.getResolvedClasspath(true);
				}
			}
			catch (JavaModelException e) {
				Logger.logException(e);
			}
		if (entries != null) {
			try {
				LOCK.acquire();
				/*
				 * Double-check that the number of build path entries has not
				 * changed. This should cover most cases such as when a
				 * library is added into or removed from a container.
				 */
				fBuildPathIsDirty = fBuildPathIsDirty || (fBuildPathEntryCount != entries.length);

				if (fBuildPathIsDirty) {
					indexClasspath(entries);
					fBuildPathIsDirty = false;
				}
			}
			finally {
				LOCK.release();
			}
		}
	}

	private TaglibInfo extractInfo(String basePath, InputStream tldContents) {
		TaglibInfo info = new TaglibInfo();
		if (tldContents != null) {
			DocumentProvider provider = new DocumentProvider();
			provider.setInputStream(tldContents);
			provider.setValidating(false);
			provider.setRootElementName(JSP12TLDNames.TAGLIB);
			provider.setBaseReference(basePath);
			Node child = provider.getRootElement();
			if (child == null || child.getNodeType() != Node.ELEMENT_NODE || !child.getNodeName().equals(JSP12TLDNames.TAGLIB)) {
				return null;
			}
			child = child.getFirstChild();
			while (child != null) {
				if (child.getNodeType() == Node.ELEMENT_NODE) {
					if (child.getNodeName().equals(JSP12TLDNames.URI)) {
						info.uri = getTextContents(child);
					}
					else if (child.getNodeName().equals(JSP12TLDNames.SHORT_NAME) || child.getNodeName().equals(JSP11TLDNames.SHORTNAME)) {
						info.shortName = getTextContents(child);
					}
					else if (child.getNodeName().equals(JSP12TLDNames.DESCRIPTION) || child.getNodeName().equals(JSP11TLDNames.INFO)) {
						info.description = getTextContents(child);
					}
					else if (child.getNodeName().equals(JSP12TLDNames.DISPLAY_NAME)) {
						info.displayName = getTextContents(child);
					}
					else if (child.getNodeName().equals(JSP12TLDNames.JSP_VERSION) || child.getNodeName().equals(JSP11TLDNames.JSPVERSION)) {
						info.jspVersion = getTextContents(child);
					}
					else if (child.getNodeName().equals(JSP12TLDNames.TLIB_VERSION) || child.getNodeName().equals(JSP11TLDNames.TLIBVERSION)) {
						info.tlibVersion = getTextContents(child);
					}
					else if (child.getNodeName().equals(JSP12TLDNames.SMALL_ICON)) {
						info.smallIcon = getTextContents(child);
					}
					else if (child.getNodeName().equals(JSP12TLDNames.LARGE_ICON)) {
						info.largeIcon = getTextContents(child);
					}
				}
				child = child.getNextSibling();
			}
		}
		return info;
	}

	List getAvailableTaglibRecords(IPath path) {
		ensureUpTodate();
		Collection records = null;
		try {
			float jspVersion = DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(path);
			LOCK.acquire();

			Collection implicitReferences = new HashSet(getImplicitReferences(path.toString()).values());
			records = new ArrayList(fTLDReferences.size() + fTagDirReferences.size() + fJARReferences.size() + fWebXMLReferences.size());
			records.addAll(fTLDReferences.values());
			if (jspVersion >= 1.1) {
				records.addAll(_getJSP11AndWebXMLJarReferences(fJARReferences.values()));
			}

			if (jspVersion >= 1.2) {
				records.addAll(implicitReferences);

				Map buildPathReferences = new HashMap();
				List projectsProcessed = new ArrayList(fClasspathProjects.size() + 1);
				projectsProcessed.add(fProject);
				addBuildPathReferences(buildPathReferences, projectsProcessed, false);
				records.addAll(buildPathReferences.values());
			}
			if (jspVersion >= 2.0) {
				records.addAll(fTagDirReferences.values());
			}

			records.addAll(getCatalogRecords());
		}
		finally {
			LOCK.release();
		}
		return new ArrayList(records);
	}

	/**
	 * Provides a stream to a local copy of the input or null if not possible
	 */
	private InputStream getCachedInputStream(ZipFile zipFile, ZipEntry zipEntry) {
		InputStream cache = null;
		if (zipFile != null) {
			if (zipEntry != null) {
				InputStream entryInputStream = null;
				try {
					entryInputStream = zipFile.getInputStream(zipEntry);
				}
				catch (IOException ioExc) {
					Logger.logException("Taglib Index: " + zipFile.getName(), ioExc); //$NON-NLS-1$
				}

				if (entryInputStream != null) {
					int c;
					ByteArrayOutputStream buffer = null;
					if (zipEntry.getSize() > 0) {
						buffer = new ByteArrayOutputStream((int) zipEntry.getSize());
					}
					else {
						buffer = new ByteArrayOutputStream();
					}
					// array dim restriction?
					byte bytes[] = new byte[2048];
					try {
						while ((c = entryInputStream.read(bytes)) >= 0) {
							buffer.write(bytes, 0, c);
						}
						cache = new ByteArrayInputStream(buffer.toByteArray());
					}
					catch (IOException ioe) {
						// no cleanup can be done
					}
					finally {
						try {
							entryInputStream.close();
						}
						catch (IOException e) {
						}
					}
				}
			}
		}

		return cache;
	}

	private Collection getCatalogRecords() {
		if (fCatalogRecords == null) {
			List records = new ArrayList();
			ICatalog defaultCatalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
			if (defaultCatalog != null) {
				// Process default catalog
				ICatalogEntry[] entries = defaultCatalog.getCatalogEntries();
				for (int entry = 0; entry < entries.length; entry++) {
					ITaglibRecord record = createCatalogRecord(entries[entry]);
					records.add(record);
				}

				// Process declared OASIS nextCatalogs catalog
				INextCatalog[] nextCatalogs = defaultCatalog.getNextCatalogs();
				for (int nextCatalog = 0; nextCatalog < nextCatalogs.length; nextCatalog++) {
					ICatalog catalog = nextCatalogs[nextCatalog].getReferencedCatalog();
					ICatalogEntry[] entries2 = catalog.getCatalogEntries();
					for (int entry = 0; entry < entries2.length; entry++) {
						String uri = entries2[entry].getURI();
						if (uri != null) {
							uri = uri.toLowerCase(Locale.US);
							if (uri.endsWith((".jar")) || uri.endsWith((".tld"))) {
								ITaglibRecord record = createCatalogRecord(entries2[entry]);
								if (record != null) {
									records.add(record);
								}
							}
						}
					}
				}
			}
			fCatalogRecords = records;
		}
		return fCatalogRecords;
	}

	/**
	 * @return Returns the implicitReferences for the given path
	 */
	Hashtable getImplicitReferences(String path) {
		String localRoot = getLocalRoot(path);
		Hashtable implicitReferences = (Hashtable) fImplicitReferences.get(localRoot);
		if (implicitReferences == null) {
			implicitReferences = new ArrayMap(1);
			fImplicitReferences.put(localRoot, implicitReferences);
		}
		return implicitReferences;
	}

	/**
	 * @param basePath
	 * @return the applicable Web context root path, if one exists
	 * @deprecated
	 */
	IPath getLocalRoot(IPath basePath) {
		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();

		// existing workspace resources - this is the 93% case
		IResource file = FileBuffers.getWorkspaceFileAtLocation(basePath);

		// Try the base path as a folder first
		if (file == null && basePath.segmentCount() > 1) {
			file = workspaceRoot.getFolder(basePath);
		}
		// If not a folder, then try base path as a file
		if (file != null && !file.exists() && basePath.segmentCount() > 1) {
			file = workspaceRoot.getFile(basePath);
		}

		if (file == null && basePath.segmentCount() == 1) {
			file = workspaceRoot.getProject(basePath.segment(0));
		}

		if (file == null) {
			/*
			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=116529
			 * 
			 * This method produces a less accurate result, but doesn't
			 * require that the file exist yet.
			 */
			IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(basePath);
			if (files.length > 0)
				file = files[0];
		}

		while (file != null) {
			/**
			 * Treat any parent folder with a WEB-INF subfolder as a web-app
			 * root
			 */
			IContainer folder = null;
			if ((file.getType() & IResource.FOLDER) != 0) {
				folder = (IContainer) file;
			}
			else {
				folder = file.getParent();
			}
			// getFolder on a workspace root must use a full path, skip
			if (folder != null && (folder.getType() & IResource.ROOT) == 0) {
				IFolder webinf = folder.getFolder(WEB_INF_PATH);
				if (webinf != null && webinf.exists()) {
					return folder.getFullPath();
				}
			}
			file = file.getParent();
		}

		return fProject.getFullPath();
	}

	/**
	 * @param basePath
	 * @return
	 */
	private String getLocalRoot(String basePath) {
		return getLocalRoot(new Path(basePath)).toString();
	}

	private String getTextContents(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();
	}

	/**
	 * @return Returns the visitor.
	 */
	IResourceDeltaVisitor getVisitor() {
		if (fVisitor == null) {
			fVisitor = new DeltaVisitor();
		}
		return fVisitor;
	}

	void handleElementChanged(IJavaElementDelta delta) {
		if (fBuildPathIsDirty) {
			return;
		}

		// Logger.log(Logger.INFO_DEBUG, "IJavaElementDelta: " + delta);
		IJavaElement element = delta.getElement();
		if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT && ((IPackageFragmentRoot) element).isArchive()) {
			time0 = System.currentTimeMillis();
			if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT && ((IPackageFragmentRoot) element).isExternal()) {
			}
			String libLocation = null;
			int taglibRecordEventKind = -1;
			if ((delta.getFlags() & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0 || (delta.getFlags() & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) > 0 || (delta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0) {
				taglibRecordEventKind = ITaglibIndexDelta.ADDED;
				IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(element.getPath());
				if (file.isAccessible() && file.getLocation() != null)
					libLocation = file.getLocation().toString();
				else
					libLocation = element.getPath().toString();
			}
			if (libLocation != null) {
				boolean fragmentisExported = true;
				try {
					IClasspathEntry rawClasspathEntry = ((IPackageFragmentRoot) element).getRawClasspathEntry();
					/*
					 * null may also be returned for deletions depending on
					 * resource/build path notification order. If it's null,
					 * it's been deleted and whether it's exported won't
					 * really matter
					 */
					if (rawClasspathEntry != null) {
						fragmentisExported = rawClasspathEntry.isExported();
					}
				}
				catch (JavaModelException e) {
					Logger.logException("Problem handling build path entry for " + element.getPath(), e); //$NON-NLS-1$
				}
				if ((delta.getFlags() & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0) {
					fBuildPathEntryCount++;
				}
				else if ((delta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0) {
					fBuildPathEntryCount--;
				}
				updateClasspathLibrary(libLocation, taglibRecordEventKind, fragmentisExported);
			}
			if (_debugIndexTime)
				Logger.log(Logger.INFO, "processed build path delta for " + fProject.getName() + "(" + element.getPath() + ") in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
	}

	void index() {
		time0 = System.currentTimeMillis();

		fTLDReferences.clear();
		fJARReferences.clear();
		fTagDirReferences.clear();
		fWebXMLReferences.clear();

		try {
			fProject.accept(new Indexer(), 0);
		}
		catch (CoreException e) {
			Logger.logException(e);
		}

		if (_debugIndexTime)
			Logger.log(Logger.INFO, "indexed " + fProject.getName() + " contents in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	/**
	 * @deprecated
	 */
	void indexClasspath() {
		if (_debugIndexTime)
			time0 = System.currentTimeMillis();
		fClasspathProjects.clear();
		fClasspathReferences.clear();
		fClasspathJars.clear();
		fBuildPathEntryCount = 0;

		IJavaProject javaProject = JavaCore.create(fProject);
		/*
		 * If the Java nature isn't present (or something else is wrong),
		 * don't check the build path.
		 */
		if (javaProject != null && javaProject.exists()) {
			indexClasspath(javaProject);
		}
		// else {
		// Logger.log(Logger.WARNING, "TaglibIndex was asked to index non-Java
		// Project " + fProject.getName()); //$NON-NLS-1$
		// }

		if (_debugIndexTime)
			Logger.log(Logger.INFO, "indexed " + fProject.getName() + " classpath in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	void indexClasspath(IClasspathEntry[] entries) {
		if (_debugIndexTime)
			time0 = System.currentTimeMillis();
		fClasspathProjects.clear();
		fClasspathReferences.clear();
		fClasspathJars.clear();

		fBuildPathEntryCount = entries.length;
		for (int i = 0; i < entries.length; i++) {
			indexClasspath(entries[i]);
		}

		if (_debugIndexTime)
			Logger.log(Logger.INFO, "indexed " + fProject.getName() + " classpath in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	/**
	 * @param entry
	 */
	private void indexClasspath(IClasspathEntry entry) {
		switch (entry.getEntryKind()) {
			case IClasspathEntry.CPE_CONTAINER : {
				IClasspathContainer container = (IClasspathContainer) entry;
				IClasspathEntry[] containedEntries = container.getClasspathEntries();
				for (int i = 0; i < containedEntries.length; i++) {
					indexClasspath(containedEntries[i]);
				}
			}
				break;
			case IClasspathEntry.CPE_LIBRARY : {
				/*
				 * Ignore libs in required projects that are not exported
				 */
				IPath libPath = entry.getPath();
				if (!fClasspathJars.containsKey(libPath.toString())) {
					if (libPath.toFile().exists()) {
						updateClasspathLibrary(libPath.toString(), ITaglibIndexDelta.ADDED, entry.isExported());
					}
					else {
						/*
						 * Note: .jars on the classpath inside of the project
						 * will have duplicate entries in the JAR references
						 * table that will e returned to
						 * getAvailableTaglibRecords().
						 */
						IFile libFile = ResourcesPlugin.getWorkspace().getRoot().getFile(libPath);
						if (libFile != null && libFile.exists()) {
							updateClasspathLibrary(libFile.getLocation().toString(), ITaglibIndexDelta.ADDED, entry.isExported());
						}
					}
				}
			}
				break;
			case IClasspathEntry.CPE_PROJECT : {
				/*
				 * We're currently ignoring whether the project exports all of
				 * its build path
				 */
				IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(entry.getPath().lastSegment());
				if (project != null) {
					fClasspathProjects.add(project);
				}
			}
				break;
			case IClasspathEntry.CPE_SOURCE :
				break;
			case IClasspathEntry.CPE_VARIABLE : {
				IPath libPath = JavaCore.getResolvedVariablePath(entry.getPath());
				if (libPath != null) {
					File file = libPath.toFile();

					// file in filesystem
					if (file.exists() && !file.isDirectory()) {
						updateClasspathLibrary(libPath.toString(), ITaglibRecordEvent.ADDED, entry.isExported());
					}
					else {
						// workspace file
						IFile jarFile = ResourcesPlugin.getWorkspace().getRoot().getFile(libPath);
						if (jarFile.isAccessible() && jarFile.getType() == IResource.FILE && jarFile.getLocation() != null) {
							String jarPathString = jarFile.getLocation().toString();
							updateClasspathLibrary(jarPathString, ITaglibRecordEvent.ADDED, entry.isExported());
						}
					}
				}
			}
				break;
		}
	}

	/*
	 * private void removeClasspathLibrary(String libraryLocation) { JarRecord
	 * record = (JarRecord) fClasspathJars.remove(libraryLocation); if (record !=
	 * null) { URLRecord[] records = (URLRecord[])
	 * record.getURLRecords().toArray(new URLRecord[0]); for (int i = 0; i <
	 * records.length; i++) {
	 * fClasspathReferences.remove(records[i].getURI()); }
	 * TaglibIndex.fireTaglibRecordEvent(new TaglibRecordEvent(record,
	 * ITaglibIndexDelta.REMOVED)); } }
	 */

	/**
	 * @deprecated
	 */
	private void indexClasspath(IJavaProject javaProject) {
		if (javaProject == null)
			return;

		IProject project = javaProject.getProject();
		if (project.equals(fProject)) {
			try {
				IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
				fBuildPathEntryCount = entries.length;
				for (int i = 0; i < entries.length; i++) {
					indexClasspath(entries[i]);
				}
			}
			catch (JavaModelException e) {
				Logger.logException("Error searching Java Build Path + (" + fProject.getName() + ") for tag libraries", e); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}
	}

	private String readTextofChild(Node node, String childName) {
		NodeList children = node.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			if (child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(childName)) {
				return getTextContents(child);
			}
		}
		return ""; //$NON-NLS-1$
	}

	void removeJAR(IResource jar) {
		if (_debugIndexCreation)
			Logger.log(Logger.INFO, "removing records for JAR " + jar.getFullPath()); //$NON-NLS-1$
		JarRecord record = (JarRecord) fJARReferences.remove(jar.getFullPath().toString());
		if (record != null) {
			URLRecord[] records = (URLRecord[]) record.getURLRecords().toArray(new URLRecord[0]);
			for (int i = 0; i < records.length; i++) {
				TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, records[i], ITaglibIndexDelta.REMOVED));
				((ArrayMap) getImplicitReferences(jar.getFullPath().toString())).remove(records[i].getURI(), records[i]);
			}
			if (record.has11TLD) {
				TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.REMOVED));
			}
		}
	}

	void removeTag(IResource resource) {
		TagDirRecord record = (TagDirRecord) fTagDirReferences.get(resource.getParent().getFullPath().toString());
		if (record != null) {
			record.tags.remove(resource.getName());
			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.CHANGED));
		}
	}

	void removeTagDir(IResource tagdir) {
		IPath tagdirPath = tagdir.getFullPath();
		if (_debugIndexCreation)
			Logger.log(Logger.INFO, "removing record for " + tagdirPath); //$NON-NLS-1$
		ITaglibRecord record = (ITaglibRecord) fTagDirReferences.remove(tagdirPath.toString());
		if (record != null) {
			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.REMOVED));
		}
	}

	void removeTLD(IResource tld) {
		if (_debugIndexCreation)
			Logger.log(Logger.INFO, "removing record for " + tld.getFullPath()); //$NON-NLS-1$
		TLDRecord record = (TLDRecord) fTLDReferences.remove(tld.getFullPath().toString());
		if (record != null) {
			if (record.getURI() != null) {
				((ArrayMap) getImplicitReferences(tld.getFullPath().toString())).remove(record.getURI(), record);
			}
			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.REMOVED));
		}
	}

	void removeWebXML(IResource webxml) {
		if (_debugIndexCreation)
			Logger.log(Logger.INFO, "removing records for " + webxml.getFullPath()); //$NON-NLS-1$
		WebXMLRecord record = (WebXMLRecord) fWebXMLReferences.remove(webxml.getFullPath().toString());
		if (record != null) {
			TLDRecord[] records = (TLDRecord[]) record.getTLDRecords().toArray(new TLDRecord[0]);
			for (int i = 0; i < records.length; i++) {
				if (_debugIndexCreation)
					Logger.log(Logger.INFO, "removed record for " + records[i].getURI() + "@" + records[i].path); //$NON-NLS-1$ //$NON-NLS-2$
				((ArrayMap) getImplicitReferences(webxml.getFullPath().toString())).remove(records[i].getURI(), records[i]);
				TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, records[i], ITaglibIndexDelta.REMOVED));
			}
		}
	}

	/**
	 * @param basePath
	 * @param reference
	 * @return
	 */
	ITaglibRecord resolve(String basePath, String reference) {
		ensureUpTodate();

		ITaglibRecord record = null;
		String path = null;
		try {
			float jspVersion = DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(new Path(basePath));

			/**
			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=196177 Support
			 * resolution in flexible projects
			 */
			IPath resourcePath = FacetModuleCoreSupport.resolve(new Path(basePath), reference);
			if (resourcePath.segmentCount() > 1) {
				if (resourcePath.toString().toLowerCase(Locale.US).endsWith(".tld")) { //$NON-NLS-1$ 
					IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(resourcePath);
					if (file.isAccessible()) {
						path = resourcePath.toString();
					}
				}
				else if (resourcePath.toString().toLowerCase(Locale.US).endsWith(".jar")) { //$NON-NLS-1$ 
					IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(resourcePath);
					if (file.isAccessible()) {
						path = resourcePath.toString();
					}
				}
			}

			LOCK.acquire();

			/**
			 * Workaround for problem in URIHelper; uris starting with '/' are
			 * returned as-is.
			 */
			if (path == null) {
				if (reference.startsWith("/")) { //$NON-NLS-1$
					path = getLocalRoot(basePath) + reference;
				}
				else {
					path = URIHelper.normalize(reference, basePath, getLocalRoot(basePath));
				}
			}

			// order dictated by JSP spec 2.0 section 7.2.3
			record = (ITaglibRecord) fJARReferences.get(path);

			// only if 1.1 TLD was found
			if (jspVersion < 1.1 || (record instanceof JarRecord && !((JarRecord) record).has11TLD)) {
				record = null;
			}
			if (record == null) {
				record = (ITaglibRecord) fTLDReferences.get(path);
			}
			if (record == null && jspVersion >= 1.2) {
				Object[] records = (Object[]) getImplicitReferences(basePath).get(reference);
				if (records != null && records.length > 0) {
					if (records.length > 1)
						records = fTaglibSorter.sort(records);
					record =  (ITaglibRecord) records[records.length - 1];
				}
			}


			if (record == null && jspVersion >= 2.0) {
				record = (ITaglibRecord) fTagDirReferences.get(path);
			}

			if (record == null && jspVersion >= 1.2) {
				record = (ITaglibRecord) fClasspathReferences.get(reference);
			}
			if (record == null && jspVersion >= 1.2) {
				Map buildPathReferences = new HashMap();
				List projectsProcessed = new ArrayList(fClasspathProjects.size() + 1);
				projectsProcessed.add(fProject);
				addBuildPathReferences(buildPathReferences, projectsProcessed, false);
				record = (ITaglibRecord) buildPathReferences.get(reference);
			}

			// Check the XML Catalog
			if (record == null) {
				ICatalog catalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
				if (catalog != null) {
					String resolvedString = null;
					try {
						// Check as system reference first
						resolvedString = catalog.resolveSystem(reference);
						// Check as URI
						if (resolvedString == null || resolvedString.trim().length() == 0) {
							resolvedString = catalog.resolveURI(reference);
						}
						// Check as public ID
						if (resolvedString == null || resolvedString.trim().length() == 0) {
							resolvedString = catalog.resolvePublic(reference, basePath);
						}
					}
					catch (Exception e) {
						Logger.logException(e);
					}
					if (resolvedString != null && resolvedString.trim().length() > 0) {
						record = createCatalogRecord(reference, resolvedString);
					}
				}
			}

			/*
			 * If no records were found and no local-root applies, check ALL
			 * of the web.xml files as a fallback
			 */
			if (record == null && fProject.getFullPath().toString().equals(getLocalRoot(basePath))) {
				WebXMLRecord[] webxmls = (WebXMLRecord[]) fWebXMLReferences.values().toArray(new WebXMLRecord[0]);
				for (int i = 0; i < webxmls.length; i++) {
					if (record != null)
						continue;
					Object[] records = (Object[]) getImplicitReferences(webxmls[i].path.toString()).get(reference);
					if (records != null && records.length > 0) {
						if (records.length > 1)
							records = fTaglibSorter.sort(records);
						record =  (ITaglibRecord) records[records.length - 1];
					}
				}
			}
		}
		finally {
			LOCK.release();
		}

		return record;
	}

	/**
	 * Restores any saved reference tables
	 */
	private void restoreReferences() {
		final boolean notifyOnRestoration = true;
		if (TaglibIndex.ENABLED) {
			// resources first
			index();
			// now build path

			// ================ test reload time ========================
			boolean restored = false;
			File savedState = new File(fSaveStateFilename);
			if (savedState.exists()) {
				Reader reader = null;
				try {
					time0 = System.currentTimeMillis();
					reader = new InputStreamReader(new BufferedInputStream(new FileInputStream(savedState)), "UTF-16"); //$NON-NLS-1$ 
					// use a string buffer temporarily to reduce string
					// creation
					StringBuffer buffer = new StringBuffer();
					char array[] = new char[2048];
					int charsRead = 0;
					while ((charsRead = reader.read(array)) != -1) {
						if (charsRead > 0) {
							buffer.append(array, 0, charsRead);
						}
					}

					IDocument doc = new org.eclipse.jface.text.Document();
					doc.set(buffer.toString());
					int lines = doc.getNumberOfLines();
					if (lines > 0) {
						IRegion line = doc.getLineInformation(0);
						String lineText = doc.get(line.getOffset(), line.getLength());
						JarRecord libraryRecord = null;
						if (SAVE_FORMAT_VERSION.equals(lineText.trim())) {
							IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();

							for (int i = 1; i < lines && !fBuildPathIsDirty; i++) {
								line = doc.getLineInformation(i);
								lineText = doc.get(line.getOffset(), line.getLength());
								StringTokenizer toker = new StringTokenizer(lineText, "|"); //$NON-NLS-1$
								if (toker.hasMoreTokens()) {
									String tokenType = toker.nextToken();
									if ("JAR".equalsIgnoreCase(tokenType)) { //$NON-NLS-1$ //$NON-NLS-2$
										boolean has11TLD = Boolean.valueOf(toker.nextToken()).booleanValue();
										boolean exported = Boolean.valueOf(toker.nextToken()).booleanValue();
										// make the rest the libraryLocation
										String libraryLocation = toker.nextToken();
										while (toker.hasMoreTokens()) {
											libraryLocation = libraryLocation + "|" + toker.nextToken(); //$NON-NLS-1$ //$NON-NLS-2$
										}
										libraryLocation = libraryLocation.trim();
										if (libraryRecord != null && notifyOnRestoration) {
											TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, libraryRecord, ITaglibIndexDelta.ADDED));
										}
										// Create a new JarRecord
										libraryRecord = createJARRecord(libraryLocation);
										libraryRecord.has11TLD = has11TLD;
										libraryRecord.isExported = exported;

										// Add a URLRecord for the 1.1 TLD
										if (has11TLD) {
											InputStream contents = JarUtilities.getInputStream(libraryLocation, JarUtilities.JSP11_TAGLIB);
											if (contents != null) {
												TaglibInfo info = extractInfo(libraryLocation, contents);

												if (info != null && info.uri != null && info.uri.length() > 0) {
													URLRecord urlRecord = new URLRecord();
													urlRecord.info = info;
													urlRecord.isExported = exported;
													urlRecord.baseLocation = libraryLocation;
													try {
														urlRecord.url = new URL("jar:file:" + libraryLocation + "!/" + JarUtilities.JSP11_TAGLIB); //$NON-NLS-1$ //$NON-NLS-2$
														libraryRecord.urlRecords.add(urlRecord);
														fClasspathReferences.put(urlRecord.getURI(), urlRecord);
														if (_debugIndexCreation)
															Logger.log(Logger.INFO, "created record for " + urlRecord.getURI() + "@" + urlRecord.getURL()); //$NON-NLS-1$ //$NON-NLS-2$
													}
													catch (MalformedURLException e) {
														/*
														 * don't record this
														 * URI
														 */
														Logger.logException(e);
													}
												}
												try {
													contents.close();
												}
												catch (IOException e) {
												}
											}
										}

										fClasspathJars.put(libraryLocation, libraryRecord);
									}
									else if ("URL".equalsIgnoreCase(tokenType) && libraryRecord != null) { //$NON-NLS-1$
										// relies on a previously declared JAR
										// record
										boolean exported = Boolean.valueOf(toker.nextToken()).booleanValue();
										// make the rest the URL
										String urlString = toker.nextToken();
										while (toker.hasMoreTokens()) {
											urlString = urlString + "|" + toker.nextToken(); //$NON-NLS-1$ //$NON-NLS-2$
										}
										urlString = urlString.trim();
										// Append a URLrecord
										URLRecord urlRecord = new URLRecord();
										urlRecord.url = new URL(urlString); //$NON-NLS-1$ //$NON-NLS-2$
										urlRecord.isExported = exported;
										urlRecord.baseLocation = libraryRecord.location.toString();
										libraryRecord.urlRecords.add(urlRecord);

										ByteArrayInputStream cachedContents = null;
										InputStream tldStream = null;
										try {
											URLConnection connection = urlRecord.url.openConnection();
											connection.setDefaultUseCaches(false);
											tldStream = connection.getInputStream();
										}
										catch (IOException e1) {
											Logger.logException(e1);
										}

										int c;
										ByteArrayOutputStream byteArrayOutput = new ByteArrayOutputStream();
										// array dim restriction?
										byte bytes[] = new byte[2048];
										try {
											while ((c = tldStream.read(bytes)) >= 0) {
												byteArrayOutput.write(bytes, 0, c);
											}
											cachedContents = new ByteArrayInputStream(byteArrayOutput.toByteArray());
										}
										catch (IOException ioe) {
											// no cleanup can be done
										}
										finally {
											try {
												tldStream.close();
											}
											catch (IOException e) {
											}
										}

										TaglibInfo info = extractInfo(urlRecord.url.toString(), cachedContents);
										if (info != null) {
											urlRecord.info = info;
										}
										try {
											cachedContents.close();
										}
										catch (IOException e) {
										}
										fClasspathReferences.put(urlRecord.getURI(), urlRecord);
									}
									else if (BUILDPATH_PROJECT.equalsIgnoreCase(tokenType)) {
										String projectName = toker.nextToken();
										if (Path.ROOT.isValidSegment(projectName)) {
											IProject project = workspaceRoot.getProject(projectName);
											/* do not check if "open" here */
											if (project != null) {
												fClasspathProjects.add(project);
											}
										}
									}
									// last since they occur once
									else if (BUILDPATH_DIRTY.equalsIgnoreCase(tokenType)) {
										fBuildPathIsDirty = Boolean.valueOf(toker.nextToken()).booleanValue();
									}
									else if (BUILDPATH_ENTRIES.equalsIgnoreCase(tokenType)) {
										fBuildPathEntryCount = Integer.valueOf(toker.nextToken()).intValue();
									}
								}
								if (libraryRecord != null && notifyOnRestoration) {
									TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, libraryRecord, ITaglibIndexDelta.ADDED));
								}
							}
							restored = true;
						}
						else {
							Logger.log(Logger.INFO, "Tag Library Index: different cache format found, was \"" + lineText + "\", supports \"" + SAVE_FORMAT_VERSION + "\", reindexing build path"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						}
					}
					if (_debugIndexTime)
						Logger.log(Logger.INFO, "time spent reloading " + fProject.getName() + " build path: " + (System.currentTimeMillis() - time0)); //$NON-NLS-1$ //$NON-NLS-2$
				}
				catch (Exception e) {
					restored = false;
					if (_debugIndexTime)
						Logger.log(Logger.INFO, "failure reloading " + fProject.getName() + " build path index", e); //$NON-NLS-1$ //$NON-NLS-2$
				}
				finally {
					if (reader != null) {
						try {
							reader.close();
						}
						catch (IOException e) {
						}
					}
				}
			}

			// ================ test reload time (end) ==================


			if (!restored) {
				setBuildPathIsDirty();
			}
		}
	}

	/**
	 * Saves any storable references to disk. This is only called when the
	 * description is being cleared and not after every update.
	 */
	void saveReferences() {
		// the build path information is out of date, remember that
		time0 = System.currentTimeMillis();
		Writer writer = null;

		/**
		 * <pre>
		 *                     		 1.0.1
		 *                     		 Save classpath information (| is field delimiter)
		 *                     		 Jars are saved as &quot;JAR:&quot;+ has11TLD + jar path 
		 *                     		 URLRecords as &quot;URL:&quot;+URL
		 * </pre>
		 */
		try {
			writer = new OutputStreamWriter(new FileOutputStream(fSaveStateFilename), "UTF-16"); //$NON-NLS-1$
			writer.write(SAVE_FORMAT_VERSION);
			writer.write('\n'); //$NON-NLS-1$
			writer.write(BUILDPATH_DIRTY + "|" + fBuildPathIsDirty); //$NON-NLS-1$
			writer.write('\n'); //$NON-NLS-1$
			writer.write(BUILDPATH_ENTRIES + "|" + fBuildPathEntryCount); //$NON-NLS-1$
			writer.write('\n'); //$NON-NLS-1$

			IProject[] projects = (IProject[]) fClasspathProjects.toArray(new IProject[0]);
			for (int i = 0; i < projects.length; i++) {
				writer.write(BUILDPATH_PROJECT);
				writer.write("|"); //$NON-NLS-1$
				writer.write(projects[i].getName());
				writer.write('\n'); //$NON-NLS-1$
			}

			Enumeration jars = fClasspathJars.keys();
			while (jars.hasMoreElements()) {
				String jarPath = jars.nextElement().toString();
				JarRecord jarRecord = (JarRecord) fClasspathJars.get(jarPath);
				writer.write("JAR|"); //$NON-NLS-1$
				writer.write(Boolean.toString(jarRecord.has11TLD));
				writer.write('|'); //$NON-NLS-1$
				writer.write(Boolean.toString(jarRecord.isExported));
				writer.write('|'); //$NON-NLS-1$
				writer.write(jarPath);
				writer.write('\n'); //$NON-NLS-1$
				Iterator i = jarRecord.urlRecords.iterator();
				while (i.hasNext()) {
					URLRecord urlRecord = (URLRecord) i.next();
					writer.write("URL|"); //$NON-NLS-1$
					writer.write(String.valueOf(urlRecord.isExported));
					writer.write("|"); //$NON-NLS-1$
					writer.write(urlRecord.getURL().toExternalForm());
					writer.write('\n'); //$NON-NLS-1$
				}
			}
		}
		catch (IOException e) {
		}
		finally {
			try {
				if (writer != null) {
					writer.close();
				}
			}
			catch (Exception e) {
			}
		}

		if (_debugIndexTime)
			Logger.log(Logger.INFO, "time spent saving index for " + fProject.getName() + ": " + (System.currentTimeMillis() - time0)); //$NON-NLS-1$
	}

	void setBuildPathIsDirty() {
		fBuildPathIsDirty = true;
		if (_debugIndexTime)
			Logger.log(Logger.INFO, "marking build path information for " + fProject.getName() + " as dirty"); //$NON-NLS-1$
	}

	void updateClasspathLibrary(String libraryLocation, int deltaKind, boolean isExported) {
		JarRecord libraryRecord = null;
		if (deltaKind == ITaglibIndexDelta.REMOVED || deltaKind == ITaglibIndexDelta.CHANGED) {
			libraryRecord = (JarRecord) fClasspathJars.remove(libraryLocation);
			if (libraryRecord != null) {
				IURLRecord[] urlRecords = (IURLRecord[]) libraryRecord.urlRecords.toArray(new IURLRecord[0]);
				for (int i = 0; i < urlRecords.length; i++) {
					ITaglibRecord record = (ITaglibRecord) fClasspathReferences.remove(urlRecords[i].getURI());
					if (record != null) {
						TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.REMOVED));
					}
				}
			}
		}
		if (deltaKind == ITaglibIndexDelta.ADDED || deltaKind == ITaglibIndexDelta.CHANGED) {
			libraryRecord = createJARRecord(libraryLocation);
			libraryRecord.isExported = isExported;
			fClasspathJars.put(libraryLocation, libraryRecord);

			ZipFile jarfile = null;
			try {
				jarfile = new ZipFile(libraryLocation);
				Enumeration entries = jarfile.entries();
				while (entries.hasMoreElements()) {
					ZipEntry z = (ZipEntry) entries.nextElement();
					if (!z.isDirectory()) {
						if (z.getName().toLowerCase(Locale.US).endsWith(".tld")) { //$NON-NLS-1$
							if (z.getName().equals(JarUtilities.JSP11_TAGLIB)) {
								libraryRecord.has11TLD = true;
							}
							InputStream contents = getCachedInputStream(jarfile, z);
							if (contents != null) {
								TaglibInfo info = extractInfo(libraryLocation, contents);

								if (info != null && info.uri != null && info.uri.length() > 0) {
									URLRecord urlRecord = new URLRecord();
									urlRecord.info = info;
									urlRecord.baseLocation = libraryLocation;
									try {
										urlRecord.isExported = isExported;
										urlRecord.url = new URL("jar:file:" + libraryLocation + "!/" + z.getName()); //$NON-NLS-1$ //$NON-NLS-2$
										libraryRecord.urlRecords.add(urlRecord);
										TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, urlRecord, deltaKind));
										fClasspathReferences.put(urlRecord.getURI(), urlRecord);
										if (_debugIndexCreation)
											Logger.log(Logger.INFO, "created record for " + urlRecord.getURI() + "@" + urlRecord.getURL()); //$NON-NLS-1$ //$NON-NLS-2$
									}
									catch (MalformedURLException e) {
										// don't record this URI
										Logger.logException(e);
									}
								}
								try {
									contents.close();
								}
								catch (IOException e) {
								}
							}
						}
					}
				}
			}
			catch (ZipException zExc) {
				Logger.log(Logger.WARNING, "Taglib Index ZipException: " + libraryLocation + " " + zExc.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
			}
			catch (IOException ioExc) {
				Logger.log(Logger.WARNING, "Taglib Index IOException: " + libraryLocation + " " + ioExc.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
			}
			finally {
				closeJarFile(jarfile);
			}
		}
		if (libraryRecord != null) {
			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, libraryRecord, deltaKind));
		}
	}

	void updateJAR(IResource jar, int deltaKind) {
		if (_debugIndexCreation)
			Logger.log(Logger.INFO, "creating records for JAR " + jar.getFullPath()); //$NON-NLS-1$

		String jarLocationString = null;
		if (jar.getLocation() != null)
			jarLocationString = jar.getLocation().toString();
		else
			jarLocationString = jar.getLocationURI().toString();
		String[] entries = JarUtilities.getEntryNames(jar);
		JarRecord jarRecord = createJARRecord(jar);
		fJARReferences.put(jar.getFullPath().toString(), jarRecord);
		for (int i = 0; i < entries.length; i++) {
			if (entries[i].endsWith(".tld")) { //$NON-NLS-1$
				if (entries[i].equals(JarUtilities.JSP11_TAGLIB)) {
					jarRecord.has11TLD = true;
				}
				InputStream contents = JarUtilities.getInputStream(jar, entries[i]);
				if (contents != null) {
					TaglibInfo info = extractInfo(jarLocationString, contents);

					if (info != null && info.uri != null && info.uri.length() > 0) {
						URLRecord record = new URLRecord();
						record.info = info;
						record.baseLocation = jarLocationString;
						try {
							record.url = new URL("jar:file:" + jarLocationString + "!/" + entries[i]); //$NON-NLS-1$ //$NON-NLS-2$
							jarRecord.urlRecords.add(record);

							int taglibDeltaKind = ITaglibIndexDelta.ADDED;
							Hashtable table = getImplicitReferences(jar.getFullPath().toString());
							if (table != null && table.get(record.getURI()) != null) {
								taglibDeltaKind = ITaglibIndexDelta.CHANGED;
							}

							getImplicitReferences(jar.getFullPath().toString()).put(record.getURI(), record);
							TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, taglibDeltaKind));
							if (_debugIndexCreation)
								Logger.log(Logger.INFO, "created record for " + record.getURI() + "@" + record.getURL()); //$NON-NLS-1$ //$NON-NLS-2$
						}
						catch (MalformedURLException e) {
							// don't record this URI
							Logger.logException(e);
						}
					}
					try {
						contents.close();
					}
					catch (IOException e) {
					}
				}
				else {
					Logger.log(Logger.ERROR_DEBUG, getClass().getName() + "could not read resource " + jar.getFullPath()); //$NON-NLS-1$
				}
			}
		}
		if (jarRecord.has11TLD) {
			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, jarRecord, deltaKind));
		}
	}


	void updateTag(IResource resource, int kind) {
		TagDirRecord record = (TagDirRecord) fTagDirReferences.get(resource.getParent().getFullPath().toString());
		if (record == null) {
			record = createTagdirRecord((IFolder) resource.getParent());
			fTagDirReferences.put(resource.getParent().getFullPath().toString(), record);
			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.ADDED));
		}
		else {
			if (!record.tags.contains(resource.getName())) {
				record.tags.add(resource.getName());
			}
			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.CHANGED));
		}
	}

	void updateTagDir(IResource tagdirResource, int deltaKind) {
		/**
		 * 8.4.1: tag files are loose files under /WEB-INF/tags
		 */
		if ((tagdirResource.getType() & IResource.FOLDER) != 0) {
			if (_debugIndexCreation)
				Logger.log(Logger.INFO, "creating record for directory " + tagdirResource.getFullPath()); //$NON-NLS-1$
			TagDirRecord record = (TagDirRecord) fTagDirReferences.get(tagdirResource.getFullPath().toString());
			if (record == null) {
				record = createTagdirRecord((IFolder) tagdirResource);
				fTagDirReferences.put(tagdirResource.getFullPath().toString(), record);
				TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, deltaKind));
			}
			else {

			}
		}
		/**
		 * 8.4.1: tag files can also be packaged in the /META-INF/tags folder
		 * of a jar in /WEB-INF/lib/ (8.4.2: but must be mentioned in a .tld)
		 */
		else {
			// these tags are merely surfaced when the TLD is modelled
		}
	}

	void updateTLD(IResource tld, int deltaKind) {
		if (_debugIndexCreation)
			Logger.log(Logger.INFO, "creating record for " + tld.getFullPath()); //$NON-NLS-1$
		TLDRecord record = createTLDRecord(tld);
		fTLDReferences.put(tld.getFullPath().toString(), record);
		if (record.getURI() != null) {
			getImplicitReferences(tld.getFullPath().toString()).put(record.getURI(), record);
		}
		TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, deltaKind));
	}

	void updateWebXML(IResource webxml, int deltaKind) {
		if (webxml.getType() != IResource.FILE)
			return;
		InputStream webxmlContents = null;
		Document document = null;
		try {
			webxmlContents = ((IFile) webxml).getContents(true);
			DocumentProvider provider = new DocumentProvider();
			provider.setInputStream(webxmlContents);
			provider.setValidating(false);
			provider.setRootElementName("web-app"); //$NON-NLS-1$
			provider.setBaseReference(webxml.getParent().getFullPath().toString());
			document = provider.getDocument(false);
		}
		catch (CoreException e) {
			Logger.log(Logger.ERROR_DEBUG, "", e); //$NON-NLS-1$
		}
		finally {
			if (webxmlContents != null)
				try {
					webxmlContents.close();
				}
				catch (IOException e1) {
					// ignore
				}
		}
		if (document == null)
			return;
		if (_debugIndexCreation)
			Logger.log(Logger.INFO, "creating records for " + webxml.getFullPath()); //$NON-NLS-1$

		WebXMLRecord webxmlRecord = new WebXMLRecord();
		webxmlRecord.path = webxml.getFullPath();
		fWebXMLReferences.put(webxmlRecord.getWebXML().toString(), webxmlRecord);
		NodeList taglibs = document.getElementsByTagName(JSP12TLDNames.TAGLIB);
		for (int iTaglib = 0; iTaglib < taglibs.getLength(); iTaglib++) {
			String taglibUri = readTextofChild(taglibs.item(iTaglib), "taglib-uri").trim(); //$NON-NLS-1$
			// specified location is relative to root of the webapp
			String taglibLocation = readTextofChild(taglibs.item(iTaglib), "taglib-location").trim(); //$NON-NLS-1$
			IPath path = null;
			if (taglibLocation.startsWith("/")) { //$NON-NLS-1$
				path = new Path(getLocalRoot(webxml.getFullPath().toString()) + taglibLocation);
			}
			else {
				path = new Path(URIHelper.normalize(taglibLocation, webxml.getFullPath().toString(), getLocalRoot(webxml.getFullPath().toString())));
			}
			if (path.segmentCount() > 1) {
				IFile resource = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
				if (resource.isAccessible()) {
					ITaglibRecord record = null;
					/*
					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=125960
					 * 
					 * Also support mappings to .jar files
					 */
					if ("jar".equalsIgnoreCase(resource.getFileExtension())) { //$NON-NLS-1$
						JarRecord jarRecord = createJARRecord(resource);
						String[] entries = JarUtilities.getEntryNames(resource);
						for (int jEntry = 0; jEntry < entries.length; jEntry++) {
							if (entries[jEntry].endsWith(".tld")) { //$NON-NLS-1$
								if (entries[jEntry].equals(JarUtilities.JSP11_TAGLIB)) {
									jarRecord.has11TLD = true;
									InputStream contents = JarUtilities.getInputStream(resource, entries[jEntry]);
									if (contents != null) {
										TaglibInfo info = extractInfo(resource.getFullPath().toString(), contents);
										jarRecord.info = info;
										try {
											contents.close();
										}
										catch (IOException e) {
										}
									}
								}
							}
						}
						record = jarRecord;
						// the stored URI should reflect the web.xml's value
						if (jarRecord.info == null) {
							jarRecord.info = new TaglibInfo();
						}
						jarRecord.info.uri = taglibUri;
						jarRecord.isMappedInWebXML = true;
						if (_debugIndexCreation)
							Logger.log(Logger.INFO, "created web.xml record for " + taglibUri + "@" + jarRecord.getLocation()); //$NON-NLS-1$ //$NON-NLS-2$
					}
					else {
						TLDRecord tldRecord = createTLDRecord(resource);
						record = tldRecord;
						// the stored URI should reflect the web.xml's value
						tldRecord.info.uri = taglibUri;
						if (_debugIndexCreation)
							Logger.log(Logger.INFO, "created web.xml record for " + taglibUri + "@" + tldRecord.getPath()); //$NON-NLS-1$ //$NON-NLS-2$
					}
					if (record != null) {
						webxmlRecord.tldRecords.add(record);
						getImplicitReferences(webxml.getFullPath().toString()).put(taglibUri, record);
						TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, deltaKind));
					}
				}
			}
		}
	}
}
