View Javadoc

1   /*
2    * $Id: SpiUtils.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.util;
12  
13  import java.io.IOException;
14  import java.io.InputStream;
15  import java.security.AccessController;
16  import java.security.PrivilegedAction;
17  import java.util.Properties;
18  
19  import org.apache.commons.discovery.DiscoveryException;
20  import org.apache.commons.discovery.resource.ClassLoaders;
21  import org.apache.commons.discovery.tools.DiscoverClass;
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  
25  // @ThreadSafe
26  public final class SpiUtils
27  {
28      private static final Log logger = LogFactory.getLog(SpiUtils.class);
29  
30      public static final String SERVICE_ROOT = "META-INF/services/";
31  
32      /** Do not instanciate. */
33      private SpiUtils ()
34      {
35          // no-op
36      }
37  
38      /**
39       * Find class implementing a specified SPI.
40       * 
41       * @param spi Service Provider Interface Class.
42       * @param propertyFileName is a location of a property file that contains the SPI
43       *            property value
44       * @param defaultImpl Default implementation class name.
45       * @param currentClass is used to include the classloader of the calling class in
46       *            the search. All system classloaders will be checked as well.
47       * @return Class implementing the SPI or null if a service was not found
48       */
49      public static Class findService(Class spi, String propertyFileName, String defaultImpl, Class currentClass)
50      {
51          ClassLoaders loaders = ClassLoaders.getAppLoaders(spi, currentClass, false);
52          DiscoverClass discover = new DiscoverClass(loaders);
53          try
54          {
55              return discover.find(spi, propertyFileName, defaultImpl);
56          }
57          catch (DiscoveryException e)
58          {
59              // TODO MULE-863: Is logging necessary and correct level?
60              logger.warn("Failed to find service for spi: " + spi.getName());
61              return null;
62          }
63      }
64  
65      /**
66       * Find class implementing a specified SPI. The system properties will be checked
67       * for an SPI property to use. this will be the fully qualified SPI class name.
68       * 
69       * @param spi Service Provider Interface Class.
70       * @param defaultImpl Default implementation class name.
71       * @param currentClass is used to include the classloader of the calling class in
72       *            the search. All system classloaders will be checked as well.
73       * @return Class implementing the SPI or the default implementation class if
74       *         nothing has been found
75       */
76      public static Class findService(final Class spi, final String defaultImpl, final Class currentClass)
77      {
78          ClassLoaders loaders = (ClassLoaders) AccessController.doPrivileged(new PrivilegedAction()
79          {
80              public Object run()
81              {
82                  return ClassLoaders.getAppLoaders(spi, currentClass, false);
83              }
84          });
85          DiscoverClass discover = new DiscoverClass(loaders);
86          try
87          {
88              return discover.find(spi, System.getProperties(), defaultImpl);
89          }
90          catch (DiscoveryException e)
91          {
92              // TODO MULE-863: What should we really do? (Not as documentation)
93              logger.warn("Failed to find service for spi: " + spi.getName());
94              return null;
95          }
96      }
97  
98      /**
99       * Find class implementing a specified SPI. The system properties will be checked
100      * for an SPI property to use. this will be the fully qualified SPI class name.
101      * 
102      * @param spi Service Provider Interface Class.
103      * @param currentClass is used to include the classloader of the calling class in
104      *            the search. All system classloaders will be checked as well.
105      * @return Class implementing the SPI or null if a service was not found
106      */
107     public static Class findService(Class spi, Class currentClass)
108     {
109         ClassLoaders loaders = ClassLoaders.getAppLoaders(spi, currentClass, false);
110         DiscoverClass discover = new DiscoverClass(loaders);
111         try
112         {
113             return discover.find(spi, System.getProperties());
114         }
115         catch (DiscoveryException e)
116         {
117             // TODO MULE-863:Necessary?  Level?
118             logger.warn("Failed to find service for spi: " + spi.getName());
119             return null;
120         }
121     }
122 
123     /**
124      * Find class implementing a specified SPI.
125      * 
126      * @param spi Service Provider Interface Class.
127      * @param currentClass is used to include the classloader of the calling class in
128      *            the search.
129      * @param props The properties will be checked for an SPI property to use. this
130      *            will be the fully qualified SPI class name. All system classloaders
131      *            will be checked as well.
132      * @return Class implementing the SPI or null if a service was not found
133      */
134     public static Class findService(Class spi, Properties props, Class currentClass)
135     {
136         ClassLoaders loaders = ClassLoaders.getAppLoaders(spi, currentClass, false);
137         DiscoverClass discover = new DiscoverClass(loaders);
138         try
139         {
140             return discover.find(spi, props);
141         }
142         catch (DiscoveryException e)
143         {
144             // TODO MULE-863: Necessary?  Level?
145             logger.warn("Failed to find service for spi: " + spi.getName());
146             return null;
147         }
148     }
149 
150     public static InputStream findServiceDescriptor(String path, String name, Class currentClass)
151     {
152         if (path.startsWith("/"))
153         {
154             path = path.substring(1);
155         }
156         if (!path.endsWith("/"))
157         {
158             path += "/";
159         }
160         if (path.startsWith(SERVICE_ROOT))
161         {
162             path += name;
163         }
164         else
165         {
166             path = SERVICE_ROOT + path + name;
167         }
168         try
169         {
170             return IOUtils.getResourceAsStream(path, currentClass, false, false);
171         }
172         catch (IOException e)
173         {
174             return null;
175         }
176     }
177 }