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 }