All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rx.plugins.RxJavaPlugins Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2014 Netflix, Inc.
 * 
 * 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 rx.plugins;

import java.util.concurrent.atomic.AtomicReference;

/**
 * Registry for plugin implementations that allows global override and handles the retrieval of correct
 * implementation based on order of precedence:
 * 
    *
  1. plugin registered globally via {@code register} methods in this class
  2. *
  3. plugin registered and retrieved using {@link java.lang.System#getProperty(String)} (see get methods for * property names)
  4. *
  5. default implementation
  6. *
* * @see RxJava Wiki: Plugins */ public class RxJavaPlugins { private final static RxJavaPlugins INSTANCE = new RxJavaPlugins(); private final AtomicReference errorHandler = new AtomicReference(); private final AtomicReference observableExecutionHook = new AtomicReference(); //deprecated private final AtomicReference schedulerOverrides = new AtomicReference(); private final AtomicReference schedulersHook = new AtomicReference(); /** * Retrieves the single {@code RxJavaPlugins} instance. * * @return the single {@code RxJavaPlugins} instance */ public static RxJavaPlugins getInstance() { return INSTANCE; } /* package accessible for unit tests */RxJavaPlugins() { } /* package accessible for unit tests */void reset() { INSTANCE.errorHandler.set(null); INSTANCE.observableExecutionHook.set(null); INSTANCE.schedulersHook.set(null); } /** * Retrieves an instance of {@link RxJavaErrorHandler} to use based on order of precedence as defined in * {@link RxJavaPlugins} class header. *

* Override the default by calling {@link #registerErrorHandler(RxJavaErrorHandler)} or by setting the * property {@code rxjava.plugin.RxJavaErrorHandler.implementation} with the full classname to load. * * @return {@link RxJavaErrorHandler} implementation to use */ public RxJavaErrorHandler getErrorHandler() { if (errorHandler.get() == null) { // check for an implementation from System.getProperty first Object impl = getPluginImplementationViaProperty(RxJavaErrorHandler.class); if (impl == null) { // nothing set via properties so initialize with default errorHandler.compareAndSet(null, RxJavaErrorHandlerDefault.getInstance()); // we don't return from here but call get() again in case of thread-race so the winner will always get returned } else { // we received an implementation from the system property so use it errorHandler.compareAndSet(null, (RxJavaErrorHandler) impl); } } return errorHandler.get(); } /** * Registers an {@link RxJavaErrorHandler} implementation as a global override of any injected or default * implementations. * * @param impl * {@link RxJavaErrorHandler} implementation * @throws IllegalStateException * if called more than once or after the default was initialized (if usage occurs before trying * to register) */ public void registerErrorHandler(RxJavaErrorHandler impl) { if (!errorHandler.compareAndSet(null, impl)) { throw new IllegalStateException("Another strategy was already registered: " + errorHandler.get()); } } /** * Retrieves the instance of {@link RxJavaObservableExecutionHook} to use based on order of precedence as * defined in {@link RxJavaPlugins} class header. *

* Override the default by calling {@link #registerObservableExecutionHook(RxJavaObservableExecutionHook)} * or by setting the property {@code rxjava.plugin.RxJavaObservableExecutionHook.implementation} with the * full classname to load. * * @return {@link RxJavaObservableExecutionHook} implementation to use */ public RxJavaObservableExecutionHook getObservableExecutionHook() { if (observableExecutionHook.get() == null) { // check for an implementation from System.getProperty first Object impl = getPluginImplementationViaProperty(RxJavaObservableExecutionHook.class); if (impl == null) { // nothing set via properties so initialize with default observableExecutionHook.compareAndSet(null, RxJavaObservableExecutionHookDefault.getInstance()); // we don't return from here but call get() again in case of thread-race so the winner will always get returned } else { // we received an implementation from the system property so use it observableExecutionHook.compareAndSet(null, (RxJavaObservableExecutionHook) impl); } } return observableExecutionHook.get(); } /** * Register an {@link RxJavaObservableExecutionHook} implementation as a global override of any injected or * default implementations. * * @param impl * {@link RxJavaObservableExecutionHook} implementation * @throws IllegalStateException * if called more than once or after the default was initialized (if usage occurs before trying * to register) */ public void registerObservableExecutionHook(RxJavaObservableExecutionHook impl) { if (!observableExecutionHook.compareAndSet(null, impl)) { throw new IllegalStateException("Another strategy was already registered: " + observableExecutionHook.get()); } } private static Object getPluginImplementationViaProperty(Class pluginClass) { String classSimpleName = pluginClass.getSimpleName(); /* * Check system properties for plugin class. *

* This will only happen during system startup thus it's okay to use the synchronized * System.getProperties as it will never get called in normal operations. */ String implementingClass = System.getProperty("rxjava.plugin." + classSimpleName + ".implementation"); if (implementingClass != null) { try { Class cls = Class.forName(implementingClass); // narrow the scope (cast) to the type we're expecting cls = cls.asSubclass(pluginClass); return cls.newInstance(); } catch (ClassCastException e) { throw new RuntimeException(classSimpleName + " implementation is not an instance of " + classSimpleName + ": " + implementingClass); } catch (ClassNotFoundException e) { throw new RuntimeException(classSimpleName + " implementation class not found: " + implementingClass, e); } catch (InstantiationException e) { throw new RuntimeException(classSimpleName + " implementation not able to be instantiated: " + implementingClass, e); } catch (IllegalAccessException e) { throw new RuntimeException(classSimpleName + " implementation not able to be accessed: " + implementingClass, e); } } else { return null; } } /** * Retrieves the instance of {@link RxJavaDefaultSchedulers} to use based on order of precedence as defined * in the {@link RxJavaPlugins} class header. *

* Override the default by calling {@link #registerDefaultSchedulers(RxJavaDefaultSchedulers)} or by setting * the property {@code rxjava.plugin.RxJavaDefaultSchedulers.implementation} with the full classname to * load. * * @return the {@link RxJavaDefaultSchedulers} implementation in use */ public RxJavaDefaultSchedulers getDefaultSchedulers() { if (schedulerOverrides.get() == null) { // check for an implementation from System.getProperty first Object impl = getPluginImplementationViaProperty(RxJavaDefaultSchedulers.class); if (impl == null) { // nothing set via properties so initialize with default schedulerOverrides.compareAndSet(null, RxJavaDefaultSchedulersDefault.getInstance()); // we don't return from here but call get() again in case of thread-race so the winner will always get returned } else { // we received an implementation from the system property so use it schedulerOverrides.compareAndSet(null, (RxJavaDefaultSchedulers) impl); } } return schedulerOverrides.get(); } /** * Registers an {@link RxJavaDefaultSchedulers} implementation as a global override of any injected or * default implementations. * * @param impl * {@link RxJavaDefaultSchedulers} implementation * @throws IllegalStateException * if called more than once or after the default was initialized (if usage occurs before trying * to register) */ public void registerDefaultSchedulers(RxJavaDefaultSchedulers impl) { if (!schedulerOverrides.compareAndSet(null, impl)) { throw new IllegalStateException("Another strategy was already registered: " + schedulerOverrides.get()); } } /** * Retrieves the instance of {@link RxJavaSchedulersHook} to use based on order of precedence as defined * in the {@link RxJavaPlugins} class header. *

* Override the default by calling {@link #registerSchedulersHook(RxJavaSchedulersHook)} or by setting * the property {@code rxjava.plugin.RxJavaSchedulersHook.implementation} with the full classname to * load. * * @return the {@link RxJavaSchedulersHook} implementation in use */ public RxJavaSchedulersHook getSchedulersHook() { if (schedulersHook.get() == null) { // check for an implementation from System.getProperty first Object impl = getPluginImplementationViaProperty(RxJavaSchedulersHook.class); if (impl == null) { // nothing set via properties so initialize with default schedulersHook.compareAndSet(null, RxJavaSchedulersHook.getDefaultInstance()); // we don't return from here but call get() again in case of thread-race so the winner will always get returned } else { // we received an implementation from the system property so use it schedulersHook.compareAndSet(null, (RxJavaSchedulersHook) impl); } } return schedulersHook.get(); } /** * Registers an {@link RxJavaSchedulersHook} implementation as a global override of any injected or * default implementations. * * @param impl * {@link RxJavaSchedulersHook} implementation * @throws IllegalStateException * if called more than once or after the default was initialized (if usage occurs before trying * to register) */ public void registerSchedulersHook(RxJavaSchedulersHook impl) { if (!schedulersHook.compareAndSet(null, impl)) { throw new IllegalStateException("Another strategy was already registered: " + schedulersHook.get()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy