JAL-3541 selectively merged build.gradle and gradle.properties
[jalview.git] / srcjar_unused / org / apache / log4j / helpers / PatternParser.java
diff --git a/srcjar_unused/org/apache/log4j/helpers/PatternParser.java b/srcjar_unused/org/apache/log4j/helpers/PatternParser.java
new file mode 100644 (file)
index 0000000..0cd997a
--- /dev/null
@@ -0,0 +1,572 @@
+/*
+ * 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.helpers;
+
+import org.apache.log4j.Layout;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.spi.LocationInfo;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+import java.util.Arrays;
+
+// Contributors:   Nelson Minar <(nelson@monkey.org>
+//                 Igor E. Poteryaev <jah@mail.ru>
+//                 Reinhard Deschler <reinhard.deschler@web.de>
+
+/**
+   Most of the work of the {@link org.apache.log4j.PatternLayout} class
+   is delegated to the PatternParser class.
+
+   <p>It is this class that parses conversion patterns and creates
+   a chained list of {@link OptionConverter OptionConverters}.
+
+   @author <a href=mailto:"cakalijp@Maritz.com">James P. Cakalic</a>
+   @author Ceki G&uuml;lc&uuml;
+   @author Anders Kristensen
+
+   @since 0.8.2
+*/
+public class PatternParser {
+
+  private static final char ESCAPE_CHAR = '%';
+
+  private static final int LITERAL_STATE = 0;
+  private static final int CONVERTER_STATE = 1;
+  private static final int DOT_STATE = 3;
+  private static final int MIN_STATE = 4;
+  private static final int MAX_STATE = 5;
+
+  static final int FULL_LOCATION_CONVERTER = 1000;
+  static final int METHOD_LOCATION_CONVERTER = 1001;
+  static final int CLASS_LOCATION_CONVERTER = 1002;
+  static final int LINE_LOCATION_CONVERTER = 1003;
+  static final int FILE_LOCATION_CONVERTER = 1004;
+
+  static final int RELATIVE_TIME_CONVERTER = 2000;
+  static final int THREAD_CONVERTER = 2001;
+  static final int LEVEL_CONVERTER = 2002;
+  static final int NDC_CONVERTER = 2003;
+  static final int MESSAGE_CONVERTER = 2004;
+
+  int state;
+  protected StringBuffer currentLiteral = new StringBuffer(32);
+  protected int patternLength;
+  protected int i;
+  PatternConverter head;
+  PatternConverter tail;
+  protected FormattingInfo formattingInfo = new FormattingInfo();
+  protected String pattern;
+
+  public
+  PatternParser(String pattern) {
+    this.pattern = pattern;
+    patternLength =  pattern.length();
+    state = LITERAL_STATE;
+  }
+
+  private
+  void  addToList(PatternConverter pc) {
+    if(head == null) {
+      head = tail = pc;
+    } else {
+      tail.next = pc;
+      tail = pc;
+    }
+  }
+
+  protected
+  String extractOption() {
+    if((i < patternLength) && (pattern.charAt(i) == '{')) {
+      int end = pattern.indexOf('}', i);
+      if (end > i) {
+       String r = pattern.substring(i + 1, end);
+       i = end+1;
+       return r;
+      }
+    }
+    return null;
+  }
+
+
+  /**
+     The option is expected to be in decimal and positive. In case of
+     error, zero is returned.  */
+  protected
+  int extractPrecisionOption() {
+    String opt = extractOption();
+    int r = 0;
+    if(opt != null) {
+      try {
+       r = Integer.parseInt(opt);
+       if(r <= 0) {
+           LogLog.error(
+               "Precision option (" + opt + ") isn't a positive integer.");
+           r = 0;
+       }
+      }
+      catch (NumberFormatException e) {
+       LogLog.error("Category option \""+opt+"\" not a decimal integer.", e);
+      }
+    }
+    return r;
+  }
+
+  public
+  PatternConverter parse() {
+    char c;
+    i = 0;
+    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;
+          case 'n':
+            currentLiteral.append(Layout.LINE_SEP);
+            i++; // move pointer
+            break;
+          default:
+            if(currentLiteral.length() != 0) {
+              addToList(new LiteralPatternConverter(
+                                                  currentLiteral.toString()));
+              //LogLog.debug("Parsed LITERAL converter: \""
+              //           +currentLiteral+"\".");
+            }
+            currentLiteral.setLength(0);
+            currentLiteral.append(c); // append %
+            state = CONVERTER_STATE;
+            formattingInfo.reset();
+          }
+        }
+        else {
+          currentLiteral.append(c);
+        }
+        break;
+      case CONVERTER_STATE:
+       currentLiteral.append(c);
+       switch(c) {
+       case '-':
+         formattingInfo.leftAlign = true;
+         break;
+       case '.':
+         state = DOT_STATE;
+         break;
+       default:
+         if(c >= '0' && c <= '9') {
+           formattingInfo.min = c - '0';
+           state = MIN_STATE;
+         } else {
+        finalizeConverter(c);
+    }
+       } // switch
+       break;
+      case MIN_STATE:
+       currentLiteral.append(c);
+       if(c >= '0' && c <= '9') {
+        formattingInfo.min = formattingInfo.min*10 + (c - '0');
+    } else if(c == '.') {
+        state = DOT_STATE;
+    } else {
+         finalizeConverter(c);
+       }
+       break;
+      case DOT_STATE:
+       currentLiteral.append(c);
+       if(c >= '0' && c <= '9') {
+         formattingInfo.max = 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.max = formattingInfo.max*10 + (c - '0');
+    } else {
+         finalizeConverter(c);
+         state = LITERAL_STATE;
+       }
+       break;
+      } // switch
+    } // while
+    if(currentLiteral.length() != 0) {
+      addToList(new LiteralPatternConverter(currentLiteral.toString()));
+      //LogLog.debug("Parsed LITERAL converter: \""+currentLiteral+"\".");
+    }
+    return head;
+  }
+
+  protected
+  void finalizeConverter(char c) {
+    PatternConverter pc = null;
+    switch(c) {
+    case 'c':
+      pc = new CategoryPatternConverter(formattingInfo,
+                                       extractPrecisionOption());
+      //LogLog.debug("CATEGORY converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'C':
+      pc = new ClassNamePatternConverter(formattingInfo,
+                                        extractPrecisionOption());
+      //LogLog.debug("CLASS_NAME converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'd':
+      String dateFormatStr = AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT;
+      DateFormat df;
+      String dOpt = extractOption();
+      if(dOpt != null) {
+        dateFormatStr = dOpt;
+    }
+
+      if(dateFormatStr.equalsIgnoreCase(
+                                    AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT)) {
+        df = new  ISO8601DateFormat();
+    } else if(dateFormatStr.equalsIgnoreCase(
+                                   AbsoluteTimeDateFormat.ABS_TIME_DATE_FORMAT)) {
+        df = new AbsoluteTimeDateFormat();
+    } else if(dateFormatStr.equalsIgnoreCase(
+                              AbsoluteTimeDateFormat.DATE_AND_TIME_DATE_FORMAT)) {
+        df = new DateTimeDateFormat();
+    } else {
+       try {
+         df = new SimpleDateFormat(dateFormatStr);
+       }
+       catch (IllegalArgumentException e) {
+         LogLog.error("Could not instantiate SimpleDateFormat with " +
+                      dateFormatStr, e);
+         df = (DateFormat) OptionConverter.instantiateByClassName(
+                                  "org.apache.log4j.helpers.ISO8601DateFormat",
+                                  DateFormat.class, null);
+       }
+      }
+      pc = new DatePatternConverter(formattingInfo, df);
+      //LogLog.debug("DATE converter {"+dateFormatStr+"}.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'F':
+      pc = new LocationPatternConverter(formattingInfo,
+                                       FILE_LOCATION_CONVERTER);
+      //LogLog.debug("File name converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'l':
+      pc = new LocationPatternConverter(formattingInfo,
+                                       FULL_LOCATION_CONVERTER);
+      //LogLog.debug("Location converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'L':
+      pc = new LocationPatternConverter(formattingInfo,
+                                       LINE_LOCATION_CONVERTER);
+      //LogLog.debug("LINE NUMBER converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'm':
+      pc = new BasicPatternConverter(formattingInfo, MESSAGE_CONVERTER);
+      //LogLog.debug("MESSAGE converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'M':
+      pc = new LocationPatternConverter(formattingInfo,
+                                       METHOD_LOCATION_CONVERTER);
+      //LogLog.debug("METHOD converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'p':
+      pc = new BasicPatternConverter(formattingInfo, LEVEL_CONVERTER);
+      //LogLog.debug("LEVEL converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'r':
+      pc = new BasicPatternConverter(formattingInfo,
+                                        RELATIVE_TIME_CONVERTER);
+      //LogLog.debug("RELATIVE time converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 't':
+      pc = new BasicPatternConverter(formattingInfo, THREAD_CONVERTER);
+      //LogLog.debug("THREAD converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+      /*case 'u':
+      if(i < patternLength) {
+       char cNext = pattern.charAt(i);
+       if(cNext >= '0' && cNext <= '9') {
+         pc = new UserFieldPatternConverter(formattingInfo, cNext - '0');
+         LogLog.debug("USER converter ["+cNext+"].");
+         formattingInfo.dump();
+         currentLiteral.setLength(0);
+         i++;
+       }
+       else
+         LogLog.error("Unexpected char" +cNext+" at position "+i);
+      }
+      break;*/
+    case 'x':
+      pc = new BasicPatternConverter(formattingInfo, NDC_CONVERTER);
+      //LogLog.debug("NDC converter.");
+      currentLiteral.setLength(0);
+      break;
+    case 'X':
+      String xOpt = extractOption();
+      pc = new MDCPatternConverter(formattingInfo, xOpt);
+      currentLiteral.setLength(0);
+      break;
+    default:
+      LogLog.error("Unexpected char [" +c+"] at position "+i
+                  +" in conversion patterrn.");
+      pc = new LiteralPatternConverter(currentLiteral.toString());
+      currentLiteral.setLength(0);
+    }
+
+    addConverter(pc);
+  }
+
+  protected
+  void addConverter(PatternConverter pc) {
+    currentLiteral.setLength(0);
+    // Add the pattern converter to the list.
+    addToList(pc);
+    // Next pattern is assumed to be a literal.
+    state = LITERAL_STATE;
+    // Reset formatting info
+    formattingInfo.reset();
+  }
+
+  // ---------------------------------------------------------------------
+  //                      PatternConverters
+  // ---------------------------------------------------------------------
+
+  private static class BasicPatternConverter extends PatternConverter {
+    int type;
+
+    BasicPatternConverter(FormattingInfo formattingInfo, int type) {
+      super(formattingInfo);
+      this.type = type;
+    }
+
+    public
+    String convert(LoggingEvent event) {
+      switch(type) {
+      case RELATIVE_TIME_CONVERTER:
+       return (Long.toString(event.timeStamp - LoggingEvent.getStartTime()));
+      case THREAD_CONVERTER:
+       return event.getThreadName();
+      case LEVEL_CONVERTER:
+       return event.getLevel().toString();
+      case NDC_CONVERTER:
+       return event.getNDC();
+      case MESSAGE_CONVERTER: {
+       return event.getRenderedMessage();
+      }
+      default: return null;
+      }
+    }
+  }
+
+  private static class LiteralPatternConverter extends PatternConverter {
+    private String literal;
+
+    LiteralPatternConverter(String value) {
+      literal = value;
+    }
+
+    public
+    final
+    void format(StringBuffer sbuf, LoggingEvent event) {
+      sbuf.append(literal);
+    }
+
+    public
+    String convert(LoggingEvent event) {
+      return literal;
+    }
+  }
+
+  private static class DatePatternConverter extends PatternConverter {
+    private DateFormat df;
+    private Date date;
+
+    DatePatternConverter(FormattingInfo formattingInfo, DateFormat df) {
+      super(formattingInfo);
+      date = new Date();
+      this.df = df;
+    }
+
+    public
+    String convert(LoggingEvent event) {
+      date.setTime(event.timeStamp);
+      String converted = null;
+      try {
+        converted = df.format(date);
+      }
+      catch (Exception ex) {
+        LogLog.error("Error occured while converting date.", ex);
+      }
+      return converted;
+    }
+  }
+
+  private static class MDCPatternConverter extends PatternConverter {
+    private String key;
+
+    MDCPatternConverter(FormattingInfo formattingInfo, String key) {
+      super(formattingInfo);
+      this.key = key;
+    }
+
+    public
+    String convert(LoggingEvent event) {
+      if (key == null) {
+          StringBuffer buf = new StringBuffer("{");
+          Map properties = event.getProperties();
+          if (properties.size() > 0) {
+            Object[] keys = properties.keySet().toArray();
+            Arrays.sort(keys);
+            for (int i = 0; i < keys.length; i++) {
+                buf.append('{');
+                buf.append(keys[i]);
+                buf.append(',');
+                buf.append(properties.get(keys[i]));
+                buf.append('}');
+            }
+          }
+          buf.append('}');
+          return buf.toString();
+      } else {
+        Object val = event.getMDC(key);
+        if(val == null) {
+               return null;
+        } else {
+               return val.toString();
+        }
+      }
+    }
+  }
+
+
+  private class LocationPatternConverter extends PatternConverter {
+    int type;
+
+    LocationPatternConverter(FormattingInfo formattingInfo, int type) {
+      super(formattingInfo);
+      this.type = type;
+    }
+
+    public
+    String convert(LoggingEvent event) {
+      LocationInfo locationInfo = event.getLocationInformation();
+      switch(type) {
+      case FULL_LOCATION_CONVERTER:
+       return locationInfo.fullInfo;
+      case METHOD_LOCATION_CONVERTER:
+       return locationInfo.getMethodName();
+      case LINE_LOCATION_CONVERTER:
+       return locationInfo.getLineNumber();
+      case FILE_LOCATION_CONVERTER:
+       return locationInfo.getFileName();
+      default: return null;
+      }
+    }
+  }
+
+  private static abstract class NamedPatternConverter extends PatternConverter {
+    int precision;
+
+    NamedPatternConverter(FormattingInfo formattingInfo, int precision) {
+      super(formattingInfo);
+      this.precision =  precision;
+    }
+
+    abstract
+    String getFullyQualifiedName(LoggingEvent event);
+
+    public
+    String convert(LoggingEvent event) {
+      String n = getFullyQualifiedName(event);
+      if(precision <= 0) {
+        return n;
+    } else {
+       int len = n.length();
+
+       // We substract 1 from 'len' when assigning to 'end' to avoid out of
+       // bounds exception in return r.substring(end+1, len). This can happen if
+       // precision is 1 and the category name ends with a dot.
+       int end = len -1 ;
+       for(int i = precision; i > 0; i--) {
+         end = n.lastIndexOf('.', end-1);
+         if(end == -1) {
+        return n;
+    }
+       }
+       return n.substring(end+1, len);
+      }
+    }
+  }
+
+  private class ClassNamePatternConverter extends NamedPatternConverter {
+
+    ClassNamePatternConverter(FormattingInfo formattingInfo, int precision) {
+      super(formattingInfo, precision);
+    }
+
+    String getFullyQualifiedName(LoggingEvent event) {
+      return event.getLocationInformation().getClassName();
+    }
+  }
+
+  private class CategoryPatternConverter extends NamedPatternConverter {
+
+    CategoryPatternConverter(FormattingInfo formattingInfo, int precision) {
+      super(formattingInfo, precision);
+    }
+
+    String getFullyQualifiedName(LoggingEvent event) {
+      return event.getLoggerName();
+    }
+  }
+}
+