Author: robbie
Date: Sun Aug 16 20:32:47 2009
New Revision: 804765

URL: http://svn.apache.org/viewvc?rev=804765&view=rev
Log:
QPID-2051: Update startup scripts to disable the Log4J default initialisation 
process. Add QpidLog4JConfigurator that validates the XML file before allowing 
it to be applied. Alter startup behaviour to shut the broker down if the 
specified log4j XML file is present present but invalid. Uses the 
-Damqj.logging.level(defaults to info) with the log4j.properties file in the 
broker jar if the XML file is not found.

Added:
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/log4j/xml/
    
qpid/trunk/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java
    qpid/trunk/qpid/java/broker/src/test/java/org/apache/log4j/
    qpid/trunk/qpid/java/broker/src/test/java/org/apache/log4j/xml/
    
qpid/trunk/qpid/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java
Modified:
    qpid/trunk/qpid/java/broker/bin/qpid-server
    qpid/trunk/qpid/java/broker/bin/qpid-server.bat   (contents, props changed)
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
    
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java

Modified: qpid/trunk/qpid/java/broker/bin/qpid-server
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/bin/qpid-server?rev=804765&r1=804764&r2=804765&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/bin/qpid-server (original)
+++ qpid/trunk/qpid/java/broker/bin/qpid-server Sun Aug 16 20:32:47 2009
@@ -23,6 +23,12 @@
     export PATH=${PATH}:${QPID_HOME}/bin
 fi
 
+if [ -z "$QPID_LOG4J_SETTINGS" ]; then
+    # Disable the Log4J default initialization process, allowing the broker to 
+    # perform the configuration using etc/log4j.xml
+    QPID_LOG4J_SETTINGS="-Dlog4j.defaultInitOverride=true"
+fi
+
 # Set classpath to include Qpid jar with all required jars in manifest
 QPID_LIBS=$QPID_HOME/lib/qpid-all.jar:$QPID_HOME/lib/bdbstore-launch.jar
 
@@ -34,6 +40,6 @@
        QPID_CLASSPATH=$QPID_LIBS \
        QPID_RUN_LOG=2
 
-QPID_OPTS="$QPID_OPTS -Damqj.read_write_pool_size=32"
+QPID_OPTS="$QPID_OPTS $QPID_LOG4J_SETTINGS -Damqj.read_write_pool_size=32"
 
 . qpid-run org.apache.qpid.server.Main "$@"

Modified: qpid/trunk/qpid/java/broker/bin/qpid-server.bat
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/bin/qpid-server.bat?rev=804765&r1=804764&r2=804765&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/bin/qpid-server.bat (original)
+++ qpid/trunk/qpid/java/broker/bin/qpid-server.bat Sun Aug 16 20:32:47 2009
@@ -20,6 +20,9 @@
 @echo off
 REM Script to run the Qpid Java Broker
 
+rem stop the Log4J default initialisation, let the broker do it using 
etc/log4j.xml
+if "%QPID_LOG4J_SETTINGS%" == "" set 
QPID_LOG4J_SETTINGS=-Dlog4j.defaultInitOverride=true
+
 rem Guess QPID_HOME if not defined
 set CURRENT_DIR=%cd%
 if not "%QPID_HOME%" == "" goto gotHome
@@ -194,7 +197,7 @@
 rem user must enclose any value for QPID_OPTS in double quotes
 :runCommand
 set MODULE_JARS=%QPID_MODULE_JARS%
-set COMMAND="%JAVA_HOME%\bin\java" %JAVA_VM% %JAVA_MEM% %JAVA_GC% %QPID_OPTS% 
%SYSTEM_PROPS% -cp "%CLASSPATH%;%MODULE_JARS%" org.apache.qpid.server.Main 
%QPID_ARGS%
+set COMMAND="%JAVA_HOME%\bin\java" %JAVA_VM% %JAVA_MEM% %JAVA_GC% %QPID_OPTS% 
%QPID_LOG4J_SETTINGS% %SYSTEM_PROPS% -cp "%CLASSPATH%;%MODULE_JARS%" 
org.apache.qpid.server.Main %QPID_ARGS%
 
 if "%debug%" == "true" echo %CLASSPATH%;%LAUNCH_JAR%;%MODULE_JARS%
 if "%debug%" == "true" echo %COMMAND%

