blob: 19f5a0d16a64c01f62e75f2f039d2d674c4293de [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2004 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
*******************************************************************************/
/*
* Created on Mar 4, 2004
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package org.eclipse.wst.common.internal.emfworkbench.integration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
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.ResourceSet;
import org.eclipse.jem.internal.util.emf.workbench.EMFWorkbenchContextFactory;
import org.eclipse.jem.util.emf.workbench.ProjectResourceSet;
import org.eclipse.jem.util.emf.workbench.ResourceSetWorkbenchSynchronizer;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jem.util.plugin.JEMUtilPlugin;
import org.eclipse.wst.common.internal.emf.resource.ReferencedResource;
import org.eclipse.wst.common.internal.emfworkbench.WorkbenchResourceHelper;
/**
* @author schacher
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class ResourceSetWorkbenchEditSynchronizer extends ResourceSetWorkbenchSynchronizer implements IResourceDeltaVisitor {
private static final String CLASS_EXTENSION = "class"; //$NON-NLS-1$
private static final String JAVA_EXTENSION = "java"; //$NON-NLS-1$
private Set recentlySavedFiles = new HashSet();
private Map ignoredFilesCache = new HashMap();
/** The emf resources to be removed from the resource set as a result of a delta */
protected List deferredRemoveResources = new ArrayList();
protected List deferredUnloadResources = new ArrayList();
protected List deferredLoadResources = new ArrayList();
protected List autoloadResourcesURIs = new ArrayList();
/**
* @param aResourceSet
* @param aProject
*/
public ResourceSetWorkbenchEditSynchronizer(ResourceSet aResourceSet, IProject aProject) {
super(aResourceSet, aProject);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.common.internal.emfworkbench.ResourceSetWorkbenchSynchronizer#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
*/
public void resourceChanged(IResourceChangeEvent event) {
super.resourceChanged(event);
try {
acceptDelta(event);
notifyExtendersIfNecessary();
processDeferredResources();
} catch (Exception e) {
e.printStackTrace();
} finally {
deferredRemoveResources.clear();
deferredUnloadResources.clear();
deferredLoadResources.clear();
}
}
protected void processDeferredRemovedResources() {
Resource resource = null;
for (int i = 0; i < deferredRemoveResources.size(); i++) {
resource = (Resource) deferredRemoveResources.get(i);
resourceSet.getResources().remove(resource);
resource.unload();
}
}
protected void processDeferredUnloadedResources() {
Resource resource = null;
for (int i = 0; i < deferredUnloadResources.size(); i++) {
resource = (Resource) deferredUnloadResources.get(i);
resource.unload();
}
}
private void processDeferredLoadResources() {
URI uri = null;
for (int i = 0; i < deferredLoadResources.size(); i++) {
uri = (URI) deferredLoadResources.get(i);
try {
resourceSet.getResource(uri, true);
} catch (WrappedException ex) {
Logger.getLogger().logError(ex);
}
}
}
protected void acceptDelta(IResourceChangeEvent event) {
IResourceDelta delta = event.getDelta();
// search for changes to any projects using a visitor
if (delta != null) {
try {
delta.accept(this);
} catch (Exception e) {
Logger.getLogger().logError(e);
}
}
}
/**
* The project is going away so we need to cleanup ourself and the ResourceSet. TODO Need to
* push up this code to ResourceSetWorkbenchSynchronizer in next release.
*/
protected void release() {
if (JEMUtilPlugin.isActivated()) {
try {
if (resourceSet instanceof ProjectResourceSet)
((ProjectResourceSet) resourceSet).release();
} finally {
EMFWorkbenchContextFactory.INSTANCE.removeCachedProject(getProject());
dispose();
}
}
}
private void processDeferredResources() {
processDeferredRemovedResources();
processDeferredUnloadedResources();
processDeferredLoadResources();
}
public boolean visit(IResourceDelta delta) {
IResource resource = delta.getResource();
// only respond to project changes
if (resource != null) {
if (resource.getType() == IResource.PROJECT) {
IProject p = (IProject) resource;
if (isInterrestedInProject(p)) {
currentProjectDelta = delta;
return true;
}
// added line
currentProjectDelta = null;
return false;
}
if (resource.getType() == IResource.FILE && isInterrestedInFile((IFile) resource)) {
switch (delta.getKind()) {
case IResourceDelta.REMOVED :
removedResource((IFile) resource);
break;
case IResourceDelta.ADDED :
addedResource((IFile) resource);
break;
case IResourceDelta.CHANGED :
if ((delta.getFlags() & IResourceDelta.CONTENT) != 0)
changedResource((IFile) resource);
break;
default :
if ((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0 || (delta.getFlags() & IResourceDelta.MOVED_TO) != 0)
movedResource((IFile) resource);
break;
}
return false;
}
}
return true;
}
/**
* Queue up the <code>Resource</code> that corresponds to <code>aFile</code>, for removal
* from the cache of resources.
*
* @post Return true if a <code>Resource</code> was queued up to be removed.
*/
protected boolean removedResource(IFile aFile) {
return processResource(aFile, true);
}
/**
* Queue up the <code>Resource</code> that corresponds to <code>aFile</code>, for reload.
*
* @post Return true if a <code>Resource</code> was queued up to be reloaded.
*/
protected boolean addedResource(IFile aFile) {
//Process resource as a refresh.
return processResource(aFile, false);
}
protected boolean processResource(IFile aFile, boolean isRemove) {
Resource resource = getResource(aFile);
if (resource != null) {
if (resource.isModified()) {
if (WorkbenchResourceHelper.isReferencedResource(resource)) {
ReferencedResource refRes = (ReferencedResource) resource;
if (!refRes.shouldForceRefresh())
return false; //Do not do anything
} else
return false;
}
if (isRemove)
deferredRemoveResources.add(resource);
else if (resource.isLoaded())
deferredUnloadResources.add(resource);
else if (autoloadResourcesURIs.contains(resource.getURI()))
deferredLoadResources.add(resource.getURI());
}
return false;
}
/**
* For now, do the same as if the <code>aFile</code> was removed.
*/
protected boolean movedResource(IFile aFile) {
return removedResource(aFile);
}
/**
* The contents of <code>aFile</code> have changed in the Workbench and we may need to update
* our cached resources.
*
* We will process this resource to be refreshed and not removed.
*
* @post Return true if a <code>Resource</code> was actually removed.
*/
protected boolean changedResource(IFile aFile) {
//Process resource as a refresh.
return processResource(aFile, false);
}
protected Resource getResource(IFile aFile) {
return resourceSet.getResource(URI.createPlatformResourceURI(aFile.getFullPath().toString()), false);
}
/**
* This method should be called prior to writing to an IFile from a MOF resource.
*/
public void preSave(IFile aFile) {
if (aFile != null) {
recentlySavedFiles.add(aFile);
ignoredFilesCache.remove(aFile);
}
}
/**
* This method should be called after a preSave if the save fails
*/
public void removeFromRecentlySavedList(IFile aFile) {
if (aFile != null) {
recentlySavedFiles.remove(aFile);
ignoredFilesCache.remove(aFile);
}
}
/**
* This method should be called just after writing to an IFile from a MOF resource.
*
* @deprecated No longer needs to be called.
*/
public void postSave(IFile aFile) {
//TODO remove this method
}
/**
* Return <code>true</code> if <code>aProject</code> has the projectNatureID.
*/
protected boolean isInterrestedInProject(IProject aProject) {
return aProject.equals(getProject());
}
/**
* Optimized not to be not interrested in files with an extension of .java or .class or if the
* file has just been saved by our own internal mechanism.
*/
protected boolean isInterrestedInFile(IFile aFile) {
String extension = aFile.getFileExtension();
if (CLASS_EXTENSION.equals(extension) || JAVA_EXTENSION.equals(extension))
return false;
if (recentlySavedFiles.remove(aFile)) {
cacheIgnored(aFile);
return false;
}
return !hasIgnored(aFile);
}
/**
* Return true if we have already ignored this <code>file</code> and that its modification
* stamp is the same as when we processed it.
*
* @param file
* @return
*/
private boolean hasIgnored(IFile file) {
Long cachedStamp = (Long) ignoredFilesCache.get(file);
if (cachedStamp == null)
return false;
long stamp = WorkbenchResourceHelper.computeModificationStamp(file);
return cachedStamp.longValue() == stamp;
}
/**
* Cache the modification stamp of the <code>file</code>.
*
* @param file
*/
private void cacheIgnored(IFile file) {
long stamp = WorkbenchResourceHelper.computeModificationStamp(file);
ignoredFilesCache.put(file, new Long(stamp));
}
public void enableAutoload(URI uri) {
URI normalized = resourceSet.getURIConverter().normalize(uri);
autoloadResourcesURIs.add(normalized);
}
public void disableAutoload(URI uri) {
URI normalized = resourceSet.getURIConverter().normalize(uri);
autoloadResourcesURIs.remove(normalized);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.common.internal.emfworkbench.ResourceSetWorkbenchSynchronizer#initialize()
*/
protected void initialize() {
getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.POST_CHANGE);
}
}