| /******************************************************************************* |
| * Copyright (c) 2003, 2004 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.j2ee.internal.web.taglib.registry; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.Vector; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IResourceDelta; |
| import org.eclipse.core.resources.IResourceVisitor; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.jem.util.logger.proxy.Logger; |
| import org.eclipse.jst.j2ee.internal.project.IWebNatureConstants; |
| import org.eclipse.jst.j2ee.internal.web.locator.WebProjectTaglibLocator; |
| import org.eclipse.jst.j2ee.internal.web.locator.WebXMLTaglibLocator; |
| import org.eclipse.jst.j2ee.internal.web.taglib.ITaglibInfo; |
| import org.eclipse.jst.j2ee.internal.web.taglib.ITaglibLocator; |
| import org.eclipse.jst.j2ee.internal.web.taglib.ITaglibRegistry; |
| import org.eclipse.jst.j2ee.internal.web.taglib.ITaglibRegistryListener; |
| |
| |
| /** |
| * @version 1.0 |
| * @author |
| */ |
| abstract public class AbstractTaglibRegistry implements ITaglibRegistry { |
| private static final boolean debug = false; |
| |
| protected IProject project; |
| protected Vector listeners; |
| protected Vector taglibs; // of type ITaglibInfo |
| protected ITaglibLocator[] locators; |
| protected boolean needsRefresh = false; |
| |
| public AbstractTaglibRegistry(IProject project) { |
| this.project = project; |
| initialize(); |
| refresh(); |
| } |
| |
| protected void initialize() { |
| this.locators = new ITaglibLocator[]{new WebProjectTaglibLocator(this.project), new WebXMLTaglibLocator(this.project)}; |
| } |
| |
| /* |
| * @see ITaglibRegistry#addTaglibRegistryListener(ITaglibRegistryListener) |
| */ |
| protected void addTaglib(ITaglibInfo taglib) { |
| // Add web.xml entries at the top of the list so that they are |
| // always returned first from the getTaglib(uri) method. |
| if (taglib.isWebXMLEntry()) |
| this.taglibs.add(0, taglib); |
| else |
| this.taglibs.add(taglib); |
| } |
| |
| public void addTaglibRegistryListener(ITaglibRegistryListener listener) { |
| if (this.listeners == null) |
| this.listeners = new Vector(); |
| this.listeners.add(listener); |
| } |
| |
| /* |
| * @see ITaglibRegistry#getTaglib(IPath) |
| */ |
| public ITaglibInfo[] getTaglibs(IPath location) { |
| Vector results = getTaglibsVector(location); |
| return (ITaglibInfo[]) results.toArray(new ITaglibInfo[results.size()]); |
| } |
| |
| protected Vector getTaglibsVector(IPath location) { |
| Vector results = new Vector(); |
| Vector tTaglibs = primGetTaglibs(); |
| |
| boolean isWebXML = isWebXMLFile(location); |
| |
| // Start at the beginning of the taglib list and return the first |
| // one that matches the location passed in. |
| for (Iterator iter = tTaglibs.iterator(); iter.hasNext();) { |
| ITaglibInfo taglib = (ITaglibInfo) iter.next(); |
| if (isWebXML) { |
| if (taglib.isWebXMLEntry()) |
| results.add(taglib); |
| } else if (taglib.getLocation().equals(location)) |
| results.add(taglib); |
| } |
| return results; |
| } |
| |
| protected Vector getExistingTaglibs(IPath location) { |
| Vector results = new Vector(); |
| Vector tTaglibs = this.taglibs; |
| |
| boolean isWebXML = isWebXMLFile(location); |
| |
| // Start at the beginning of the taglib list and return the first |
| // one that matches the location passed in. |
| for (Iterator iter = tTaglibs.iterator(); iter.hasNext();) { |
| ITaglibInfo taglib = (ITaglibInfo) iter.next(); |
| if (isWebXML) { |
| if (taglib.isWebXMLEntry()) |
| results.add(taglib); |
| } else if (taglib.getLocation().equals(location) && !taglib.isWebXMLEntry()) |
| results.add(taglib); |
| } |
| return results; |
| } |
| |
| public IProject getProject() { |
| return this.project; |
| } |
| |
| /* |
| * @see ITaglibRegistry#getRecommendedTaglibs() |
| */ |
| public ITaglibInfo[] getRecommendedTaglibs() { |
| // we pass false because we dont want to show all entries per resource,just one |
| return getValidTaglibs(false); |
| } |
| |
| /* |
| * @see ITaglibRegistry#getVisibleTaglibs() |
| */ |
| public ITaglibInfo[] getVisibleTaglibs() { |
| // we pass true because we want to show all entries that are valid uri's for a resource |
| return getValidTaglibs(true); |
| } |
| |
| |
| protected ITaglibInfo[] getValidTaglibs(boolean showAllEntriesPerResource) { |
| Vector allTaglibs = primGetTaglibs(); |
| Vector results = new Vector(allTaglibs.size()); |
| Set locationSet = new HashSet(); |
| Set uriSet = new HashSet(); |
| |
| // first pass web.xml entries |
| for (Iterator iter = allTaglibs.iterator(); iter.hasNext();) { |
| ITaglibInfo iTaglib = (ITaglibInfo) iter.next(); |
| if (iTaglib.isWebXMLEntry()) { |
| if (!uriSet.contains(iTaglib.getURI())) { |
| // show all web.xml entries whether they are mapped to the same resource |
| // if(showAllEntriesPerResource || |
| // !locationSet.contains(iTaglib.getLocation())){ |
| if (!locationSet.contains(iTaglib.getLocation())) |
| locationSet.add(iTaglib.getLocation()); |
| results.add(iTaglib); |
| // } |
| uriSet.add(iTaglib.getURI()); |
| } |
| } |
| } |
| |
| // second pass uri in tld entries |
| for (Iterator iter = allTaglibs.iterator(); iter.hasNext();) { |
| ITaglibInfo iTaglib = (ITaglibInfo) iter.next(); |
| if (iTaglib.isURIFromTLD() && !iTaglib.isWebXMLEntry()) { |
| if (!uriSet.contains(iTaglib.getURI())) { |
| if (!iTaglib.isInJar()) { |
| // i.e its a tld file in the web application |
| if (showAllEntriesPerResource || !locationSet.contains(iTaglib.getLocation())) { |
| if (!locationSet.contains(iTaglib.getLocation())) |
| locationSet.add(iTaglib.getLocation()); |
| results.add(iTaglib); |
| } |
| } else { // i.e its a tld file in a JAR file in the web application |
| String jarRelativePath = iTaglib.getTLDLocation().toString(); |
| if (jarRelativePath.equalsIgnoreCase(IWebNatureConstants.META_INFO_DIRECTORY + "/taglib.tld")) { //$NON-NLS-1$ |
| if (!iTaglib.isServerContribution() // dont add META-INF/taglib.tld that |
| // comes from a server |
| && (showAllEntriesPerResource || !locationSet.contains(iTaglib.getLocation()))) { |
| if (!locationSet.contains(iTaglib.getLocation())) |
| locationSet.add(iTaglib.getLocation()); |
| results.add(iTaglib); |
| } |
| } else { // if not metainf/taglib.tld |
| // we want to include all the non meta-inf entries in the results |
| results.add(iTaglib); |
| } |
| } |
| uriSet.add(iTaglib.getURI()); |
| } // if !uriSet.contains |
| } // if .isURIFromTLD |
| } |
| |
| // third pass for entries whose uri's are resource paths |
| for (Iterator iter = allTaglibs.iterator(); iter.hasNext();) { |
| ITaglibInfo iTaglib = (ITaglibInfo) iter.next(); |
| if (!iTaglib.isURIFromTLD() && !iTaglib.isWebXMLEntry() && !iTaglib.isDirectoryEntry()) { |
| if (!uriSet.contains(iTaglib.getURI())) { |
| if (showAllEntriesPerResource || !locationSet.contains(iTaglib.getLocation())) { |
| results.add(iTaglib); |
| locationSet.add(iTaglib.getLocation()); |
| } |
| } |
| } |
| } |
| |
| // fourth pass for entries whose uri's are resource paths & directory entries |
| for (Iterator iter = allTaglibs.iterator(); iter.hasNext();) { |
| ITaglibInfo iTaglib = (ITaglibInfo) iter.next(); |
| if (iTaglib.isDirectoryEntry()) { |
| IPath directoryLoc = iTaglib.getLocation(); |
| if (!uriSet.contains(iTaglib.getURI())) { |
| boolean canAdd = true; |
| for (Iterator iterator = locationSet.iterator(); iterator.hasNext();) { |
| IPath locationPath = (IPath) iterator.next(); |
| |
| if (directoryLoc.matchingFirstSegments(locationPath) == locationPath.segmentCount() - 1) { |
| canAdd = false; |
| break; |
| } |
| } |
| if (canAdd) {// don't add directories that have tld's in them |
| results.add(iTaglib); |
| locationSet.add(iTaglib.getLocation()); |
| } |
| } |
| } |
| } |
| |
| |
| return (ITaglibInfo[]) results.toArray(new ITaglibInfo[results.size()]); |
| } |
| |
| protected Vector primGetTaglibs() { |
| if (this.needsRefresh) |
| refresh(); |
| return this.taglibs; |
| } |
| |
| /* |
| * @see ITaglibRegistry#getTaglibs() |
| */ |
| public ITaglibInfo[] getTaglibs() { |
| Vector tTaglibs = primGetTaglibs(); |
| return (ITaglibInfo[]) tTaglibs.toArray(new ITaglibInfo[tTaglibs.size()]); |
| } |
| |
| /* |
| * @see ITaglibRegistry#getTaglib(String) |
| */ |
| public ITaglibInfo getTaglib(String uri) { |
| List tTaglibs = Arrays.asList(getVisibleTaglibs()); |
| //commented out because we dont want to return the taglib for resources that are not |
| // visible |
| // or are not visible because of precedence //primGetTaglibs(); |
| for (Iterator iter = tTaglibs.iterator(); iter.hasNext();) { |
| ITaglibInfo taglib = (ITaglibInfo) iter.next(); |
| if (taglib.getURI().equals(uri)) |
| return taglib; |
| } |
| return null; |
| } |
| |
| protected void fireTaglibAdded(ITaglibInfo addedTaglib) { |
| if (debug) |
| System.out.println("TaglibRegistry: taglib added: " + addedTaglib); //$NON-NLS-1$ |
| |
| if (this.listeners == null) |
| return; |
| for (Iterator iter = this.listeners.iterator(); iter.hasNext();) { |
| ITaglibRegistryListener listener = (ITaglibRegistryListener) iter.next(); |
| listener.taglibAdded(addedTaglib); |
| } |
| } |
| |
| protected void fireTaglibChanged(ITaglibInfo changedTaglib) { |
| if (debug) |
| System.out.println("TaglibRegistry: taglib changed: " + changedTaglib); //$NON-NLS-1$ |
| |
| if (this.listeners == null) |
| return; |
| for (Iterator iter = this.listeners.iterator(); iter.hasNext();) { |
| ITaglibRegistryListener listener = (ITaglibRegistryListener) iter.next(); |
| listener.taglibChanged(changedTaglib); |
| } |
| } |
| |
| protected void fireTaglibRemoved(ITaglibInfo removedTaglib) { |
| if (debug) |
| System.out.println("TaglibRegistry: taglib removed: " + removedTaglib); //$NON-NLS-1$ |
| |
| if (this.listeners == null) |
| return; |
| for (Iterator iter = this.listeners.iterator(); iter.hasNext();) { |
| ITaglibRegistryListener listener = (ITaglibRegistryListener) iter.next(); |
| listener.taglibRemoved(removedTaglib); |
| } |
| } |
| |
| abstract protected boolean isWebXMLFile(IPath filePath); |
| |
| protected boolean isTaglibTLD(IPath tldPath) { |
| return tldPath.lastSegment().equalsIgnoreCase("taglib.tld"); //$NON-NLS-1$ |
| } |
| |
| public void processResourceChanged(IResourceDelta delta) { |
| int kind = delta.getKind(); |
| IResource resource = delta.getResource(); |
| int flags = delta.getFlags(); |
| if (delta.getKind() == IResourceDelta.CHANGED && flags == IResourceDelta.NO_CHANGE) |
| return; |
| |
| // If the websettings file changed, refresh everything in case the context root |
| // was modified or the J2EE level was changed. |
| if (requiresFullUpdate(delta)) { |
| updateAll(); |
| return; |
| } |
| // Make sure resource is not null |
| if (resource == null) |
| return; |
| |
| // Only process resource changes that are under the refreshRoot. |
| IPath resourcePath = resource.getProjectRelativePath(); |
| |
| IResource refreshRoot = getRefreshRoot(); |
| // RATLC00974251 for a java project before build is done, output location does not exist |
| if (refreshRoot == null) |
| return; |
| |
| IPath refreshPath = refreshRoot.getProjectRelativePath(); |
| if (resourcePath.matchingFirstSegments(refreshPath) != refreshPath.segmentCount()) |
| return; |
| |
| if (debug) |
| System.out.println("TaglibRegistry(" + this.project.getName() + ").resourceChanged: " + delta); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| if (kind == IResourceDelta.CHANGED || kind == IResourceDelta.REPLACED) { |
| handleResourceModified(resource); |
| } else if (kind == IResourceDelta.REMOVED) { |
| handleResourceRemoved(resource); |
| } else if (kind == IResourceDelta.ADDED) { |
| handleResourceAdded(resource); |
| } else { |
| if (debug) |
| System.out.println("TaglibRegistry.resourceChanged: UNHANDLED DELTA TYPE"); //$NON-NLS-1$ |
| } |
| } |
| |
| protected void handleResourceAdded(IResource resource) { |
| handleResourceModified(resource); |
| } |
| |
| protected void handleResourceModified(IResource resource) { |
| try { |
| resource.accept(new IResourceVisitor() { |
| public boolean visit(IResource aresource) throws CoreException { |
| if (aresource.getType() != IResource.ROOT && AbstractTaglibRegistry.this.project != aresource.getProject()) |
| return false; |
| |
| if (aresource.getType() == IResource.FILE) { |
| processFile(aresource); |
| return false; |
| } |
| if (shouldProcessDirectory(aresource)) { |
| processDirectory(aresource); |
| } |
| return (canVisitResource(aresource)); |
| |
| } |
| |
| |
| }); |
| } catch (CoreException e) { |
| Logger.getLogger().log(e); |
| } |
| } |
| |
| /** |
| * Return true if the resource and its children should be visited |
| * |
| * @param resource |
| * @return |
| */ |
| protected boolean canVisitResource(IResource resource) { |
| if (resource.getType() != IResource.ROOT && this.project != resource.getProject()) |
| return false; |
| if (resource.getType() != IResource.FILE) |
| return true; |
| return true; |
| } |
| |
| protected void handleResourceRemoved(IResource resource) { |
| IPath location = resource.getProjectRelativePath(); |
| ITaglibInfo[] removedTaglibs = removeTaglibs(location); |
| if (removedTaglibs != null) { |
| for (int i = 0; i < removedTaglibs.length; i++) { |
| ITaglibInfo iTaglibInfo = removedTaglibs[i]; |
| if (debug) |
| System.out.println("TaglibRegistry.handleResourceRemoved taglib removed: " + iTaglibInfo); //$NON-NLS-1$ |
| fireTaglibRemoved(iTaglibInfo); |
| } |
| } |
| } |
| |
| protected IResource getRefreshRoot() { |
| return getProject(); |
| } |
| |
| public void refresh() { |
| this.taglibs = new Vector(); |
| IResource refreshRoot = getRefreshRoot(); |
| |
| // RATLC00974251 for a java project before build is done, output location does not exist |
| if (refreshRoot != null) |
| handleResourceAdded(refreshRoot); |
| |
| this.needsRefresh = false; |
| } |
| |
| protected void updateAll() { |
| try { |
| IResource refreshRoot = getRefreshRoot(); |
| |
| // RATLC00974251 for a java project before build is done, output location does not exist |
| if (refreshRoot == null) |
| return; |
| refreshRoot.accept(new IResourceVisitor() { |
| public boolean visit(IResource resource) throws CoreException { |
| handleResourceModified(resource); |
| return true; |
| } |
| }); |
| } catch (CoreException e) { |
| //Do nothing |
| } |
| } |
| |
| /** |
| * Remove all the taglibs associated with the location. |
| * |
| * @param location |
| * @return ITaglibInfo[] The taglibs that are removed. Null if none are removed. |
| */ |
| protected ITaglibInfo[] removeTaglibs(IPath location) { |
| List results = new ArrayList(); |
| |
| boolean isWebXML = isWebXMLFile(location); |
| for (int i = 0; i < this.taglibs.size(); i++) { |
| ITaglibInfo taglib = (ITaglibInfo) this.taglibs.get(i); |
| if (isWebXML) { |
| if (taglib.isWebXMLEntry()) { |
| removeTaglib(i); |
| results.add(taglib); |
| i--; |
| } |
| } else if (taglib.getLocation().equals(location)) { |
| removeTaglib(i); |
| results.add(taglib); |
| i--; |
| } |
| } |
| return results.isEmpty() ? null : (ITaglibInfo[]) results.toArray(new ITaglibInfo[results.size()]); |
| } |
| |
| abstract protected boolean requiresFullUpdate(IResourceDelta delta); |
| |
| protected void removeTaglib(int i) { |
| this.taglibs.remove(i); |
| } |
| |
| protected ITaglibInfo[] searchForTaglibs(IResource resource) { |
| ArrayList results = new ArrayList(); |
| for (int i = 0; i < this.locators.length; i++) { |
| ITaglibLocator tLocator = this.locators[i]; |
| ITaglibInfo[] tTaglibs = tLocator.search(resource); |
| if (tTaglibs != null) { |
| for (int j = 0; j < tTaglibs.length; j++) { |
| results.add(tTaglibs[j]); |
| } |
| } |
| } |
| return (ITaglibInfo[]) results.toArray(new ITaglibInfo[results.size()]); |
| } |
| |
| /* |
| * @see ITaglibRegistry#removeTaglibRegistryListener(ITaglibRegistryListener) |
| */ |
| public void removeTaglibRegistryListener(ITaglibRegistryListener listener) { |
| if (this.listeners == null) |
| return; |
| this.listeners.remove(listener); |
| } |
| |
| /* |
| * @see Object#toString() |
| */ |
| public String toString() { |
| StringBuffer sb = new StringBuffer(); |
| sb.append("TaglibRegistry: \n"); //$NON-NLS-1$ |
| for (Iterator iter = this.taglibs.iterator(); iter.hasNext();) { |
| ITaglibInfo taglib = (ITaglibInfo) iter.next(); |
| sb.append("\t"); //$NON-NLS-1$ |
| sb.append(taglib); |
| sb.append("\n"); //$NON-NLS-1$ |
| } |
| return sb.toString(); |
| } |
| |
| protected void processDirectory(IResource resource) { |
| // do nothing |
| } |
| |
| protected boolean shouldProcessDirectory(IResource resource) { |
| return true; |
| } |
| |
| /** |
| * @param resource |
| */ |
| protected void processFile(IResource resource) { |
| Vector existingTaglibs = getExistingTaglibs(resource.getProjectRelativePath()); |
| ITaglibInfo[] newTaglibs = searchForTaglibs(resource); |
| |
| for (int i = 0; i < newTaglibs.length; i++) { |
| ITaglibInfo newTaglib = newTaglibs[i]; |
| int existingIndex = existingTaglibs.indexOf(newTaglib); |
| if (existingIndex >= 0) { |
| // If its an exact match, leave it in alone the taglibs registry |
| // but fire a taglibChangedEvent. |
| if (!newTaglib.isWebXMLEntry()) |
| fireTaglibChanged(newTaglib); |
| existingTaglibs.remove(existingIndex); |
| } else { |
| // The taglib did not exist previously in the list, add it and |
| // fire a taglibAdded event. |
| addTaglib(newTaglib); |
| fireTaglibAdded(newTaglib); |
| } |
| } |
| |
| for (Iterator iter = existingTaglibs.iterator(); iter.hasNext();) { |
| ITaglibInfo remainingTaglib = (ITaglibInfo) iter.next(); |
| this.taglibs.remove(remainingTaglib); |
| fireTaglibRemoved(remainingTaglib); |
| } |
| } |
| |
| } |