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