X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=srcjar_unused%2Forg%2Fapache%2Flog4j%2Fpattern%2FPatternParser.java;fp=srcjar_unused%2Forg%2Fapache%2Flog4j%2Fpattern%2FPatternParser.java;h=901b0fefebf0b4c00bf0d239d4d85dad86a99d3c;hb=4f30214e8098748469c6a4269ac2ed6c5750e4b0;hp=0000000000000000000000000000000000000000;hpb=9dabc02511e3a334a5749a504f57f69d6c9017bd;p=jalview.git diff --git a/srcjar_unused/org/apache/log4j/pattern/PatternParser.java b/srcjar_unused/org/apache/log4j/pattern/PatternParser.java new file mode 100644 index 0000000..901b0fe --- /dev/null +++ b/srcjar_unused/org/apache/log4j/pattern/PatternParser.java @@ -0,0 +1,701 @@ +/* + * 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.pattern; + +import org.apache.log4j.helpers.Loader; +import org.apache.log4j.helpers.LogLog; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +// Contributors: Nelson Minar <(nelson@monkey.org> +// Igor E. Poteryaev +// Reinhard Deschler + +/** + * Most of the work of the {@link org.apache.log4j.EnhancedPatternLayout} class + * is delegated to the PatternParser class. + *

It is this class that parses conversion patterns and creates + * a chained list of {@link PatternConverter PatternConverters}. + * + * @author James P. Cakalic + * @author Ceki Gülcü + * @author Anders Kristensen + * @author Paul Smith + * @author Curt Arnold + * +*/ +public final class PatternParser { + /** + * Escape character for format specifier. + */ + private static final char ESCAPE_CHAR = '%'; + + /** + * Literal state. + */ + private static final int LITERAL_STATE = 0; + + /** + * In converter name state. + */ + private static final int CONVERTER_STATE = 1; + + /** + * Dot state. + */ + private static final int DOT_STATE = 3; + + /** + * Min state. + */ + private static final int MIN_STATE = 4; + + /** + * Max state. + */ + private static final int MAX_STATE = 5; + + /** + * Standard format specifiers for EnhancedPatternLayout. + */ + private static final Map PATTERN_LAYOUT_RULES; + + /** + * Standard format specifiers for rolling file appenders. + */ + private static final Map FILENAME_PATTERN_RULES; + + static { + // We set the global rules in the static initializer of PatternParser class + Map rules = new HashMap(17); + rules.put("c", LoggerPatternConverter.class); + rules.put("logger", LoggerPatternConverter.class); + + rules.put("C", ClassNamePatternConverter.class); + rules.put("class", ClassNamePatternConverter.class); + + rules.put("d", DatePatternConverter.class); + rules.put("date", DatePatternConverter.class); + + rules.put("F", FileLocationPatternConverter.class); + rules.put("file", FileLocationPatternConverter.class); + + rules.put("l", FullLocationPatternConverter.class); + + rules.put("L", LineLocationPatternConverter.class); + rules.put("line", LineLocationPatternConverter.class); + + rules.put("m", MessagePatternConverter.class); + rules.put("message", MessagePatternConverter.class); + + rules.put("n", LineSeparatorPatternConverter.class); + + rules.put("M", MethodLocationPatternConverter.class); + rules.put("method", MethodLocationPatternConverter.class); + + rules.put("p", LevelPatternConverter.class); + rules.put("level", LevelPatternConverter.class); + + rules.put("r", RelativeTimePatternConverter.class); + rules.put("relative", RelativeTimePatternConverter.class); + + rules.put("t", ThreadPatternConverter.class); + rules.put("thread", ThreadPatternConverter.class); + + rules.put("x", NDCPatternConverter.class); + rules.put("ndc", NDCPatternConverter.class); + + rules.put("X", PropertiesPatternConverter.class); + rules.put("properties", PropertiesPatternConverter.class); + + rules.put("sn", SequenceNumberPatternConverter.class); + rules.put("sequenceNumber", SequenceNumberPatternConverter.class); + + rules.put("throwable", ThrowableInformationPatternConverter.class); + PATTERN_LAYOUT_RULES = new ReadOnlyMap(rules); + + Map fnameRules = new HashMap(4); + fnameRules.put("d", FileDatePatternConverter.class); + fnameRules.put("date", FileDatePatternConverter.class); + fnameRules.put("i", IntegerPatternConverter.class); + fnameRules.put("index", IntegerPatternConverter.class); + + FILENAME_PATTERN_RULES = new ReadOnlyMap(fnameRules); + } + + /** + * Private constructor. + */ + private PatternParser() { + } + + /** + * Get standard format specifiers for EnhancedPatternLayout. + * @return read-only map of format converter classes keyed by format specifier strings. + */ + public static Map getPatternLayoutRules() { + return PATTERN_LAYOUT_RULES; + } + + /** + * Get standard format specifiers for rolling file appender file specification. + * @return read-only map of format converter classes keyed by format specifier strings. + */ + public static Map getFileNamePatternRules() { + return FILENAME_PATTERN_RULES; + } + + /** Extract the converter identifier found at position i. + * + * After this function returns, the variable i will point to the + * first char after the end of the converter identifier. + * + * If i points to a char which is not a character acceptable at the + * start of a unicode identifier, the value null is returned. + * + * @param lastChar last processed character. + * @param pattern format string. + * @param i current index into pattern format. + * @param convBuf buffer to receive conversion specifier. + * @param currentLiteral literal to be output in case format specifier in unrecognized. + * @return position in pattern after converter. + */ + private static int extractConverter( + char lastChar, final String pattern, int i, final StringBuffer convBuf, + final StringBuffer currentLiteral) { + convBuf.setLength(0); + + // When this method is called, lastChar points to the first character of the + // conversion word. For example: + // For "%hello" lastChar = 'h' + // For "%-5hello" lastChar = 'h' + //System.out.println("lastchar is "+lastChar); + if (!Character.isUnicodeIdentifierStart(lastChar)) { + return i; + } + + convBuf.append(lastChar); + + while ( + (i < pattern.length()) + && Character.isUnicodeIdentifierPart(pattern.charAt(i))) { + convBuf.append(pattern.charAt(i)); + currentLiteral.append(pattern.charAt(i)); + + //System.out.println("conv buffer is now ["+convBuf+"]."); + i++; + } + + return i; + } + + /** + * Extract options. + * @param pattern conversion pattern. + * @param i start of options. + * @param options array to receive extracted options + * @return position in pattern after options. + */ + private static int extractOptions(String pattern, int i, List options) { + while ((i < pattern.length()) && (pattern.charAt(i) == '{')) { + int end = pattern.indexOf('}', i); + + if (end == -1) { + break; + } + + String r = pattern.substring(i + 1, end); + options.add(r); + i = end + 1; + } + + return i; + } + + /** + * Parse a format specifier. + * @param pattern pattern to parse. + * @param patternConverters list to receive pattern converters. + * @param formattingInfos list to receive field specifiers corresponding to pattern converters. + * @param converterRegistry map of user-supported pattern converters keyed by format specifier, may be null. + * @param rules map of stock pattern converters keyed by format specifier. + */ + public static void parse( + final String pattern, final List patternConverters, + final List formattingInfos, final Map converterRegistry, final Map rules) { + if (pattern == null) { + throw new NullPointerException("pattern"); + } + + StringBuffer currentLiteral = new StringBuffer(32); + + int patternLength = pattern.length(); + int state = LITERAL_STATE; + char c; + int i = 0; + FormattingInfo formattingInfo = FormattingInfo.getDefault(); + + while (i < patternLength) { + c = pattern.charAt(i++); + + switch (state) { + case LITERAL_STATE: + + // In literal state, the last char is always a literal. + if (i == patternLength) { + currentLiteral.append(c); + + continue; + } + + if (c == ESCAPE_CHAR) { + // peek at the next char. + switch (pattern.charAt(i)) { + case ESCAPE_CHAR: + currentLiteral.append(c); + i++; // move pointer + + break; + + default: + + if (currentLiteral.length() != 0) { + patternConverters.add( + new LiteralPatternConverter(currentLiteral.toString())); + formattingInfos.add(FormattingInfo.getDefault()); + } + + currentLiteral.setLength(0); + currentLiteral.append(c); // append % + state = CONVERTER_STATE; + formattingInfo = FormattingInfo.getDefault(); + } + } else { + currentLiteral.append(c); + } + + break; + + case CONVERTER_STATE: + currentLiteral.append(c); + + switch (c) { + case '-': + formattingInfo = + new FormattingInfo( + true, + formattingInfo.isRightTruncated(), + formattingInfo.getMinLength(), + formattingInfo.getMaxLength()); + break; + + case '!': + formattingInfo = + new FormattingInfo( + formattingInfo.isLeftAligned(), + true, + formattingInfo.getMinLength(), + formattingInfo.getMaxLength()); + break; + + + case '.': + state = DOT_STATE; + + break; + + default: + + if ((c >= '0') && (c <= '9')) { + formattingInfo = + new FormattingInfo( + formattingInfo.isLeftAligned(), + formattingInfo.isRightTruncated(), + c - '0', + formattingInfo.getMaxLength()); + state = MIN_STATE; + } else { + i = finalizeConverter( + c, pattern, i, currentLiteral, formattingInfo, + converterRegistry, rules, patternConverters, formattingInfos); + + // Next pattern is assumed to be a literal. + state = LITERAL_STATE; + formattingInfo = FormattingInfo.getDefault(); + currentLiteral.setLength(0); + } + } // switch + + break; + + case MIN_STATE: + currentLiteral.append(c); + + if ((c >= '0') && (c <= '9')) { + formattingInfo = + new FormattingInfo( + formattingInfo.isLeftAligned(), + formattingInfo.isRightTruncated(), + (formattingInfo.getMinLength() * 10) + (c - '0'), + formattingInfo.getMaxLength()); + } else if (c == '.') { + state = DOT_STATE; + } else { + i = finalizeConverter( + c, pattern, i, currentLiteral, formattingInfo, + converterRegistry, rules, patternConverters, formattingInfos); + state = LITERAL_STATE; + formattingInfo = FormattingInfo.getDefault(); + currentLiteral.setLength(0); + } + + break; + + case DOT_STATE: + currentLiteral.append(c); + + if ((c >= '0') && (c <= '9')) { + formattingInfo = + new FormattingInfo( + formattingInfo.isLeftAligned(), + formattingInfo.isRightTruncated(), + formattingInfo.getMinLength(), + c - '0'); + state = MAX_STATE; + } else { + LogLog.error( + "Error occured in position " + i + + ".\n Was expecting digit, instead got char \"" + c + "\"."); + + state = LITERAL_STATE; + } + + break; + + case MAX_STATE: + currentLiteral.append(c); + + if ((c >= '0') && (c <= '9')) { + formattingInfo = + new FormattingInfo( + formattingInfo.isLeftAligned(), + formattingInfo.isRightTruncated(), + formattingInfo.getMinLength(), + (formattingInfo.getMaxLength() * 10) + (c - '0')); + } else { + i = finalizeConverter( + c, pattern, i, currentLiteral, formattingInfo, + converterRegistry, rules, patternConverters, formattingInfos); + state = LITERAL_STATE; + formattingInfo = FormattingInfo.getDefault(); + currentLiteral.setLength(0); + } + + break; + } // switch + } + + // while + if (currentLiteral.length() != 0) { + patternConverters.add( + new LiteralPatternConverter(currentLiteral.toString())); + formattingInfos.add(FormattingInfo.getDefault()); + } + } + + /** + * Creates a new PatternConverter. + * + * + * @param converterId converterId. + * @param currentLiteral literal to be used if converter is unrecognized or following converter + * if converterId contains extra characters. + * @param converterRegistry map of user-supported pattern converters keyed by format specifier, may be null. + * @param rules map of stock pattern converters keyed by format specifier. + * @param options converter options. + * @return converter or null. + */ + private static PatternConverter createConverter( + final String converterId, final StringBuffer currentLiteral, + final Map converterRegistry, final Map rules, final List options) { + String converterName = converterId; + Object converterObj = null; + + for (int i = converterId.length(); (i > 0) && (converterObj == null); + i--) { + converterName = converterName.substring(0, i); + + if (converterRegistry != null) { + converterObj = converterRegistry.get(converterName); + } + + if ((converterObj == null) && (rules != null)) { + converterObj = rules.get(converterName); + } + } + + if (converterObj == null) { + LogLog.error("Unrecognized format specifier [" + converterId + "]"); + + return null; + } + + Class converterClass = null; + + if (converterObj instanceof Class) { + converterClass = (Class) converterObj; + } else { + if (converterObj instanceof String) { + try { + converterClass = Loader.loadClass((String) converterObj); + } catch (ClassNotFoundException ex) { + LogLog.warn( + "Class for conversion pattern %" + converterName + " not found", + ex); + + return null; + } + } else { + LogLog.warn( + "Bad map entry for conversion pattern %" + converterName + "."); + + return null; + } + } + + try { + Method factory = + converterClass.getMethod( + "newInstance", + new Class[] { + Class.forName("[Ljava.lang.String;") + }); + String[] optionsArray = new String[options.size()]; + optionsArray = (String[]) options.toArray(optionsArray); + + Object newObj = + factory.invoke(null, new Object[] { optionsArray }); + + if (newObj instanceof PatternConverter) { + currentLiteral.delete( + 0, + currentLiteral.length() + - (converterId.length() - converterName.length())); + + return (PatternConverter) newObj; + } else { + LogLog.warn( + "Class " + converterClass.getName() + + " does not extend PatternConverter."); + } + } catch (Exception ex) { + LogLog.error("Error creating converter for " + converterId, ex); + + try { + // + // try default constructor + PatternConverter pc = (PatternConverter) converterClass.newInstance(); + currentLiteral.delete( + 0, + currentLiteral.length() + - (converterId.length() - converterName.length())); + + return pc; + } catch (Exception ex2) { + LogLog.error("Error creating converter for " + converterId, ex2); + } + } + + return null; + } + + /** + * Processes a format specifier sequence. + * + * @param c initial character of format specifier. + * @param pattern conversion pattern + * @param i current position in conversion pattern. + * @param currentLiteral current literal. + * @param formattingInfo current field specifier. + * @param converterRegistry map of user-provided pattern converters keyed by format specifier, may be null. + * @param rules map of stock pattern converters keyed by format specifier. + * @param patternConverters list to receive parsed pattern converter. + * @param formattingInfos list to receive corresponding field specifier. + * @return position after format specifier sequence. + */ + private static int finalizeConverter( + char c, String pattern, int i, + final StringBuffer currentLiteral, final FormattingInfo formattingInfo, + final Map converterRegistry, final Map rules, final List patternConverters, + final List formattingInfos) { + StringBuffer convBuf = new StringBuffer(); + i = extractConverter(c, pattern, i, convBuf, currentLiteral); + + String converterId = convBuf.toString(); + + List options = new ArrayList(); + i = extractOptions(pattern, i, options); + + PatternConverter pc = + createConverter( + converterId, currentLiteral, converterRegistry, rules, options); + + if (pc == null) { + StringBuffer msg; + + if ((converterId == null) || (converterId.length() == 0)) { + msg = + new StringBuffer("Empty conversion specifier starting at position "); + } else { + msg = new StringBuffer("Unrecognized conversion specifier ["); + msg.append(converterId); + msg.append("] starting at position "); + } + + msg.append(Integer.toString(i)); + msg.append(" in conversion pattern."); + + LogLog.error(msg.toString()); + + patternConverters.add( + new LiteralPatternConverter(currentLiteral.toString())); + formattingInfos.add(FormattingInfo.getDefault()); + } else { + patternConverters.add(pc); + formattingInfos.add(formattingInfo); + + if (currentLiteral.length() > 0) { + patternConverters.add( + new LiteralPatternConverter(currentLiteral.toString())); + formattingInfos.add(FormattingInfo.getDefault()); + } + } + + currentLiteral.setLength(0); + + return i; + } + + /** + * The class wraps another Map but throws exceptions on any attempt to modify the map. + */ + private static class ReadOnlyMap implements Map { + /** + * Wrapped map. + */ + private final Map map; + + /** + * Constructor + * @param src source map. + */ + public ReadOnlyMap(Map src) { + map = src; + } + + /** + * {@inheritDoc} + */ + public void clear() { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public boolean containsKey(Object key) { + return map.containsKey(key); + } + + /** + * {@inheritDoc} + */ + public boolean containsValue(Object value) { + return map.containsValue(value); + } + + /** + * {@inheritDoc} + */ + public Set entrySet() { + return map.entrySet(); + } + + /** + * {@inheritDoc} + */ + public Object get(Object key) { + return map.get(key); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return map.isEmpty(); + } + + /** + * {@inheritDoc} + */ + public Set keySet() { + return map.keySet(); + } + + /** + * {@inheritDoc} + */ + public Object put(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void putAll(Map t) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public Object remove(Object key) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public int size() { + return map.size(); + } + + /** + * {@inheritDoc} + */ + public Collection values() { + return map.values(); + } + } +}