001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.discovery.tools; 018 019 import java.util.Enumeration; 020 import java.util.NoSuchElementException; 021 022 import org.apache.commons.discovery.ResourceClass; 023 import org.apache.commons.discovery.ResourceClassIterator; 024 import org.apache.commons.discovery.ResourceNameIterator; 025 import org.apache.commons.discovery.resource.ClassLoaders; 026 import org.apache.commons.discovery.resource.classes.DiscoverClasses; 027 import org.apache.commons.discovery.resource.names.DiscoverServiceNames; 028 029 /** 030 * [this was ServiceDiscovery12... the 1.1 versus 1.2 issue 031 * has been abstracted to org.apache.commons.discover.jdk.JDKHooks] 032 * 033 * <p>Implement the JDK1.3 'Service Provider' specification. 034 * ( http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html ) 035 * </p> 036 * 037 * This class supports any VM, including JDK1.1, via 038 * org.apache.commons.discover.jdk.JDKHooks. 039 * 040 * The caller will first configure the discoverer by adding ( in the desired 041 * order ) all the places to look for the META-INF/services. Currently 042 * we support loaders. 043 * 044 * The findResources() method will check every loader. 045 */ 046 public class Service { 047 048 /** 049 * Construct a new service discoverer 050 */ 051 protected Service() { 052 } 053 054 /** 055 * as described in 056 * sun/jdk1.3.1/docs/guide/jar/jar.html#Service Provider, 057 * Except this uses <code>Enumeration</code> 058 * instead of <code>Interator</code>. 059 * 060 * @param <T> Service Provider Interface type 061 * @param <S> Any type extends the SPI type 062 * @param spiClass Service Provider Interface Class 063 * @return Enumeration of class instances ({@code S}) 064 */ 065 public static <T, S extends T> Enumeration<S> providers(Class<T> spiClass) { 066 return providers(new SPInterface<T>(spiClass), null); 067 } 068 069 /** 070 * This version lets you specify constructor arguments.. 071 * 072 * @param <T> Service Provider Interface type 073 * @param <S> Any type extends the SPI type 074 * @param spi SPI to look for and load. 075 * @param loaders loaders to use in search. 076 * If <code>null</code> then use ClassLoaders.getAppLoaders(). 077 * @return Enumeration of class instances ({@code S}) 078 */ 079 public static <T, S extends T> Enumeration<S> providers(final SPInterface<T> spi, 080 ClassLoaders loaders) { 081 if (loaders == null) { 082 loaders = ClassLoaders.getAppLoaders(spi.getSPClass(), 083 Service.class, 084 true); 085 } 086 087 ResourceNameIterator servicesIter = 088 (new DiscoverServiceNames(loaders)).findResourceNames(spi.getSPName()); 089 090 final ResourceClassIterator<T> services = 091 (new DiscoverClasses<T>(loaders)).findResourceClasses(servicesIter); 092 093 return new Enumeration<S>() { 094 095 private S object = getNextClassInstance(); 096 097 public boolean hasMoreElements() { 098 return object != null; 099 } 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 }