| /* |
| * 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.chainsaw; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Properties; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| |
| import org.apache.log4j.chainsaw.messages.MessageCenter; |
| import org.apache.log4j.helpers.OptionConverter; |
| import org.apache.log4j.pattern.ClassNamePatternConverter; |
| import org.apache.log4j.pattern.DatePatternConverter; |
| import org.apache.log4j.pattern.FileLocationPatternConverter; |
| import org.apache.log4j.pattern.FullLocationPatternConverter; |
| import org.apache.log4j.pattern.LevelPatternConverter; |
| import org.apache.log4j.pattern.LineLocationPatternConverter; |
| import org.apache.log4j.pattern.LineSeparatorPatternConverter; |
| import org.apache.log4j.pattern.LiteralPatternConverter; |
| import org.apache.log4j.pattern.LoggerPatternConverter; |
| import org.apache.log4j.pattern.LoggingEventPatternConverter; |
| import org.apache.log4j.pattern.MessagePatternConverter; |
| import org.apache.log4j.pattern.MethodLocationPatternConverter; |
| import org.apache.log4j.pattern.NDCPatternConverter; |
| import org.apache.log4j.pattern.PatternParser; |
| import org.apache.log4j.pattern.PropertiesPatternConverter; |
| import org.apache.log4j.pattern.RelativeTimePatternConverter; |
| import org.apache.log4j.pattern.SequenceNumberPatternConverter; |
| import org.apache.log4j.pattern.ThreadPatternConverter; |
| import org.apache.log4j.xml.Log4jEntityResolver; |
| import org.apache.log4j.xml.SAXErrorHandler; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| |
| public class LogFilePatternLayoutBuilder |
| { |
| public static String getLogFormatFromPatternLayout(String patternLayout) { |
| String input = OptionConverter.convertSpecialChars(patternLayout); |
| List converters = new ArrayList(); |
| List fields = new ArrayList(); |
| Map converterRegistry = null; |
| |
| PatternParser.parse(input, converters, fields, converterRegistry, PatternParser.getPatternLayoutRules()); |
| return getFormatFromConverters(converters); |
| } |
| |
| public static String getTimeStampFormat(String patternLayout) { |
| int basicIndex = patternLayout.indexOf("%d"); |
| if (basicIndex < 0) { |
| return null; |
| } |
| |
| int index = patternLayout.indexOf("%d{"); |
| //%d - default |
| if (index < 0) { |
| return "yyyy-MM-dd HH:mm:ss,SSS"; |
| } |
| |
| int length = patternLayout.substring(index).indexOf("}"); |
| String timestampFormat = patternLayout.substring(index + "%d{".length(), index + length); |
| if (timestampFormat.equals("ABSOLUTE")) { |
| return "HH:mm:ss,SSS"; |
| } |
| if (timestampFormat.equals("ISO8601")) { |
| return "yyyy-MM-dd HH:mm:ss,SSS"; |
| } |
| if (timestampFormat.equals("DATE")) { |
| return "dd MMM yyyy HH:mm:ss,SSS"; |
| } |
| return timestampFormat; |
| } |
| |
| private static String getFormatFromConverters(List converters) { |
| StringBuffer buffer = new StringBuffer(); |
| for (Iterator iter = converters.iterator();iter.hasNext();) { |
| LoggingEventPatternConverter converter = (LoggingEventPatternConverter)iter.next(); |
| if (converter instanceof DatePatternConverter) { |
| buffer.append("TIMESTAMP"); |
| } else if (converter instanceof MessagePatternConverter) { |
| buffer.append("MESSAGE"); |
| } else if (converter instanceof LoggerPatternConverter) { |
| buffer.append("LOGGER"); |
| } else if (converter instanceof ClassNamePatternConverter) { |
| buffer.append("CLASS"); |
| } else if (converter instanceof RelativeTimePatternConverter) { |
| buffer.append("PROP(RELATIVETIME)"); |
| } else if (converter instanceof ThreadPatternConverter) { |
| buffer.append("THREAD"); |
| } else if (converter instanceof NDCPatternConverter) { |
| buffer.append("NDC"); |
| } else if (converter instanceof LiteralPatternConverter) { |
| LiteralPatternConverter literal = (LiteralPatternConverter)converter; |
| //format shouldn't normally take a null, but we're getting a literal, so passing in the buffer will work |
| literal.format(null, buffer); |
| } else if (converter instanceof SequenceNumberPatternConverter) { |
| buffer.append("PROP(log4jid)"); |
| } else if (converter instanceof LevelPatternConverter) { |
| buffer.append("LEVEL"); |
| } else if (converter instanceof MethodLocationPatternConverter) { |
| buffer.append("METHOD"); |
| } else if (converter instanceof FullLocationPatternConverter) { |
| buffer.append("PROP(locationInfo)"); |
| } else if (converter instanceof LineLocationPatternConverter) { |
| buffer.append("LINE"); |
| } else if (converter instanceof FileLocationPatternConverter) { |
| buffer.append("FILE"); |
| } else if (converter instanceof PropertiesPatternConverter) { |
| // PropertiesPatternConverter propertiesConverter = (PropertiesPatternConverter) converter; |
| // String option = propertiesConverter.getOption(); |
| // if (option != null && option.length() > 0) { |
| // buffer.append("PROP(" + option + ")"); |
| // } else { |
| buffer.append("PROP(PROPERTIES)"); |
| // } |
| } else if (converter instanceof LineSeparatorPatternConverter) { |
| //done |
| } |
| } |
| return buffer.toString(); |
| } |
| |
| public static Map getAppenderConfiguration(File file) { |
| try { |
| return getXMLFileAppenderConfiguration(file); |
| } catch (IOException e) { |
| //ignore |
| } catch (ParserConfigurationException e) { |
| //ignore |
| } catch (SAXException e) { |
| //ignore |
| } |
| try { |
| return getPropertiesFileAppenderConfiguration(file); |
| } catch (Exception e) { |
| //ignore |
| } |
| //don't return null |
| return new HashMap(); |
| } |
| |
| public static Map getPropertiesFileAppenderConfiguration(File propertyFile) throws IOException, ParserConfigurationException, SAXException { |
| Map result = new HashMap(); |
| String appenderPrefix = "log4j.appender"; |
| Properties props = new Properties(); |
| FileInputStream inputStream = null; |
| try { |
| inputStream = new FileInputStream(propertyFile); |
| props.load(inputStream); |
| Enumeration propertyNames = props.propertyNames(); |
| Map appenders = new HashMap(); |
| while (propertyNames.hasMoreElements()) { |
| String propertyName = propertyNames.nextElement().toString(); |
| if (propertyName.startsWith(appenderPrefix)) { |
| String value = propertyName.substring(appenderPrefix.length() + 1); |
| if (value.indexOf(".") == -1) { |
| //no sub-values - this entry is the appender name & class |
| appenders.put(value, props.getProperty(propertyName).trim()); |
| } |
| } |
| } |
| for (Iterator iter = appenders.entrySet().iterator();iter.hasNext();) { |
| Map.Entry appenderEntry = (Map.Entry)iter.next(); |
| String appenderName = appenderEntry.getKey().toString(); |
| String appenderClassName = appenderEntry.getValue().toString(); |
| if (appenderClassName.toLowerCase(Locale.ENGLISH).endsWith("fileappender")) { |
| String layout = props.getProperty(appenderPrefix + "." + appenderName + ".layout"); |
| if (layout != null && layout.trim().equals("org.apache.log4j.PatternLayout")) { |
| String conversion = props.getProperty(appenderPrefix + "." + appenderName + ".layout.ConversionPattern"); |
| String file = props.getProperty(appenderPrefix + "." + appenderName + ".File"); |
| if (conversion != null && file != null) { |
| Map entry = new HashMap(); |
| entry.put("file", file.trim()); |
| entry.put("conversion", conversion.trim()); |
| result.put(appenderName, entry); |
| } |
| } |
| } |
| } |
| /* |
| example: |
| log4j.appender.R=org.apache.log4j.RollingFileAppender |
| log4j.appender.R.File=${catalina.base}/logs/tomcat.log |
| log4j.appender.R.MaxFileSize=10MB |
| log4j.appender.R.MaxBackupIndex=10 |
| log4j.appender.R.layout=org.apache.log4j.PatternLayout |
| log4j.appender.R.layout.ConversionPattern=%d - %p %t %c - %m%n |
| */ |
| } |
| catch (IOException ioe) { |
| } |
| finally { |
| if (inputStream != null) { |
| inputStream.close(); |
| } |
| } |
| //don't return null |
| return result; |
| } |
| |
| private static Map getXMLFileAppenderConfiguration(File file) throws IOException, ParserConfigurationException, SAXException { |
| InputStream stream = file.toURI().toURL().openStream(); |
| Map result = new HashMap(); |
| try { |
| InputSource src = new InputSource(stream); |
| src.setSystemId(file.toURI().toURL().toString()); |
| DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); |
| DocumentBuilder docBuilder = dbf.newDocumentBuilder(); |
| |
| docBuilder.setErrorHandler(new SAXErrorHandler()); |
| docBuilder.setEntityResolver(new Log4jEntityResolver()); |
| Document doc = docBuilder.parse(src); |
| NodeList appenders = doc.getElementsByTagName("appender"); |
| for (int i = 0; i < appenders.getLength(); i++) { |
| Node appender = appenders.item(i); |
| NamedNodeMap appenderAttributes = appender.getAttributes(); |
| // Class appenderClass = Class.forName(map.getNamedItem("class").getNodeValue()); |
| Node appenderClass = appenderAttributes.getNamedItem("class"); |
| if (appenderAttributes.getNamedItem("name") != null && appenderClass != null && appenderClass.getNodeValue() != null) { |
| //all log4j fileappenders end in fileappender..if a custom fileappender also ends in fileappender and uses the same dom nodes to be loaded, |
| //try to parse the nodes as well |
| if (appenderClass.getNodeValue().toLowerCase(Locale.ENGLISH).endsWith("fileappender")) { |
| String appenderName = appenderAttributes.getNamedItem("name").getNodeValue(); |
| //subclass of FileAppender - add it |
| Map entry = new HashMap(); |
| NodeList appenderChildren = appender.getChildNodes(); |
| for (int j = 0; j < appenderChildren.getLength(); j++) { |
| Node appenderChild = appenderChildren.item(j); |
| if (appenderChild.getNodeName().equals("param") && appenderChild.hasAttributes()) { |
| Node fileNameNode = appenderChild.getAttributes().getNamedItem("name"); |
| if (fileNameNode != null && fileNameNode.getNodeValue().equalsIgnoreCase("file")) { |
| Node fileValueNode = appenderChild.getAttributes().getNamedItem("value"); |
| if (fileValueNode != null) { |
| entry.put("file", fileValueNode.getNodeValue()); |
| } |
| } |
| } |
| if (appenderChild.getNodeName().equalsIgnoreCase("layout") && appenderChild.hasAttributes()) { |
| NamedNodeMap layoutAttributes = appenderChild.getAttributes(); |
| Node layoutNode = layoutAttributes.getNamedItem("class"); |
| if (layoutNode != null && layoutNode.getNodeValue() != null && layoutNode.getNodeValue().equalsIgnoreCase("org.apache.log4j.PatternLayout")) { |
| NodeList layoutChildren = appenderChild.getChildNodes(); |
| for (int k = 0; k < layoutChildren.getLength(); k++) { |
| Node layoutChild = layoutChildren.item(k); |
| if (layoutChild.getNodeName().equals("param") && layoutChild.hasAttributes()) { |
| Node layoutName = layoutChild.getAttributes().getNamedItem("name"); |
| if (layoutName != null && layoutName.getNodeValue() != null && layoutName.getNodeValue().equalsIgnoreCase("conversionpattern")) { |
| Node conversionValue = layoutChild.getAttributes().getNamedItem("value"); |
| if (conversionValue != null) { |
| entry.put("conversion", conversionValue.getNodeValue()); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| result.put(appenderName, entry); |
| } |
| } |
| } |
| } finally { |
| stream.close(); |
| } |
| MessageCenter.getInstance().getLogger().info("getXMLFileAppenderConfiguration for file: " + file + ", result: " + result); |
| return result; |
| } |
| } |