Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcbateman2007-09-18 19:37:33 +0000
committercbateman2007-09-18 19:37:33 +0000
commitc16783677c96be96fa678625abe591dc89fa1c28 (patch)
tree0defe9296bf101fba01d5ba24c460d5b7cced863
parent7897421dae0875d06fc0d2f194afdb263ba78ec9 (diff)
downloadwebtools.jsf-c16783677c96be96fa678625abe591dc89fa1c28.tar.gz
webtools.jsf-c16783677c96be96fa678625abe591dc89fa1c28.tar.xz
webtools.jsf-c16783677c96be96fa678625abe591dc89fa1c28.zip
Fix for PMC approved bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=203145
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/ITestTracker.java40
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/IResourceLifecycleListener.java32
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/LifecycleListener.java256
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/ResourceLifecycleEvent.java16
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/jsp/JSPModelProcessor.java284
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/jsp/StartupHandler.java99
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/symbols/JSPTagVariableSymbolSourceProvider.java7
-rw-r--r--jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/symbols/ResourceBundleMapSource.java4
8 files changed, 466 insertions, 272 deletions
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/ITestTracker.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/ITestTracker.java
new file mode 100644
index 000000000..a3369aa0e
--- /dev/null
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/ITestTracker.java
@@ -0,0 +1,40 @@
+package org.eclipse.jst.jsf.common.internal;
+
+/**
+ * An injection interface that allows classes to selectively report test progress.
+ *
+ * @author cbateman
+ *
+ */
+public interface ITestTracker
+{
+ /**
+ * Event types
+ *
+ */
+ public enum Event
+ {
+ /**
+ * Signals that tracking should begin on the eventLabel
+ * The seqId must be repeated on the STOP_TRACKING event
+ * for the same event.
+ */
+ START_TRACKING,
+ /**
+ * Signals that tracking should stop on the named event
+ * for the seqId that was passed first in the START_TRACKING.
+ *
+ */
+ STOP_TRACKING
+ }
+
+ /**
+ * Fires the event of type event, a unique instance tracking seqId
+ * and a label called eventLabel.
+ *
+ * @param event
+ * @param seqId
+ * @param eventLabel
+ */
+ void fireEvent(Event event, long seqId, String eventLabel);
+}
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/IResourceLifecycleListener.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/IResourceLifecycleListener.java
index 16a3d440a..a3ab30fb7 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/IResourceLifecycleListener.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/IResourceLifecycleListener.java
@@ -22,6 +22,36 @@ public interface IResourceLifecycleListener
*/
public static class EventResult
{
+ private static EventResult DEFAULT;
+
+ /**
+ * @return an event result with defaults initialized
+ */
+ public static EventResult getDefaultEventResult()
+ {
+ if (DEFAULT == null)
+ {
+ DEFAULT = new EventResult();
+ }
+ return DEFAULT;
+ }
+
+ private static EventResult DISPOSE_AFTER_EVENT;
+
+ /**
+ * @return an event result with default except dispose after
+ * is set
+ */
+ public static EventResult getDisposeAfterEventResult()
+ {
+ if (DISPOSE_AFTER_EVENT == null)
+ {
+ DISPOSE_AFTER_EVENT = new EventResult();
+ DISPOSE_AFTER_EVENT.setDisposeAfterEvent(true);
+ }
+ return DISPOSE_AFTER_EVENT;
+ }
+
/**
* set to true if after the current event is finished firing, the source
* should be disposed. If self-disposal is not applicable, the flag is ignored
@@ -39,7 +69,7 @@ public interface IResourceLifecycleListener
/**
* @param disposeAfterEvent
*/
- public void setDisposeAfterEvent(boolean disposeAfterEvent) {
+ protected void setDisposeAfterEvent(boolean disposeAfterEvent) {
_disposeAfterEvent = disposeAfterEvent;
}
}
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/LifecycleListener.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/LifecycleListener.java
index 2cb476be4..6e99b5204 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/LifecycleListener.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/LifecycleListener.java
@@ -8,13 +8,12 @@ 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.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jst.jsf.common.JSFCommonPlugin;
+import org.eclipse.jst.jsf.common.internal.ITestTracker;
+import org.eclipse.jst.jsf.common.internal.ITestTracker.Event;
+import org.eclipse.jst.jsf.common.internal.resource.IResourceLifecycleListener.EventResult;
import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.EventType;
import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.ReasonType;
-import org.eclipse.jst.jsf.common.internal.resource.IResourceLifecycleListener.EventResult;
/**
* Listens to resource changes and fires lifecycle events
@@ -22,11 +21,27 @@ import org.eclipse.jst.jsf.common.internal.resource.IResourceLifecycleListener.E
* @author cbateman
*
*/
-public class LifecycleListener implements IResourceChangeListener, IResourceDeltaVisitor
+public class LifecycleListener implements IResourceChangeListener
{
- private final IResource _res;
+ private final static boolean ENABLE_TEST_TRACKING = false;
+ private static long _seqId;
+
+ private final List<IResource> _resources;
private final List<IResourceLifecycleListener> _listeners;
private boolean _isDisposed = false;
+ private ITestTracker _testTracker; // == null; initialized by setter injection
+
+ /**
+ * Initialize an inactive lifecycle listener. A workspace listener will not
+ * be installed by this constructor. The object created using this constructor
+ * will not fire any events until addResource is called at least once to add
+ * a target resource
+ */
+ public LifecycleListener()
+ {
+ _resources = new ArrayList<IResource>();
+ _listeners = new ArrayList<IResourceLifecycleListener>(1);
+ }
/**
* Create a new lifecycle listener for the res
@@ -34,13 +49,72 @@ public class LifecycleListener implements IResourceChangeListener, IResourceDelt
*/
public LifecycleListener(IResource res)
{
- _res = res;
- _listeners = new ArrayList<IResourceLifecycleListener>(1);
+ this();
+ _resources.add(res);
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
+ }
+
+ /**
+ * @param resources
+ */
+ public LifecycleListener(List<IResource> resources)
+ {
+ this();
+ _resources.addAll(resources);
ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
}
/**
+ * @param testTracker
+ */
+ public final void setTestTracker(ITestTracker testTracker)
+ {
+ _testTracker = testTracker;
+ }
+
+ /**
+ * @param res
+ */
+ public void addResource(final IResource res)
+ {
+ synchronized(_resources)
+ {
+ int preSize = _resources.size();
+ if (!_resources.contains(res))
+ {
+ _resources.add(res);
+ }
+
+ // if the size of the array was 0
+ // and is now greater, make sure the listener is added
+ if (preSize == 0
+ && _resources.size() > 0)
+ {
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
+ }
+ }
+ }
+
+ /**
+ * @param res
+ */
+ public void removeResource(final IResource res)
+ {
+ synchronized(_resources)
+ {
+ _resources.remove(res);
+
+ // if there are no longer target resources,
+ // remove the workspace listener
+ if (_resources.size() == 0)
+ {
+ ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+ }
+ }
+ }
+
+ /**
* Release the resource change listener
*/
public void dispose()
@@ -82,7 +156,7 @@ public class LifecycleListener implements IResourceChangeListener, IResourceDelt
{
throw new IllegalStateException();
}
-
+
synchronized(_listeners)
{
if (!_listeners.contains(listener))
@@ -116,16 +190,32 @@ public class LifecycleListener implements IResourceChangeListener, IResourceDelt
public void resourceChanged(IResourceChangeEvent event)
{
+ long seqId = _seqId++;
+
+ if (ENABLE_TEST_TRACKING && _testTracker != null)
+ {
+ _testTracker.fireEvent(Event.START_TRACKING, seqId, "trackMethod_resourceChanged");
+ }
+
assert(!isDisposed());
switch(event.getType())
{
case IResourceChangeEvent.PRE_CLOSE:
{
- IProject proj = (IProject) event.getResource();
- if (proj == _res || proj == _res.getProject())
+ final IProject proj = (IProject) event.getResource();
+
+ synchronized(_resources)
{
- fireLifecycleEvent(new ResourceLifecycleEvent(_res, EventType.RESOURCE_INACCESSIBLE, ReasonType.RESOURCE_PROJECT_CLOSED));
+ final List<IResource> resources = copyResourceList();
+ for (final IResource res : resources)
+ {
+ if (proj == res || proj == res.getProject())
+ {
+ fireLifecycleEvent(
+ new ResourceLifecycleEvent(res, EventType.RESOURCE_INACCESSIBLE, ReasonType.RESOURCE_PROJECT_CLOSED));
+ }
+ }
}
}
break;
@@ -134,90 +224,142 @@ public class LifecycleListener implements IResourceChangeListener, IResourceDelt
{
IProject proj = (IProject) event.getResource();
- // if the resource being tracked is the resource being deleted,
- // then fire a resource delete event
- if (proj == _res)
- {
- fireLifecycleEvent(new ResourceLifecycleEvent(_res, EventType.RESOURCE_INACCESSIBLE, ReasonType.RESOURCE_DELETED));
- }
- // if the resource being tracked is a resource in the project being
- // deleted, then fire a project deleted event
- else if (proj == _res.getProject())
+ synchronized(_resources)
{
- fireLifecycleEvent(new ResourceLifecycleEvent(_res, EventType.RESOURCE_INACCESSIBLE, ReasonType.RESOURCE_PROJECT_DELETED));
+ final List<IResource> resources = copyResourceList();
+ for (final IResource res : resources)
+ {
+ // if the resource being tracked is the resource being deleted,
+ // then fire a resource delete event
+ if (proj == res)
+ {
+ fireLifecycleEvent(new ResourceLifecycleEvent(res, EventType.RESOURCE_INACCESSIBLE, ReasonType.RESOURCE_DELETED));
+ }
+ // if the resource being tracked is a resource in the project being
+ // deleted, then fire a project deleted event
+ else if (proj == res.getProject())
+ {
+ fireLifecycleEvent(
+ new ResourceLifecycleEvent(res, EventType.RESOURCE_INACCESSIBLE, ReasonType.RESOURCE_PROJECT_DELETED));
+ }
+ }
}
}
break;
case IResourceChangeEvent.POST_CHANGE:
{
- // only bother continuing if the resource we are tracking
- // is not a project since post-change events on projects
- // that we care about won't occur
- if (_res.getType() != IResource.PROJECT)
+ synchronized(_resources)
{
- IResourceDelta delta = event.getDelta();
- // only care about post change events to resources
- // that we are tracking
- delta = delta.findMember(_res.getFullPath());
-
- try
+ final List<IResource> resources = copyResourceList();
+ for (final IResource res : resources)
{
- if (delta != null)
+ // only bother continuing if the resource we are tracking
+ // is not a project since post-change events on projects
+ // that we care about won't occur
+ if (res.getType() != IResource.PROJECT)
{
- delta.accept(this);
+ IResourceDelta delta = event.getDelta();
+
+// long seqId2 = _seqId++;
+// if (ENABLE_TEST_TRACKING && _testTracker != null)
+// {
+// _testTracker.fireEvent(Event.START_TRACKING, seqId2, "testFindMember");
+// }
+ // only care about post change events to resources
+ // that we are tracking
+ delta = delta.findMember(res.getFullPath());
+
+ if (delta != null)
+ {
+ visit(delta);
+ }
+
+// if (ENABLE_TEST_TRACKING && _testTracker != null)
+// {
+// _testTracker.fireEvent(Event.STOP_TRACKING, seqId2, "testFindMember");
+// }
}
}
- catch (CoreException ce)
- {
- // can't do anything but log
- JSFCommonPlugin.log(new Throwable(ce));
- }
}
}
break;
+
+ default:
+ // do nothing
// we only handle these three
}
+
+ if (ENABLE_TEST_TRACKING && _testTracker != null)
+ {
+ _testTracker.fireEvent(Event.STOP_TRACKING, seqId, "trackMethod_resourceChanged");
+ }
+ }
+
+ private List<IResource> copyResourceList()
+ {
+ synchronized(_resources)
+ {
+ List<IResource> resList = new ArrayList<IResource>(_resources.size());
+ resList.addAll(_resources);
+ return resList;
+ }
}
private void fireLifecycleEvent(ResourceLifecycleEvent event)
{
+ List<IResourceLifecycleListener> copyListeners
+ = new ArrayList(_listeners.size());
+
+ // copy the listeners to avoid concurrent modification problems
+ // if a listeners removes itself due to an event
synchronized(_listeners)
{
- boolean disposeAfter = false;
+ copyListeners.addAll(_listeners);
+ }
- for (final IResourceLifecycleListener listener : _listeners)
- {
- EventResult result = listener.acceptEvent(event);
- disposeAfter |= result.getDisposeAfterEvent();
- }
+ boolean disposeAfter = false;
- if (disposeAfter)
- {
- dispose();
- }
+ for (final IResourceLifecycleListener listener : copyListeners)
+ {
+ EventResult result = listener.acceptEvent(event);
+ disposeAfter |= result.getDisposeAfterEvent();
+ }
+
+ if (disposeAfter)
+ {
+ dispose();
}
}
- public boolean visit(IResourceDelta delta) throws CoreException
+ private void visit(IResourceDelta delta)
{
assert(!isDisposed());
+ final IResource res = delta.getResource();
+
switch (delta.getKind())
{
- case IResourceDelta.REMOVED:
+ case IResourceDelta.CHANGED:
{
- if (_res.equals(delta.getResource()))
+ // the contents of the file have changed
+ if ((delta.getFlags() & IResourceDelta.CONTENT) != 0)
{
fireLifecycleEvent(
new ResourceLifecycleEvent
- (_res, EventType.RESOURCE_INACCESSIBLE, ReasonType.RESOURCE_DELETED));
- // TODO: return false to stop child visits?
+ (res, EventType.RESOURCE_CHANGED
+ , ReasonType.RESOURCE_CHANGED_CONTENTS));
}
}
+ break;
+ case IResourceDelta.REMOVED:
+ {
+ fireLifecycleEvent(
+ new ResourceLifecycleEvent
+ (res, EventType.RESOURCE_INACCESSIBLE
+ , ReasonType.RESOURCE_DELETED));
+ }
+ break;
}
-
- // keep going on children
- return true;
}
}
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/ResourceLifecycleEvent.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/ResourceLifecycleEvent.java
index b4e6fd137..81f6ff684 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/ResourceLifecycleEvent.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/resource/ResourceLifecycleEvent.java
@@ -18,7 +18,13 @@ public class ResourceLifecycleEvent
* Indicates that the resource is no longer accessible (as testable with
* IResource.isAccessible). The reasonType will indicate why.
*/
- RESOURCE_INACCESSIBLE;
+ RESOURCE_INACCESSIBLE,
+
+ /**
+ * Indicates that the resource being tracked has changed in some
+ * way, use ReasonType to determine specifics
+ */
+ RESOURCE_CHANGED;
}
/**
@@ -43,9 +49,13 @@ public class ResourceLifecycleEvent
/**
* The resource's project was closed. This event is pre-change
*/
- RESOURCE_PROJECT_CLOSED
+ RESOURCE_PROJECT_CLOSED,
+ /**
+ * Occurs when the contents of a non-project resource has changed
+ */
+ RESOURCE_CHANGED_CONTENTS
}
-
+
private final IResource _affectedResource;
private final EventType _eventType;
private final ReasonType _reasonType;
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/jsp/JSPModelProcessor.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/jsp/JSPModelProcessor.java
index 879933185..45d3407c7 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/jsp/JSPModelProcessor.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/jsp/JSPModelProcessor.java
@@ -18,7 +18,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.core.resources.IFile;
@@ -28,10 +27,11 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jst.jsf.common.JSFCommonPlugin;
-import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent;
import org.eclipse.jst.jsf.common.internal.resource.IResourceLifecycleListener;
import org.eclipse.jst.jsf.common.internal.resource.LifecycleListener;
+import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent;
import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.EventType;
+import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.ReasonType;
import org.eclipse.jst.jsf.common.metadata.Trait;
import org.eclipse.jst.jsf.common.metadata.internal.TraitValueHelper;
import org.eclipse.jst.jsf.common.metadata.query.ITaglibDomainMetaDataModelContext;
@@ -50,8 +50,6 @@ import org.eclipse.jst.jsf.designtime.DesignTimeApplicationManager;
import org.eclipse.jst.jsf.designtime.context.DTFacesContext;
import org.eclipse.jst.jsp.core.internal.domdocument.DOMModelForJSP;
import org.eclipse.wst.sse.core.StructuredModelManager;
-import org.eclipse.wst.sse.core.internal.model.ModelLifecycleEvent;
-import org.eclipse.wst.sse.core.internal.provisional.IModelLifecycleListener;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
@@ -70,98 +68,100 @@ import org.w3c.dom.NodeList;
public class JSPModelProcessor
{
private final static Map<IFile, JSPModelProcessor> RESOURCE_MAP =
- new HashMap<IFile, JSPModelProcessor>();
+ new HashMap<IFile, JSPModelProcessor>();
private final static java.util.concurrent.locks.Lock CRITICAL_SECTION =
- new ReentrantLock();
-
+ new ReentrantLock();
+ private static LifecycleListener LIFECYCLE_LISTENER;
+
/**
* @param file The file to get the model processor for
* @return the processor for a particular model, creating it if it does not
* already exist
* @throws CoreException if an attempt to get the model associated with file
* fails due to reasons other than I/O problems
- * @throws IOException if an attempt to get the model associated with file
- * fails due to I/O problems
*/
- public static JSPModelProcessor get(IFile file) throws CoreException, IOException
+ public static JSPModelProcessor get(IFile file) throws CoreException
{
- CRITICAL_SECTION.lock();
- try
- {
- if (!file.isAccessible())
- {
- throw new CoreException(new Status(IStatus.ERROR, JSFCorePlugin.PLUGIN_ID, "File must be accessible"));
- }
-
- JSPModelProcessor processor = RESOURCE_MAP.get(file);
-
- if (processor == null)
- {
- processor = new JSPModelProcessor(file);
- RESOURCE_MAP.put(file, processor);
- processor._refCount.set(1);
- }
- else
- {
- // TODO: should lock refCount separately since this
- // static method does not have exclusive access
- processor._refCount.incrementAndGet();
- }
- return processor;
- }
- finally
- {
- CRITICAL_SECTION.unlock();
- }
+ CRITICAL_SECTION.lock();
+ try
+ {
+ if (!file.isAccessible())
+ {
+ throw new CoreException(new Status(IStatus.ERROR, JSFCorePlugin.PLUGIN_ID, "File must be accessible"));
+ }
+
+ JSPModelProcessor processor = RESOURCE_MAP.get(file);
+
+ if (processor == null)
+ {
+ if (LIFECYCLE_LISTENER == null)
+ {
+ LIFECYCLE_LISTENER = new LifecycleListener(file);
+ }
+ else
+ {
+ LIFECYCLE_LISTENER.addResource(file);
+ }
+
+ processor = new JSPModelProcessor(file,LIFECYCLE_LISTENER);
+ RESOURCE_MAP.put(file, processor);
+ }
+
+ return processor;
+ }
+ finally
+ {
+ CRITICAL_SECTION.unlock();
+ }
}
/**
* Disposes of the JSPModelProcessor associated with model
* @param file the model processor to be disposed
*/
- public static void dispose(IFile file)
+ private static void dispose(IFile file)
{
- CRITICAL_SECTION.lock();
+ CRITICAL_SECTION.lock();
try
{
- JSPModelProcessor processor = RESOURCE_MAP.get(file);
-
- if (processor != null)
- {
- int refCount = processor._refCount.decrementAndGet();
-
- // if either the ref count drops below zero
- // or the file is no longer accessible, the dispose
- if (refCount < 1
- || !file.isAccessible())
- {
- RESOURCE_MAP.remove(file);
-
- if (!processor.isDisposed())
- {
- processor.dispose();
- }
- }
- }
+ JSPModelProcessor processor = RESOURCE_MAP.get(file);
+
+ if (processor != null)
+ {
+ RESOURCE_MAP.remove(file);
+
+ if (!processor.isDisposed())
+ {
+ processor.dispose();
+ LIFECYCLE_LISTENER.removeResource(file);
+ }
+
+ }
+
+ if (RESOURCE_MAP.size() == 0)
+ {
+ // if we no longer have any resources being tracked,
+ // then dispose the lifecycle listener
+ LIFECYCLE_LISTENER.dispose();
+ LIFECYCLE_LISTENER = null;
+ }
}
finally
{
- CRITICAL_SECTION.unlock();
+ CRITICAL_SECTION.unlock();
}
}
private final IFile _file;
- private final DOMModelForJSP _model;
- private final ModelListener _modelListener;
- private final LifecycleListener _resourceListener;
+ private LifecycleListener _lifecycleListener;
+ private IResourceLifecycleListener _resListener;
private boolean _isDisposed;
private Map<Object, ISymbol> _requestMap;
private Map<Object, ISymbol> _sessionMap;
private Map<Object, ISymbol> _applicationMap;
private Map<Object, ISymbol> _noneMap;
private long _lastModificationStamp;
- private AtomicInteger _refCount = new AtomicInteger(0);
-
+
// used to avoid infinite recursion in refresh. Must never be null
private final CountingMutex _lastModificationStampMonitor = new CountingMutex();
@@ -170,32 +170,48 @@ public class JSPModelProcessor
*
* @param model
*/
- private JSPModelProcessor(final IFile file) throws CoreException, IOException
+ private JSPModelProcessor(final IFile file, final LifecycleListener lifecycleListener)
{
- _model = getModelForFile(file);
- _modelListener = new ModelListener();
- _model.addModelLifecycleListener(_modelListener);
+ //_model = getModelForFile(file);
+ //_modelListener = new ModelListener();
+ //_model.addModelLifecycleListener(_modelListener);
_file = file;
- _resourceListener = new LifecycleListener(file);
- _resourceListener.addListener(new IResourceLifecycleListener()
+ _lifecycleListener = lifecycleListener;
+ _resListener = new IResourceLifecycleListener()
{
public EventResult acceptEvent(ResourceLifecycleEvent event)
{
- EventResult result = new EventResult();
+ final EventResult result = EventResult.getDefaultEventResult();
+
+ // not interested
+ if (!_file.equals(event.getAffectedResource()))
+ {
+ return result;
+ }
if (event.getEventType() == EventType.RESOURCE_INACCESSIBLE)
{
dispose(_file);
- result.setDisposeAfterEvent(true);
+ }
+ else if (event.getEventType() == EventType.RESOURCE_CHANGED)
+ {
+ // if the file has changed contents on disk, then
+ // invoke an unforced refresh of the JSP file
+ if (event.getReasonType() == ReasonType.RESOURCE_CHANGED_CONTENTS)
+ {
+ refresh(false);
+ }
}
return result;
}
- });
+ };
+
+ lifecycleListener.addListener(_resListener);
+
// a negative value guarantees that refresh(false) will
// force a refresh on the first run
_lastModificationStamp = -1;
-
}
private DOMModelForJSP getModelForFile(final IFile file)
@@ -229,12 +245,11 @@ public class JSPModelProcessor
{
if (!_isDisposed)
{
- _model.releaseFromRead();
- _model.removeModelLifecycleListener(_modelListener);
-
// ensure the resource listener is disposed
- _resourceListener.dispose();
-
+ _lifecycleListener.removeListener(_resListener);
+ _resListener = null;
+ _lifecycleListener = null;
+
if (_requestMap != null)
{
_requestMap.clear();
@@ -259,7 +274,6 @@ public class JSPModelProcessor
_noneMap = null;
}
- _refCount.set(0);
// mark as disposed
_isDisposed = true;
}
@@ -275,13 +289,15 @@ public class JSPModelProcessor
}
/**
- * Mainly for test and diagnostic purposes.
- *
- * @return the current number of undisposed references to this model processor
+ * If isModelDirty() returns true, then it means that a call
+ * to refresh(false) will trigger a reprocess of the underlying document.
+ *
+ * @return true if the underlying JSP model is considered to be dirty
*/
- public int getRefCount()
+ public boolean isModelDirty()
{
- return _refCount.get();
+ final long currentModificationStamp = _file.getModificationStamp();
+ return _lastModificationStamp != currentModificationStamp;
}
/**
@@ -289,14 +305,13 @@ public class JSPModelProcessor
* @param forceRefresh -- if true, always refreshes, if false,
* then it only refreshes if the file's modification has changed
* since the last refresh
+ * @throws IllegalStateException if isDisposed() == true
*/
public void refresh(final boolean forceRefresh)
{
if (isDisposed())
{
- // TODO: should we throw exception? return false?
- JSFCorePlugin.log(IStatus.WARNING, "Attempt to refresh a disposed processor", new Throwable("Exception is only to get a stack trace, not an error"));
- return;
+ throw new IllegalStateException("Processor is disposed for file: "+_file.toString());
}
synchronized(_lastModificationStampMonitor)
@@ -309,23 +324,27 @@ public class JSPModelProcessor
return;
}
+ DOMModelForJSP model = null;
try
{
_lastModificationStampMonitor.setSignalled(true);
- long currentModificationStamp;
-
- currentModificationStamp = _file.getModificationStamp();
-
+
// only refresh if forced or if the underlying file has changed
// since the last run
if (forceRefresh
- || _lastModificationStamp != currentModificationStamp)
+ || isModelDirty())
{
- refreshInternal();
+ model = getModelForFile(_file);
+ refreshInternal(model);
_lastModificationStamp = _file.getModificationStamp();
}
}
+ catch (CoreException e) {
+ JSFCorePlugin.log(new RuntimeException(e), "Error refreshing internal model");
+ } catch (IOException e) {
+ JSFCorePlugin.log(new RuntimeException(e), "Error refreshing internal model");
+ }
// make sure that we unsignal the monitor before releasing the
// mutex
finally
@@ -335,23 +354,24 @@ public class JSPModelProcessor
}
}
- private void refreshInternal()
+ private void refreshInternal(DOMModelForJSP model)
{
final IStructuredDocumentContext context =
- IStructuredDocumentContextFactory.INSTANCE.getContext(_model.getStructuredDocument(), -1);
+ IStructuredDocumentContextFactory.INSTANCE.getContext(model.getStructuredDocument(), -1);
final ITaglibContextResolver taglibResolver =
IStructuredDocumentContextResolverFactory.INSTANCE.getTaglibContextResolver(context);
- IDOMDocument document = _model.getDocument();
+ IDOMDocument document = model.getDocument();
getApplicationMap().clear();
getRequestMap().clear();
getSessionMap().clear();
//long curTime = System.currentTimeMillis();
- recurseChildNodes(document.getChildNodes(), taglibResolver);
+ recurseChildNodes(model, document.getChildNodes(), taglibResolver);
//long netTime = System.currentTimeMillis() - curTime;
//System.out.println("Net time to recurse document: "+netTime);
}
-
- private void recurseChildNodes(final NodeList nodes,
+
+ private void recurseChildNodes(final DOMModelForJSP model,
+ final NodeList nodes,
final ITaglibContextResolver taglibResolver)
{
for (int i = 0; i < nodes.getLength(); i++)
@@ -359,12 +379,12 @@ public class JSPModelProcessor
final Node child = nodes.item(i);
// process attributes at this node before recursing
- processAttributes(child, taglibResolver);
- recurseChildNodes(child.getChildNodes(), taglibResolver);
+ processAttributes(model, child, taglibResolver);
+ recurseChildNodes(model, child.getChildNodes(), taglibResolver);
}
}
-
- private void processAttributes(final Node node,
+
+ private void processAttributes(final DOMModelForJSP model, final Node node,
final ITaglibContextResolver taglibResolver)
{
if (taglibResolver.hasTag(node))
@@ -377,13 +397,13 @@ public class JSPModelProcessor
{
final Node attribute = node.getAttributes().item(i);
- processSymbolContrib(uri, elementName, attribute);
+ processSymbolContrib(model, uri, elementName, attribute);
processSetsLocale(uri, elementName, attribute);
}
}
}
- private void processSymbolContrib(final String uri, final String elementName, Node attribute)
+ private void processSymbolContrib(final DOMModelForJSP model, final String uri, final String elementName, Node attribute)
{
final SymbolContribAggregator aggregator =
SymbolContribAggregator.
@@ -403,7 +423,7 @@ public class JSPModelProcessor
factory.create(symbolName,
ISymbolConstants.SYMBOL_SCOPE_REQUEST, //TODO:
IStructuredDocumentContextFactory.INSTANCE.
- getContext(_model.getStructuredDocument(),
+ getContext(model.getStructuredDocument(),
attribute),
problems);
@@ -434,7 +454,7 @@ public class JSPModelProcessor
{
DesignTimeApplicationManager dtAppMgr =
DesignTimeApplicationManager.getInstance(_file.getProject());
-
+
DTFacesContext facesContext = dtAppMgr.getFacesContext(_file);
if (facesContext != null)
@@ -457,14 +477,14 @@ public class JSPModelProcessor
{
return Collections.unmodifiableMap(map);
}
-
+
return Collections.EMPTY_MAP;
}
-
+
private void updateMap(ISymbol symbol, String scopeName)
{
final Map<Object, ISymbol> map = getMapForScopeInternal(scopeName);
-
+
if (map != null)
{
map.put(symbol.getName(), symbol);
@@ -540,32 +560,6 @@ public class JSPModelProcessor
}
/**
- * Listens to the JSP model and reacts to changes
- * @author cbateman
- *
- */
- private class ModelListener implements IModelLifecycleListener
- {
- public void processPostModelEvent(ModelLifecycleEvent event)
- {
- // TODO: figure this event structure out seems like it is possibly
- // broken...
- if (((event.getType() & ModelLifecycleEvent.MODEL_DIRTY_STATE) != 0
- && !_model.isDirty()) // if the dirty state changed as now not dirty, then we have a save
- )//|| (event.getType() & ModelLifecycleEvent.MODEL_REINITIALIZED) != 0)
- {
- // refresh if modified on disk
- refresh(false);
- }
- }
-
- public void processPreModelEvent(ModelLifecycleEvent arg0) {
- // do nothing
- }
- }
-
-
- /**
* Aggregates the sets-locale meta-data
*
* @author cbateman
@@ -577,8 +571,8 @@ public class JSPModelProcessor
static LocaleSetAggregator create(IProject project,
final String uri,
final String elementName, final String attributeName)
- {
- final ITaglibDomainMetaDataModelContext mdContext = TaglibDomainMetaDataQueryHelper.createMetaDataModelContext(project, uri);
+ {
+ final ITaglibDomainMetaDataModelContext mdContext = TaglibDomainMetaDataQueryHelper.createMetaDataModelContext(project, uri);
Trait trait = TaglibDomainMetaDataQueryHelper.getTrait(mdContext, elementName+"/"+attributeName, SETS_LOCALE); //$NON-NLS-1$
if (TraitValueHelper.getValueAsBoolean(trait))
@@ -609,12 +603,12 @@ public class JSPModelProcessor
* @return a new instance only if attributeName is a symbol contributor
*/
static SymbolContribAggregator create(final IProject project,
- final String uri,
+ final String uri,
final String elementName,
final String attributeName)
{
- final String entityKey = elementName+"/"+attributeName; //$NON-NLS-1$
- final ITaglibDomainMetaDataModelContext mdContext = TaglibDomainMetaDataQueryHelper.createMetaDataModelContext(project, uri);
+ final String entityKey = elementName+"/"+attributeName; //$NON-NLS-1$
+ final ITaglibDomainMetaDataModelContext mdContext = TaglibDomainMetaDataQueryHelper.createMetaDataModelContext(project, uri);
Trait trait = TaglibDomainMetaDataQueryHelper.getTrait(mdContext, entityKey, CONTRIBUTES_VALUE_BINDING);
boolean contribsValueBindings = TraitValueHelper.getValueAsBoolean(trait);
@@ -629,8 +623,8 @@ public class JSPModelProcessor
if (scope != null && !scope.equals("")) //$NON-NLS-1$
{
- trait = TaglibDomainMetaDataQueryHelper.getTrait(mdContext, entityKey, VALUE_BINDING_SYMBOL_FACTORY);
- symbolFactory = TraitValueHelper.getValueAsString(trait);
+ trait = TaglibDomainMetaDataQueryHelper.getTrait(mdContext, entityKey, VALUE_BINDING_SYMBOL_FACTORY);
+ symbolFactory = TraitValueHelper.getValueAsString(trait);
}
return new SymbolContribAggregator(scope, symbolFactory);
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/jsp/StartupHandler.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/jsp/StartupHandler.java
index 05c442e9e..b3b437742 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/jsp/StartupHandler.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/jsp/StartupHandler.java
@@ -39,8 +39,8 @@ import org.eclipse.ui.PlatformUI;
public class StartupHandler implements IStartup
{
private final JSPEditorListener _partListener = new JSPEditorListener();
-
- public void earlyStartup()
+
+ public void earlyStartup()
{
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable()
{
@@ -67,73 +67,69 @@ public class StartupHandler implements IStartup
}
windows[i].getPartService().addPartListener(_partListener);
}
-
+
// TODO: register with all windows?
PlatformUI.getWorkbench().addWindowListener(new IWindowListener()
{
-
public void windowActivated(IWorkbenchWindow window) {
// do nothing
}
-
+
public void windowDeactivated(IWorkbenchWindow window) {
// do nothing
}
-
+
public void windowClosed(IWorkbenchWindow window) {
window.getPartService().removePartListener(_partListener);
}
-
+
public void windowOpened(IWorkbenchWindow window) {
window.getPartService().addPartListener(_partListener);
}
- });
+ });
}
});
- }
+ }
- private static class JSPEditorListener implements IPartListener2
- {
- private JSPModelProcessor _processor;
-
- public void partActivated(IWorkbenchPartReference partRef) {
- // do nothing
- }
+ private static class JSPEditorListener implements IPartListener2
+ {
+ private JSPModelProcessor _processor;
- public void partBroughtToTop(IWorkbenchPartReference partRef) {
- // do nothing
- }
+ public void partActivated(IWorkbenchPartReference partRef) {
+ // do nothing
+ }
+
+ public void partBroughtToTop(IWorkbenchPartReference partRef) {
+ // do nothing
+ }
public void partClosed(IWorkbenchPartReference partRef) {
- if (partRef instanceof IEditorReference)
- {
- releaseJSPModelListener((IEditorReference) partRef);
- }
- }
+ // do nothing
+ }
- public void partDeactivated(IWorkbenchPartReference partRef) {
- // do nothing
- }
+ public void partDeactivated(IWorkbenchPartReference partRef) {
+ // do nothing
+ }
- public void partOpened(IWorkbenchPartReference partRef) {
+ public void partOpened(IWorkbenchPartReference partRef) {
if (isValidJSPEditor(partRef))
{
setJSPModelListener((IEditorReference)partRef);
}
- }
+ }
- public void partHidden(IWorkbenchPartReference partRef) {
- // do nothing
- }
+ public void partHidden(IWorkbenchPartReference partRef) {
+ // do nothing
+ }
- public void partVisible(IWorkbenchPartReference partRef) {
- // do nothing
- }
+ public void partVisible(IWorkbenchPartReference partRef) {
+ // do nothing
+ }
+
+ public void partInputChanged(IWorkbenchPartReference partRef) {
+ // do nothing
+ }
- public void partInputChanged(IWorkbenchPartReference partRef) {
- // do nothing
- }
-
private boolean isJSPEditor(IEditorReference editorRef)
{
IFile file = getIFile(editorRef);
@@ -145,7 +141,7 @@ public class StartupHandler implements IStartup
return false;
}
-
+
/**
* @param editorRef
* @return true if the editor is editing the JSP content type and
@@ -159,18 +155,17 @@ public class StartupHandler implements IStartup
JSFAppConfigUtils.isValidJSFProject(file.getProject()) &&
isJSPEditor(editorRef);
}
-
-
+
boolean isValidJSPEditor(IWorkbenchPartReference partRef)
{
if (partRef instanceof IEditorReference)
{
return isValidJSPEditor((IEditorReference)partRef);
}
-
+
return false;
}
-
+
void setJSPModelListener(IEditorReference editorRef)
{
IFile file = getIFile(editorRef);
@@ -189,17 +184,7 @@ public class StartupHandler implements IStartup
}
}
}
-
- void releaseJSPModelListener(IEditorReference editorRef)
- {
- IFile file = getIFile(editorRef);
-
- if (file != null)
- {
- JSPModelProcessor.dispose(file);
- }
- }
-
+
IFile getIFile(IEditorReference editorRef)
{
try
@@ -216,8 +201,8 @@ public class StartupHandler implements IStartup
{
JSFCorePlugin.getDefault().getLog().log(new Status(IStatus.ERROR, JSFCorePlugin.PLUGIN_ID, 0, "Error acquiring editor input",excp)); //$NON-NLS-1$
}
-
+
return null;
}
- }
+ }
}
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/symbols/JSPTagVariableSymbolSourceProvider.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/symbols/JSPTagVariableSymbolSourceProvider.java
index 994dc7daf..ca109f718 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/symbols/JSPTagVariableSymbolSourceProvider.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/symbols/JSPTagVariableSymbolSourceProvider.java
@@ -86,13 +86,6 @@ public class JSPTagVariableSymbolSourceProvider extends
JSFCorePlugin.getDefault().getLog().log(new Status(IStatus.ERROR, JSFCorePlugin.PLUGIN_ID, 0, "Error acquiring model processor",e)); //$NON-NLS-1$
// fall-through to empty symbol array
}
- finally
- {
- if (modelProcessor != null)
- {
- JSPModelProcessor.dispose(fileContext);
- }
- }
}
return ISymbol.EMPTY_SYMBOL_ARRAY;
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/symbols/ResourceBundleMapSource.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/symbols/ResourceBundleMapSource.java
index 2e454c0f9..4e7d66c4b 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/symbols/ResourceBundleMapSource.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/internal/symbols/ResourceBundleMapSource.java
@@ -77,7 +77,7 @@ class ResourceBundleMapSource extends AbstractMap
{
public EventResult acceptEvent(ResourceLifecycleEvent event)
{
- EventResult result = new EventResult();
+ EventResult result = EventResult.getDefaultEventResult();
if (event.getEventType() == EventType.RESOURCE_INACCESSIBLE)
{
@@ -92,7 +92,7 @@ class ResourceBundleMapSource extends AbstractMap
{
JSFCorePlugin.log("Error clearing bundle file cache", ce); //$NON-NLS-1$
}
- result.setDisposeAfterEvent(true);
+ result = EventResult.getDisposeAfterEventResult();
}
return result;

Back to the top