blob: ac9127625d7d8e7a731db8bb1a759264d8552ef6 [file] [log] [blame]
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;
}
}
}