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 021 import org.apache.commons.discovery.ResourceClass; 022 import org.apache.commons.discovery.ResourceClassIterator; 023 import org.apache.commons.discovery.ResourceNameIterator; 024 import org.apache.commons.discovery.resource.ClassLoaders; 025 import org.apache.commons.discovery.resource.classes.DiscoverClasses; 026 import org.apache.commons.discovery.resource.names.DiscoverServiceNames; 027 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 * @author Richard A. Sitze 047 * @author Craig R. McClanahan 048 * @author Costin Manolache 049 * @author James Strachan 050 */ 051 public class Service 052 { 053 /** Construct a new service discoverer 054 */ 055 protected Service() { 056 } 057 058 /** 059 * as described in 060 * sun/jdk1.3.1/docs/guide/jar/jar.html#Service Provider, 061 * Except this uses <code>Enumeration</code> 062 * instead of <code>Interator</code>. 063 * 064 * @return Enumeration of class instances (<code>Object</code>) 065 */ 066 public static Enumeration providers(Class spiClass) { 067 return providers(new SPInterface(spiClass), null); 068 } 069 070 /** 071 * This version lets you specify constructor arguments.. 072 * 073 * @param spi SPI to look for and load. 074 * @param loaders loaders to use in search. 075 * If <code>null</code> then use ClassLoaders.getAppLoaders(). 076 */ 077 public static Enumeration providers(final SPInterface spi, 078 ClassLoaders loaders) 079 { 080 if (loaders == null) { 081 loaders = ClassLoaders.getAppLoaders(spi.getSPClass(), 082 Service.class, 083 true); 084 } 085 086 ResourceNameIterator servicesIter = 087 (new DiscoverServiceNames(loaders)).findResourceNames(spi.getSPName()); 088 089 final ResourceClassIterator services = 090 (new DiscoverClasses(loaders)).findResourceClasses(servicesIter); 091 092 return new Enumeration() { 093 private Object object = null; 094 095 public boolean hasMoreElements() { 096 if (object == null) { 097 object = getNextClassInstance(); 098 } 099 return object != null; 100 } 101 102 public Object nextElement() { 103 Object obj = object; 104 object = null; 105 return obj; 106 } 107 108 private Object getNextClassInstance() { 109 while (services.hasNext()) { 110 ResourceClass info = services.nextResourceClass(); 111 try { 112 return spi.newInstance(info.loadClass()); 113 } catch (Exception e) { 114 // ignore 115 } 116 } 117 return null; 118 } 119 }; 120 } 121 }