blob: 11b61e9e69eb28fb92336d752a04fb0e0e587d7d [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.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
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.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentDescription;
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.resource.URIConverter;
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.model.IModelProvider;
import org.eclipse.jst.j2ee.model.IModelProviderListener;
import org.eclipse.jst.javaee.core.internal.util.JavaeeResourceImpl;
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;
public class JEE5ModelProvider implements IModelProvider{
protected XMLResourceImpl writableResource;
protected IProject proj;
protected IPath defaultResourcePath;
private static boolean resourceChangeListenerEnabled = false;
private static HashMap<IProject, HashSet<IPath>> modelResources = new HashMap<IProject, HashSet<IPath>>();
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;
}
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)
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);
HashSet<IPath> currentResources = modelResources.get(proj);
if (currentResources == null)
{
currentResources = new HashSet<IPath>();
}
currentResources.add(new Path(uri.toString()));
modelResources.put(proj, currentResources);
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.
return createModelResource(modelPath, resSet, projURI);
}
} 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) {
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)
{
// do nothing for now
}
public void removeListener(IModelProviderListener listener)
{
// do nothing for now
}
}