| /** |
| * Copyright (c) 2009-2010 Thales Corporate Services S.A.S. |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-v2.0 |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Thales Corporate Services S.A.S - initial API and implementation |
| */ |
| package org.eclipse.egf.core.pde.internal.resource; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| 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.IResourceDeltaVisitor; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.resources.WorkspaceJob; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.SubMonitor; |
| import org.eclipse.egf.common.helper.BundleHelper; |
| import org.eclipse.egf.common.helper.ProjectHelper; |
| import org.eclipse.egf.common.helper.URIHelper; |
| import org.eclipse.egf.core.fcore.IPlatformFcoreConstants; |
| import org.eclipse.egf.core.fcore.IResourceFcoreDelta; |
| import org.eclipse.egf.core.fcore.IResourceFcoreListener; |
| import org.eclipse.egf.core.pde.EGFPDEPlugin; |
| import org.eclipse.egf.core.pde.l10n.EGFPDEMessages; |
| import org.eclipse.egf.core.pde.plugin.IPluginChangesCommand; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.common.util.UniqueEList; |
| import org.eclipse.osgi.util.NLS; |
| |
| /** |
| * @author Xavier Maysonnave |
| * |
| */ |
| public class FcoreResourceListener implements IResourceChangeListener { |
| |
| // Type of event that should be processed no matter what the real event type is. |
| public int _overridenEventType = -1; |
| |
| // A list of listeners interested in changes to fcore resources |
| private List<IResourceFcoreListener> _listeners; |
| |
| public FcoreResourceListener() { |
| // ensure that we are listening to the workspace |
| ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); |
| } |
| |
| /** |
| * Notify all interested listeners in changes made to fcore resource |
| * |
| * @param delta |
| * the delta of changes |
| */ |
| private void fireResourceFcore(IResourceFcoreDelta delta) { |
| if (_listeners != null) { |
| for (IResourceFcoreListener listener : _listeners) { |
| listener.fcoreChanged(delta); |
| } |
| } |
| } |
| |
| /** |
| * Add a listener |
| * |
| * @param listener |
| * the listener to be added |
| */ |
| public void addResourceFcoreListener(IResourceFcoreListener listener) { |
| if (_listeners == null) { |
| _listeners = new ArrayList<IResourceFcoreListener>(); |
| } |
| if (_listeners.contains(listener) == false) { |
| _listeners.add(listener); |
| } |
| } |
| |
| /** |
| * Remove a listener |
| * |
| * @param listener |
| * the listener to be removed |
| */ |
| public void removeResourceFcoreListener(IResourceFcoreListener listener) { |
| if (_listeners == null) { |
| return; |
| } |
| _listeners.remove(listener); |
| } |
| |
| /** |
| * This listens for workspace changes. |
| */ |
| |
| public void resourceChanged(IResourceChangeEvent event) { |
| |
| int eventType = _overridenEventType == -1 ? event.getType() : _overridenEventType; |
| |
| try { |
| |
| class ResourceDeltaVisitor implements IResourceDeltaVisitor { |
| |
| protected List<IPath> _newFcores = new UniqueEList<IPath>(); |
| |
| protected List<IPath> _removedFcores = new UniqueEList<IPath>(); |
| |
| protected Map<IPath, IPath> _movedFcores = new HashMap<IPath, IPath>(); |
| |
| protected ResourceFcoreDelta _deltaFcores = new ResourceFcoreDelta(); |
| |
| public boolean visit(IResourceDelta delta) throws CoreException { |
| |
| try { |
| |
| // Ignore opening and closing projects, handled by PlatformManager |
| if (delta.getResource().getType() == IResource.PROJECT && (delta.getFlags() & IResourceDelta.OPEN) != 0) { |
| return false; |
| } |
| |
| // Process file |
| if (delta.getResource().getType() != IResource.FILE) { |
| return true; |
| } |
| |
| // check whether or not we are processing an fcore |
| boolean isFcore = IPlatformFcoreConstants.FCORE_FILE_EXTENSION.equals(delta.getResource().getFileExtension()); |
| // Locate the bundleId, resource should be located in a bundle project |
| String bundleId = BundleHelper.getBundleId(delta.getResource()); |
| URI uri = URIHelper.getPlatformPluginURI(delta.getResource()); |
| if (uri != null && bundleId != null) { |
| if (delta.getKind() == IResourceDelta.CHANGED && isFcore) { |
| if (delta.getFlags() != IResourceDelta.MARKERS && (delta.getFlags() & IResourceDelta.CONTENT) != 0) { |
| _deltaFcores.addUpdatedFcore(delta); |
| } |
| } else if (delta.getKind() == IResourceDelta.ADDED && isFcore) { |
| if ((delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) { |
| _deltaFcores.addNewFcore(delta.getFullPath()); |
| _newFcores.add(delta.getResource().getFullPath()); |
| } |
| } else if (delta.getKind() == IResourceDelta.REMOVED) { |
| boolean isMovedToFcore = false; |
| if ((delta.getFlags() & IResourceDelta.MOVED_TO) != 0) { |
| isMovedToFcore = IPlatformFcoreConstants.FCORE_FILE_EXTENSION.equals(delta.getMovedToPath().getFileExtension()); |
| } |
| // Check whether or not we are moving an fcore to an fcore |
| if ((delta.getFlags() & IResourceDelta.MOVED_TO) != 0 && isFcore && isMovedToFcore) { |
| _deltaFcores.addMovedFcore(delta.getResource().getFullPath(), delta.getMovedToPath()); |
| _movedFcores.put(delta.getResource().getFullPath(), delta.getMovedToPath()); |
| // Check whether or not we are moving a non fcore to an fcore |
| } else if ((delta.getFlags() & IResourceDelta.MOVED_TO) != 0 && isFcore == false && isMovedToFcore) { |
| _deltaFcores.addNewFcore(delta.getMovedToPath(), delta.getResource().getProject()); |
| _newFcores.add(delta.getMovedToPath()); |
| // Check whether or not we are deleting an fcore |
| } else if (isFcore) { |
| _deltaFcores.addRemovedFcore(delta.getResource().getFullPath()); |
| _removedFcores.add(delta.getResource().getFullPath()); |
| } |
| } |
| |
| } |
| |
| } catch (Throwable t) { |
| EGFPDEPlugin.getDefault().logError("FcoreResourceListener.resourceChanged(..) _ ", t); //$NON-NLS-1$ |
| } |
| |
| return true; |
| |
| } |
| |
| public ResourceFcoreDelta getFcoresDelta() { |
| return _deltaFcores; |
| } |
| |
| public Map<IPath, IPath> getMovedFcores() { |
| return _movedFcores; |
| } |
| |
| public List<IPath> getRemovedFcores() { |
| return _removedFcores; |
| } |
| |
| public List<IPath> getNewFcores() { |
| return _newFcores; |
| } |
| |
| } |
| |
| switch (eventType) { |
| case IResourceChangeEvent.POST_CHANGE: |
| final ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(); |
| event.getDelta().accept(visitor); |
| // Process added, moved and removed resources |
| if (visitor.getMovedFcores().isEmpty() == false || visitor.getRemovedFcores().isEmpty() == false || visitor.getNewFcores().isEmpty() == false) { |
| WorkspaceJob job = new FcoreSynchJob(visitor.getFcoresDelta().getAffectedProjects(), visitor.getMovedFcores(), visitor.getRemovedFcores(), visitor.getNewFcores()); |
| job.setUser(false); |
| job.setSystem(true); |
| job.schedule(); |
| } |
| // Broadcast events if any |
| if (visitor.getFcoresDelta().isEmpty() == false) { |
| // Debug |
| if (EGFPDEPlugin.getDefault().isDebugging()) { |
| trace(visitor.getFcoresDelta()); |
| } |
| // Notify all interested listeners in the changes made to models |
| fireResourceFcore(visitor.getFcoresDelta()); |
| } |
| } |
| |
| } catch (CoreException ce) { |
| EGFPDEPlugin.getDefault().logError("FcoreResourceListener.resourceChanged(..) _", ce); //$NON-NLS-1$ |
| } |
| |
| } |
| |
| public void dispose() { |
| ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); |
| _listeners = null; |
| } |
| |
| private void trace(IResourceFcoreDelta delta) { |
| if (delta.getNewFcores().size() > 0) { |
| EGFPDEPlugin.getDefault().logInfo(NLS.bind("FcoreResourceListener Added {0} Fcore{1}.", //$NON-NLS-1$ |
| delta.getNewFcores().size(), delta.getNewFcores().size() < 2 ? "" : "s" //$NON-NLS-1$ //$NON-NLS-2$ |
| )); |
| for (URI uri : delta.getNewFcores()) { |
| EGFPDEPlugin.getDefault().logInfo(URIHelper.toString(uri), 1); |
| } |
| } |
| if (delta.getRemovedFcores().size() > 0) { |
| EGFPDEPlugin.getDefault().logInfo(NLS.bind("FcoreResourceListener Removed {0} Fcore{1}.", //$NON-NLS-1$ |
| delta.getRemovedFcores().size(), delta.getRemovedFcores().size() < 2 ? "" : "s" //$NON-NLS-1$ //$NON-NLS-2$ |
| )); |
| for (URI uri : delta.getRemovedFcores()) { |
| EGFPDEPlugin.getDefault().logInfo(URIHelper.toString(uri), 1); |
| } |
| } |
| if (delta.getUpdatedFcores().size() > 0) { |
| EGFPDEPlugin.getDefault().logInfo(NLS.bind("FcoreResourceListener Updated {0} Fcore{1}.", //$NON-NLS-1$ |
| delta.getUpdatedFcores().size(), delta.getUpdatedFcores().size() < 2 ? "" : "s" //$NON-NLS-1$ //$NON-NLS-2$ |
| )); |
| for (URI uri : delta.getUpdatedFcores()) { |
| EGFPDEPlugin.getDefault().logInfo(URIHelper.toString(uri), 1); |
| } |
| } |
| if (delta.getMovedFcores().size() > 0) { |
| EGFPDEPlugin.getDefault().logInfo(NLS.bind("FcoreResourceListener Moved {0} Fcore{1}.", //$NON-NLS-1$ |
| delta.getMovedFcores().size(), delta.getMovedFcores().size() < 2 ? "" : "s" //$NON-NLS-1$ //$NON-NLS-2$ |
| )); |
| for (URI uri : delta.getMovedFcores().keySet()) { |
| EGFPDEPlugin.getDefault().logInfo(URIHelper.toString(uri), 1); |
| EGFPDEPlugin.getDefault().logInfo("To: " + URIHelper.toString(delta.getMovedFcores().get(uri)), 2); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| private static class FcoreSynchJob extends WorkspaceJob { |
| |
| private Map<IPath, IPath> _movedFcores; |
| |
| private List<IPath> _newFcores; |
| |
| private List<IPath> _removedFcores; |
| |
| /** |
| * Initializes me with the list of resources changes that I am to |
| * process. |
| * |
| * @param affectedProjects |
| * the projects affected by the workspace changes |
| */ |
| FcoreSynchJob(List<IProject> affectedProjects, Map<IPath, IPath> movedFcores, List<IPath> removedFcores, List<IPath> newFcores) { |
| super(EGFPDEMessages.PluginModelUpdate_progressMessage); |
| _movedFcores = movedFcores; |
| _removedFcores = removedFcores; |
| _newFcores = newFcores; |
| setRule(ProjectHelper.getRule(affectedProjects)); |
| } |
| |
| @Override |
| public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { |
| try { |
| SubMonitor subMonitor = SubMonitor.convert(monitor, EGFPDEMessages.PluginModelUpdate_progressMessage, (_movedFcores.size() + _removedFcores.size() + _newFcores.size()) * 1000); |
| // Moved Fcores |
| for (IPath path : _movedFcores.keySet()) { |
| // Ignore non Bundle project |
| if (BundleHelper.getPluginModelBase(path) != null) { |
| // Delete command |
| IPluginChangesCommand unsetCommand = EGFPDEPlugin.getFcoreExtensionHelper().unsetFcoreExtension(path); |
| unsetCommand.execute(subMonitor.newChild(1000, SubMonitor.SUPPRESS_NONE)); |
| if (monitor.isCanceled()) { |
| throw new InterruptedException(); |
| } |
| } |
| // Ignore non Bundle project |
| if (BundleHelper.getPluginModelBase(_movedFcores.get(path)) != null) { |
| // Create command |
| IPluginChangesCommand createCommand = EGFPDEPlugin.getFcoreExtensionHelper().setFcoreExtension(_movedFcores.get(path)); |
| createCommand.execute(subMonitor.newChild(1000, SubMonitor.SUPPRESS_NONE)); |
| if (monitor.isCanceled()) { |
| throw new InterruptedException(); |
| } |
| } |
| } |
| // Removed Fcores |
| for (IPath path : _removedFcores) { |
| // Ignore non Bundle project |
| if (BundleHelper.getPluginModelBase(path) != null) { |
| // Delete command |
| IPluginChangesCommand unsetCommand = EGFPDEPlugin.getFcoreExtensionHelper().unsetFcoreExtension(path); |
| unsetCommand.execute(subMonitor.newChild(1000, SubMonitor.SUPPRESS_NONE)); |
| if (monitor.isCanceled()) { |
| throw new InterruptedException(); |
| } |
| } |
| } |
| // Added Fcores |
| for (IPath path : _newFcores) { |
| // Ignore non Bundle project |
| if (BundleHelper.getPluginModelBase(path) != null) { |
| // Create command |
| IPluginChangesCommand createCommand = EGFPDEPlugin.getFcoreExtensionHelper().setFcoreExtension(path); |
| createCommand.execute(subMonitor.newChild(1000, SubMonitor.SUPPRESS_NONE)); |
| if (monitor.isCanceled()) { |
| throw new InterruptedException(); |
| } |
| } |
| } |
| } catch (InterruptedException e) { |
| return Status.CANCEL_STATUS; |
| } finally { |
| monitor.done(); |
| } |
| return Status.OK_STATUS; |
| } |
| |
| } |
| |
| } |