]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.project/src/org/simantics/project/management/PlatformUtil.java
Work in progress
[simantics/platform.git] / bundles / org.simantics.project / src / org / simantics / project / management / PlatformUtil.java
index d5c88782a87e42d980773fd8542d8af087327e46..5298df922f7ab54ebfc8d48085900bd0abe59ed2 100644 (file)
@@ -26,7 +26,9 @@ import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicReference;
@@ -62,7 +64,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * This class contains utilities for managing bundles in a active platform. 
+ * This class contains utilities for managing bundles in a active platform.
  *
  */
 @SuppressWarnings("restriction")
@@ -82,13 +84,15 @@ public class PlatformUtil {
        /**
         * Get the manifest file of a bundle
         * 
-        * @param bundle bundle
+        * @param bundle
+        *            bundle
         * @return manifest or <tt>null</tt> if doesn't not exist
-        * @throws IOException 
+        * @throws IOException
         */
        public static Manifest getManifest(Bundle bundle) throws IOException {
                URL url = bundle.getEntry("META-INF/MANIFEST.MF");
-               if (url==null) return null;
+               if (url == null)
+                       return null;
                try (InputStream is = url.openStream()) {
                        return new Manifest(is);
                }
@@ -97,39 +101,41 @@ public class PlatformUtil {
        /**
         * Get the manifest file of a bundle
         * 
-        * @param bundle bundle
+        * @param bundle
+        *            bundle
         * @return manifest or <tt>null</tt> if doesn't not exist
-        * @throws IOException 
+        * @throws IOException
         */
        public static Manifest getSimanticsManifest(Bundle bundle) throws IOException {
                URL url = bundle.getEntry("META-INF/SIMANTICS.MF");
-               if (url==null) return null;
+               if (url == null)
+                       return null;
                try (InputStream is = url.openStream()) {
                        return new Manifest(is);
                }
        }
-       
+
        /**
-        * Get a list (BundleIds) of all user installable units. These are the 
-        * top-level items that are visible for the end-user. 
-        * The list is acquired from the bundles of the current application. 
+        * Get a list (BundleIds) of all user installable units. These are the top-level
+        * items that are visible for the end-user. The list is acquired from the
+        * bundles of the current application.
         * 
-        * @param list of simantics features URIs
-        * @throws IOException 
+        * @param list
+        *            of simantics features URIs
+        * @throws IOException
         */
-       public static void getUserInstallableUnits(Collection<String> list) 
-       throws IOException 
-       {
+       public static void getUserInstallableUnits(Collection<String> list) throws IOException {
                for (Bundle bundle : getBundles()) {
                        Manifest manifest = getSimanticsManifest(bundle);
-                       if (manifest==null) continue;
+                       if (manifest == null)
+                               continue;
                        Attributes attributes = manifest.getMainAttributes();
                        for (Entry<Object, Object> entry2 : attributes.entrySet()) {
                                Object key = entry2.getKey();
-                       if (key.toString().contains("Installable-Unit")) {
-                               String bid = entry2.getValue().toString();
-                               list.add( bid );
-                       }
+                               if (key.toString().contains("Installable-Unit")) {
+                                       String bid = entry2.getValue().toString();
+                                       list.add(bid);
+                               }
                        }
                }
        }
@@ -137,69 +143,72 @@ public class PlatformUtil {
        /**
         * Get all transferable graphs in the platform
         * 
-        * @param result collection to be filled with transferable graph info 
+        * @param result
+        *            collection to be filled with transferable graph info
         */
        public static void getPlatformTGInfos(Collection<TGInfo> result) {
                for (Bundle bundle : getBundles()) {
                        Enumeration<URL> e = bundle.findEntries("graphs/", "*.tg", false);
-                       if (e==null) continue;
+                       if (e == null)
+                               continue;
                        while (e.hasMoreElements()) {
                                org.osgi.framework.Version osgiVersion = bundle.getVersion();
-                               Version p2Version = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(), osgiVersion.getMicro(), osgiVersion.getQualifier());
+                               Version p2Version = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(),
+                                               osgiVersion.getMicro(), osgiVersion.getQualifier());
                                String id = bundle.getSymbolicName();
 
                                TGInfo info = new TGInfo();
                                info.location = e.nextElement();
                                info.bundle = bundle;
                                info.vid = new VersionedId(id, p2Version);
-                               result.add( info );
+                               result.add(info);
+                       }
+               }
+       }
+
+       private static void uncheckedClose(Closeable closeable) {
+               try {
+                       if (closeable != null)
+                               closeable.close();
+               } catch (IOException e) {
+                       // ignore
+               }
+       }
+
+       private static File copyResource(URL url, File targetFile) throws IOException, FileNotFoundException {
+               FileOutputStream os = null;
+               InputStream is = null;
+               try {
+                       if (targetFile.exists())
+                               targetFile.delete();
+
+                       is = url.openStream();
+                       int read;
+                       byte[] buffer = new byte[16384];
+                       os = new FileOutputStream(targetFile);
+                       while ((read = is.read(buffer)) != -1) {
+                               os.write(buffer, 0, read);
                        }
+                       os.close();
+                       is.close();
+
+                       return targetFile;
+               } finally {
+                       uncheckedClose(os);
+                       uncheckedClose(is);
                }
        }
 
-    private static void uncheckedClose(Closeable closeable) {
-        try {
-            if (closeable != null)
-                closeable.close();
-        } catch (IOException e) {
-            //ignore
-        }
-    }
-
-    private static File copyResource(URL url, File targetFile) throws IOException, FileNotFoundException {
-        FileOutputStream os = null;
-        InputStream is = null;
-        try {
-            if (targetFile.exists())
-                targetFile.delete();
-
-            is = url.openStream();
-            int read;
-            byte [] buffer = new byte [16384];
-            os = new FileOutputStream (targetFile);
-            while ((read = is.read (buffer)) != -1) {
-                os.write(buffer, 0, read);
-            }
-            os.close ();
-            is.close ();
-
-            return targetFile;
-        } finally {
-            uncheckedClose(os);
-            uncheckedClose(is);
-        }
-    }
-
-    private static File extractLib(URL libURL, String libName) throws FileNotFoundException, IOException {
-        String tmpDirStr = System.getProperty("java.io.tmpdir");
-        if (tmpDirStr == null)
-            throw new NullPointerException("java.io.tmpdir property is null");
-        File tmpDir = new File(tmpDirStr);
-        File libFile = new File(tmpDir, libName);
-        return copyResource(libURL, libFile);
-    }
-
-    private static File url2file(URL url, String fileName) {
+       private static File extractLib(URL libURL, String libName) throws FileNotFoundException, IOException {
+               String tmpDirStr = System.getProperty("java.io.tmpdir");
+               if (tmpDirStr == null)
+                       throw new NullPointerException("java.io.tmpdir property is null");
+               File tmpDir = new File(tmpDirStr);
+               File libFile = new File(tmpDir, libName);
+               return copyResource(libURL, libFile);
+       }
+
+       private static File url2file(URL url, String fileName) {
                if ("file".equals(url.getProtocol())) {
                        try {
                                File path = new File(URLDecoder.decode(url.getPath(), "UTF-8"));
@@ -218,27 +227,41 @@ public class PlatformUtil {
                        }
                } else {
                        LOGGER.error("Unsupported URL protocol '" + url + "' for FastLZ native library file '" + fileName);
-               }       
+               }
                return null;
        }
 
+       public static Collection<URL> getTGFiles(Bundle b) {
+               Enumeration<URL> enu = b.findEntries("/", "*.tg", false);
+               if (enu == null)
+                       return Collections.emptyList();
+               if (!enu.hasMoreElements())
+                       return Collections.emptyList();
+               ArrayList<URL> result = new ArrayList<>();
+               while (enu.hasMoreElements()) {
+                       result.add(enu.nextElement());
+               }
+               return result;
+       }
+
        public static void compile(Bundle b) throws Exception {
 
                Collection<ISource> sources = new ArrayList<>();
                Collection<TransferableGraph1> dependencies = new ArrayList<>();
 
                for (Bundle b2 : getBundles()) {
-                       if(b.equals(b2)) continue;
-                       URL url = b2.getEntry("graph.tg");
-                       if (url==null) continue;
-                       File graphFile = url2file(FileLocator.resolve(b2.getEntry("/graph.tg")), b2.toString());
-                       dependencies.add(GraphCompiler.read(graphFile));
+                       if (b.equals(b2))
+                               continue;
+                       for (URL url : getTGFiles(b2)) {
+                               File graphFile = url2file(url, b2.toString() + url.toString());
+                               dependencies.add(GraphCompiler.read(graphFile));
+                       }
                }
 
                File bundleFile = FileLocator.getBundleFile(b);
-               if(bundleFile.isDirectory()) {
+               if (bundleFile.isDirectory()) {
                        File folder = new File(bundleFile, "dynamicGraph");
-                       for(File f : folder.listFiles(new FilenameFilter() {
+                       for (File f : folder.listFiles(new FilenameFilter() {
 
                                @Override
                                public boolean accept(File dir, String name) {
@@ -250,22 +273,23 @@ public class PlatformUtil {
                        }
                }
 
-//             System.out.println("source is " + tmpFile.getAbsolutePath());
+               // System.out.println("source is " + tmpFile.getAbsolutePath());
 
                final StringBuilder errorStringBuilder = new StringBuilder();
                GraphCompilerPreferences prefs = new GraphCompilerPreferences();
                prefs.validate = true;
                prefs.validateRelationRestrictions = ValidationMode.ERROR;
                prefs.validateResourceHasType = ValidationMode.ERROR;
-               String currentLayer0Version = OntologyVersions.getInstance().currentOntologyVersion("http://www.simantics.org/Layer0-0.0");
+               String currentLayer0Version = OntologyVersions.getInstance()
+                               .currentOntologyVersion("http://www.simantics.org/Layer0-0.0");
                CompilationResult result = GraphCompiler.compile(currentLayer0Version, sources, dependencies, null, prefs);
 
-               for(Problem problem : result.getErrors())
+               for (Problem problem : result.getErrors())
                        errorStringBuilder.append(problem.getLocation() + ": " + problem.getDescription() + "\n");
-               for(Problem problem : result.getWarnings())
+               for (Problem problem : result.getWarnings())
                        errorStringBuilder.append(problem.getLocation() + ": " + problem.getDescription() + "\n");
 
-               if(errorStringBuilder.length() > 0) {
+               if (errorStringBuilder.length() > 0) {
                        LOGGER.error(errorStringBuilder.toString());
                } else {
                        GraphCompiler.write(new File(bundleFile, "graph.tg"), result.getGraph());
@@ -281,15 +305,15 @@ public class PlatformUtil {
         */
        public static void compileAllDynamicOntologies() {
                for (Bundle bundle : getBundles()) {
-                       if(bundle.getEntry("dynamicGraph") != null) {
+                       if (bundle.getEntry("dynamicGraph") != null) {
                                try {
                                        File bundleFile = FileLocator.getBundleFile(bundle);
-                                       if(bundleFile.isDirectory()) {
+                                       if (bundleFile.isDirectory()) {
                                                File tg = new File(bundleFile, "graph.tg");
                                                long tgLastModified = tg.lastModified();
                                                File folder = new File(bundleFile, "dynamicGraph");
-                                               for(File f : folder.listFiles()) {
-                                                       if(f.isFile() && f.getName().endsWith(".pgraph") && f.lastModified() > tgLastModified) {
+                                               for (File f : folder.listFiles()) {
+                                                       if (f.isFile() && f.getName().endsWith(".pgraph") && f.lastModified() > tgLastModified) {
                                                                compile(bundle);
                                                                break;
                                                        }
@@ -311,24 +335,45 @@ public class PlatformUtil {
        public static Collection<GraphBundle> getAllGraphs() throws IOException {
                AtomicReference<IOException> problem = new AtomicReference<>();
 
+               // Collection<GraphBundle> gbundles = Arrays.stream(getBundles())
+               // // #7806: Due to databoard Binding/Serializer construction process
+               // thread-unsafety
+               // // not even the DataContainer.readHeader invocations can run in parallel,
+               // most likely
+               // // due to recurring serializer construction for Variant datatypes.
+               // // Therefore, we must disable parallel loading for now.
+               // //.parallel()
+               // .map(b -> {
+               // try {
+               // return problem.get() == null ? getGraph(b) : null;
+               // } catch (IOException e) {
+               // if (LOGGER.isDebugEnabled())
+               // LOGGER.debug("Could not get graph from bundle {}", b, e);
+               // problem.set(e);
+               // return null;
+               // }
+               // })
+               // .filter(Objects::nonNull)
+               // .collect(Collectors.toList());
+
                Collection<GraphBundle> gbundles = Arrays.stream(getBundles())
-                               // #7806: Due to databoard Binding/Serializer construction process thread-unsafety
-                               // not even the DataContainer.readHeader invocations can run in parallel, most likely
+                               // #7806: Due to databoard Binding/Serializer construction process
+                               // thread-unsafety
+                               // not even the DataContainer.readHeader invocations can run in parallel, most
+                               // likely
                                // due to recurring serializer construction for Variant datatypes.
                                // Therefore, we must disable parallel loading for now.
-                               //.parallel()
+                               // .parallel()
                                .map(b -> {
                                        try {
-                                               return problem.get() == null ? getGraph(b) : null;
+                                               return problem.get() == null ? getGraphs(b) : null;
                                        } catch (IOException e) {
                                                if (LOGGER.isDebugEnabled())
                                                        LOGGER.debug("Could not get graph from bundle {}", b, e);
                                                problem.set(e);
                                                return null;
                                        }
-                               })
-                               .filter(Objects::nonNull)
-                               .collect(Collectors.toList());
+                               }).flatMap(Collection::stream).filter(Objects::nonNull).collect(Collectors.toList());
 
                if (problem.get() != null)
                        throw problem.get();
@@ -336,24 +381,27 @@ public class PlatformUtil {
        }
 
        /**
-        * Get bundle 
+        * Get bundle
         * 
         * @param symbolicName
-        * @return bundle or <tt>null</tt> if there is no bundle or graph 
+        * @return bundle or <tt>null</tt> if there is no bundle or graph
         * @throws IOException
         */
        public static GraphBundle getGraph(String symbolicName) throws IOException {
                Bundle bundle = Platform.getBundle(symbolicName);
-               if (bundle == null) return null;
-               return getGraph( bundle );
+               if (bundle == null)
+                       return null;
+               return getGraph(bundle);
        }
 
        /**
-        * Read the graph in a graph bundle. Graph is read from "graph.tg" file in the root.
+        * Read the graph in a graph bundle. Graph is read from "graph.tg" file in the
+        * root.
         * 
         * @param bundle
-        * @return transferable graph, or <tt>null</tt> if there is no graph in the bundle. 
-        * @throws IOException 
+        * @return transferable graph, or <tt>null</tt> if there is no graph in the
+        *         bundle.
+        * @throws IOException
         */
        public static GraphBundleEx getGraph(Bundle bundle) throws IOException {
                URL url = bundle.getEntry("graph.tg");
@@ -363,13 +411,24 @@ public class PlatformUtil {
                return result != null ? result : getCompleteGraph(bundle, url);
        }
 
+       public static Collection<GraphBundleEx> getGraphs(Bundle bundle) throws IOException {
+               return getTGFiles(bundle).stream().map(url -> {
+                       try {
+                               GraphBundleEx result = tryGetOnDemandGraph(bundle, url);
+                               return result != null ? result : getCompleteGraph(bundle, url);
+                       } catch (IOException e) {
+                               if (LOGGER.isDebugEnabled())
+                                       LOGGER.debug("Could not get graph from bundle url {}", url, e);
+                               return null;
+                       }
+               }).filter(Objects::nonNull).collect(Collectors.toList());
+       }
+
        private static GraphBundleEx getCompleteGraph(Bundle bundle, URL url) throws IOException {
                try {
-                       String id = bundle.getSymbolicName();
-                       return new GraphBundleEx(
-                                       getBundleName(bundle, id),
-                                       readTG(url),
-                                       new VersionedId(id, toP2Version(bundle)),
+                       String id = tgFileId(bundle, url);
+                       System.err.println("getCompleteGraph " + id);
+                       return new GraphBundleEx(getBundleName(bundle, id), readTG(url), new VersionedId(id, toP2Version(bundle)),
                                        isImmutable(bundle));
                } catch (Exception e) {
                        throw new IOException("Problem loading graph.tg from bundle " + bundle.getSymbolicName(), e);
@@ -378,13 +437,21 @@ public class PlatformUtil {
                        throw e;
                }
        }
+       
+       private static String tgFileId(Bundle bundle, URL url) {
+               String urlString = url.toString();
+               String file = urlString.substring(urlString.lastIndexOf("/")+1);
+               return bundle.getSymbolicName() + "_" + file;
+       }
 
        /**
-        * Read the graph in a graph bundle. Graph is read from "graph.tg" file in the root.
+        * Read the graph in a graph bundle. Graph is read from "graph.tg" file in the
+        * root.
         * 
         * @param bundle
-        * @return transferable graph, or <tt>null</tt> if there is no graph in the bundle. 
-        * @throws IOException 
+        * @return transferable graph, or <tt>null</tt> if there is no graph in the
+        *         bundle.
+        * @throws IOException
         */
        private static GraphBundleEx tryGetOnDemandGraph(Bundle bundle, URL url) throws IOException {
                try {
@@ -405,14 +472,12 @@ public class PlatformUtil {
                                }
                        };
 
-                       String id = bundle.getSymbolicName();
+                       String id = tgFileId(bundle, url);
+                       
+                       System.err.println("tryGetOnDemandGraph: " + id);
 
-                       return new GraphBundleEx(
-                                       getBundleName(bundle, id),
-                                       graphSource,
-                                       cachedHash,
-                                       new VersionedId(id, toP2Version(bundle)),
-                                       isImmutable(bundle));
+                       return new GraphBundleEx(getBundleName(bundle, id), graphSource, cachedHash,
+                                       new VersionedId(id, toP2Version(bundle)), isImmutable(bundle));
                } catch (Exception e) {
                        throw new IOException("Problem loading graph.tg from bundle " + bundle.getSymbolicName(), e);
                }
@@ -438,7 +503,8 @@ public class PlatformUtil {
 
        private static Version toP2Version(Bundle bundle) {
                org.osgi.framework.Version osgiVersion = bundle.getVersion();
-               return Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(), osgiVersion.getMicro(), osgiVersion.getQualifier());
+               return Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(), osgiVersion.getMicro(),
+                               osgiVersion.getQualifier());
        }
 
        private static String getBundleName(Bundle bundle, String id) {