]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.project/src/org/simantics/project/management/PlatformUtil.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.project / src / org / simantics / project / management / PlatformUtil.java
diff --git a/bundles/org.simantics.project/src/org/simantics/project/management/PlatformUtil.java b/bundles/org.simantics.project/src/org/simantics/project/management/PlatformUtil.java
new file mode 100644 (file)
index 0000000..dafb8f1
--- /dev/null
@@ -0,0 +1,393 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.project.management;\r
+\r
+import java.io.BufferedInputStream;\r
+import java.io.Closeable;\r
+import java.io.DataInput;\r
+import java.io.DataInputStream;\r
+import java.io.File;\r
+import java.io.FileNotFoundException;\r
+import java.io.FileOutputStream;\r
+import java.io.FilenameFilter;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.UnsupportedEncodingException;\r
+import java.net.URL;\r
+import java.net.URLDecoder;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Enumeration;\r
+import java.util.Map.Entry;\r
+import java.util.jar.Attributes;\r
+import java.util.jar.Manifest;\r
+\r
+import org.eclipse.core.internal.runtime.PlatformActivator;\r
+import org.eclipse.core.runtime.FileLocator;\r
+import org.eclipse.core.runtime.Platform;\r
+import org.eclipse.equinox.p2.metadata.IVersionedId;\r
+import org.eclipse.equinox.p2.metadata.Version;\r
+import org.eclipse.equinox.p2.metadata.VersionedId;\r
+import org.osgi.framework.Bundle;\r
+import org.simantics.databoard.adapter.AdaptException;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.databoard.container.DataContainer;\r
+import org.simantics.databoard.container.DataContainers;\r
+import org.simantics.databoard.serialization.SerializationException;\r
+import org.simantics.db.common.utils.Logger;\r
+import org.simantics.graph.compiler.CompilationResult;\r
+import org.simantics.graph.compiler.GraphCompiler;\r
+import org.simantics.graph.compiler.GraphCompilerPreferences;\r
+import org.simantics.graph.compiler.ValidationMode;\r
+import org.simantics.graph.representation.TransferableGraph1;\r
+import org.simantics.ltk.FileSource;\r
+import org.simantics.ltk.ISource;\r
+import org.simantics.ltk.Problem;\r
+import org.simantics.scl.reflection.OntologyVersions;\r
+\r
+/**\r
+ * This class contains utilities for managing bundles in a active platform. \r
+ *\r
+ */\r
+@SuppressWarnings("restriction")\r
+public class PlatformUtil {\r
+\r
+       \r
+       /**\r
+        * Get all bundles in the platform.\r
+        * \r
+        * @return\r
+        */\r
+       public static Bundle[] getBundles() {\r
+               return PlatformActivator.getContext().getBundles();\r
+       }\r
+               \r
+       /**\r
+        * Get the manifest file of a bundle\r
+        * \r
+        * @param bundle bundle\r
+        * @return manifest or <tt>null</tt> if doesn't not exist\r
+        * @throws IOException \r
+        */\r
+       public static Manifest getManifest(Bundle bundle) throws IOException {\r
+               URL url = bundle.getEntry("META-INF/MANIFEST.MF");\r
+               if (url==null) return null;\r
+               InputStream is = url.openStream();\r
+               try {\r
+                       return new Manifest(is);                        \r
+               } finally {\r
+                       is.close();\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Get the manifest file of a bundle\r
+        * \r
+        * @param bundle bundle\r
+        * @return manifest or <tt>null</tt> if doesn't not exist\r
+        * @throws IOException \r
+        */\r
+       public static Manifest getSimanticsManifest(Bundle bundle) throws IOException {\r
+               URL url = bundle.getEntry("META-INF/SIMANTICS.MF");\r
+               if (url==null) return null;\r
+               InputStream is = url.openStream();\r
+               try {\r
+                       return new Manifest(is);                        \r
+               } finally {\r
+                       is.close();\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Get a list (BundleIds) of all user installable units. These are the \r
+        * top-level items that are visible for the end-user. \r
+        * The list is acquired from the bundles of the current application. \r
+        * \r
+        * @param list of simantics features URIs\r
+        * @throws IOException \r
+        */\r
+       public static void getUserInstallableUnits(Collection<String> list) \r
+       throws IOException \r
+       {\r
+               for (Bundle bundle : getBundles()) {\r
+                       Manifest manifest = getSimanticsManifest(bundle);\r
+                       if (manifest==null) continue;\r
+                       Attributes attributes = manifest.getMainAttributes();\r
+                       for (Entry<Object, Object> entry2 : attributes.entrySet()) {\r
+                               Object key = entry2.getKey();\r
+                       if (key.toString().contains("Installable-Unit")) {\r
+                               String bid = entry2.getValue().toString();                              \r
+                               list.add( bid );\r
+                       }\r
+                       }\r
+               }               \r
+       }\r
+       \r
+       /**\r
+        * Get all transferable graphs in the platform\r
+        * \r
+        * @param result collection to be filled with transferable graph info \r
+        */\r
+       public static void getPlatformTGInfos(Collection<TGInfo> result) {\r
+               for (Bundle bundle : getBundles()) {\r
+                       Enumeration<URL> e = bundle.findEntries("graphs/", "*.tg", false);\r
+                       if (e==null) continue;\r
+                       while (e.hasMoreElements()) {\r
+                               org.osgi.framework.Version osgiVersion = bundle.getVersion();\r
+                               Version p2Version = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(), osgiVersion.getMicro(), osgiVersion.getQualifier());\r
+                               String id = bundle.getSymbolicName();\r
+                               \r
+                               TGInfo info = new TGInfo();\r
+                               info.location = e.nextElement();\r
+                               info.bundle = bundle;\r
+                               info.vid = new VersionedId(id, p2Version);\r
+                               result.add( info );\r
+                       }\r
+               }\r
+       }\r
+\r
+    private static void uncheckedClose(Closeable closeable) {\r
+        try {\r
+            if (closeable != null)\r
+                closeable.close();\r
+        } catch (IOException e) {\r
+            //ignore\r
+        }\r
+    }\r
+       \r
+    private static File copyResource(URL url, File targetFile) throws IOException, FileNotFoundException {\r
+        FileOutputStream os = null;\r
+        InputStream is = null;\r
+        try {\r
+            if (targetFile.exists())\r
+                targetFile.delete();\r
+\r
+            is = url.openStream();\r
+            int read;\r
+            byte [] buffer = new byte [16384];\r
+            os = new FileOutputStream (targetFile);\r
+            while ((read = is.read (buffer)) != -1) {\r
+                os.write(buffer, 0, read);\r
+            }\r
+            os.close ();\r
+            is.close ();\r
+\r
+            return targetFile;\r
+        } finally {\r
+            uncheckedClose(os);\r
+            uncheckedClose(is);\r
+        }\r
+    }\r
+       \r
+    private static File extractLib(URL libURL, String libName) throws FileNotFoundException, IOException {\r
+        String tmpDirStr = System.getProperty("java.io.tmpdir");\r
+        if (tmpDirStr == null)\r
+            throw new NullPointerException("java.io.tmpdir property is null");\r
+        File tmpDir = new File(tmpDirStr);\r
+        File libFile = new File(tmpDir, libName);\r
+        return copyResource(libURL, libFile);\r
+    }\r
+       \r
+    private static File url2file(URL url, String fileName) {\r
+               if ("file".equals(url.getProtocol())) {\r
+                       try {\r
+                               File path = new File(URLDecoder.decode(url.getPath(), "UTF-8"));\r
+                               return path;\r
+                       } catch (UnsupportedEncodingException e) {\r
+                               Logger.defaultLogError(e);\r
+                       }\r
+               } else if ("jar".equals(url.getProtocol())) {\r
+                       try {\r
+                               File libFile = extractLib(url, fileName);\r
+                               return libFile;\r
+                       } catch (FileNotFoundException e) {\r
+                               Logger.defaultLogError(e);\r
+                       } catch (IOException e) {\r
+                               Logger.defaultLogError(e);\r
+                       }\r
+               } else {\r
+                       System.err.println("Unsupported URL protocol '" + url + "' for FastLZ native library file '" + fileName);\r
+               }       \r
+               return null;\r
+       }\r
+       \r
+       public static void compile(Bundle b) throws Exception {\r
+               \r
+               Collection<ISource> sources = new ArrayList<ISource>();\r
+               Collection<TransferableGraph1> dependencies = new ArrayList<TransferableGraph1>();\r
+               \r
+               for (Bundle b2 : getBundles()) {\r
+                       if(b.equals(b2)) continue;\r
+                       URL url = b2.getEntry("graph.tg");\r
+                       if (url==null) continue;\r
+                       File graphFile = url2file(FileLocator.resolve(b2.getEntry("/graph.tg")), b2.toString());\r
+                       dependencies.add(GraphCompiler.read(graphFile));\r
+               }\r
+               \r
+               File bundleFile = FileLocator.getBundleFile(b);\r
+               if(bundleFile.isDirectory()) {\r
+                       File folder = new File(bundleFile, "dynamicGraph");\r
+                       for(File f : folder.listFiles(new FilenameFilter() {\r
+                               \r
+                               @Override\r
+                               public boolean accept(File dir, String name) {\r
+                                       return name.endsWith(".pgraph");\r
+                               }\r
+                               \r
+                       })) {\r
+                               sources.add(new FileSource(f));\r
+                       }\r
+               }               \r
+               \r
+//             System.out.println("source is " + tmpFile.getAbsolutePath());\r
+               \r
+               final StringBuilder errorStringBuilder = new StringBuilder();\r
+               GraphCompilerPreferences prefs = new GraphCompilerPreferences();\r
+               prefs.validate = true;\r
+               prefs.validateRelationRestrictions = ValidationMode.ERROR;\r
+               prefs.validateResourceHasType = ValidationMode.ERROR;\r
+               String currentLayer0Version = OntologyVersions.getInstance().currentOntologyVersion("http://www.simantics.org/Layer0-0.0");\r
+               CompilationResult result = GraphCompiler.compile(currentLayer0Version, sources, dependencies, null, prefs);\r
+               \r
+               for(Problem problem : result.getErrors())\r
+                       errorStringBuilder.append(problem.getLocation() + ": " + problem.getDescription() + "\n");\r
+               for(Problem problem : result.getWarnings())\r
+                       errorStringBuilder.append(problem.getLocation() + ": " + problem.getDescription() + "\n");\r
+\r
+               if(errorStringBuilder.length() > 0) {\r
+                       Logger.defaultLogError(errorStringBuilder.toString());\r
+               } else {\r
+                       DataContainers.writeFile(new File(bundleFile, "graph.tg"), \r
+                                       new DataContainer("graph", 1, new Variant(TransferableGraph1.BINDING, result.getGraph())));\r
+               }\r
+               \r
+       }\r
+       \r
+       /**\r
+        * Compile all dynamic ontologies in the Platform\r
+        * \r
+        * @param collection\r
+        * @throws IOException\r
+        */\r
+       public static void compileAllDynamicOntologies() {\r
+               for (Bundle bundle : getBundles()) {\r
+                       if(bundle.getEntry("dynamicGraph") != null) {\r
+                               try {\r
+                                       File bundleFile = FileLocator.getBundleFile(bundle);\r
+                                       if(bundleFile.isDirectory()) {\r
+                                               File tg = new File(bundleFile, "graph.tg");\r
+                                               long tgLastModified = tg.lastModified();\r
+                                               File folder = new File(bundleFile, "dynamicGraph");\r
+                                               for(File f : folder.listFiles()) {\r
+                                                       if(f.isFile() && f.getName().endsWith(".pgraph") && f.lastModified() > tgLastModified) {\r
+                                                               compile(bundle);\r
+                                                               break;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               } catch (Throwable e) {\r
+                                       Logger.defaultLogError(e);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Get all graphs in the Platform\r
+        * \r
+        * @param collection\r
+        * @throws IOException\r
+        */\r
+       public static void getAllGraphs(Collection<GraphBundle> collection) throws IOException {\r
+               for (Bundle bundle : getBundles()) {\r
+                       GraphBundle entry = getGraph(bundle);\r
+                       if (entry!=null) collection.add(entry);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Get bundle \r
+        * \r
+        * @param symbolicName\r
+        * @return bundle or <tt>null</tt> if there is no bundle or graph \r
+        * @throws IOException\r
+        */\r
+       public static GraphBundle getGraph(String symbolicName) throws IOException {\r
+               Bundle bundle = Platform.getBundle(symbolicName);\r
+               if (bundle == null) return null;\r
+               return getGraph( bundle );\r
+       }\r
+       \r
+       /**\r
+        * Read the graph in a graph bundle. Graph is read from "graph.tg" file in the root.\r
+        * \r
+        * @param bundle\r
+        * @return transferable graph, or <tt>null</tt> if there is no graph in the bundle. \r
+        * @throws IOException \r
+        */\r
+       public static GraphBundleEx getGraph(Bundle bundle) throws IOException {\r
+               URL url = bundle.getEntry("graph.tg");\r
+               \r
+               if (url==null) return null;\r
+               InputStream is = url.openStream(); \r
+               // NOTE: this is vital for performance.\r
+               is = new BufferedInputStream(is, 128*1024);\r
+               try {\r
+                       DataInput dis = new DataInputStream(is);\r
+                       // or\r
+                       // dis = new InputStreamReadable(is, <max limit>) to protect from OOM\r
+                       \r
+                       org.simantics.databoard.container.DataContainer container = \r
+                                       DataContainers.readFile(dis); \r
+\r
+                       Binding binding = TransferableGraph1.BINDING;\r
+                       TransferableGraph1 graph = (TransferableGraph1)container.content.getValue(binding);\r
+//                     TransferableGraph1 graph = (TransferableGraph1) Files.readFile(is, binding);\r
+//                     System.out.println("getGraph(" + bundle.getSymbolicName() + "): read transferable graph in " + (System.nanoTime()-start)*1e-6 + "ms");\r
+                       org.osgi.framework.Version osgiVersion = bundle.getVersion();\r
+                       Version p2Version = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(), osgiVersion.getMicro(), osgiVersion.getQualifier());\r
+                       String id = bundle.getSymbolicName();\r
+                       VersionedId vid = new VersionedId(id, p2Version);\r
+                       String name = (String) bundle.getHeaders().get("Bundle-Name");\r
+                       if (name == null) name = id;\r
+                       String immutable = (String) bundle.getHeaders().get("Immutable");\r
+                       boolean isImmutable = \r
+                                       immutable != null ? \r
+                                                       "true".equals(immutable) : \r
+                                                               true;\r
+\r
+//                     System.out.println("getGraph(" + bundle.getSymbolicName() + "): before hashcode calculation in " + (System.nanoTime()-start)*1e-6 + "ms");\r
+                       GraphBundleEx entry = new GraphBundleEx(name, graph, vid, isImmutable);\r
+//                     System.out.println("getGraph(" + bundle.getSymbolicName() + "): completed in " + (System.nanoTime()-start)*1e-6 + "ms");\r
+                       return entry;\r
+               } catch (SerializationException e) {\r
+                       throw new IOException(e);\r
+               } catch (IOException e) {\r
+                       throw new IOException("Problem loading graph.tg from bundle " + bundle.getSymbolicName(), e);\r
+               } catch (RuntimeException e) {\r
+                       throw new IOException("Problem loading graph.tg from bundle " + bundle.getSymbolicName(), e);\r
+               } catch (AdaptException e) {\r
+                       throw new IOException("Problem loading graph.tg from bundle " + bundle.getSymbolicName(), e);\r
+               } finally {\r
+                       is.close();\r
+               }\r
+       }\r
+       \r
+       public static class TGInfo {\r
+               public Bundle bundle;\r
+               public URL location;\r
+               public IVersionedId vid;\r
+       }\r
+       \r
+}\r
+\r