1 package org
.argeo
.osgi
.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
.osgi
.framework
.Bundle
;
22 import org
.osgi
.framework
.BundleContext
;
23 import org
.osgi
.framework
.BundleException
;
24 import org
.osgi
.framework
.Constants
;
25 import org
.osgi
.framework
.Version
;
27 /** Where components are retrieved from. */
28 public abstract class AbstractProvisioningSource
implements ProvisioningSource
{
29 protected final Map
<String
, A2Contribution
> contributions
= Collections
.synchronizedSortedMap(new TreeMap
<>());
31 public Iterable
<A2Contribution
> listContributions(Object filter
) {
32 return contributions
.values();
36 public Bundle
install(BundleContext bc
, A2Module module
) {
39 if (module
.getLocator() instanceof Path
&& Files
.isDirectory((Path
) module
.getLocator()))
40 tempJar
= toTempJar((Path
) module
.getLocator());
42 try (InputStream in
= newInputStream(tempJar
!= null ? tempJar
: module
.getLocator())) {
43 bundle
= bc
.installBundle(module
.getBranch().getCoordinates(), in
);
46 Files
.deleteIfExists(tempJar
);
48 } catch (BundleException
| IOException e
) {
49 throw new A2Exception("Cannot install module " + module
, e
);
54 public void update(Bundle bundle
, A2Module module
) {
57 if (module
.getLocator() instanceof Path
&& Files
.isDirectory((Path
) module
.getLocator()))
58 tempJar
= toTempJar((Path
) module
.getLocator());
59 try (InputStream in
= newInputStream(tempJar
!= null ? tempJar
: module
.getLocator())) {
63 Files
.deleteIfExists(tempJar
);
64 } catch (BundleException
| IOException e
) {
65 throw new A2Exception("Cannot update module " + module
, e
);
70 public A2Branch
findBranch(String componentId
, Version version
) {
71 A2Component component
= findComponent(componentId
);
72 if (component
== null)
74 String branchId
= version
.getMajor() + "." + version
.getMinor();
75 if (!component
.branches
.containsKey(branchId
))
77 return component
.branches
.get(branchId
);
80 protected A2Contribution
getOrAddContribution(String contributionId
) {
81 if (contributions
.containsKey(contributionId
))
82 return contributions
.get(contributionId
);
84 A2Contribution contribution
= new A2Contribution(this, contributionId
);
85 contributions
.put(contributionId
, contribution
);
90 protected void asTree(String prefix
, StringBuffer buf
) {
93 for (String contributionId
: contributions
.keySet()) {
95 buf
.append(contributionId
);
97 A2Contribution contribution
= contributions
.get(contributionId
);
98 contribution
.asTree(prefix
+ " ", buf
);
102 protected void asTree() {
103 StringBuffer buf
= new StringBuffer();
105 System
.out
.println(buf
);
108 protected A2Component
findComponent(String componentId
) {
109 SortedMap
<A2Contribution
, A2Component
> res
= new TreeMap
<>();
110 for (A2Contribution contribution
: contributions
.values()) {
111 components
: for (String componentIdKey
: contribution
.components
.keySet()) {
112 if (componentId
.equals(componentIdKey
)) {
113 res
.put(contribution
, contribution
.components
.get(componentIdKey
));
120 // TODO explicit contribution priorities
121 return res
.get(res
.lastKey());
125 protected String
readVersionFromModule(Path modulePath
) {
127 if (Files
.isDirectory(modulePath
)) {
128 manifest
= findManifest(modulePath
);
130 try (JarInputStream in
= new JarInputStream(newInputStream(modulePath
))) {
131 manifest
= in
.getManifest();
132 } catch (IOException e
) {
133 throw new A2Exception("Cannot read manifest from " + modulePath
, e
);
136 String versionStr
= manifest
.getMainAttributes().getValue(Constants
.BUNDLE_VERSION
);
140 protected String
readSymbolicNameFromModule(Path modulePath
) {
142 if (Files
.isDirectory(modulePath
)) {
143 manifest
= findManifest(modulePath
);
145 try (JarInputStream in
= new JarInputStream(newInputStream(modulePath
))) {
146 manifest
= in
.getManifest();
147 } catch (IOException e
) {
148 throw new A2Exception("Cannot read manifest from " + modulePath
, e
);
151 String symbolicName
= manifest
.getMainAttributes().getValue(Constants
.BUNDLE_SYMBOLICNAME
);
152 int semiColIndex
= symbolicName
.indexOf(';');
153 if (semiColIndex
>= 0)
154 symbolicName
= symbolicName
.substring(0, semiColIndex
);
158 private static Manifest
findManifest(Path currentPath
) {
159 Path metaInfPath
= currentPath
.resolve("META-INF");
160 if (Files
.exists(metaInfPath
) && Files
.isDirectory(metaInfPath
)) {
161 Path manifestPath
= metaInfPath
.resolve("MANIFEST.MF");
163 try (InputStream in
= Files
.newInputStream(manifestPath
)) {
164 Manifest manifest
= new Manifest(in
);
167 } catch (IOException e
) {
168 throw new A2Exception("Cannot read manifest from " + manifestPath
, e
);
171 Path parentPath
= currentPath
.getParent();
172 if (parentPath
== null)
173 throw new A2Exception("MANIFEST.MF file not found.");
174 return findManifest(currentPath
.getParent());
178 private static Path
toTempJar(Path dir
) {
180 Manifest manifest
= findManifest(dir
);
181 Path jarPath
= Files
.createTempFile("a2Source", ".jar");
182 try (JarOutputStream zos
= new JarOutputStream(new FileOutputStream(jarPath
.toFile()), manifest
)) {
183 Files
.walkFileTree(dir
, new SimpleFileVisitor
<Path
>() {
184 public FileVisitResult
visitFile(Path file
, BasicFileAttributes attrs
) throws IOException
{
185 Path relPath
= dir
.relativize(file
);
186 // skip MANIFEST from folder
187 if (relPath
.toString().contentEquals("META-INF/MANIFEST.MF"))
188 return FileVisitResult
.CONTINUE
;
189 zos
.putNextEntry(new ZipEntry(relPath
.toString()));
190 Files
.copy(file
, zos
);
192 return FileVisitResult
.CONTINUE
;
197 } catch (IOException e
) {
198 throw new A2Exception("Cannot install OSGi bundle from " + dir
, e
);
203 private InputStream
newInputStream(Object locator
) throws IOException
{
204 if (locator
instanceof Path
) {
205 return Files
.newInputStream((Path
) locator
);
206 } else if (locator
instanceof URL
) {
207 return ((URL
) locator
).openStream();
209 throw new IllegalArgumentException("Unsupported module locator type " + locator
.getClass());