001/* 002 * Units of Measurement API 003 * Copyright (c) 2014-2015, Jean-Marie Dautelle, Werner Keil, V2COM. 004 * 005 * All rights reserved. 006 * 007 * Redistribution and use in source and binary forms, with or without modification, 008 * are permitted provided that the following conditions are met: 009 * 010 * 1. Redistributions of source code must retain the above copyright notice, 011 * this list of conditions and the following disclaimer. 012 * 013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 014 * and the following disclaimer in the documentation and/or other materials provided with the distribution. 015 * 016 * 3. Neither the name of JSR-363 nor the names of its contributors may be used to endorse or promote products 017 * derived from this software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package javax.measure.spi; 031 032import static java.util.logging.Level.INFO; 033import static java.util.logging.Level.WARNING; 034 035import java.util.Collection; 036import java.util.ServiceLoader; 037import java.util.logging.Logger; 038 039/** 040 * This singleton provides access to the services available in the current runtime environment. The 041 * behavior can be adapted, by calling {@link #init(ServiceProvider)} before accessing any measurement 042 * services. 043 * 044 * @author <a href="mailto:[email protected]">Werner Keil</a> 045 * @version 0.5, October 4, 2015 046 */ 047public final class Bootstrap { 048 /** 049 * The ServiceProvider used. 050 */ 051 private static volatile ServiceProvider serviceProviderDelegate; 052 /** 053 * The shared lock instance user. 054 */ 055 private static final Object LOCK = new Object(); 056 057 /** 058 * Private singleton constructor. 059 */ 060 private Bootstrap() { 061 } 062 063 /** 064 * Load the {@link ServiceProvider} to be used. 065 * 066 * @return {@link ServiceProvider} to be used for loading the services. 067 */ 068 private static ServiceProvider loadDefaultServiceProvider() { 069 try { 070 for (ServiceProvider sp : ServiceLoader.load(ServiceProvider.class)) { 071 return sp; 072 } 073 } catch (Exception e) { 074 Logger.getLogger(Bootstrap.class.getName()).log(INFO, "No ServiceProvider loaded, using default."); 075 } 076 return new DefaultServiceProvider(); 077 } 078 079 /** 080 * Replace the current {@link ServiceProvider} in use. 081 * 082 * @param serviceProvider the new {@link ServiceProvider} 083 * @return the removed , or null. 084 */ 085 public static ServiceProvider init(ServiceProvider serviceProvider) { 086 if (serviceProvider == null) { 087 throw new NullPointerException(); 088 } 089 synchronized (LOCK) { 090 if (Bootstrap.serviceProviderDelegate==null) { 091 Bootstrap.serviceProviderDelegate = serviceProvider; 092 Logger.getLogger(Bootstrap.class.getName()).log(INFO, 093 "Measurement Bootstrap: new ServiceProvider set: " + serviceProvider.getClass().getName()); 094 return null; 095 } else { 096 ServiceProvider prevProvider = Bootstrap.serviceProviderDelegate; 097 Bootstrap.serviceProviderDelegate = serviceProvider; 098 Logger.getLogger(Bootstrap.class.getName()).log(WARNING, 099 "Measurement Bootstrap: ServiceProvider replaced: " + serviceProvider.getClass().getName()); 100 return prevProvider; 101 } 102 } 103 } 104 105 /** 106 * Returns the current {@link ServiceProvider}. If necessary the {@link ServiceProvider} will be lazily loaded. 107 * 108 * @return the {@link ServiceProvider} used. 109 */ 110 static ServiceProvider getServiceProvider() { 111 if (serviceProviderDelegate==null) { 112 synchronized (LOCK) { 113 if (serviceProviderDelegate==null) { 114 serviceProviderDelegate = loadDefaultServiceProvider(); 115 } 116 } 117 } 118 return serviceProviderDelegate; 119 } 120 121 /** 122 * Delegate method for {@link ServiceProvider#getServices(Class)}. 123 * 124 * @param serviceType the service type. 125 * @return the services found. 126 * @see ServiceProvider#getServices(Class) 127 */ 128 public static <T> Collection<T> getServices(Class<T> serviceType) { 129 return getServiceProvider().getServices(serviceType); 130 } 131 132 /** 133 * Delegate method for {@link ServiceProvider#getService(Class)}. 134 * 135 * @param serviceType the service type. 136 * @return the service found, or {@code null}. 137 * @see ServiceProvider#getServices(Class) 138 */ 139 public static <T> T getService(Class<T> serviceType) { 140 return getServiceProvider().getService(serviceType); 141 } 142}