/******************************************************************************* * Copyright (c) 2008, 2014 Stuart McCulloch * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stuart McCulloch - initial API and implementation *******************************************************************************/ package org.eclipse.sisu.peaberry; import org.eclipse.sisu.peaberry.builders.DecoratedServiceBuilder; import org.eclipse.sisu.peaberry.internal.ServiceBuilderImpl; import org.eclipse.sisu.peaberry.osgi.OSGiModule; import org.osgi.framework.BundleContext; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.TypeLiteral; /** * Guice extension that supports injection and outjection of dynamic services. * <p> * For example, injecting a stock quote service: * * <pre> {@literal @}Inject * StockQuote quote; * ... * bind(StockQuote.class).toProvider(service(StockQuote.class).single());</pre> * * Injecting many stock quote services: * * <pre> {@literal @}Inject * Iterable<StockQuote> quotes; * ... * bind(iterable(StockQuote.class)).toProvider(service(StockQuote.class).multiple());</pre> * * Exporting an implementation as a stock quote service: * * <pre> {@literal @}Inject * // the service can be controlled by the Export handle * Export<StockQuote> exportedQuote; * ... * // the service is exported at injection time * bind(export(StockQuote.class)).toProvider(service(myQuoteImpl).export());</pre> * * Applying a custom filter to find a specific service: * * <pre> service(StockQuote.class).filter(ldap("(Currency=GBP)")).single()</pre> * * Applying custom attributes to an exported service: * * <pre> service(myQuoteImpl).attributes(names("Currency=GBP")).export()</pre> * * (the ldap and names utility methods are from {@link org.eclipse.sisu.peaberry.util}) * <p> * You can also decorate services with additional behaviour: * * <pre> service(StockQuote.class).decoratedWith(someDecoratorImpl).single()</pre> * * or ask for them to be injected directly, instead of using a dynamic proxy: * * <pre> service(StockQuote.class).single().direct()</pre> * * similarly, if you don't want to bother with an Export handle when exporting: * * <pre> service(myQuoteImpl).export().direct()</pre> * * Outjection is a way of actively monitoring for services instead of polling: * * <pre> service(StockQuote.class).out(myWatcherImpl).multiple()</pre> * * the given watcher is notified when matching services appear and disappear. <br> * ({@link org.eclipse.sisu.peaberry.util} has abstract watcher and decorator classes) * <p> * See the online <a href="http://code.google.com/p/peaberry/wiki/UserGuide" * target="_blank">User Guide</a> for the latest examples and suggested best * practice. * * @author mcculls@gmail.com (Stuart McCulloch) */ public final class Peaberry { // instances not allowed private Peaberry() {} /** * Start building a dynamic service provider for the given key. * * @param key binding key * @return dynamic service builder */ public static <T> DecoratedServiceBuilder<T> service(final Key<T> key) { return new ServiceBuilderImpl<T>(key); } /** * Start building a dynamic service provider for the given type. * * @param type binding type * @return dynamic service builder */ public static <T> DecoratedServiceBuilder<T> service(final TypeLiteral<T> type) { return new ServiceBuilderImpl<T>(Key.get(type)); } /** * Start building a dynamic service provider for the given class. * * @param clazz binding class * @return dynamic service builder */ public static <T> DecoratedServiceBuilder<T> service(final Class<T> clazz) { return new ServiceBuilderImpl<T>(Key.get(clazz)); } /** * Start building a dynamic service provider for the given instance. * * @param instance service instance * @return dynamic service builder */ public static <T> DecoratedServiceBuilder<T> service(final T instance) { return new ServiceBuilderImpl<T>(instance); } /** * Name of system property ({@code "org.eclipse.sisu.peaberry.cache.interval"}) * suggests the time in milliseconds between flushes of the service cache. */ public static final String CACHE_INTERVAL_HINT = "org.eclipse.sisu.peaberry.cache.interval"; /** * Name of system property ({@code "org.eclipse.sisu.peaberry.cache.generations"}) * suggests the number of flushes before an unused service is released. */ public static final String CACHE_GENERATIONS_HINT = "org.eclipse.sisu.peaberry.cache.generations"; /** * Name of system property ({@code "org.eclipse.sisu.peaberry.filter.native"}) * suggests using {@code AttributeFilter.toString()} as native filter. */ public static final String NATIVE_FILTER_HINT = "org.eclipse.sisu.peaberry.filter.native"; /** * Create a new Guice binding {@link Module} for the given bundle context. * * @param bundleContext current bundle context * @return OSGi specific Guice bindings */ public static Module osgiModule(final BundleContext bundleContext) { return new OSGiModule(bundleContext); } /** * Create a new Guice binding {@link Module} for the given bundle context * along with a list of additional {@link ServiceRegistry}s to query when * injecting or watching for services. * * @param bundleContext current bundle context * @param registries extra service registries * @return OSGi specific Guice bindings * * @since 1.1 */ public static Module osgiModule(final BundleContext bundleContext, final ServiceRegistry... registries) { return new OSGiModule(bundleContext, registries); } /** * Create a new Guice binding {@link Module} that uses an externally bound * bundle context along with a list of additional {@link ServiceRegistry}s * to query when injecting or watching for services. * * @param registries extra service registries * @return OSGi specific Guice bindings * * @since 1.3 */ public static Module osgiModule(final ServiceRegistry... registries) { return new OSGiModule(registries); } }