| /** |
| * Copyright (c) 2002-2012 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 - Initial API and implementation |
| */ |
| package org.eclipse.emf.ecore.plugin; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.lang.reflect.Method; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.PropertyResourceBundle; |
| import java.util.ResourceBundle; |
| import java.util.jar.JarFile; |
| import java.util.jar.Manifest; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| import java.util.zip.ZipEntry; |
| |
| import javax.xml.parsers.SAXParser; |
| import javax.xml.parsers.SAXParserFactory; |
| |
| import org.osgi.framework.BundleActivator; |
| import org.osgi.framework.BundleContext; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.DefaultHandler; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspaceRoot; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.ContributorFactorySimple; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IContributor; |
| import org.eclipse.core.runtime.IExtensionRegistry; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.RegistryFactory; |
| import org.eclipse.core.runtime.spi.IRegistryProvider; |
| import org.eclipse.core.runtime.spi.RegistryStrategy; |
| import org.eclipse.emf.common.CommonPlugin; |
| import org.eclipse.emf.common.EMFPlugin; |
| import org.eclipse.emf.common.util.ResourceLocator; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.common.util.WrappedException; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.impl.EPackageRegistryImpl; |
| import org.eclipse.emf.ecore.resource.URIConverter; |
| |
| |
| /** |
| * A collection of platform-neutral static utilities |
| * as well as Eclipse support utilities. |
| */ |
| public class EcorePlugin extends EMFPlugin |
| { |
| /** |
| * The singleton instance of the plugin. |
| */ |
| public static final EcorePlugin INSTANCE = new EcorePlugin(); |
| |
| /** |
| * Creates the singleton instance. |
| */ |
| private EcorePlugin() |
| { |
| super(new ResourceLocator[] {}); |
| } |
| |
| @Override |
| public ResourceLocator getPluginResourceLocator() |
| { |
| return plugin; |
| } |
| |
| /** |
| * Returns the platform resource map. |
| * <p> |
| * This map is from {@link String} to {@link URI}. |
| * It is the logical equivalent of the map implied by an {@link IWorkspaceRoot}: |
| * I.e., each entry in the map corresponds to |
| * an {@link org.eclipse.core.resources.IProject} |
| * that has a {@link org.eclipse.core.resources.IResource#getName name} |
| * and a location {@link org.eclipse.core.resources.IResource#getLocation location}; |
| * the name is the key |
| * and the location, interpreted as a {@link URI#createFileURI file URI}, is the value. |
| * This map is used to {@link #resolvePlatformResourcePath resolve} a platform resource path, |
| * and thereby supports relocatable projects in a manner that is transparently the same as an Eclipse workspace. |
| * </p> |
| * @return the platform resource map. |
| * @see #resolvePlatformResourcePath |
| */ |
| public static Map<String, URI> getPlatformResourceMap() |
| { |
| if (platformResourceMap == null) |
| { |
| platformResourceMap = new HashMap<String, URI>(); |
| } |
| return platformResourceMap; |
| } |
| |
| /** |
| * Resolves a platform resource path of the form <code>"/project/path"</code> |
| * against the platform resource map. |
| * <p> |
| * The first segment of the path, i.e., the <em>project name</em>, |
| * is used to get a URI from the {@link #getPlatformResourceMap() map}. |
| * If a URI results, the remaining segments are {@link URI#resolve(URI) resolved} against it |
| * and that is the result. |
| * Otherwise, the result is <code>null</code>. |
| * For example, given this mapping |
| *<pre> |
| * EcoreUtil.getPlatformResourceMap().put |
| * ("project", URI.createURI("file:///C:/location/")); |
| *</pre> |
| * the following transformation would result: |
| *<pre> |
| * /project/directory/file |
| * -> |
| * file:///C:/location/directory/file |
| *</pre> |
| * </p> |
| * @return the resolved URI or <code>null</code>. |
| */ |
| public static URI resolvePlatformResourcePath(String platformResourcePath) |
| { |
| if (platformResourceMap != null) |
| { |
| int index = platformResourcePath.indexOf("/", 1); |
| String rootContainerName = platformResourcePath.substring(1, index); |
| String relativeName = platformResourcePath.substring(index + 1); |
| URI rootContainerLocation = getPlatformResourceMap().get(rootContainerName); |
| if (rootContainerLocation != null) |
| { |
| return URI.createURI(relativeName).resolve(rootContainerLocation); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Handles recognized platform resource arguments and returns the stripped result. |
| * <p> |
| * Recognized arguments are of this form: |
| *<pre> |
| * -platformResource ( <project-name> <file-or-URI> )+ |
| *</pre> |
| * E.g., This these arguments |
| *<pre> |
| * -platformResource project file:///C:/location/ |
| *</pre> |
| * will produce this effect: |
| *<pre> |
| * EcoreUtil.getPlatformResourceMap().put |
| * ("project", URI.createURI("file:///C:/location/")); |
| *</pre> |
| * This mechanism supports relocatable projects outside of Eclipse. |
| * </p> |
| * @param arguments an array of "command line" options. |
| * @return the arguments stripped of those recognized as platform resource options. |
| */ |
| public static String [] handlePlatformResourceOptions(String [] arguments) |
| { |
| getPlatformResourceMap(); |
| |
| for (int i = 0; i < arguments.length; ++i) |
| { |
| if (arguments[i].equalsIgnoreCase("-platformResource")) |
| { |
| int start = i; |
| while (++i < arguments.length && !arguments[i].startsWith("-")) |
| { |
| String rootContainerName = arguments[i]; |
| if (++i < arguments.length) |
| { |
| String rootContainerLocation = arguments[i]; |
| |
| // This let's us test whether the string exists as a file. |
| // If not, we try as a URI. |
| // |
| URI uri; |
| File file = new File(rootContainerLocation); |
| if (file.isDirectory() || !file.exists() && file.getParent() != null && file.getParentFile().isDirectory()) |
| { |
| try |
| { |
| file = file.getCanonicalFile(); |
| } |
| catch (IOException exception) |
| { |
| throw new WrappedException(exception); |
| } |
| uri = URI.createFileURI(file.toString() + "/"); |
| } |
| else |
| { |
| uri = URI.createURI(rootContainerLocation); |
| } |
| |
| platformResourceMap.put(rootContainerName, uri); |
| } |
| } |
| |
| String [] remainingArguments = new String [arguments.length - (i - start)]; |
| System.arraycopy(arguments, 0, remainingArguments, 0, start); |
| System.arraycopy(arguments, i, remainingArguments, start, arguments.length - i); |
| return remainingArguments; |
| } |
| } |
| |
| return arguments; |
| } |
| |
| /** |
| * Returns a map from {@link EPackage#getNsURI() package namespace URI} (represented as a String) |
| * to the location of the GenModel containing a GenPackage for the package (represented as a {@link URI URI}). |
| * <p> |
| * It's implemented like this: |
| *<pre> |
| * return getEPackageNsURIToGenModelLocationMap(false); |
| *</pre> |
| * </p> |
| * @return a map from package namespace to GenModel location. |
| * @deprecated since 2.9; |
| * use {@link #getEPackageNsURIToGenModelLocationMap(boolean) getEPackageNsURItoGenModelLocationMap(true)} |
| * to get the locations in the target platform, |
| * or use {@link #getEPackageNsURIToGenModelLocationMap(boolean) getEPackageNsURItoGenModelLocationMap(false)} to get the legacy behavior, i.e., the locations in the installed environment. |
| * It's generally expected that all clients, will migrate to use the target platform. |
| */ |
| @Deprecated |
| public static Map<String, URI> getEPackageNsURIToGenModelLocationMap() |
| { |
| return getEPackageNsURIToGenModelLocationMap(false); |
| } |
| |
| /** |
| * Returns a map from {@link EPackage#getNsURI() package namespace URI} (represented as a String) |
| * to the location of the GenModel containing a GenPackage for the package (represented as a {@link URI URI}) |
| * for either the target platform or the environment itself. |
| * If there is no target platform, i.e., if the PDE is not installed, it defaults back to the environment. |
| * It's generally expected that an application using these URIs will also {@link URIConverter#getURIMap() register} the mappings returned by {@link #computePlatformURIMap(boolean)}. |
| * @param targetPlatform whether to get locations for the target platform or for the environment itself; the former is preferred. |
| * @return a map from package namespace to GenModel location. |
| * @see #computePlatformURIMap(boolean) |
| * @since 2.9 |
| */ |
| public static Map<String, URI> getEPackageNsURIToGenModelLocationMap(boolean targetPlatform) |
| { |
| if (!targetPlatform || !IS_RESOURCES_BUNDLE_AVAILABLE || !PDEHelper.IS_PDE_BUNDLE_AVAILABLE) |
| { |
| if (ePackageNsURIToGenModelLocationMap == null) |
| { |
| ePackageNsURIToGenModelLocationMap = new HashMap<String, URI>(); |
| } |
| return ePackageNsURIToGenModelLocationMap; |
| } |
| else |
| { |
| Map<String, URI> nsURIMap = new HashMap<String, URI>(); |
| try |
| { |
| PDEHelper.computeModels(null, nsURIMap); |
| } |
| catch (Exception exception) |
| { |
| INSTANCE.log(exception); |
| } |
| return nsURIMap; |
| } |
| } |
| |
| /** |
| * Computes a map from <code>platform:/resource/<plugin-location>/</code> {@link URI} to |
| * <code>platform:/plugin/<plugin-id>/</code> URI |
| * for each URI in the collection of the form <code>platform:/plugin/<plugin-id>/...</code>. |
| * This allows each plugin to be {@link org.eclipse.emf.ecore.resource.URIConverter#getURIMap() treated} |
| * as if it were a project in the workspace. |
| * If the workspace or {@link #getPlatformResourceMap() platform resource map} already contains a project for the plugin location, no such mapping is produced. |
| * In addition, when running stand alone and after invoking {@link ExtensionProcessor#process(ClassLoader) extension processing}, |
| * mappings from <code>platform:/plugin/<plugin-id>/</code> to the physical location of the plugin's archive or root folder are produced. |
| * This allows the URIs to be loaded from their proper physical location. |
| * @param uris a collections of {@link URI}s. |
| * @return a map from platform resource URI to platform plugin URI. |
| */ |
| public static Map<URI, URI> computePlatformResourceToPlatformPluginMap(Collection<URI> uris) |
| { |
| Map<URI, URI> result = new HashMap<URI, URI>(); |
| IWorkspaceRoot root = getWorkspaceRoot(); |
| if (root != null) |
| { |
| for (URI uri : uris) |
| { |
| if (uri.isPlatformPlugin()) |
| { |
| String pluginID = uri.segment(1); |
| if (!root.getProject(pluginID).isOpen()) |
| { |
| result.put(URI.createPlatformResourceURI(pluginID + "/", false), URI.createPlatformPluginURI(pluginID + "/", false)); |
| } |
| } |
| } |
| } |
| else if (platformResourceMap != null || ExtensionProcessor.platformPluginToLocationURIMap != null) |
| { |
| for (URI uri : uris) |
| { |
| if (uri.isPlatformPlugin()) |
| { |
| String pluginID = uri.segment(1); |
| if (platformResourceMap == null || !platformResourceMap.containsKey(pluginID)) |
| { |
| URI platformPluginURI = uri.trimSegments(uri.segmentCount() - 2).appendSegment(""); |
| URI platformResourceURI = URI.createPlatformResourceURI(platformPluginURI.segment(1), false).appendSegment(""); |
| result.put(platformResourceURI, platformPluginURI); |
| |
| if (ExtensionProcessor.platformPluginToLocationURIMap != null) |
| { |
| URI locationURI = ExtensionProcessor.platformPluginToLocationURIMap.get(platformPluginURI); |
| if (locationURI != null) |
| { |
| result.put(platformPluginURI, locationURI); |
| } |
| } |
| } |
| } |
| } |
| } |
| return result; |
| } |
| |
| private static Pattern bundleSymbolNamePattern; |
| private static byte [] NO_BYTES = new byte [0]; |
| |
| /** |
| * Computes a map from <code>platform:/plugin/<plugin-id>/</code> {@link URI} to |
| * <code>platform:/resource/<plugin-location>/</code> URI |
| * for each plugin project in the workspace or {@link #getPlatformResourceMap() platform resource map}. |
| * This allows each plugin from the runtime to be {@link org.eclipse.emf.ecore.resource.URIConverter#getURIMap() redirected} |
| * to its active version in the workspace or platform resource map. |
| * @return a map from plugin URIs to resource URIs. |
| * @see org.eclipse.emf.ecore.resource.URIConverter#getURIMap() |
| * @see URI |
| */ |
| public static Map<URI, URI> computePlatformPluginToPlatformResourceMap() |
| { |
| Map<URI, URI> result = new HashMap<URI, URI>(); |
| IWorkspaceRoot root = getWorkspaceRoot(); |
| if (root != null) |
| { |
| IProject [] projects = root.getProjects(); |
| if (projects != null) |
| { |
| String pluginID = null; |
| |
| class Handler extends DefaultHandler |
| { |
| public String pluginID; |
| |
| @Override |
| public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException |
| { |
| if ("".equals(uri) && "plugin".equals(localName)) |
| { |
| pluginID = attributes.getValue("id"); |
| } |
| throw new SAXException("Done"); |
| } |
| } |
| Handler handler = new Handler(); |
| |
| SAXParserFactory parserFactory= SAXParserFactory.newInstance(); |
| parserFactory.setNamespaceAware(true); |
| SAXParser parser = null; |
| |
| try |
| { |
| parser = parserFactory.newSAXParser(); |
| } |
| catch (Exception exception) |
| { |
| INSTANCE.log(exception); |
| } |
| |
| if (bundleSymbolNamePattern == null) |
| { |
| bundleSymbolNamePattern = Pattern.compile("^\\s*Bundle-SymbolicName\\s*:\\s*([^\\s;]*)\\s*(;.*)?$", Pattern.MULTILINE); |
| } |
| |
| byte [] bytes = NO_BYTES; |
| |
| for (int i = 0, size = projects.length; i < size; ++i) |
| { |
| IProject project = projects[i]; |
| if (project.isOpen()) |
| { |
| pluginID = null; |
| IFile manifest = project.getFile("META-INF/MANIFEST.MF"); |
| if (manifest.exists()) |
| { |
| InputStream inputStream = null; |
| try |
| { |
| inputStream = manifest.getContents(true); |
| int available = inputStream.available(); |
| if (bytes.length < available) |
| { |
| bytes = new byte [available]; |
| } |
| inputStream.read(bytes); |
| String contents = new String(bytes, "UTF-8"); |
| Matcher matcher = bundleSymbolNamePattern.matcher(contents); |
| if (matcher.find()) |
| { |
| pluginID = matcher.group(1); |
| } |
| } |
| catch (Exception exception) |
| { |
| INSTANCE.log(exception); |
| } |
| finally |
| { |
| if (inputStream != null) |
| { |
| try |
| { |
| inputStream.close(); |
| } |
| catch (IOException exception) |
| { |
| INSTANCE.log(exception); |
| } |
| } |
| } |
| } |
| else if (parser != null) |
| { |
| final IFile plugin = project.getFile("plugin.xml"); |
| if (plugin.exists()) |
| { |
| try |
| { |
| parser.parse(new InputSource(plugin.getContents(true)), handler); |
| } |
| catch (Exception exception) |
| { |
| if (handler.pluginID != null) |
| { |
| pluginID = handler.pluginID; |
| } |
| else |
| { |
| INSTANCE.log(exception); |
| } |
| } |
| } |
| } |
| |
| if (pluginID != null) |
| { |
| URI platformPluginURI = URI.createPlatformPluginURI(pluginID + "/", false); |
| URI platformResourceURI = URI.createPlatformResourceURI(project.getName() + "/", true); |
| result.put(platformPluginURI, platformResourceURI); |
| } |
| } |
| } |
| } |
| } |
| else if (platformResourceMap != null) |
| { |
| for (Map.Entry<String, URI> entry : platformResourceMap.entrySet()) |
| { |
| String pluginID = entry.getKey(); |
| URI platformPluginURI = URI.createPlatformPluginURI(pluginID, true).appendSegment(""); |
| URI platformResourceURI = URI.createPlatformResourceURI(pluginID, true).appendSegment(""); |
| result.put(platformPluginURI, platformResourceURI); |
| } |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Computes a map so that plugins in the workspace will override those in the target platform or the environment |
| * and so that plugins with Ecore and GenModels in the target platform or the environment will look like projects in the workspace. |
| * It's implemented like this: |
| *<pre> |
| * return computePlatformURIMap(false); |
| *</pre> |
| * @deprecated since 2.9; |
| * use {@link #computePlatformURIMap(boolean) computePlatformURIMap(true)} |
| * to get the mappings for the target platform, |
| * or use {@link #computePlatformURIMap(boolean) computePlatformURIMap(false)} to get the legacy behavior, i.e., the mappings for the installed environment. |
| * It's generally expected that all clients, will migrate to use the target platform. |
| * @return computes a map so that plugins in the workspace will override those in the environment |
| * and so that plugins with Ecore and GenModels will look like projects in the workspace. |
| * @see org.eclipse.emf.ecore.resource.URIConverter#getURIMap() |
| * @see #computePlatformPluginToPlatformResourceMap() |
| * @see #computePlatformResourceToPlatformPluginMap(Collection) |
| */ |
| @Deprecated |
| public static Map<URI, URI> computePlatformURIMap() |
| { |
| return computePlatformURIMap(false); |
| } |
| |
| /** |
| * Computes a map so that plugins in the workspace will override those in the target platform or the environment |
| * and so that plugins with Ecore and GenModels in the target platform or the environment will look like projects in the workspace, |
| * i.e., so that each plugin can be accessed via a logical <code>platform:/resource</code> URI |
| * equivalent to what would be used if the plugin were actually imported into the workspace. |
| * If there is no target platform, i.e., if the PDE is not installed, it defaults back to the environment |
| * as if <code>targetPlatform</code> were <code>false</code>. |
| * <p> |
| * If <code>targetPlatform</code> is <code>false</code>, it's computed from the environment like this: |
| *<pre> |
| result.putAll(computePlatformPluginToPlatformResourceMap()); |
| result.putAll(computePlatformResourceToPlatformPluginMap(new HashSet<URI>(EcorePlugin.getEPackageNsURIToGenModelLocationMap(false).values()))); |
| *</pre> |
| * If <code>targetPlatform</code> is <code>true</code>, it does essentially the same logical thing, |
| * however, it uses the PDE's target platform to determine the available plugins rather than the environment. |
| * The essential difference being that it produces results based on the physical location of all the non-workspace plugins in the PDE's target platform, |
| * rather than based on <code>platform:/plugin</code> URIs |
| * that always refer to plugins in the running environment. |
| * For example, suppose there is a jarred plugin with ID <code>org.example.model</code> in the target platform but not in the workspace |
| * that registers a generated model's GenModel at location <code>model/Example.genmodel</code>, |
| * the mapping from <code>platform:/resource/org.example.model/</code> to <code>archive:file:/<location-of-plugin-jar>!/</code> |
| * is produced. |
| * If instead that same plugin were actually in the workspace, |
| * the mapping from <code>platform:/plugin/org.example.model/</code> to <code>platform/resource/org.example.model/</code> |
| * would be produced. |
| * </p> |
| * <p> |
| * The expected usage of this API is to initialize a resource set's URI converter's {@link URIConverter#getURIMap()} as follows: |
| *<pre> |
| * resourceSet.getURIConverter().getURIMap().putAll(EcorePlugin.computePlatformURIMap(true)); |
| *</pre> |
| * This is particularly important when working with Ecore and GenModel resources because they often have references to models in the environment. |
| * </p> |
| * @param targetPlatform whether to compute locations for the target platform or for the environment itself; the former is preferred. |
| * @return computes a map so that plugins in the workspace will override those in the target platform of the environment |
| * and so that plugins in the target platform or environment with Ecore and GenModels will look like projects in the workspace. |
| * @see org.eclipse.emf.ecore.resource.URIConverter#getURIMap() |
| * @see #computePlatformPluginToPlatformResourceMap() |
| * @see #computePlatformResourceToPlatformPluginMap(Collection) |
| * @see #getEPackageNsURIToGenModelLocationMap(boolean) |
| * @since 2.9 |
| */ |
| public static Map<URI, URI> computePlatformURIMap(boolean targetPlatform) |
| { |
| Map<URI, URI> result = new HashMap<URI, URI>(); |
| if (!targetPlatform || !IS_RESOURCES_BUNDLE_AVAILABLE || !PDEHelper.IS_PDE_BUNDLE_AVAILABLE) |
| { |
| result.putAll(computePlatformPluginToPlatformResourceMap()); |
| result.putAll(computePlatformResourceToPlatformPluginMap(new HashSet<URI>(EcorePlugin.getEPackageNsURIToGenModelLocationMap(false).values()))); |
| } |
| else |
| { |
| try |
| { |
| Map<URI, URI> pluginMap = new HashMap<URI, URI>(); |
| PDEHelper.computeModels(pluginMap, null); |
| result.putAll(pluginMap); |
| } |
| catch (Exception e) |
| { |
| INSTANCE.log(e); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * The platform resource map. |
| * @see #getPlatformResourceMap |
| */ |
| private static Map<String, URI> platformResourceMap; |
| |
| /** |
| * The map from package namespace URIs to the location of the GenModel for that package. |
| * @see #getPlatformResourceMap |
| */ |
| private static Map<String, URI> ePackageNsURIToGenModelLocationMap; |
| |
| /** |
| * A plugin implementation that handles Ecore plugin registration. |
| * @see #startup() |
| */ |
| static public class Implementation extends EclipsePlugin |
| { |
| /** |
| * Creates the singleton instance. |
| */ |
| public Implementation() |
| { |
| super(); |
| plugin = this; |
| } |
| |
| /** |
| * Starts up this plugin by reading some extensions and populating the relevant registries. |
| * <p> |
| * The {@link org.eclipse.emf.ecore.EPackage.Registry#INSTANCE global} package registry |
| * is populated by plugin registration of the form: |
| *<pre> |
| * <extension point="org.eclipse.emf.ecore.generated_package" > |
| * <package uri="http://www.example.org/abc/Abc.ecore" class="org.example.abc.AbcPackage"/> |
| * <extension> |
| *</pre> |
| * </p> |
| * The URI is arbitrary but an absolute URI is recommended. |
| * Provision for access to the serialized model via <code>"http:"</code> is encouraged. |
| * <p> |
| * The {@link org.eclipse.emf.ecore.resource.Resource.Factory.Registry#INSTANCE global} resource factory registry's |
| * {@link org.eclipse.emf.ecore.resource.Resource.Factory.Registry#getExtensionToFactoryMap() extension} map |
| * is populated by plugin registration of the form: |
| *<pre> |
| * <extension point="org.eclipse.emf.ecore.extension_parser"> |
| * <parser type="abc" class="org.example.abc.util.AbcResourceFactoryImpl"/> |
| * <extension> |
| *</pre> |
| * </p> |
| * <p> |
| * The {@link org.eclipse.emf.ecore.resource.Resource.Factory.Registry#INSTANCE global} resource factory registry's |
| * {@link org.eclipse.emf.ecore.resource.Resource.Factory.Registry#getProtocolToFactoryMap() protocol} map |
| * is populated by plugin registration of the form: |
| *<pre> |
| * <extension point="org.eclipse.emf.ecore.protocol_parser" > |
| * <parser protocolName="abc" class="org.example.abc.util.AbcResourceFactoryImpl"/> |
| * <extension> |
| *</pre> |
| * </p> |
| * <p> |
| * The {@link org.eclipse.emf.ecore.resource.URIConverter#URI_MAP global} URI map |
| * is populated by plugin registration of the form: |
| *<pre> |
| * <extension point="org.eclipse.emf.ecore.uri_mapping" > |
| * <mapping source="//special/" target="special/"/> |
| * <extension> |
| *</pre> |
| * If the target is relative, it is resolved against the plugin's installed location, |
| * resulting in a URI of the form: |
| *<pre> |
| * platform:/plugin/plugin-name_1.2.3/... |
| *</pre> |
| * The above registration would map |
| *<pre> |
| * //special/a/b.c |
| *</pre> |
| * to |
| *<pre> |
| * platform:/plugin/plugin-name_1.2.3/special/a/b.c |
| *</pre> |
| * </p> |
| * @throws Exception if there is a show stopping problem. |
| */ |
| @Override |
| public void start(BundleContext context) throws Exception |
| { |
| super.start(context); |
| ExtensionProcessor.internalProcessExtensions(); |
| |
| } |
| |
| /** |
| * @since 2.10 |
| */ |
| public static final class Activator extends EMFPlugin.OSGiDelegatingBundleActivator |
| { |
| @Override |
| protected BundleActivator createBundle() |
| { |
| return new Implementation(); |
| } |
| } |
| } |
| |
| /** |
| * A class containing a single utility method for processing extensions. |
| * @see ExtensionProcessor#process(ClassLoader) |
| * @since 2.9 |
| */ |
| public static class ExtensionProcessor |
| { |
| private static Map<URI, URI> platformPluginToLocationURIMap; |
| |
| |
| /** |
| * This explicitly triggers processing of all plugin.xml registered extensions. |
| * It does nothing if invoked in the context of an Eclipse application as processing of extensions happens implicitly during {@link Implementation#start(BundleContext) bundle activation}. |
| * As such this method is useful only in non-Eclipse applications to ensure that plugin.xml registrations are processed just as they are in an Eclipse application. |
| * The exploit this mechanism, the classpath of the application must minimally include <code>org.eclipse.equinox.common</code>, <code>org.eclipse.equinox.registry</code>, and <code>org.eclipse.osgi</code> |
| * <p> |
| * This method creates a registry if {@link RegistryFactory#getRegistry() one does not already exist}. |
| * It will first consider all entries on the classpath as provided by {@link System#getProperty(String) System.getProperty("java.class.path")} |
| * to determine if there are any folder entries whose parent folder contains a plugin.xml; |
| * such entries are common when launching a Java application from Eclipse at development time. |
| * In that case, the class loader is not used and only registrations for entries of the classpath are considered. |
| * Otherwise, the class loader is used to find all plugin.xml resources and only those entries are considered. |
| * </p> |
| * <p> |
| * </p> |
| * @param classLoader the class loader used to locate plugin.xml resources; it may be null in which class the {@link Thread#getContextClassLoader() current thread's context class loader} is used, if necessary. |
| * @since 2.9 |
| */ |
| public static synchronized void process(ClassLoader classLoader) |
| { |
| // Ensure processing only happens once and only when not running an Eclipse application. |
| // |
| if (platformPluginToLocationURIMap == null && !IS_ECLIPSE_RUNNING) |
| { |
| platformPluginToLocationURIMap = new HashMap<URI, URI>(); |
| |
| // If there isn't already a registry... |
| // |
| IExtensionRegistry registry = RegistryFactory.getRegistry(); |
| if (registry == null) |
| { |
| // Create a new registry. |
| // |
| final IExtensionRegistry newRegistry = |
| RegistryFactory.createRegistry |
| (new RegistryStrategy(null, null) |
| { |
| @Override |
| public void log(IStatus status) |
| { |
| INSTANCE.log(status); |
| } |
| |
| @Override |
| public String translate(String key, ResourceBundle resources) |
| { |
| try |
| { |
| // The org.eclipse.core.resources bundle has keys that aren't translated, so avoid exception propagation. |
| // |
| return super.translate(key, resources); |
| } |
| catch (Throwable throwable) |
| { |
| return key; |
| } |
| } |
| }, |
| null, |
| null); |
| |
| // Make the new registry the default. |
| // |
| try |
| { |
| RegistryFactory.setDefaultRegistryProvider |
| (new IRegistryProvider() |
| { |
| public IExtensionRegistry getRegistry() |
| { |
| return newRegistry; |
| } |
| }); |
| } |
| catch (CoreException exception) |
| { |
| INSTANCE.log(exception); |
| } |
| |
| registry = newRegistry; |
| } |
| |
| // If there is no class loader provided, use the thread's context class loader. |
| // |
| if (classLoader == null) |
| { |
| classLoader = Thread.currentThread().getContextClassLoader(); |
| } |
| |
| // Process all the URIs for plugin.xml files from the class path or the class loader. |
| // |
| for (URI pluginXMLURI : getPluginXMLs(classLoader)) |
| { |
| // Construct the URI for the manifest and check that it exists... |
| // |
| URI pluginLocation = pluginXMLURI.trimSegments(1); |
| URI manifestURI = pluginLocation.appendSegments(new String[] { "META-INF", "MANIFEST.MF" }); |
| if (URIConverter.INSTANCE.exists(manifestURI, null)) |
| { |
| InputStream manifestInputStream = null; |
| try |
| { |
| // Read the manifest. |
| // |
| manifestInputStream = URIConverter.INSTANCE.createInputStream(manifestURI); |
| Manifest manifest = new Manifest(manifestInputStream); |
| java.util.jar.Attributes mainAttributes = manifest.getMainAttributes(); |
| |
| // Determine the bundle's name |
| // |
| String bundleSymbolicName = mainAttributes.getValue("Bundle-SymbolicName"); |
| if (bundleSymbolicName != null) |
| { |
| // Split out the OSGi noise. |
| // |
| bundleSymbolicName = bundleSymbolicName.split(";")[0].trim(); |
| |
| // Compute the map entry from platform:/plugin/<bundleSymbolicName>/ to the location URI's root. |
| // |
| URI logicalPlatformPluginURI = URI.createPlatformPluginURI(bundleSymbolicName, true).appendSegment(""); |
| URI pluginLocationURI = pluginLocation.isArchive() ? pluginLocation : pluginLocation.appendSegment(""); |
| platformPluginToLocationURIMap.put(logicalPlatformPluginURI, pluginLocationURI); |
| |
| // Also create a global URI mapping so that any uses of platform:/plugin/<plugin-ID> will map to the physical location of that plugin. |
| // This ensures that registered URI mappings that use a relative URI into the plugin will work correctly. |
| // |
| URIConverter.URI_MAP.put(logicalPlatformPluginURI, pluginLocationURI); |
| |
| // Find the localization resource bundle, if there is one. |
| // |
| String bundleLocalization = mainAttributes.getValue("Bundle-Localization"); |
| ResourceBundle resourceBundle = null; |
| if (bundleLocalization != null) |
| { |
| bundleLocalization += ".properties"; |
| InputStream bundleLocalizationInputStream = URIConverter.INSTANCE.createInputStream(pluginLocation.appendSegment(bundleLocalization)); |
| resourceBundle = new PropertyResourceBundle(bundleLocalizationInputStream); |
| bundleLocalizationInputStream.close(); |
| } |
| |
| // Add the contribution. |
| // |
| InputStream pluginXMLInputStream = URIConverter.INSTANCE.createInputStream(pluginXMLURI); |
| IContributor contributor = ContributorFactorySimple.createContributor(bundleSymbolicName); |
| registry.addContribution(pluginXMLInputStream, contributor, false, bundleSymbolicName, resourceBundle, null); |
| } |
| } |
| catch (IOException exception) |
| { |
| INSTANCE.log(exception); |
| } |
| } |
| } |
| |
| // Process the extension for the registry. |
| // |
| ExtensionProcessor.internalProcessExtensions(); |
| } |
| } |
| |
| /** |
| * Read all the registered extensions for Ecore's extension points. |
| */ |
| private static void internalProcessExtensions() |
| { |
| new RegistryReader |
| (RegistryFactory.getRegistry(), |
| EcorePlugin.INSTANCE.getSymbolicName(), |
| PACKAGE_REGISTRY_IMPLEMENTATION_PPID) |
| { |
| IConfigurationElement previous; |
| |
| @Override |
| protected boolean readElement(IConfigurationElement element) |
| { |
| if (element.getName().equals("registry")) |
| { |
| String implementationClass = element.getAttribute("class"); |
| if (implementationClass == null) |
| { |
| logMissingAttribute(element, "class"); |
| } |
| else |
| { |
| if (defaultRegistryImplementation != null) |
| { |
| if (previous != null) |
| { |
| INSTANCE.log("Both '" + previous.getContributor().getName() + "' and '" + element.getContributor().getName() + "' register a package registry implementation"); |
| } |
| if (defaultRegistryImplementation instanceof EPackageRegistryImpl.Delegator) |
| { |
| return false; |
| } |
| } |
| try |
| { |
| defaultRegistryImplementation = (EPackage.Registry)element.createExecutableExtension("class"); |
| previous = element; |
| } |
| catch (CoreException exception) |
| { |
| INSTANCE.log(exception); |
| } |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| }.readRegistry(); |
| |
| new GeneratedPackageRegistryReader(getEPackageNsURIToGenModelLocationMap(false)).readRegistry(); |
| new DynamicPackageRegistryReader().readRegistry(); |
| new FactoryOverrideRegistryReader().readRegistry(); |
| new ExtensionParserRegistryReader().readRegistry(); |
| new ProtocolParserRegistryReader().readRegistry(); |
| new ContentParserRegistryReader().readRegistry(); |
| new ContentHandlerRegistryReader().readRegistry(); |
| new URIMappingRegistryReader().readRegistry(); |
| new ValidationDelegateRegistryReader().readRegistry(); |
| new SettingDelegateFactoryRegistryReader().readRegistry(); |
| new InvocationDelegateFactoryRegistryReader().readRegistry(); |
| new QueryDelegateFactoryRegistryReader().readRegistry(); |
| new ConversionDelegateFactoryRegistryReader().readRegistry(); |
| new AnnotationValidatorRegistryReader().readRegistry(); |
| } |
| } |
| |
| /** |
| * Determine all the available plugin.xml resources. |
| */ |
| private static List<URI> getPluginXMLs(ClassLoader classLoader) |
| { |
| List<URI> result = new ArrayList<URI>(); |
| |
| String classpath = null; |
| try |
| { |
| // Try to get the classpath from the class loader. |
| // |
| Method method = classLoader.getClass().getMethod("getClassPath", (Class<?>) null); |
| if (method != null) |
| { |
| classpath = (String) method.invoke(classLoader, (Object) null); |
| } |
| } |
| catch (Throwable throwable) |
| { |
| // Failing thet, get it from the system properties. |
| // |
| classpath = System.getProperty("java.class.path"); |
| } |
| |
| // Keep track of whether we find any plugin.xml in the parent of a folder on the classpath, i.e., whether we're in development mode with bin folders on the classpath. |
| // |
| boolean nonClasspathXML = false; |
| |
| // If we have a classpath to use... |
| // |
| if (classpath != null) |
| { |
| // Split out the entries on the classpath. |
| // |
| for (String classpathEntry: classpath.split(File.pathSeparator)) |
| { |
| classpathEntry = classpathEntry.trim(); |
| |
| // Determine if the entry is a folder or an archive file. |
| // |
| File file = new File(classpathEntry); |
| if (file.isDirectory()) |
| { |
| // Determine if there is a plugin.xml at the root of the folder. |
| // |
| File pluginXML = new File(file, "plugin.xml"); |
| if (!pluginXML.exists()) |
| { |
| // If not, check if there is one in the parent folder. |
| // |
| pluginXML = new File(file.getParentFile(), "plugin.xml"); |
| if (pluginXML.isFile()) |
| { |
| // If there is, then we have plugin.xml files that aren't on the classpath. |
| // |
| nonClasspathXML = true; |
| } |
| else |
| { |
| // Otherwise this is bogus too. |
| // |
| pluginXML = null; |
| } |
| } |
| |
| // If we found a plugin.xml, create a URI for it. |
| // |
| if (pluginXML != null) |
| { |
| result.add(URI.createFileURI(pluginXML.getPath())); |
| } |
| } |
| else if (file.isFile()) |
| { |
| // The file must be a jar... |
| // |
| JarFile jarFile = null; |
| try |
| { |
| // Look for a plugin.xml entry... |
| // |
| jarFile = new JarFile(classpathEntry); |
| ZipEntry entry = jarFile.getEntry("plugin.xml"); |
| if (entry != null) |
| { |
| // If we find one, create a URI for it. |
| // |
| result.add(URI.createURI("archive:" + URI.createFileURI(classpathEntry) + "!/" + entry)); |
| } |
| } |
| catch (IOException exception) |
| { |
| // Ignore. |
| } |
| finally |
| { |
| if (jarFile != null) |
| { |
| try |
| { |
| jarFile.close(); |
| } |
| catch (IOException exception) |
| { |
| INSTANCE.log(exception); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| // If we didn't find any non-classpath plugin.xml files, use the class loader to enumerate all the plugin.xml files. |
| // This is more reliable given the possibility of specialized class loader behavior. |
| // |
| if (!nonClasspathXML) |
| { |
| result.clear(); |
| try |
| { |
| for (Enumeration<URL> resources = classLoader.getResources("plugin.xml"); resources.hasMoreElements(); ) |
| { |
| // Create a URI for each plugin.xml found by the class loader. |
| // |
| URL url = resources.nextElement(); |
| result.add(URI.createURI(url.toURI().toString())); |
| } |
| } |
| catch (IOException exception) |
| { |
| INSTANCE.log(exception); |
| } |
| catch (URISyntaxException exception) |
| { |
| INSTANCE.log(exception); |
| } |
| } |
| |
| return result; |
| } |
| |
| @Override |
| public String getSymbolicName() |
| { |
| ResourceLocator resourceLocator = getPluginResourceLocator(); |
| if (resourceLocator instanceof InternalEclipsePlugin) |
| { |
| return ((InternalEclipsePlugin)resourceLocator).getSymbolicName(); |
| } |
| else |
| { |
| return "org.eclipse.emf.ecore"; |
| } |
| } |
| |
| /** |
| * The default registry implementation singleton. |
| */ |
| private static EPackage.Registry defaultRegistryImplementation; |
| |
| /** |
| * Returns the default registry implementation singleton. |
| * @return the default registry implementation singleton. |
| */ |
| public static EPackage.Registry getDefaultRegistryImplementation() |
| { |
| return defaultRegistryImplementation; |
| } |
| |
| /** |
| * Returns the Eclipse plugin singleton. |
| * @return the plugin singleton. |
| */ |
| public static Implementation getPlugin() |
| { |
| return plugin; |
| } |
| |
| /** |
| * The plugin singleton |
| */ |
| private static Implementation plugin; |
| |
| /** |
| * The workspace root. |
| * @see #getWorkspaceRoot |
| */ |
| private static IWorkspaceRoot workspaceRoot; |
| |
| /** |
| * Returns the workspace root, or <code>null</code>, if the runtime environment is stand-alone. |
| * @return the workspace root, or <code>null</code>. |
| */ |
| public static IWorkspaceRoot getWorkspaceRoot() |
| { |
| if (workspaceRoot == null && IS_RESOURCES_BUNDLE_AVAILABLE && System.getProperty("org.eclipse.emf.ecore.plugin.EcorePlugin.doNotLoadResourcesPlugin") == null) |
| { |
| workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); |
| } |
| return workspaceRoot; |
| } |
| |
| private static class PDEHelper |
| { |
| private static final Method PLUGIN_MODEL_BASE_GET_BUNDLE_DESCRIPTION_METHOD; |
| private static final Method PLUGIN_MODEL_BASE_GET_UNDERLYING_RESOURCE_METHOD; |
| private static final Method PLUGIN_MODEL_BASE_GET_INSTALL_LOCATION_METHOD; |
| private static final Method PLUGIN_MODEL_BASE_GET_EXTENSIONS_METHOD; |
| private static final Method PLUGIN_REGISTRY_GET_ACTIVE_MODELS_METHOD; |
| private static final Method BUNDLE_DESCRIPTION_GET_SYMBOLIC_NAME_METHOD; |
| private static final Method EXTENSIONS_GET_EXTENSIONS_METHOD; |
| private static final Method PLUGIN_EXTENSION_GET_POINT_METHOD; |
| private static final Method PLUGIN_EXTENSION_GET_CHILDREN_METHOD; |
| private static final Class<?> PLUGIN_ELEMENT_CLASS; |
| private static final Method PLUGIN_ELEMENT_GET_ATTRIBUTE_METHOD; |
| private static final Method PLUGIN_ATTRIBUTE_GET_VALUE_METHOD; |
| private static final boolean IS_PDE_BUNDLE_AVAILABLE; |
| |
| static |
| { |
| Method pluginModelBaseGetBundleDescriptionMethod = null; |
| Method pluginModelBaseGetUnderlyingResourceMethod = null; |
| Method pluginModelBaseGetInstallLocationMethod = null; |
| Method pluginModelBaseGetExtensionsMethod = null; |
| Method pluginRegistryGetActiveModelsMethod = null; |
| Method bundleDescriptionGetSymbolicNameMethod = null; |
| Method extensionsGetExtensionsMethod = null; |
| Method pluginExtensionGetPointMethod = null; |
| Method pluginExtensionGetChildrenMethod = null; |
| Class<?> pluginElementClass = null; |
| Method pluginElementGetAttributeMethod = null; |
| Method pluginAttributeGetValueMethod = null; |
| boolean isPDEBundleAvailable = false; |
| |
| try |
| { |
| Class<?> pluginModelBaseClass = CommonPlugin.loadClass("org.eclipse.pde.core", "org.eclipse.pde.core.plugin.IPluginModelBase"); |
| pluginModelBaseGetBundleDescriptionMethod = pluginModelBaseClass.getMethod("getBundleDescription"); |
| pluginModelBaseGetUnderlyingResourceMethod = pluginModelBaseClass.getMethod("getUnderlyingResource"); |
| pluginModelBaseGetInstallLocationMethod = pluginModelBaseClass.getMethod("getInstallLocation"); |
| pluginModelBaseGetExtensionsMethod = pluginModelBaseClass.getMethod("getExtensions"); |
| Class<?> pluginRegistryClass = CommonPlugin.loadClass("org.eclipse.pde.core", "org.eclipse.pde.core.plugin.PluginRegistry"); |
| pluginRegistryGetActiveModelsMethod = pluginRegistryClass.getMethod("getActiveModels", boolean.class); |
| Class<?> bundleDescriptionClass = CommonPlugin.loadClass("org.eclipse.pde.core", "org.eclipse.osgi.service.resolver.BundleDescription"); |
| bundleDescriptionGetSymbolicNameMethod = bundleDescriptionClass.getMethod("getSymbolicName"); |
| Class<?> extensionsClass = CommonPlugin.loadClass("org.eclipse.pde.core", "org.eclipse.pde.core.plugin.IExtensions"); |
| extensionsGetExtensionsMethod = extensionsClass.getMethod("getExtensions"); |
| Class<?> pluginExtensionClass = CommonPlugin.loadClass("org.eclipse.pde.core", "org.eclipse.pde.core.plugin.IPluginExtension"); |
| pluginExtensionGetPointMethod = pluginExtensionClass.getMethod("getPoint"); |
| pluginExtensionGetChildrenMethod = pluginExtensionClass.getMethod("getChildren"); |
| pluginElementClass = CommonPlugin.loadClass("org.eclipse.pde.core", "org.eclipse.pde.core.plugin.IPluginElement"); |
| pluginElementGetAttributeMethod = pluginElementClass.getMethod("getAttribute", String.class); |
| Class<?> pluginAttributeClass = CommonPlugin.loadClass("org.eclipse.pde.core", "org.eclipse.pde.core.plugin.IPluginAttribute"); |
| pluginAttributeGetValueMethod = pluginAttributeClass.getMethod("getValue"); |
| isPDEBundleAvailable = true; |
| } |
| catch (Throwable exception) |
| { |
| // Ignore. |
| } |
| |
| PLUGIN_MODEL_BASE_GET_BUNDLE_DESCRIPTION_METHOD = pluginModelBaseGetBundleDescriptionMethod; |
| PLUGIN_MODEL_BASE_GET_UNDERLYING_RESOURCE_METHOD = pluginModelBaseGetUnderlyingResourceMethod; |
| PLUGIN_MODEL_BASE_GET_INSTALL_LOCATION_METHOD = pluginModelBaseGetInstallLocationMethod; |
| PLUGIN_MODEL_BASE_GET_EXTENSIONS_METHOD = pluginModelBaseGetExtensionsMethod; |
| PLUGIN_REGISTRY_GET_ACTIVE_MODELS_METHOD = pluginRegistryGetActiveModelsMethod; |
| BUNDLE_DESCRIPTION_GET_SYMBOLIC_NAME_METHOD = bundleDescriptionGetSymbolicNameMethod; |
| EXTENSIONS_GET_EXTENSIONS_METHOD = extensionsGetExtensionsMethod; |
| PLUGIN_EXTENSION_GET_POINT_METHOD = pluginExtensionGetPointMethod; |
| PLUGIN_EXTENSION_GET_CHILDREN_METHOD = pluginExtensionGetChildrenMethod; |
| PLUGIN_ELEMENT_CLASS = pluginElementClass; |
| PLUGIN_ELEMENT_GET_ATTRIBUTE_METHOD = pluginElementGetAttributeMethod; |
| PLUGIN_ATTRIBUTE_GET_VALUE_METHOD = pluginAttributeGetValueMethod; |
| IS_PDE_BUNDLE_AVAILABLE = isPDEBundleAvailable; |
| } |
| |
| private static Object invoke(Object object, Method method, Object... arguments) |
| { |
| try |
| { |
| return method.invoke(object, arguments); |
| } |
| catch (Exception exception) |
| { |
| return null; |
| } |
| } |
| |
| private static void computeModels(Map<URI, URI> pluginMap, Map<String, URI> nsURIMap) |
| { |
| // Cache the workspace for use in the loop. |
| // |
| IWorkspaceRoot root = getWorkspaceRoot(); |
| |
| // Iterate over all the active models in the workspace and target platform. |
| // |
| // IPluginModelBase[] activeModels = PluginRegistry.getActiveModels(false); |
| // |
| Object[] activeModels = (Object[])invoke(null, PLUGIN_REGISTRY_GET_ACTIVE_MODELS_METHOD, Boolean.FALSE); |
| LOOP: |
| for (Object activeModel : activeModels) |
| { |
| // Determine the symbolic name, underlying resource, if any, and the install location. |
| // |
| // BundleDescription bundleDescription = activeModel.getBundleDescription(); |
| // String symbolicName = bundleDescription.getSymbolicName(); |
| // IResource underlyingResource = activeModel.getUnderlyingResource(); |
| // String installLocation = activeModel.getInstallLocation(); |
| // |
| Object bundleDescription = invoke(activeModel, PLUGIN_MODEL_BASE_GET_BUNDLE_DESCRIPTION_METHOD); |
| String symbolicName = (String)invoke(bundleDescription, BUNDLE_DESCRIPTION_GET_SYMBOLIC_NAME_METHOD); |
| IResource underlyingResource = (IResource)invoke(activeModel, PLUGIN_MODEL_BASE_GET_UNDERLYING_RESOURCE_METHOD); |
| String installLocation = (String)invoke(activeModel, PLUGIN_MODEL_BASE_GET_INSTALL_LOCATION_METHOD); |
| |
| // The URI for the location is determined from the underlying resource or the install location, with preference to the former if available. |
| // |
| URI location = null; |
| if (underlyingResource != null) |
| { |
| // If there is an underlying resource, use the platform resource URI referencing the project in the workspace as the location. |
| // |
| location = URI.createPlatformResourceURI(underlyingResource.getProject().getFullPath().toString(), true); |
| } |
| else if (installLocation != null) |
| { |
| // Otherwise, the install location in the file system is used... |
| // |
| File file = new File(installLocation); |
| if (file.isDirectory()) |
| { |
| // If the file is a directory, create a file URI for that directory. |
| // |
| location = URI.createFileURI(installLocation); |
| } |
| else |
| { |
| // Otherwise, the location must be an archive, create an archive URI for the file URI of the jar. |
| // |
| location = URI.createURI("archive:" + URI.createFileURI(installLocation) + "!/"); |
| } |
| } |
| |
| // If we're able to compute a location... |
| // |
| if (location != null) |
| { |
| // The logical URI will be computed when we need it to deal with generated package extension points. |
| // |
| URI logicalLocation = null; |
| |
| // Iterate over the plugin's extensions... |
| // |
| // IExtensions extensions = activeModel.getExtensions(); |
| // IPluginExtension[] pluginExtensions = extensions.getExtensions(); |
| // |
| Object extensions = invoke(activeModel, PLUGIN_MODEL_BASE_GET_EXTENSIONS_METHOD); |
| Object[] pluginExtensions = (Object[])invoke(extensions, EXTENSIONS_GET_EXTENSIONS_METHOD); |
| for (Object pluginExtension : pluginExtensions) |
| { |
| // Consider only the generated package extension points. |
| // |
| // String point = pluginExtension.getPoint(); |
| // |
| String point = (String)invoke(pluginExtension, PLUGIN_EXTENSION_GET_POINT_METHOD); |
| |
| // Process both generated and dynamic extension points. |
| // |
| boolean isGeneratedPackage = "org.eclipse.emf.ecore.generated_package".equals(point); |
| if (isGeneratedPackage || "org.eclipse.emf.ecore.dynamic_package".equals(point)) |
| { |
| // Iterate over the child elements, i.e., the <package> elements, of the generated package extension point... |
| // |
| // IPluginObject[] children = pluginExtension.getChildren(); |
| // |
| Object[] children = (Object[])invoke(pluginExtension, PLUGIN_EXTENSION_GET_CHILDREN_METHOD); |
| for (Object child : children) |
| { |
| // if (child instanceof IPluginElement) |
| // |
| if (PLUGIN_ELEMENT_CLASS.isInstance(child)) |
| { |
| // If the the uri and the genModel attributes are present... |
| // |
| // IPluginElement pluginElement = (IPluginElement)child; |
| // IPluginAttribute uri = pluginElement.getAttribute("uri"); |
| // IPluginAttribute genModel = pluginElement.getAttribute("genModel"); |
| // |
| Object uri = invoke(child, PLUGIN_ELEMENT_GET_ATTRIBUTE_METHOD, "uri"); |
| Object genModel = invoke(child, PLUGIN_ELEMENT_GET_ATTRIBUTE_METHOD, isGeneratedPackage ? "genModel" : "location"); |
| if (uri != null && genModel != null) |
| { |
| // We need the logical location of the plugin, so if we haven't computed it already, do so now.. |
| // This creates folder mappings as a side-effect. |
| // |
| if (logicalLocation == null) |
| { |
| // We'll always want to redirect the platform plugin URI to the platform resource URI for this plugin... |
| // |
| URI platformPluginURI = URI.createPlatformPluginURI(symbolicName, true).appendSegment(""); |
| if (location.isPlatformResource()) |
| { |
| // If we're computing the plugin map and the physical location is in the workspace, map the platform plugin URI to the platform resource URI of the workspace project. |
| // |
| if (pluginMap != null) |
| { |
| pluginMap.put(platformPluginURI, location.appendSegment("")); |
| } |
| |
| // The physical location is also the logical location. |
| // |
| logicalLocation = location; |
| } |
| else |
| { |
| // The logical location will be a platform resource URI as if the external plugin were in the workspace. |
| // |
| logicalLocation = URI.createPlatformResourceURI(symbolicName, true); |
| |
| // We'll create a folder mapping for this logical location... |
| // |
| URI resourceURI = logicalLocation.appendSegment(""); |
| |
| // But only if an actual project doesn't already exist in the workspace. |
| // |
| boolean exists = root.getProject(symbolicName).isAccessible(); |
| |
| // If we're computing the plugin map... |
| // |
| if (pluginMap != null) |
| { |
| // If the physical location is an external folder... |
| // |
| if (location.isFile()) |
| { |
| // If the physical location is an external folder, map the platform plugin URI to file URI of that external folder. |
| // |
| pluginMap.put(platformPluginURI, location.appendSegment("")); |
| if (!exists) |
| { |
| // If there is no corresponding project physically present in the workspace, also map the platform resource URI of the plugin to the file URI of the external folder. |
| // |
| pluginMap.put(resourceURI, location.appendSegment("")); |
| } |
| } |
| else |
| { |
| // If the physical location is an external jar, map the platform plugin URI to the archive URI of that external jar. |
| // |
| pluginMap.put(platformPluginURI, location); |
| if (!exists) |
| { |
| // If there is no corresponding project physically present in the workspace, also map the platform resource URI of the plugin to the archive URI of that external jar. |
| // |
| pluginMap.put(resourceURI, location); |
| } |
| } |
| } |
| } |
| } |
| |
| // If we're not computing the nsURI map, we're done with this plugin. |
| // |
| if (nsURIMap == null) |
| { |
| continue LOOP; |
| } |
| |
| // Map the nsURI to the logical location URI of the registered GenModel, if we're dealing with a generated package extension point. |
| // |
| // nsURIMap.put(uri.getValue(), logicalLocation.appendSegments(new Path(genModel.getValue()).segments())); |
| // |
| if (isGeneratedPackage) |
| { |
| nsURIMap.put((String)invoke(uri, PLUGIN_ATTRIBUTE_GET_VALUE_METHOD), logicalLocation.appendSegments(new Path((String)invoke(genModel, PLUGIN_ATTRIBUTE_GET_VALUE_METHOD)).segments())); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| public static final String DYNAMIC_PACKAGE_PPID = "dynamic_package"; |
| public static final String GENERATED_PACKAGE_PPID = "generated_package"; |
| public static final String FACTORY_OVERRIDE_PPID = "factory_override"; |
| public static final String EXTENSION_PARSER_PPID = "extension_parser"; |
| public static final String PROTOCOL_PARSER_PPID = "protocol_parser"; |
| public static final String CONTENT_PARSER_PPID = "content_parser"; |
| public static final String CONTENT_HANDLER_PPID = "content_handler"; |
| public static final String SCHEME_PARSER_PPID = "scheme_parser"; |
| public static final String URI_MAPPING_PPID = "uri_mapping"; |
| public static final String PACKAGE_REGISTRY_IMPLEMENTATION_PPID = "package_registry_implementation"; |
| public static final String VALIDATION_DELEGATE_PPID = "validation_delegate"; |
| public static final String SETTING_DELEGATE_PPID = "setting_delegate"; |
| public static final String INVOCATION_DELEGATE_PPID = "invocation_delegate"; |
| public static final String QUERY_DELEGATE_PPID = "query_delegate"; |
| public static final String CONVERSION_DELEGATE_PPID = "conversion_delegate"; |
| |
| /** |
| * Since 2.14 |
| */ |
| public static final String ANNOTATION_VALIDATOR_PPID = "annotation_validator"; |
| } |