KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > emf > ecore > plugin > EcorePlugin


1 /**
2  * <copyright>
3  *
4  * Copyright (c) 2002-2004 IBM Corporation and others.
5  * All rights reserved. This program and the accompanying materials
6  * are made available under the terms of the Eclipse Public License v1.0
7  * which accompanies this distribution, and is available at
8  * http://www.eclipse.org/legal/epl-v10.html
9  *
10  * Contributors:
11  * IBM - Initial API and implementation
12  *
13  * </copyright>
14  *
15  * $Id: EcorePlugin.java,v 1.9 2005/06/12 13:29:22 emerks Exp $
16  */

17 package org.eclipse.emf.ecore.plugin;
18
19 import java.io.File JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.regex.Matcher JavaDoc;
28 import java.util.regex.Pattern JavaDoc;
29
30 import javax.xml.parsers.SAXParser JavaDoc;
31 import javax.xml.parsers.SAXParserFactory JavaDoc;
32
33 import org.osgi.framework.BundleContext;
34 import org.xml.sax.Attributes JavaDoc;
35 import org.xml.sax.InputSource JavaDoc;
36 import org.xml.sax.SAXException JavaDoc;
37 import org.xml.sax.helpers.DefaultHandler JavaDoc;
38
39 import org.eclipse.core.resources.IFile;
40 import org.eclipse.core.resources.IProject;
41 import org.eclipse.core.resources.IWorkspaceRoot;
42 import org.eclipse.core.resources.ResourcesPlugin;
43 import org.eclipse.core.runtime.Platform;
44
45 import org.eclipse.emf.common.EMFPlugin;
46 import org.eclipse.emf.common.util.ResourceLocator;
47 import org.eclipse.emf.common.util.URI;
48 import org.eclipse.emf.common.util.WrappedException;
49
50
51 /**
52  * A collection of platform-neutral static utilities
53  * as well as Eclipse support utilities.
54  */

