/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.osgi; import java.lang.reflect.Array; import java.util.HashMap; import java.util.Map; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.service.spi.Stoppable; import org.osgi.framework.BundleContext; import org.osgi.util.tracker.ServiceTracker; /** * Utilities for dealing with OSGi environments * * @author Brett Meyer */ public class OsgiServiceUtil implements Stoppable { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( OsgiServiceUtil.class ); private BundleContext context; private Map<String, ServiceTracker> serviceTrackers = new HashMap<String, ServiceTracker>(); public OsgiServiceUtil(BundleContext context) { this.context = context; } /** * Locate all implementors of the given service contract in the given OSGi buindle context. Utilizes * {@link ServiceTracker} (best practice, automatically handles a lot of boilerplate and error conditions). * * @param contract The service contract for which to locate implementors * @param context The OSGi bundle context * @param T[] The Java type of the service to locate * @return All know implementors */ public <T> T[] getServiceImpls(Class<T> contract) { T[] services = (T[]) Array.newInstance( contract, 0 ); final ServiceTracker serviceTracker = getServiceTracker( contract.getName() ); try { // Yep, this is stupid. But, it's the only way to prevent #getServices from handing us back Object[]. services = (T[]) serviceTracker.getServices( services ); if ( services != null ) { return services; } } catch (Exception e) { LOG.unableToDiscoverOsgiService( contract.getName(), e ); } return services; } /** * Locate the single implementor of the given service contract in the given OSGi buindle context. Utilizes * {@link ServiceTracker#waitForService(long)} * * @param contract The service contract for which to locate implementors * @param context The OSGi bundle context * @param T[] The Java type of the service to locate * @return All know implementors */ public <T> T getServiceImpl(Class<T> contract) { final ServiceTracker serviceTracker = getServiceTracker( contract.getName() ); try { return (T) serviceTracker.waitForService( 1000 ); } catch (Exception e) { LOG.unableToDiscoverOsgiService( contract.getName(), e ); return null; } } private <T> ServiceTracker getServiceTracker(String contractClassName) { if ( !serviceTrackers.containsKey( contractClassName ) ) { final ServiceTracker<T, T> serviceTracker = new ServiceTracker<T, T>( context, contractClassName, null ); serviceTracker.open(); serviceTrackers.put( contractClassName, serviceTracker ); } return serviceTrackers.get( contractClassName ); } @Override public void stop() { for (String key : serviceTrackers.keySet()) { serviceTrackers.get( key ).close(); } serviceTrackers.clear(); } }