1 package org
.argeo
.osgi
.boot
.a2
;
3 import java
.io
.FileOutputStream
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStream
;
7 import java
.nio
.file
.FileVisitResult
;
8 import java
.nio
.file
.Files
;
9 import java
.nio
.file
.Path
;
10 import java
.nio
.file
.SimpleFileVisitor
;
11 import java
.nio
.file
.attribute
.BasicFileAttributes
;
12 import java
.util
.Collections
;
14 import java
.util
.SortedMap
;
15 import java
.util
.TreeMap
;
16 import java
.util
.jar
.JarInputStream
;
17 import java
.util
.jar
.JarOutputStream
;
18 import java
.util
.jar
.Manifest
;
19 import java
.util
.zip
.ZipEntry
;
21 import org
.argeo
.osgi
.boot
.OsgiBootException
;
22 import org
.osgi
.framework
.Bundle
;
23 import org
.osgi
.framework
.BundleContext
;
24 import org
.osgi
.framework
.BundleException
;
25 import org
.osgi
.framework
.Constants
;
26 import org
.osgi
.framework
.Version
;
28 /** Where components are retrieved from. */
29 abstract class ProvisioningSource
{
30 final Map
<String
, A2Contribution
> contributions
= Collections
.synchronizedSortedMap(new TreeMap
<>());
32 A2Contribution
getOrAddContribution(String contributionId
) {
33 if (contributions
.containsKey(contributionId
))
34 return contributions
.get(contributionId
);
36 return new A2Contribution(this, contributionId
);
39 void asTree(String prefix
, StringBuffer buf
) {
42 for (String contributionId
: contributions
.keySet()) {
44 buf
.append(contributionId
);
46 A2Contribution contribution
= contributions
.get(contributionId
);
47 contribution
.asTree(prefix
+ " ", buf
);
52 StringBuffer buf
= new StringBuffer();
54 System
.out
.println(buf
);
57 A2Component
findComponent(String componentId
) {
58 SortedMap
<A2Contribution
, A2Component
> res
= new TreeMap
<>();
59 for (A2Contribution contribution
: contributions
.values()) {
60 components
: for (String componentIdKey
: contribution
.components
.keySet()) {
61 if (componentId
.equals(componentIdKey
)) {
62 res
.put(contribution
, contribution
.components
.get(componentIdKey
));
69 // TODO explicit contribution priorities
70 return res
.get(res
.lastKey());
74 A2Branch
findBranch(String componentId
, Version version
) {
75 A2Component component
= findComponent(componentId
);
76 if (component
== null)
78 String branchId
= version
.getMajor() + "." + version
.getMinor();
79 if (!component
.branches
.containsKey(branchId
))
81 return component
.branches
.get(branchId
);
84 protected String
readVersionFromModule(Path modulePath
) {
86 if (Files
.isDirectory(modulePath
)) {
87 manifest
= findManifest(modulePath
);
89 try (JarInputStream in
= new JarInputStream(newInputStream(modulePath
))) {
90 manifest
= in
.getManifest();
91 } catch (IOException e
) {
92 throw new OsgiBootException("Cannot read manifest from " + modulePath
, e
);
95 String versionStr
= manifest
.getMainAttributes().getValue(Constants
.BUNDLE_VERSION
);
99 protected String
readSymbolicNameFromModule(Path modulePath
) {
101 if (Files
.isDirectory(modulePath
)) {
102 manifest
= findManifest(modulePath
);
104 try (JarInputStream in
= new JarInputStream(newInputStream(modulePath
))) {
105 manifest
= in
.getManifest();
106 } catch (IOException e
) {
107 throw new OsgiBootException("Cannot read manifest from " + modulePath
, e
);
110 String symbolicName
= manifest
.getMainAttributes().getValue(Constants
.BUNDLE_SYMBOLICNAME
);
111 int semiColIndex
= symbolicName
.indexOf(';');
112 if (semiColIndex
>= 0)
113 symbolicName
= symbolicName
.substring(0, semiColIndex
);
117 private static Manifest
findManifest(Path currentPath
) {
118 Path metaInfPath
= currentPath
.resolve("META-INF");
119 if (Files
.exists(metaInfPath
) && Files
.isDirectory(metaInfPath
)) {
120 Path manifestPath
= metaInfPath
.resolve("MANIFEST.MF");
122 try (InputStream in
= Files
.newInputStream(manifestPath
)) {
123 Manifest manifest
= new Manifest(in
);
126 } catch (IOException e
) {
127 throw new OsgiBootException("Cannot read manifest from " + manifestPath
, e
);
130 Path parentPath
= currentPath
.getParent();
131 if (parentPath
== null)
132 throw new OsgiBootException("MANIFEST.MF file not found.");
133 return findManifest(currentPath
.getParent());
137 public Bundle
install(BundleContext bc
, A2Module module
) throws IOException
, BundleException
{
139 if (module
.getLocator() instanceof Path
&& Files
.isDirectory((Path
) module
.getLocator()))
140 tempJar
= toTempJar((Path
) module
.getLocator());
142 try (InputStream in
= newInputStream(tempJar
!= null ? tempJar
: module
.getLocator())) {
143 bundle
= bc
.installBundle(module
.getBranch().getCoordinates(), in
);
146 Files
.deleteIfExists(tempJar
);
150 public void update(Bundle bundle
, A2Module module
) throws IOException
, BundleException
{
152 if (module
.getLocator() instanceof Path
&& Files
.isDirectory((Path
) module
.getLocator()))
153 tempJar
= toTempJar((Path
) module
.getLocator());
154 try (InputStream in
= newInputStream(tempJar
!= null ? tempJar
: module
.getLocator())) {
158 Files
.deleteIfExists(tempJar
);
161 static Path
toTempJar(Path dir
) {
163 Manifest manifest
= findManifest(dir
);
164 Path jarPath
= Files
.createTempFile("a2Source", ".jar");
165 try (JarOutputStream zos
= new JarOutputStream(new FileOutputStream(jarPath
.toFile()), manifest
)) {
166 Files
.walkFileTree(dir
, new SimpleFileVisitor
<Path
>() {
167 public FileVisitResult
visitFile(Path file
, BasicFileAttributes attrs
) throws IOException
{
168 Path relPath
= dir
.relativize(file
);
169 // skip MANIFEST from folder
170 if (relPath
.toString().contentEquals("META-INF/MANIFEST.MF"))
171 return FileVisitResult
.CONTINUE
;
172 zos
.putNextEntry(new ZipEntry(relPath
.toString()));
173 Files
.copy(file
, zos
);
175 return FileVisitResult
.CONTINUE
;
180 } catch (IOException e
) {
181 throw new OsgiBootException("Cannot install OSGi bundle from " + dir
, e
);
186 private InputStream
newInputStream(Object locator
) throws IOException
{
187 if (locator
instanceof Path
) {
188 return Files
.newInputStream((Path
) locator
);
189 } else if (locator
instanceof URL
) {
190 return ((URL
) locator
).openStream();
192 throw new IllegalArgumentException("Unsupported module locator type " + locator
.getClass());