1 package org
.argeo
.init
.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 private final boolean useReference
;
33 public AbstractProvisioningSource(boolean useReference
) {
34 this.useReference
= useReference
;
37 public Iterable
<A2Contribution
> listContributions(Object filter
) {
38 return contributions
.values();
42 public Bundle
install(BundleContext bc
, A2Module module
) {
44 Object locator
= module
.getLocator();
45 if (useReference
&& locator
instanceof Path locatorPath
) {
46 String referenceUrl
= "reference:file:" + locatorPath
.toString();
47 Bundle bundle
= bc
.installBundle(referenceUrl
);
52 if (locator
instanceof Path
&& Files
.isDirectory((Path
) locator
))
53 tempJar
= toTempJar((Path
) locator
);
55 try (InputStream in
= newInputStream(tempJar
!= null ? tempJar
: locator
)) {
56 bundle
= bc
.installBundle(module
.getBranch().getCoordinates(), in
);
60 Files
.deleteIfExists(tempJar
);
63 } catch (BundleException
| IOException e
) {
64 throw new A2Exception("Cannot install module " + module
, e
);
69 public void update(Bundle bundle
, A2Module module
) {
71 Object locator
= module
.getLocator();
72 if (useReference
&& locator
instanceof Path
) {
73 try (InputStream in
= newInputStream(locator
)) {
78 if (locator
instanceof Path
&& Files
.isDirectory((Path
) locator
))
79 tempJar
= toTempJar((Path
) locator
);
80 try (InputStream in
= newInputStream(tempJar
!= null ? tempJar
: locator
)) {
84 Files
.deleteIfExists(tempJar
);
86 } catch (BundleException
| IOException e
) {
87 throw new A2Exception("Cannot update module " + module
, e
);
92 public A2Branch
findBranch(String componentId
, Version version
) {
93 A2Component component
= findComponent(componentId
);
94 if (component
== null)
96 String branchId
= version
.getMajor() + "." + version
.getMinor();
97 if (!component
.branches
.containsKey(branchId
))
99 return component
.branches
.get(branchId
);
102 protected A2Contribution
getOrAddContribution(String contributionId
) {
103 if (contributions
.containsKey(contributionId
))
104 return contributions
.get(contributionId
);
106 A2Contribution contribution
= new A2Contribution(this, contributionId
);
107 contributions
.put(contributionId
, contribution
);
112 protected void asTree(String prefix
, StringBuffer buf
) {
115 for (String contributionId
: contributions
.keySet()) {
117 buf
.append(contributionId
);
119 A2Contribution contribution
= contributions
.get(contributionId
);
120 contribution
.asTree(prefix
+ " ", buf
);
124 protected void asTree() {
125 StringBuffer buf
= new StringBuffer();
127 System
.out
.println(buf
);
130 protected A2Component
findComponent(String componentId
) {
131 SortedMap
<A2Contribution
, A2Component
> res
= new TreeMap
<>();
132 for (A2Contribution contribution
: contributions
.values()) {
133 components
: for (String componentIdKey
: contribution
.components
.keySet()) {
134 if (componentId
.equals(componentIdKey
)) {
135 res
.put(contribution
, contribution
.components
.get(componentIdKey
));
142 // TODO explicit contribution priorities
143 return res
.get(res
.lastKey());
147 protected String
[] readNameVersionFromModule(Path modulePath
) {
149 if (Files
.isDirectory(modulePath
)) {
150 manifest
= findManifest(modulePath
);
152 try (JarInputStream in
= new JarInputStream(newInputStream(modulePath
))) {
153 manifest
= in
.getManifest();
154 } catch (IOException e
) {
155 throw new A2Exception("Cannot read manifest from " + modulePath
, e
);
158 String versionStr
= manifest
.getMainAttributes().getValue(Constants
.BUNDLE_VERSION
);
159 String symbolicName
= manifest
.getMainAttributes().getValue(Constants
.BUNDLE_SYMBOLICNAME
);
160 int semiColIndex
= symbolicName
.indexOf(';');
161 if (semiColIndex
>= 0)
162 symbolicName
= symbolicName
.substring(0, semiColIndex
);
163 return new String
[] { symbolicName
, versionStr
};
166 protected String
readVersionFromModule(Path modulePath
) {
168 if (Files
.isDirectory(modulePath
)) {
169 manifest
= findManifest(modulePath
);
171 try (JarInputStream in
= new JarInputStream(newInputStream(modulePath
))) {
172 manifest
= in
.getManifest();
173 } catch (IOException e
) {
174 throw new A2Exception("Cannot read manifest from " + modulePath
, e
);
177 String versionStr
= manifest
.getMainAttributes().getValue(Constants
.BUNDLE_VERSION
);
181 protected String
readSymbolicNameFromModule(Path modulePath
) {
183 if (Files
.isDirectory(modulePath
)) {
184 manifest
= findManifest(modulePath
);
186 try (JarInputStream in
= new JarInputStream(newInputStream(modulePath
))) {
187 manifest
= in
.getManifest();
188 } catch (IOException e
) {
189 throw new A2Exception("Cannot read manifest from " + modulePath
, e
);
192 String symbolicName
= manifest
.getMainAttributes().getValue(Constants
.BUNDLE_SYMBOLICNAME
);
193 int semiColIndex
= symbolicName
.indexOf(';');
194 if (semiColIndex
>= 0)
195 symbolicName
= symbolicName
.substring(0, semiColIndex
);
199 private static Manifest
findManifest(Path currentPath
) {
200 Path metaInfPath
= currentPath
.resolve("META-INF");
201 if (Files
.exists(metaInfPath
) && Files
.isDirectory(metaInfPath
)) {
202 Path manifestPath
= metaInfPath
.resolve("MANIFEST.MF");
204 try (InputStream in
= Files
.newInputStream(manifestPath
)) {
205 Manifest manifest
= new Manifest(in
);
208 } catch (IOException e
) {
209 throw new A2Exception("Cannot read manifest from " + manifestPath
, e
);
212 Path parentPath
= currentPath
.getParent();
213 if (parentPath
== null)
214 throw new A2Exception("MANIFEST.MF file not found.");
215 return findManifest(currentPath
.getParent());
219 private static Path
toTempJar(Path dir
) {
221 Manifest manifest
= findManifest(dir
);
222 Path jarPath
= Files
.createTempFile("a2Source", ".jar");
223 try (JarOutputStream zos
= new JarOutputStream(new FileOutputStream(jarPath
.toFile()), manifest
)) {
224 Files
.walkFileTree(dir
, new SimpleFileVisitor
<Path
>() {
225 public FileVisitResult
visitFile(Path file
, BasicFileAttributes attrs
) throws IOException
{
226 Path relPath
= dir
.relativize(file
);
227 // skip MANIFEST from folder
228 if (relPath
.toString().contentEquals("META-INF/MANIFEST.MF"))
229 return FileVisitResult
.CONTINUE
;
230 zos
.putNextEntry(new ZipEntry(relPath
.toString()));
231 Files
.copy(file
, zos
);
233 return FileVisitResult
.CONTINUE
;
238 } catch (IOException e
) {
239 throw new A2Exception("Cannot install OSGi bundle from " + dir
, e
);
244 private InputStream
newInputStream(Object locator
) throws IOException
{
245 if (locator
instanceof Path
) {
246 return Files
.newInputStream((Path
) locator
);
247 } else if (locator
instanceof URL
) {
248 return ((URL
) locator
).openStream();
250 throw new IllegalArgumentException("Unsupported module locator type " + locator
.getClass());