blob: b40404daf9ede6322b22a60a4353c0c2aff54289 [file] [log] [blame]
/*******************************************************************************
* 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.File;
import java.lang.ref.Reference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.CRC32;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.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.ElementChangedEvent;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
import org.eclipse.jst.jsp.core.internal.Logger;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
import org.osgi.framework.Bundle;
/**
* A non-extendable index manager for taglibs similar to the previous J2EE
* ITaglibRegistry but lacking any ties to project natures. Each record
* returned from the index represents a single tag library descriptor.
*
* Indexing is only persisted between sessions for entries on the Java Build
* Path. New ADD events will be sent to ITaglibIndexListeners during each
* workbench session for both cached and newly found records. REMOVE events
* are not fired on workbench shutdown. The record's contents should be
* examined for any further information.
*
* @since 1.0
*/
public final class TaglibIndex {
class ClasspathChangeListener implements IElementChangedListener {
List projectsIndexed = new ArrayList(1);
public void elementChanged(ElementChangedEvent event) {
if (!isIndexAvailable())
return;
try {
LOCK.acquire();
if (_debugEvents) {
Logger.log(Logger.INFO, "TaglibIndex responding to:" + event); //$NON-NLS-1$
}
projectsIndexed.clear();
elementChanged(event.getDelta(), true);
fireCurrentDelta(event);
}
finally {
LOCK.release();
}
}
private void elementChanged(IJavaElementDelta delta, boolean forceUpdate) {
if (frameworkIsShuttingDown())
return;
IJavaElement element = delta.getElement();
if (element.getElementType() == IJavaElement.JAVA_MODEL) {
IJavaElementDelta[] changed = delta.getAffectedChildren();
for (int i = 0; i < changed.length; i++) {
elementChanged(changed[i], forceUpdate);
}
}
// Handle any changes at the project level
else if (element.getElementType() == IJavaElement.JAVA_PROJECT) {
if ((delta.getFlags() & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0) {
IJavaElement proj = element;
handleClasspathChange((IJavaProject) proj, forceUpdate);
}
else {
IJavaElementDelta[] deltas = delta.getAffectedChildren();
if (deltas.length == 0) {
if (delta.getKind() == IJavaElementDelta.REMOVED || (delta.getFlags() & IJavaElementDelta.F_CLOSED) != 0) {
/*
* If the project is being deleted or closed, just
* remove the description
*/
IJavaProject proj = (IJavaProject) element;
ProjectDescription description = (ProjectDescription) fProjectDescriptions.remove(proj.getProject());
if (description != null) {
if (_debugIndexCreation) {
Logger.log(Logger.INFO, "removing index of " + description.fProject.getName()); //$NON-NLS-1$
}
// removing the index file ensures that we
// don't get stale data if the project is
// reopened
removeIndex(proj.getProject());
}
}
}
/*
* (else) Without the classpath changing, there's nothing
* else to do
*/
else {
for (int i = 0; i < deltas.length; i++) {
elementChanged(deltas[i], false);
}
}
}
}
/*
* Other modification to the classpath (such as within a classpath
* container like "Web App Libraries") go to the description
* itself
*/
else if ((delta.getFlags() & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0 || (delta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) {
IJavaProject affectedProject = element.getJavaProject();
if (affectedProject != null) {
/*
* If the affected project has an index on-disk, it's
* going to be invalid--we need to create/load the
* description so it will be up to date [loading now and
* updating is usually faster than regenerating the entire
* index]. If there is no index on disk, do nothing more.
*/
File indexFile = new File(computeIndexLocation(affectedProject.getProject().getFullPath()));
if (indexFile.exists()) {
ProjectDescription affectedDescription = createDescription(affectedProject.getProject());
if (affectedDescription != null) {
affectedDescription.handleElementChanged(delta);
}
}
projectsIndexed.add(affectedProject.getProject());
}
}
}
private void handleClasspathChange(IJavaProject project, boolean forceUpdate) {
if (frameworkIsShuttingDown())
return;
try {
/* Handle large changes to this project's build path */
IResource resource = project.getCorrespondingResource();
if (resource.getType() == IResource.PROJECT && !projectsIndexed.contains(resource)) {
/*
* Use get instead of create since the downstream
* (upstream?) project wasn't itself modified.
*/
ProjectDescription description = null;
if (forceUpdate) {
description = createDescription((IProject) resource);
}
else {
description = getDescription((IProject) resource);
}
if (description != null && !frameworkIsShuttingDown()) {
projectsIndexed.add(resource);
description.setBuildPathIsDirty();
}
}
}
catch (JavaModelException e) {
Logger.logException(e);
}
}
}
class ResourceChangeListener implements IResourceChangeListener {
public void resourceChanged(IResourceChangeEvent event) {
if (!isIndexAvailable())
return;
try {
LOCK.acquire();
if (_debugEvents) {
Logger.log(Logger.INFO, "TaglibIndex responding to:" + event + "\n" + event.getDelta()); //$NON-NLS-2$ //$NON-NLS-1$
}
switch (event.getType()) {
case IResourceChangeEvent.PRE_CLOSE :
case IResourceChangeEvent.PRE_DELETE : {
try {
// pair deltas with projects
IResourceDelta[] deltas = new IResourceDelta[]{event.getDelta()};
IProject[] projects = null;
if (deltas.length > 0) {
IResource resource = null;
if (deltas[0] != null) {
resource = deltas[0].getResource();
}
else {
resource = event.getResource();
}
if (resource != null) {
if (resource.getType() == IResource.ROOT) {
deltas = deltas[0].getAffectedChildren();
projects = new IProject[deltas.length];
for (int i = 0; i < deltas.length; i++) {
if (deltas[i].getResource().getType() == IResource.PROJECT) {
projects[i] = (IProject) deltas[i].getResource();
}
}
}
else {
projects = new IProject[1];
if (resource.getType() != IResource.PROJECT) {
projects[0] = resource.getProject();
}
else {
projects[0] = (IProject) resource;
}
}
}
for (int i = 0; i < projects.length; i++) {
if (_debugIndexCreation) {
Logger.log(Logger.INFO, "TaglibIndex noticed " + projects[i].getName() + " is about to be deleted/closed"); //$NON-NLS-1$ //$NON-NLS-2$
}
ProjectDescription description = (ProjectDescription) fProjectDescriptions.remove(projects[i]);
if (description != null) {
if (_debugIndexCreation) {
Logger.log(Logger.INFO, "removing index of " + description.fProject.getName()); //$NON-NLS-1$
}
description.clear();
}
}
}
}
catch (Exception e) {
Logger.logException("Exception while processing resource deletion", e); //$NON-NLS-1$
}
}
case IResourceChangeEvent.POST_CHANGE : {
try {
// pair deltas with projects
IResourceDelta[] deltas = new IResourceDelta[]{event.getDelta()};
IProject[] projects = null;
if (deltas.length > 0) {
IResource resource = null;
if (deltas[0] != null) {
resource = deltas[0].getResource();
}
else {
resource = event.getResource();
}
if (resource != null) {
if (resource.getType() == IResource.ROOT) {
deltas = deltas[0].getAffectedChildren();
projects = new IProject[deltas.length];
for (int i = 0; i < deltas.length; i++) {
if (deltas[i].getResource().getType() == IResource.PROJECT) {
projects[i] = (IProject) deltas[i].getResource();
}
}
}
else {
projects = new IProject[1];
if (resource.getType() != IResource.PROJECT) {
projects[0] = resource.getProject();
}
else {
projects[0] = (IProject) resource;
}
}
}
for (int i = 0; i < projects.length; i++) {
if (deltas[i].getKind() == IResourceDelta.CHANGED && (deltas[i].getFlags() == IResourceDelta.ENCODING || deltas[i].getFlags() == IResourceDelta.MARKERS))
continue;
try {
if (deltas[i] != null && deltas[i].getKind() != IResourceDelta.REMOVED && projects[i].isAccessible()) {
ProjectDescription description = getDescription(projects[i]);
if (description != null && !frameworkIsShuttingDown()) {
deltas[i].accept(description.getVisitor());
}
}
if (!projects[i].isAccessible() || (deltas[i] != null && deltas[i].getKind() == IResourceDelta.REMOVED)) {
if (_debugIndexCreation) {
Logger.log(Logger.INFO, "TaglibIndex noticed " + projects[i].getName() + " was removed or is no longer accessible"); //$NON-NLS-1$ //$NON-NLS-2$
}
ProjectDescription description = (ProjectDescription) fProjectDescriptions.remove(projects[i]);
if (description != null) {
if (_debugIndexCreation) {
Logger.log(Logger.INFO, "removing index of " + description.fProject.getName()); //$NON-NLS-1$
}
description.clear();
}
}
}
catch (CoreException e) {
Logger.logException(e);
}
}
}
}
catch (Exception e) {
Logger.logException("Exception while processing resource change", e); //$NON-NLS-1$
}
}
}
fireCurrentDelta(event);
}
finally {
LOCK.release();
}
}
}
static final boolean _debugChangeListener = false;
static boolean _debugEvents = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/events")); //$NON-NLS-1$ //$NON-NLS-2$
static boolean _debugIndexCreation = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/indexcreation")); //$NON-NLS-1$ //$NON-NLS-2$
static final boolean _debugResolution = "true".equals(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/resolve")); //$NON-NLS-1$ //$NON-NLS-2$
static TaglibIndex _instance = new TaglibIndex();
private boolean initialized;
private static final CRC32 checksumCalculator = new CRC32();
private static final String CLEAN = "CLEAN";
private static final String DIRTY = "DIRTY";
static boolean ENABLED = false;
static ILock LOCK = Job.getJobManager().newLock();
/**
* NOT API.
*
* @param listener
* the listener to be added
*/
public static void addTaglibIndexListener(ITaglibIndexListener listener) {
if (getInstance().isInitialized())
getInstance().internalAddTaglibIndexListener(listener);
}
static void fireTaglibDelta(ITaglibIndexDelta delta) {
if (_debugEvents) {
Logger.log(Logger.INFO, "TaglibIndex fired delta:" + delta + " [" + delta.getAffectedChildren().length + "]\n" + ((TaglibIndexDelta) delta).trigger); //$NON-NLS-1$
}
/*
* Flush any shared cache entries, the TaglibControllers should handle
* updating their documents as needed.
*/
ITaglibIndexDelta[] deltas = delta.getAffectedChildren();
for (int i = 0; i < deltas.length; i++) {
ITaglibRecord taglibRecord = deltas[i].getTaglibRecord();
if (taglibRecord != null) {
Object uniqueIdentifier = TLDCMDocumentManager.getUniqueIdentifier(taglibRecord);
if (uniqueIdentifier != null) {
TLDCMDocumentManager.getSharedDocumentCache().remove(uniqueIdentifier);
}
else {
Logger.log(Logger.ERROR, "identifier for " + taglibRecord + " was null");
}
}
}
synchronized (TLDCMDocumentManager.getSharedDocumentCache()) {
Iterator values = TLDCMDocumentManager.getSharedDocumentCache().values().iterator();
while (values.hasNext()) {
Object o = values.next();
if (o instanceof Reference) {
values.remove();
}
}
}
if (_instance.isInitialized()) {
ITaglibIndexListener[] listeners = _instance.fTaglibIndexListeners;
if (listeners != null) {
for (int j = 0; j < listeners.length; j++) {
try {
listeners[j].indexChanged(delta);
}
catch (Exception e) {
Logger.log(Logger.WARNING, e.getMessage());
}
}
}
}
}
/**
* Finds all of the visible ITaglibRecords for the given path in the
* workspace. Taglib mappings from web.xml files are only visible to paths
* within the web.xml's corresponding web content folder.
* This method will almost certainly require a workspace lock to complete.
*
* @param fullPath -
* a path within the workspace
* @return All of the visible ITaglibRecords from the given path.
*/
public static ITaglibRecord[] getAvailableTaglibRecords(IPath fullPath) {
if (!_instance.isInitialized()) {
return new ITaglibRecord[0];
}
ITaglibRecord[] records = null;
if (getInstance().isInitialized()) {
records = getInstance().internalGetAvailableTaglibRecords(fullPath);
}
else {
records = new ITaglibRecord[0];
}
getInstance().fireCurrentDelta("enumerate: " + fullPath); //$NON-NLS-1$
return records;
}
/**
* Returns the IPath considered to be the web-app root for the given path.
* All resolution from the given path beginning with '/' will be relative
* to the computed web-app root.
*
* @deprecated - is not correct in flexible projects
* @param path -
* a path under the web-app root
* @return the IPath considered to be the web-app's root for the given
* path or null if one could not be determined
*/
public static IPath getContextRoot(IPath path) {
try {
LOCK.acquire();
if (getInstance().isInitialized()) {
return getInstance().internalGetContextRoot(path);
}
}
finally {
LOCK.release();
}
return null;
}
public static TaglibIndex getInstance() {
return _instance;
}
/**
* NOT API.
*
* @param listener
* the listener to be removed
*/
public static void removeTaglibIndexListener(ITaglibIndexListener listener) {
if (!getInstance().isInitialized())
return;
if (getInstance().isInitialized())
getInstance().internalRemoveTaglibIndexListener(listener);
}
/**
* Finds a matching ITaglibRecord given the reference. Typically the
* result will have to be cast to a subinterface of ITaglibRecord. This
* method will almost certainly require a workspace lock to complete.
*
* @param basePath
* - the workspace-relative path for IResources, full
* filesystem path otherwise
* @param reference
* - the URI to lookup, for example the uri value from a taglib
* directive
* @param crossProjects
* - whether to search across projects (currently ignored)
*
* @return a visible ITaglibRecord or null if the reference points to no
* known tag library descriptor
*
* @See ITaglibRecord
*/
public static ITaglibRecord resolve(String basePath, String reference, boolean crossProjects) {
ITaglibRecord result = null;
if (getInstance().isInitialized()) {
result = getInstance().internalResolve(basePath, reference, crossProjects);
}
getInstance().fireCurrentDelta("resolve: " + reference); //$NON-NLS-1$
if (_debugResolution) {
if (result == null) {
Logger.log(Logger.INFO, "TaglibIndex could not resolve \"" + reference + "\" from " + basePath); //$NON-NLS-1$ //$NON-NLS-2$
}
else {
switch (result.getRecordType()) {
case (ITaglibRecord.TLD) : {
ITLDRecord record = (ITLDRecord) result;
Logger.log(Logger.INFO, "TaglibIndex resolved " + basePath + ":" + reference + " = " + record.getPath()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
break;
case (ITaglibRecord.JAR) : {
IJarRecord record = (IJarRecord) result;
Logger.log(Logger.INFO, "TaglibIndex resolved " + basePath + ":" + reference + " = " + record.getLocation()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
break;
case (ITaglibRecord.TAGDIR) : {
ITagDirRecord record = (ITagDirRecord) result;
Logger.log(Logger.INFO, "TaglibIndex resolved " + basePath + ":" + reference + " = " + record.getPath()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
break;
case (ITaglibRecord.URL) : {
IURLRecord record = (IURLRecord) result;
Logger.log(Logger.INFO, "TaglibIndex resolved " + basePath + ":" + reference + " = " + record.getURL()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
break;
}
}
}
return result;
}
/**
* Instructs the index to stop listening for resource and classpath
* changes, and to forget all information about the workspace.
*/
public static void shutdown() {
try {
LOCK.acquire();
if (_instance.isInitialized()) {
_instance.stop();
}
}
finally {
LOCK.release();
}
}
/**
* Instructs the index to begin listening for resource and classpath
* changes.
*/
public static void startup() {
boolean shuttingDown = !Platform.isRunning() || Platform.getBundle(OSGI_FRAMEWORK_ID).getState() == Bundle.STOPPING;
if (!shuttingDown) {
try {
LOCK.acquire();
ENABLED = !"false".equalsIgnoreCase(System.getProperty(TaglibIndex.class.getName())); //$NON-NLS-1$
getInstance().initializeInstance();
}
finally {
LOCK.release();
}
}
}
private ClasspathChangeListener fClasspathChangeListener = null;
private TaglibIndexDelta fCurrentTopLevelDelta = null;
Map fProjectDescriptions = null;
private ResourceChangeListener fResourceChangeListener;
private ITaglibIndexListener[] fTaglibIndexListeners = null;
/** symbolic name for OSGI framework */
private final static String OSGI_FRAMEWORK_ID = "org.eclipse.osgi"; //$NON-NLS-1$
private TaglibIndex() {
super();
}
private void initializeInstance() {
if (isInitialized())
return;
try {
LOCK.acquire();
/*
* check again, just incase it was initialized on another thread,
* while we were waiting for the lock
*/
if (!isInitialized()) {
/*
* Only consider a crash if a value exists and is DIRTY (not a
* new workspace)
*/
if (DIRTY.equalsIgnoreCase(getState())) {
Logger.log(Logger.ERROR, "A workspace crash was detected. The previous session did not exit normally. Not using saved taglib indexes."); //$NON-NLS-3$
removeIndexes(false);
}
fProjectDescriptions = new Hashtable();
fResourceChangeListener = new ResourceChangeListener();
fClasspathChangeListener = new ClasspathChangeListener();
if (ENABLED) {
ResourcesPlugin.getWorkspace().addResourceChangeListener(fResourceChangeListener, IResourceChangeEvent.POST_CHANGE);
JavaCore.addElementChangedListener(fClasspathChangeListener);
}
setIntialized(true);
}
}
finally {
LOCK.release();
}
}
/**
* Adds the given delta as a child to an overall delta
*
* @param delta
*/
void addDelta(ITaglibIndexDelta delta) {
ensureDelta(delta.getProject()).addChildDelta(delta);
}
/**
* Based on org.eclipse.jdt.internal.core.search.indexing.IndexManager
*
* @param containerPath
* @return
*/
String computeIndexLocation(IPath containerPath) {
String fileName = computeIndexName(containerPath);
if (_debugIndexCreation)
Logger.log(Logger.INFO, "-> index name for " + containerPath + " is " + fileName); //$NON-NLS-1$ //$NON-NLS-2$
String indexLocation = getTaglibIndexStateLocation().append(fileName).toOSString();
return indexLocation;
}
String computeIndexName(IPath containerPath) {
checksumCalculator.reset();
checksumCalculator.update(containerPath.toOSString().getBytes());
// use ".dat" so we're not confused with JDT indexes
String fileName = Long.toString(checksumCalculator.getValue()) + ".dat"; //$NON-NLS-1$
return fileName;
}
/**
* @param project
* @return
*/
ProjectDescription createDescription(IProject project) {
ProjectDescription description = null;
try {
LOCK.acquire();
description = (ProjectDescription) fProjectDescriptions.get(project);
if (description == null) {
// Once we've started indexing, we're dirty again
if (fProjectDescriptions.isEmpty()) {
setState(DIRTY);
}
description = new ProjectDescription(project, computeIndexLocation(project.getFullPath()));
fProjectDescriptions.put(project, description);
}
}
finally {
LOCK.release();
}
return description;
}
/**
* Ensures that a delta exists for holding index change information
*/
private TaglibIndexDelta ensureDelta(IProject project) {
/*
* The first delta to be added will determine which project the
* top-level delta will contain.
*/
if (fCurrentTopLevelDelta == null) {
fCurrentTopLevelDelta = new TaglibIndexDelta(project, null, ITaglibIndexDelta.CHANGED);
}
return fCurrentTopLevelDelta;
}
void fireCurrentDelta(Object trigger) {
if (fCurrentTopLevelDelta != null) {
fCurrentTopLevelDelta.trigger = trigger;
ITaglibIndexDelta delta = fCurrentTopLevelDelta;
fCurrentTopLevelDelta = null;
fireTaglibDelta(delta);
}
}
/**
* A check to see if the OSGI framework is shutting down.
*
* @return true if the System Bundle is stopped (ie. the framework is
* shutting down)
*/
boolean frameworkIsShuttingDown() {
// in the Framework class there's a note:
// set the state of the System Bundle to STOPPING.
// this must be done first according to section 4.19.2 from the OSGi
// R3 spec.
boolean shuttingDown = !Platform.isRunning() || Platform.getBundle(OSGI_FRAMEWORK_ID).getState() == Bundle.STOPPING;
return shuttingDown;
}
ProjectDescription getDescription(IProject project) {
ProjectDescription description = null;
if (isInitialized()) {
description = (ProjectDescription) fProjectDescriptions.get(project);
}
return description;
}
private String getState() {
String state = JSPCorePlugin.getDefault().getPluginPreferences().getString(TaglibIndex.class.getName());
return state;
}
private IPath getTaglibIndexStateLocation() {
return JSPCorePlugin.getDefault().getStateLocation().append("taglibindex/");
}
private void internalAddTaglibIndexListener(ITaglibIndexListener listener) {
try {
LOCK.acquire();
if (fTaglibIndexListeners == null) {
fTaglibIndexListeners = new ITaglibIndexListener[]{listener};
}
else {
List listeners = new ArrayList(Arrays.asList(fTaglibIndexListeners));
if (!listeners.contains(listener)) {
listeners.add(listener);
}
fTaglibIndexListeners = (ITaglibIndexListener[]) listeners.toArray(new ITaglibIndexListener[0]);
}
}
finally {
LOCK.release();
}
}
private ITaglibRecord[] internalGetAvailableTaglibRecords(IPath path) {
ITaglibRecord[] records = new ITaglibRecord[0];
if (path.segmentCount() > 0) {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0));
if (project.isAccessible()) {
ProjectDescription description = createDescription(project);
List availableRecords = description.getAvailableTaglibRecords(path);
// ICatalog catalog =
// XMLCorePlugin.getDefault().getDefaultXMLCatalog();
// while (catalog != null) {
// ICatalogEntry[] entries = catalog.getCatalogEntries();
// for (int i = 0; i < entries.length; i++) {
// // System.out.println(entries[i].getURI());
// }
// INextCatalog[] nextCatalogs = catalog.getNextCatalogs();
// for (int i = 0; i < nextCatalogs.length; i++) {
// ICatalogEntry[] entries2 =
// nextCatalogs[i].getReferencedCatalog().getCatalogEntries();
// for (int j = 0; j < entries2.length; j++) {
// // System.out.println(entries2[j].getURI());
// }
// }
// }
records = (ITaglibRecord[]) availableRecords.toArray(records);
}
}
return records;
}
private IPath internalGetContextRoot(IPath path) {
IFile baseResource = FileBuffers.getWorkspaceFileAtLocation(path);
if (baseResource != null && baseResource.getProject().isAccessible()) {
IProject project = baseResource.getProject();
ProjectDescription description = getInstance().createDescription(project);
IPath rootPath = description.getLocalRoot(baseResource.getFullPath());
return rootPath;
}
// try to handle out-of-workspace paths
IPath root = path.makeAbsolute();
while (root.segmentCount() > 0 && !root.isRoot())
root = root.removeLastSegments(1);
return root;
}
private void internalRemoveTaglibIndexListener(ITaglibIndexListener listener) {
try {
LOCK.acquire();
if (fTaglibIndexListeners != null) {
List listeners = new ArrayList(Arrays.asList(fTaglibIndexListeners));
listeners.remove(listener);
fTaglibIndexListeners = (ITaglibIndexListener[]) listeners.toArray(new ITaglibIndexListener[0]);
}
}
finally {
LOCK.release();
}
}
private ITaglibRecord internalResolve(String basePath, final String reference, boolean crossProjects) {
IProject project = null;
ITaglibRecord resolved = null;
Path baseIPath = new Path(basePath);
IResource baseResource = FileBuffers.getWorkspaceFileAtLocation(baseIPath);
if (baseResource == null) {
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
// Try the base path as a folder first
if (baseIPath.segmentCount() > 1) {
baseResource = workspaceRoot.getFolder(baseIPath);
}
// If not a folder, then try base path as a file
if (baseResource != null && !baseResource.exists() && baseIPath.segmentCount() > 1) {
baseResource = workspaceRoot.getFile(baseIPath);
}
if (baseResource == null && baseIPath.segmentCount() == 1) {
baseResource = workspaceRoot.getProject(baseIPath.segment(0));
}
}
if (baseResource == 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(baseIPath);
if (files.length > 0)
baseResource = files[0];
}
if (baseResource != null) {
project = ResourcesPlugin.getWorkspace().getRoot().getProject(baseIPath.segment(0));
if (project.isAccessible()) {
ProjectDescription description = createDescription(project);
resolved = description.resolve(basePath, reference);
}
}
return resolved;
}
boolean isIndexAvailable() {
return _instance.isInitialized() && ENABLED;
}
/**
* Removes index file for the given project.
*/
private void removeIndex(IProject project) {
File indexFile = new File(computeIndexLocation(project.getFullPath()));
if (indexFile.exists()) {
indexFile.delete();
}
}
/**
* Removes index files. Used for maintenance and keeping the index folder
* a manageable size.
*
* @param staleOnly -
* if <b>true</b>, removes only the indexes for projects not
* open in the workspace, if <b>false</b>, removes all of the
* indexes
*/
private void removeIndexes(boolean staleOnly) {
String osPath = getTaglibIndexStateLocation().toOSString();
File folder = new File(osPath);
if (!folder.isDirectory()) {
try {
folder.mkdir();
}
catch (SecurityException e) {
}
}
// remove any extraneous index files
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
List indexNames = new ArrayList(projects.length);
if (staleOnly) {
for (int i = 0; i < projects.length; i++) {
if (projects[i].isAccessible()) {
indexNames.add(computeIndexName(projects[i].getFullPath()));
}
}
}
if (folder.isDirectory()) {
File[] files = folder.listFiles();
for (int i = 0; files != null && i < files.length; i++) {
if (!indexNames.contains(files[i].getName()))
files[i].delete();
}
}
}
private void setState(String state) {
if (!state.equals(getState())) {
JSPCorePlugin.getDefault().getPluginPreferences().setValue(TaglibIndex.class.getName(), state);
JSPCorePlugin.getDefault().savePluginPreferences();
}
}
private void stop() {
if (isInitialized()) {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(fResourceChangeListener);
JavaCore.removeElementChangedListener(fClasspathChangeListener);
/*
* Clearing the existing saved states helps prune dead data from
* the index folder.
*/
removeIndexes(true);
Iterator i = fProjectDescriptions.values().iterator();
while (i.hasNext()) {
ProjectDescription description = (ProjectDescription) i.next();
description.saveReferences();
}
fProjectDescriptions.clear();
setState(CLEAN);
fProjectDescriptions = null;
fResourceChangeListener = null;
fClasspathChangeListener = null;
setIntialized(false);
}
}
private boolean isInitialized() {
return initialized;
}
private void setIntialized(boolean intialized) {
this.initialized = intialized;
}
}