001: /*
002: *
003: *
004: * @ author Igor Smirnov
005: */
006:
007: package org.enhydra.logging;
008:
009: import java.io.FileInputStream;
010: import java.io.IOException;
011: import java.util.Enumeration;
012: import java.util.Hashtable;
013: import java.util.Iterator;
014: import java.util.Locale;
015: import java.util.Properties;
016: import java.util.ResourceBundle;
017: import java.util.Set;
018: import java.util.Vector;
019:
020: import javax.management.MBeanServer;
021: import javax.management.MBeanServerFactory;
022: import javax.management.ObjectName;
023:
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogConfigurationException;
026: import org.apache.commons.logging.LogFactory;
027: import org.objectweb.util.monolog.Monolog;
028: import org.objectweb.util.monolog.api.Logger;
029: import org.objectweb.util.monolog.api.LoggerFactory;
030: import org.objectweb.util.monolog.wrapper.common.Configurable;
031:
032: import com.lutris.util.ConfigException;
033:
034: /**
035: * <p>Concrete subclass of {@link LogFactory} specific to log4j.
036: *
037: * @deprecated Per discussion on COMMONS-DEV, the behind-the-scenes use
038: * of this class as a proxy factory has been removed. For 1.0, you
039: * can still request it directly if you wish, but it doesn't really
040: * do anything useful, and will be removed in 1.1.
041: *
042: * @author Costin Manolache
043: */
044: public final class MonologFactory extends LogFactory {
045: public org.objectweb.util.monolog.api.LoggerFactory lf;
046: public String traceproperties;
047: // private Logger logger = null;
048: // private String path, jonas, fileName;
049: private static ResourceBundle rb = null;
050: public static String PROPERTY_FILE;
051: static ObjectName objectName;
052:
053: public MonologFactory() throws ConfigException {
054:
055: super ();
056: try {
057: configure();
058: // this.logger = lf.getLogger("MonologFactory");
059: } catch (ConfigException ex) {
060: throw new ConfigException(
061: "Cannot configure logger. Logger not initialized.");
062: }
063: }
064:
065: /**
066: * The configuration attributes for this {@link LogFactory}.
067: */
068: private Hashtable attributes = new Hashtable();
069:
070: // previously returned instances, to avoid creation of proxies
071: private Hashtable instances = new Hashtable();
072:
073: // --------------------------------------------------------- Public Methods
074:
075: /**
076: * Return the configuration attribute with the specified name (if any),
077: * or <code>null</code> if there is no such attribute.
078: *
079: * @param name Name of the attribute to return
080: */
081: public Object getAttribute(String name) {
082: return (attributes.get(name));
083: }
084:
085: /**
086: * Return an array containing the names of all currently defined
087: * configuration attributes. If there are no such attributes, a zero
088: * length array is returned.
089: */
090: public String[] getAttributeNames() {
091: Vector names = new Vector();
092: Enumeration keys = attributes.keys();
093: while (keys.hasMoreElements()) {
094: names.addElement((String) keys.nextElement());
095: }
096: String results[] = new String[names.size()];
097: for (int i = 0; i < results.length; i++) {
098: results[i] = (String) names.elementAt(i);
099: }
100: return (results);
101: }
102:
103: /**
104: * Convenience method to derive a name from the specified class and
105: * call <code>getInstance(String)</code> with it.
106: *
107: * @param clazz Class for which a suitable Log name will be derived
108: *
109: * @exception LogConfigurationException if a suitable <code>Log</code>
110: * instance cannot be returned
111: */
112: public Log getInstance(Class clazz)
113: throws LogConfigurationException
114:
115: {
116: Log instance = (Log) instances.get(clazz.getName());
117: if (instance != null)
118: return instance;
119: instance = new CommonLoggingMonologLogger(lf.getLogger(clazz
120: .getName()));
121: instances.put(clazz.getName(), instance);
122: return instance;
123: }
124:
125: public Log getInstance(String name)
126: throws LogConfigurationException {
127: Log instance = (Log) instances.get(name);
128: if (instance != null)
129: return instance;
130:
131: instance = new CommonLoggingMonologLogger(lf.getLogger(name));
132: instances.put(name, instance);
133: return instance;
134: }
135:
136: /**
137: * Release any internal references to previously created {@link Log}
138: * instances returned by this factory. This is useful environments
139: * like servlet containers, which implement application reloading by
140: * throwing away a ClassLoader. Dangling references to objects in that
141: * class loader would prevent garbage collection.
142: */
143: public void release() {
144:
145: instances.clear();
146:
147: // what's the log4j mechanism to cleanup ???
148: }
149:
150: /**
151: * Remove any configuration attribute associated with the specified name.
152: * If there is no such attribute, no action is taken.
153: *
154: * @param name Name of the attribute to remove
155: */
156: public void removeAttribute(String name) {
157: attributes.remove(name);
158: }
159:
160: /**
161: * Set the configuration attribute with the specified name. Calling
162: * this with a <code>null</code> value is equivalent to calling
163: * <code>removeAttribute(name)</code>.
164: *
165: * @param name Name of the attribute to set
166: * @param value Value of the attribute to set, or <code>null</code>
167: * to remove any setting for this attribute
168: */
169: public void setAttribute(String name, Object value) {
170: if (value == null) {
171: attributes.remove(name);
172: } else {
173: attributes.put(name, value);
174: }
175: }
176:
177: /**
178: * Configure the logger. All current configuration is discarded.
179: * This is a simplistic initial implementation that just allows
180: * directing to a single log file or stderr on a level basis.
181: * A more complete interface will be provided in the future.
182: *
183: * @param logFile The log file to write to.
184: * @param fileLevels List of levels that will be written to the file.
185: * @param stderrLevels List of levels that will be written to stderr.
186: * The same level may appear in both lists.
187: * @exception java.io.IOException If an error occurs opening the log file.
188: */
189: public synchronized void configure(String monologConfFile) {
190:
191: // Load the configuration in a Properties object
192: String b = null;
193: Properties p = new Properties();
194: FileInputStream fis = null;
195: try {
196: fis = new FileInputStream(monologConfFile);
197: p.load(fis);
198: // Search the class name of the LoggerFactory which must be instanciated
199: b = p.getProperty("log.config.classname", null);
200: // Instanciate the LoggerFactory
201: lf = (LoggerFactory) Class.forName(b).newInstance();
202: // Configure with the properties
203: p.put(Configurable.LOG_CONFIGURATION_TYPE,
204: Configurable.PROPERTY);
205: p.put(Configurable.LOG_CONFIGURATION_FILE, monologConfFile);
206:
207: ((Configurable) lf).configure(p);
208:
209: fis.close();
210: } catch (Exception e) {
211: try {
212: fis.close();
213: } catch (IOException e1) {
214: e1.printStackTrace();
215: }
216: }
217: }
218:
219: /**
220: * Default configuration of the logger. A JMX search for logger configuration file name.
221: * This file must be present in the classpath
222: */
223: public synchronized void configure() throws ConfigException {
224: String b = null;
225: String propkey;
226: String propvalue;
227: Properties props = new Properties();
228:
229: try {
230: findMBeanServer();
231: findObjectName();
232: if (objectName != null)
233: PROPERTY_FILE = objectName.getKeyProperty("fname");
234: // Search the classpath for the logger configuration file
235: rb = ResourceBundle.getBundle(PROPERTY_FILE, new Locale(
236: "en", "US"), ClassLoader.getSystemClassLoader());
237:
238: Enumeration enumeration = rb.getKeys();
239:
240: while (enumeration.hasMoreElements()) {
241:
242: propkey = (String) enumeration.nextElement();
243: propvalue = rb.getString(propkey);
244: props.setProperty(propkey, propvalue);
245: }
246:
247: } catch (Exception e) {
248: throw new ConfigException(
249: "Logger configuration file could not be found: logger could not be initialized!");
250: }
251:
252: try {
253:
254: // Search the class name of the LoggerFactory which must be instanciated
255: b = props.getProperty("log.config.classname", null);
256: if (b == null) {
257: throw new ConfigException(
258: "Malformed configuration log file:"
259: + " log.config.classname not available");
260: }
261:
262: // Instanciate the LoggerFactory
263:
264: props.put(Configurable.LOG_CONFIGURATION_TYPE,
265: Configurable.PROPERTY);
266: // lf = Monolog.getMonologFactory(props);
267:
268: lf = Monolog.getMonologFactory(b);
269:
270: } catch (Exception e) {
271: throw new ConfigException(
272: "Malformed configuration log file:"
273: + " log.config.classname not available");
274: }
275:
276: }
277:
278: private MBeanServer findMBeanServer() throws Exception {
279: MBeanServer mBeanServer;
280: try {
281: java.util.ArrayList server = MBeanServerFactory
282: .findMBeanServer(null);
283: if (server == null) {
284: throw new Exception("MBeansServer not found");
285: } else {
286: mBeanServer = (MBeanServer) server.get(0);
287: //System.err.println("domain:" + mBeanServer.getDefaultDomain());
288: }
289: } catch (Exception e) {
290: throw new com.lutris.appserver.server.session.SessionException(
291: e);
292: }
293: return mBeanServer;
294: }
295:
296: /**
297: * finds the ObjectName which correspondes to the MBean of the jonas logger
298: */
299: private void findObjectName() throws Exception {
300: try {
301: objectName = new ObjectName("jonas:type=service,name=log,*");
302: MBeanServer mBeanServer = findMBeanServer();
303: Set mBeans = mBeanServer.queryNames(objectName, null);
304: int l;
305: if ((l = mBeans.size()) > 1) {
306: throw new Exception("MBean set size not equal 1: " + l);
307: } else if (l == 0) {
308: objectName = null;
309: return;
310: }
311: Iterator i = mBeans.iterator();
312: objectName = (ObjectName) i.next();
313: } catch (Exception e) {
314: throw new Exception(e);
315: }
316: return;
317: }
318:
319: }
|