1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.discovery.tools; 18 19 import java.util.Enumeration; 20 import java.util.NoSuchElementException; 21 22 import org.apache.commons.discovery.ResourceClass; 23 import org.apache.commons.discovery.ResourceClassIterator; 24 import org.apache.commons.discovery.ResourceNameIterator; 25 import org.apache.commons.discovery.resource.ClassLoaders; 26 import org.apache.commons.discovery.resource.classes.DiscoverClasses; 27 import org.apache.commons.discovery.resource.names.DiscoverServiceNames; 28 29 /** 30 * [this was ServiceDiscovery12... the 1.1 versus 1.2 issue 31 * has been abstracted to org.apache.commons.discover.jdk.JDKHooks] 32 * 33 * <p>Implement the JDK1.3 'Service Provider' specification. 34 * ( http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html ) 35 * </p> 36 * 37 * This class supports any VM, including JDK1.1, via 38 * org.apache.commons.discover.jdk.JDKHooks. 39 * 40 * The caller will first configure the discoverer by adding ( in the desired 41 * order ) all the places to look for the META-INF/services. Currently 42 * we support loaders. 43 * 44 * The findResources() method will check every loader. 45 */ 46 public class Service { 47 48 /** 49 * Construct a new service discoverer 50 */ 51 protected Service() { 52 } 53 54 /** 55 * as described in 56 * sun/jdk1.3.1/docs/guide/jar/jar.html#Service Provider, 57 * Except this uses <code>Enumeration</code> 58 * instead of <code>Interator</code>. 59 * 60 * @param <T> Service Provider Interface type 61 * @param <S> Any type extends the SPI type 62 * @param spiClass Service Provider Interface Class 63 * @return Enumeration of class instances ({@code S}) 64 */ 65 public static <T, S extends T> Enumeration<S> providers(Class<T> spiClass) { 66 return providers(new SPInterface<T>(spiClass), null); 67 } 68 69 /** 70 * This version lets you specify constructor arguments.. 71 * 72 * @param <T> Service Provider Interface type 73 * @param <S> Any type extends the SPI type 74 * @param spi SPI to look for and load. 75 * @param loaders loaders to use in search. 76 * If <code>null</code> then use ClassLoaders.getAppLoaders(). 77 * @return Enumeration of class instances ({@code S}) 78 */ 79 public static <T, S extends T> Enumeration<S> providers(final SPInterface<T> spi, 80 ClassLoaders loaders) { 81 if (loaders == null) { 82 loaders = ClassLoaders.getAppLoaders(spi.getSPClass(), 83 Service.class, 84 true); 85 } 86 87 ResourceNameIterator servicesIter = 88 (new DiscoverServiceNames(loaders)).findResourceNames(spi.getSPName()); 89 90 final ResourceClassIterator<T> services = 91 (new DiscoverClasses<T>(loaders)).findResourceClasses(servicesIter); 92 93 return new Enumeration<S>() { 94 95 private S object = getNextClassInstance(); 96 97 public boolean hasMoreElements() { 98 return object != null; 99 } 100 101 public S nextElement() { 102 if (object == null) { 103 throw new NoSuchElementException(); 104 } 105 106 S obj = object; 107 object = getNextClassInstance(); 108 return obj; 109 } 110 111 private S getNextClassInstance() { 112 while (services.hasNext()) { 113 ResourceClass<S> info = services.nextResourceClass(); 114 try { 115 return spi.newInstance(info.loadClass()); 116 } catch (Exception e) { 117 // ignore 118 } catch (LinkageError le) { 119 // ignore 120 } 121 } 122 return null; 123 } 124 }; 125 } 126 127 }