001: /*
002: *
003: * @ author Igor Smirnov
004: */
005:
006: package org.enhydra.logging;
007:
008: import java.io.FileInputStream;
009: import java.io.IOException;
010: import java.util.Enumeration;
011: import java.util.Iterator;
012: import java.util.Locale;
013: import java.util.Properties;
014: import java.util.ResourceBundle;
015: import java.util.Set;
016:
017: import javax.management.MBeanServerConnection;
018: import javax.management.ObjectName;
019: import javax.management.remote.JMXConnector;
020: import javax.management.remote.JMXConnectorFactory;
021: import javax.management.remote.JMXServiceURL;
022:
023: import org.apache.commons.logging.Log;
024: import org.objectweb.util.monolog.Monolog;
025: import org.objectweb.util.monolog.api.BasicLevel;
026: import org.objectweb.util.monolog.api.Logger;
027: import org.objectweb.util.monolog.api.LoggerFactory;
028: import org.objectweb.util.monolog.wrapper.common.Configurable;
029:
030: import com.lutris.util.ConfigException;
031:
032: /**
033: * <p>Implementation of {@link Log} that maps directly to a Monolog
034: * <strong>Logger</strong>. Initial configuration of the corresponding
035: * Logger instances should be done in the usual manner, as outlined in
036: * the Monolog documentation.</p>
037: *
038: *
039: * @author Igor Smirnov
040: */
041: public final class CommonLoggingMonologLogger implements Log {
042:
043: // ------------------------------------------------------------- Attributes
044:
045: /** The fully qualified name of the Monolog class. */
046: private static final String FQCN = CommonLoggingMonologLogger.class
047: .getName();
048:
049: /** Log to this logger */
050: private org.objectweb.util.monolog.api.LoggerFactory lf;
051: private Logger logger = null;
052: private static ResourceBundle rb = null;
053: public static String PROPERTY_FILE;
054: static ObjectName objectName;
055:
056: // ------------------------------------------------------------ Constructor
057:
058: public CommonLoggingMonologLogger() throws ConfigException {
059: try {
060:
061: configure();
062: this .logger = lf.getLogger("MonologFactory");
063:
064: } catch (ConfigException ex) {
065: throw new ConfigException(
066: "Cannot configure logger. Logger not initialized.");
067: }
068: this .logger = lf.getLogger("CommonLoggingMonologAdapter");
069: }
070:
071: /**
072: * Base constructor
073: */
074: public CommonLoggingMonologLogger(String name)
075: throws ConfigException {
076: try {
077: //System.out.println("****3CommonLoggingMonologLogger");
078: configure();
079: this .logger = lf.getLogger("MonologFactory");
080: } catch (ConfigException ex) {
081: throw new ConfigException(
082: "Cannot configure logger. Logger not initialized.");
083: }
084: this .logger = lf.getLogger("CommonLoggingMonologAdapter");
085: }
086:
087: /** For use with a Monolog factory
088: */
089: public CommonLoggingMonologLogger(Logger logger) {
090: this .logger = logger;
091: }
092:
093: // ---------------------------------------------------------- Implmentation
094:
095: /**
096: * Log a message to the CommonLoggingMonologLogger with <code>TRACE</code> priority.
097: * Currently logs to <code>DEBUG</code> level in CommonLoggingMonologLogger.
098: */
099: public void trace(Object message) {
100: logger.log(BasicLevel.LEVEL_DEBUG, message);
101: }
102:
103: /**
104: * Log an error to the CommonLoggingMonologLogger Logger with <code>TRACE</code> priority.
105: * Currently logs to <code>DEBUG</code> level in CommonLoggingMonologLogger.
106: */
107: public void trace(Object message, Throwable t) {
108: logger.log(BasicLevel.LEVEL_DEBUG, message, t);
109: }
110:
111: /**
112: * Log a message to the CommonLoggingMonologLogger Logger with <code>DEBUG</code> priority.
113: */
114: public void debug(Object message) {
115: logger.log(BasicLevel.LEVEL_DEBUG, message);
116: }
117:
118: /**
119: * Log an error to the CommonLoggingMonologLogger Logger with <code>DEBUG</code> priority.
120: */
121: public void debug(Object message, Throwable t) {
122: logger.log(BasicLevel.LEVEL_DEBUG, message, t);
123: }
124:
125: /**
126: * Log a message to the CommonLoggingMonologLogger Logger with <code>INFO</code> priority.
127: */
128: public void info(Object message) {
129: logger.log(BasicLevel.LEVEL_INFO, message);
130: }
131:
132: /**
133: * Log an error to the CommonLoggingMonologLogger Logger with <code>INFO</code> priority.
134: */
135: public void info(Object message, Throwable t) {
136: logger.log(BasicLevel.LEVEL_INFO, message, t);
137: }
138:
139: /**
140: * Log a message to the CommonLoggingMonologLogger Logger with <code>WARN</code> priority.
141: */
142: public void warn(Object message) {
143: logger.log(BasicLevel.LEVEL_WARN, message);
144: }
145:
146: /**
147: * Log an error to the CommonLoggingMonologLogger Logger with <code>WARN</code> priority.
148: */
149: public void warn(Object message, Throwable t) {
150: logger.log(BasicLevel.LEVEL_WARN, message, t);
151: }
152:
153: /**
154: * Log a message to the CommonLoggingMonologLogger Logger with <code>ERROR</code> priority.
155: */
156: public void error(Object message) {
157: logger.log(BasicLevel.LEVEL_ERROR, message);
158: }
159:
160: /**
161: * Log an error to the CommonLoggingMonologLogger Logger with <code>ERROR</code> priority.
162: */
163: public void error(Object message, Throwable t) {
164: logger.log(BasicLevel.LEVEL_ERROR, message, t);
165: }
166:
167: /**
168: * Log a message to the CommonLoggingMonologLogger Logger with <code>FATAL</code> priority.
169: */
170: public void fatal(Object message) {
171: logger.log(BasicLevel.LEVEL_FATAL, message);
172: }
173:
174: /**
175: * Log an error to the CommonLoggingMonologLogger Logger with <code>FATAL</code> priority.
176: */
177: public void fatal(Object message, Throwable t) {
178: logger.log(BasicLevel.LEVEL_FATAL, message, t);
179: }
180:
181: /**
182: * Return the native Logger instance we are using.
183: */
184: public Logger getLogger() {
185:
186: return (this .logger);
187: }
188:
189: /**
190: * Check whether the CommonLoggingMonologLogger Logger used is enabled for <code>DEBUG</code> priority.
191: */
192: public boolean isDebugEnabled() {
193: return logger.isLoggable(BasicLevel.LEVEL_DEBUG);
194: }
195:
196: /**
197: * Check whether the CommonLoggingMonologLogger Logger used is enabled for <code>ERROR</code> priority.
198: */
199: public boolean isErrorEnabled() {
200: return logger.isLoggable(BasicLevel.LEVEL_ERROR);
201: }
202:
203: /**
204: * Check whether the CommonLoggingMonologLogger Logger used is enabled for <code>FATAL</code> priority.
205: */
206: public boolean isFatalEnabled() {
207: return logger.isLoggable(BasicLevel.LEVEL_FATAL);
208: }
209:
210: /**
211: * Check whether the CommonLoggingMonologLogger Logger used is enabled for <code>INFO</code> priority.
212: */
213: public boolean isInfoEnabled() {
214: return logger.isLoggable(BasicLevel.LEVEL_INFO);
215: }
216:
217: /**
218: * Check whether the CommonLoggingMonologLogger Logger used is enabled for <code>TRACE</code> priority.
219: * For CommonLoggingMonologLogger, this returns the value of <code>isDebugEnabled()</code>
220: */
221: public boolean isTraceEnabled() {
222: return logger.isLoggable(BasicLevel.LEVEL_DEBUG);
223: }
224:
225: /**
226: * Check whether the CommonLoggingMonologLogger Logger used is enabled for <code>WARN</code> priority.
227: */
228: public boolean isWarnEnabled() {
229: return logger.isLoggable(BasicLevel.LEVEL_WARN);
230: }
231:
232: /**
233: * Configure the logger. All current configuration is discarded.
234: * This is a simplistic initial implementation that just allows
235: * directing to a single log file or stderr on a level basis.
236: * A more complete interface will be provided in the future.
237: *
238: * @param logFile The log file to write to.
239: * @param fileLevels List of levels that will be written to the file.
240: * @param stderrLevels List of levels that will be written to stderr.
241: * The same level may appear in both lists.
242: * @exception java.io.IOException If an error occurs opening the log file.
243: */
244: public synchronized void configure(String monologConfFile) {
245:
246: if (monologConfFile == null || monologConfFile.length() == 0) {
247: // throw new ConfigException(
248: // "impossible to configure monolog without configuration file");
249: }
250: // Load the configuration in a Properties object
251: String b = null;
252: Properties p = new Properties();
253: FileInputStream fis = null;
254: try {
255: fis = new FileInputStream(monologConfFile);
256: p.load(fis);
257: // Search the class name of the LoggerFactory which must be instanciated
258: b = p.getProperty("log.config.classname", null);
259: if (b == null) {
260: // throw new ConfigException("Malformed configuration log file:"
261: // + " log.config.classname not available");
262: }
263:
264: // Instanciate the LoggerFactory
265: lf = (LoggerFactory) Class.forName(b).newInstance();
266: // Configure with the properties
267: p.put(Configurable.LOG_CONFIGURATION_TYPE,
268: Configurable.PROPERTY);
269: p.put(Configurable.LOG_CONFIGURATION_FILE, monologConfFile);
270: // p.put(Configurable.LOG_CONFIGURATION_FILE_USE_CLASSPATH, "true");
271: ((Configurable) lf).configure(p);
272: fis.close();
273: // PropertiesConfAccess.load(p, lf, (HandlerFactory) lf, (LevelFactory) lf);
274: } catch (Exception e) {
275: try {
276: fis.close();
277: } catch (IOException e1) {
278: e1.printStackTrace();
279: }
280: // throw new ConfigException("Malformed configuration log file:"
281: // + " log.config.classname not available");
282: }
283:
284: }
285:
286: /**
287: * Default configuration of the logger. A JMX search for logger configuration file name.
288: * This file must be present in the classpath
289: */
290: public synchronized void configure() throws ConfigException {
291: String b = null;
292: String propkey;
293: String propvalue;
294: Properties props = new Properties();
295:
296: try {
297: //findMBeanServer();
298: findObjectName();
299: System.out.println("***PROSAO findObjectName");
300: if (objectName != null)
301: PROPERTY_FILE = objectName.getKeyProperty("fname");
302: // Search the classpath for the logger configuration file
303: rb = ResourceBundle.getBundle(PROPERTY_FILE, new Locale(
304: "en", "US"), ClassLoader.getSystemClassLoader());
305:
306: Enumeration enumeration = rb.getKeys();
307:
308: while (enumeration.hasMoreElements()) {
309:
310: propkey = (String) enumeration.nextElement();
311: propvalue = rb.getString(propkey);
312: props.setProperty(propkey, propvalue);
313: }
314:
315: } catch (Exception e) {
316: throw new ConfigException(
317: "Logger configuration file could not be found: logger could not be initialized!");
318: }
319:
320: try {
321:
322: // Search the class name of the LoggerFactory which must be instanciated
323: b = props.getProperty("log.config.classname", null);
324: if (b == null) {
325: throw new ConfigException(
326: "Malformed configuration log file:"
327: + " log.config.classname not available");
328: }
329:
330: // Instanciate the LoggerFactory
331:
332: props.put(Configurable.LOG_CONFIGURATION_TYPE,
333: Configurable.PROPERTY);
334: lf = Monolog.getMonologFactory(props);
335: this .logger = lf.getLogger("MonologFileLogger");
336:
337: } catch (Exception e) {
338: throw new ConfigException(
339: "Malformed configuration log file:"
340: + " log.config.classname not available");
341: }
342:
343: }
344:
345: /**
346: * finds the ObjectName which correspondes to the MBean of the jonas logger
347: */
348: private void findObjectName() throws Exception {
349: JMXConnector connector = null;
350: try {
351:
352: String serviceName = "jonas";
353: //System.out.println ("MONOLOG FILE Name of the service is 1 " + serviceName);
354:
355: // The name of the started jonas server (service name)
356: serviceName = System.getProperty("jonas.name");
357: if (serviceName == null) {
358: serviceName = "jonas";
359: }
360:
361: System.out.println("findObjectName servicename: "
362: + serviceName);
363:
364: // The address of the connector server
365: JMXServiceURL url = new JMXServiceURL(
366: "service:jmx:rmi://localhost/jndi/jrmpconnector_"
367: + serviceName);
368:
369: // Connect a JSR 160 JMXConnector to the server side
370: connector = JMXConnectorFactory.connect(url);
371:
372: // Retrieve an MBeanServerConnection that represent the MBeanServer the remote
373: // connector server is bound to
374: MBeanServerConnection connection = connector
375: .getMBeanServerConnection();
376:
377: objectName = new ObjectName(serviceName
378: + ":type=service,name=log,*");
379:
380: Set mBeans = connection.queryNames(objectName, null);
381: int l = mBeans.size();
382: if ((l) > 1) {
383: throw new Exception("MBean set size not equal 1: " + l);
384: } else if (l == 0) {
385: objectName = null;
386: if (connector != null) {
387: try {
388: connector.close();
389: } catch (Exception exept) {
390: }
391: }
392: return;
393: }
394: Iterator i = mBeans.iterator();
395: objectName = (ObjectName) i.next();
396: } catch (Exception e) {
397: throw new Exception(e);
398: } finally {
399: if (connector != null) {
400: try {
401: connector.close();
402: } catch (Exception exept) {
403: }
404: }
405: }
406: return;
407: }
408:
409: }
|