[146924] component caching for expensive lookups
diff --git a/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/ComponentCore.java b/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/ComponentCore.java
index 7bf4904..6f5b682 100644
--- a/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/ComponentCore.java
+++ b/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/ComponentCore.java
@@ -23,7 +23,7 @@
import org.eclipse.wst.common.componentcore.internal.resources.VirtualFile;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualReference;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualResource;
-import org.eclipse.wst.common.componentcore.internal.util.ComponentImplRegistryReader;
+import org.eclipse.wst.common.componentcore.internal.util.ComponentImplManager;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualContainer;
import org.eclipse.wst.common.componentcore.resources.IVirtualFile;
@@ -61,7 +61,7 @@
public static IVirtualComponent createComponent(IProject aProject) {
if (!ModuleCoreNature.isFlexibleProject(aProject))
return null;
- return ComponentImplRegistryReader.instance().createComponent(aProject);
+ return ComponentImplManager.instance().createComponent(aProject);
}
/**
@@ -91,7 +91,7 @@
* @see IVirtualContainer#create(int, IProgressMonitor)
*/
public static IVirtualComponent createArchiveComponent(IProject aProject, String aComponentName) {
- return ComponentImplRegistryReader.instance().createArchiveComponent(aProject, aComponentName);
+ return ComponentImplManager.instance().createArchiveComponent(aProject, aComponentName);
}
/**
@@ -109,7 +109,7 @@
* @see IVirtualResource#createLink(IPath, int, IProgressMonitor)
*/
public static IVirtualFolder createFolder(IProject aProject, IPath aRuntimePath) {
- return ComponentImplRegistryReader.instance().createFolder(aProject, aRuntimePath);
+ return ComponentImplManager.instance().createFolder(aProject, aRuntimePath);
}
/**
diff --git a/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/resources/ResourceTimestampMappings.java b/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/resources/ResourceTimestampMappings.java
new file mode 100644
index 0000000..6182b44
--- /dev/null
+++ b/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/resources/ResourceTimestampMappings.java
@@ -0,0 +1,277 @@
+/***************************************************************************************************
+ * 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.wst.common.componentcore.internal.resources;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+
+/**
+ * Maps resources to cached data and remembers when the data was cached based on a timestamp
+ * signature of a given resource.
+ *
+ */
+public class ResourceTimestampMappings {
+
+ private static final IPath COMPONENT_MANIFEST_PATH = new Path(".settings/org.eclipse.wst.common.component");
+ private static final IPath FACET_CONFIG_PATH = new Path(".settings/org.eclipse.wst.common.project.facet.core.xml");
+
+ private static final Object NO_DATA = new Object();
+ private static final Object ERROR = new Object();
+
+ private final Map timestamps = new HashMap();
+ private final Map data = new HashMap();
+
+
+ /**
+ * Record a timestamp signature for the given resource.
+ * <p>
+ * Clients may use {@link #hasChanged(IResource)} to determine if the resource has changed since
+ * it was recorded.
+ * </p>
+ *
+ * @param resource
+ * The resource that was processed.
+ * @return True if the recording was successfull. The recording may fail if the resource does
+ * not exist.
+ *
+ * @see #hasChanged(IResource)
+ */
+ public synchronized boolean mark(IResource resource) {
+ return mark(resource, NO_DATA);
+ }
+
+ /**
+ * Cache the data that was determined when processing the resource. The a timestamp signature
+ * will be recorded for the resource as well.
+ *
+ * <p>
+ * Clients may use {@link #hasChanged(IResource)} to determine if the cached data should be
+ * replaced.
+ * </p>
+ *
+ * @param resource
+ * The resource that was processed.
+ * @param cachedData
+ * The data that was determined when the Resource was processed.
+ *
+ * @return True if the recording was successfull. The recording may fail if the resource does
+ * not exist.
+ *
+ *
+ * @see #hasChanged(IResource)
+ * @see #hasCacheData(IResource)
+ */
+ public synchronized boolean mark(IResource resource, Object cachedData) {
+
+ if (resource.getModificationStamp() != IResource.NULL_STAMP) {
+ if (timestamps.containsKey(resource)) {
+ TimestampSignature signature = (TimestampSignature) timestamps.get(resource);
+ signature.update(resource);
+ } else {
+ timestamps.put(resource, createTimestampSignature(resource));
+ }
+ data.put(resource, cachedData);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Note that an error occurred when processing this resource.
+ *
+ * @param resource
+ * The resource that had some sort of error while processing.
+ * @return True if the error was recorded. The error may not be recorded if the resource does
+ * not exist.
+ * @see #hasCacheError(IResource)
+ */
+ public synchronized boolean markError(IResource resource) {
+
+ if (resource.getModificationStamp() != IResource.NULL_STAMP) {
+ if (timestamps.containsKey(resource)) {
+ TimestampSignature signature = (TimestampSignature) timestamps.get(resource);
+ signature.update(resource);
+ } else {
+ timestamps.put(resource, createTimestampSignature(resource));
+ }
+ data.put(resource, ERROR);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ *
+ * @param resource
+ * The resource that was or is about to be processed.
+ * @return True if the given resource has changed in a noticeable way since it was marked.
+ *
+ * @see #mark(IResource)
+ * @see #mark(IResource, Object)
+ * @see #markError(IResource)
+ */
+ public boolean hasChanged(IResource resource) {
+ TimestampSignature signature = (TimestampSignature) timestamps.get(resource);
+ return signature == null || signature.hasChanged(resource);
+ }
+
+ /**
+ *
+ * @param resource
+ * The resource that was or is about to be processed.
+ * @return True if there is any data cached for the given resource.
+ *
+ * @see #mark(IResource)
+ * @see #mark(IResource, Object)
+ * @see #markError(IResource)
+ */
+ public boolean hasCacheData(IResource resource) {
+ Object datum = data.get(resource);
+ return datum != null && datum != NO_DATA;
+
+ }
+
+
+ /**
+ *
+ * @param resource
+ * The resource that was or is about to be processed.
+ * @return True if there is any data cached for the given resource.
+ *
+ * @see #mark(IResource)
+ * @see #mark(IResource, Object)
+ * @see #markError(IResource)
+ */
+ public boolean hasCacheError(IResource resource) {
+ return data.get(resource) == ERROR;
+ }
+
+ public Object getData(IResource resource) {
+ Object datum = data.get(resource);
+ if (datum != NO_DATA)
+ return datum;
+ return null;
+ }
+
+
+ private TimestampSignature createTimestampSignature(IResource resource) {
+ switch (resource.getType()) {
+ case IResource.PROJECT :
+ return new ProjectTimestamp((IProject) resource);
+ default :
+ return new SimpleResourceTimestamp(resource);
+ }
+ }
+
+ /**
+ * Provides a point in time signature of a Resource to determine whether that resource has
+ * changed in a meaningful way since the time this signature was created or last updated.
+ *
+ */
+ public interface TimestampSignature {
+
+ /**
+ *
+ * @param resource
+ * A resource related to this signature
+ * @return True if the current resource is different from this signature in a meaningful way
+ */
+ boolean hasChanged(IResource resource);
+
+ /**
+ *
+ * @param resource
+ * Update the signature details to the given resource's signature.
+ */
+ void update(IResource resource);
+
+ }
+
+ /**
+ * Provides a signature based on the modificationStamp of a resource.
+ */
+ public class SimpleResourceTimestamp implements TimestampSignature {
+ private long timestamp = 0;
+
+ public SimpleResourceTimestamp(IResource resource) {
+ update(resource);
+ }
+
+ public boolean hasChanged(IResource resource) {
+ return timestamp != resource.getModificationStamp();
+ }
+
+ public void update(IResource resource) {
+ timestamp = resource.getModificationStamp();
+ }
+ }
+
+ /**
+ * Provides a signature for a project based on the modificationStamp of the (1) project, (2) the
+ * component manifest, and (3) the facet configuration
+ */
+ public class ProjectTimestamp implements TimestampSignature {
+
+ private long projectTimestamp = 0;
+ private long componentManifestTimestamp = 0;
+ private long facetConfigTimestamp = 0;
+
+ public ProjectTimestamp(IProject project) {
+ update(project);
+ }
+
+ public boolean hasChanged(IResource resource) {
+ if (resource.getType() == IResource.PROJECT) {
+ IProject project = (IProject) resource;
+ if (projectTimestamp != project.getModificationStamp())
+ return true;
+
+ IFile file = project.getFile(COMPONENT_MANIFEST_PATH);
+ if (!file.exists() || componentManifestTimestamp != file.getModificationStamp())
+ return true;
+
+ file = project.getFile(FACET_CONFIG_PATH);
+ if (!file.exists() || facetConfigTimestamp != file.getModificationStamp())
+ return true;
+
+ return false;
+ }
+ return true;
+
+ }
+
+ public void update(IResource resource) {
+
+ if (resource instanceof IProject) {
+
+ IProject project = (IProject) resource;
+
+ projectTimestamp = project.getModificationStamp();
+
+ IFile file = project.getFile(COMPONENT_MANIFEST_PATH);
+ componentManifestTimestamp = file.getModificationStamp();
+
+ file = project.getFile(FACET_CONFIG_PATH);
+ facetConfigTimestamp = file.getModificationStamp();
+
+ } else {
+ projectTimestamp = componentManifestTimestamp = facetConfigTimestamp = IResource.NULL_STAMP;
+ }
+
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/resources/VirtualResource.java b/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/resources/VirtualResource.java
index 9088003..c5ec204 100644
--- a/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/resources/VirtualResource.java
+++ b/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/resources/VirtualResource.java
@@ -45,6 +45,8 @@
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
private IVirtualComponent component;
private String resourceType;
+
+ private final ResourceTimestampMappings mapping = new ResourceTimestampMappings();
protected VirtualResource(IProject aComponentProject, IPath aRuntimePath) {
@@ -110,55 +112,37 @@
}
public IPath[] getProjectRelativePaths() {
- StructureEdit moduleCore = null;
- try {
- moduleCore = StructureEdit.getStructureEditForRead(getProject());
- if (moduleCore !=null) {
- WorkbenchComponent aComponent = moduleCore.getComponent();
- if (aComponent != null) {
- ResourceTreeRoot root = ResourceTreeRoot.getDeployResourceTreeRoot(aComponent);
- // still need some sort of loop here to search subpieces of the runtime path.
- ComponentResource[] componentResources = null;
-
- if (root != null) {
- IPath[] estimatedPaths = null;
- IPath searchPath = null;
- do {
- searchPath = (searchPath == null) ? getRuntimePath() : searchPath.removeLastSegments(1);
- componentResources = root.findModuleResources(searchPath, ResourceTreeNode.CREATE_NONE);
- estimatedPaths = findBestMatches(componentResources);
- } while (estimatedPaths.length==0 && canSearchContinue(componentResources, searchPath));
- if (estimatedPaths==null || estimatedPaths.length==0)
- return new IPath[] {getRuntimePath()};
- return estimatedPaths;
- }
- }
+
+ WorkbenchComponent aComponent = getReadOnlyComponent();
+ if (aComponent != null) {
+ ResourceTreeRoot root = ResourceTreeRoot.getDeployResourceTreeRoot(aComponent);
+ // still need some sort of loop here to search subpieces of the runtime path.
+ ComponentResource[] componentResources = null;
+
+ if (root != null) {
+ IPath[] estimatedPaths = null;
+ IPath searchPath = null;
+ do {
+ searchPath = (searchPath == null) ? getRuntimePath() : searchPath.removeLastSegments(1);
+ componentResources = root.findModuleResources(searchPath, ResourceTreeNode.CREATE_NONE);
+ estimatedPaths = findBestMatches(componentResources);
+ } while (estimatedPaths.length==0 && canSearchContinue(componentResources, searchPath));
+ if (estimatedPaths==null || estimatedPaths.length==0)
+ return new IPath[] {getRuntimePath()};
+ return estimatedPaths;
}
- } finally {
- if (moduleCore != null) {
- moduleCore.dispose();
- }
- }
+ }
+
return new IPath[] {getRuntimePath()};
}
- public IPath getProjectRelativePath() {
- StructureEdit moduleCore = null;
- if (getRuntimePath().equals(new Path("/"))) {
- try {
- moduleCore = StructureEdit.getStructureEditForRead(getProject());
- if (moduleCore != null) {
- WorkbenchComponent aComponent = moduleCore.getComponent();
- if (aComponent != null) {
- if (((WorkbenchComponentImpl) aComponent).getDefaultSourceRoot() != null)
- return ((WorkbenchComponentImpl) aComponent).getDefaultSourceRoot();
- }
- }
- } finally {
- if (moduleCore != null) {
- moduleCore.dispose();
- }
- }
+ public IPath getProjectRelativePath() {
+ if (getRuntimePath().equals(new Path("/"))) {
+ WorkbenchComponent aComponent = getReadOnlyComponent();
+ if (aComponent != null) {
+ if (((WorkbenchComponentImpl) aComponent).getDefaultSourceRoot() != null)
+ return ((WorkbenchComponentImpl) aComponent).getDefaultSourceRoot();
+ }
}
return getProjectRelativePaths()[0];
}
@@ -257,39 +241,25 @@
}
public void setResourceType(String aResourceType) {
- resourceType = aResourceType;
- StructureEdit moduleCore = null;
- try {
- moduleCore = StructureEdit.getStructureEditForRead(getProject());
- WorkbenchComponent aComponent = moduleCore.getComponent();
- ComponentResource[] resources = aComponent.findResourcesByRuntimePath(getRuntimePath());
- for (int i = 0; i < resources.length; i++) {
- resources[i].setResourceType(aResourceType);
- }
- } finally {
- if (moduleCore != null) {
- moduleCore.dispose();
- }
+ resourceType = aResourceType;
+ WorkbenchComponent aComponent = getReadOnlyComponent();
+ ComponentResource[] resources = aComponent.findResourcesByRuntimePath(getRuntimePath());
+ for (int i = 0; i < resources.length; i++) {
+ resources[i].setResourceType(aResourceType);
}
+
}
// TODO Fetch the resource type from the model.
public String getResourceType() {
- if (null == resourceType) {
- StructureEdit moduleCore = null;
- try {
- moduleCore = StructureEdit.getStructureEditForRead(getProject());
- WorkbenchComponent aComponent = moduleCore.getComponent();
- ComponentResource[] resources = aComponent.findResourcesByRuntimePath(getRuntimePath());
- for (int i = 0; i < resources.length; i++) {
- resourceType = resources[i].getResourceType();
- return resourceType;
- }
- } finally {
- if (moduleCore != null) {
- moduleCore.dispose();
- }
+ if (null == resourceType) {
+ WorkbenchComponent aComponent = getReadOnlyComponent();
+ ComponentResource[] resources = aComponent.findResourcesByRuntimePath(getRuntimePath());
+ for (int i = 0; i < resources.length; i++) {
+ resourceType = resources[i].getResourceType();
+ return resourceType;
}
+
}
resourceType = ""; //$NON-NLS-1$
return resourceType;
@@ -335,4 +305,24 @@
}
}
}
+
+ protected final WorkbenchComponent getReadOnlyComponent() {
+ if(!mapping.hasChanged(getProject()) && mapping.hasCacheData(getProject()))
+ return (WorkbenchComponent) mapping.getData(getProject());
+
+ StructureEdit moduleCore = null;
+ WorkbenchComponent component = null;
+ try {
+ moduleCore = StructureEdit.getStructureEditForRead(getProject());
+ component = moduleCore.getComponent();
+ mapping.mark(getProject(), component);
+ } finally {
+ if (moduleCore != null) {
+ moduleCore.dispose();
+ }
+ }
+ return component;
+
+
+ }
}
diff --git a/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/util/ComponentImplRegistryReader.java b/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/util/ComponentImplManager.java
similarity index 67%
rename from plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/util/ComponentImplRegistryReader.java
rename to plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/util/ComponentImplManager.java
index 4f92654..8e6efc9 100644
--- a/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/util/ComponentImplRegistryReader.java
+++ b/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/util/ComponentImplManager.java
@@ -22,6 +22,7 @@
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jem.util.RegistryReader;
import org.eclipse.wst.common.componentcore.internal.ModulecorePlugin;
+import org.eclipse.wst.common.componentcore.internal.resources.ResourceTimestampMappings;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualArchiveComponent;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualComponent;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualFolder;
@@ -31,29 +32,30 @@
import org.eclipse.wst.common.project.facet.core.IProjectFacet;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
-public class ComponentImplRegistryReader extends RegistryReader {
+public class ComponentImplManager {
private static final String COMPONENT_IMPL_EXTENSION_POINT = "componentimpl"; //$NON-NLS-1$
- private static final String COMPONENT_IMPL = "componentimpl"; //$NON-NLS-1$
- private static final String TYPE = "typeID"; //$NON-NLS-1$
- private static final String CLASS = "class"; //$NON-NLS-1$
+ private static final String TAG_COMPONENT_IMPL = "componentimpl"; //$NON-NLS-1$
+ private static final String ATT_TYPE = "typeID"; //$NON-NLS-1$
+ private static final String ATT_CLASS = "class"; //$NON-NLS-1$
- private static final ComponentImplRegistryReader instance = new ComponentImplRegistryReader();
+ private static final ComponentImplManager instance = new ComponentImplManager();
+ private static final Object LOAD_FAILED = new Object();
- private final Map/* <String, ComponentImplDescriptor> */descriptors = new Hashtable();
+ private final Map/* <String, ComponentImplDescriptor> */ descriptors = new Hashtable();
- private final Map/* <ComponentImplDescriptor, IComponentImplFactory> */instances = new Hashtable();
+ private final Map/* <ComponentImplDescriptor, IComponentImplFactory> */ instances = new Hashtable();
+ private final ResourceTimestampMappings factoryMap = new ResourceTimestampMappings();
/**
* @return Returns the instance.
*/
- public static ComponentImplRegistryReader instance() {
+ public static ComponentImplManager instance() {
/* already initialized and registry read by the time the class initializes */
return instance;
}
- public ComponentImplRegistryReader() {
- super(ModulecorePlugin.PLUGIN_ID, COMPONENT_IMPL_EXTENSION_POINT);
+ public ComponentImplManager() {
SafeRunner.run(new ISafeRunnable() {
public void handleException(Throwable exception) {
@@ -61,34 +63,12 @@
}
public void run() throws Exception {
- readRegistry();
+ new ComponentImplRegistryReader().readRegistry();
}
});
}
- /**
- * @see org.eclipse.wst.common.frameworks.internal.RegistryReader#readElement(org.eclipse.core.runtime.IConfigurationElement)
- */
- public boolean readElement(IConfigurationElement element) {
- if (COMPONENT_IMPL.equals(element.getName())) {
-
- /*
- * Because the only instance of this type is created from a static singleton field, and
- * the registry is initialized in the constructor of this type, other threads cannot
- * compete with readElement() for access to <i>descriptors</i>
- */
- String type = element.getAttribute(TYPE);
- if (type != null)
- descriptors.put(element.getAttribute(TYPE), new ComponentImplDescriptor(element));
- else
- ModulecorePlugin.logError(0, "No type attribute is specified for " + //$NON-NLS-1$
- ModulecorePlugin.PLUGIN_ID + "." + COMPONENT_IMPL_EXTENSION_POINT + //$NON-NLS-1$
- " extension in " + element.getDeclaringExtension().getNamespaceIdentifier(), null); //$NON-NLS-1$
- return true;
- }
- return false;
- }
private IComponentImplFactory getComponentImplFactory(String typeID) {
@@ -110,10 +90,20 @@
}
return factory;
}
-
- // TODO Don't like this because it's going to cycle every project facet for each project
- protected IComponentImplFactory findFactoryForProject(IProject project){
+
+ private IComponentImplFactory findFactoryForProject(IProject project){
try {
+ IComponentImplFactory factory = null;
+
+ if( !factoryMap.hasChanged(project) ) {
+
+ if( factoryMap.hasCacheError(project))
+ return null;
+
+ if( factoryMap.hasCacheData(project))
+ return (IComponentImplFactory) factoryMap.getData(project);
+ }
+
IFacetedProject facetedProject = ProjectFacetsManager.create(project);
if (facetedProject == null) return null;
Iterator keys = descriptors.keySet().iterator();
@@ -122,8 +112,9 @@
try {
IProjectFacet projectFacet = ProjectFacetsManager.getProjectFacet(typeID);
if (projectFacet != null && facetedProject.hasProjectFacet(projectFacet)){
- IComponentImplFactory factory = getComponentImplFactory(typeID);
+ factory = getComponentImplFactory(typeID);
if(null != factory){
+ factoryMap.mark(project, factory);
return factory;
}
}
@@ -131,11 +122,14 @@
continue;
}
}
+
} catch (Exception e) {
- // Just return null
+ ModulecorePlugin.logError(0, "Returning null factory for project: " + project, e); //$NON-NLS-1$
+ factoryMap.markError(project);
}
return null;
}
+
public IVirtualFolder createFolder(IProject aProject, IPath aRuntimePath){
@@ -181,7 +175,7 @@
public ComponentImplDescriptor(IConfigurationElement configElement) {
element = configElement;
- type = element.getAttribute(TYPE);
+ type = element.getAttribute(ATT_TYPE);
}
/**
@@ -202,7 +196,7 @@
}
public void run() throws Exception {
- factory[0] = (IComponentImplFactory) element.createExecutableExtension(CLASS);
+ factory[0] = (IComponentImplFactory) element.createExecutableExtension(ATT_CLASS);
}
});
@@ -219,5 +213,35 @@
}
}
+
+ private class ComponentImplRegistryReader extends RegistryReader {
+
+ public ComponentImplRegistryReader() {
+ super(ModulecorePlugin.PLUGIN_ID, COMPONENT_IMPL_EXTENSION_POINT);
+ }
+
+ /**
+ * @see org.eclipse.wst.common.frameworks.internal.RegistryReader#readElement(org.eclipse.core.runtime.IConfigurationElement)
+ */
+ public boolean readElement(IConfigurationElement element) {
+ if (TAG_COMPONENT_IMPL.equals(element.getName())) {
+
+ /*
+ * Because the only instance of this type is created from a static singleton field, and
+ * the registry is initialized in the constructor of this type, other threads cannot
+ * compete with readElement() for access to <i>descriptors</i>
+ */
+ String type = element.getAttribute(ATT_TYPE);
+ if (type != null)
+ descriptors.put(element.getAttribute(ATT_TYPE), new ComponentImplDescriptor(element));
+ else
+ ModulecorePlugin.logError(0, "No type attribute is specified for " + //$NON-NLS-1$
+ ModulecorePlugin.PLUGIN_ID + "." + COMPONENT_IMPL_EXTENSION_POINT + //$NON-NLS-1$
+ " extension in " + element.getDeclaringExtension().getNamespaceIdentifier(), null); //$NON-NLS-1$
+ return true;
+ }
+ return false;
+ }
+ }
}
diff --git a/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/util/ComponentUtilities.java b/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/util/ComponentUtilities.java
index e20ac2c..ddd0e6e 100644
--- a/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/util/ComponentUtilities.java
+++ b/plugins/org.eclipse.wst.common.modulecore/modulecore-src/org/eclipse/wst/common/componentcore/internal/util/ComponentUtilities.java
@@ -38,6 +38,7 @@
import org.eclipse.wst.common.componentcore.internal.operation.CreateReferenceComponentsOp;
import org.eclipse.wst.common.componentcore.internal.operation.RemoveReferenceComponentOperation;
import org.eclipse.wst.common.componentcore.internal.operation.RemoveReferenceComponentsDataModelProvider;
+import org.eclipse.wst.common.componentcore.internal.resources.ResourceTimestampMappings;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
@@ -48,6 +49,8 @@
import org.eclipse.wst.common.internal.emfworkbench.WorkbenchResourceHelper;
public class ComponentUtilities {
+
+ private static final ResourceTimestampMappings ContextRootMapping = new ResourceTimestampMappings();
/**
* Ensure the container is not read-only.
@@ -257,14 +260,24 @@
*
* @return String value of the context root for runtime of the associated module
*/
- public static String getServerContextRoot(IProject project) {
+ public static String getServerContextRoot(IProject project) {
+
+ if(!ContextRootMapping.hasChanged(project)) {
+ if(ContextRootMapping.hasCacheData(project))
+ return (String) ContextRootMapping.getData(project);
+ else if(ContextRootMapping.hasCacheError(project))
+ return null;
+
+ }
StructureEdit moduleCore = null;
WorkbenchComponent wbComponent = null;
try {
moduleCore = StructureEdit.getStructureEditForRead(project);
- if (moduleCore == null || moduleCore.getComponent() == null)
+ if (moduleCore == null || moduleCore.getComponent() == null) {
+ ContextRootMapping.markError(project);
return null;
+ }
wbComponent = moduleCore.getComponent();
} finally {
if (moduleCore != null) {
@@ -275,9 +288,11 @@
for (int i = 0; i < existingProps.size(); i++) {
Property prop = (Property) existingProps.get(i);
if(prop.getName().equals(IModuleConstants.CONTEXTROOT)){
+ ContextRootMapping.mark(project, prop.getValue());
return prop.getValue();
}
- }
+ }
+ ContextRootMapping.markError(project);
// If all else fails...
return null;
}