[jboss-svn-commits] JBoss Common SVN: r3234 - in jboss-logmanager/trunk: src/main/java/org/jboss/logmanager and 2 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Tue Jun 9 17:47:07 EDT 2009


Author: david.lloyd at jboss.com
Date: 2009-06-09 17:47:07 -0400 (Tue, 09 Jun 2009)
New Revision: 3234

Added:
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ClassPathConfigurationLocator.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ConfigurationLocator.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Configurator.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/PropertyConfigurator.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/PatternFormatter.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/FileHandler.java
Modified:
   jboss-logmanager/trunk/pom.xml
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogContext.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogManager.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Logger.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/Formatters.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/MultistepFormatter.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ConsoleHandler.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/OutputStreamHandler.java
Log:
Add a simple property-based bootstrap configurator

Modified: jboss-logmanager/trunk/pom.xml
===================================================================
--- jboss-logmanager/trunk/pom.xml	2009-06-09 16:01:12 UTC (rev 3233)
+++ jboss-logmanager/trunk/pom.xml	2009-06-09 21:47:07 UTC (rev 3234)
@@ -66,6 +66,12 @@
                 </exclusion>
             </exclusions>
         </dependency>
+        <dependency>
+            <groupId>org.jboss</groupId>
+            <artifactId>jboss-common-core</artifactId>
+            <version>2.2.14.GA</version>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
     <build>
         <plugins>

Added: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ClassPathConfigurationLocator.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ClassPathConfigurationLocator.java	                        (rev 0)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ClassPathConfigurationLocator.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -0,0 +1,42 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logmanager;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * A configuration locator which looks for a {@code logging.properties} file in the class path.
+ */
+public final class ClassPathConfigurationLocator implements ConfigurationLocator {
+
+    /** {@inheritDoc} */
+    public InputStream findConfiguration() throws IOException {
+        final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+        if (tccl != null) try {
+            return tccl.getResourceAsStream("logging.properties");
+        } catch (Exception e) {
+        }
+        return getClass().getResourceAsStream("logging.properties");
+    }
+}

Added: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ConfigurationLocator.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ConfigurationLocator.java	                        (rev 0)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ConfigurationLocator.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -0,0 +1,39 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logmanager;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * A locator for logger configuration.
+ */
+public interface ConfigurationLocator {
+
+    /**
+     * Find the configuration file.
+     *
+     * @return the configuration file input stream
+     */
+    InputStream findConfiguration() throws IOException;
+}

Added: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Configurator.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Configurator.java	                        (rev 0)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Configurator.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logmanager;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A configurator for a log manager or context.
+ */
+public interface Configurator {
+
+    /**
+     * Configure the logmanager.
+     *
+     * @param inputStream the input stream to read
+     * @throws IOException if an error occurs
+     */
+    void configure(InputStream inputStream) throws IOException;
+}

Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogContext.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogContext.java	2009-06-09 16:01:12 UTC (rev 3233)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogContext.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -49,35 +49,44 @@
     @SuppressWarnings({ "ThisEscapedInObjectConstruction" })
     private final LoggingMXBean mxBean = new LoggingMXBeanImpl(this);
 
