]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.project/src/org/simantics/project/management/ProvisioningUtil.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.project / src / org / simantics / project / management / ProvisioningUtil.java
diff --git a/bundles/org.simantics.project/src/org/simantics/project/management/ProvisioningUtil.java b/bundles/org.simantics.project/src/org/simantics/project/management/ProvisioningUtil.java
new file mode 100644 (file)
index 0000000..858a13e
--- /dev/null
@@ -0,0 +1,520 @@
+/*******************************************************************************\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.ByteArrayInputStream;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.util.Collection;\r
+import java.util.Comparator;\r
+import java.util.Enumeration;\r
+import java.util.Iterator;\r
+import java.util.Set;\r
+import java.util.TreeSet;\r
+import java.util.jar.JarEntry;\r
+import java.util.jar.JarFile;\r
+import java.util.jar.JarInputStream;\r
+import java.util.jar.Manifest;\r
+\r
+import org.eclipse.core.runtime.Path;\r
+import org.eclipse.equinox.internal.p2.metadata.RequiredCapability;\r
+import org.eclipse.equinox.internal.p2.touchpoint.eclipse.Util;\r
+import org.eclipse.equinox.internal.p2.ui.query.RequiredIUsQuery;\r
+import org.eclipse.equinox.p2.core.IProvisioningAgent;\r
+import org.eclipse.equinox.p2.core.ProvisionException;\r
+import org.eclipse.equinox.p2.metadata.IArtifactKey;\r
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;\r
+import org.eclipse.equinox.p2.metadata.IInstallableUnitFragment;\r
+import org.eclipse.equinox.p2.metadata.IRequirement;\r
+import org.eclipse.equinox.p2.metadata.Version;\r
+import org.eclipse.equinox.p2.publisher.AdviceFileAdvice;\r
+import org.eclipse.equinox.p2.publisher.PublisherInfo;\r
+import org.eclipse.equinox.p2.publisher.eclipse.BundleShapeAdvice;\r
+import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;\r
+import org.eclipse.equinox.p2.publisher.eclipse.IBundleShapeAdvice;\r
+import org.eclipse.equinox.p2.query.IQuery;\r
+import org.eclipse.equinox.p2.query.IQueryResult;\r
+import org.eclipse.equinox.p2.query.IQueryable;\r
+import org.eclipse.equinox.p2.query.QueryUtil;\r
+import org.eclipse.equinox.p2.repository.artifact.ArtifactKeyQuery;\r
+import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;\r
+import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;\r
+import org.eclipse.equinox.p2.repository.artifact.IFileArtifactRepository;\r
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;\r
+import org.eclipse.osgi.service.resolver.BundleDescription;\r
+import org.osgi.framework.BundleException;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.Files;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.util.StreamUtil;\r
+import org.simantics.graph.db.TransferableGraphException;\r
+import org.simantics.graph.representation.TransferableGraph1;\r
+\r
+/**\r
+ * This class contains provisioning utilities.\r
+ *\r
+ * @see QueryUtil\r
+ * @see Util\r
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
+ */\r
+@SuppressWarnings("restriction")\r
+public class ProvisioningUtil {\r
+\r
+       private static IRequirement IS_FEATURE_REQUIREMENT = new RequiredCapability("org.eclipse.equinox.p2.eclipse.type", "feature", null, null, false, false, false);\r
+\r
+       public static void getAllRequirements(IInstallableUnit iu, IQueryable<IInstallableUnit> repo, Set<IInstallableUnit> result) \r
+       {\r
+               if (result.contains(iu)) return;\r
+               result.add(iu);\r
+               IQuery<IInstallableUnit> reqsQuery = new RequiredIUsQuery(iu);\r
+               for (IInstallableUnit _iu : repo.query( reqsQuery, null ).toSet()) {\r
+                       if (result.contains(_iu)) continue;\r
+                       getAllRequirements(_iu, repo, result);\r
+               }               \r
+       }\r
+       \r
+       \r
+       /**\r
+        * Get IUs that are required to install this bundle. \r
+        * Assumed architecture is x86 and os win32. \r
+        * Throws an exception if not all requirements can be satisfied.\r
+        * \r
+        * @param iu\r
+        * @param availableIUs\r
+        * @return\r
+        */\r
+       /*\r
+       public static Collection<IRequirement> getAllRequirements(IInstallableUnit iu, IQueryable<IInstallableUnit> repo)\r
+       {               \r
+               // Installable Units analysed\r
+               Set<IInstallableUnit> ius = new HashSet<IInstallableUnit>();\r
+               \r
+               // Requirements\r
+               Set<IRequirement> reqs = new HashSet<IRequirement>();\r
+               \r
+               // Satisfied requirements\r
+               Set<IRequirement> sats = new HashSet<IRequirement>();\r
+               ius.add(iu);\r
+               reqs.addAll( iu.getRequirements() );\r
+               \r
+               // Find satisfactions\r
+               return result;\r
+       }*/\r
+       /*\r
+       static void _addIU(IInstallableUnit iu, Set<IInstallableUnit> ius, Set<IRequirement> reqs, Set<IRequirement> sats, Set<IRequirement> unsats, IQueryable<IInstallableUnit> repo) \r
+       {\r
+               if (ius.contains(iu)) return;\r
+               ius.add( iu );\r
+               \r
+               for (IRequirement req : iu.getRequirements()) {\r
+                       if (sats.contains(req)) continue;\r
+                       if (unsats.contains(req)) continue;\r
+                       \r
+                       // req is unsatisfied\r
+                       IQuery\r
+                       IQueryResult<IInstallableUnit> result = repo.query(req, null);\r
+               }\r
+               \r
+               for (IInstallableUnit _iu : availableIUs) {\r
+                       if (sats.contains(_iu)) continue;\r
+                       \r
+                       boolean satisfies = _iu.satisfies(  ) \r
+               }\r
+       }*/\r
+       \r
+       /**\r
+        * Get all installable units from a metadata repository\r
+        * \r
+        * @param repo\r
+        * @return\r
+        */\r
+       public static Collection<IInstallableUnit> getInstallableUnits(IMetadataRepository repo) {\r
+               \r
+//             IQuery<IInstallableUnit> query = QueryUtil.createIUQuery(null, VersionRange.emptyRange);\r
+               IQuery<IInstallableUnit> query = QueryUtil.createIUAnyQuery();\r
+           IQueryResult<IInstallableUnit> matches = repo.query(query, null);\r
+           return matches.toUnmodifiableSet();\r
+       }\r
+       \r
+\r
+       /**\r
+        * Test if the {@link IInstallableUnit} is a category. \r
+        * @param iu the element being tested.\r
+        * @return <tt>true</tt> if the parameter is a category.\r
+        */\r
+       public static boolean isCategory(IInstallableUnit iu) {\r
+               String PROP_TYPE_CATEGORY = "org.eclipse.equinox.p2.type.category"; //$NON-NLS-1$\r
+               String value = iu.getProperty(PROP_TYPE_CATEGORY);\r
+               if (value != null && (value.equals(Boolean.TRUE.toString())))\r
+                       return true;\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Test if the {@link IInstallableUnit} is a fragment. \r
+        * @param iu the element being tested.\r
+        * @return <tt>true</tt> if the parameter is a fragment.\r
+        */\r
+       public static boolean isFragment(IInstallableUnit iu) {\r
+               return iu instanceof IInstallableUnitFragment;\r
+       }\r
+\r
+       /**\r
+        * Test if the {@link IInstallableUnit} is a group. \r
+        * @param iu the element being tested.\r
+        * @return <tt>true</tt> if the parameter is a group.\r
+        */\r
+       public static boolean isGroup(IInstallableUnit iu) {\r
+               String PROP_TYPE_GROUP = "org.eclipse.equinox.p2.type.group"; //$NON-NLS-1$\r
+               String value = iu.getProperty(PROP_TYPE_GROUP);\r
+               if (value != null && (value.equals(Boolean.TRUE.toString())))\r
+                       return true;\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Test if the {@link IInstallableUnit} is a patch. \r
+        * @param iu the element being tested.\r
+        * @return <tt>true</tt> if the parameter is a patch.\r
+        */\r
+       public static boolean isPatch(IInstallableUnit iu) {\r
+               String PROP_TYPE_PATCH = "org.eclipse.equinox.p2.type.patch"; //$NON-NLS-1$\r
+               String value = iu.getProperty(PROP_TYPE_PATCH);\r
+               if (value != null && (value.equals(Boolean.TRUE.toString())))\r
+                       return true;\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * Checks whether a installable unit is a feature\r
+        * \r
+        * @param iu\r
+        * @return <code>true</code> if is feature\r
+        */\r
+       public static boolean isFeature(IInstallableUnit iu) {\r
+//             String value = iu.getProperty("org.eclipse.equinox.p2.eclipse.type");\r
+//             return value != null && value.equals("feature");\r
+       return iu.satisfies(IS_FEATURE_REQUIREMENT);\r
+       }\r
+\r
+       public static boolean isGraph(IInstallableUnit iu, IMetadataRepository metadata, IArtifactRepository arts) throws IOException {\r
+       Collection<IArtifactKey> artifacts = iu.getArtifacts();\r
+       for (IArtifactKey key : artifacts) {\r
+                       if (isGraphArtifact(arts, key)) return true;                    \r
+       }\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Checks whether artifact is a graph bundle. \r
+        * \r
+        * @param repo artifact repo\r
+        * @param key key to artifact\r
+        * @return <code>true</code> if is a graph bundle\r
+        * @throws IOException \r
+        */\r
+       public static boolean isGraphArtifact(IArtifactRepository repo, IArtifactKey key) throws IOException {\r
+               return hasFile(repo, key, "graph.tg");\r
+       }\r
+       \r
+       public static boolean hasFile(IArtifactRepository repo, IArtifactKey key, String filename) throws IOException {\r
+               boolean isBundle = key.getClassifier().equals("osgi.bundle");\r
+               if (!isBundle) return false;\r
+               \r
+               for (IArtifactDescriptor desc : repo.getArtifactDescriptors(key)) {             \r
+                       if (repo instanceof IFileArtifactRepository) {                          \r
+                               IFileArtifactRepository filerepo = (IFileArtifactRepository) repo;\r
+                               File f = filerepo.getArtifactFile(key);\r
+                               if (!f.exists()) return false;\r
+                               \r
+                               boolean isJar = f.getName().toLowerCase().endsWith(".jar");\r
+                               if (!isJar) return false;\r
+                               \r
+                               JarFile jf = new JarFile(f);\r
+                               try {\r
+                                       Enumeration<JarEntry> enm = jf.entries();\r
+                                       while (enm.hasMoreElements()) {\r
+                                               JarEntry entry = enm.nextElement();\r
+                                               String entryName = entry.getName();\r
+                                               if ( entryName.equals(filename) ) return true;\r
+                                       }\r
+                               } finally {\r
+                                       jf.close();\r
+                               }\r
+                               \r
+                       } else {\r
+                               int size = Integer.valueOf( desc.getProperties().get("download.size") );\r
+                               ByteArrayOutputStream bos = new ByteArrayOutputStream(size);\r
+                               repo.getArtifact(desc, bos, null);\r
+                               ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());\r
+                               JarInputStream jis = new JarInputStream( bis );\r
+                               for (JarEntry entry = jis.getNextJarEntry(); entry!=null; entry = jis.getNextJarEntry()) {\r
+                                       String entryName = entry.getName();\r
+                                       if ( entryName.equals(filename) ) return true;\r
+                               }                               \r
+                               \r
+                       }\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Get a file from a repository\r
+        * \r
+        * @param repo artifact repo\r
+        * @param key key to artifact\r
+        * @return input stream (must be closed) or null\r
+        * @throws IOException \r
+        */\r
+       public static InputStream getFile(IArtifactRepository repo, IArtifactKey key, String filename) throws IOException {\r
+               boolean isBundle = key.getClassifier().equals("osgi.bundle");\r
+               if (!isBundle) return null;\r
+               \r
+               for (IArtifactDescriptor desc : repo.getArtifactDescriptors(key)) {             \r
+                       if (repo instanceof IFileArtifactRepository) {                          \r
+                               IFileArtifactRepository filerepo = (IFileArtifactRepository) repo;\r
+                               File f = filerepo.getArtifactFile(key);\r
+                               if (!f.exists()) return null;\r
+                               \r
+                               boolean isJar = f.getName().toLowerCase().endsWith(".jar");\r
+                               if (!isJar) return null;\r
+                               \r
+                               JarFile jf = new JarFile(f);\r
+                               try {\r
+                                       Enumeration<JarEntry> enm = jf.entries();\r
+                                       while (enm.hasMoreElements()) {\r
+                                               JarEntry entry = enm.nextElement();\r
+                                               String entryName = entry.getName();\r
+                                               if (! entryName.equals(filename) ) continue;\r
+                                               InputStream is = jf.getInputStream(entry);\r
+                                               byte[] data = StreamUtil.readFully(is);                                         \r
+                                               is.close();\r
+                                               return new ByteArrayInputStream(data);\r
+                                       }\r
+                               } finally {\r
+                                       jf.close();\r
+                               }\r
+                               \r
+                       } else {\r
+                               int size = Integer.valueOf( desc.getProperties().get("download.size") );\r
+                               ByteArrayOutputStream bos = new ByteArrayOutputStream(size);\r
+                               repo.getArtifact(desc, bos, null);\r
+                               ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());\r
+                               JarInputStream jis = new JarInputStream( bis );\r
+                               for (JarEntry entry = jis.getNextJarEntry(); entry!=null; entry = jis.getNextJarEntry()) {\r
+                                       String entryName = entry.getName();\r
+                                       if (! entryName.equals(filename) ) continue;                                    \r
+                                       return jis;\r
+                               }                               \r
+                               \r
+                       }\r
+               }\r
+               return null;\r
+       }       \r
+       /**\r
+        * Checks whether artifact is a graph bundle. \r
+        * \r
+        * @param repo artifact repo\r
+        * @param key key to artifact\r
+        * @return manifest or null\r
+        * @throws IOException \r
+        */\r
+       public static Manifest getManifest(IArtifactRepository repo, IArtifactKey key) throws IOException {\r
+               InputStream is = getFile(repo, key, "META-INF/MANIFEST.MF");\r
+               if (is == null) return null;\r
+               try {\r
+                       return new Manifest(is);\r
+               } finally {\r
+                       is.close();\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Checks whether artifact is a graph bundle. \r
+        * \r
+        * @param repo artifact repo\r
+        * @param key key to artifact\r
+        * @return manifest or null\r
+        * @throws IOException \r
+        */\r
+       public static Manifest getSimanticsManifest(IArtifactRepository repo, IArtifactKey key) throws IOException {\r
+               InputStream is = getFile(repo, key, "META-INF/SIMANTICS.MF");\r
+               if (is == null) return null;\r
+               try {\r
+                       return new Manifest(is);\r
+               } finally {\r
+                       is.close();\r
+               }\r
+       }\r
+       \r
+       public static IArtifactKey[] getAllArtifactKeys(IArtifactRepository repo) {\r
+               return repo.query( ArtifactKeyQuery.ALL_KEYS, null ).toArray( IArtifactKey.class );\r
+       }\r
+       \r
+       public static void getUserInstallables(IArtifactRepository repo, Collection<String> result) throws IOException {\r
+               IArtifactKey[] keys = repo.query( ArtifactKeyQuery.ALL_KEYS, null ).toArray( IArtifactKey.class );\r
+               for (IArtifactKey key : keys) {\r
+                       Manifest mf = getSimanticsManifest(repo, key);\r
+                       if (mf==null) continue;\r
+                       String bundleId = mf.getMainAttributes().getValue("Simantics-Feature-Bundle");\r
+                       result.add( bundleId );\r
+               }\r
+       }\r
+       \r
+       public static GraphBundle getGraphBundle(IArtifactRepository repo, IArtifactKey key, IInstallableUnit iu) \r
+       throws TransferableGraphException\r
+       {\r
+               String name = ProvisioningUtil.getName(iu);\r
+               TransferableGraph1 tg = getTransferableGraph(repo, key);                \r
+               return new GraphBundleEx(name, tg, key.getId(), key.getVersion());              \r
+       }\r
+       \r
+       /**\r
+        * Get the .tg file from a Graph bundle\r
+        * \r
+        * @param repo\r
+        * @param key\r
+        * @return byte[] transferable fraph\r
+        * @throws TGException\r
+        */\r
+       public static TransferableGraph1 getTransferableGraph(IArtifactRepository repo, IArtifactKey key) \r
+       throws TransferableGraphException\r
+       {\r
+               boolean isBundle = key.getClassifier().equals("osgi.bundle");\r
+               if (!isBundle) throw new TransferableGraphException("Artifact Key is not osgi.bundle");\r
+               \r
+               for (IArtifactDescriptor desc : repo.getArtifactDescriptors(key)) {             \r
+                       if (repo instanceof IFileArtifactRepository) {\r
+                               IFileArtifactRepository filerepo = (IFileArtifactRepository) repo;\r
+                               File f = filerepo.getArtifactFile(key);\r
+                               if (!f.exists()) {\r
+                                       throw new TransferableGraphException(f+" not found");\r
+                               }\r
+                               \r
+                               boolean isJar = f.getName().toLowerCase().endsWith(".jar");\r
+                               if (!isJar) throw new TransferableGraphException(f+" is not jar as expected");\r
+\r
+                               JarFile jf = null;\r
+                               try {\r
+                                       jf = new JarFile(f);\r
+                                       Enumeration<JarEntry> enm = jf.entries();\r
+                                       while (enm.hasMoreElements()) {\r
+                                               JarEntry entry = enm.nextElement();\r
+                                               String entryName = entry.getName().toLowerCase();\r
+                                               boolean isTG = entryName.equalsIgnoreCase("graph.tg");\r
+                                               if (!isTG) continue;\r
+                                               try {\r
+                                                       Binding binding = Bindings.getBindingUnchecked( TransferableGraph1.class );\r
+                                                       long size = entry.getSize();\r
+                                                       InputStream is = jf.getInputStream(entry);\r
+                                                       return (TransferableGraph1) Files.readFile(is, size, binding);\r
+                                               } catch (IOException e) {\r
+                                                       throw new TransferableGraphException(e);\r
+                                               }\r
+                                       }\r
+                               } catch (IOException e) {\r
+                                       throw new TransferableGraphException(e);\r
+                               } finally {\r
+                                       try {\r
+                                               if (jf!=null) jf.close();\r
+                                       } catch (IOException e) {\r
+                                       }\r
+                               }\r
+                               throw new TransferableGraphException(".tg file was not found in "+key);\r
+                               \r
+                       } else {\r
+                               try {\r
+                                       int size = Integer.valueOf( desc.getProperties().get("download.size") );\r
+                                       ByteArrayOutputStream bos = new ByteArrayOutputStream(size);\r
+                                       repo.getArtifact(desc, bos, null);\r
+                                       ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());\r
+                                       JarInputStream jis = new JarInputStream( bis );\r
+                                       for (JarEntry entry = jis.getNextJarEntry(); entry!=null; entry = jis.getNextJarEntry()) {\r
+                                               String entryName = entry.getName().toLowerCase();\r
+                                               boolean isTG = entryName.equalsIgnoreCase("graph.tg");\r
+                                               if (!isTG) continue;\r
+                                               //long fileSize = entry.getSize();\r
+                                               Binding binding = Bindings.getBindingUnchecked(TransferableGraph1.class);\r
+                                               return (TransferableGraph1) Files.readFile(jis, binding);\r
+                                               \r
+                                       }\r
+                               } catch (IOException e) {\r
+                                       throw new TransferableGraphException(e);\r
+                               }\r
+                               throw new TransferableGraphException(".tg file was not found in "+key);\r
+                       }\r
+               }\r
+               throw new TransferableGraphException(".tg file was not found in "+key);\r
+       }\r
+       \r
+       public static String getDescription(IInstallableUnit iu) {\r
+               return iu.getProperty("org.eclipse.equinox.p2.description");\r
+       }\r
+       \r
+       public static String getName(IInstallableUnit iu) {\r
+               return iu.getProperty("org.eclipse.equinox.p2.name");\r
+       }\r
+\r
+       /**\r
+        * Returns an IU corresponding to the given artifact key and bundle, or <code>null</code>\r
+        * if an IU could not be created.\r
+        */\r
+    public static IInstallableUnit createBundleIU(IArtifactKey artifactKey, File bundleFile) {\r
+               BundleDescription bundleDescription = null;\r
+               try {\r
+                       bundleDescription = BundlesAction.createBundleDescription(bundleFile);\r
+               } catch (IOException | BundleException e) {\r
+                       e.printStackTrace();\r
+               }\r
+               if (bundleDescription == null)\r
+                       return null;\r
+               PublisherInfo info = new PublisherInfo();\r
+               Version version = Version.create(bundleDescription.getVersion().toString());\r
+               AdviceFileAdvice advice = new AdviceFileAdvice(bundleDescription.getSymbolicName(), version, new Path(bundleFile.getAbsolutePath()), AdviceFileAdvice.BUNDLE_ADVICE_FILE);\r
+               if (advice.containsAdvice())\r
+                       info.addAdvice(advice);\r
+               String shape = bundleFile.isDirectory() ? IBundleShapeAdvice.DIR : IBundleShapeAdvice.JAR;\r
+               info.addAdvice(new BundleShapeAdvice(bundleDescription.getSymbolicName(), version, shape));\r
+               return BundlesAction.createBundleIU(bundleDescription, artifactKey, info);\r
+       }\r
+\r
+       public static IFileArtifactRepository getDownloadCacheRepo(IProvisioningAgent agent) throws ProvisionException {\r
+               return org.eclipse.equinox.internal.p2.touchpoint.natives.Util.getDownloadCacheRepo(agent);\r
+       }\r
+\r
+       public static Comparator<IInstallableUnit> getIUComparator() {\r
+               return new Comparator<IInstallableUnit>() {\r
+                       @Override\r
+                       public int compare(IInstallableUnit o1, IInstallableUnit o2) {\r
+                               return o1.getId().compareTo(o2.getId());\r
+                       }\r
+                       \r
+               };\r
+       }\r
+\r
+       public static TreeSet<IInstallableUnit> getSorted( Iterator<IInstallableUnit> iter ) {\r
+               TreeSet<IInstallableUnit> result = new TreeSet<IInstallableUnit>( getIUComparator() );\r
+               while (iter.hasNext()) {\r
+                       IInstallableUnit iu = iter.next();\r
+                       result.add( iu );\r
+               }\r
+               return result;\r
+       }\r
+\r
+       public static TreeSet<IInstallableUnit> getSorted( IQueryResult<IInstallableUnit> result ) {\r
+               return getSorted(result.iterator());\r
+       }\r
+       \r
+}\r
+\r