| package org.eclipse.jst.jsf.designtime.internal.resources; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.jst.jsf.common.internal.componentcore.AbstractVirtualComponentQuery; |
| import org.eclipse.jst.jsf.common.internal.finder.AbstractMatcher.AlwaysMatcher; |
| import org.eclipse.jst.jsf.common.internal.finder.VisitorMatcher; |
| import org.eclipse.jst.jsf.common.internal.finder.acceptor.FileMatchingAcceptor; |
| import org.eclipse.jst.jsf.common.internal.resource.ContentTypeResolver; |
| import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent; |
| import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.ReasonType; |
| import org.eclipse.jst.jsf.common.internal.resource.ResourceManager; |
| import org.eclipse.jst.jsf.common.internal.resource.ResourceTracker; |
| import org.eclipse.jst.jsf.core.internal.JSFCorePlugin; |
| import org.eclipse.jst.jsf.designtime.internal.resources.JSFResourceChangeListener.JSFResourceChangedEvent; |
| import org.eclipse.jst.jsf.designtime.internal.resources.JSFResourceChangeListener.JSFResourceChangedEvent.CHANGE_TYPE; |
| import org.eclipse.jst.jsf.designtime.internal.resources.ResourceIdentifierFactory.InvalidIdentifierException; |
| import org.eclipse.wst.common.componentcore.resources.IVirtualFolder; |
| |
| /** |
| * Resource Manager that tracks JSF resources in a workspace. |
| * |
| * @author cbateman |
| * |
| */ |
| public class WorkspaceResourceManager extends ResourceManager<IResource> |
| { |
| private final AbstractVirtualComponentQuery _vcQuery; |
| private final IProject _project; |
| private final AbstractJSFResourceLocator _locator; |
| private final ContentTypeResolver _contentTypeResolver; |
| private final ResourceIdentifierFactory _factory; |
| |
| /** |
| * @param project |
| * @param vcQuery |
| * @param locator |
| * @param contentTypeResolver |
| */ |
| public WorkspaceResourceManager(final IProject project, |
| final AbstractVirtualComponentQuery vcQuery, |
| final AbstractJSFResourceLocator locator, |
| final ContentTypeResolver contentTypeResolver) |
| { |
| super(project.getWorkspace()); |
| _project = project; |
| _vcQuery = vcQuery; |
| _locator = locator; |
| _contentTypeResolver = contentTypeResolver; |
| _factory = new ResourceIdentifierFactory(); |
| } |
| |
| @Override |
| protected JSFResourceTracker createNewInstance(final IResource resource) |
| { |
| final boolean isJSFResource = !getRootResourceFolder().getParent() |
| .equals(resource); |
| return new JSFResourceTracker(resource, isJSFResource); |
| } |
| |
| @Override |
| public void initResources() |
| { |
| final IFolder folder = getRootResourceFolder(); |
| if (folder != null) |
| { |
| try |
| { |
| track(folder.getParent()); |
| track(folder); |
| } catch (final Exception e1) |
| { |
| JSFCorePlugin |
| .log(e1, |
| "While trying to locate JSF resources in the workspace"); //$NON-NLS-1$ |
| } |
| if (folder.isAccessible()) |
| { |
| trackAllInFolder(folder); |
| } |
| } |
| } |
| |
| private List<IWorkspaceJSFResourceFragment> trackAllInFolder( |
| final IContainer folder) |
| { |
| final VisitorMatcher<IContainer, IResource, String> matcher = new VisitorMatcher<IContainer, IResource, String>( |
| "", "", //$NON-NLS-1$ //$NON-NLS-2$ |
| new FileMatchingAcceptor(), |
| Collections.singletonList(new AlwaysMatcher())); |
| final List<IWorkspaceJSFResourceFragment> newFragments = new ArrayList<IWorkspaceJSFResourceFragment>(); |
| try |
| { |
| final Collection<? extends IResource> foundResources = matcher |
| .find(folder); |
| for (final IResource res : foundResources) |
| { |
| try |
| { |
| newFragments.add(track(res)); |
| } catch (final InvalidIdentifierException e) |
| { |
| JSFCorePlugin.log(IStatus.INFO, |
| "Ignoring invalid JSF resource: "+res); //$NON-NLS-1$ |
| } |
| catch (final ManagedObjectException e) |
| { |
| JSFCorePlugin.log(e, |
| "Problem adding managed object for resource: "+res); //$NON-NLS-1$ |
| } |
| } |
| } catch (final Exception e) |
| { |
| JSFCorePlugin.log(e, |
| "While trying to locate JSF resources in the workspace"); //$NON-NLS-1$ |
| } |
| return newFragments; |
| } |
| |
| private IWorkspaceJSFResourceFragment track(final IResource res) |
| throws ManagedObjectException, InvalidIdentifierException |
| { |
| final IPath fullPath = res.getFullPath().makeRelativeTo( |
| getRootResourceFolder().getFullPath()); |
| // cause the resource to get tracked |
| final JSFResourceTracker tracker = (JSFResourceTracker) getInstance(res); |
| IWorkspaceJSFResourceFragment jsfRes = null; |
| if (res.getType() == IResource.FILE) |
| { |
| try |
| { |
| jsfRes = new WorkspaceJSFResource( |
| _factory.createLibraryResource(fullPath.toString()), res, |
| _contentTypeResolver); |
| } |
| catch (InvalidIdentifierException e) |
| { |
| // ensure that the tracker gets released before we throw the exception. |
| unmanageResource(res); |
| tracker.dispose(); |
| throw e; |
| } |
| } else |
| { |
| jsfRes = new WorkspaceJSFResourceContainer( |
| _factory.createLibraryFragment(fullPath.toString()), |
| (IContainer) res); |
| } |
| tracker.setJsfResource(jsfRes); |
| addLifecycleEventListener(tracker); |
| return jsfRes; |
| } |
| |
| /** |
| * @return the root folder for resources in the workspace. |
| */ |
| public IFolder getRootResourceFolder() |
| { |
| final IVirtualFolder webContentFolder = _vcQuery |
| .getWebContentFolder(_project); |
| if (webContentFolder != null |
| && webContentFolder.getUnderlyingFolder().isAccessible()) |
| { |
| return webContentFolder.getUnderlyingFolder().getFolder( |
| new Path("resources")); //$NON-NLS-1$ |
| } |
| return null; |
| } |
| |
| @Override |
| public List<IResource> getResources() |
| { |
| return new ArrayList(getManagedResources()); |
| } |
| |
| /** |
| * @return the jsf resource currently known. List is a copy but the |
| * contained JSFResource references are not. |
| */ |
| public List<IJSFResourceFragment> getJSFResources() |
| { |
| final List<IJSFResourceFragment> jsfResources = new ArrayList<IJSFResourceFragment>(); |
| final Map<IResource, ManagedResourceObject<ResourceTracker<IResource>>> jsfResourceTrackers = getPerResourceObjects(); |
| for (final Map.Entry<IResource, ManagedResourceObject<ResourceTracker<IResource>>> entry : jsfResourceTrackers |
| .entrySet()) |
| { |
| final JSFResourceTracker jsfResourceTracker = (JSFResourceTracker) entry |
| .getValue().getManagedObject(); |
| if (jsfResourceTracker.isJSFResource()) |
| { |
| jsfResources.add(jsfResourceTracker.getJsfResource()); |
| } |
| } |
| return jsfResources; |
| } |
| |
| private class JSFResourceTracker extends ResourceTracker<IResource> |
| { |
| private IWorkspaceJSFResourceFragment _jsfResource; |
| private final boolean _isJSFResource; |
| |
| /** |
| * @param resource |
| * @param isJSFResource |
| * if false, indicates that the resource being tracked is |
| * related to JSF resources but not an actual JSF resource |
| * (i.e. web root). |
| */ |
| public JSFResourceTracker(final IResource resource, |
| final boolean isJSFResource) |
| { |
| super(resource); |
| _isJSFResource = isJSFResource; |
| } |
| |
| public boolean isJSFResource() |
| { |
| return _isJSFResource; |
| } |
| |
| @Override |
| protected void fireResourceInAccessible( |
| final IResource affectedResource, final ReasonType reasonType) |
| { |
| if (reasonType == ReasonType.RESOURCE_DELETED_FROM_CONTAINER |
| || reasonType == ReasonType.RESOURCE_MOVED_CONTAINER) |
| { |
| try |
| { |
| final List<JSFResourceTracker> trackers = getTrackers(affectedResource); |
| for (final JSFResourceTracker tracker : trackers) |
| { |
| final IWorkspaceJSFResourceFragment jsfResource = tracker |
| .getJsfResource(); |
| removeLifecycleEventListener(tracker); |
| _locator.fireChangeEvent(new JSFResourceChangedEvent( |
| _locator, jsfResource, null, |
| CHANGE_TYPE.REMOVED)); |
| } |
| } catch (final ManagedObjectException e) |
| { |
| JSFCorePlugin.log(e, |
| "Processing an inaccessible resource event"); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| private List<JSFResourceTracker> getTrackers(final IResource res) |
| throws ManagedObjectException |
| { |
| final JSFResourceTracker tracker = (JSFResourceTracker) getInstance(res); |
| final List<JSFResourceTracker> allChildren = new ArrayList<JSFResourceTracker>(); |
| allChildren.add(tracker); |
| if (res instanceof IContainer) |
| { |
| final IPath parentPath = res.getFullPath(); |
| for (final Entry<IResource, ManagedResourceObject<ResourceTracker<IResource>>> trackerEntry : getPerResourceObjects() |
| .entrySet()) |
| { |
| final IPath trackerPath = trackerEntry.getKey() |
| .getFullPath(); |
| if (parentPath.isPrefixOf(trackerPath) |
| && !parentPath.equals(trackerPath)) |
| { |
| allChildren.add((JSFResourceTracker) trackerEntry |
| .getValue().getManagedObject()); |
| } |
| } |
| } |
| return allChildren; |
| } |
| |
| @Override |
| protected void fireResourceChanged(final IResource affectedResource, |
| final ReasonType reasonType) |
| { |
| _locator.fireChangeEvent(new JSFResourceChangedEvent(_locator, |
| _jsfResource, _jsfResource, CHANGE_TYPE.CHANGED)); |
| } |
| |
| @Override |
| protected void fireResourceAdded(final IResource affectedResource, |
| final ReasonType reasonType) |
| { |
| if (reasonType == ReasonType.RESOURCE_ADDED_TO_CONTAINER |
| || reasonType == ReasonType.RESOURCE_MOVED_CONTAINER) |
| { |
| final IContainer parent = affectedResource.getParent(); |
| if (parent != null && parent.isAccessible()) |
| { |
| try |
| { |
| final IWorkspaceJSFResourceFragment newJsfRes = track(affectedResource); |
| fireNewJSFResourceEvent(newJsfRes); |
| if (reasonType == ReasonType.RESOURCE_MOVED_CONTAINER |
| && affectedResource instanceof IContainer) |
| { |
| final List<IWorkspaceJSFResourceFragment> newFragments = trackAllInFolder((IContainer) affectedResource); |
| for (final IWorkspaceJSFResourceFragment frag : newFragments) |
| { |
| fireNewJSFResourceEvent(frag); |
| } |
| } |
| } catch (final ManagedObjectException e) |
| { |
| JSFCorePlugin |
| .log(e, |
| "While adding new resource " + affectedResource); //$NON-NLS-1$ |
| } catch (final InvalidIdentifierException e) |
| { |
| JSFCorePlugin |
| .log(IStatus.INFO, |
| "While adding new resource " + affectedResource); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| |
| private void fireNewJSFResourceEvent( |
| final IWorkspaceJSFResourceFragment newJsfRes) |
| { |
| final JSFResourceChangedEvent event = new JSFResourceChangedEvent( |
| _locator, null, newJsfRes, CHANGE_TYPE.ADDED); |
| _locator.fireChangeEvent(event); |
| } |
| |
| @Override |
| protected boolean isInteresting(final ResourceLifecycleEvent event) |
| { |
| boolean isInteresting = false; |
| final ReasonType reasonType = event.getReasonType(); |
| switch (event.getEventType()) |
| { |
| case RESOURCE_ADDED: |
| { |
| final IResource resource = getResource(); |
| isInteresting = (reasonType == ReasonType.RESOURCE_ADDED_TO_CONTAINER || reasonType == ReasonType.RESOURCE_MOVED_CONTAINER) |
| && event.getAffectedResource().getParent() |
| .equals(resource); |
| // ignore if my resource is web content and this is trying |
| // to add something other than resources folder |
| if (resource.equals(_vcQuery.getWebContentFolder(_project) |
| .getUnderlyingFolder())) |
| { |
| isInteresting &= event.getAffectedResource().equals( |
| getRootResourceFolder()); |
| } |
| } |
| break; |
| case RESOURCE_INACCESSIBLE: |
| { |
| final IResource resource = getResource(); |
| // if the resource made inaccessible was deleted or moved |
| // from its container |
| // and it's parent is me, then it is interesting. |
| isInteresting = (reasonType == ReasonType.RESOURCE_DELETED_FROM_CONTAINER || reasonType == ReasonType.RESOURCE_MOVED_CONTAINER) |
| && event.getAffectedResource().getParent() |
| .equals(resource); |
| // ignore if my resource is web content and this is trying |
| // to add something other than resources folder |
| if (resource.equals(_vcQuery.getWebContentFolder(_project) |
| .getUnderlyingFolder())) |
| { |
| isInteresting &= event.getAffectedResource().equals( |
| getRootResourceFolder()); |
| } |
| // isInteresting &= (_isJSFResource || (resource.getType() == IResource.FOLDER && "resources".equals(resource.getName()))); //$NON-NLS-1$ |
| // or if the resource being delted or moved is the root |
| // folder and that is my resource. |
| // isInteresting |= (reasonType == |
| // ReasonType.RESOURCE_DELETED || reasonType == |
| // ReasonType.RESOURCE_MOVED_CONTAINER) |
| // && (resource.equals(event.getAffectedResource()) && |
| // resource.equals(getRootResourceFolder())); |
| } |
| break; |
| default: |
| isInteresting = super.isInteresting(event); |
| } |
| return isInteresting; |
| } |
| |
| public final IWorkspaceJSFResourceFragment getJsfResource() |
| { |
| return _jsfResource; |
| } |
| |
| public final void setJsfResource( |
| final IWorkspaceJSFResourceFragment jsfResource) |
| { |
| _jsfResource = jsfResource; |
| } |
| } |
| } |