55 public class EcorePlugin extends EMFPlugin
56 {
57   /**
58    * The singleton instance of the plugin.
59    */

60   public static final EcorePlugin INSTANCE = new EcorePlugin();
61
62   /**
63    * Creates the singleton instance.
64    */

65   private EcorePlugin()
66   {
67     super(new ResourceLocator[] {});
68   }
69
70   /*
71    * Javadoc copied from base class.
72    */

73   public ResourceLocator getPluginResourceLocator()
74   {
75     return plugin;
76   }
77
78   /**
79    * Returns the platform resource map.
80    * <p>
81    * This map is from {@link String} to {@link URI}.
82    * It is the logical equivalent of the map implied by an {@link IWorkspaceRoot}:
83    * I.e., each entry in the map corresponds to
84    * an {@link org.eclipse.core.resources.IProject}
85    * that has a {@link org.eclipse.core.resources.IResource#getName name}
86    * and a location {@link org.eclipse.core.resources.IResource#getLocation location};
87    * the name is the key
88    * and the location, interpretted as a {@link URI#createFileURI file URI}, is the value.
89    * This map is used to {@link #resolvePlatformResourcePath resolve} a platform resource path,
90    * and thereby supports relocatable projects in a manner that is transparently the same as an Eclipse workspace.
91    * </p>
92    * @return the platform resource map.
93    * @see #resolvePlatformResourcePath
94    */

95   public static Map JavaDoc getPlatformResourceMap()
96   {
97     if (platformResourceMap == null)
98     {
99       platformResourceMap = new HashMap JavaDoc();
100     }
101     return platformResourceMap;
102   }
103
104   /**
105    * Resolves a platform resource path of the form <code>"/project/path"</code>
106    * against the platform resource map.
107    * <p>
108    * The first segment of the path, i.e., the <em>project name</em>,
109    * is used to get a URI from the {@link #getPlatformResourceMap() map}.
110    * If a URI results, the remaining segments are {@link URI#resolve resolved} against it
111    * and that is the result.
112    * Otherwise, the result is <code>null</code>.
113    * For example, given this mapping
114    *<pre>
115    * EcoreUtil.getPlatformResourceMap().put
116    * ("project", URI.createURI("file:///C:/location/"));
117    *</pre>
118    * the following transformation would result:
119    *<pre>
120    * /project/directory/file
121    * ->
122    * file:///C:/location/directory/file
123    *</pre>
124    * </p>
125    * @return the resolved URI or <code>null</code>.
126    */

127   public static URI resolvePlatformResourcePath(String JavaDoc platformResourcePath)
128   {
129     int index = platformResourcePath.indexOf("/", 1);
130     String JavaDoc rootContainerName = platformResourcePath.substring(1, index);
131     String JavaDoc relativeName = platformResourcePath.substring(index + 1);
132     URI rootContainerLocation = (URI)platformResourceMap.get(rootContainerName);
133     return
134       rootContainerLocation != null ?
135         URI.createURI(relativeName).resolve(rootContainerLocation) :
136          null;
137   }
138
139   /**
140    * Handles recognized platform resource arguments and returns the stripped result.
141    * <p>
142    * Recognized arguments are of this form:
143    *<pre>
144    * -platformResource ( &lt;project-name> &lt;file-or-URI> )+
145    *</pre>
146    * E.g., This these arguments
147    *<pre>
148    * -platformResource project file:///C:/location/
149    *</pre>
150    * will produce this effect:
151    *<pre>
152    * EcoreUtil.getPlatformResourceMap().put
153    * ("project", URI.createURI("file:///C:/location/"));
154    *</pre>
155    * This mechanism supports relocatable projects outside of Eclipse.
156    * </p>
157    * @param arguments an array of "command line" options.
158    * @return the arguments stripped of those recognized as platform resource options.
159    */

160   public static String JavaDoc [] handlePlatformResourceOptions(String JavaDoc [] arguments)
161   {
162     getPlatformResourceMap();
163
164     for (int i = 0; i < arguments.length; ++i)
165     {
166       if (arguments[i].equalsIgnoreCase("-platformResource"))
167       {
168         int start = i;
169         while (++i < arguments.length && !arguments[i].startsWith("-"))
170         {
171           String JavaDoc rootContainerName = arguments[i];
172           if (++i < arguments.length)
173           {
174             String JavaDoc rootContainerLocation = arguments[i];
175
176             // This let's us test whether the string exists as a file.
177
// If not, we try as a URI.
178
//
179
URI uri;
180             File JavaDoc file = new File JavaDoc(rootContainerLocation);
181             if (file.isDirectory() || !file.exists() && file.getParent() != null && file.getParentFile().isDirectory())
182             {
183               try
184               {
185                 file = file.getCanonicalFile();
186               }
187               catch (IOException JavaDoc exception)
188               {
189                 throw new WrappedException(exception);
190               }
191               uri = URI.createFileURI(file.toString() + "/");
192             }
193             else
194             {
195               uri = URI.createURI(rootContainerLocation);
196             }
197
198             platformResourceMap.put(rootContainerName, uri);
199           }
200         }
201
202         String JavaDoc [] remainingArguments = new String JavaDoc [arguments.length - (i - start)];
203         System.arraycopy(arguments, 0, remainingArguments, 0, start);
204         System.arraycopy(arguments, i, remainingArguments, start, arguments.length - i);
205         return remainingArguments;
206       }
207     }
208
209     return arguments;
210   }
211   
212   /**
213    * Returns a map from {@link EPackage#getNsURI() package namespace URI} (represented as a String)
214    * to the location of the GenModel containing a GenPackage for the package (represented as a {@link URI URI}).
215    * @return a map from package namespace to GenModel location.
216    */

217   public static Map JavaDoc getEPackageNsURIToGenModelLocationMap()
218   {
219     if (ePackageNsURIToGenModelLocationMap == null)
220     {
221       ePackageNsURIToGenModelLocationMap = new HashMap JavaDoc();
222     }
223     return ePackageNsURIToGenModelLocationMap;
224   }
225
226   /**
227    * Computes a map from <code>platform:/resource/&lt;plugin-location>/</code> {@link URI} to
228    * <code>platform:/plugin/&lt;plugin-id>/</code> URI
229    * for each URI in the collection of the form <code>platform:/plugin/&lt;plugin-id>/...</code>.
230    * This allows each plugin to be {@link org.eclipse.emf.ecore.resource.URIConverter#getURIMap() treated}
231    * as if it were a project in the workspace.
232    * If the workspace already contains a project for the plugin location, no mapping is produced.
233    * @return a map from workspace URIs to plugin URIs.
234    * @param uris a collections of {@link URI}s.
235    * @return a map from platform resource URI to platform plugin URI.
236    */

237   public static Map JavaDoc computePlatformResourceToPlatformPluginMap(Collection JavaDoc uris)
238   {
239     Map JavaDoc result = new HashMap JavaDoc();
240     IWorkspaceRoot root = getWorkspaceRoot();
241     if (root != null)
242     {
243       for (Iterator JavaDoc i = uris.iterator(); i.hasNext(); )
244       {
245         URI uri = (URI)i.next();
246         if ("platform".equals(uri.scheme()) && uri.segmentCount() > 1 && "plugin".equals(uri.segment(0)))
247         {
248           String JavaDoc pluginID = uri.segment(1);
249           if (!root.getProject(pluginID).isOpen())
250           {
251             result.put(URI.createPlatformResourceURI(pluginID + "/"), URI.createURI("platform:/plugin/" + pluginID + "/"));
252           }
253         }
254       }
255     }
256     return result;
257   }
258   
259   private static Pattern JavaDoc bundleSymbolNamePattern;
260   private static byte [] NO_BYTES = new byte [0];
261   
262   /**
263    * Computes a map from <code>platform:/plugin/&lt;plugin-id>/</code> {@link URI} to
264    * <code>platform:/resource/&lt;plugin-location>/</code> URI
265    * for each plugin project in the workspace.
266    * This allows each plugin from the runtime to be {@link org.eclipse.emf.ecore.resource.URIConverter#getURIMap() redirected}
267    * to its active version in the workspace.
268    * @return a map from plugin URIs to resource URIs.
269    * @see org.eclipse.emf.ecore.resource.URIConverter#getURIMap()
270    * @see URI
271    */

272   public static Map JavaDoc computePlatformPluginToPlatformResourceMap()
273   {
274     Map JavaDoc result = new HashMap JavaDoc();
275     IWorkspaceRoot root = getWorkspaceRoot();
276     if (root != null)
277     {
278       IProject [] projects = root.getProjects();
279       if (projects != null)
280       {
281         String JavaDoc pluginID = null;
282         
283         class Handler extends DefaultHandler JavaDoc
284         {
285           public String JavaDoc pluginID;
286           public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc attributes) throws SAXException JavaDoc
287           {
288             if ("".equals(uri) && "plugin".equals(localName))
289             {
290               pluginID = attributes.getValue("id");
291             }
292             throw new SAXException JavaDoc("Done");
293           }
294         };
295         Handler JavaDoc handler = new Handler JavaDoc();
296         
297         SAXParserFactory JavaDoc parserFactory= SAXParserFactory.newInstance();
298         parserFactory.setNamespaceAware(true);
299         SAXParser JavaDoc parser = null;
300         
301         try
302         {
303           parser = parserFactory.newSAXParser();
304         }
305         catch (Exception JavaDoc exception)
306         {
307           INSTANCE.log(exception);
308         }
309         
310         if (bundleSymbolNamePattern == null)
311         {
312           bundleSymbolNamePattern = Pattern.compile("^\\s*Bundle-SymbolicName\\s*:\\s*([^\\s;]*)\\s*(;.*)?$", Pattern.MULTILINE);
313         }
314         
315         byte [] bytes = NO_BYTES;
316         
317         for (int i = 0, size = projects.length; i < size; ++i)
318         {
319           IProject project = projects[i];
320           if (project.isOpen())
321           {
322             pluginID = null;
323             IFile manifest = project.getFile("META-INF/MANIFEST.MF");
324             if (manifest.exists())
325             {
326               try
327               {
328                 InputStream JavaDoc inputStream = manifest.getContents();
329                 int available = inputStream.available();
330                 if (bytes.length < available)
331                 {
332                   bytes = new byte [available];
333                 }
334                 inputStream.read(bytes);
335                 String JavaDoc contents = new String JavaDoc(bytes, "UTF-8");
336                 Matcher JavaDoc matcher = bundleSymbolNamePattern.matcher(contents);
337                 if (matcher.find())
338                 {
339                   pluginID = matcher.group(1);
340                 }
341               }
342               catch (Exception JavaDoc exception)
343               {
344                 EcorePlugin.INSTANCE.log(exception);
345               }
346             }
347             else if (parser != null)
348             {
349               final IFile plugin = project.getFile("plugin.xml");
350               if (plugin.exists())
351               {
352                 try
353                 {
354                   parser.parse(new InputSource JavaDoc(plugin.getContents()), handler);
355                 }
356                 catch (Exception JavaDoc exception)
357                 {
358                   if (handler.pluginID != null)
359                   {
360                     pluginID = handler.pluginID;
361                   }
362                   else
363                   {
364                     INSTANCE.log(exception);
365                   }
366                 }
367               }
368             }
369             
370             if (pluginID != null)
371             {
372               URI platformPluginURI = URI.createURI("platform:/plugin/" + pluginID + "/");
373               URI platformResourceURI = URI.createPlatformResourceURI(project.getName() + "/");
374               result.put(platformPluginURI, platformResourceURI);
375             }
376           }
377         }
378       }
379     }
380     
381     return result;
382   }
383   
384   /**
385    * Computes a map so that plugins in the workspace will override those in the environment
386    * and so that plugins with Ecore and GenModels will look like projects in the workspace.
387    * It's implemented like this:
388    *<pre>
389    * Map result = new HashMap();
390    * result.putAll(computePlatformPluginToPlatformResourceMap());
391    * result.putAll(computePlatformResourceToPlatformPluginMap(new HashSet(EcorePlugin.getEPackageNsURIToGenModelLocationMap().values())));
392    * return result;
393    *</pre>
394    * @return computes a map so that plugins in the workspace will override those in the environment
395    * and so that plugins with Ecore and GenModels will look like projects in the workspace.
396    * @see org.eclipse.emf.ecore.resource.URIConverter#getURIMap()
397    * @see URI
398    * @see #computePlatformPluginToPlatformResourceMap()
399    * @see #computePlatformResourceToPlatformPluginMap(Collection)
400    */

