1. /*
  2. * $Header$
  3. * $Revision$
  4. * $Date$
  5. *
  6. * ====================================================================
  7. *
  8. * The Apache Software License, Version 1.1
  9. *
  10. * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
  11. * reserved.
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions
  15. * are met:
  16. *
  17. * 1. Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. *
  20. * 2. Redistributions in binary form must reproduce the above copyright
  21. * notice, this list of conditions and the following disclaimer in
  22. * the documentation and/or other materials provided with the
  23. * distribution.
  24. *
  25. * 3. The end-user documentation included with the redistribution, if
  26. * any, must include the following acknowlegement:
  27. * "This product includes software developed by the
  28. * Apache Software Foundation (http://www.apache.org/)."
  29. * Alternately, this acknowlegement may appear in the software itself,
  30. * if and wherever such third-party acknowlegements normally appear.
  31. *
  32. * 4. The names "The Jakarta Project", "Commons", and "Apache Software
  33. * Foundation" must not be used to endorse or promote products derived
  34. * from this software without prior written permission. For written
  35. * permission, please contact apache@apache.org.
  36. *
  37. * 5. Products derived from this software may not be called "Apache"
  38. * nor may "Apache" appear in their names without prior written
  39. * permission of the Apache Group.
  40. *
  41. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  42. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  43. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  44. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  45. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  46. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  47. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  48. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  49. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  50. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  51. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  52. * SUCH DAMAGE.
  53. * ====================================================================
  54. *
  55. * This software consists of voluntary contributions made by many
  56. * individuals on behalf of the Apache Software Foundation. For more
  57. * information on the Apache Software Foundation, please see
  58. * <http://www.apache.org/>.
  59. *
  60. */
  61. package org.apache.commons.discovery.tools;
  62. import java.io.IOException;
  63. import java.io.InputStream;
  64. import java.util.Properties;
  65. import org.apache.commons.discovery.DiscoveryException;
  66. import org.apache.commons.discovery.Resource;
  67. import org.apache.commons.discovery.ResourceIterator;
  68. import org.apache.commons.discovery.resource.ClassLoaders;
  69. import org.apache.commons.discovery.resource.DiscoverResources;
  70. /**
  71. * Mechanisms to locate and load a class.
  72. * The load methods locate a class only.
  73. * The find methods locate a class and verify that the
  74. * class implements an given interface or extends a given class.
  75. *
  76. * @author Richard A. Sitze
  77. * @author Craig R. McClanahan
  78. * @author Costin Manolache
  79. */
  80. public class ResourceUtils {
  81. /**
  82. * Get package name.
  83. * Not all class loaders 'keep' package information,
  84. * in which case Class.getPackage() returns null.
  85. * This means that calling Class.getPackage().getName()
  86. * is unreliable at best.
  87. */
  88. public static String getPackageName(Class clazz) {
  89. Package clazzPackage = clazz.getPackage();
  90. String packageName;
  91. if (clazzPackage != null) {
  92. packageName = clazzPackage.getName();
  93. } else {
  94. String clazzName = clazz.getName();
  95. packageName = new String(clazzName.toCharArray(), 0, clazzName.lastIndexOf('.'));
  96. }
  97. return packageName;
  98. }
  99. /**
  100. * Load the resource <code>resourceName</code>.
  101. * Try each classloader in succession,
  102. * until first succeeds, or all fail.
  103. * If all fail and <code>resouceName</code> is not absolute
  104. * (doesn't start with '/' character), then retry with
  105. * <code>packageName/resourceName</code> after changing all
  106. * '.' to '/'.
  107. *
  108. * @param resourceName The name of the resource to load.
  109. */
  110. public static Resource getResource(Class spi,
  111. String resourceName,
  112. ClassLoaders loaders)
  113. throws DiscoveryException
  114. {
  115. DiscoverResources explorer = new DiscoverResources(loaders);
  116. ResourceIterator resources = explorer.findResources(resourceName);
  117. if (spi != null &&
  118. !resources.hasNext() &&
  119. resourceName.charAt(0) != '/')
  120. {
  121. /**
  122. * If we didn't find the resource, and if the resourceName
  123. * isn't an 'absolute' path name, then qualify with
  124. * package name of the spi.
  125. */
  126. resourceName = getPackageName(spi).replace('.','/') + "/" + resourceName;
  127. resources = explorer.findResources(resourceName);
  128. }
  129. return resources.hasNext()
  130. ? resources.nextResource()
  131. : null;
  132. }
  133. /**
  134. * Load named property file, optionally qualifed by spi's package name
  135. * as per Class.getResource.
  136. *
  137. * A property file is loaded using the following sequence of class loaders:
  138. * <ul>
  139. * <li>Thread Context Class Loader</li>
  140. * <li>DiscoverSingleton's Caller's Class Loader</li>
  141. * <li>SPI's Class Loader</li>
  142. * <li>DiscoverSingleton's (this class) Class Loader</li>
  143. * <li>System Class Loader</li>
  144. * </ul>
  145. *
  146. * @param
  147. * @param propertiesFileName The property file name.
  148. *
  149. * @return Instance of a class implementing the SPI.
  150. *
  151. * @exception DiscoveryException Thrown if the name of a class implementing
  152. * the SPI cannot be found, if the class cannot be loaded and
  153. * instantiated, or if the resulting class does not implement
  154. * (or extend) the SPI.
  155. */
  156. public static Properties loadProperties(Class spi,
  157. String propertiesFileName,
  158. ClassLoaders classLoaders)
  159. throws DiscoveryException
  160. {
  161. Properties properties = null;
  162. if (propertiesFileName != null) {
  163. try {
  164. Resource resource = getResource(spi, propertiesFileName, classLoaders);
  165. if (resource != null) {
  166. InputStream stream = resource.getResourceAsStream();
  167. if (stream != null) {
  168. properties = new Properties();
  169. try {
  170. properties.load(stream);
  171. } finally {
  172. stream.close();
  173. }
  174. }
  175. }
  176. } catch (IOException e) {
  177. ; // ignore
  178. } catch (SecurityException e) {
  179. ; // ignore
  180. }
  181. }
  182. return properties;
  183. }
  184. }