001: /**
002: * Copyright (C) 2001-2003 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.util.monolog.wrapper.log4jMini;
018:
019: import org.apache.log4j.Category;
020: import org.apache.log4j.PropertyConfigurator;
021: import org.objectweb.util.monolog.api.BasicLevel;
022: import org.objectweb.util.monolog.api.Handler;
023: import org.objectweb.util.monolog.api.HandlerFactory;
024: import org.objectweb.util.monolog.api.Level;
025: import org.objectweb.util.monolog.api.LevelFactory;
026: import org.objectweb.util.monolog.api.Logger;
027: import org.objectweb.util.monolog.api.LoggerFactory;
028: import org.objectweb.util.monolog.api.TopicalLogger;
029: import org.objectweb.util.monolog.api.MonologFactory;
030: import org.objectweb.util.monolog.wrapper.common.Configurable;
031:
032: import java.util.Hashtable;
033: import java.util.Properties;
034: import java.util.Vector;
035: import java.util.Enumeration;
036: import java.io.FileInputStream;
037: import java.io.IOException;
038: import java.io.InputStream;
039: import java.io.FileNotFoundException;
040:
041: public class MonologLoggerFactory implements MonologFactory {
042:
043: static Hashtable monologCategories;
044:
045: public static final String LOG4J_CF_PROP = "log4j.categoryFactory";
046: public static final String LOG4J_CF_VALUE = "org.objectweb.util.monolog.wrapper.log4j.MonologCategoryFactory";
047:
048: /**
049: * This static code initializes the BasicLevel fields.
050: */
051: static {
052: BasicLevel.INHERIT = -1;
053: BasicLevel.DEBUG = org.apache.log4j.Priority.DEBUG_INT;
054: BasicLevel.INFO = org.apache.log4j.Priority.INFO_INT;
055: BasicLevel.WARN = org.apache.log4j.Priority.WARN_INT;
056: BasicLevel.ERROR = org.apache.log4j.Priority.ERROR_INT;
057: BasicLevel.FATAL = org.apache.log4j.Priority.FATAL_INT;
058:
059: BasicLevel.LEVEL_INHERIT = new LevelImpl("INHERIT",
060: BasicLevel.INHERIT);
061: BasicLevel.LEVEL_DEBUG = new LevelImpl("DEBUG",
062: BasicLevel.DEBUG);
063: BasicLevel.LEVEL_INFO = new LevelImpl("INFO", BasicLevel.INFO);
064: BasicLevel.LEVEL_WARN = new LevelImpl("WARN", BasicLevel.WARN);
065: BasicLevel.LEVEL_ERROR = new LevelImpl("ERROR",
066: BasicLevel.ERROR);
067: BasicLevel.LEVEL_FATAL = new LevelImpl("FATAL",
068: BasicLevel.FATAL);
069:
070: monologCategories = new Hashtable();
071: Category root = Category.getRoot();
072: }
073:
074: /**
075: * This field references the level instances by their names.<br/>
076: * key = a level name<br/>
077: * value = the unique Level instance linked to the name.
078: */
079: protected Hashtable nameToLevel = null;
080:
081: /**
082: * This field reference the level names by their integer value.<br/>
083: * key = a java.lang.Integer which the value is the level<br/>
084: * value = a String or an ArrayList of String. The strings represent the
085: * name which match to the integer value. Indeed both name can be associated
086: * to the same integer value.
087: */
088: protected Hashtable intToNames = null;
089:
090: /**
091: * This field references the handler instance by their names.<br/>
092: * key = a String object which is an handler name.
093: * value = the unique handler instance which has the key for name.
094: */
095: protected Hashtable handlers = null;
096:
097: /**
098: * The root logger of the logger hierarchy
099: */
100: protected Logger rootLogger = null;
101:
102: public MonologLoggerFactory() {
103: intToNames = new Hashtable();
104: nameToLevel = new Hashtable();
105: defineDefaultLevels();
106: handlers = new Hashtable();
107: rootLogger = new MonologCategory(Category.getRoot());
108: }
109:
110: /**
111: * It initializes the default monolog level:
112: * <ul>
113: * <li>DEBUG: 10 000</li>
114: * <li>INFO: 20 000</li>
115: * <li>WARN: 30 000</li>
116: * <li>ERROR: 40 000</li>
117: * <li>FATAL: 50 000</li>
118: * </ul>
119: */
120: protected void defineDefaultLevels() {
121: defineLevel("INHERIT", -1);
122: defineLevel("DEBUG", 10000);
123: defineLevel("INFO", 20000);
124: defineLevel("WARN", 30000);
125: defineLevel("ERROR", 40000);
126: defineLevel("FATAL", 50000);
127: }
128:
129: // IMPLEMENTATION OF THE Configurable INTERFACE //
130:
131: /**
132: * This method permits to configure the factory.
133: */
134: public void configure(Properties prop) throws Exception {
135: if (prop == null) {
136: return;
137: }
138: String conf = prop.getProperty(LOG_CONFIGURATION_TYPE, prop
139: .getProperty("log4jConfiguration", DEFAULT));
140: if (PROPERTY.equals(conf)) {
141:
142: // Fetch the configuration file name
143: String filename = prop.getProperty(LOG_CONFIGURATION_FILE,
144: prop.getProperty("log4jConfigurationFile", ""));
145: Properties log4jfileprop = null;
146: // Check if the file name designs a path valid into the
147: // classpath, or designs a path valid into the file system.
148: // In both case load the property file
149: if (prop.getProperty(LOG_CONFIGURATION_FILE_USE_CLASSPATH,
150: "false").equalsIgnoreCase("true")
151: || prop.getProperty("findFileInClassPath", "false")
152: .equalsIgnoreCase("true")) {
153:
154: if (!"log4j.properties".equals(filename)) {
155: // valid into the classpath
156: log4jfileprop = getProperties(filename);
157: log4jfileprop.put(LOG4J_CF_PROP, LOG4J_CF_VALUE);
158: PropertyConfigurator.configure(log4jfileprop);
159: }
160: // else the file is already loaded by the Category class
161: } else {
162: // valid into the file system
163: log4jfileprop = new Properties();
164: log4jfileprop.load(new FileInputStream(filename));
165: log4jfileprop.put(LOG4J_CF_PROP, LOG4J_CF_VALUE);
166: PropertyConfigurator.configure(log4jfileprop);
167: }
168: } else if (XML.equals(conf)) {
169: throw new Exception(
170: "xml log4jConfiguration is not suported in the log4jME wrapper");
171: }
172: }
173:
174: // Return null if properties are not reachable
175: private Properties getProperties(String name) throws IOException {
176: InputStream is = ClassLoader.getSystemResourceAsStream(name);
177: if (is != null) {
178: Properties props = new Properties();
179: props.load(is);
180: return props;
181: }
182: throw new FileNotFoundException("Not found in classpath: "
183: + name);
184: }
185:
186: // IMPLEMENTATION OF INTERFACE LoggerFactory
187: public Logger[] getLoggers() {
188: Logger[] logs = new TopicalLogger[monologCategories.size() + 1];
189: logs[0] = rootLogger;
190: int i = 1;
191: for (Enumeration en = monologCategories.elements(); en
192: .hasMoreElements();) {
193: logs[i++] = (TopicalLogger) en.nextElement();
194: }
195: return logs;
196: }
197:
198: public String getTopicPrefix() {
199: return null;
200: }
201:
202: public Logger getLogger(String key) {
203: if (key == null || key.length() == 0
204: || key.equalsIgnoreCase("root")) {
205: return rootLogger;
206: }
207: Logger log = (Logger) monologCategories.get(key);
208: if (log == null) {
209: log = new MonologCategory(Category.getInstance(key));
210: monologCategories.put(key, log);
211: }
212: return log;
213: }
214:
215: public synchronized Logger getLogger(String key, String rbn) {
216: return getLogger(key);
217: }
218:
219: public String getResourceBundleName() {
220: return "";
221: }
222:
223: public void setResourceBundleName(String rbn) {
224: }
225:
226: // IMPLEMENTATION OF THE LevelFactory INTERFACE //
227: //-----------------------------------------------//
228:
229: public Level defineLevel(String name, int value) {
230: return defineLevel(new LevelImpl(name, value));
231: }
232:
233: public Level defineLevel(String name, String value) {
234: return defineLevel(new LevelImpl(name, value, this ));
235: }
236:
237: public Level getLevel(String name) {
238: return (Level) nameToLevel.get(name);
239: }
240:
241: public Level getLevel(int value) {
242: Object temp = intToNames.get(new Integer(value));
243: if (temp == null) {
244: return null;
245: } else if (temp instanceof String) {
246: return getLevel((String) temp);
247: } else if (temp instanceof Vector) {
248: return getLevel((String) ((Vector) temp).elementAt(0));
249: }
250: return null;
251: }
252:
253: public Level[] getLevels() {
254: if (nameToLevel == null) {
255: return new Level[0];
256: }
257: Level[] result = new Level[nameToLevel.size()];
258: int i = 0;
259: for (Enumeration e = nameToLevel.elements(); e
260: .hasMoreElements(); i++) {
261: result[i] = (Level) (e.nextElement());
262: }
263: return result;
264: }
265:
266: public void removeLevel(String name) {
267: Level removed = (Level) nameToLevel.remove(name);
268: if (removed != null) {
269: Integer i = new Integer(removed.getIntValue());
270: Object temp = intToNames.get(i);
271: if (temp instanceof String) {
272: intToNames.remove(i);
273: } else if (temp instanceof Vector) {
274: ((Vector) temp).removeElement(name);
275: }
276: }
277: }
278:
279: // OTHER METHODS //
280: //---------------//
281:
282: /**
283: * Insert a level into the data structure.<br/>
284: * If the level name is already used with other integer value, the null
285: * value is returned.<br/>
286: * If the level name is already used with the same integer value, the level
287: * found in the data structure is returned.<br/>
288: *
289: * @param l the Level instance which must be inserted.
290: * @return the Level instance or a null value.
291: */
292: private Level defineLevel(Level l) {
293: //System.out.println("def(" + l + ") begin");
294: String name = l.getName();
295: int value = l.getIntValue();
296: Level res = (Level) nameToLevel.get(name);
297: if (res != null) {
298: // The name is already defined.
299: return (res.getIntValue() == value ? res : null);
300: } else {
301: res = l;
302: nameToLevel.put(name, res);
303: Integer i = new Integer(value);
304: Object temp = intToNames.get(i);
305: if (temp != null) {
306: if (temp instanceof String) {
307: if (!((String) temp).equalsIgnoreCase(name)) {
308: // The int value has already another name
309: // Add the new name to the other
310: Vector al = new Vector(5);
311: al.addElement(temp);
312: al.addElement(name);
313: intToNames.put(i, al);
314: }
315: } else if (temp instanceof Vector) {
316: // The int value has already several another name
317: Vector al = (Vector) temp;
318: if (!al.contains(name)) {
319: // Add the new name to the others
320: al.addElement(name);
321: }
322: }
323: } else {
324: // The int value does not have any name
325: intToNames.put(i, name);
326: }
327: }
328: //System.out.println("def(" + l + ") end");
329: return res;
330: }
331:
332: // IMPLEMENTATION OF THE HandlerFactory INTERFACE //
333: //------------------------------------------------//
334:
335: public Handler createHandler(String hn, String handlertype) {
336: Handler res = (Handler) handlers.get(hn);
337: if (res != null) {
338: return null;
339: }
340: res = new FileHandler(handlertype, hn);
341: handlers.put(hn, res);
342: return res;
343: }
344:
345: public Handler[] getHandlers() {
346: if (handlers == null) {
347: return new Handler[0];
348: }
349: Handler[] result = new Handler[handlers.size()];
350: int i = 0;
351: for (Enumeration e = handlers.elements(); e.hasMoreElements(); i++) {
352: result[i] = (Handler) (e.nextElement());
353: }
354: return result;
355: }
356:
357: public Handler getHandler(String hn) {
358: return (Handler) handlers.get(hn);
359: }
360:
361: public Handler removeHandler(String hn) {
362: return (Handler) handlers.remove(hn);
363: }
364: }
|