-    private static final HashMap<String, LevelRef> INITIAL_LEVEL_MAP;
+    /**
+     * This lazy holder class is required to prevent a problem due to a LogContext instance being constructed
+     * before the class init is complete.
+     */
+    private static final class LazyHolder {
+        private static final HashMap<String, LevelRef> INITIAL_LEVEL_MAP;
 
-    private static void addStrong(Map<String, LevelRef> map, Level level) {
-        map.put(level.getName().toUpperCase(), new StrongLevelRef(level));
-    }
+        private LazyHolder() {
+        }
 
-    static {
-        final HashMap<String, LevelRef> map = new HashMap<String, LevelRef>();
-        addStrong(map, Level.OFF);
-        addStrong(map, Level.ALL);
-        addStrong(map, Level.SEVERE);
-        addStrong(map, Level.WARNING);
-        addStrong(map, Level.CONFIG);
-        addStrong(map, Level.INFO);
-        addStrong(map, Level.FINE);
-        addStrong(map, Level.FINER);
-        addStrong(map, Level.FINEST);
+        private static void addStrong(Map<String, LevelRef> map, Level level) {
+            map.put(level.getName().toUpperCase(), new StrongLevelRef(level));
+        }
 
-        addStrong(map, org.jboss.logmanager.Level.FATAL);
-        addStrong(map, org.jboss.logmanager.Level.ERROR);
-        addStrong(map, org.jboss.logmanager.Level.WARN);
-        addStrong(map, org.jboss.logmanager.Level.INFO);
-        addStrong(map, org.jboss.logmanager.Level.DEBUG);
-        addStrong(map, org.jboss.logmanager.Level.TRACE);
+        static {
+            final HashMap<String, LevelRef> map = new HashMap<String, LevelRef>();
+            addStrong(map, Level.OFF);
+            addStrong(map, Level.ALL);
+            addStrong(map, Level.SEVERE);
+            addStrong(map, Level.WARNING);
+            addStrong(map, Level.CONFIG);
+            addStrong(map, Level.INFO);
+            addStrong(map, Level.FINE);
+            addStrong(map, Level.FINER);
+            addStrong(map, Level.FINEST);
 
-        INITIAL_LEVEL_MAP = map;
+            addStrong(map, org.jboss.logmanager.Level.FATAL);
+            addStrong(map, org.jboss.logmanager.Level.ERROR);
+            addStrong(map, org.jboss.logmanager.Level.WARN);
+            addStrong(map, org.jboss.logmanager.Level.INFO);
+            addStrong(map, org.jboss.logmanager.Level.DEBUG);
+            addStrong(map, org.jboss.logmanager.Level.TRACE);
+
+            INITIAL_LEVEL_MAP = map;
+        }
     }
 
-    private final AtomicReference<Map<String, LevelRef>> levelMapReference = new AtomicReference<Map<String, LevelRef>>(INITIAL_LEVEL_MAP);
+    private final AtomicReference<Map<String, LevelRef>> levelMapReference;
 
     /**
      * This lock is taken any time a change is made which affects multiple nodes in the hierarchy.
@@ -85,6 +94,7 @@
     final Lock treeLock = new ReentrantLock(false);
 
     LogContext() {
+        levelMapReference = new AtomicReference<Map<String, LevelRef>>(LazyHolder.INITIAL_LEVEL_MAP);
     }
 
     /**
@@ -141,11 +151,14 @@
      * @throws IllegalArgumentException if the name is not known
      */
     public Level getLevelForName(String name) throws IllegalArgumentException {
-        final LogContext.LevelRef levelRef = levelMapReference.get().get(name);
-        if (levelRef != null) {
-            final Level level = levelRef.get();
-            if (level != null) {
-                return level;
+        if (name != null) {
+            final Map<String, LevelRef> map = levelMapReference.get();
+            final LogContext.LevelRef levelRef = map.get(name);
+            if (levelRef != null) {
+                final Level level = levelRef.get();
+                if (level != null) {
+                    return level;
+                }
             }
         }
         throw new IllegalArgumentException("Unknown level \"" + name + "\"");

Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogManager.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogManager.java	2009-06-09 16:01:12 UTC (rev 3233)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogManager.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -24,6 +24,7 @@
 
 import java.beans.PropertyChangeListener;
 import java.io.InputStream;
+import java.io.IOException;
 import java.lang.reflect.Field;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -33,6 +34,7 @@
 import java.util.Iterator;
 import java.util.ListIterator;
 import java.util.NoSuchElementException;
+import java.net.URL;
 
 /**
  * Simplified log manager.  Designed to work around the (many) design flaws of the JDK platform log manager.
@@ -194,21 +196,52 @@
     // Configuration
 
     /**
-     * Do nothing.  Does not support non-programmatic configuraiton.
+     * Configure the log manager.  An implementation of {@link ConfigurationLocator} is created by constructing an
+     * instance of the class name specified in the {@code org.jboss.logmanager.configurationLocator} system property.
      */
-    public void readConfiguration() {
+    public void readConfiguration() throws IOException, SecurityException {
+        checkAccess();
+        final String confLocClassName = System.getProperty("org.jboss.logmanager.configurationLocator", "org.jboss.logmanager.ClassPathConfigurationLocator");
+        final ConfigurationLocator locator = construct(ConfigurationLocator.class, confLocClassName);
+        final InputStream configuration = locator.findConfiguration();
+        if (configuration != null) {
+            readConfiguration(configuration);
+        }
         return;
     }
 
     /**
-     * Do nothing.  Does not support non-programmatic configuraiton.
+     * Configure the log manager.
      *
-     * @param ins ignored
+     * @param inputStream the input stream from which the logmanager should be configured
      */
-    public void readConfiguration(InputStream ins) {
+    public void readConfiguration(InputStream inputStream) throws IOException, SecurityException {
+        checkAccess();
+        final String confClassName = System.getProperty("org.jboss.logmanager.configurator", "org.jboss.logmanager.PropertyConfigurator");
+        final Configurator configurator = construct(Configurator.class, confClassName);
+        configurator.configure(inputStream);
         return;
     }
 
+    static <T> T construct(Class<? extends T> type, String className) throws IOException {
+        try {
+            Class<?> clazz = null;
+            try {
+                final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+                if (tccl != null) {
+                    clazz = Class.forName(className, true, tccl);
+                }
+            } catch (ClassNotFoundException e) {
+            }
+            if (clazz == null) clazz = Class.forName(className, true, LogManager.class.getClassLoader());
+            return type.cast(clazz.getConstructor().newInstance());
+        } catch (Exception e) {
+            final IOException ioe = new IOException("Unable to load configuration class " + className);
+            ioe.initCause(e);
+            throw ioe;
+        }
+    }
+
     /**
      * Do nothing.  Properties and their listeners are not supported.
      *

Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Logger.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Logger.java	2009-06-09 16:01:12 UTC (rev 3233)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Logger.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -77,7 +77,8 @@
      * @return the logger
      */
     public static Logger getLogger(final String name) {
-        return LogContext.getLogContext().getLogger(name);
+        // call through j.u.l.Logger so that primordial configuration is set up
+        return (Logger) java.util.logging.Logger.getLogger(name);
     }
 
     /**

Added: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/PropertyConfigurator.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/PropertyConfigurator.java	                        (rev 0)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/PropertyConfigurator.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -0,0 +1,360 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logmanager;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Closeable;
+import java.util.Properties;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import org.jboss.util.StringPropertyReplacer;
+
+import java.util.logging.Filter;
+import java.util.logging.Handler;
+import java.util.logging.Formatter;
+import java.util.logging.ErrorManager;
+
+/**
+ * A configurator which uses a simple property file format.  Use of this class adds a requirement on the JBoss
+ * Common Core project.
+ */
+public final class PropertyConfigurator implements Configurator {
+
+    /**
+     * Construct an instance.
+     */
+    public PropertyConfigurator() {
+    }
+
+    private Map<String, Handler> configuredHandlers;
+    private Map<String, Filter> configuredFilters;
+    private Map<String, Formatter> configuredFormatters;
+    private Map<String, ErrorManager> configuredErrorManagers;
+
+    /** {@inheritDoc} */
+    public void configure(final InputStream inputStream) throws IOException {
+        configuredHandlers = new HashMap<String, Handler>();
+        configuredFilters = new HashMap<String, Filter>();
+        configuredFormatters = new HashMap<String, Formatter>();
+        configuredErrorManagers = new HashMap<String, ErrorManager>();
+        final Properties properties = new Properties();
+        try {
+            properties.load(inputStream);
+            inputStream.close();
+        } finally {
+            safeClose(inputStream);
+        }
+        configure(properties);
+    }
+
+    private void configure(final Properties properties) throws IOException {
+        // Start with the list of loggers to configure.  The root logger is always on the list.
+        final List<String> loggerNames = getStringCsvList(properties, "loggers", "");
+
+        // Now, for each logger name, configure any filters, handlers, etc.
+        for (String loggerName : loggerNames) {
+            final Logger logger = LogContext.getSystemLogContext().getLogger(loggerName);
+
+            // Get logger level
+            final String levelName = getStringProperty(properties, getKey("logger", loggerName, "level"));
+            if (levelName != null) {
+                logger.setLevel(LogContext.getSystemLogContext().getLevelForName(levelName));
+            }
+
+            // Get logger filter
+            final String filterName = getStringProperty(properties, getKey("logger", loggerName, "filter"));
+            if (filterName != null) {
+                logger.setFilter(configureFilter(properties, filterName));
+            }
+
+            // Get logger handlers
+            final List<String> handlerNames = getStringCsvList(properties, getKey("logger", loggerName, "handlers"));
+            for (String handlerName : handlerNames) {
+                logger.addHandler(configureHandler(properties, handlerName));
+            }
+
+            // Get logger properties
+            final String useParentHandlersString = getStringProperty(properties, getKey("logger", loggerName, "useParentHandlers"));
+            if (useParentHandlersString != null) {
+                logger.setUseParentHandlers(Boolean.parseBoolean(useParentHandlersString));
+            }
+        }
+    }
+
+    private void configureProperties(final Properties properties, final Object object, final String prefix) throws IOException {
+        final List<String> propertyNames = getStringCsvList(properties, getKey(prefix, "properties"));
+        final Class<? extends Object> objClass = object.getClass();
+        final Iterator<String> it = propertyNames.iterator();
+        if (! it.hasNext()) {
+            return;
+        } else {
+            final Map<String, Method> setters = new HashMap<String, Method>();
+            for (Method method : objClass.getMethods()) {
+                final int modifiers = method.getModifiers();
+                if (Modifier.isStatic(modifiers) || ! Modifier.isPublic(modifiers)) {
+                    continue;
+                }
+                final String name = method.getName();
+                if (! name.startsWith("set")) {
+                    continue;
+                }
+                final Class<?>[] parameterTypes = method.getParameterTypes();
+                if (parameterTypes.length != 1) {
+                    continue;
+                }
+                if (method.getReturnType() != void.class) {
+                    continue;
+                }
+                setters.put(name.substring(3, 4).toLowerCase() + name.substring(4), method);
+            }
+            do {
+                String propertyName = it.next();
+                final String propValue = getStringProperty(properties, getKey(prefix, propertyName));
+                if (propValue != null) {
+                    final Object argument;
+                    final Method method = setters.get(propertyName);
+                    if (method == null) {
+                        throw new IllegalArgumentException("Declared property " + propertyName + " wasn't found on " + objClass);
+                    }
+                    argument = getArgument(properties, method, propertyName, propValue);
+                    try {
+                        method.invoke(object, argument);
+                    } catch (Exception e) {
+                        throw new IllegalArgumentException("Unable to set property " + propertyName + " on " + objClass, e);
+                    }
+                }
+            } while (it.hasNext());
+        }
+    }
+
+    private Object getArgument(final Properties properties, final Method method, final String propertyName, final String propValue) throws IOException {
+        final Class<? extends Object> objClass = method.getDeclaringClass();
+        final Object argument;
+        final Class<?> paramType = method.getParameterTypes()[0];
+        if (paramType == String.class) {
+            argument = propValue;
+        } else if (paramType == Handler.class) {
+            argument = configureHandler(properties, propValue);
+        } else if (paramType == Filter.class) {
+            argument = configureFilter(properties, propValue);
+        } else if (paramType == Formatter.class) {
+            argument = configureFormatter(properties, propValue);
+        } else if (paramType == java.util.logging.Level.class) {
+            argument = LogContext.getSystemLogContext().getLevelForName(propValue);
+        } else if (paramType == java.util.logging.Logger.class) {
+            argument = LogContext.getSystemLogContext().getLogger(propValue);
+        } else if (paramType == boolean.class || paramType == Boolean.class) {
+            argument = Boolean.valueOf(propValue);
+        } else if (paramType == byte.class || paramType == Byte.class) {
+            argument = Byte.valueOf(propValue);
+        } else if (paramType == short.class || paramType == Short.class) {
+            argument = Short.valueOf(propValue);
+        } else if (paramType == int.class || paramType == Integer.class) {
+            argument = Integer.valueOf(propValue);
+        } else if (paramType == long.class || paramType == Long.class) {
+            argument = Long.valueOf(propValue);
+        } else if (paramType == float.class || paramType == Float.class) {
+            argument = Float.valueOf(propValue);
+        } else if (paramType == double.class || paramType == Double.class) {
+            argument = Double.valueOf(propValue);
+        } else if (paramType == char.class || paramType == Character.class) {
+            argument = Character.valueOf(propValue.length() > 0 ? propValue.charAt(0) : 0);
+        } else {
+            // ???
+            throw new IllegalArgumentException("Unknown paramter type for property " + propertyName + " on " + objClass);
+        }
+        return argument;
+    }
+
+    private Handler configureHandler(final Properties properties, final String handlerName) throws IOException {
+        if (configuredHandlers.containsKey(handlerName)) {
+            return configuredHandlers.get(handlerName);
+        }
+
+        // Get handler class name, instantiate it
+        final String handlerClassName = getStringProperty(properties, getKey("handler", handlerName));
+        if (handlerClassName == null) {
+            throw new IllegalArgumentException("Handler " + handlerName + " has no class name");
+        }
+        final Handler handler;
+        try {
+            handler = (Handler) Class.forName(handlerClassName).getConstructor().newInstance();
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Handler " + handlerName + " could not be instantiated", e);
+        }
+        configuredHandlers.put(handlerName, handler);
+
+        // Get handler level
+        final String levelName = getStringProperty(properties, getKey("handler", handlerName, "level"));
+        if (levelName != null) {
+            handler.setLevel(LogContext.getSystemLogContext().getLevelForName(levelName));
+        }
+
+        // Get handler encoding
+        final String encodingName = getStringProperty(properties, getKey("handler", handlerName, "encoding"));
+        if (encodingName != null) {
+            handler.setEncoding(encodingName);
+        }
+
+        // Get error handler
+        final String errorManagerName = getStringProperty(properties, getKey("handler", handlerName, "errorManager"));
+        if (errorManagerName != null) {
+            handler.setErrorManager(configureErrorManager(properties, errorManagerName));
+        }
+
+        // Get filter
+        final String filterName = getStringProperty(properties, getKey("handler", handlerName, "filter"));
+        if (filterName != null) {
+            handler.setFilter(configureFilter(properties, filterName));
+        }
+
+        // Get formatter
+        final String formatterName = getStringProperty(properties, getKey("handler", handlerName, "formatter"));
+        if (formatterName != null) {
+            handler.setFormatter(configureFormatter(properties, formatterName));
+        }
+
+        // Get properties
+        configureProperties(properties, handler, getKey("handler", handlerName));
+
+        return handler;
+    }
+
+    private ErrorManager configureErrorManager(final Properties properties, final String errorManagerName) throws IOException {
+        if (configuredErrorManagers.containsKey(errorManagerName)) {
+            return configuredErrorManagers.get(errorManagerName);
+        }
+        
+        // Get error manager class name, instantiate it
+        final String errorManagerClassName = getStringProperty(properties, getKey("errorManager", errorManagerName));
+        if (errorManagerClassName == null) {
+            throw new IllegalArgumentException("Error manager " + errorManagerName + " has no class name");
+        }
+        final ErrorManager errorManager;
+        try {
+            errorManager = (ErrorManager) Class.forName(errorManagerClassName).getConstructor().newInstance();
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Error manager " + errorManagerName + " could not be instantiated", e);
+        }
+        configuredErrorManagers.put(errorManagerName, errorManager);
+
+        // Get properties
+        configureProperties(properties, errorManager, getKey("errorManager", errorManagerName));
+
+        return errorManager;
+    }
+
+    private Formatter configureFormatter(final Properties properties, final String formatterName) throws IOException {
+        if (configuredFormatters.containsKey(formatterName)) {
+            return configuredFormatters.get(formatterName);
+        }
+
+        // Get formatter class name, instantiate it
+        final String formatterClassName = getStringProperty(properties, getKey("formatter", formatterName));
+        if (formatterClassName == null) {
+            throw new IllegalArgumentException("Formatter " + formatterName + " has no class name");
+        }
+        final Formatter formatter;
+        try {
+            formatter = (Formatter) Class.forName(formatterClassName).getConstructor().newInstance();
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Formatter " + formatterName + " could not be instantiated", e);
+        }
+        configuredFormatters.put(formatterName, formatter);
+
+        // Get properties
+        configureProperties(properties, formatter, getKey("formatter", formatterName));
+
+        return formatter;
+    }
+
+    private Filter configureFilter(final Properties properties, final String filterName) throws IOException {
+        if (configuredFilters.containsKey(filterName)) {
+            return configuredFilters.get(filterName);
+        }
+
+        // Get filter class name, instantiate it
+        final String filterClassName = getStringProperty(properties, getKey("filter", filterName));
+        if (filterClassName == null) {
+            throw new IllegalArgumentException("Filter " + filterName + " has no class name");
+        }
+        final Filter filter;
+        try {
+            filter = (Filter) Class.forName(filterClassName).getConstructor().newInstance();
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Filter " + filterName + " could not be instantiated", e);
+        }
+        configuredFilters.put(filterName, filter);
+
+        // Get properties
+        configureProperties(properties, filter, getKey("filter", filterName));
+
+        return filter;
+    }
+
+    private static String getKey(final String prefix, final String objectName) {
+        return objectName.length() > 0 ? prefix + "." + objectName : prefix;
+    }
+
+    private static String getKey(final String prefix, final String objectName, final String key) {
+        return objectName.length() > 0 ? prefix + "." + objectName + "." + key : prefix + "." + key;
+    }
+
+    private static String getStringProperty(final Properties properties, final String key) {
+        final String val = properties.getProperty(key);
+        return val == null ? null : StringPropertyReplacer.replaceProperties(val);
+    }
+
+    private static String[] getStringCsvArray(final Properties properties, final String key) {
+        final String value = properties.getProperty(key, "");
+        final String realValue = StringPropertyReplacer.replaceProperties(value);
+        return realValue.split("\\s*,\\s*");
+    }
+
+    private static List<String> getStringCsvList(final Properties properties, final String key) {
+        return new ArrayList<String>(Arrays.asList(getStringCsvArray(properties, key)));
+    }
+
+    private static List<String> getStringCsvList(final Properties properties, final String key, final String... prepend) {
+        final String[] array = getStringCsvArray(properties, key);
+        final List<String> list = new ArrayList<String>(array.length + prepend.length);
+        list.addAll(Arrays.asList(prepend));
+        list.addAll(Arrays.asList(array));
+        return list;
+    }
+
+    private static void safeClose(final Closeable stream) {
+        if (stream != null) try {
+            stream.close();
+        } catch (Exception e) {
+            // can't do anything about it
+        }
+    }
+}

Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/Formatters.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/Formatters.java	2009-06-09 16:01:12 UTC (rev 3233)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/Formatters.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -25,6 +25,8 @@
 import org.jboss.logmanager.ExtLogRecord;
 
 import java.util.logging.Level;
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -41,7 +43,22 @@
     private Formatters() {
     }
 
+    private static final Formatter NULL_FORMATTER = new Formatter() {
+        public String format(final LogRecord record) {
+            return "";
+        }
+    };
+
     /**
+     * Get the null formatter, which outputs nothing.
+     *
+     * @return the null formatter
+     */
+    public static Formatter nullFormatter() {
+        return NULL_FORMATTER;
+    }
+
+    /**
      * Create a format step which simply emits the given string.
      *
      * @param string the string to emit

Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/MultistepFormatter.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/MultistepFormatter.java	2009-06-09 16:01:12 UTC (rev 3233)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/MultistepFormatter.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -28,17 +28,23 @@
 /**
  * A formatter which formats a record in a series of steps.
  */
-public final class MultistepFormatter extends ExtFormatter {
-    private final FormatStep[] steps;
-    private final int builderLength;
+public class MultistepFormatter extends ExtFormatter {
+    private volatile FormatStep[] steps;
+    private volatile int builderLength;
 
+    private static final FormatStep[] EMPTY_STEPS = new FormatStep[0];
+
     /**
      * Construct a new instance.
      *
      * @param steps the steps to execute to format the record
      */
     public MultistepFormatter(final FormatStep[] steps) {
-        this.steps = steps;
+        this.steps = steps.clone();
+        calculateBuilderLength();
+    }
+
+    private void calculateBuilderLength() {
         int builderLength = 0;
         for (FormatStep step : steps) {
             builderLength += step.estimateLength();
@@ -46,6 +52,32 @@
         this.builderLength = max(32, builderLength);
     }
 
+    /**
+     * Construct a new instance.
+     */
+    public MultistepFormatter() {
+        steps = EMPTY_STEPS;
+    }
+
+    /**
+     * Get a copy of the format steps.
+     *
+     * @return a copy of the format steps
+     */
+    public FormatStep[] getSteps() {
+        return steps.clone();
+    }
+
+    /**
+     * Assign new format steps.
+     *
+     * @param steps the new format steps
+     */
+    public void setSteps(final FormatStep[] steps) {
+        this.steps = steps == null || steps.length == 0 ? EMPTY_STEPS : steps.clone();
+        calculateBuilderLength();
+    }
+
     /** {@inheritDoc} */
     public String format(final ExtLogRecord record) {
         final StringBuilder builder = new StringBuilder(builderLength);

Added: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/PatternFormatter.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/PatternFormatter.java	                        (rev 0)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/PatternFormatter.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logmanager.formatters;
+
+/**
+ * A formatter which uses a text pattern to format messages.
+ */
+public class PatternFormatter extends MultistepFormatter {
+
+    private volatile String pattern;
+
+    /**
+     * Construct a new instance.
+     */
+    public PatternFormatter() {
+    }
+
+    /**
+     * Construct a new instance.
+     *
+     * @param pattern the initial pattern
+     */
+    public PatternFormatter(String pattern) {
+        super(FormatStringParser.getSteps(pattern));
+        this.pattern = pattern;
+    }
+
+    /**
+     * Get the current format pattern.
+     *
+     * @return the pattern
+     */
+    public String getPattern() {
+        return pattern;
+    }
+
+    /**
+     * Set the format pattern.
+     *
+     * @param pattern the pattern
+     */
+    public void setPattern(final String pattern) {
+        setSteps(FormatStringParser.getSteps(pattern));
+        this.pattern = pattern;
+    }
+}

Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ConsoleHandler.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ConsoleHandler.java	2009-06-09 16:01:12 UTC (rev 3233)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ConsoleHandler.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -34,6 +34,12 @@
 
     /**
      * Construct a new instance.
+     */
+    public ConsoleHandler() {
+    }
+
+    /**
+     * Construct a new instance.
      *
      * @param formatter the formatter to use
      */

Added: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/FileHandler.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/FileHandler.java	                        (rev 0)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/FileHandler.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logmanager.handlers;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+
+/**
+ * A simple file handler.
+ */
+public class FileHandler extends OutputStreamHandler {
+
+    /**
+     * Construct a new instance with no formatter and no output file.
+     */
+    public FileHandler() {
+    }
+
+    /**
+     * Set the output file.
+     *
+     * @param file the file
+     * @throws FileNotFoundException if an error occurs opening the file
+     */
+    public void setFile(File file) throws FileNotFoundException {
+        final File parentFile = file.getParentFile();
+        if (parentFile != null) {
+            parentFile.mkdirs();
+        }
+        setOutputStream(new FileOutputStream(file, false));
+    }
+
+    /**
+     * Set the output file.
+     *
+     * @param fileName the file name
+     * @throws FileNotFoundException if an error occurs opening the file
+     */
+    public void setFileName(String fileName) throws FileNotFoundException {
+        setFile(new File(fileName));
+    }
+}

Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/OutputStreamHandler.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/OutputStreamHandler.java	2009-06-09 16:01:12 UTC (rev 3233)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/OutputStreamHandler.java	2009-06-09 21:47:07 UTC (rev 3234)
@@ -23,6 +23,7 @@
 package org.jboss.logmanager.handlers;
 
 import org.jboss.logmanager.ExtLogRecord;
+import org.jboss.logmanager.formatters.Formatters;
 import java.io.OutputStream;
 import java.io.Writer;
 import java.io.OutputStreamWriter;
@@ -42,12 +43,19 @@
  */
 public class OutputStreamHandler extends ExtHandler {
 
-    private volatile boolean autoflush = false;
+    private volatile boolean autoFlush = false;
     private final Object outputLock = new Object();
     private OutputStream outputStream;
     private Writer writer;
 
     /**
+     * Construct a new instance with no formatter.
+     */
+    public OutputStreamHandler() {
+        setFormatter(Formatters.nullFormatter());
+    }
+
+    /**
      * Construct a new instance.
      *
      * @param formatter the formatter to use
@@ -72,19 +80,19 @@
      *
      * @return {@code true} if autoflush is enabled
      */
-    public boolean isAutoflush() {
-        return autoflush;
+    public boolean isAutoFlush() {
+        return autoFlush;
     }
 
     /**
      * Change the autoflush status.
      *
-     * @param autoflush {@code true} to enable autoflush, {@code false} to disable it
+     * @param autoFlush {@code true} to enable autoflush, {@code false} to disable it
      * @throws SecurityException if you do not have sufficient permission to invoke this operation
      */
-    public void setAutoflush(final boolean autoflush) throws SecurityException {
+    public void setAutoFlush(final boolean autoFlush) throws SecurityException {
         checkControl();
-        this.autoflush = autoflush;
+        this.autoFlush = autoFlush;
     }
 
     /**
@@ -167,7 +175,7 @@
                 reportError("Error writing log message", ex, ErrorManager.WRITE_FAILURE);
                 return;
             }
-            if (autoflush) flush();
+            if (autoFlush) flush();
         }
     }
 




More information about the jboss-svn-commits mailing list