Propchange: qpid/trunk/qpid/java/broker/bin/qpid-server.bat
            ('svn:executable' removed)

Added: 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java?rev=804765&view=auto
==============================================================================
--- 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java
 (added)
+++ 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java
 Sun Aug 16 20:32:47 2009
@@ -0,0 +1,250 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.log4j.xml;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.logging.management.LoggingManagementMBean;
+import 
org.apache.qpid.server.logging.management.LoggingManagementMBean.QpidLog4JSaxErrorHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * Substitute for the Log4J XMLWatchdog (as used by 
DOMConfigurator.configureAndWatch)
+ * 
+ * Extends the default behaviour with a strict parser check on the XML file 
before allowing the reconfiguration to proceed,
+ * ensuring that any parser error or warning prevents initiation of a 
configuration update by Log4J, which aborts mid-update
+ * upon fatal errors from the parser and proceeds in the event of 'regular' 
parser errors and warnings, in all cases allowing
+ * startup to proceed with whatever half-baked configuration then exists.
+ */
+public class QpidLog4JConfigurator
+{
+    //lock to protect access to the configuration file
+    private static final ReentrantLock LOCK = new ReentrantLock();
+    private static Logger _logger;
+
+    private QpidLog4JConfigurator()
+    {
+        //no instances
+    }
+    
+    public static void configure(String filename) throws IOException, 
ParserConfigurationException, 
+                                                         SAXException, 
IllegalLoggerLevelException
+    {
+        try
+        {
+            LOCK.lock();
+
+            strictlyParseXMLConfigFile(filename);
+            checkLoggerLevels(filename);
+
+            DOMConfigurator.configure(filename);
+        }
+        finally
+        {
+            LOCK.unlock();
+        }
+    }
+    
+    public static void configureAndWatch(String filename, long delay) throws 
IOException, ParserConfigurationException, 
+                                                                             
SAXException, IllegalLoggerLevelException
+    {
+        strictlyParseXMLConfigFile(filename);
+        checkLoggerLevels(filename);
+        
+        QpidLog4JXMLWatchdog watchdog = new QpidLog4JXMLWatchdog(filename);
+        watchdog.setDelay(delay);
+        watchdog.start();
+    }
+    
+    private static void strictlyParseXMLConfigFile(String fileName) throws 
IOException, SAXException,
+                                                                               
         ParserConfigurationException
+    {
+        try
+        {
+            LOCK.lock();
+
+            //check file was specified, exists, and is readable
+            if(fileName == null)
+            {
+                throw new IOException("Provided log4j XML configuration 
filename was null");
+            }
+
+            File configFile = new File(fileName);
+
+            if (!configFile.exists())
+            {
+                throw new IOException("The log4j XML configuration file does 
not exist: " + fileName);
+            }
+            else if (!configFile.canRead())
+            {
+                throw new IOException("The log4j XML configuration file is not 
readable: " + fileName);
+            }
+
+            //parse it
+            DocumentBuilderFactory docFactory = 
DocumentBuilderFactory.newInstance();
+            DocumentBuilder docBuilder;
+
+            ErrorHandler errHandler = new QpidLog4JSaxErrorHandler();
+
+            docFactory.setValidating(true);
+            docBuilder = docFactory.newDocumentBuilder();
+            docBuilder.setErrorHandler(errHandler);
+            docBuilder.setEntityResolver(new Log4jEntityResolver());
+            docBuilder.parse(fileName);
+        }
+        finally
+        {
+            LOCK.unlock();
+        }
+    }
+    
+    private static class QpidLog4JXMLWatchdog extends XMLWatchdog
+    {
+        public QpidLog4JXMLWatchdog(String filename)
+        {
+            super(filename);
+        }
+
+        public void doOnChange()
+        {
+            try
+            {
+                LOCK.lock();
+                
+                try
+                {
+                    strictlyParseXMLConfigFile(filename);
+                }
+                catch (Exception e)
+                {
+                    //logger will be instantiated following first 
configuration success, which has been pre-validated
+                    //and so the null check should never actually be required.
+                    if(_logger != null)
+                    {
+                        _logger.warn("Parsing the log4j XML configuration file 
generated errors/warnings. " +
+                                "The new configuration was not applied. 
Correct the issues to prompt " +
+                                "another update attempt: " + e.getMessage());
+                    }
+                    return;
+                }
+
+                try
+                {
+                    checkLoggerLevels(filename);
+                }
+                catch (Exception e)
+                {
+                    //logger will be instantiated following first 
configuration success, which has been pre-validated
+                    //and so the null check should never actually be required.
+                    if(_logger != null)
+                    {
+                        _logger.warn("Errors were found when validating the 
logger level values in the " +
+                                "log4j XML configuration file. The new 
configuration was not applied. " +
+                                "Correct the issues to prompt another update 
attempt: " + e.getMessage());
+                    }
+                    return;
+                }
+
+                //everything checked was ok, let the normal update process 
proceed
+                super.doOnChange();
+
+                //a configuration has now been applied, enable logging for 
future attempts
+                if(_logger == null)
+                {
+                    _logger = Logger.getLogger(QpidLog4JConfigurator.class);
+                }
+
+                _logger.info("Applied log4j configuration from: " + filename);
+            }
+            finally
+            {
+                LOCK.unlock();
+            }
+
+        }
+    }
+    
+    protected static void checkLoggerLevels(String filename) throws 
IllegalLoggerLevelException, IOException
+    {
+        //check that the logger levels specified in the XML are actually valid
+
+        try
+        {
+            LOCK.lock();
+            
+            Map<String, String> loggersLevels;
+            loggersLevels = 
LoggingManagementMBean.retrieveConfigFileLoggersLevels(filename);
+
+            for (String loggerName : loggersLevels.keySet())
+            {
+                String levelString = loggersLevels.get(loggerName);
+                checkLevel(loggerName,levelString);
+            }
+
+            //check the root logger level
+            String rootLoggerlevelString = 
LoggingManagementMBean.retrieveConfigFileRootLoggerLevel(filename);
+            checkLevel("Root", rootLoggerlevelString);
+        }
+        finally
+        {
+            LOCK.unlock();
+        }
+    }
+    
+    private static void checkLevel(String loggerName, String levelString) 
throws IllegalLoggerLevelException
+    {
+        if("null".equalsIgnoreCase(levelString) || 
"inherited".equalsIgnoreCase(levelString))
+        {
+            //the string "null" signals to inherit from a parent logger 
+            return;
+        }
+        
+        Level level = Level.toLevel(levelString);
+
+        //above Level.toLevel call returns a DEBUG Level if the request fails. 
Check the result.
+        if (level.equals(Level.DEBUG) && 
!(levelString.equalsIgnoreCase("debug")))
+        {
+            //received DEBUG but we did not ask for it, the Level request 
failed.
+            throw new IllegalLoggerLevelException("Level '" + levelString + "' 
specified for Logger '" + loggerName + "' is invalid");
+        }
+    }
+    
+    public static class IllegalLoggerLevelException extends Exception
+    {
+        private static final long serialVersionUID = 1L;
+
+        public IllegalLoggerLevelException(String msg)
+        {
+            super(msg);
+        }
+    }
+}
+

Modified: 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java?rev=804765&r1=804764&r2=804765&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java 
(original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java 
Sun Aug 16 20:32:47 2009
@@ -27,9 +27,9 @@
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 import org.apache.commons.cli.PosixParser;
-import org.apache.log4j.BasicConfigurator;
 import org.apache.log4j.Logger;
-import org.apache.log4j.xml.DOMConfigurator;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.log4j.xml.QpidLog4JConfigurator;
 import org.apache.mina.common.ByteBuffer;
 import org.apache.mina.common.FixedSizeByteBufferAllocator;
 import org.apache.mina.common.IoAcceptor;
@@ -56,9 +56,11 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.BindException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.util.Properties;
 
 /**
  * Main entry point for AMQPD.
@@ -200,7 +202,7 @@
             }
             catch (InitException e)
             {
-                System.out.println(e.getMessage());
+                System.out.println("Initialisation Error : " + e.getMessage());
                 _brokerLogger.error("Initialisation Error : " + 
e.getMessage());
                 shutdown(1);
             }
@@ -498,7 +500,7 @@
         return ip;
     }
 
-    private void configureLogging(File logConfigFile, int logWatchTime)
+    private void configureLogging(File logConfigFile, int logWatchTime) throws 
InitException, IOException
     {
         if (logConfigFile.exists() && logConfigFile.canRead())
         {
@@ -509,18 +511,43 @@
                 System.out.println("log file " + 
logConfigFile.getAbsolutePath() + " will be checked for changes every "
                                    + logWatchTime + " seconds");
                 // log4j expects the watch interval in milliseconds
-                
DOMConfigurator.configureAndWatch(logConfigFile.getAbsolutePath(), logWatchTime 
* 1000);
+                try
+                {
+                    
QpidLog4JConfigurator.configureAndWatch(logConfigFile.getPath(), logWatchTime * 
1000);
+                }
+                catch (Exception e)
+                {
+                    throw new InitException(e.getMessage(),e);
+                }
             }
             else
             {
-                DOMConfigurator.configure(logConfigFile.getAbsolutePath());
+                try
+                {
+                    QpidLog4JConfigurator.configure(logConfigFile.getPath());
+                }
+                catch (Exception e)
+                {
+                    throw new InitException(e.getMessage(),e);
+                }
             }
         }
         else
         {
             System.err.println("Logging configuration error: unable to read 
file " + logConfigFile.getAbsolutePath());
-            System.err.println("Using basic log4j configuration");
-            BasicConfigurator.configure();
+            System.err.println("Using the fallback internal log4j.properties 
configuration");
+            
+            InputStream propsFile = 
this.getClass().getResourceAsStream("/log4j.properties");
+            if(propsFile == null)
+            {
+                throw new IOException("Unable to load the fallback internal 
log4j.properties configuration file");
+            }
+            else
+            {
+                Properties fallbackProps = new Properties();
+                fallbackProps.load(propsFile);
+                PropertyConfigurator.configure(fallbackProps);
+            }
         }
     }
 

Modified: 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java?rev=804765&r1=804764&r2=804765&view=diff
==============================================================================
--- 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java
 (original)
+++ 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java
 Sun Aug 16 20:32:47 2009
@@ -24,7 +24,9 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.qpid.management.common.mbeans.LoggingManagement;
 import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
@@ -34,6 +36,8 @@
 import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
 import org.apache.log4j.xml.Log4jEntityResolver;
+import org.apache.log4j.xml.QpidLog4JConfigurator;
+import org.apache.log4j.xml.QpidLog4JConfigurator.IllegalLoggerLevelException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -244,46 +248,50 @@
     }
     
     //handler to catch errors signalled by the JAXP parser and throw an 
appropriate exception
-    private class SaxErrorHandler implements ErrorHandler
+    public static class QpidLog4JSaxErrorHandler implements ErrorHandler
     {
-        
         public void error(SAXParseException e) throws SAXException
         {
-            throw new SAXException("Error parsing XML file: " + 
e.getMessage());
+            throw new SAXException(constructMessage("Error parsing XML file", 
e));
         }
 
         public void fatalError(SAXParseException e) throws SAXException
         {
-            throw new SAXException("Fatal error parsing XML file: " + 
e.getMessage());
+            throw new SAXException(constructMessage("Fatal error parsing XML 
file", e));
         }
 
         public void warning(SAXParseException e) throws SAXException
         {
-            throw new SAXException("Warning parsing XML file: " + 
e.getMessage());
+            throw new SAXException(constructMessage("Warning parsing XML 
file", e));
+        }
+
+        private static String constructMessage(final String msg, final 
SAXParseException ex)
+        {
+            return new String(msg + ": Line " + ex.getLineNumber()+" column " 
+ex.getColumnNumber() + ": " + ex.getMessage());
         }
     }
 
     //method to parse the XML configuration file, validating it in the 
process, and returning a DOM Document of the content.
-    private synchronized Document parseConfigFile(String fileName) throws 
IOException
+    private static synchronized Document parseConfigFile(String fileName) 
throws IOException
     {
         //check file was specified, exists, and is readable
         if(fileName == null)
         {
-            _logger.warn("No log4j XML configuration file has been set");
-            throw new IOException("No log4j XML configuration file has been 
set");
+            _logger.warn("Provided log4j XML configuration filename is null");
+            throw new IOException("Provided log4j XML configuration filename 
is null");
         }
 
         File configFile = new File(fileName);
 
         if (!configFile.exists())
         {
-            _logger.warn("Specified log4j XML configuration file does not 
exist: " + fileName);
-            throw new IOException("Specified log4j XML configuration file does 
not exist");
+            _logger.warn("The log4j XML configuration file could not be found: 
" + fileName);
+            throw new IOException("The log4j XML configuration file could not 
be found");
         }
         else if (!configFile.canRead())
         {
-            _logger.warn("Specified log4j XML configuration file is not 
readable: " + fileName);
-            throw new IOException("Specified log4j XML configuration file is 
not readable");
+            _logger.warn("The log4j XML configuration file is not readable: " 
+ fileName);
+            throw new IOException("The log4j XML configuration file is not 
readable");
         }
 
         //parse it
@@ -291,7 +299,7 @@
         DocumentBuilder docBuilder;
         Document doc;
 
-        ErrorHandler errHandler = new SaxErrorHandler();
+        ErrorHandler errHandler = new QpidLog4JSaxErrorHandler();
         try
         {
             docFactory.setValidating(true);
@@ -315,14 +323,14 @@
         catch (IOException e)
         {
             _logger.warn("Unable to parse the specified log4j XML file" + e);
-            throw new IOException("Unable to parse the specified log4j XML 
file", e);
+            throw new IOException("Unable to parse the specified log4j XML 
file: " + e.getMessage());
         }
 
         return doc;
     }
 
     
-    private synchronized boolean writeUpdatedConfigFile(String 
log4jConfigFileName, Document doc) throws IOException
+    private static synchronized boolean writeUpdatedConfigFile(String 
log4jConfigFileName, Document doc) throws IOException
     {
         File log4jConfigFile = new File(log4jConfigFileName);
         
@@ -389,20 +397,11 @@
      * and not the only possible child element.
      */
     
-    
-    public synchronized TabularData viewConfigFileLoggerLevels() throws 
IOException
+    public static synchronized Map<String,String> 
retrieveConfigFileLoggersLevels(String fileName) throws IOException
     {
-        if (_loggerLevelTabularType == null)
-        {
-            _logger.warn("TabluarData type not set up correctly");
-            return null;
-        }
-        
-        _logger.info("Getting logger levels from log4j configuration file");
-        
-        Document doc = parseConfigFile(_log4jConfigFileName);
+        Document doc = parseConfigFile(fileName);
 
-        TabularData loggerLevelList = new 
TabularDataSupport(_loggerLevelTabularType);
+        HashMap<String,String> loggerLevelList = new HashMap<String,String>();
 
         //retrieve the 'category' element nodes
         NodeList categoryElements = doc.getElementsByTagName("category");
@@ -436,17 +435,7 @@
                 continue;
             }
 
-            try
-            {
-                Object[] itemData = {categoryName, priority};
-                CompositeData loggerData = new 
CompositeDataSupport(_loggerLevelCompositeType, COMPOSITE_ITEM_NAMES, itemData);
-                loggerLevelList.put(loggerData);
-            }
-            catch (OpenDataException e)
-            {
-                _logger.warn("Unable to create logger level list due to :" + 
e);
-                return null;
-            }
+            loggerLevelList.put(categoryName, priority);
         }
 
         //retrieve the 'logger' element nodes
@@ -467,6 +456,30 @@
             Element levelElement = (Element) levelElements.item(0);
             level = levelElement.getAttribute("value").toUpperCase();
             
+            loggerLevelList.put(loggerName, level);
+        }
+        
+        return loggerLevelList;
+    }
+
+    public synchronized TabularData viewConfigFileLoggerLevels() throws 
IOException
+    {
+        if (_loggerLevelTabularType == null)
+        {
+            _logger.warn("TabluarData type not set up correctly");
+            return null;
+        }
+        
+        _logger.info("Getting logger levels from log4j configuration file");
+
+        TabularData loggerLevelList = new 
TabularDataSupport(_loggerLevelTabularType);
+        
+        Map<String,String> levels = 
retrieveConfigFileLoggersLevels(_log4jConfigFileName);
+
+        for (String loggerName : levels.keySet())
+        {
+            String level = levels.get(loggerName);
+            
             try
             {
                 Object[] itemData = {loggerName, level};
@@ -574,19 +587,17 @@
      * and not the only possible child element.
      */
     
-    public synchronized String getConfigFileRootLoggerLevel() throws 
IOException
+    public static synchronized String retrieveConfigFileRootLoggerLevel(String 
fileName) throws IOException
     {
-        _logger.info("Getting root logger level from log4j configuration 
file");
-
-        Document doc = parseConfigFile(_log4jConfigFileName);
+        Document doc = parseConfigFile(fileName);
        
         //retrieve the optional 'root' element node
         NodeList rootElements = doc.getElementsByTagName("root");
 
         if (rootElements.getLength() == 0)
         {
-            //there is not root logger definition
-            return null;
+            //there is no root logger definition
+            return "N/A";
         }
 
         Element rootElement = (Element) rootElements.item(0);
@@ -618,6 +629,11 @@
         }
     }
     
+    public synchronized String getConfigFileRootLoggerLevel() throws 
IOException
+    {
+        return retrieveConfigFileRootLoggerLevel(_log4jConfigFileName);
+    }
+    
     public synchronized boolean setConfigFileRootLoggerLevel(String level) 
throws IOException
     {
         //check that the specified level is a valid log4j Level

Added: 
qpid/trunk/qpid/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java?rev=804765&view=auto
==============================================================================
--- 
qpid/trunk/qpid/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java
 (added)
+++ 
qpid/trunk/qpid/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java
 Sun Aug 16 20:32:47 2009
@@ -0,0 +1,396 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.    
+ *
+ * 
+ */
+package org.apache.log4j.xml;
+
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import org.apache.log4j.xml.QpidLog4JConfigurator.IllegalLoggerLevelException;
+
+import junit.framework.TestCase;
+
+public class QpidLog4JConfiguratorTest extends TestCase
+{
+    private static final String NEWLINE = System.getProperty("line.separator");
+
+    private File _testConfigFile;
+
+    private File createTempTestLog4JConfig(String loggerLevel,String 
rootLoggerLevel, boolean missingTagClose, boolean incorrectAttribute)
+    {
+        File tmpFile = null;
+        try
+        {
+            tmpFile = File.createTempFile("LogManMBeanTestLog4jConfig", 
".tmp");
+            tmpFile.deleteOnExit();
+
+            FileWriter fstream = new FileWriter(tmpFile);
+            BufferedWriter writer = new BufferedWriter(fstream);
+
+            writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+NEWLINE);
+            writer.write("<!DOCTYPE log4j:configuration SYSTEM 
\"log4j.dtd\">"+NEWLINE);
+
+            writer.write("<log4j:configuration 
xmlns:log4j=\"http://jakarta.apache.org/log4j/\"; debug=\"null\" " +
+                    "threshold=\"null\">"+NEWLINE);
+
+            writer.write("  <appender 
class=\"org.apache.log4j.ConsoleAppender\" name=\"STDOUT\">"+NEWLINE);
+            writer.write("      <layout 
class=\"org.apache.log4j.PatternLayout\">"+NEWLINE);
+            writer.write("          <param name=\"ConversionPattern\" 
value=\"%d %-5p [%t] %C{2} (%F:%L) - %m%n\"/>"+NEWLINE);
+            writer.write("      </layout>"+NEWLINE);
+            writer.write("  </appender>"+NEWLINE);
+            
+            String closeTag="/";
+            if(missingTagClose)
+            {
+                closeTag="";
+            }
+
+            //Example of a 'category' with a 'priority'
+            writer.write("  <category additivity=\"true\" 
name=\"logger1\">"+NEWLINE);
+            writer.write("      <priority value=\"" + loggerLevel+ "\"" + 
closeTag + ">"+NEWLINE);
+            writer.write("      <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
+            writer.write("  </category>"+NEWLINE);
+
+            String attributeName="value";
+            if(incorrectAttribute)
+            {
+                attributeName="values";
+            }
+            
+            //Example of a 'category' with a 'level'
+            writer.write("  <category additivity=\"true\" 
name=\"logger2\">"+NEWLINE);
+            writer.write("      <level " + attributeName + "=\"" + 
loggerLevel+ "\"/>"+NEWLINE);
+            writer.write("      <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
+            writer.write("  </category>"+NEWLINE);
+
+            //Example of a 'logger' with a 'level'
+            writer.write("  <logger additivity=\"true\" 
name=\"logger3\">"+NEWLINE);
+            writer.write("      <level value=\"" + loggerLevel+ 
"\"/>"+NEWLINE);
+            writer.write("      <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
+            writer.write("  </logger>"+NEWLINE);
+
+            //'root' logger
+            writer.write("  <root>"+NEWLINE);
+            writer.write("      <priority value=\"" + rootLoggerLevel+ 
"\"/>"+NEWLINE);
+            writer.write("      <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
+            writer.write("  </root>"+NEWLINE);
+
+            writer.write("</log4j:configuration>"+NEWLINE);
+
+            writer.flush();
+            writer.close();
+        }
+        catch (IOException e)
+        {
+            fail("Unable to create temporary test log4j configuration");
+        }
+
+        return tmpFile;
+    }
+
+
+
+    //******* Test Methods ******* //
+
+    public void testCheckLevelsAndStrictParser()
+    {
+        //try the valid logger levels
+        _testConfigFile = createTempTestLog4JConfig("all", "info", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("trace", "info", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("debug", "info", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "info", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("warn", "info", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("error", "info", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("fatal", "info", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("off", "info", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("null", "info", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("inherited", "info", 
false, false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        //now try an invalid logger level
+        _testConfigFile = createTempTestLog4JConfig("madeup", "info", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+            fail("IllegalLoggerLevelException expected, invalid levels used");
+        }
+        catch (IllegalLoggerLevelException e)
+        {
+            //expected, ignore
+        }
+        catch (IOException e)
+        {
+            fail("Incorrect Exception, expected an 
IllegalLoggerLevelException");
+        }
+        
+        
+        
+        //now try the valid rootLogger levels
+        _testConfigFile = createTempTestLog4JConfig("info", "all", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "trace", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "debug", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "info", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "warn", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "error", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "fatal", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "off", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "null", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "inherited", 
false, false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "debug", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+        }
+        catch (Exception e)
+        {
+            fail("No exception expected, valid levels and xml were used");
+        }
+        
+        //now try an invalid logger level
+        _testConfigFile = createTempTestLog4JConfig("info", "madeup", false, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+            fail("IllegalLoggerLevelException expected, invalid levels used");
+        }
+        catch (IllegalLoggerLevelException e)
+        {
+            //expected, ignore
+        }
+        catch (IOException e)
+        {
+            fail("Incorrect Exception, expected an 
IllegalLoggerLevelException");
+        }
+        
+        
+        
+        //now try invalid xml
+        _testConfigFile = createTempTestLog4JConfig("info", "info", true, 
false);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+            fail("IOException expected, malformed XML used");
+        }
+        catch (IllegalLoggerLevelException e)
+        {
+            fail("Incorrect Exception, expected an IOException");
+        }
+        catch (IOException e)
+        {
+            //expected, ignore
+        }
+        
+        _testConfigFile = createTempTestLog4JConfig("info", "info", false, 
true);
+        try
+        {
+            
QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
+            fail("IOException expected, malformed XML used");
+        }
+        catch (IllegalLoggerLevelException e)
+        {
+            fail("Incorrect Exception, expected an IOException");
+        }
+        catch (IOException e)
+        {
+            //expected, ignore
+        }
+    }
+}



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscr...@qpid.apache.org

Reply via email to