diff options
author | cbateman | 2007-09-18 19:37:33 +0000 |
---|---|---|
committer | cbateman | 2007-09-18 19:37:33 +0000 |
commit | c16783677c96be96fa678625abe591dc89fa1c28 (patch) | |
tree | 0defe9296bf101fba01d5ba24c460d5b7cced863 /jsf | |
parent | 7897421dae0875d06fc0d2f194afdb263ba78ec9 (diff) | |
download | webtools.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
Diffstat (limited to 'jsf')
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; |