| /******************************************************************************* |
| * Copyright (c) 2005, 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.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.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.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.util.StringTokenizer; |
| |
| 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(); |
| } |
| } |
| |
| 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; |
| |
| 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() { |
| LOCK.acquire(); |
| |
| if (!fBuildPathIsDirty) { |
| /* |
| * 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. |
| */ |
| try { |
| IJavaProject jproject = JavaCore.create(fProject); |
| if (jproject != null && jproject.exists()) { |
| IClasspathEntry[] entries = jproject.getResolvedClasspath(true); |
| fBuildPathIsDirty = (fBuildPathEntryCount != entries.length); |
| } |
| } |
| catch (JavaModelException e) { |
| Logger.logException(e); |
| } |
| } |
| if (fBuildPathIsDirty) { |
| indexClasspath(); |
| fBuildPathIsDirty = false; |
| } |
| |
| 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(); |
| |
| float jspVersion = DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(path); |
| |
| LOCK.acquire(); |
| |
| Collection implicitReferences = new HashSet(getImplicitReferences(path.toString()).values()); |
| Collection 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()); |
| |
| 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 Hashtable(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$ |
| } |
| |
| 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$ |
| } |
| |
| /** |
| * @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)); } } |
| */ |
| |
| /** |
| * @param javaProject |
| */ |
| 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)); |
| getImplicitReferences(jar.getFullPath().toString()).remove(records[i].getURI()); |
| } |
| 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) { |
| getImplicitReferences(tld.getFullPath().toString()).remove(record.getURI()); |
| } |
| 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$ |
| getImplicitReferences(webxml.getFullPath().toString()).remove(records[i].getURI()); |
| 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; |
| 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) { |
| record = (ITaglibRecord) getImplicitReferences(basePath).get(reference); |
| } |
| |
| |
| 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; |
| record = (ITaglibRecord) getImplicitReferences(webxmls[i].path.toString()).get(reference); |
| } |
| } |
| |
| 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 "JAR:"+ has11TLD + jar path |
| * URLRecords as "URL:"+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)); |
| } |
| } |
| } |
| } |
| } |
| } |