Improve SLC commands in OSGi console
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 26 Jul 2009 10:56:47 +0000 (10:56 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 26 Jul 2009 10:56:47 +0000 (10:56 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@2752 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

runtime/org.argeo.slc.support.equinox/.classpath
runtime/org.argeo.slc.support.equinox/pom.xml
runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/equinox/ExecutionCommandProvider.java
runtime/org.argeo.slc.support.equinox/src/main/resources/META-INF/spring/manager.xml
runtime/org.argeo.slc.support.equinox/src/main/resources/META-INF/spring/osgi.xml
runtime/org.argeo.slc.support.equinox/src/main/resources/equinox.properties [new file with mode: 0644]
runtime/org.argeo.slc.support.equinox/src/test/java/org/argeo/slc/osgi/test/HelloTest.java
runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/BundlesManager.java

index 3e386d407d84208e216c085e4f61d3f4267a7045..438f0fe3b3dd07a0a6fea8f835009e2072fa178b 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
        <classpathentry kind="src" output="target/classes" path="src/main/java"/>
-       <classpathentry kind="src" path="src/main/resources"/>
+       <classpathentry kind="src" output="target/classes" path="src/main/resources"/>
        <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
        <classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
index 21cb4437d106f3f006f9728e11fe55703920c077..1e9d2b8f6e1d0e92088ea755aceca7fb82045e2e 100644 (file)
@@ -1,4 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <groupId>org.argeo.slc</groupId>
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-jar-plugin</artifactId>
-                               <executions>
-                                       <execution>
-                                               <goals>
-                                                       <goal>test-jar</goal>
-                                               </goals>
-                                               <configuration>
-                                                       <archive>
-                                                               <manifestFile>src/test/resources/META-INF/MANIFEST.MF</manifestFile>
-                                                       </archive>
-                                               </configuration>
-                                       </execution>
-                               </executions>
+                               <!--
+                                       <executions> <execution> <goals> <goal>test-jar</goal> </goals>
+                                       <configuration> <archive>
+                                       <manifestFile>src/test/resources/META-INF/MANIFEST.MF</manifestFile>
+                                       </archive> </configuration> </execution> </executions>
+                               -->
                        </plugin>
                        <plugin>
                                <groupId>org.apache.felix</groupId>
@@ -38,6 +33,9 @@
                                                <Export-Package>
                                                        org.argeo.slc.*
                                                </Export-Package>
+                                               <Import-Package>*,
+                                                       org.springframework.beans.factory.config
+                                               </Import-Package>
                                        </instructions>
                                </configuration>
                        </plugin>
@@ -48,7 +46,7 @@
                        <groupId>org.argeo.slc.runtime</groupId>
                        <artifactId>org.argeo.slc.support.osgi</artifactId>
                </dependency>
-               
+
                <!-- Unit Tests -->
                <dependency>
                        <groupId>org.argeo.slc.runtime</groupId>
index 56bcc3c4f21c6cd3cd541aaf88f25d45350134b2..ab30014f9de8338d65808546f37cf9da882d6895 100644 (file)
@@ -8,24 +8,33 @@ import org.argeo.slc.process.RealizedFlow;
 import org.eclipse.core.runtime.adaptor.EclipseStarter;
 import org.eclipse.osgi.framework.console.CommandInterpreter;
 import org.eclipse.osgi.framework.console.CommandProvider;
-import org.springframework.beans.factory.InitializingBean;
 
-public class ExecutionCommandProvider implements CommandProvider,
-               InitializingBean {
+public class ExecutionCommandProvider implements CommandProvider {
        private final static Log log = LogFactory
                        .getLog(ExecutionCommandProvider.class);
 
+       private final static String SLC_WITH_REFRESH = "slc";
+       private final static String SLC_NO_REFRESH = "slcnr";
+
        private OsgiExecutionModulesManager modulesManager;
 
        private RealizedFlow lastLaunch = null;
 
        public Object _slc(CommandInterpreter ci) {
+               return exec(SLC_WITH_REFRESH, ci);
+       }
+
+       public Object _slcnr(CommandInterpreter ci) {
+               return exec(SLC_NO_REFRESH, ci);
+       }
+
+       protected Object exec(String slcCommand, CommandInterpreter ci) {
                // TODO: check version
                String firstArg = ci.nextArgument();
                if (firstArg == null) {
                        if (lastLaunch != null) {
-                               String cmd = "slc " + lastLaunch.getModuleName() + " "
-                                               + lastLaunch.getFlowDescriptor().getName();
+                               String cmd = slcCommand + " " + lastLaunch.getModuleName()
+                                               + " " + lastLaunch.getFlowDescriptor().getName();
                                if (log.isDebugEnabled())
                                        log.debug("Execute again last command: " + cmd);
                                return ci.execute(cmd);
@@ -36,25 +45,35 @@ public class ExecutionCommandProvider implements CommandProvider,
                }
                String executionName = ci.nextArgument();
 
-               launch(firstArg, executionName);
+               launch(slcCommand, firstArg, executionName);
                return "COMMAND COMPLETED";
        }
 
-       protected void launch(String firstArg, String executionName) {
+       protected void launch(String slcCommand, String firstArg,
+                       String executionName) {
                lastLaunch = modulesManager.findRealizedFlow(firstArg, executionName);
                if (lastLaunch == null)
                        throw new SlcException("Cannot find launch for " + firstArg + " "
                                        + executionName);
 
-               modulesManager.updateAndExecute(lastLaunch);
-
+               // Execute
+               if (SLC_WITH_REFRESH.equals(slcCommand))
+                       modulesManager.updateAndExecute(lastLaunch);
+               else if (SLC_NO_REFRESH.equals(slcCommand))
+                       modulesManager.execute(lastLaunch);
+               else
+                       throw new SlcException("Unrecognized SLC command " + slcCommand);
        }
 
        public String getHelp() {
                StringBuffer buf = new StringBuffer();
                buf.append("---SLC Execution Commands---\n");
                buf
-                               .append("\tslc (<id>|<segment of bsn>) <execution bean>  - execute an execution flow (without arg, execute last)\n");
+                               .append("\tslc (<id>|<segment of bsn>) <execution bean>"
+                                               + "  - refresh the bundle, execute an execution flow (without arg, execute last)\n");
+               buf
+                               .append("\tslcnr (<id>|<segment of bsn>) <execution bean>"
+                                               + "  - execute an execution flow (without arg, execute last)\n");
                return buf.toString();
 
        }
@@ -63,7 +82,7 @@ public class ExecutionCommandProvider implements CommandProvider,
                this.modulesManager = osgiModulesManager;
        }
 
-       public void afterPropertiesSet() throws Exception {
+       public void init() throws Exception {
                final String module = System.getProperty("slc.launch.module");
                final String executionName = System.getProperty("slc.launch.execution");
                if (module != null) {
@@ -72,7 +91,7 @@ public class ExecutionCommandProvider implements CommandProvider,
                                @Override
                                public void run() {
                                        try {
-                                               launch(module, executionName);
+                                               launch(SLC_NO_REFRESH, module, executionName);
                                                // in case of failure OSGi runtime stays up and last
                                                // launch can be used to debug by calling 'slc'
                                        } catch (Exception e) {
index 89bf607c5be8ee05303e95f679b212a1b42a1d37..70fc63fe2e3d86996f87c4528678405a9e085857 100644 (file)
@@ -7,7 +7,25 @@
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
 \r
-       <bean id="bundlesManager" class="org.argeo.slc.osgi.BundlesManager" />\r
+       <bean\r
+               class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">\r
+               <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />\r
+               <property name="ignoreUnresolvablePlaceholders" value="false" />\r
+               <property name="locations">\r
+                       <value>osgibundle:equinox.properties\r
+                       </value>\r
+               </property>\r
+       </bean>\r
+\r
+       <bean id="commandProvider" class="org.argeo.slc.equinox.ExecutionCommandProvider"\r
+               init-method="init">\r
+               <property name="modulesManager" ref="modulesManager" />\r
+       </bean>\r
+\r
+       <bean id="bundlesManager" class="org.argeo.slc.osgi.BundlesManager">\r
+               <property name="defaultTimeout" value="${slc.equinox.commandTimeout}" />\r
+               <property name="pollingPeriod" value="${slc.equinox.commandPollingPeriod}" />\r
+       </bean>\r
 \r
        <bean id="modulesManager" class="org.argeo.slc.osgi.OsgiExecutionModulesManager">\r
                <property name="bundlesManager" ref="bundlesManager" />\r
index 7a76831c497ef41a6ac737fc0dd2e2c317c9eb3f..0a98838284e144653363b5c5d3adab23caa1d99f 100644 (file)
@@ -6,10 +6,7 @@
        http://www.springframework.org/schema/beans   \r
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
 \r
-       <service interface="org.eclipse.osgi.framework.console.CommandProvider">\r
-               <beans:bean class="org.argeo.slc.equinox.ExecutionCommandProvider">\r
-                       <beans:property name="modulesManager" ref="modulesManager" />\r
-               </beans:bean>\r
-       </service>\r
+       <service interface="org.eclipse.osgi.framework.console.CommandProvider"\r
+               ref="commandProvider" />\r
 \r
 </beans:beans>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.support.equinox/src/main/resources/equinox.properties b/runtime/org.argeo.slc.support.equinox/src/main/resources/equinox.properties
new file mode 100644 (file)
index 0000000..dae8b2e
--- /dev/null
@@ -0,0 +1,4 @@
+# Timeout for the SLC command in the OSGi console (in ms)
+slc.equinox.commandTimeout=10000
+# Polling period for synchronous OSGi commands (in ms)
+slc.equinox.commandPollingPeriod=100
\ No newline at end of file
index 2c55612bf066ddf2d777a3f531d9ef652575c172..02a7bd3d03cb67856f2d5263a556e4ca37d6451e 100644 (file)
@@ -2,8 +2,6 @@ package org.argeo.slc.osgi.test;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
 
 import org.argeo.slc.equinox.unit.AbstractOsgiRuntimeTestCase;
 import org.argeo.slc.osgiboot.OsgiBoot;
index c87f602979e6e3008662f4f9786edd39e7f0856b..8872844545d54e650f13fdcb2c0adbccc0aa8a4b 100644 (file)
@@ -28,7 +28,11 @@ public class BundlesManager implements BundleContextAware, FrameworkListener,
        private BundleContext bundleContext;
 
        private Long defaultTimeout = 10000l;
+       private Long pollingPeriod = 100l;
+
+       // Refresh sync objects
        private final Object refreshedPackageSem = new Object();
+       private Boolean packagesRefreshed = false;
 
        /**
         * Stop the module, update it, refresh it and restart it. All synchronously.
@@ -36,21 +40,54 @@ public class BundlesManager implements BundleContextAware, FrameworkListener,
        public void upgradeSynchronous(OsgiBundle osgiBundle) {
                try {
                        Bundle bundle = findRelatedBundle(osgiBundle);
+
+                       long begin = System.currentTimeMillis();
+
+                       long bStop = begin;
                        stopSynchronous(bundle);
+
+                       long bUpdate = System.currentTimeMillis();
                        updateSynchronous(bundle);
+
                        // Refresh in case there are fragments
+                       long bRefresh = System.currentTimeMillis();
                        refreshSynchronous(bundle);
+
+                       long bStart = System.currentTimeMillis();
                        startSynchronous(bundle);
 
+                       long aStart = System.currentTimeMillis();
+                       if (log.isDebugEnabled()) {
+                               log.debug("OSGi upgrade performed in " + (aStart - begin)
+                                               + "ms for bundle " + osgiBundle);
+                               log.debug(" stop \t: " + (bUpdate - bStop) + "ms");
+                               log.debug(" update\t: " + (bRefresh - bUpdate) + "ms");
+                               log.debug(" refresh\t: " + (bStart - bRefresh) + "ms");
+                               log.debug(" start\t: " + (aStart - bStart) + "ms");
+                               log.debug(" TOTAL\t: " + (aStart - begin) + "ms");
+                       }
+
+                       long bAppContext = System.currentTimeMillis();
                        String filter = "(Bundle-SymbolicName=" + bundle.getSymbolicName()
                                        + ")";
                        // Wait for application context to be ready
                        // TODO: use service tracker
                        getServiceRefSynchronous(ApplicationContext.class.getName(), filter);
+                       long aAppContext = System.currentTimeMillis();
+                       long end = aAppContext;
+
+                       if (log.isDebugEnabled()) {
+                               log.debug("Application context refresh performed in "
+                                               + (aAppContext - bAppContext) + "ms for bundle "
+                                               + osgiBundle);
+                               log.debug(" TOTAL\t: " + (aAppContext - bAppContext) + "ms");
+                       }
 
                        if (log.isDebugEnabled())
                                log.debug("Bundle " + bundle.getSymbolicName()
-                                               + " ready to be used at latest version.");
+                                               + " ready to be used at latest version."
+                                               + " (upgrade performed in " + (end - begin) + "ms).");
+                       log.debug(" TOTAL\t: " + (end - begin) + "ms");
                } catch (Exception e) {
                        throw new SlcException("Cannot update bundle " + osgiBundle, e);
                }
@@ -58,7 +95,6 @@ public class BundlesManager implements BundleContextAware, FrameworkListener,
 
        /** Updates bundle synchronously. */
        protected void updateSynchronous(Bundle bundle) throws BundleException {
-               // int originalState = bundle.getState();
                bundle.update();
                boolean waiting = true;
 
@@ -69,11 +105,9 @@ public class BundlesManager implements BundleContextAware, FrameworkListener,
                                        || state == Bundle.RESOLVED)
                                waiting = false;
 
-                       sleep(100);
-                       if (System.currentTimeMillis() - begin > defaultTimeout)
-                               throw new SlcException("Update of bundle "
-                                               + bundle.getSymbolicName()
-                                               + " timed out. Bundle state = " + bundle.getState());
+                       sleepWhenPolling();
+                       checkTimeout(begin, "Update of bundle " + bundle.getSymbolicName()
+                                       + " timed out. Bundle state = " + bundle.getState());
                } while (waiting);
 
                if (log.isTraceEnabled())
@@ -94,11 +128,9 @@ public class BundlesManager implements BundleContextAware, FrameworkListener,
                        if (bundle.getState() == Bundle.ACTIVE)
                                waiting = false;
 
-                       sleep(100);
-                       if (System.currentTimeMillis() - begin > defaultTimeout)
-                               throw new SlcException("Start of bundle "
-                                               + bundle.getSymbolicName()
-                                               + " timed out. Bundle state = " + bundle.getState());
+                       sleepWhenPolling();
+                       checkTimeout(begin, "Start of bundle " + bundle.getSymbolicName()
+                                       + " timed out. Bundle state = " + bundle.getState());
                } while (waiting);
 
                if (log.isTraceEnabled())
@@ -120,11 +152,9 @@ public class BundlesManager implements BundleContextAware, FrameworkListener,
                                        && bundle.getState() != Bundle.STOPPING)
                                waiting = false;
 
-                       sleep(100);
-                       if (System.currentTimeMillis() - begin > defaultTimeout)
-                               throw new SlcException("Stop of bundle "
-                                               + bundle.getSymbolicName()
-                                               + " timed out. Bundle state = " + bundle.getState());
+                       sleepWhenPolling();
+                       checkTimeout(begin, "Stop of bundle " + bundle.getSymbolicName()
+                                       + " timed out. Bundle state = " + bundle.getState());
                } while (waiting);
 
                if (log.isTraceEnabled())
@@ -138,14 +168,23 @@ public class BundlesManager implements BundleContextAware, FrameworkListener,
                PackageAdmin packageAdmin = (PackageAdmin) bundleContext
                                .getService(packageAdminRef);
                Bundle[] bundles = { bundle };
-               packageAdmin.refreshPackages(bundles);
 
+               long begin = System.currentTimeMillis();
                synchronized (refreshedPackageSem) {
+                       packagesRefreshed = false;
+                       packageAdmin.refreshPackages(bundles);
                        try {
                                refreshedPackageSem.wait(defaultTimeout);
                        } catch (InterruptedException e) {
                                // silent
                        }
+                       if (!packagesRefreshed) {
+                               long now = System.currentTimeMillis();
+                               throw new SlcException("Packages not refreshed after "
+                                               + (now - begin) + "ms");
+                       } else {
+                               packagesRefreshed = false;
+                       }
                }
 
                if (log.isTraceEnabled())
@@ -155,6 +194,7 @@ public class BundlesManager implements BundleContextAware, FrameworkListener,
        public void frameworkEvent(FrameworkEvent event) {
                if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
                        synchronized (refreshedPackageSem) {
+                               packagesRefreshed = true;
                                refreshedPackageSem.notifyAll();
                        }
                }
@@ -173,7 +213,7 @@ public class BundlesManager implements BundleContextAware, FrameworkListener,
                        if (sfs != null)
                                waiting = false;
 
-                       sleep(100);
+                       sleepWhenPolling();
                        if (System.currentTimeMillis() - begin > defaultTimeout)
                                throw new SlcException("Search of services " + clss
                                                + " with filter " + filter + " timed out.");
@@ -182,9 +222,17 @@ public class BundlesManager implements BundleContextAware, FrameworkListener,
                return sfs;
        }
 
-       protected void sleep(long ms) {
+       protected void checkTimeout(long begin, String msg) {
+               long now = System.currentTimeMillis();
+               if (now - begin > defaultTimeout)
+                       throw new SlcException(msg + " (timeout after " + (now - begin)
+                                       + "ms)");
+
+       }
+
+       protected void sleepWhenPolling() {
                try {
-                       Thread.sleep(ms);
+                       Thread.sleep(pollingPeriod);
                } catch (InterruptedException e) {
                        // silent
                }
@@ -288,4 +336,8 @@ public class BundlesManager implements BundleContextAware, FrameworkListener,
                return bundleContext;
        }
 
+       public void setPollingPeriod(Long pollingPeriod) {
+               this.pollingPeriod = pollingPeriod;
+       }
+
 }