View Javadoc

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  
21  import org.apache.commons.discovery.ResourceClass;
22  import org.apache.commons.discovery.ResourceClassIterator;
23  import org.apache.commons.discovery.ResourceNameIterator;
24  import org.apache.commons.discovery.resource.ClassLoaders;
25  import org.apache.commons.discovery.resource.classes.DiscoverClasses;
26  import org.apache.commons.discovery.resource.names.DiscoverServiceNames;
27  
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   * @author Richard A. Sitze
47   * @author Craig R. McClanahan
48   * @author Costin Manolache
49   * @author James Strachan
50   */
51  public class Service
52  {
53      /*** Construct a new service discoverer
54       */
55      protected Service() {
56      }
57      
58      /***
59       * as described in
60       * sun/jdk1.3.1/docs/guide/jar/jar.html#Service Provider,
61       * Except this uses <code>Enumeration</code>
62       * instead of <code>Interator</code>.
63       * 
64       * @return Enumeration of class instances (<code>Object</code>)
65       */
66      public static Enumeration providers(Class spiClass) {
67          return providers(new SPInterface(spiClass), null);
68      }
69      
70      /***
71       * This version lets you specify constructor arguments..
72       * 
73       * @param spi SPI to look for and load.
74       * @param loaders loaders to use in search.
75       *        If <code>null</code> then use ClassLoaders.getAppLoaders().
76       */
77      public static Enumeration providers(final SPInterface spi,
78                                          ClassLoaders loaders)
79      {
80          if (loaders == null) {
81              loaders = ClassLoaders.getAppLoaders(spi.getSPClass(),
82                                                   Service.class,
83                                                   true);
84          }
85          
86          ResourceNameIterator servicesIter =
87              (new DiscoverServiceNames(loaders)).findResourceNames(spi.getSPName());
88  
89          final ResourceClassIterator services =
90              (new DiscoverClasses(loaders)).findResourceClasses(servicesIter);
91          
92          return new Enumeration() {
93              private Object object = null;
94              
95              public boolean hasMoreElements() {
96                  if (object == null) {
97                      object = getNextClassInstance();
98                  }
99                  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 }