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.io.IOException;
020 import java.io.InputStream;
021 import java.util.Properties;
022
023 import org.apache.commons.discovery.DiscoveryException;
024 import org.apache.commons.discovery.Resource;
025 import org.apache.commons.discovery.ResourceIterator;
026 import org.apache.commons.discovery.resource.ClassLoaders;
027 import org.apache.commons.discovery.resource.DiscoverResources;
028
029
030 /**
031 * Mechanisms to locate and load a class.
032 * The load methods locate a class only.
033 * The find methods locate a class and verify that the
034 * class implements an given interface or extends a given class.
035 *
036 * @author Richard A. Sitze
037 * @author Craig R. McClanahan
038 * @author Costin Manolache
039 */
040 public class ResourceUtils {
041 /**
042 * Get package name.
043 * Not all class loaders 'keep' package information,
044 * in which case Class.getPackage() returns null.
045 * This means that calling Class.getPackage().getName()
046 * is unreliable at best.
047 */
048 public static String getPackageName(Class clazz) {
049 Package clazzPackage = clazz.getPackage();
050 String packageName;
051 if (clazzPackage != null) {
052 packageName = clazzPackage.getName();
053 } else {
054 String clazzName = clazz.getName();
055 packageName = new String(clazzName.toCharArray(), 0, clazzName.lastIndexOf('.'));
056 }
057 return packageName;
058 }
059
060
061 /**
062 * Load the resource <code>resourceName</code>.
063 * Try each classloader in succession,
064 * until first succeeds, or all fail.
065 * If all fail and <code>resouceName</code> is not absolute
066 * (doesn't start with '/' character), then retry with
067 * <code>packageName/resourceName</code> after changing all
068 * '.' to '/'.
069 *
070 * @param resourceName The name of the resource to load.
071 */
072 public static Resource getResource(Class spi,
073 String resourceName,
074 ClassLoaders loaders)
075 throws DiscoveryException
076 {
077 DiscoverResources explorer = new DiscoverResources(loaders);
078 ResourceIterator resources = explorer.findResources(resourceName);
079
080 if (spi != null &&
081 !resources.hasNext() &&
082 resourceName.charAt(0) != '/')
083 {
084 /**
085 * If we didn't find the resource, and if the resourceName
086 * isn't an 'absolute' path name, then qualify with
087 * package name of the spi.
088 */
089 resourceName = getPackageName(spi).replace('.','/') + "/" + resourceName;
090 resources = explorer.findResources(resourceName);
091 }
092
093 return resources.hasNext()
094 ? resources.nextResource()
095 : null;
096 }
097
098 /**
099 * Load named property file, optionally qualifed by spi's package name
100 * as per Class.getResource.
101 *
102 * A property file is loaded using the following sequence of class loaders:
103 * <ul>
104 * <li>Thread Context Class Loader</li>
105 * <li>DiscoverSingleton's Caller's Class Loader</li>
106 * <li>SPI's Class Loader</li>
107 * <li>DiscoverSingleton's (this class) Class Loader</li>
108 * <li>System Class Loader</li>
109 * </ul>
110 *
111 * @param propertiesFileName The property file name.
112 *
113 * @return Instance of a class implementing the SPI.
114 *
115 * @exception DiscoveryException Thrown if the name of a class implementing
116 * the SPI cannot be found, if the class cannot be loaded and
117 * instantiated, or if the resulting class does not implement
118 * (or extend) the SPI.
119 */
120 public static Properties loadProperties(Class spi,
121 String propertiesFileName,
122 ClassLoaders classLoaders)
123 throws DiscoveryException
124 {
125 Properties properties = null;
126
127 if (propertiesFileName != null) {
128 try {
129 Resource resource = getResource(spi, propertiesFileName, classLoaders);
130 if (resource != null) {
131 InputStream stream = resource.getResourceAsStream();
132
133 if (stream != null) {
134 properties = new Properties();
135 try {
136 properties.load(stream);
137 } finally {
138 stream.close();
139 }
140 }
141 }
142 } catch (IOException e) {
143 // ignore
144 } catch (SecurityException e) {
145 // ignore
146 }
147 }
148
149 return properties;
150 }
151 }