/****************************************************************************** * Copyright (c) 2002, 2010 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.gmf.runtime.common.ui.resources; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IMarkerDelta; 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.IResourceDeltaVisitor; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.gmf.runtime.common.core.util.Log; import org.eclipse.gmf.runtime.common.core.util.Trace; import org.eclipse.gmf.runtime.common.ui.internal.CommonUIDebugOptions; import org.eclipse.gmf.runtime.common.ui.internal.CommonUIPlugin; import org.eclipse.gmf.runtime.common.ui.internal.CommonUIStatusCodes; import org.eclipse.gmf.runtime.common.ui.internal.resources.FileChangeEvent; import org.eclipse.gmf.runtime.common.ui.internal.resources.FileChangeEventType; import org.eclipse.gmf.runtime.common.ui.internal.resources.IFileChangeManager; import org.eclipse.gmf.runtime.common.ui.internal.resources.MarkerChangeEvent; import org.eclipse.gmf.runtime.common.ui.internal.resources.MarkerChangeEventType; /** * The file change manager handles changes made to file resources within the * Eclipse workspace. Files in the workspace are affected by change events on * the files themselves as well as change events on the project and folder that * contains these files. * * @author Anthony Hunter <a * href="mailto:ahunter@rational.com">ahunter@rational.com </a> */ public class FileChangeManager implements IResourceChangeListener, IResourceDeltaVisitor, IFileChangeManager { /** * singleton instance of this class */ private static FileChangeManager INSTANCE = new FileChangeManager(); /** * get the singleton instance of this class * * @return singleton instance of the FileChangeManager class */ public static FileChangeManager getInstance() { return INSTANCE; } /** * list of resource observers */ private FileObserverManager fileObserverManager = new FileObserverManager(); /** * Simple constructor. */ private FileChangeManager() { super(); ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); } /* * (non-Javadoc) * * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) */ public final void resourceChanged(IResourceChangeEvent event) { switch (event.getType()) { case IResourceChangeEvent.POST_CHANGE: try { event.getDelta().accept(this); } catch (CoreException e) { Trace.catching(CommonUIPlugin.getDefault(), CommonUIDebugOptions.EXCEPTIONS_CATCHING, getClass(), "resourceChanged", e); //$NON-NLS-1$ Log.warning(CommonUIPlugin.getDefault(), CommonUIStatusCodes.IGNORED_EXCEPTION_WARNING, e .getMessage(), e); } break; default: break; } } /* * (non-Javadoc) * * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) */ public final boolean visit(IResourceDelta delta) { switch (delta.getKind()) { case IResourceDelta.ADDED: if ((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) { if (delta.getMovedFromPath().removeLastSegments(1) .equals( delta.getResource().getFullPath() .removeLastSegments(1))) { if (Trace.shouldTrace(CommonUIPlugin.getDefault(), CommonUIDebugOptions.RESOURCE)) { Trace.trace(CommonUIPlugin.getDefault(), "...FileChangeManager: Resource " //$NON-NLS-1$ + getAbsolutePath(delta.getResource()) + " was renamed from " //$NON-NLS-1$ + delta.getMovedFromPath().toString()); } if (delta.getResource() instanceof IFile) { FileChangeEvent event = new FileChangeEvent( FileChangeEventType.RENAMED, (IFile) getMovedFromResource(delta), (IFile) delta.getResource()); fileObserverManager.notify(event); } } else { if (Trace.shouldTrace(CommonUIPlugin.getDefault(), CommonUIDebugOptions.RESOURCE)) { Trace.trace(CommonUIPlugin.getDefault(), "...FileChangeManager: Resource " //$NON-NLS-1$ + getAbsolutePath(delta.getResource()) + " was moved from " //$NON-NLS-1$ + delta.getMovedFromPath().toString()); } if (delta.getResource() instanceof IFile) { FileChangeEvent event = new FileChangeEvent( FileChangeEventType.MOVED, (IFile) getMovedFromResource(delta), (IFile) delta.getResource()); fileObserverManager.notify(event); } } } else if (delta.getResource() instanceof IFile) { FileChangeEvent event = new FileChangeEvent( FileChangeEventType.CHANGED, (IFile) delta .getResource()); fileObserverManager.notify(event); if (Trace.shouldTrace(CommonUIPlugin.getDefault(), CommonUIDebugOptions.RESOURCE)) { Trace.trace(CommonUIPlugin.getDefault(), "...FileChangeManager: Resource " //$NON-NLS-1$ + getAbsolutePath(delta.getResource()) + " was added"); //$NON-NLS-1$ } } else { if (Trace.shouldTrace(CommonUIPlugin.getDefault(), CommonUIDebugOptions.RESOURCE)) { Trace.trace(CommonUIPlugin.getDefault(), "...FileChangeManager: Resource " //$NON-NLS-1$ + getAbsolutePath(delta.getResource()) + " was added"); //$NON-NLS-1$ } } break; case IResourceDelta.REMOVED: if ((delta.getFlags() & IResourceDelta.MOVED_TO) == 0) { if (Trace.shouldTrace(CommonUIPlugin.getDefault(), CommonUIDebugOptions.RESOURCE)) { Trace.trace(CommonUIPlugin.getDefault(), "...FileChangeManager: Resource " //$NON-NLS-1$ + getAbsolutePath(delta.getResource()) + " was deleted"); //$NON-NLS-1$ } if (delta.getResource() instanceof IFile) { FileChangeEvent event = new FileChangeEvent( FileChangeEventType.DELETED, (IFile) delta .getResource()); fileObserverManager.notify(event); } } break; case IResourceDelta.CHANGED: if (Trace.shouldTrace(CommonUIPlugin.getDefault(), CommonUIDebugOptions.RESOURCE)) { Trace.trace(CommonUIPlugin.getDefault(), "...FileChangeManager: Resource " //$NON-NLS-1$ + getAbsolutePath(delta.getResource()) + " was changed"); //$NON-NLS-1$ } if ((delta.getFlags() & IResourceDelta.MARKERS) != 0) { // fire notifications if markers have been // added/removed/changed List markers = Arrays.asList(delta.getMarkerDeltas()); for (Iterator i = markers.iterator(); i.hasNext();) { if (Trace.shouldTrace(CommonUIPlugin.getDefault(), CommonUIDebugOptions.RESOURCE)) { Trace.trace(CommonUIPlugin.getDefault(), "...FileChangeManager: Resource marker of " //$NON-NLS-1$ + getAbsolutePath(delta.getResource()) + " was changed"); //$NON-NLS-1$ } MarkerChangeEvent event = null; IMarkerDelta markerDelta = (IMarkerDelta) i.next(); switch (markerDelta.getKind()) { case IResourceDelta.ADDED: event = new MarkerChangeEvent( MarkerChangeEventType.ADDED, markerDelta .getMarker()); fileObserverManager.notify(event); break; case IResourceDelta.REMOVED: event = new MarkerChangeEvent( MarkerChangeEventType.REMOVED, markerDelta .getMarker(), markerDelta .getAttributes()); fileObserverManager.notify(event); break; case IResourceDelta.CHANGED: event = new MarkerChangeEvent( MarkerChangeEventType.CHANGED, markerDelta .getMarker()); fileObserverManager.notify(event); break; default: break; } } } else if (delta.getResource() instanceof IFile) { FileChangeEvent event = new FileChangeEvent( FileChangeEventType.CHANGED, (IFile) delta .getResource()); fileObserverManager.notify(event); } break; default: break; } return true; } /* * (non-Javadoc) * * @see org.eclipse.gmf.runtime.common.ui.resources.IFileChangeManager#okToEdit(org.eclipse.core.resources.IFile[], * java.lang.String) */ public boolean okToEdit(IFile[] files, String modificationReason) { return FileModificationValidator.getInstance().okToEdit(files, modificationReason); } /* * (non-Javadoc) * * @see org.eclipse.gmf.runtime.common.ui.resources.IFileChangeManager#okToSave(org.eclipse.core.resources.IFile) */ public boolean okToSave(IFile file) { return FileModificationValidator.getInstance().okToSave(file); } /* * (non-Javadoc) * * @see org.eclipse.gmf.runtime.common.ui.resources.IFileChangeManager#removeFileObserver(org.eclipse.gmf.runtime.common.ui.resources.IFileObserver) */ public void removeFileObserver(IFileObserver fileObserver) { fileObserverManager.remove(fileObserver); } /* * (non-Javadoc) * * @see org.eclipse.gmf.runtime.common.ui.resources.IFileChangeManager#addFileObserver(org.eclipse.gmf.runtime.common.ui.resources.IFileObserver, * org.eclipse.core.resources.IFile) */ public void addFileObserver(IFileObserver fileObserver, IFile fileFilter) { fileObserverManager.add(fileObserver, fileFilter); } /* * (non-Javadoc) * * @see org.eclipse.gmf.runtime.common.ui.resources.IFileChangeManager#addFileObserver(org.eclipse.gmf.runtime.common.ui.resources.IFileObserver, * org.eclipse.core.runtime.content.IContentType[]) */ public void addFileObserver(IFileObserver fileObserver, IContentType[] contentTypeFilter) { fileObserverManager.add(fileObserver, contentTypeFilter); } /* * (non-Javadoc) * * @see org.eclipse.gmf.runtime.common.ui.resources.IFileChangeManager#addFileObserver(org.eclipse.gmf.runtime.common.ui.resources.IFileObserver, * org.eclipse.core.resources.IFolder) */ public void addFileObserver(IFileObserver fileObserver, IFolder folderFilter) { fileObserverManager.add(fileObserver, folderFilter); } /* * (non-Javadoc) * * @see org.eclipse.gmf.runtime.common.ui.resources.IFileChangeManager#addFileObserver(org.eclipse.gmf.runtime.common.ui.resources.IFileObserver, * java.lang.String[]) */ public void addFileObserver(IFileObserver fileObserver, String[] extensionFilter) { fileObserverManager.add(fileObserver, extensionFilter); } /* * (non-Javadoc) * * @see org.eclipse.gmf.runtime.common.ui.resources.IFileChangeManager#addFileObserver(org.eclipse.gmf.runtime.common.ui.resources.IFileObserver) */ public void addFileObserver(IFileObserver fileObserver) { fileObserverManager.add(fileObserver); } /* * (non-Javadoc) * * @see org.eclipse.gmf.runtime.common.ui.resources.IFileChangeManager#refreshLocal(org.eclipse.core.resources.IFile) */ public void refreshLocal(final IFile file) { try { file.getWorkspace().run(new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { if (Trace.shouldTrace(CommonUIPlugin.getDefault(), CommonUIDebugOptions.RESOURCE)) { Trace.trace(CommonUIPlugin.getDefault(), "...FileChangeManager: Resource " + //$NON-NLS-1$ getAbsolutePath(file) + " was refreshed"); //$NON-NLS-1$ } file.refreshLocal(IResource.DEPTH_ZERO, null); } }, new NullProgressMonitor()); } catch (CoreException e) { Trace.catching(CommonUIPlugin.getDefault(), CommonUIDebugOptions.EXCEPTIONS_CATCHING, getClass(), "refreshResource", e); //$NON-NLS-1$ Log.error(CommonUIPlugin.getDefault(), CommonUIStatusCodes.SERVICE_FAILURE, e.getMessage(), e); } } /** * Retrieve the moved from resource from the resource delta. The moved from * resource is the original resource after a rename or move. * * @param delta * the resource change containing the moved from path. * @return the moved from resource. */ public static IResource getMovedFromResource(IResourceDelta delta) { IPath movedFromPath = delta.getMovedFromPath(); IResource resource = delta.getResource(); IResource movedResource = null; switch (resource.getType()) { case IResource.PROJECT: movedResource = ResourcesPlugin.getWorkspace().getRoot() .getProject(movedFromPath.lastSegment()); break; case IResource.FOLDER: movedResource = ResourcesPlugin.getWorkspace().getRoot() .getFolder(movedFromPath); break; case IResource.FILE: movedResource = ResourcesPlugin.getWorkspace().getRoot() .getFile(movedFromPath); break; default: break; } return movedResource; } /** * Get the path for a resource. In the case of a moved or deleted resource, * resource.getLocation() returns null since it does not exist in the * workspace. The workaround is below. * * @param resource * the resource. * @return the path for a resource. */ private String getAbsolutePath(IResource resource) { if (resource.getLocationURI() == null) { return resource.getFullPath().toString(); } else { return resource.getLocationURI().toString(); } } }