401   public static Map JavaDoc computePlatformURIMap()
402   {
403     Map JavaDoc result = new HashMap JavaDoc();
404     result.putAll(computePlatformPluginToPlatformResourceMap());
405     result.putAll(computePlatformResourceToPlatformPluginMap(new HashSet JavaDoc(EcorePlugin.getEPackageNsURIToGenModelLocationMap().values())));
406     return result;
407   }
408   
409   /**
410    * The platform resource map.
411    * @see #getPlatformResourceMap
412    */

413   private static Map JavaDoc platformResourceMap;
414   
415   /**
416    * The map fro
417    * @see #getPlatformResourceMap
418    */

419   private static Map JavaDoc ePackageNsURIToGenModelLocationMap;
420
421   /**
422    * A plugin implementation that handles Ecore plugin registration.
423    * @see #startup
424    */

425   static public class Implementation extends EclipsePlugin
426   {
427     /**
428      * Creates the singleton instance.
429      */

430     public Implementation()
431     {
432       super();
433       plugin = this;
434     }
435   
436     /**
437      * Starts up this plugin by reading some extensions and populating the relevant registries.
438      * <p>
439      * The {@link org.eclipse.emf.ecore.EPackage.Registry#INSTANCE global} package registry
440      * is populated by plugin registration of the form:
441      *<pre>
442      * &lt;extension point="org.eclipse.emf.ecore.generated_package" >
443      * &lt;package uri="http://www.example.org/abc/Abc.ecore" class="org.example.abc.AbcPackage"/>
444      * &lt;extension>
445      *</pre>
446      * </p>
447      * The URI is arbitrary but an absolute URI is recommended.
448      * Provision for access to the serialized model via <code>"http:"</code> is encouraged.
449      * <p>
450      * The {@link org.eclipse.emf.ecore.resource.Resource.Factory.Registry#INSTANCE global} resource factory registry's
451      * {@link org.eclipse.emf.ecore.resource.Resource.Factory.Registry#getExtensionToFactoryMap() extension} map
452      * is populated by plugin registration of the form:
453      *<pre>
454      * &lt;extension point="org.eclipse.emf.ecore.extension_parser">
455      * &lt;parser type="abc" class="org.example.abc.util.AbcResourceFactoryImpl"/>
456      * &lt;extension>
457      *</pre>
458      * </p>
459      * <p>
460      * The {@link org.eclipse.emf.ecore.resource.Resource.Factory.Registry#INSTANCE global} resource factory registry's
461      * {@link org.eclipse.emf.ecore.resource.Resource.Factory.Registry#getProtocolToFactoryMap() protocol} map
462      * is populated by plugin registration of the form:
463      *<pre>
464      * &lt;extension point="org.eclipse.emf.ecore.protocol_parser" >
465      * &lt;parser protocolName="abc" class="org.example.abc.util.AbcResourceFactoryImpl"/>
466      * &lt;extension>
467      *</pre>
468      * </p>
469      * <p>
470      * The {@link org.eclipse.emf.ecore.resource.URIConverter#URI_MAP global} URI map
471      * is populated by plugin registration of the form:
472      *<pre>
473      * &lt;extension point="org.eclipse.emf.ecore.uri_mapping" >
474      * &lt;mapping source="//special/" target="special/"/>
475      * &lt;extension>
476      *</pre>
477      * If the target is relative, it is resolved against the plugin's installed location,
478      * resulting in a URI of the form:
479      *<pre>
480      * platform:/plugin/plugin-name_1.2.3/...
481      *</pre>
482      * The above registration would map
483      *<pre>
484      * //special/a/b.c
485      *</pre>
486      * to
487      *<pre>
488      * platform:/plugin/plugin-name_1.2.3/special/a/b.c
489      *</pre>
490      * </p>
491      * @throws Exception if there is a show stopping problem.
492      */

493     public void start(BundleContext context) throws Exception JavaDoc
494     {
495       super.start(context);
496
497       if (System.getProperty("org.eclipse.emf.ecore.plugin.EcorePlugin.doNotLoadResourcesPlugin") == null &&
498             Platform.getBundle("org.eclipse.core.resources") != null)
499       {
500         workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
501       }
502
503       new GeneratedPackageRegistryReader(getEPackageNsURIToGenModelLocationMap()).readRegistry();
504       new ExtensionParserRegistryReader().readRegistry();
505       new ProtocolParserRegistryReader().readRegistry();
506       new URIMappingRegistryReader().readRegistry();
507     }
508   }
509
510   /**
511    * Returns the Eclipse plugin singleton.
512    * @return the plugin singleton.
513    */

514   public static Implementation getPlugin()
515   {
516     return plugin;
517   }
518
519   /**
520    * The plugin singleton
521    */

522   private static Implementation plugin;
523
524   /**
525    * The workspace root.
526    * @see #getWorkspaceRoot
527    */

528   private static IWorkspaceRoot workspaceRoot;
529
530   /**
531    * Returns the workspace root, or <code>null</code>, if the runtime environment is stand-alone.
532    * @return the workspace root, or <code>null</code>.
533    */

534   public static IWorkspaceRoot getWorkspaceRoot()
535   {
536     return workspaceRoot;
537   }
538
539   static final String JavaDoc GENERATED_PACKAGE_PPID = "generated_package";
540   static final String JavaDoc EXTENSION_PARSER_PPID = "extension_parser";
541   static final String JavaDoc PROTOCOL_PARSER_PPID = "protocol_parser";
542   static final String JavaDoc SCHEME_PARSER_PPID = "scheme_parser";
543   static final String JavaDoc URI_MAPPING_PPID = "uri_mapping";
544 }
Popular Tags