KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lutris > logging > MonologLogger


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: MonologLogger.java,v 1.13 2005/03/24 12:19:58 slobodan Exp $
22  */

23 package com.lutris.logging;
24
25 import java.io.File JavaDoc;
26 import java.io.FileInputStream JavaDoc;
27 import java.util.Enumeration JavaDoc;
28 import java.util.Hashtable JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.Locale JavaDoc;
31 import java.util.Properties JavaDoc;
32 import java.util.ResourceBundle JavaDoc;
33 import java.util.Set JavaDoc;
34
35 import javax.management.MBeanServerConnection JavaDoc;
36 import javax.management.ObjectName JavaDoc;
37 import javax.management.remote.JMXConnector JavaDoc;
38 import javax.management.remote.JMXConnectorFactory JavaDoc;
39 import javax.management.remote.JMXServiceURL JavaDoc;
40
41 import org.objectweb.util.monolog.Monolog;
42 import org.objectweb.util.monolog.api.LoggerFactory;
43 import org.objectweb.util.monolog.wrapper.common.Configurable;
44
45 import com.lutris.util.Config;
46 import com.lutris.util.ConfigException;
47 /**
48  * Monolog implementation of the <CODE>Logger</CODE>. This is
49  * general-purpose logging facility. A client that needs additional
50  * functionality can either extend this class or provide there own
51  * implementationm of <CODE>Logger</CODE>. <P>
52  *
53  * Currently this is a bare-bones class that writes INFO and above
54  * levels to stderr and all others to a log file.
55  *
56  * @author Sinisa Milosevic
57  * @see com.lutris.logging.Logger
58  * @see com.lutris.logging.LogChannel
59  */

