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 import org.apache.activemq.transport.LogWriter;
026 import org.apache.activemq.transport.TransportLoggerView;
027 import org.slf4j.Logger;
028 import org.slf4j.LoggerFactory;
029
030 /**
031 * Class used to find a LogWriter implementation, and returning
032 * a LogWriter object, taking as argument the name of a log writer.
033 * The mapping between the log writer names and the classes
034 * implementing LogWriter is specified by the files in the
035 * resources/META-INF/services/org/apache/activemq/transport/logwriters
036 * directory.
037 *
038 * @author David Martin Clavo david(dot)martin(dot)clavo(at)gmail.com
039 *
040 */
041 public class LogWriterFinder {
042
043 private static final Logger log = LoggerFactory.getLogger(TransportLoggerView.class);
044
045 private final String path;
046 private final ConcurrentHashMap classMap = new ConcurrentHashMap();
047
048 /**
049 * Builds a LogWriterFinder that will look for the mappings between
050 * LogWriter names and classes in the directory "path".
051 * @param path The directory where the files that map log writer names to
052 * LogWriter classes are.
053 */
054 public LogWriterFinder(String path) {
055 this.path = path;
056 }
057
058 /**
059 * Returns a LogWriter object, given a log writer name (for example "default", or "custom").
060 * Uses a ConcurrentHashMap to cache the Class objects that have already been loaded.
061 * @param logWriterName a log writer name (for example "default", or "custom").
062 * @return a LogWriter object to be used by the TransportLogger class.
063 * @throws IllegalAccessException
064 * @throws InstantiationException
065 * @throws IOException
066 * @throws ClassNotFoundException
067 */
068 public LogWriter newInstance(String logWriterName)
069 throws IllegalAccessException, InstantiationException, IOException, ClassNotFoundException
070 {
071 Class clazz = (Class) classMap.get(logWriterName);
072 if (clazz == null) {
073 clazz = newInstance(doFindLogWriterProperties(logWriterName));
074 classMap.put(logWriterName, clazz);
075 }
076 return (LogWriter)clazz.newInstance();
077 }
078
079 /**
080 * Loads and returns a class given a Properties object with a "class" property.
081 * @param properties a Properties object with a "class" property.
082 * @return a Class object.
083 * @throws ClassNotFoundException
084 * @throws IOException
085 */
086 private Class newInstance(Properties properties) throws ClassNotFoundException, IOException {
087
088 String className = properties.getProperty("class");
089 if (className == null) {
090 throw new IOException("Expected property is missing: " + "class");
091 }
092 Class clazz;
093 try {
094 clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
095 } catch (ClassNotFoundException e) {
096 clazz = LogWriterFinder.class.getClassLoader().loadClass(className);
097 }
098
099 return clazz;
100 }
101
102 /**
103 * Given a log writer name, returns a Properties object with a "class" property
104 * whose value is a String with the name of the class to be loaded.
105 * @param logWriterName a log writer name.
106 * @return a Properties object with a "class" property
107 * @throws IOException
108 */
109 protected Properties doFindLogWriterProperties (String logWriterName) throws IOException {
110
111 String uri = path + logWriterName;
112
113 // lets try the thread context class loader first
114 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
115 if (classLoader == null) classLoader = getClass().getClassLoader();
116 InputStream in = classLoader.getResourceAsStream(uri);
117 if (in == null) {
118 in = LogWriterFinder.class.getClassLoader().getResourceAsStream(uri);
119 if (in == null) {
120 log.error("Could not find log writer for resource: " + uri);
121 throw new IOException("Could not find log writer for resource: " + uri);
122 }
123 }
124
125 // lets load the file
126 BufferedInputStream reader = null;
127 Properties properties = new Properties();
128 try {
129 reader = new BufferedInputStream(in);
130 properties.load(reader);
131 return properties;
132 } finally {
133 try {
134 reader.close();
135 } catch (Exception e) {
136 }
137 }
138 }
139
140
141 }