]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.project/src/org/simantics/project/management/ProvisioningUtil.java
Support ontology install option trueWhenDeployed also during development
[simantics/platform.git] / bundles / org.simantics.project / src / org / simantics / project / management / ProvisioningUtil.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.project.management;
13
14 import java.io.ByteArrayInputStream;
15 import java.io.ByteArrayOutputStream;
16 import java.io.File;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.util.Collection;
20 import java.util.Comparator;
21 import java.util.Enumeration;
22 import java.util.Iterator;
23 import java.util.Set;
24 import java.util.TreeSet;
25 import java.util.jar.JarEntry;
26 import java.util.jar.JarFile;
27 import java.util.jar.JarInputStream;
28 import java.util.jar.Manifest;
29
30 import org.eclipse.core.runtime.Path;
31 import org.eclipse.equinox.internal.p2.metadata.RequiredCapability;
32 import org.eclipse.equinox.internal.p2.touchpoint.eclipse.Util;
33 import org.eclipse.equinox.internal.p2.ui.query.RequiredIUsQuery;
34 import org.eclipse.equinox.p2.core.IProvisioningAgent;
35 import org.eclipse.equinox.p2.core.ProvisionException;
36 import org.eclipse.equinox.p2.metadata.IArtifactKey;
37 import org.eclipse.equinox.p2.metadata.IInstallableUnit;
38 import org.eclipse.equinox.p2.metadata.IInstallableUnitFragment;
39 import org.eclipse.equinox.p2.metadata.IRequirement;
40 import org.eclipse.equinox.p2.metadata.Version;
41 import org.eclipse.equinox.p2.publisher.AdviceFileAdvice;
42 import org.eclipse.equinox.p2.publisher.PublisherInfo;
43 import org.eclipse.equinox.p2.publisher.eclipse.BundleShapeAdvice;
44 import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
45 import org.eclipse.equinox.p2.publisher.eclipse.IBundleShapeAdvice;
46 import org.eclipse.equinox.p2.query.IQuery;
47 import org.eclipse.equinox.p2.query.IQueryResult;
48 import org.eclipse.equinox.p2.query.IQueryable;
49 import org.eclipse.equinox.p2.query.QueryUtil;
50 import org.eclipse.equinox.p2.repository.artifact.ArtifactKeyQuery;
51 import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
52 import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
53 import org.eclipse.equinox.p2.repository.artifact.IFileArtifactRepository;
54 import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
55 import org.eclipse.osgi.service.resolver.BundleDescription;
56 import org.osgi.framework.BundleException;
57 import org.simantics.databoard.Bindings;
58 import org.simantics.databoard.Files;
59 import org.simantics.databoard.binding.Binding;
60 import org.simantics.databoard.util.StreamUtil;
61 import org.simantics.graph.db.TransferableGraphException;
62 import org.simantics.graph.representation.TransferableGraph1;
63
64 /**
65  * This class contains provisioning utilities.
66  *
67  * @see QueryUtil
68  * @see Util
69  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
70  */
71 @SuppressWarnings("restriction")
72 public class ProvisioningUtil {
73
74         private static IRequirement IS_FEATURE_REQUIREMENT = new RequiredCapability("org.eclipse.equinox.p2.eclipse.type", "feature", null, null, false, false, false);
75
76         public static void getAllRequirements(IInstallableUnit iu, IQueryable<IInstallableUnit> repo, Set<IInstallableUnit> result) 
77         {
78                 if (result.contains(iu)) return;
79                 result.add(iu);
80                 IQuery<IInstallableUnit> reqsQuery = new RequiredIUsQuery(iu);
81                 for (IInstallableUnit _iu : repo.query( reqsQuery, null ).toSet()) {
82                         if (result.contains(_iu)) continue;
83                         getAllRequirements(_iu, repo, result);
84                 }               
85         }
86         
87         
88         /**
89          * Get IUs that are required to install this bundle. 
90          * Assumed architecture is x86 and os win32. 
91          * Throws an exception if not all requirements can be satisfied.
92          * 
93          * @param iu
94          * @param availableIUs
95          * @return
96          */
97         /*
98         public static Collection<IRequirement> getAllRequirements(IInstallableUnit iu, IQueryable<IInstallableUnit> repo)
99         {               
100                 // Installable Units analysed
101                 Set<IInstallableUnit> ius = new HashSet<IInstallableUnit>();
102                 
103                 // Requirements
104                 Set<IRequirement> reqs = new HashSet<IRequirement>();
105                 
106                 // Satisfied requirements
107                 Set<IRequirement> sats = new HashSet<IRequirement>();
108                 ius.add(iu);
109                 reqs.addAll( iu.getRequirements() );
110                 
111                 // Find satisfactions
112                 return result;
113         }*/
114         /*
115         static void _addIU(IInstallableUnit iu, Set<IInstallableUnit> ius, Set<IRequirement> reqs, Set<IRequirement> sats, Set<IRequirement> unsats, IQueryable<IInstallableUnit> repo) 
116         {
117                 if (ius.contains(iu)) return;
118                 ius.add( iu );
119                 
120                 for (IRequirement req : iu.getRequirements()) {
121                         if (sats.contains(req)) continue;
122                         if (unsats.contains(req)) continue;
123                         
124                         // req is unsatisfied
125                         IQuery
126                         IQueryResult<IInstallableUnit> result = repo.query(req, null);
127                 }
128                 
129                 for (IInstallableUnit _iu : availableIUs) {
130                         if (sats.contains(_iu)) continue;
131                         
132                         boolean satisfies = _iu.satisfies(  ) 
133                 }
134         }*/
135         
136         /**
137          * Get all installable units from a metadata repository
138          * 
139          * @param repo
140          * @return
141          */
142         public static Collection<IInstallableUnit> getInstallableUnits(IMetadataRepository repo) {
143                 
144 //              IQuery<IInstallableUnit> query = QueryUtil.createIUQuery(null, VersionRange.emptyRange);
145                 IQuery<IInstallableUnit> query = QueryUtil.createIUAnyQuery();
146             IQueryResult<IInstallableUnit> matches = repo.query(query, null);
147             return matches.toUnmodifiableSet();
148         }
149         
150
151         /**
152          * Test if the {@link IInstallableUnit} is a category. 
153          * @param iu the element being tested.
154          * @return <tt>true</tt> if the parameter is a category.
155          */
156         public static boolean isCategory(IInstallableUnit iu) {
157                 String PROP_TYPE_CATEGORY = "org.eclipse.equinox.p2.type.category"; //$NON-NLS-1$
158                 String value = iu.getProperty(PROP_TYPE_CATEGORY);
159                 if (value != null && (value.equals(Boolean.TRUE.toString())))
160                         return true;
161                 return false;
162         }
163
164         /**
165          * Test if the {@link IInstallableUnit} is a fragment. 
166          * @param iu the element being tested.
167          * @return <tt>true</tt> if the parameter is a fragment.
168          */
169         public static boolean isFragment(IInstallableUnit iu) {
170                 return iu instanceof IInstallableUnitFragment;
171         }
172
173         /**
174          * Test if the {@link IInstallableUnit} is a group. 
175          * @param iu the element being tested.
176          * @return <tt>true</tt> if the parameter is a group.
177          */
178         public static boolean isGroup(IInstallableUnit iu) {
179                 String PROP_TYPE_GROUP = "org.eclipse.equinox.p2.type.group"; //$NON-NLS-1$
180                 String value = iu.getProperty(PROP_TYPE_GROUP);
181                 if (value != null && (value.equals(Boolean.TRUE.toString())))
182                         return true;
183                 return false;
184         }
185
186         /**
187          * Test if the {@link IInstallableUnit} is a patch. 
188          * @param iu the element being tested.
189          * @return <tt>true</tt> if the parameter is a patch.
190          */
191         public static boolean isPatch(IInstallableUnit iu) {
192                 String PROP_TYPE_PATCH = "org.eclipse.equinox.p2.type.patch"; //$NON-NLS-1$
193                 String value = iu.getProperty(PROP_TYPE_PATCH);
194                 if (value != null && (value.equals(Boolean.TRUE.toString())))
195                         return true;
196                 return false;
197         }
198         
199         /**
200          * Checks whether a installable unit is a feature
201          * 
202          * @param iu
203          * @return <code>true</code> if is feature
204          */
205         public static boolean isFeature(IInstallableUnit iu) {
206 //              String value = iu.getProperty("org.eclipse.equinox.p2.eclipse.type");
207 //              return value != null && value.equals("feature");
208         return iu.satisfies(IS_FEATURE_REQUIREMENT);
209         }
210
211         public static boolean isGraph(IInstallableUnit iu, IMetadataRepository metadata, IArtifactRepository arts) throws IOException {
212         Collection<IArtifactKey> artifacts = iu.getArtifacts();
213         for (IArtifactKey key : artifacts) {
214                         if (isGraphArtifact(arts, key)) return true;                    
215         }
216                 return false;
217         }
218
219         /**
220          * Checks whether artifact is a graph bundle. 
221          * 
222          * @param repo artifact repo
223          * @param key key to artifact
224          * @return <code>true</code> if is a graph bundle
225          * @throws IOException 
226          */
227         public static boolean isGraphArtifact(IArtifactRepository repo, IArtifactKey key) throws IOException {
228                 return hasFile(repo, key, "graph.tg");
229         }
230         
231         public static boolean hasFile(IArtifactRepository repo, IArtifactKey key, String filename) throws IOException {
232                 boolean isBundle = key.getClassifier().equals("osgi.bundle");
233                 if (!isBundle) return false;
234                 
235                 for (IArtifactDescriptor desc : repo.getArtifactDescriptors(key)) {             
236                         if (repo instanceof IFileArtifactRepository) {                          
237                                 IFileArtifactRepository filerepo = (IFileArtifactRepository) repo;
238                                 File f = filerepo.getArtifactFile(key);
239                                 if (!f.exists()) return false;
240                                 
241                                 boolean isJar = f.getName().toLowerCase().endsWith(".jar");
242                                 if (!isJar) return false;
243                                 
244                                 JarFile jf = new JarFile(f);
245                                 try {
246                                         Enumeration<JarEntry> enm = jf.entries();
247                                         while (enm.hasMoreElements()) {
248                                                 JarEntry entry = enm.nextElement();
249                                                 String entryName = entry.getName();
250                                                 if ( entryName.equals(filename) ) return true;
251                                         }
252                                 } finally {
253                                         jf.close();
254                                 }
255                                 
256                         } else {
257                                 int size = Integer.valueOf( desc.getProperties().get("download.size") );
258                                 ByteArrayOutputStream bos = new ByteArrayOutputStream(size);
259                                 repo.getArtifact(desc, bos, null);
260                                 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
261                                 JarInputStream jis = new JarInputStream( bis );
262                                 for (JarEntry entry = jis.getNextJarEntry(); entry!=null; entry = jis.getNextJarEntry()) {
263                                         String entryName = entry.getName();
264                                         if ( entryName.equals(filename) ) return true;
265                                 }                               
266                                 
267                         }
268                 }
269                 return false;
270         }
271
272         /**
273          * Get a file from a repository
274          * 
275          * @param repo artifact repo
276          * @param key key to artifact
277          * @return input stream (must be closed) or null
278          * @throws IOException 
279          */
280         public static InputStream getFile(IArtifactRepository repo, IArtifactKey key, String filename) throws IOException {
281                 boolean isBundle = key.getClassifier().equals("osgi.bundle");
282                 if (!isBundle) return null;
283                 
284                 for (IArtifactDescriptor desc : repo.getArtifactDescriptors(key)) {             
285                         if (repo instanceof IFileArtifactRepository) {                          
286                                 IFileArtifactRepository filerepo = (IFileArtifactRepository) repo;
287                                 File f = filerepo.getArtifactFile(key);
288                                 if (!f.exists()) return null;
289                                 
290                                 boolean isJar = f.getName().toLowerCase().endsWith(".jar");
291                                 if (!isJar) return null;
292                                 
293                                 JarFile jf = new JarFile(f);
294                                 try {
295                                         Enumeration<JarEntry> enm = jf.entries();
296                                         while (enm.hasMoreElements()) {
297                                                 JarEntry entry = enm.nextElement();
298                                                 String entryName = entry.getName();
299                                                 if (! entryName.equals(filename) ) continue;
300                                                 InputStream is = jf.getInputStream(entry);
301                                                 byte[] data = StreamUtil.readFully(is);                                         
302                                                 is.close();
303                                                 return new ByteArrayInputStream(data);
304                                         }
305                                 } finally {
306                                         jf.close();
307                                 }
308                                 
309                         } else {
310                                 int size = Integer.valueOf( desc.getProperties().get("download.size") );
311                                 ByteArrayOutputStream bos = new ByteArrayOutputStream(size);
312                                 repo.getArtifact(desc, bos, null);
313                                 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
314                                 JarInputStream jis = new JarInputStream( bis );
315                                 for (JarEntry entry = jis.getNextJarEntry(); entry!=null; entry = jis.getNextJarEntry()) {
316                                         String entryName = entry.getName();
317                                         if (! entryName.equals(filename) ) continue;                                    
318                                         return jis;
319                                 }                               
320                                 
321                         }
322                 }
323                 return null;
324         }       
325         /**
326          * Checks whether artifact is a graph bundle. 
327          * 
328          * @param repo artifact repo
329          * @param key key to artifact
330          * @return manifest or null
331          * @throws IOException 
332          */
333         public static Manifest getManifest(IArtifactRepository repo, IArtifactKey key) throws IOException {
334                 InputStream is = getFile(repo, key, "META-INF/MANIFEST.MF");
335                 if (is == null) return null;
336                 try {
337                         return new Manifest(is);
338                 } finally {
339                         is.close();
340                 }
341         }
342         
343         /**
344          * Checks whether artifact is a graph bundle. 
345          * 
346          * @param repo artifact repo
347          * @param key key to artifact
348          * @return manifest or null
349          * @throws IOException 
350          */
351         public static Manifest getSimanticsManifest(IArtifactRepository repo, IArtifactKey key) throws IOException {
352                 InputStream is = getFile(repo, key, "META-INF/SIMANTICS.MF");
353                 if (is == null) return null;
354                 try {
355                         return new Manifest(is);
356                 } finally {
357                         is.close();
358                 }
359         }
360         
361         public static IArtifactKey[] getAllArtifactKeys(IArtifactRepository repo) {
362                 return repo.query( ArtifactKeyQuery.ALL_KEYS, null ).toArray( IArtifactKey.class );
363         }
364         
365         public static void getUserInstallables(IArtifactRepository repo, Collection<String> result) throws IOException {
366                 IArtifactKey[] keys = repo.query( ArtifactKeyQuery.ALL_KEYS, null ).toArray( IArtifactKey.class );
367                 for (IArtifactKey key : keys) {
368                         Manifest mf = getSimanticsManifest(repo, key);
369                         if (mf==null) continue;
370                         String bundleId = mf.getMainAttributes().getValue("Simantics-Feature-Bundle");
371                         result.add( bundleId );
372                 }
373         }
374         
375         public static GraphBundle getGraphBundle(IArtifactRepository repo, IArtifactKey key, IInstallableUnit iu) 
376         throws TransferableGraphException
377         {
378                 String name = ProvisioningUtil.getName(iu);
379                 TransferableGraph1 tg = getTransferableGraph(repo, key);                
380                 return new GraphBundleEx(name, tg, key.getId(), key.getVersion());              
381         }
382         
383         /**
384          * Get the .tg file from a Graph bundle
385          * 
386          * @param repo
387          * @param key
388          * @return byte[] transferable fraph
389          * @throws TGException
390          */
391         public static TransferableGraph1 getTransferableGraph(IArtifactRepository repo, IArtifactKey key) 
392         throws TransferableGraphException
393         {
394                 boolean isBundle = key.getClassifier().equals("osgi.bundle");
395                 if (!isBundle) throw new TransferableGraphException("Artifact Key is not osgi.bundle");
396                 
397                 for (IArtifactDescriptor desc : repo.getArtifactDescriptors(key)) {             
398                         if (repo instanceof IFileArtifactRepository) {
399                                 IFileArtifactRepository filerepo = (IFileArtifactRepository) repo;
400                                 File f = filerepo.getArtifactFile(key);
401                                 if (!f.exists()) {
402                                         throw new TransferableGraphException(f+" not found");
403                                 }
404                                 
405                                 boolean isJar = f.getName().toLowerCase().endsWith(".jar");
406                                 if (!isJar) throw new TransferableGraphException(f+" is not jar as expected");
407
408                                 JarFile jf = null;
409                                 try {
410                                         jf = new JarFile(f);
411                                         Enumeration<JarEntry> enm = jf.entries();
412                                         while (enm.hasMoreElements()) {
413                                                 JarEntry entry = enm.nextElement();
414                                                 String entryName = entry.getName().toLowerCase();
415                                                 boolean isTG = entryName.equalsIgnoreCase("graph.tg");
416                                                 if (!isTG) continue;
417                                                 try {
418                                                         Binding binding = Bindings.getBindingUnchecked( TransferableGraph1.class );
419                                                         long size = entry.getSize();
420                                                         InputStream is = jf.getInputStream(entry);
421                                                         return (TransferableGraph1) Files.readFile(is, size, binding);
422                                                 } catch (IOException e) {
423                                                         throw new TransferableGraphException(e);
424                                                 }
425                                         }
426                                 } catch (IOException e) {
427                                         throw new TransferableGraphException(e);
428                                 } finally {
429                                         try {
430                                                 if (jf!=null) jf.close();
431                                         } catch (IOException e) {
432                                         }
433                                 }
434                                 throw new TransferableGraphException(".tg file was not found in "+key);
435                                 
436                         } else {
437                                 try {
438                                         int size = Integer.valueOf( desc.getProperties().get("download.size") );
439                                         ByteArrayOutputStream bos = new ByteArrayOutputStream(size);
440                                         repo.getArtifact(desc, bos, null);
441                                         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
442                                         JarInputStream jis = new JarInputStream( bis );
443                                         for (JarEntry entry = jis.getNextJarEntry(); entry!=null; entry = jis.getNextJarEntry()) {
444                                                 String entryName = entry.getName().toLowerCase();
445                                                 boolean isTG = entryName.equalsIgnoreCase("graph.tg");
446                                                 if (!isTG) continue;
447                                                 //long fileSize = entry.getSize();
448                                                 Binding binding = Bindings.getBindingUnchecked(TransferableGraph1.class);
449                                                 return (TransferableGraph1) Files.readFile(jis, binding);
450                                                 
451                                         }
452                                 } catch (IOException e) {
453                                         throw new TransferableGraphException(e);
454                                 }
455                                 throw new TransferableGraphException(".tg file was not found in "+key);
456                         }
457                 }
458                 throw new TransferableGraphException(".tg file was not found in "+key);
459         }
460         
461         public static String getDescription(IInstallableUnit iu) {
462                 return iu.getProperty("org.eclipse.equinox.p2.description");
463         }
464         
465         public static String getName(IInstallableUnit iu) {
466                 return iu.getProperty("org.eclipse.equinox.p2.name");
467         }
468
469         /**
470          * Returns an IU corresponding to the given artifact key and bundle, or <code>null</code>
471          * if an IU could not be created.
472          */
473     public static IInstallableUnit createBundleIU(IArtifactKey artifactKey, File bundleFile) {
474                 BundleDescription bundleDescription = null;
475                 try {
476                         bundleDescription = BundlesAction.createBundleDescription(bundleFile);
477                 } catch (IOException | BundleException e) {
478                         e.printStackTrace();
479                 }
480                 if (bundleDescription == null)
481                         return null;
482                 PublisherInfo info = new PublisherInfo();
483                 Version version = Version.create(bundleDescription.getVersion().toString());
484                 AdviceFileAdvice advice = new AdviceFileAdvice(bundleDescription.getSymbolicName(), version, new Path(bundleFile.getAbsolutePath()), AdviceFileAdvice.BUNDLE_ADVICE_FILE);
485                 if (advice.containsAdvice())
486                         info.addAdvice(advice);
487                 String shape = bundleFile.isDirectory() ? IBundleShapeAdvice.DIR : IBundleShapeAdvice.JAR;
488                 info.addAdvice(new BundleShapeAdvice(bundleDescription.getSymbolicName(), version, shape));
489                 return BundlesAction.createBundleIU(bundleDescription, artifactKey, info);
490         }
491
492         public static IFileArtifactRepository getDownloadCacheRepo(IProvisioningAgent agent) throws ProvisionException {
493                 return org.eclipse.equinox.internal.p2.touchpoint.natives.Util.getDownloadCacheRepo(agent);
494         }
495
496         public static Comparator<IInstallableUnit> getIUComparator() {
497                 return new Comparator<IInstallableUnit>() {
498                         @Override
499                         public int compare(IInstallableUnit o1, IInstallableUnit o2) {
500                                 return o1.getId().compareTo(o2.getId());
501                         }
502                         
503                 };
504         }
505
506         public static TreeSet<IInstallableUnit> getSorted( Iterator<IInstallableUnit> iter ) {
507                 TreeSet<IInstallableUnit> result = new TreeSet<IInstallableUnit>( getIUComparator() );
508                 while (iter.hasNext()) {
509                         IInstallableUnit iu = iter.next();
510                         result.add( iu );
511                 }
512                 return result;
513         }
514
515         public static TreeSet<IInstallableUnit> getSorted( IQueryResult<IInstallableUnit> result ) {
516                 return getSorted(result.iterator());
517         }
518         
519 }
520