diff options
Diffstat (limited to 'java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java')
-rw-r--r-- | java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java | 579 |
1 files changed, 0 insertions, 579 deletions
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java deleted file mode 100644 index 931171b175..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java +++ /dev/null @@ -1,579 +0,0 @@ -/* - * - * 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.qpid.server.logging.log4j; - -import org.apache.log4j.Level; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; -import org.apache.log4j.xml.DOMConfigurator; -import org.apache.log4j.xml.Log4jEntityResolver; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.ErrorHandler; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import java.io.File; -import java.io.FileOutputStream; -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 java.util.Random; - -/** - * A facade over log4j that allows both the control of the runtime logging behaviour (that is, the ability to - * turn {@link Logger} on, off and control their {@link Level}, and the manipulation and reload - * of the log4j configuration file. - */ -public class LoggingFacade -{ - private static Logger LOGGER; - private static transient LoggingFacade _instance; - private final String _filename; - private final int _delay; - - public static LoggingFacade configure(String filename) throws LoggingFacadeException - { - _instance = new LoggingFacade(filename); - return _instance; - } - - public static LoggingFacade configureAndWatch(String filename, int delay) throws LoggingFacadeException - { - _instance = new LoggingFacade(filename, delay); - return _instance; - } - - public static LoggingFacade getCurrentInstance() - { - return _instance; - } - - private LoggingFacade(String filename) - { - DOMConfigurator.configure(filename); - - if(LOGGER == null) - { - LOGGER = Logger.getLogger(LoggingFacade.class); - } - _filename = filename; - _delay = 0; - } - - private LoggingFacade(String filename, int delay) - { - DOMConfigurator.configureAndWatch(filename, delay); - - if(LOGGER == null) - { - LOGGER = Logger.getLogger(LoggingFacade.class); - } - - _filename = filename; - _delay = delay; - } - - public int getLog4jLogWatchInterval() - { - return _delay; - } - - public synchronized void reload() throws LoggingFacadeException - { - DOMConfigurator.configure(_filename); - } - - /** The log4j XML configuration file DTD defines three possible element - * combinations for specifying optional logger+level settings. - * Must account for the following: - * - * <category name="x"> <priority value="y"/> </category> OR - * <category name="x"> <level value="y"/> </category> OR - * <logger name="x"> <level value="y"/> </logger> - * - * Noting also that the level/priority child element is optional too, - * and not the only possible child element. - */ - public synchronized Map<String,String> retrieveConfigFileLoggersLevels() throws LoggingFacadeException - { - try - { - Map<String,String> loggerLevelList = new HashMap<String,String>(); - LOGGER.info("Getting logger levels from log4j configuration file"); - - Document doc = parseConfigFile(_filename); - List<Element> categoryOrLoggerElements = buildListOfCategoryOrLoggerElements(doc); - - for (Element categoryOrLogger : categoryOrLoggerElements) - { - - Element priorityOrLevelElement; - try - { - priorityOrLevelElement = getPriorityOrLevelElement(categoryOrLogger); - } - catch (LoggingFacadeException lfe) - { - //there is no exiting priority or level to view, move onto next category/logger - continue; - } - - String categoryName = categoryOrLogger.getAttribute("name"); - String priorityOrLevelValue = priorityOrLevelElement.getAttribute("value"); - loggerLevelList.put(categoryName, priorityOrLevelValue); - } - - return loggerLevelList; - } - catch (IOException e) - { - throw new LoggingFacadeException(e); - } - } - - /** - * The log4j XML configuration file DTD defines 2 possible element - * combinations for specifying the optional root logger level settings - * Must account for the following: - * - * <root> <priority value="y"/> </root> OR - * <root> <level value="y"/> </root> - * - * Noting also that the level/priority child element is optional too, - * and not the only possible child element. - */ - public synchronized String retrieveConfigFileRootLoggerLevel() throws LoggingFacadeException - { - try - { - Document doc = parseConfigFile(_filename); - - //retrieve the optional 'root' element node - NodeList rootElements = doc.getElementsByTagName("root"); - - if (rootElements.getLength() == 0) - { - //there is no root logger definition - return "N/A"; - } - - Element rootElement = (Element) rootElements.item(0); - Element levelElement = getPriorityOrLevelElement(rootElement); - - if(levelElement != null) - { - return levelElement.getAttribute("value"); - } - else - { - return "N/A"; - } - } - catch (IOException e) - { - throw new LoggingFacadeException(e); - } - } - - public synchronized void setConfigFileLoggerLevel(String logger, String level) throws LoggingFacadeException - { - LOGGER.info("Setting level to " + level + " for logger '" + logger - + "' in log4j xml configuration file: " + _filename); - - try - { - Document doc = parseConfigFile(_filename); - - List<Element> logElements = buildListOfCategoryOrLoggerElements(doc); - - //try to locate the specified logger/category in the elements retrieved - Element logElement = null; - for (Element e : logElements) - { - if (e.getAttribute("name").equals(logger)) - { - logElement = e; - break; - } - } - - if (logElement == null) - { - throw new LoggingFacadeException("Can't find logger " + logger); - } - - Element levelElement = getPriorityOrLevelElement(logElement); - - //update the element with the new level/priority - levelElement.setAttribute("value", level); - - //output the new file - writeUpdatedConfigFile(_filename, doc); - } - catch (IOException ioe) - { - throw new LoggingFacadeException(ioe); - } - catch (TransformerConfigurationException e) - { - throw new LoggingFacadeException(e); - } - } - - public synchronized void setConfigFileRootLoggerLevel(String level) throws LoggingFacadeException - { - try - { - LOGGER.info("Setting level to " + level + " for the Root logger in " + - "log4j xml configuration file: " + _filename); - - Document doc = parseConfigFile(_filename); - - //retrieve the optional 'root' element node - NodeList rootElements = doc.getElementsByTagName("root"); - - if (rootElements.getLength() == 0) - { - throw new LoggingFacadeException("Configuration contains no root element"); - } - - Element rootElement = (Element) rootElements.item(0); - Element levelElement = getPriorityOrLevelElement(rootElement); - - //update the element with the new level/priority - levelElement.setAttribute("value", level); - - //output the new file - writeUpdatedConfigFile(_filename, doc); - } - catch (IOException e) - { - throw new LoggingFacadeException(e); - } - catch (TransformerConfigurationException e) - { - throw new LoggingFacadeException(e); - } - } - - public List<String> getAvailableLoggerLevels() - { - return new ArrayList<String>() - {{ - add(Level.ALL.toString()); - add(Level.TRACE.toString()); - add(Level.DEBUG.toString()); - add(Level.INFO.toString()); - add(Level.WARN.toString()); - add(Level.ERROR.toString()); - add(Level.FATAL.toString()); - add(Level.OFF.toString()); - }}; - } - - public String retrieveRuntimeRootLoggerLevel() - { - Logger rootLogger = Logger.getRootLogger(); - return rootLogger.getLevel().toString(); - } - - public void setRuntimeRootLoggerLevel(String level) - { - Level newLevel = Level.toLevel(level); - - LOGGER.info("Setting RootLogger level to " + level); - - Logger log = Logger.getRootLogger(); - log.setLevel(newLevel); - } - - public void setRuntimeLoggerLevel(String loggerName, String level) throws LoggingFacadeException - { - Level newLevel = level == null ? null : Level.toLevel(level); - - Logger targetLogger = findRuntimeLogger(loggerName); - - if(targetLogger == null) - { - throw new LoggingFacadeException("Can't find logger " + loggerName); - } - - LOGGER.info("Setting level to " + newLevel + " for logger '" + targetLogger.getName() + "'"); - - targetLogger.setLevel(newLevel); - } - - public Map<String,String> retrieveRuntimeLoggersLevels() - { - LOGGER.info("Getting levels for currently active log4j loggers"); - - Map<String, String> levels = new HashMap<String, String>(); - @SuppressWarnings("unchecked") - Enumeration<Logger> loggers = LogManager.getCurrentLoggers(); - - while (loggers.hasMoreElements()) - { - Logger logger = loggers.nextElement(); - levels.put(logger.getName(), logger.getEffectiveLevel().toString()); - } - - return levels; - } - - private void writeUpdatedConfigFile(String log4jConfigFileName, Document doc) throws IOException, TransformerConfigurationException - { - File log4jConfigFile = new File(log4jConfigFileName); - - if (!log4jConfigFile.canWrite()) - { - LOGGER.warn("Specified log4j XML configuration file is not writable: " + log4jConfigFile); - throw new IOException("Specified log4j XML configuration file is not writable"); - } - - Transformer transformer = null; - transformer = TransformerFactory.newInstance().newTransformer(); - - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "log4j.dtd"); - DOMSource source = new DOMSource(doc); - - File tmp; - Random r = new Random(); - - do - { - tmp = new File(log4jConfigFile.getAbsolutePath() + r.nextInt() + ".tmp"); - } - while(tmp.exists()); - - tmp.deleteOnExit(); - - try - { - StreamResult result = new StreamResult(new FileOutputStream(tmp)); - transformer.transform(source, result); - } - catch (TransformerException e) - { - LOGGER.warn("Could not transform the XML into new file: ", e); - throw new IOException("Could not transform the XML into new file: ", e); - } - - // Swap temp file in to replace existing configuration file. - File old = new File(log4jConfigFile.getAbsoluteFile() + ".old"); - if (old.exists()) - { - old.delete(); - } - - if(!log4jConfigFile.renameTo(old)) - { - //unable to rename the existing file to the backup name - LOGGER.error("Could not backup the existing log4j XML file"); - throw new IOException("Could not backup the existing log4j XML file"); - } - - if(!tmp.renameTo(log4jConfigFile)) - { - //failed to rename the new file to the required filename - - if(!old.renameTo(log4jConfigFile)) - { - //unable to return the backup to required filename - LOGGER.error("Could not rename the new log4j configuration file into place, and unable to restore original file"); - throw new IOException("Could not rename the new log4j configuration file into place, and unable to restore original file"); - } - - LOGGER.error("Could not rename the new log4j configuration file into place"); - throw new IOException("Could not rename the new log4j configuration file into place"); - } - } - - //method to parse the XML configuration file, validating it in the process, and returning a DOM Document of the content. - private static Document parseConfigFile(String fileName) throws IOException - { - //check file was specified, exists, and is readable - if(fileName == null) - { - 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("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("The log4j XML configuration file is not readable: " + fileName); - throw new IOException("The log4j XML configuration file is not readable"); - } - - //parse it - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder; - Document doc; - - ErrorHandler errHandler = new QpidLog4JSaxErrorHandler(); - try - { - docFactory.setValidating(true); - docBuilder = docFactory.newDocumentBuilder(); - docBuilder.setErrorHandler(errHandler); - docBuilder.setEntityResolver(new Log4jEntityResolver()); - doc = docBuilder.parse(fileName); - } - catch (ParserConfigurationException e) - { - LOGGER.warn("Unable to parse the log4j XML file due to possible configuration error: ", e); - throw new IOException("Unable to parse the log4j XML file due to possible configuration error: ", e); - } - catch (SAXException e) - { - LOGGER.warn("The specified log4j XML file is invalid: ", e); - throw new IOException("The specified log4j XML file is invalid: ", e); - } - 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); - } - - return doc; - } - - private Logger findRuntimeLogger(String loggerName) - { - Logger targetLogger = null; - @SuppressWarnings("unchecked") - Enumeration<Logger> loggers = LogManager.getCurrentLoggers(); - while(loggers.hasMoreElements()) - { - targetLogger = loggers.nextElement(); - if (targetLogger.getName().equals(loggerName)) - { - return targetLogger; - } - } - return null; - } - - private List<Element> buildListOfCategoryOrLoggerElements(Document doc) - { - //retrieve the 'category' and 'logger' element nodes - NodeList categoryElements = doc.getElementsByTagName("category"); - NodeList loggerElements = doc.getElementsByTagName("logger"); - - //collect them into a single elements list - List<Element> logElements = new ArrayList<Element>(); - - for (int i = 0; i < categoryElements.getLength(); i++) - { - logElements.add((Element) categoryElements.item(i)); - } - for (int i = 0; i < loggerElements.getLength(); i++) - { - logElements.add((Element) loggerElements.item(i)); - } - return logElements; - } - - private Element getPriorityOrLevelElement(Element categoryOrLogger) throws LoggingFacadeException - { - //retrieve the optional 'priority' or 'level' sub-element value. - //It may not be the only child node, so request by tag name. - NodeList priorityElements = categoryOrLogger.getElementsByTagName("priority"); - NodeList levelElements = categoryOrLogger.getElementsByTagName("level"); - - Element levelElement = null; - if (priorityElements.getLength() != 0) - { - levelElement = (Element) priorityElements.item(0); - } - else if (levelElements.getLength() != 0) - { - levelElement = (Element) levelElements.item(0); - } - else - { - throw new LoggingFacadeException("Configuration " + categoryOrLogger.getNodeName() - + " element contains neither priority nor level child"); - } - return levelElement; - } - - private static class QpidLog4JSaxErrorHandler implements ErrorHandler - { - public void error(SAXParseException e) throws SAXException - { - if(LOGGER != null) - { - LOGGER.warn(constructMessage("Error parsing XML file", e)); - } - else - { - System.err.println(constructMessage("Error parsing XML file", e)); - } - } - - public void fatalError(SAXParseException e) throws SAXException - { - throw new SAXException(constructMessage("Fatal error parsing XML file", e)); - } - - public void warning(SAXParseException e) throws SAXException - { - if(LOGGER != null) - { - LOGGER.warn(constructMessage("Warning parsing XML file", e)); - } - else - { - System.err.println(constructMessage("Warning parsing XML file", e)); - } - } - - private static String constructMessage(final String msg, final SAXParseException ex) - { - return msg + ": Line " + ex.getLineNumber()+" column " +ex.getColumnNumber() + ": " + ex.getMessage(); - } - } -} - |