60 public class MonologLogger extends com.lutris.logging.Logger {
61     
62   /**
63    * object name of the MBean which represents the Tomcat's session manager
64    */

65   static ObjectName JavaDoc objectName;
66    
67     /**
68      * Table of level names to level numbers. While level configuration
69      * is local to a facility, a global table is kept assigning numbers
70      * to each level name.
71      */

72     private Hashtable JavaDoc levelNumbers = new Hashtable JavaDoc();
73
74     /**
75      * Table translating level number to name and the largest entry in the
76      * array that is valid. Will be expanded if needed.
77      */

78     protected String JavaDoc[] levelNames = new String JavaDoc[MAX_STD_LEVEL * 2];
79     protected int numLevels = 0;
80
81     /**
82      * Table of levels that are to be enabled.
83      * Accessed directly by the channel. If null, ignored.
84      */

85     protected boolean[] enabledLevelFlags = null;
86
87     /**
88      * Table of levels that are to be written to the log file.
89      * Accessed directly by the channel. If null, ignored.
90      */

91     protected boolean[] logFileLevelFlags = null;
92
93     /**
94      * Table of levels that are to be written to stderr
95      * Accessed directly by the channel. If null, then
96      * the default behavior of writing serious standard
97      * levels to stderr is in affect.
98      */

99     protected boolean[] stderrLevelFlags = null;
100     
101     /**
102      * Default Monolog configuration file
103      */

104         protected String JavaDoc DEFAULT_LOG_CONFIG_FILE = "trace.properties";
105
106     /**
107      * Log file name.
108      */

109     File JavaDoc activeLogFile;
110
111     /**
112      * .
113      */

114     LoggerFactory lf;
115     
116     private static ResourceBundle JavaDoc rb = null;
117     public static String JavaDoc PROPERTY_FILE;
118
119
120     /**
121      * Table of <CODE>StandardLogChannel<CODE> objects, indexed by facility
122      * name.
123      */

124     private Hashtable JavaDoc logChannels = new Hashtable JavaDoc();
125
126     String JavaDoc defaultSeparatorLine ="";
127     Hashtable JavaDoc appSeparatorLine = new Hashtable JavaDoc();
128    
129     /**
130      * Construct a new logger. Configuration is not done now, to allow
131      * the logger to be created very early.
132      *
133      * @param makeCentral Make this object the central logging object.
134      */

135     public MonologLogger(boolean makeCentral) {
136         int level;
137
138         for (level = 0; level <= MAX_STD_LEVEL; level++) {
139             String JavaDoc name = standardLevelNames[level];
140
141             levelNumbers.put(name, new Integer JavaDoc(level));
142             levelNames[level] = name;
143         }
144         numLevels = level;
145         if (makeCentral) {
146             centralLogger = this;
147         }
148
149     }
150
151     /**
152      * Get maximum level number in a set of level names.
153      *
154      * @param levels String names of levels.
155      * @return The maximum level number
156      */

157     private int getMaxLevel(String JavaDoc[] levels) {
158         int levelNum;
159         int maxLevelNum = 0;
160
161         for (int idx = 0; idx < levels.length; idx++) {
162             levelNum = getLevel(levels[idx]);
163             if (levelNum > maxLevelNum) {
164                 maxLevelNum = levelNum;
165             }
166         }
167         return maxLevelNum;
168     }
169
170
171
172     /**
173      * Configure the logger. All current configuration is discarded.
174      * This is a simplistic initial implementation that just allows
175      * directing to a single log file or stderr on a level basis.
176      * A more complete interface will be provided in the future.
177      *
178      * @param logFile The log file to write to.
179      * @param fileLevels List of levels that will be written to the file.
180      * @param stderrLevels List of levels that will be written to stderr.
181      * The same level may appear in both lists.
182      * @exception java.io.IOException If an error occurs opening the log file.
183      */

184      
185     public synchronized void configure(String JavaDoc monologConfFile)
186         throws ConfigException {
187       
188         if (monologConfFile==null || monologConfFile.length() == 0) {
189             throw new ConfigException(
190                 "impossible to configure monolog without configuration file");
191         }
192         // Load the configuration in a Properties object
193
String JavaDoc b = null;
194       Properties JavaDoc p = new Properties JavaDoc();
195         try {
196   
197            p.load(new FileInputStream JavaDoc(monologConfFile));
198         // Search the class name of the LoggerFactory which must be instanciated
199
b = p.getProperty("log.config.classname", null);
200          
201            if (b == null) {
202                throw new ConfigException("Malformed configuration log file:"
203                    + " log.config.classname not available");
204            }
205   
206            // Instanciate the LoggerFactory
207
lf = (LoggerFactory) Class.forName(b).newInstance();
208            // Configure with the properties
209
p.put(Configurable.LOG_CONFIGURATION_TYPE, Configurable.PROPERTY);
210          p.put(Configurable.LOG_CONFIGURATION_FILE, monologConfFile);
211   // p.put(Configurable.LOG_CONFIGURATION_FILE_USE_CLASSPATH, "true");
212

213          ((Configurable) lf).configure(p);
214
215   
216   // PropertiesConfAccess.load(p, lf, (HandlerFactory) lf, (LevelFactory) lf);
217
}
218         catch (Exception JavaDoc e) {
219            throw new ConfigException("Malformed configuration log file:"
220                    + " log.config.classname not available");
221        }
222   }
223   
224     public synchronized void configure()
225         throws ConfigException {
226           String JavaDoc b = null;
227           String JavaDoc propkey;
228           String JavaDoc propvalue;
229           Properties JavaDoc props = new Properties JavaDoc();
230        
231    // Search the classpath for the logger configuration file
232

233              
234      try{
235          findObjectName();
236          if (objectName != null)
237             PROPERTY_FILE = objectName.getKeyProperty("fname");
238           rb = ResourceBundle.getBundle(PROPERTY_FILE,new Locale JavaDoc("en","US"), ClassLoader.getSystemClassLoader());
239       
240      Enumeration JavaDoc enumeration = rb.getKeys();
241  
242      
243      while (enumeration.hasMoreElements())
244      {
245
246          propkey = (String JavaDoc) enumeration.nextElement();
247          propvalue = rb.getString(propkey);
248          props.setProperty(propkey, propvalue);
249      }
250       
251       
252       } catch (Exception JavaDoc e){
253         throw new ConfigException("Logger configuration file could not be found: logger could not be initialized!");
254     }
255
256         try {
257
258         // Search the class name of the LoggerFactory which must be instanciated
259
b = props.getProperty("log.config.classname", null);
260            if (b == null) {
261                throw new ConfigException("Malformed configuration log file:"
262                    + " log.config.classname not available");
263            }
264
265            // Instanciate the LoggerFactory
266

267          props.put(Configurable.LOG_CONFIGURATION_TYPE, Configurable.PROPERTY);
268          lf = Monolog.getMonologFactory(b);
269
270     // PropertiesConfAccess.load(p, lf, (HandlerFactory) lf, (LevelFactory) lf);
271
}
272         catch (Exception JavaDoc e) {
273            throw new ConfigException("Malformed configuration log file:"
274                    + " log.config.classname not available");
275        }
276
277   }
278
279
280     /**
281      * Create a log channel.
282      */

283     private synchronized MonologLogChannel createChannel(String JavaDoc facility) {
284        
285         String JavaDoc sepLine= (String JavaDoc)appSeparatorLine.get(facility);
286         if(sepLine==null)
287           sepLine=defaultSeparatorLine;
288      
289         MonologLogChannel channel
290                 = (MonologLogChannel) logChannels.get(facility);
291
292         if (channel == null) {
293             channel = new MonologLogChannel(facility,
294                     lf.getLogger(facility),sepLine);
295             logChannels.put(facility, channel);
296         }
297         return channel;
298     }
299
300     /**
301      * Get the log channel object for a facility. For a given facility,
302      * the same object is always returned.
303      *
304      * @param facility Facility the channel is associated with.
305      */

306     public LogChannel getChannel(String JavaDoc facility) {
307         MonologLogChannel channel
308                 = (MonologLogChannel) logChannels.get(facility);
309
310         if (channel == null) {
311             // Slow path, synchronized
312
channel = createChannel(facility);
313         }
314         return channel;
315     }
316
317     /**
318      * Create a log level.
319      */

320     private synchronized Integer JavaDoc createLevel(String JavaDoc level) {
321         Integer JavaDoc intLevel = (Integer JavaDoc) levelNumbers.get(level);
322
323         if (intLevel == null) {
324             intLevel = new Integer JavaDoc(numLevels);
325             levelNames[numLevels] = level;
326             levelNumbers.put(level, intLevel);
327             numLevels++;
328         }
329         return intLevel;
330     }
331
332     /**
333      * Convert a symbolic level to an integer identifier,
334      * creating it if it doesn't exist
335      *
336      * @param level Symbolic level that is to be checked.
337      * @return The numeric level identifier
338      */

339     public synchronized int getLevel(String JavaDoc level) {
340         Integer JavaDoc intLevel = (Integer JavaDoc) levelNumbers.get(level);
341
342         if (intLevel == null) {
343             // Slow path, synchronized
344
intLevel = createLevel(level);
345         }
346         return intLevel.intValue();
347     }
348
349     /**
350      * Convert an int to a symbolic level name.
351      *
352      * @param level an int level.
353      * @return The String symolic level name or null if there is not one.
354      */

355     public String JavaDoc getLevelName(int level) {
356         if ((level >= 0) && (level < numLevels)) {
357             return levelNames[level];
358         } else {
359             return null;
360         }
361     }
362
363     /**
364      * Configure Logger with given config section
365      *
366      * @param logConfig containing parameters for configuring logger
367      */

368     public void configure(Config logConfig) throws ConfigException {
369         String JavaDoc fileName = null;
370                 File JavaDoc logConfigFile = null;
371         if (logConfig.containsKey("Monolog")) {
372             fileName = logConfig.getString("Monolog");
373             logConfigFile = new File JavaDoc(fileName);
374             if (!logConfigFile.exists()){
375                 fileName = logConfig.getConfigFile().getFile().getParent()+File.separator+fileName;
376                 logConfigFile = new File JavaDoc(fileName);
377                 if (!logConfigFile.exists()){
378                             fileName = logConfig.getConfigFile().getFile().getParent();
379                         if (null != fileName) {
380                             fileName += File.separator + DEFAULT_LOG_CONFIG_FILE;
381                         }
382                     }
383             }
384             try{
385               configure(fileName);
386              } catch (Exception JavaDoc ex) {
387                 try {
388                   configure();
389                 }catch (ConfigException cex) {
390                   throw new ConfigException("Cannot configure logger. Config file is null.");
391                 }
392              }
393
394         } else {
395             try {
396               configure();
397             }catch (ConfigException ex) {
398               throw new ConfigException("Cannot configure logger. Logger not initialized.");
399             }
400         }
401           if (logConfig.containsKey("SeparatorLine")) {
402                   String JavaDoc app=logConfig.getString("Server.AppClass");
403                   String JavaDoc separator = logConfig.getString("SeparatorLine");
404                   int index =app.lastIndexOf(".");
405                   String JavaDoc temp=app.substring(index);
406                   appSeparatorLine.put(temp.substring(1) ,separator);
407           }
408          
409      }
410   
411   
412   /**
413    * finds the ObjectName which correspondes to the MBean of the jonas logger
414    */

415   private void findObjectName () throws Exception JavaDoc {
416     JMXConnector JavaDoc connector = null;
417     try {
418       
419       String JavaDoc serviceName = "jonas";
420       
421       // The name of the started jonas server (service name)
422
serviceName = System.getProperty("jonas.name");
423       if ( serviceName == null) {
424         serviceName = "jonas";
425       }
426       
427       // The address of the connector server
428
JMXServiceURL JavaDoc url = new JMXServiceURL JavaDoc("service:jmx:rmi://localhost/jndi/jrmpconnector_" + serviceName);
429
430       // Connect a JSR 160 JMXConnector to the server side
431
connector = JMXConnectorFactory.connect(url);
432
433       // Retrieve an MBeanServerConnection that represent the MBeanServer the remote
434
// connector server is bound to
435
MBeanServerConnection JavaDoc connection = connector.getMBeanServerConnection();
436
437         objectName = new ObjectName JavaDoc(serviceName + ":type=service,name=log,*");
438         
439       Set JavaDoc mBeans = connection.queryNames(objectName, null);
440       int l = mBeans.size();
441       if ((l) > 1) {
442         throw new Exception JavaDoc("MBean set size not equal 1: " + l);
443       }else if (l == 0){
444         objectName = null;
445         if (connector!=null){
446             try {
447                 connector.close();
448             } catch (Exception JavaDoc exept){}
449         }
450         return;
451         }
452       Iterator JavaDoc i = mBeans.iterator();
453       objectName = (ObjectName JavaDoc)i.next();
454     } catch (Exception JavaDoc e) {
455       throw new Exception JavaDoc(e);
456     } finally {
457         if (connector!=null){
458             try {
459                 connector.close();
460             } catch (Exception JavaDoc exept){}
461         }
462     }
463     return;
464   }
465     
466 }
467
468
469
470
Popular Tags