View Javadoc

1   /*
2    * $Id: SpiUtils.java 10404 2008-01-18 17:06:25Z 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              logger.warn("Failed to find service for spi: " + spi.getName());
60              return null;
61          }
62      }
63  
64      /**
65       * Find class implementing a specified SPI. The system properties will be checked
66       * for an SPI property to use. this will be the fully qualified SPI class name.
67       * 
68       * @param spi Service Provider Interface Class.
69       * @param defaultImpl Default implementation class name.
70       * @param currentClass is used to include the classloader of the calling class in
71       *            the search. All system classloaders will be checked as well.
72       * @return Class implementing the SPI or the default implementation class if
73       *         nothing has been found
74       */
75      public static Class findService(final Class spi, final String defaultImpl, final Class currentClass)
76      {
77          ClassLoaders loaders = (ClassLoaders) AccessController.doPrivileged(new PrivilegedAction()
78          {
79              public Object run()
80              {
81                  return ClassLoaders.getAppLoaders(spi, currentClass, false);
82              }
83          });
84          DiscoverClass discover = new DiscoverClass(loaders);
85          try
86          {
87              return discover.find(spi, System.getProperties(), defaultImpl);
88          }
89          catch (DiscoveryException e)
90          {
91              logger.warn("Failed to find service for spi: " + spi.getName());
92              return null;
93          }
94      }
95  
96      /**
97       * Find class implementing a specified SPI. The system properties will be checked
98       * for an SPI property to use. this will be the fully qualified SPI class name.
99       * 
100      * @param spi Service Provider Interface Class.
101      * @param currentClass is used to include the classloader of the calling class in
102      *            the search. All system classloaders will be checked as well.
103      * @return Class implementing the SPI or null if a service was not found
104      */
105     public static Class findService(Class spi, Class currentClass)
106     {
107         ClassLoaders loaders = ClassLoaders.getAppLoaders(spi, currentClass, false);
108         DiscoverClass discover = new DiscoverClass(loaders);
109         try
110         {
111             return discover.find(spi, System.getProperties());
112         }
113         catch (DiscoveryException e)
114         {
115             logger.warn("Failed to find service for spi: " + spi.getName());
116             return null;
117         }
118     }
119 
120     /**
121      * Find class implementing a specified SPI.
122      * 
123      * @param spi Service Provider Interface Class.
124      * @param currentClass is used to include the classloader of the calling class in
125      *            the search.
126      * @param props The properties will be checked for an SPI property to use. this
127      *            will be the fully qualified SPI class name. All system classloaders
128      *            will be checked as well.
129      * @return Class implementing the SPI or null if a service was not found
130      */
131     public static Class findService(Class spi, Properties props, Class currentClass)
132     {
133         ClassLoaders loaders = ClassLoaders.getAppLoaders(spi, currentClass, false);
134         DiscoverClass discover = new DiscoverClass(loaders);
135         try
136         {
137             return discover.find(spi, props);
138         }
139         catch (DiscoveryException e)
140         {
141             logger.warn("Failed to find service for spi: " + spi.getName());
142             return null;
143         }
144     }
145 
146     public static InputStream findServiceDescriptor(String path, String name, Class currentClass)
147     {
148         if (path.startsWith("/"))
149         {
150             path = path.substring(1);
151         }
152         if (!path.endsWith("/"))
153         {
154             path += "/";
155         }
156         if (path.startsWith(SERVICE_ROOT))
157         {
158             path += name;
159         }
160         else
161         {
162             path = SERVICE_ROOT + path + name;
163         }
164         try
165         {
166             return IOUtils.getResourceAsStream(path, currentClass, false, false);
167         }
168         catch (IOException e)
169         {
170             return null;
171         }
172     }
173 }