blob: f8b63b2f361285620100cab0de1bf6286132c7ee [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jee.model.internal;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl;
import org.eclipse.jem.util.emf.workbench.FlexibleProjectResourceSet;
import org.eclipse.jem.util.emf.workbench.ProjectResourceSet;
import org.eclipse.jem.util.emf.workbench.WorkbenchResourceHelperBase;
import org.eclipse.jst.j2ee.componentcore.EnterpriseArtifactEdit;
import org.eclipse.jst.j2ee.model.IModelProvider;
import org.eclipse.jst.j2ee.model.IModelProviderEvent;
import org.eclipse.jst.j2ee.model.IModelProviderListener;
import org.eclipse.jst.j2ee.model.ModelProviderEvent;
import org.eclipse.jst.javaee.core.internal.util.JavaeeResourceImpl;
import org.eclipse.jst.jee.JEEPlugin;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.internal.impl.ModuleURIUtil;
import org.eclipse.wst.common.componentcore.internal.impl.PlatformURLModuleConnection;
import org.eclipse.wst.common.componentcore.internal.impl.WTPResourceFactoryRegistry;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
import org.eclipse.wst.common.internal.emfworkbench.WorkbenchResourceHelper;
import org.eclipse.wst.common.internal.emfworkbench.validateedit.ResourceStateInputProvider;
import org.eclipse.wst.common.internal.emfworkbench.validateedit.ResourceStateValidator;
import org.eclipse.wst.common.internal.emfworkbench.validateedit.ResourceStateValidatorImpl;
import org.eclipse.wst.common.internal.emfworkbench.validateedit.ResourceStateValidatorPresenter;
public class JEE5ModelProvider implements IModelProvider, ResourceStateInputProvider, ResourceStateValidator, IModelProviderListener{
protected XMLResourceImpl writableResource;
protected IProject proj;
protected IPath defaultResourcePath;
protected ResourceStateValidator stateValidator;
protected ResourceAdapter resourceAdapter = new ResourceAdapter();
protected final ListenerList listeners = new ListenerList();
//private static boolean resourceChangeListenerEnabled = false;
private List modelResources = new ArrayList();
protected class ResourceAdapter extends AdapterImpl {
public void notifyChanged(Notification notification) {
if ( notification.getEventType() == Notification.SET && notification.getFeatureID(null) == Resource.RESOURCE__IS_LOADED) {
resourceIsLoadedChanged((Resource) notification.getNotifier(), notification.getOldBooleanValue(), notification.getNewBooleanValue());
}
}
}
public JEE5ModelProvider() {
super();
}
protected ProjectResourceSet getResourceSet(IProject proj2) {
return (ProjectResourceSet)WorkbenchResourceHelperBase.getResourceSet(proj);
}
public XMLResourceImpl getWritableResource() {
return writableResource;
}
public void setWritableResource(XMLResourceImpl writableResource) {
this.writableResource = writableResource;
}
protected void resourceIsLoadedChanged(Resource aResource, boolean oldValue, boolean newValue) {
if (hasListeners()) {
int eventCode = newValue ? ModelProviderEvent.LOADED_RESOURCE : ModelProviderEvent.UNLOADED_RESOURCE;
ModelProviderEvent evt = new ModelProviderEvent(eventCode, this, proj);
evt.addResource(aResource);
notifyListeners(evt);
}
}
private void addManagedResource(XMLResourceImpl res) {
modelResources.add(res);
if (!res.eAdapters().contains(resourceAdapter))
res.eAdapters().add(resourceAdapter);
}
/**
* Returns true if there are any listeners
*/
public boolean hasListeners() {
return !listeners.isEmpty();
}
private URI getModuleURI(URI uri) {
URI moduleuri = ModuleURIUtil.fullyQualifyURI(proj,getContentTypeDescriber());
IPath requestPath = new Path(moduleuri.path()).append(new Path(uri.path()));
URI resourceURI = URI.createURI(PlatformURLModuleConnection.MODULE_PROTOCOL + requestPath.toString());
return resourceURI;
}
protected XMLResourceImpl getModelResource(IPath modelPath) {
if (writableResource != null) {
addManagedResource(writableResource);
return writableResource;
}
if ((modelPath == null) || modelPath.equals(IModelProvider.FORCESAVE))
modelPath = getDefaultResourcePath();
ProjectResourceSet resSet = getResourceSet(proj);
IVirtualFolder container = ComponentCore.createComponent(proj).getRootFolder();
String modelPathURI = modelPath.toString();
URI uri = URI.createURI(modelPathURI);
IPath projURIPath = new Path("");//$NON-NLS-1$
projURIPath = projURIPath.append(container.getProjectRelativePath());
projURIPath = projURIPath.addTrailingSeparator();
projURIPath = projURIPath.append(modelPath);
URI projURI = URI.createURI(projURIPath.toString());
XMLResourceImpl res = null;
try {
if (proj.getFile(projURI.toString()).exists())
{
res = (XMLResourceImpl) resSet.getResource(getModuleURI(uri),true);
addManagedResource(res);
// if (!resourceChangeListenerEnabled)
// {
// resourceChangeListenerEnabled = true;
// ResourcesPlugin.getWorkspace().addResourceChangeListener(new ResourceChangeListener(), IResourceChangeEvent.POST_CHANGE);
// }
} else {//First find in resource set, then create if not found new Empty Resource.
XMLResourceImpl newRes = createModelResource(modelPath, resSet, projURI);
addManagedResource(newRes);
return newRes;
}
} catch (WrappedException ex) {
if (ex.getCause() instanceof FileNotFoundException)
return null;
else throw ex;
}
return res;
}
protected XMLResourceImpl createModelResource(IPath modelPath, ProjectResourceSet resourceSet, URI uri) {
// First try to find existing cached resource.
XMLResourceImpl res = (XMLResourceImpl)resourceSet.getResource(getModuleURI(uri), false);
if (res == null || !res.isLoaded()) {
// Create temp resource if no file exists
res= (XMLResourceImpl)((FlexibleProjectResourceSet)resourceSet).createResource(getModuleURI(uri),WTPResourceFactoryRegistry.INSTANCE.getFactory(uri, getContentType(getContentTypeDescriber())));
populateRoot(res, resourceSet.getProject().getName());
}
return res;
}
public void populateRoot(XMLResourceImpl res, String string) {
// TODO Auto-generated method stub
}
private IContentDescription getContentType(String contentTypeDescriber) {
if (contentTypeDescriber != null)
return Platform.getContentTypeManager().getContentType(contentTypeDescriber).getDefaultDescription();
else
return null;
}
public IPath getDefaultResourcePath() {
return defaultResourcePath;
}
public void setDefaultResourcePath(IPath defaultResourcePath) {
this.defaultResourcePath = defaultResourcePath;
}
public Object getModelObject() {
return getModelObject(getDefaultResourcePath());
}
public Object getModelObject(IPath modelPath) {
// TODO Auto-generated method stub
return null;
}
/**
* Used to optionally define an associated content type for XML file creation
* @return
*/
protected String getContentTypeDescriber() {
return null;
}
public IStatus validateEdit(IPath modelPath, Object context) {
if (modelPath == null)
modelPath = getDefaultResourcePath();
IWorkspace work = ResourcesPlugin.getWorkspace();
IFile file = WorkbenchResourceHelper.getFile(getModelResource(modelPath));
if (file != null && file.exists()) {
IFile[] files = { file };
if (context == null)
context = IWorkspace.VALIDATE_PROMPT;
return work.validateEdit(files, context);
} else
return Status.OK_STATUS;
}
public void modify(Runnable runnable, IPath modelPath) {
//About to modify and save this model
try {
JavaeeResourceImpl res = (JavaeeResourceImpl)getModelResource(modelPath);
if (res != null)
setWritableResource(res);
runnable.run();
try {
if (res != null) {
if (modelPath != null && modelPath.equals(IModelProvider.FORCESAVE))
res.save(Collections.EMPTY_MAP,true);
else
res.save(Collections.EMPTY_MAP);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
setWritableResource(null);
}
}
// private class ResourceChangeListener implements IResourceChangeListener {
// public void resourceChanged(IResourceChangeEvent event) {
// IResourceDelta delta= event.getDelta();
// // make sure that there is a delta (since some events don't have one)
// if (delta != null)
// {
// IResourceDelta[] affectedChildren= delta.getAffectedChildren(IResourceDelta.CHANGED | IResourceDelta.REMOVED , IResource.FILE);
// IResourceDelta projectDelta = null;
// IResource changedResource = null;
// IProject changedProject = null;
// IPath resourcePath = null;
//
// for (int i= 0; i < affectedChildren.length; i++) {
// projectDelta = affectedChildren[i];
// changedResource = projectDelta.getResource();
// changedProject = changedResource.getProject();
// HashSet<IPath> currentResources = modelResources.get(changedProject);
// // only deal with the projects that have resources that have been loaded
// if (currentResources != null)
// {
// // if this is a project deletion, remove the project from the HashMap.
// if (changedResource == changedProject && projectDelta.getKind() == IResourceDelta.REMOVED)
// {
// modelResources.remove(changedProject);
// // if modelResources is empty, we should self-destruct
// if (modelResources.isEmpty())
// {
// resourceChangeListenerEnabled = false;
// ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
// }
// }
// else
// {
// Iterator<IPath> iter = currentResources.iterator();
// ArrayList<IPath> toUnload = new ArrayList<IPath>();
// // check each resource that was loaded from the project to see if it is part of the change
// while (iter.hasNext())
// {
// resourcePath = iter.next();
// if (projectDelta.findMember(resourcePath) != null)
// {
// // limit the list of resources that need to be unloaded to those that have changed
// toUnload.add(resourcePath);
// }
// }
// if (toUnload.size() > 0)
// {
// Resource current = null;
// ProjectResourceSet resourceSet = getResourceSet(changedProject);
// URIConverter uriConverter = resourceSet.getURIConverter();
// HashSet<URI> resourceURIs = new HashSet<URI>();
// iter = toUnload.iterator();
// while (iter.hasNext())
// {
// // convert all of the resources to URIs - this is a faster match during the compare
// resourceURIs.add(uriConverter.normalize(URI.createURI(iter.next().toString())));
// }
// Iterator<Resource> iter2 = resourceSet.getResources().iterator();
// while (iter2.hasNext())
// {
// current = iter2.next();
// if (resourceURIs.contains(current.getURI()))
// {
// current.unload();
// }
// }
// }
// }
// }
// }
// }
// }
// }
public void addListener(IModelProviderListener listener) {
listeners.add(listener);
}
public void removeListener(IModelProviderListener listener)
{
listeners.remove(listener);
}
/**
* Save only resources that need to be saved (i.e., no other references).
*/
public void modelsChanged(IModelProviderEvent anEvent) {
int code = anEvent.getEventCode();
switch (code) {
case IModelProviderEvent.REMOVED_RESOURCE : {
if (hasResourceReference(anEvent.getChangedResources()))
removeResources(anEvent.getChangedResources());
else
return;
break;
}
}
if (hasListeners()) {
anEvent.setModel(this);
notifyListeners(anEvent);
}
}
protected void removeResources(List aList) {
Resource res;
for (int i = 0; i < aList.size(); i++) {
res = (Resource) aList.get(i);
removeResource(res) ;
}
}
/**
* Remove reference to the aResource.
*/
protected boolean removeResource(Resource aResource) {
if (aResource != null) {
aResource.eAdapters().remove(resourceAdapter);
return getResources().remove(aResource);
}
return false;
}
/**
* Return true if any Resource in the list of
*
* @resources is referenced by me.
*/
protected boolean hasResourceReference(List tResources) {
for (int i = 0; i < tResources.size(); i++) {
if (hasResourceReference((Resource) tResources.get(i)))
return true;
}
return false;
}
/**
* Return true if aResource is referenced by me.
*/
protected boolean hasResourceReference(Resource aResource) {
if (aResource != null)
return getResources().contains(aResource);
return false;
}
/**
* Notify listeners of
*
* @anEvent.
*/
protected void notifyListeners(IModelProviderEvent anEvent) {
NotifyRunner notifier = new NotifyRunner(anEvent);
Object[] notifyList = listeners.getListeners();
for (int i = 0; i < notifyList.length; i++) {
notifier.setListener( (IModelProviderListener) notifyList[i] );
SafeRunner.run(notifier);
}
}
public class NotifyRunner implements ISafeRunnable {
private final IModelProviderEvent event;
private IModelProviderListener listener;
public NotifyRunner(IModelProviderEvent event) {
Assert.isNotNull(event);
this.event = event;
}
public void setListener(IModelProviderListener listener) {
this.listener = listener;
}
public void handleException(Throwable exception) {
JEEPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, JEEPlugin.PLUGIN_ID, 0, exception.getMessage(), exception));
}
public void run() throws Exception {
if(listener != null)
listener.modelsChanged(event);
}
}
public ResourceStateValidator getStateValidator() {
if (stateValidator == null)
stateValidator = createStateValidator();
return stateValidator;
}
/**
* Method createStateValidator.
*
* @return ResourceStateValidator
*/
private ResourceStateValidator createStateValidator() {
return new ResourceStateValidatorImpl(this);
}
protected EnterpriseArtifactEdit createArtifactEdit() {
return null;
}
public void checkActivation(ResourceStateValidatorPresenter presenter) throws CoreException {
getStateValidator().checkActivation(presenter);
}
public boolean checkReadOnly() {
return getStateValidator().checkReadOnly();
}
public boolean checkSave(ResourceStateValidatorPresenter presenter) throws CoreException {
return getStateValidator().checkSave(presenter);
}
public void lostActivation(ResourceStateValidatorPresenter presenter) throws CoreException {
getStateValidator().lostActivation(presenter);
}
public IStatus validateState(ResourceStateValidatorPresenter presenter) throws CoreException {
if (presenter == null)
return Status.OK_STATUS;
return getStateValidator().validateState(presenter);
}
public void cacheNonResourceValidateState(List roNonResourceFiles) {
// do nothing
}
public List getNonResourceFiles() {
return null;
}
public List getNonResourceInconsistentFiles() {
return null;
}
public List getResources() {
return modelResources;
}
public boolean isDirty() {
List list = getResources();
for (int i = 0; i < list.size(); i++) {
if (((Resource) list.get(i)).isModified())
return true;
}
return false;
}
}