package org.eclipse.gmf.internal.xpand.migration; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; 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.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Status; import org.eclipse.emf.ecore.EPackage; import org.eclipse.gmf.internal.xpand.ResourceManager; import org.eclipse.gmf.internal.xpand.RootManager; import org.eclipse.gmf.internal.xpand.build.MetaModelSource; import org.osgi.framework.BundleContext; /** * The activator class controls the plug-in life cycle */ public class Activator extends Plugin { // The plug-in ID public static final String PLUGIN_ID = "org.eclipse.gmf.xpand.migration"; // The shared instance private static Activator plugin; private final Set<MetaModelSource> modelSources = new LinkedHashSet<MetaModelSource>(); /** * The constructor */ public Activator() { } public void start(BundleContext context) throws Exception { super.start(context); plugin = this; ResourcesPlugin.getWorkspace().addResourceChangeListener(myRootsTracker); } public void stop(BundleContext context) throws Exception { ResourcesPlugin.getWorkspace().removeResourceChangeListener(myRootsTracker); plugin = null; super.stop(context); } /** * Returns the shared instance * * @return the shared instance */ public static Activator getDefault() { return plugin; } public static void logError(Exception e) { if (e instanceof CoreException) { log(((CoreException) e).getStatus()); } else { log(new Status(IStatus.ERROR, getId(), 0, e.getMessage(), e)); } } public static void log(IStatus status) { getDefault().getLog().log(status); } public static void logWarn(String message) { log(new Status(IStatus.WARNING, getId(), 0, message, null)); } private static String getId() { return getDefault().getBundle().getSymbolicName(); } public static void registerModelSource(MetaModelSource modelSource) { assert modelSource != null; getDefault().modelSources.add(modelSource); } public static EPackage findMetaModel(String nsURI) { if (getDefault() == null) { // this is for tests execution (which doesn't take place in plugin // env) return null; } for (MetaModelSource s : getDefault().modelSources) { EPackage p = s.find(nsURI); if (p != null) { return p; } } return EPackage.Registry.INSTANCE.getEPackage(nsURI); } /* Root managers are necessary for legacy xpand builders only */ private final Map<IProject, RootManager> rootManagers = new HashMap<IProject, RootManager>(); public static ResourceManager getResourceManager(final IFile file) { // TODO: return a delegating resource manager to XpandEditor, to // silently change context when roots change. RootManager manager = getRootManager(file.getProject()); ResourceManager result = manager.getResourceManager(file); assert result != null; return result; } public static RootManager getRootManager(IProject project) { synchronized (plugin.myRootsTracker) { RootManager result = plugin.rootManagers.get(project); if (result == null) { result = new RootManager(project); plugin.rootManagers.put(project, result); } return result; } } private final IResourceChangeListener myRootsTracker = new IResourceChangeListener() { public synchronized void resourceChanged(IResourceChangeEvent event) { if (event == null || event.getDelta() == null) { return; } Set<RootManager> affectedRootManagers = new HashSet<RootManager>(); IResourceDelta rootDelta = event.getDelta(); for (IResourceDelta projectDelta : rootDelta.getAffectedChildren()) { IProject affectedProject = (IProject) projectDelta.getResource(); if (isRemovedOrClosed(projectDelta)) { rootManagers.remove(affectedProject); } else { IResourceDelta configFileDelta = projectDelta.findMember(RootManager.PROJECT_RELATIVE_PATH_TO_CONFIG_FILE); if (configFileDelta != null && rootManagers.containsKey(affectedProject) && affectsConfigFile(configFileDelta)) { affectedRootManagers.add(getRootManager(affectedProject)); } } } // Opening/closing or creating/deleting a project may affect roots // with absolute paths. for (IResourceDelta projectDelta : rootDelta.getAffectedChildren()) { if (mayAffectOtherResourceManagers(projectDelta)) { IPath projectPath = projectDelta.getFullPath(); for (RootManager nextManager : rootManagers.values()) { if (nextManager.containsProject(projectPath)) { affectedRootManagers.add(nextManager); } } } } for (RootManager nextManager : affectedRootManagers) { nextManager.rootsChanged(); } } private boolean affectsConfigFile(IResourceDelta configFileDelta) { if ((configFileDelta.getKind() & (IResourceDelta.ADDED | IResourceDelta.REMOVED)) > 0) { return true; } if ((configFileDelta.getFlags() & (IResourceDelta.CONTENT | IResourceDelta.ENCODING | IResourceDelta.SYNC | IResourceDelta.TYPE | IResourceDelta.REPLACED)) > 0) { return true; } return false; } private boolean isRemovedOrClosed(IResourceDelta projectDelta) { if (projectDelta.getKind() == IResourceDelta.REMOVED) { return true; } if ((projectDelta.getFlags() & IResourceDelta.OPEN) > 0) { return !projectDelta.getResource().isAccessible(); } return false; } private boolean mayAffectOtherResourceManagers(IResourceDelta projectDelta) { if ((projectDelta.getKind() & (IResourceDelta.REMOVED | IResourceDelta.ADDED)) > 0) { return true; } if ((projectDelta.getFlags() & IResourceDelta.OPEN) > 0) { return !projectDelta.getResource().isAccessible(); } return false; } }; private LegacyTemplateRootRegistry legacyTemplateRootRegistry; public LegacyTemplateRootRegistry getLegacyTemplateRootRegistry() { if (legacyTemplateRootRegistry == null) { legacyTemplateRootRegistry = new LegacyTemplateRootRegistry(); } return legacyTemplateRootRegistry; } }