summaryrefslogtreecommitdiff
path: root/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java')
-rw-r--r--trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java819
1 files changed, 0 insertions, 819 deletions
diff --git a/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java b/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java
deleted file mode 100644
index c36eeb5016..0000000000
--- a/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java
+++ /dev/null
@@ -1,819 +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.management;
-
-import static org.apache.log4j.xml.QpidLog4JConfigurator.LOCK;
-
-import java.io.File;
-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;
-
-import org.apache.qpid.management.common.mbeans.LoggingManagement;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.util.FileUtils;
-
-import org.apache.log4j.Level;
-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.QpidLog4JSaxErrorHandler;
-import org.apache.log4j.xml.QpidLog4JConfigurator.IllegalLoggerLevelException;
-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.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-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.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-
-/** MBean class for BrokerLoggingManagerMBean. It implements all the management features exposed for managing logging. */
-@MBeanDescription("Logging Management Interface")
-public class LoggingManagementMBean extends AMQManagedObject implements LoggingManagement
-{
-
- private static final Logger _logger = Logger.getLogger(LoggingManagementMBean.class);
- private String _log4jConfigFileName;
- private int _log4jLogWatchInterval;
- private static final String INHERITED = "INHERITED";
- private static final String[] LEVELS = new String[]{Level.ALL.toString(), Level.TRACE.toString(),
- Level.DEBUG.toString(), Level.INFO.toString(),
- Level.WARN.toString(), Level.ERROR.toString(),
- Level.FATAL.toString(),Level.OFF.toString(),
- INHERITED};
- static TabularType _loggerLevelTabularType;
- static CompositeType _loggerLevelCompositeType;
-
- static
- {
- try
- {
- OpenType[] loggerLevelItemTypes = new OpenType[]{SimpleType.STRING, SimpleType.STRING};
-
- _loggerLevelCompositeType = new CompositeType("LoggerLevelList", "Logger Level Data",
- COMPOSITE_ITEM_NAMES, COMPOSITE_ITEM_DESCRIPTIONS, loggerLevelItemTypes);
-
- _loggerLevelTabularType = new TabularType("LoggerLevel", "List of loggers with levels",
- _loggerLevelCompositeType, TABULAR_UNIQUE_INDEX);
- }
- catch (OpenDataException e)
- {
- _logger.error("Tabular data setup for viewing logger levels was incorrect.");
- _loggerLevelTabularType = null;
- }
- }
-
- public LoggingManagementMBean(String log4jConfigFileName, int log4jLogWatchInterval) throws JMException
- {
- super(LoggingManagement.class, LoggingManagement.TYPE, LoggingManagement.VERSION);
- _log4jConfigFileName = log4jConfigFileName;
- _log4jLogWatchInterval = log4jLogWatchInterval;
- }
-
- public String getObjectInstanceName()
- {
- return LoggingManagement.TYPE;
- }
-
- public Integer getLog4jLogWatchInterval()
- {
- return _log4jLogWatchInterval;
- }
-
- public String[] getAvailableLoggerLevels()
- {
- return LEVELS;
- }
- @SuppressWarnings("unchecked")
- public synchronized boolean setRuntimeLoggerLevel(String logger, String level)
- {
- //check specified level is valid
- Level newLevel;
- try
- {
- newLevel = getLevel(level);
- }
- catch (Exception e)
- {
- return false;
- }
-
- //check specified logger exists
- Enumeration loggers = LogManager.getCurrentLoggers();
- Boolean loggerExists = false;
-
- while(loggers.hasMoreElements())
- {
- Logger log = (Logger) loggers.nextElement();
- if (log.getName().equals(logger))
- {
- loggerExists = true;
- break;
- }
- }
-
- if(!loggerExists)
- {
- return false;
- }
-
- //set the logger to the new level
- _logger.info("Setting level to " + level + " for logger: " + logger);
-
- Logger log = Logger.getLogger(logger);
- log.setLevel(newLevel);
-
- return true;
- }
-
- @SuppressWarnings("unchecked")
- public synchronized TabularData viewEffectiveRuntimeLoggerLevels()
- {
- if (_loggerLevelTabularType == null)
- {
- _logger.warn("TabluarData type not set up correctly");
- return null;
- }
-
- _logger.info("Getting levels for currently active log4j loggers");
-
- Enumeration loggers = LogManager.getCurrentLoggers();
-
- TabularData loggerLevelList = new TabularDataSupport(_loggerLevelTabularType);
-
- Logger logger;
- String loggerName;
- String level;
-
- try
- {
- while(loggers.hasMoreElements()){
- logger = (Logger) loggers.nextElement();
-
- loggerName = logger.getName();
- level = logger.getEffectiveLevel().toString();
-
- Object[] itemData = {loggerName, level};
- 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;
- }
-
- return loggerLevelList;
-
- }
-
- public synchronized String getRuntimeRootLoggerLevel()
- {
- Logger rootLogger = Logger.getRootLogger();
-
- return rootLogger.getLevel().toString();
- }
-
- public synchronized boolean setRuntimeRootLoggerLevel(String level)
- {
- Level newLevel;
- try
- {
- newLevel = getLevel(level);
- }
- catch (Exception e)
- {
- return false;
- }
-
- if(newLevel == null)
- {
- //A null Level reference implies inheritance. Setting the runtime RootLogger
- //to null is catastrophic (and prevented by Log4J at startup and runtime anyway).
- return false;
- }
-
- _logger.info("Setting RootLogger level to " + level);
-
- Logger log = Logger.getRootLogger();
- log.setLevel(newLevel);
-
- return true;
- }
-
- //method to convert from a string to a log4j Level, throws exception if the given value is invalid
- private Level getLevel(String level) throws Exception
- {
- if("null".equalsIgnoreCase(level) || INHERITED.equalsIgnoreCase(level))
- {
- //the string "null" or "inherited" signals to inherit from a parent logger,
- //using a null Level reference for the logger.
- return null;
- }
-
- Level newLevel = Level.toLevel(level);
-
- //above Level.toLevel call returns a DEBUG Level if the request fails. Check the result.
- if (newLevel.equals(Level.DEBUG) && !(level.equalsIgnoreCase("debug")))
- {
- //received DEBUG but we did not ask for it, the Level request failed.
- throw new Exception("Invalid level name");
- }
-
- return newLevel;
- }
-
- //method to parse the XML configuration file, validating it in the process, and returning a DOM Document of the content.
- private static synchronized Document parseConfigFile(String fileName) throws IOException
- {
- try
- {
- LOCK.lock();
-
- //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);
- //recommended that MBeans should use java.* and javax.* exceptions only
- throw new IOException("Unable to parse the log4j XML file due to possible configuration error: " + e.getMessage());
- }
- catch (SAXException e)
- {
- _logger.warn("The specified log4j XML file is invalid: " + e);
- //recommended that MBeans should use standard java.* and javax.* exceptions only
- throw new IOException("The specified log4j XML file is invalid: " + e.getMessage());
- }
- 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.getMessage());
- }
-
- return doc;
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
-
- private static synchronized boolean writeUpdatedConfigFile(String log4jConfigFileName, Document doc) throws IOException
- {
- try
- {
- LOCK.lock();
-
- 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;
- try
- {
- transformer = TransformerFactory.newInstance().newTransformer();
- }
- catch (Exception e)
- {
- _logger.warn("Could not create an XML transformer: " +e);
- return false;
- }
-
- 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.getPath() + r.nextInt() + ".tmp");
- }
- while(tmp.exists());
-
- tmp.deleteOnExit();
-
- try
- {
- StreamResult result = new StreamResult(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");
- }
-
- return true;
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
-
- /* 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 static synchronized Map<String,String> retrieveConfigFileLoggersLevels(String fileName) throws IOException
- {
- try
- {
- LOCK.lock();
-
- Document doc = parseConfigFile(fileName);
-
- HashMap<String,String> loggerLevelList = new HashMap<String,String>();
-
- //retrieve the 'category' element nodes
- NodeList categoryElements = doc.getElementsByTagName("category");
-
- String categoryName;
- String priority = null;
-
- for (int i = 0; i < categoryElements.getLength(); i++)
- {
- Element categoryElement = (Element) categoryElements.item(i);
- categoryName = categoryElement.getAttribute("name");
-
- //retrieve the category's mandatory 'priority' or 'level' element's value.
- //It may not be the only child node, so request by tag name.
- NodeList priorityElements = categoryElement.getElementsByTagName("priority");
- NodeList levelElements = categoryElement.getElementsByTagName("level");
-
- if (priorityElements.getLength() != 0)
- {
- Element priorityElement = (Element) priorityElements.item(0);
- priority = priorityElement.getAttribute("value");
- }
- else if (levelElements.getLength() != 0)
- {
- Element levelElement = (Element) levelElements.item(0);
- priority = levelElement.getAttribute("value");
- }
- else
- {
- //there is no exiting priority or level to view, move onto next category/logger
- continue;
- }
-
- loggerLevelList.put(categoryName, priority);
- }
-
- //retrieve the 'logger' element nodes
- NodeList loggerElements = doc.getElementsByTagName("logger");
-
- String loggerName;
- String level;
-
- for (int i = 0; i < loggerElements.getLength(); i++)
- {
- Element loggerElement = (Element) loggerElements.item(i);
- loggerName = loggerElement.getAttribute("name");
-
- //retrieve the logger's mandatory 'level' element's value
- //It may not be the only child node, so request by tag name.
- NodeList levelElements = loggerElement.getElementsByTagName("level");
-
- Element levelElement = (Element) levelElements.item(0);
- level = levelElement.getAttribute("value");
-
- loggerLevelList.put(loggerName, level);
- }
-
- return loggerLevelList;
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
- public synchronized TabularData viewConfigFileLoggerLevels() throws IOException
- {
- try
- {
- LOCK.lock();
-
- 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.toUpperCase()};
- 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;
- }
- }
-
- return loggerLevelList;
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
- public synchronized boolean setConfigFileLoggerLevel(String logger, String level) throws IOException
- {
- try
- {
- LOCK.lock();
-
- //check that the specified level is a valid log4j Level
- try
- {
- getLevel(level);
- }
- catch (Exception e)
- {
- //it isnt a valid level
- return false;
- }
-
- _logger.info("Setting level to " + level + " for logger '" + logger
- + "' in log4j xml configuration file: " + _log4jConfigFileName);
-
- Document doc = parseConfigFile(_log4jConfigFileName);
-
- //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));
- }
-
- //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)
- {
- //no loggers/categories with given name found, does not exist to update
- _logger.warn("Specified logger does not exist in the configuration file: " +logger);
- return false;
- }
-
- //retrieve the optional 'priority' or 'level' sub-element value.
- //It may not be the only child node, so request by tag name.
- NodeList priorityElements = logElement.getElementsByTagName("priority");
- NodeList levelElements = logElement.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
- {
- //there is no exiting priority or level element to update
- return false;
- }
-
- //update the element with the new level/priority
- levelElement.setAttribute("value", level.toLowerCase());
-
- //output the new file
- return writeUpdatedConfigFile(_log4jConfigFileName, doc);
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
-
- /* 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 static synchronized String retrieveConfigFileRootLoggerLevel(String fileName) throws IOException
- {
- try
- {
- LOCK.lock();
-
- 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);
-
- //retrieve the optional 'priority' or 'level' element value.
- //It may not be the only child node, so request by tag name.
- NodeList priorityElements = rootElement.getElementsByTagName("priority");
- NodeList levelElements = rootElement.getElementsByTagName("level");
- String priority = null;
-
- if (priorityElements.getLength() != 0)
- {
- Element priorityElement = (Element) priorityElements.item(0);
- priority = priorityElement.getAttribute("value");
- }
- else if(levelElements.getLength() != 0)
- {
- Element levelElement = (Element) levelElements.item(0);
- priority = levelElement.getAttribute("value");
- }
-
- if(priority != null)
- {
- return priority;
- }
- else
- {
- return "N/A";
- }
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
- public synchronized String getConfigFileRootLoggerLevel() throws IOException
- {
- return retrieveConfigFileRootLoggerLevel(_log4jConfigFileName).toUpperCase();
- }
-
- public synchronized boolean setConfigFileRootLoggerLevel(String level) throws IOException
- {
- try
- {
- LOCK.lock();
-
- //check that the specified level is a valid log4j Level
- try
- {
- Level newLevel = getLevel(level);
- if(newLevel == null)
- {
- //A null Level reference implies inheritance. Setting the config file RootLogger
- //to "null" or "inherited" just ensures it defaults to DEBUG at startup as Log4J
- //prevents this catastrophic situation at startup and runtime anyway.
- return false;
- }
- }
- catch (Exception e)
- {
- //it isnt a valid level
- return false;
- }
-
- _logger.info("Setting level to " + level + " for the Root logger in " +
- "log4j xml configuration file: " + _log4jConfigFileName);
-
- Document doc = parseConfigFile(_log4jConfigFileName);
-
- //retrieve the optional 'root' element node
- NodeList rootElements = doc.getElementsByTagName("root");
-
- if (rootElements.getLength() == 0)
- {
- return false;
- }
-
- Element rootElement = (Element) rootElements.item(0);
-
- //retrieve the optional 'priority' or 'level' sub-element value.
- //It may not be the only child node, so request by tag name.
- NodeList priorityElements = rootElement.getElementsByTagName("priority");
- NodeList levelElements = rootElement.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
- {
- //there is no exiting priority/level to update
- return false;
- }
-
- //update the element with the new level/priority
- levelElement.setAttribute("value", level);
-
- //output the new file
- return writeUpdatedConfigFile(_log4jConfigFileName, doc);
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
- public synchronized void reloadConfigFile() throws IOException
- {
- try
- {
- LOCK.lock();
-
- QpidLog4JConfigurator.configure(_log4jConfigFileName);
- _logger.info("Applied log4j configuration from: " + _log4jConfigFileName);
- }
- catch (IllegalLoggerLevelException e)
- {
- _logger.warn("The log4j configuration reload request was aborted: " + e);
- //recommended that MBeans should use standard java.* and javax.* exceptions only
- throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage());
- }
- catch (ParserConfigurationException e)
- {
- _logger.warn("The log4j configuration reload request was aborted: " + e);
- throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage());
- }
- catch (SAXException e)
- {
- _logger.warn("The log4j configuration reload request was aborted: " + e);
- //recommended that MBeans should use standard java.* and javax.* exceptions only
- throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage());
- }
- catch (IOException e)
- {
- _logger.warn("The log4j configuration reload request was aborted: " + e);
- throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage());
- }
- finally
- {
- LOCK.unlock();
- }
- }
-}