]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.osgi.boot/src/org/argeo/osgi/boot/a2/ProvisioningSource.java
Rename container scripts.
[lgpl/argeo-commons.git] / org.argeo.osgi.boot / src / org / argeo / osgi / boot / a2 / ProvisioningSource.java
1 package org.argeo.osgi.boot.a2;
2
3 import java.io.FileOutputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.net.URL;
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;
13 import java.util.Map;
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;
20
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;
27
28 /** Where components are retrieved from. */
29 abstract class ProvisioningSource {
30 final Map<String, A2Contribution> contributions = Collections.synchronizedSortedMap(new TreeMap<>());
31
32 A2Contribution getOrAddContribution(String contributionId) {
33 if (contributions.containsKey(contributionId))
34 return contributions.get(contributionId);
35 else
36 return new A2Contribution(this, contributionId);
37 }
38
39 void asTree(String prefix, StringBuffer buf) {
40 if (prefix == null)
41 prefix = "";
42 for (String contributionId : contributions.keySet()) {
43 buf.append(prefix);
44 buf.append(contributionId);
45 buf.append('\n');
46 A2Contribution contribution = contributions.get(contributionId);
47 contribution.asTree(prefix + " ", buf);
48 }
49 }
50
51 void asTree() {
52 StringBuffer buf = new StringBuffer();
53 asTree("", buf);
54 System.out.println(buf);
55 }
56
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));
63 break components;
64 }
65 }
66 }
67 if (res.size() == 0)
68 return null;
69 // TODO explicit contribution priorities
70 return res.get(res.lastKey());
71
72 }
73
74 A2Branch findBranch(String componentId, Version version) {
75 A2Component component = findComponent(componentId);
76 if (component == null)
77 return null;
78 String branchId = version.getMajor() + "." + version.getMinor();
79 if (!component.branches.containsKey(branchId))
80 return null;
81 return component.branches.get(branchId);
82 }
83
84 protected String readVersionFromModule(Path modulePath) {
85 Manifest manifest;
86 if (Files.isDirectory(modulePath)) {
87 manifest = findManifest(modulePath);
88 } else {
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);
93 }
94 }
95 String versionStr = manifest.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
96 return versionStr;
97 }
98
99 protected String readSymbolicNameFromModule(Path modulePath) {
100 Manifest manifest;
101 if (Files.isDirectory(modulePath)) {
102 manifest = findManifest(modulePath);
103 } else {
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);
108 }
109 }
110 String symbolicName = manifest.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
111 int semiColIndex = symbolicName.indexOf(';');
112 if (semiColIndex >= 0)
113 symbolicName = symbolicName.substring(0, semiColIndex);
114 return symbolicName;
115 }
116
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");
121 try {
122 try (InputStream in = Files.newInputStream(manifestPath)) {
123 Manifest manifest = new Manifest(in);
124 return manifest;
125 }
126 } catch (IOException e) {
127 throw new OsgiBootException("Cannot read manifest from " + manifestPath, e);
128 }
129 } else {
130 Path parentPath = currentPath.getParent();
131 if (parentPath == null)
132 throw new OsgiBootException("MANIFEST.MF file not found.");
133 return findManifest(currentPath.getParent());
134 }
135 }
136
137 public Bundle install(BundleContext bc, A2Module module) throws IOException, BundleException {
138 Path tempJar = null;
139 if (module.getLocator() instanceof Path && Files.isDirectory((Path) module.getLocator()))
140 tempJar = toTempJar((Path) module.getLocator());
141 Bundle bundle;
142 try (InputStream in = newInputStream(tempJar != null ? tempJar : module.getLocator())) {
143 bundle = bc.installBundle(module.getBranch().getCoordinates(), in);
144 }
145 if (tempJar != null)
146 Files.deleteIfExists(tempJar);
147 return bundle;
148 }
149
150 public void update(Bundle bundle, A2Module module) throws IOException, BundleException {
151 Path tempJar = null;
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())) {
155 bundle.update(in);
156 }
157 if (tempJar != null)
158 Files.deleteIfExists(tempJar);
159 }
160
161 static Path toTempJar(Path dir) {
162 try {
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);
174 zos.closeEntry();
175 return FileVisitResult.CONTINUE;
176 }
177 });
178 }
179 return jarPath;
180 } catch (IOException e) {
181 throw new OsgiBootException("Cannot install OSGi bundle from " + dir, e);
182 }
183
184 }
185
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();
191 } else {
192 throw new IllegalArgumentException("Unsupported module locator type " + locator.getClass());
193 }
194 }
195 }