X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=runtime%2Forg.argeo.slc.support.osgi%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fosgi%2FBundlesManager.java;h=788f2da57b79bcb1c35c1db34ac7d2f5d75d5663;hb=7b8669f41556f46a0f229192d05e2f2592c57d5f;hp=a096a44d413bf6eca8c216440144bfd09bfab427;hpb=593b5ee7a27f426f2c14126a9144ac3630ab4ee6;p=gpl%2Fargeo-slc.git diff --git a/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/BundlesManager.java b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/BundlesManager.java index a096a44d4..788f2da57 100644 --- a/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/BundlesManager.java +++ b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/BundlesManager.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2007-2012 Mathieu Baudier + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.argeo.slc.osgi; import org.apache.commons.logging.Log; @@ -17,18 +32,24 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.osgi.context.BundleContextAware; +import org.springframework.osgi.context.event.OsgiBundleApplicationContextEvent; +import org.springframework.osgi.context.event.OsgiBundleApplicationContextListener; +import org.springframework.osgi.context.event.OsgiBundleContextClosedEvent; +import org.springframework.osgi.context.event.OsgiBundleContextFailedEvent; +import org.springframework.osgi.context.event.OsgiBundleContextRefreshedEvent; +import org.springframework.osgi.util.OsgiBundleUtils; import org.springframework.osgi.util.OsgiFilterUtils; import org.springframework.util.Assert; /** Wraps low-level access to a {@link BundleContext} */ public class BundlesManager implements BundleContextAware, FrameworkListener, - InitializingBean, DisposableBean { + InitializingBean, DisposableBean, OsgiBundleApplicationContextListener { private final static Log log = LogFactory.getLog(BundlesManager.class); private BundleContext bundleContext; - private Long defaultTimeout = 10000l; - private Long pollingPeriod = 100l; + private Long defaultTimeout = 30 * 1000l; + private Long pollingPeriod = 200l; // Refresh sync objects private final Object refreshedPackageSem = new Object(); @@ -57,7 +78,7 @@ public class BundlesManager implements BundleContextAware, FrameworkListener, startSynchronous(bundle); long aStart = System.currentTimeMillis(); - if (log.isDebugEnabled()) { + if (log.isTraceEnabled()) { log.debug("OSGi upgrade performed in " + (aStart - begin) + "ms for bundle " + osgiBundle); log.debug(" stop \t: " + (bUpdate - bStop) + "ms"); @@ -72,22 +93,35 @@ public class BundlesManager implements BundleContextAware, FrameworkListener, + ")"; // Wait for application context to be ready // TODO: use service tracker - getServiceRefSynchronous(ApplicationContext.class.getName(), filter); + ServiceReference[] srs = getServiceRefSynchronous( + ApplicationContext.class.getName(), filter); + ServiceReference sr = srs[0]; long aAppContext = System.currentTimeMillis(); long end = aAppContext; - if (log.isDebugEnabled()) { + if (log.isTraceEnabled()) { 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." - + " (upgrade performed in " + (end - begin) + "ms)."); - log.debug(" TOTAL\t: " + (end - begin) + "ms"); + log.debug("Bundle '" + bundle.getSymbolicName() + + "' upgraded and ready " + " (upgrade performed in " + + (end - begin) + "ms)."); + + if (log.isTraceEnabled()) { + ApplicationContext applicationContext = (ApplicationContext) bundleContext + .getService(sr); + int beanDefCount = applicationContext.getBeanDefinitionCount(); + log.debug(" " + beanDefCount + " beans in app context of " + + bundle.getSymbolicName() + + ", average init time per bean=" + (end - begin) + / beanDefCount + "ms"); + } + + bundleContext.ungetService(sr); + } catch (Exception e) { throw new SlcException("Cannot update bundle " + osgiBundle, e); } @@ -233,7 +267,7 @@ public class BundlesManager implements BundleContextAware, FrameworkListener, try { Thread.sleep(pollingPeriod); } catch (InterruptedException e) { - // silent + throw new SlcException("Polling interrupted"); } } @@ -246,11 +280,16 @@ public class BundlesManager implements BundleContextAware, FrameworkListener, } @SuppressWarnings(value = { "unchecked" }) - public T getSingleService(Class clss, String filter) { + public T getSingleService(Class clss, String filter, + Boolean synchronous) { Assert.isTrue(OsgiFilterUtils.isValidFilter(filter), "valid filter"); ServiceReference[] sfs; try { - sfs = bundleContext.getServiceReferences(clss.getName(), filter); + if (synchronous) + sfs = getServiceRefSynchronous(clss.getName(), filter); + else + sfs = bundleContext + .getServiceReferences(clss.getName(), filter); } catch (InvalidSyntaxException e) { throw new SlcException("Cannot retrieve service reference for " + filter, e); @@ -264,15 +303,20 @@ public class BundlesManager implements BundleContextAware, FrameworkListener, return (T) bundleContext.getService(sfs[0]); } - public T getSingleServiceStrict(Class clss, String filter) { - T service = getSingleService(clss, filter); + public T getSingleServiceStrict(Class clss, String filter, + Boolean synchronous) { + T service = getSingleService(clss, filter, synchronous); if (service == null) throw new SlcException("No execution flow found for " + filter); else return service; } - /** @return the related bundle or null if not found */ + /** + * @param osgiBundle + * cannot be null + * @return the related bundle or null if not found + */ public Bundle findRelatedBundle(OsgiBundle osgiBundle) { Bundle bundle = null; if (osgiBundle.getInternalBundleId() != null) { @@ -280,16 +324,33 @@ public class BundlesManager implements BundleContextAware, FrameworkListener, Assert.isTrue( osgiBundle.getName().equals(bundle.getSymbolicName()), "symbolic name consistent"); - Assert.isTrue(osgiBundle.getVersion().equals( - bundle.getHeaders().get(Constants.BUNDLE_VERSION)), - "version consistent"); - } else { - for (Bundle b : bundleContext.getBundles()) { + if (osgiBundle.getVersion() != null) + Assert.isTrue( + osgiBundle.getVersion().equals( + bundle.getHeaders().get( + Constants.BUNDLE_VERSION)), + "version consistent"); + } else if (osgiBundle.getVersion() == null) { + bundle = OsgiBundleUtils.findBundleBySymbolicName(bundleContext, + osgiBundle.getName()); + } else {// scan all bundles + bundles: for (Bundle b : bundleContext.getBundles()) { + if (b.getSymbolicName() == null) { + log.warn("Bundle " + b + " has no symbolic name defined."); + continue bundles; + } + if (b.getSymbolicName().equals(osgiBundle.getName())) { - if (b.getHeaders().get(Constants.BUNDLE_VERSION).equals( - osgiBundle.getVersion())) { + if (osgiBundle.getVersion() == null) { + bundle = b; + break bundles; + } + + if (b.getHeaders().get(Constants.BUNDLE_VERSION) + .equals(osgiBundle.getVersion())) { bundle = b; osgiBundle.setInternalBundleId(b.getBundleId()); + break bundles; } } } @@ -330,8 +391,11 @@ public class BundlesManager implements BundleContextAware, FrameworkListener, this.defaultTimeout = defaultTimeout; } - /** Temporary internal access for {@link OsgiExecutionModulesManager} */ - BundleContext getBundleContext() { + /** + * Use with caution since it may interfer with some cached information + * within this object + */ + public BundleContext getBundleContext() { return bundleContext; } @@ -339,4 +403,16 @@ public class BundlesManager implements BundleContextAware, FrameworkListener, this.pollingPeriod = pollingPeriod; } + public void onOsgiApplicationEvent(OsgiBundleApplicationContextEvent event) { + if (event instanceof OsgiBundleContextRefreshedEvent) { + log.debug("App context refreshed: " + event); + } else if (event instanceof OsgiBundleContextFailedEvent) { + log.debug("App context failed: " + event); + } + if (event instanceof OsgiBundleContextClosedEvent) { + log.debug("App context closed: " + event); + } + + } + }