/******************************************************************************* * Copyright (c) 2005, 2006 Eclipse Foundation * 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: * Bjorn Freeman-Benson - initial implementation * Ward Cunningham - initial implementation *******************************************************************************/ package org.eclipse.eclipsemonkey; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.InvalidRegistryObjectException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.eclipsemonkey.language.IMonkeyLanguageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.ui.IStartup; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.activities.IActivityManager; import org.eclipse.ui.activities.IIdentifier; import org.eclipse.ui.activities.IIdentifierListener; import org.eclipse.ui.activities.IdentifierEvent; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; /** * The main plugin class to be used in the desktop. */ public class EclipseMonkeyPlugin extends AbstractUIPlugin implements IStartup { /** * Marker indicating the start of an Aptana Scripting script */ public static final String PUBLISH_BEFORE_MARKER = "--- Came wiffling through the eclipsey wood ---"; //$NON-NLS-1$ /** * Marker indicating the end of an Aptana Scripting script */ public static final String PUBLISH_AFTER_MARKER = "--- And burbled as it ran! ---"; //$NON-NLS-1$ // The shared instance. private static EclipseMonkeyPlugin plugin; private static Map<String, StoredScript> _scriptStore = new ConcurrentHashMap<String, StoredScript>(); private static Set<IScriptStoreListener> _storeListeners = new HashSet<IScriptStoreListener>(); private static Map<String, IMonkeyLanguageFactory> _languageStore = new ConcurrentHashMap<String, IMonkeyLanguageFactory>(); private static Map<String, Object> _scopeStore = new ConcurrentHashMap<String, Object>(); /** * All loaded languages * @return a map of loaded languages */ public Map<String, IMonkeyLanguageFactory> getLanguageStore() { return _languageStore; } /** * All loaded scripts * @return a map of loaded scripts */ public Map<String, StoredScript> getScriptStore() { return _scriptStore; } /** * All loaded scopes * @return a map of loaded scopes */ public Map<String, Object> getScopeStore() { return _scopeStore; } /** * This method is called upon plug-in activation * @param context * @throws Exception */ public void start(BundleContext context) throws Exception { super.start(context); plugin = this; } /** * This method is called when the plug-in is stopped * @param context * @throws Exception */ public void stop(BundleContext context) throws Exception { super.stop(context); plugin = null; } /** * Returns the shared instance. * @return EclipseMonkeyPlugin */ public static EclipseMonkeyPlugin getDefault() { return plugin; } /** * @param path * @return ImageDescriptor */ public static ImageDescriptor getImageDescriptor(String path) { return AbstractUIPlugin.imageDescriptorFromPlugin( "org.eclipse.eclipsemonkey", path); //$NON-NLS-1$ } private UpdateMonkeyActionsResourceChangeListener listener; /** * @see org.eclipse.ui.IStartup#earlyStartup() */ public void earlyStartup() { EclipseMonkeyPlugin eclipseMonkeyPlugin = EclipseMonkeyPlugin.getDefault(); if ( eclipseMonkeyPlugin == null ){ return; } listener = new UpdateMonkeyActionsResourceChangeListener(); ResourcesPlugin.getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.POST_CHANGE); loadScripts(); runStartupScripts(); } private void loadScripts() { String[] extensions = loadLanguageSupport(); String[] alternateScriptPaths = findAlternateScriptPaths(); listener.rescanAllFiles(extensions, alternateScriptPaths); UpdateMonkeyActionsResourceChangeListener.setExtensions(extensions); UpdateMonkeyActionsResourceChangeListener.createTheMonkeyMenu(); } /** * @param name * @param script */ public void addScript(String name, StoredScript script) { /* we are using the full file path as the key into the store * the consequence is that renames or moves are considered deletes and adds * is this what we want? */ Map<String, StoredScript> store = getScriptStore(); StoredScript oldScript = store.get(name); if (oldScript != null) { oldScript.metadata.unsubscribe(); } store.put(name, script); script.metadata.subscribe(); this.notifyScriptsChanged(); } /** * @param name */ public void removeScript(String name) { Map<String, StoredScript> store = getScriptStore(); StoredScript oldScript = store.remove(name); if (oldScript == null) return; oldScript.metadata.unsubscribe(); this.notifyScriptsChanged(); } /** * */ public void clearScripts() { for (Iterator<StoredScript> iter = getScriptStore().values().iterator(); iter.hasNext();) { StoredScript script = iter.next(); script.metadata.unsubscribe(); } getScriptStore().clear(); this.notifyScriptsChanged(); } /** * */ public void notifyScriptsChanged() { for (Iterator<IScriptStoreListener> iter = _storeListeners.iterator(); iter.hasNext();) { IScriptStoreListener element = iter.next(); element.storeChanged(); } } /** * @param listener */ public void addScriptStoreListener( IScriptStoreListener listener ) { _storeListeners.add(listener); } /** * @param listener */ public void removeScriptStoreListener( IScriptStoreListener listener ) { _storeListeners.remove(listener); } /** * runStartupScripts */ private void runStartupScripts() { PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { public void run() { for (Iterator<StoredScript> iter = getDefault().getScriptStore().values().iterator(); iter.hasNext();) { StoredScript script = iter.next(); String onLoadFunction = script.metadata.getOnLoadFunction(); if(onLoadFunction != null) { MenuRunMonkeyScript runner = new MenuRunMonkeyScript(script.scriptPath); try { runner.run(onLoadFunction, new Object[0]); } catch (RunMonkeyException e) { // Do nothing } } } } }); } private IIdentifierListener identifierListener = new IIdentifierListener() { public void identifierChanged(IdentifierEvent identifierEvent) { if ( identifierEvent.hasEnabledChanged() ) { IIdentifier identifier = identifierEvent.getIdentifier(); loadScripts(); } } }; private static final IActivityManager activityManager = PlatformUI.getWorkbench().getActivitySupport().getActivityManager(); private final boolean isActivityEnabled(IConfigurationElement element){ String extensionId = element.getAttribute("id"); //$NON-NLS-1$ String extensionPluginId = element.getNamespaceIdentifier(); String extensionString = null; if (extensionPluginId != null && extensionId != null && extensionPluginId.length() > 0 && extensionId.length() > 0) { extensionString = extensionPluginId + "/" + extensionId; //$NON-NLS-1$ } if ( extensionString != null) { final IIdentifier id = activityManager.getIdentifier(extensionString); if ( id != null ){ id.addIdentifierListener(identifierListener); return id.isEnabled(); } } return true; } /** * findAlternateScriptPaths * * @return List of alternate paths to use to find scripts */ private String[] findAlternateScriptPaths() { List<String> list = new ArrayList<String>(); IExtensionRegistry registry = Platform.getExtensionRegistry(); IExtensionPoint point = registry.getExtensionPoint("org.eclipse.eclipsemonkey.scriptpath"); //$NON-NLS-1$ if (point != null) { IExtension[] extensions = point.getExtensions(); for (int i = 0; i < extensions.length; i++) { IExtension extension = extensions[i]; IConfigurationElement[] configurations = extension.getConfigurationElements(); for (int j = 0; j < configurations.length; j++) { IConfigurationElement element = configurations[j]; if ( !isActivityEnabled(element)){ continue; } try { IExtension declaring = element.getDeclaringExtension(); // String declaringPluginID = declaring // .getDeclaringPluginDescriptor() // .getUniqueIdentifier(); String declaringPluginID = declaring.getNamespaceIdentifier(); String fullPath = element.getAttribute("directory"); //$NON-NLS-1$ Bundle b = Platform.getBundle(declaringPluginID); URL url = Platform.find(b, new Path(fullPath)); if(url != null) { try { URL localUrl = Platform.asLocalURL(url); if(localUrl != null) { String filename = localUrl.getFile(); list.add(filename); } } catch (IOException e) { e.printStackTrace(); } } } catch (InvalidRegistryObjectException x) { // ignore bad extensions } } } } return list.toArray(new String[0]); } /** * loadLanguageSupport * @return String[] */ private String[] loadLanguageSupport() { IExtensionRegistry registry = Platform.getExtensionRegistry(); IExtensionPoint point = registry.getExtensionPoint("org.eclipse.eclipsemonkey.language"); //$NON-NLS-1$ if (point != null) { IExtension[] extensions = point.getExtensions(); for (int i = 0; i < extensions.length; i++) { IExtension extension = extensions[i]; IConfigurationElement[] configurations = extension.getConfigurationElements(); for (int j = 0; j < configurations.length; j++) { IConfigurationElement element = configurations[j]; try { if ( !isActivityEnabled(element) ){ continue; } IExtension declaring = element.getDeclaringExtension(); // String declaring_plugin_id = declaring // .getDeclaringPluginDescriptor() // .getUniqueIdentifier(); String declaringPluginID = declaring.getNamespaceIdentifier(); String languageName = element.getAttribute("languageName"); //$NON-NLS-1$ String languageExtension = element.getAttribute("languageExtension"); //$NON-NLS-1$ String[] languageExtensions = null; if(languageExtension != null) { languageExtensions = languageExtension.split("\\,"); //$NON-NLS-1$ Object object = element.createExecutableExtension("class"); //$NON-NLS-1$ IMonkeyLanguageFactory langFactory = (IMonkeyLanguageFactory) object; for (int k = 0; k < languageExtensions.length; k++) { EclipseMonkeyPlugin.getDefault().getLanguageStore().put(languageExtensions[k], langFactory); } langFactory.init(declaringPluginID, languageName); } } catch (InvalidRegistryObjectException x) { // ignore bad extensions } catch (CoreException x) { // ignore bad extensions } } } } String[] extensions = (String []) EclipseMonkeyPlugin.getDefault().getLanguageStore().keySet().toArray(new String[0]); if(extensions == null) { return new String[0]; } else { return extensions; } } }