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.activemq.util; 018 019 import java.io.BufferedInputStream; 020 import java.io.IOException; 021 import java.io.InputStream; 022 import java.util.Properties; 023 import java.util.concurrent.ConcurrentHashMap; 024 025 /** 026 * 027 */ 028 public class FactoryFinder { 029 030 /** 031 * The strategey that the FactoryFinder uses to find load and instanciate Objects 032 * can be chagned out by calling the 033 * {@link org.apache.activemq.util.FactoryFinder#setObjectFactory(org.apache.activemq.util.FactoryFinder.ObjectFactory)} 034 * method with a custom implemenation of ObjectFactory. 035 * 036 * The default ObjectFactory is typically changed out when running in a specialized container 037 * enviorment where service discovery needs to be done via the container system. For example, 038 * in an OSGi scenario. 039 */ 040 public interface ObjectFactory { 041 /** 042 * @param path the full service path 043 * @return 044 */ 045 public Object create(String path) throws IllegalAccessException, InstantiationException, IOException, ClassNotFoundException; 046 047 } 048 049 /** 050 * The default implementation of Object factory which works well in standalone applications. 051 */ 052 protected static class StandaloneObjectFactory implements ObjectFactory { 053 final ConcurrentHashMap<String, Class> classMap = new ConcurrentHashMap<String, Class>(); 054 055 public Object create(final String path) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IOException { 056 Class clazz = classMap.get(path); 057 if (clazz == null) { 058 clazz = loadClass(loadProperties(path)); 059 classMap.put(path, clazz); 060 } 061 return clazz.newInstance(); 062 } 063 064 static public Class loadClass(Properties properties) throws ClassNotFoundException, IOException { 065 066 String className = properties.getProperty("class"); 067 if (className == null) { 068 throw new IOException("Expected property is missing: class"); 069 } 070 Class clazz = null; 071 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 072 if (loader != null) { 073 try { 074 clazz = loader.loadClass(className); 075 } catch (ClassNotFoundException e) { 076 // ignore 077 } 078 } 079 if (clazz == null) { 080 clazz = FactoryFinder.class.getClassLoader().loadClass(className); 081 } 082 083 return clazz; 084 } 085 086 static public Properties loadProperties(String uri) throws IOException { 087 // lets try the thread context class loader first 088 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 089 if (classLoader == null) { 090 classLoader = StandaloneObjectFactory.class.getClassLoader(); 091 } 092 InputStream in = classLoader.getResourceAsStream(uri); 093 if (in == null) { 094 in = FactoryFinder.class.getClassLoader().getResourceAsStream(uri); 095 if (in == null) { 096 throw new IOException("Could not find factory class for resource: " + uri); 097 } 098 } 099 100 // lets load the file 101 BufferedInputStream reader = null; 102 try { 103 reader = new BufferedInputStream(in); 104 Properties properties = new Properties(); 105 properties.load(reader); 106 return properties; 107 } finally { 108 try { 109 reader.close(); 110 } catch (Exception e) { 111 } 112 } 113 } 114 } 115 116 // ================================================================ 117 // Class methods and properties 118 // ================================================================ 119 private static ObjectFactory objectFactory = new StandaloneObjectFactory(); 120 121 public static ObjectFactory getObjectFactory() { 122 return objectFactory; 123 } 124 125 public static void setObjectFactory(ObjectFactory objectFactory) { 126 FactoryFinder.objectFactory = objectFactory; 127 } 128 129 // ================================================================ 130 // Instance methods and properties 131 // ================================================================ 132 private final String path; 133 134 public FactoryFinder(String path) { 135 this.path = path; 136 } 137 138 /** 139 * Creates a new instance of the given key 140 * 141 * @param key is the key to add to the path to find a text file containing 142 * the factory name 143 * @return a newly created instance 144 */ 145 public Object newInstance(String key) throws IllegalAccessException, InstantiationException, IOException, ClassNotFoundException { 146 return objectFactory.create(path+key); 147 } 148 149 150 }