Improve A2 provisioning framework.
[lgpl/argeo-commons.git] / org.argeo.osgi.boot / src / org / argeo / osgi / boot / a2 / ProvisioningSource.java
index a9fab396d6bc13974f70c20dce17a69506be593a..62d7042d69588588d7fb6ce0dd4b1cff33e119cc 100644 (file)
 package org.argeo.osgi.boot.a2;
 
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.Collections;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.jar.JarInputStream;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-import java.util.zip.ZipEntry;
-
-import org.argeo.osgi.boot.OsgiBootException;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
 
 /** Where components are retrieved from. */
-abstract class ProvisioningSource {
-       final Map<String, A2Contribution> contributions = Collections.synchronizedSortedMap(new TreeMap<>());
-
-       A2Contribution getOrAddContribution(String contributionId) {
-               if (contributions.containsKey(contributionId))
-                       return contributions.get(contributionId);
-               else
-                       return new A2Contribution(this, contributionId);
-       }
-
-       void asTree(String prefix, StringBuffer buf) {
-               if (prefix == null)
-                       prefix = "";
-               for (String contributionId : contributions.keySet()) {
-                       buf.append(prefix);
-                       buf.append(contributionId);
-                       buf.append('\n');
-                       A2Contribution contribution = contributions.get(contributionId);
-                       contribution.asTree(prefix + " ", buf);
-               }
-       }
-
-       void asTree() {
-               StringBuffer buf = new StringBuffer();
-               asTree("", buf);
-               System.out.println(buf);
-       }
-
-       A2Component findComponent(String componentId) {
-               SortedMap<A2Contribution, A2Component> res = new TreeMap<>();
-               for (A2Contribution contribution : contributions.values()) {
-                       components: for (String componentIdKey : contribution.components.keySet()) {
-                               if (componentId.equals(componentIdKey)) {
-                                       res.put(contribution, contribution.components.get(componentIdKey));
-                                       break components;
-                               }
-                       }
-               }
-               if (res.size() == 0)
-                       return null;
-               // TODO explicit contribution priorities
-               return res.get(res.lastKey());
-
-       }
-
-       A2Branch findBranch(String componentId, Version version) {
-               A2Component component = findComponent(componentId);
-               if (component == null)
-                       return null;
-               String branchId = version.getMajor() + "." + version.getMinor();
-               if (!component.branches.containsKey(branchId))
-                       return null;
-               return component.branches.get(branchId);
-       }
-
-       protected String readVersionFromModule(Path modulePath) {
-               Manifest manifest;
-               if (Files.isDirectory(modulePath)) {
-                       manifest = findManifest(modulePath);
-               } else {
-                       try (JarInputStream in = new JarInputStream(newInputStream(modulePath))) {
-                               manifest = in.getManifest();
-                       } catch (IOException e) {
-                               throw new OsgiBootException("Cannot read manifest from " + modulePath, e);
-                       }
-               }
-               String versionStr = manifest.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
-               return versionStr;
-       }
-
-       protected String readSymbolicNameFromModule(Path modulePath) {
-               Manifest manifest;
-               if (Files.isDirectory(modulePath)) {
-                       manifest = findManifest(modulePath);
-               } else {
-                       try (JarInputStream in = new JarInputStream(newInputStream(modulePath))) {
-                               manifest = in.getManifest();
-                       } catch (IOException e) {
-                               throw new OsgiBootException("Cannot read manifest from " + modulePath, e);
-                       }
-               }
-               String symbolicName = manifest.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
-               int semiColIndex = symbolicName.indexOf(';');
-               if (semiColIndex >= 0)
-                       symbolicName = symbolicName.substring(0, semiColIndex);
-               return symbolicName;
-       }
-
-       private static Manifest findManifest(Path currentPath) {
-               Path metaInfPath = currentPath.resolve("META-INF");
-               if (Files.exists(metaInfPath) && Files.isDirectory(metaInfPath)) {
-                       Path manifestPath = metaInfPath.resolve("MANIFEST.MF");
-                       try {
-                               try (InputStream in = Files.newInputStream(manifestPath)) {
-                                       Manifest manifest = new Manifest(in);
-                                       return manifest;
-                               }
-                       } catch (IOException e) {
-                               throw new OsgiBootException("Cannot read manifest from " + manifestPath, e);
-                       }
-               } else {
-                       Path parentPath = currentPath.getParent();
-                       if (parentPath == null)
-                               throw new OsgiBootException("MANIFEST.MF file not found.");
-                       return findManifest(currentPath.getParent());
-               }
-       }
-
-       public Bundle install(BundleContext bc, A2Module module) throws IOException, BundleException {
-               Path tempJar = null;
-               if (module.getLocator() instanceof Path && Files.isDirectory((Path) module.getLocator()))
-                       tempJar = toTempJar((Path) module.getLocator());
-               Bundle bundle;
-               try (InputStream in = newInputStream(tempJar != null ? tempJar : module.getLocator())) {
-                       bundle = bc.installBundle(module.getBranch().getCoordinates(), in);
-               }
-               if (tempJar != null)
-                       Files.deleteIfExists(tempJar);
-               return bundle;
-       }
+public interface ProvisioningSource {
+       /** List all contributions of this source. */
+       Iterable<A2Contribution> listContributions(Object filter);
 
-       public void update(Bundle bundle, A2Module module) throws IOException, BundleException {
-               Path tempJar = null;
-               if (module.getLocator() instanceof Path && Files.isDirectory((Path) module.getLocator()))
-                       tempJar = toTempJar((Path) module.getLocator());
-               try (InputStream in = newInputStream(tempJar != null ? tempJar : module.getLocator())) {
-                       bundle.update(in);
-               }
-               if (tempJar != null)
-                       Files.deleteIfExists(tempJar);
-       }
+       /** Install a module in the OSGi runtime. */
+       Bundle install(BundleContext bc, A2Module module);
 
-       static Path toTempJar(Path dir) {
-               try {
-                       Manifest manifest = findManifest(dir);
-                       Path jarPath = Files.createTempFile("a2Source", ".jar");
-                       try (JarOutputStream zos = new JarOutputStream(new FileOutputStream(jarPath.toFile()), manifest)) {
-                               Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
-                                       public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
-                                               Path relPath = dir.relativize(file);
-                                               // skip MANIFEST from folder
-                                               if (relPath.toString().contentEquals("META-INF/MANIFEST.MF"))
-                                                       return FileVisitResult.CONTINUE;
-                                               zos.putNextEntry(new ZipEntry(relPath.toString()));
-                                               Files.copy(file, zos);
-                                               zos.closeEntry();
-                                               return FileVisitResult.CONTINUE;
-                                       }
-                               });
-                       }
-                       return jarPath;
-               } catch (IOException e) {
-                       throw new OsgiBootException("Cannot install OSGi bundle from " + dir, e);
-               }
+       /** Update a module in the OSGi runtime. */
+       void update(Bundle bundle, A2Module module);
 
-       }
+       /** Finds the {@link A2Branch} related to this component and version. */
+       A2Branch findBranch(String componentId, Version version);
 
-       private InputStream newInputStream(Object locator) throws IOException {
-               if (locator instanceof Path) {
-                       return Files.newInputStream((Path) locator);
-               } else if (locator instanceof URL) {
-                       return ((URL) locator).openStream();
-               } else {
-                       throw new IllegalArgumentException("Unsupported module locator type " + locator.getClass());
-               }
-       }
 }