/** * Copyright (C) 2011-2015 The XDocReport Team <xdocreport@googlegroups.com> * * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package fr.opensagres.xdocreport.core.internal; import java.lang.reflect.Method; import java.util.Iterator; import java.util.logging.Level; import java.util.logging.Logger; import fr.opensagres.xdocreport.core.logging.LogUtils; /** * JDK ServiceLoader is used to load services declared in the META-INF/services/MyClass. Switch JDK using, it uses: * <ul> * <li><b>java.util.ServiceLoader</b> if XDocReport works on Java6. For example : * <p> * <code>Iterator<Discovery> discoveries = ServiceLoader.load( registryType, getClass().getClassLoader() ).iterator();</code> * </p> * </li> * <li><b>javax.imageio.spi.ServiceRegistry</b> if XDocReport works on Java5. For example : * <p> * <code>Iterator<Discovery> discoveries = ServiceRegistry.lookupProviders( registryType, getClass().getClassLoader() );</code> * </p> * </li> * </ul> */ public abstract class JDKServiceLoader { private static final Logger LOGGER = LogUtils.getLogger( JDKServiceLoader.class.getName() ); // The JDK Service loader to use. private static JDKServiceLoader JDK_SERVICE_LOADER; static { ClassLoader classLoader = JDKServiceLoader.class.getClassLoader(); try { // At first, try to use JDK6 java.util.ServiceLoader JDK_SERVICE_LOADER = new JDK6ServiceLoader( classLoader ); if ( LOGGER.isLoggable( Level.FINE ) ) { LOGGER.fine( "Uses JDK6 java.util.ServiceLoader to load services." ); } } catch ( Throwable e ) { // JDK6 is not used here, uses the JDK5 javax.imageio.spi.ServiceRegistry try { JDK_SERVICE_LOADER = new JDK5ServiceLoader( classLoader ); if ( LOGGER.isLoggable( Level.FINE ) ) { LOGGER.fine( "Uses JDK5 javax.imageio.spi.ServiceRegistry to load services." ); } } catch ( Throwable e1 ) { // Should never thrown. if ( LOGGER.isLoggable( Level.SEVERE ) ) { LOGGER.log( Level.SEVERE, "Error while initialization of JDKServiceLoader", e1 ); } } } } public static <T> Iterator<T> lookupProviders( Class<T> providerClass, ClassLoader loader ) { try { return JDK_SERVICE_LOADER.lookupProvidersFromJDK( providerClass, loader ); } catch ( Exception e ) { throw new RuntimeException( e ); } } protected abstract <T> Iterator<T> lookupProvidersFromJDK( Class<T> providerClass, ClassLoader loader ) throws Exception; private static class JDK5ServiceLoader extends JDKServiceLoader { private final Method lookupProvidersMethod; public JDK5ServiceLoader( ClassLoader classLoader ) throws ClassNotFoundException, SecurityException, NoSuchMethodException { Class<?> slc = classLoader.loadClass( "javax.imageio.spi.ServiceRegistry" ); lookupProvidersMethod = slc.getMethod( "lookupProviders", Class.class, ClassLoader.class ); } @SuppressWarnings( "unchecked" ) @Override protected <T> Iterator<T> lookupProvidersFromJDK( Class<T> providerClass, ClassLoader loader ) throws Exception { return (Iterator<T>) lookupProvidersMethod.invoke( null, providerClass, loader ); } } private static class JDK6ServiceLoader extends JDKServiceLoader { private Method loadMethod; private Method iteratorMethod; public JDK6ServiceLoader( ClassLoader classLoader ) throws ClassNotFoundException, SecurityException, NoSuchMethodException { Class<?> slc = classLoader.loadClass( "java.util.ServiceLoader" ); loadMethod = slc.getMethod( "load", Class.class, ClassLoader.class ); iteratorMethod = slc.getMethod( "iterator" ); } @SuppressWarnings( "unchecked" ) @Override protected <T> Iterator<T> lookupProvidersFromJDK( Class<T> providerClass, ClassLoader loader ) throws Exception { Object serviceLoader = loadMethod.invoke( null, providerClass, loader ); return (Iterator<T>) iteratorMethod.invoke( serviceLoader ); } } }