Fix override of installed bundles
[lgpl/argeo-commons.git] / org.argeo.init / src / org / argeo / init / osgi / OsgiBoot.java
index 223effb549c39799d6a34c2279f93cbe736ba0d7..f5b260caba404735f9f296830bab0e6e29c369bf 100644 (file)
@@ -19,7 +19,6 @@ import java.util.Set;
 import java.util.SortedMap;
 import java.util.StringTokenizer;
 import java.util.TreeMap;
-import java.util.concurrent.ForkJoinPool;
 
 import org.argeo.init.a2.A2Source;
 import org.argeo.init.a2.ProvisioningManager;
@@ -99,19 +98,25 @@ public class OsgiBoot implements OsgiBootConstants {
                                        queryPart = source.substring(qmIndex);
                                        source = source.substring(0, qmIndex);
                                }
+                               // TODO centralise in A" package?
                                if (source.trim().equals(A2Source.DEFAULT_A2_URI)) {
                                        if (Files.exists(homePath))
                                                provisioningManager.registerSource(
                                                                A2Source.SCHEME_A2 + "://" + homePath.toString() + "/.local/share/a2" + queryPart);
                                        provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/share/a2" + queryPart);
+                                       provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/lib/a2" + queryPart);
                                        provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/share/a2" + queryPart);
+                                       provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/lib/a2" + queryPart);
                                } else if (source.trim().equals(A2Source.DEFAULT_A2_REFERENCE_URI)) {
                                        if (Files.exists(homePath))
                                                provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + "://" + homePath.toString()
                                                                + "/.local/share/a2" + queryPart);
                                        provisioningManager
                                                        .registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/share/a2" + queryPart);
+                                       provisioningManager
+                                                       .registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/lib/a2" + queryPart);
                                        provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/share/a2" + queryPart);
+                                       provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/lib/a2" + queryPart);
                                } else {
                                        provisioningManager.registerSource(source + queryPart);
                                }
@@ -356,15 +361,16 @@ public class OsgiBoot implements OsgiBootConstants {
                FrameworkStartLevel frameworkStartLevel = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class);
 
                // default and active start levels from System properties
-               Integer defaultStartLevel = Integer.parseInt(getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "4"));
-               Integer activeStartLevel = Integer.parseInt(getProperty(PROP_OSGI_STARTLEVEL, "6"));
+               int initialStartLevel = frameworkStartLevel.getInitialBundleStartLevel();
+               int defaultStartLevel = Integer.parseInt(getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "4"));
+               int activeStartLevel = Integer.parseInt(getProperty(PROP_OSGI_STARTLEVEL, "6"));
                if (OsgiBootUtils.isDebug()) {
                        OsgiBootUtils.debug("OSGi default start level: "
                                        + getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "<not set>") + ", using " + defaultStartLevel);
                        OsgiBootUtils.debug("OSGi active start level: " + getProperty(PROP_OSGI_STARTLEVEL, "<not set>")
                                        + ", using " + activeStartLevel);
                        OsgiBootUtils.debug("Framework start level: " + frameworkStartLevel.getStartLevel() + " (initial: "
-                                       + frameworkStartLevel.getInitialBundleStartLevel() + ")");
+                                       + initialStartLevel + ")");
                }
 
                SortedMap<Integer, List<String>> startLevels = new TreeMap<Integer, List<String>>();
@@ -375,7 +381,23 @@ public class OsgiBoot implements OsgiBootConstants {
                        for (String bsn : startLevels.get(level))
                                bundleStartLevels.put(bsn, level);
                }
-               for (Bundle bundle : bundleContext.getBundles()) {
+
+               // keep only bundles with the highest version
+               Map<String, Bundle> startableBundles = new HashMap<>();
+               bundles: for (Bundle bundle : bundleContext.getBundles()) {
+                       if (bundle.getVersion() == null)
+                               continue bundles;
+                       String bsn = bundle.getSymbolicName();
+                       if (!startableBundles.containsKey(bsn)) {
+                               startableBundles.put(bsn, bundle);
+                       } else {
+                               if (bundle.getVersion().compareTo(startableBundles.get(bsn).getVersion()) > 0) {
+                                       startableBundles.put(bsn, bundle);
+                               }
+                       }
+               }
+
+               for (Bundle bundle : startableBundles.values()) {
                        String bsn = bundle.getSymbolicName();
                        if (bundleStartLevels.containsKey(bsn)) {
                                BundleStartLevel bundleStartLevel = bundle.adapt(BundleStartLevel.class);
@@ -388,7 +410,7 @@ public class OsgiBoot implements OsgiBootConstants {
                                                OsgiBootUtils.error("Cannot mark " + bsn + " as started", e);
                                        }
                                        if (OsgiBootUtils.isDebug())
-                                               OsgiBootUtils.debug(bsn + " starts at level " + level);
+                                               OsgiBootUtils.debug(bsn + " v" + bundle.getVersion() + " starts at level " + level);
                                }
                        }
                }
@@ -396,18 +418,36 @@ public class OsgiBoot implements OsgiBootConstants {
                if (OsgiBootUtils.isDebug())
                        OsgiBootUtils.debug("About to set framework start level to " + activeStartLevel + " ...");
 
-               // Start the framework asynchronously
-               ForkJoinPool.commonPool().execute(() -> {
-                       frameworkStartLevel.setStartLevel(activeStartLevel, (FrameworkEvent event) -> {
-                               if (OsgiBootUtils.isDebug())
-                                       OsgiBootUtils.debug("Framework event: " + event);
-                               int initialStartLevel = frameworkStartLevel.getInitialBundleStartLevel();
-                               int startLevel = frameworkStartLevel.getStartLevel();
+               frameworkStartLevel.setStartLevel(activeStartLevel, (FrameworkEvent event) -> {
+                       if (event.getType() == FrameworkEvent.ERROR) {
+                               OsgiBootUtils.error("Start sequence failed", event.getThrowable());
+                       } else {
                                if (OsgiBootUtils.isDebug())
-                                       OsgiBootUtils
-                                                       .debug("Framework start level: " + startLevel + " (initial: " + initialStartLevel + ")");
-                       });
+                                       OsgiBootUtils.debug("Framework started at level " + frameworkStartLevel.getStartLevel());
+                       }
                });
+
+//             // Start the framework level after level
+//             int currentStartLevel = frameworkStartLevel.getStartLevel();
+//             stages: for (int stage = currentStartLevel + 1; stage <= activeStartLevel; stage++) {
+//                     if (OsgiBootUtils.isDebug())
+//                             OsgiBootUtils.debug("Starting stage " + stage + "...");
+//                     final int nextStage = stage;
+//                     final CompletableFuture<FrameworkEvent> stageCompleted = new CompletableFuture<>();
+//                     frameworkStartLevel.setStartLevel(nextStage, (FrameworkEvent event) -> {
+//                             stageCompleted.complete(event);
+//                     });
+//                     FrameworkEvent event;
+//                     try {
+//                             event = stageCompleted.get();
+//                     } catch (InterruptedException | ExecutionException e) {
+//                             throw new IllegalStateException("Cannot continue start", e);
+//                     }
+//                     if (event.getThrowable() != null) {
+//                             OsgiBootUtils.error("Stage " + nextStage + " failed, aborting start.", event.getThrowable());
+//                             break stages;
+//                     }
+//             }
        }
 
        private static void computeStartLevels(SortedMap<Integer, List<String>> startLevels, Map<String, String> properties,