logback-dev
Threads by month
- ----- 2025 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
December 2010
- 5 participants
- 93 discussions

16 Dec '10
Wrong date format in access log
-------------------------------
Key: LBACCESS-22
URL: http://jira.qos.ch/browse/LBACCESS-22
Project: logback-access
Issue Type: Bug
Environment: French default locale
Reporter: Vincent Ricard
Assignee: Logback dev list
Priority: Minor
Hi,
According to http://httpd.apache.org/docs/current/mod/mod_log_config.html#formats (see '%t' documentation) and http://httpd.apache.org/docs/current/logs.html#common, the output should be "10/Dec/2010" (with no accents, even with my french environment).
So, i think the CoreConstants.CLF_DATE_PATTERN should be "dd/MMM/yyyy:HH:mm:ss Z"; and the SimpleDateFormat should be instantiated with Locale.EN_US or Locale.ENGLISH for the %t default case.
Regards
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0

[GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-43-g888d97d
by git-noreply@pixie.qos.ch 15 Dec '10
by git-noreply@pixie.qos.ch 15 Dec '10
15 Dec '10
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Logback: the generic, reliable, fast and flexible logging framework.".
The branch, master has been updated
via 888d97dcca98ab928da7d67bf6660c293cd47b9e (commit)
from 2742a97de478cd3fc270223816eaa1c24d13cd82 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=888d97dcca98ab928da7d67b…
http://github.com/ceki/logback/commit/888d97dcca98ab928da7d67bf6660c293cd47…
commit 888d97dcca98ab928da7d67bf6660c293cd47b9e
Author: Ceki Gulcu <ceki(a)qos.ch>
Date: Wed Dec 15 22:49:48 2010 +0100
ongoing work on compound conversion words
diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassicConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassicConverter.java
index 8933733..15bd005 100644
--- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassicConverter.java
+++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassicConverter.java
@@ -14,7 +14,6 @@
package ch.qos.logback.classic.pattern;
import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.spi.LoggerContextAware;
import ch.qos.logback.classic.spi.LoggerContextAwareBase;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Context;
@@ -24,53 +23,10 @@ import ch.qos.logback.core.status.Status;
/**
* This class serves the super-class of all converters in logback. It extends
- * {@link DynamicConverter} and also implements {@link LoggerContextAware}.
- *
+ * {@link DynamicConverter}.
+ *
* @author Ceki Gulcu
*/
-abstract public class ClassicConverter extends DynamicConverter<ILoggingEvent> implements
- LoggerContextAware {
-
- LoggerContextAwareBase lcab = new LoggerContextAwareBase();
-
- public void setLoggerContext(LoggerContext lc) {
- lcab.setLoggerContext(lc);
- }
-
- public void setContext(Context context) {
- lcab.setContext(context);
- }
-
- public Context getContext() {
- return lcab.getContext();
- }
-
- public void addStatus(Status status) {
- lcab.addStatus(status);
- }
-
- public void addInfo(String msg) {
- lcab.addInfo(msg);
- }
-
- public void addInfo(String msg, Throwable ex) {
- lcab.addInfo(msg, ex);
- }
-
- public void addWarn(String msg) {
- lcab.addWarn(msg);
- }
-
- public void addWarn(String msg, Throwable ex) {
- lcab.addWarn(msg, ex);
- }
-
- public void addError(String msg) {
- lcab.addError(msg);
- }
-
- public void addError(String msg, Throwable ex) {
- lcab.addError(msg, ex);
- }
+abstract public class ClassicConverter extends DynamicConverter<ILoggingEvent> {
}
diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java
index 7189586..e72d4b3 100644
--- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java
+++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java
@@ -94,7 +94,7 @@ public class ReconfigureOnChangeFilter extends TurboFilter {
// its values may *not* be incremented sequentially. However, we don't care
// about the actual value of the field except that from time to time the
// expression (invocationCounter++ & 0xF) == 0xF) should be true.
- private int invocationCounter = 0;
+ private long invocationCounter = 0;
@Override
public FilterReply decide(Marker marker, Logger logger, Level level,
@@ -108,6 +108,7 @@ public class ReconfigureOnChangeFilter extends TurboFilter {
return FilterReply.NEUTRAL;
}
+ //System.out.println(".");
synchronized (lock) {
boolean changed = changeDetected();
if (changed) {
diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java
index 8ede4bc..fad905e 100644
--- a/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java
+++ b/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java
@@ -22,6 +22,8 @@ import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
+import ch.qos.logback.core.status.Status;
+import ch.qos.logback.core.util.StatusPrinter;
import org.junit.Before;
import org.junit.Test;
@@ -42,7 +44,7 @@ public class PatternLayoutTest extends AbstractPatternLayoutBaseTest<ILoggingEve
private LoggerContext lc = new LoggerContext();
Logger logger = lc.getLogger(ConverterTest.class);
Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME);
-
+
ILoggingEvent le;
List<String> optionList = new ArrayList<String>();
@@ -59,8 +61,8 @@ public class PatternLayoutTest extends AbstractPatternLayoutBaseTest<ILoggingEve
ILoggingEvent makeLoggingEvent(Exception ex) {
return new LoggingEvent(
- ch.qos.logback.core.pattern.FormattingConverter.class.getName(),
- logger, Level.INFO, "Some message", ex, null);
+ ch.qos.logback.core.pattern.FormattingConverter.class.getName(),
+ logger, Level.INFO, "Some message", ex, null);
}
@Override
@@ -80,7 +82,7 @@ public class PatternLayoutTest extends AbstractPatternLayoutBaseTest<ILoggingEve
// 2006-02-01 22:38:06,212 INFO [main] c.q.l.pattern.ConverterTest - Some
// message
String regex = ISO_REGEX + " INFO " + MAIN_REGEX
- + " c.q.l.c.pattern.ConverterTest - Some message\\s*";
+ + " c.q.l.c.pattern.ConverterTest - Some message\\s*";
assertTrue(val.matches(regex));
}
@@ -100,7 +102,7 @@ public class PatternLayoutTest extends AbstractPatternLayoutBaseTest<ILoggingEve
String val = pl.doLayout(getEventObject());
// 2008-03-18 21:55:54,250 c.q.l.c.pattern.ConverterTest - Some message
String regex = ISO_REGEX
- + " c.q.l.c.p.ConverterTest - Some message\\s*";
+ + " c.q.l.c.p.ConverterTest - Some message\\s*";
assertTrue(val.matches(regex));
}
@@ -109,10 +111,11 @@ public class PatternLayoutTest extends AbstractPatternLayoutBaseTest<ILoggingEve
pl.setPattern("%property{a}");
pl.start();
lc.putProperty("a", "b");
-
+
String val = pl.doLayout(getEventObject());
assertEquals("b", val);
}
+
@Test
public void testNopExeptionHandler() {
pl.setPattern("%nopex %m%n");
@@ -140,11 +143,29 @@ public class PatternLayoutTest extends AbstractPatternLayoutBaseTest<ILoggingEve
// 2006-02-01 22:38:06,212 INFO [main] c.q.l.pattern.ConverterTest - Some
// message
String regex = ClassicTestConstants.ISO_REGEX + " INFO " + MAIN_REGEX
- + " c.q.l.c.pattern.ConverterTest - Some message\\s*";
+ + " c.q.l.c.pattern.ConverterTest - Some message\\s*";
assertTrue(val.matches(regex));
}
@Test
+ public void replace() {
+// {
+// pl.setPattern("%replace(a){'a', 'b'}");
+// pl.start();
+// String val = pl.doLayout(getEventObject());
+// assertEquals("b", val);
+// }
+ {
+ pl.setPattern("%replace(a1234b){'\\d{4\\}', 'XXXX'}");
+ pl.start();
+ StatusPrinter.print(lc);
+ String val = pl.doLayout(getEventObject());
+ assertEquals("aXXXXb", val);
+ }
+
+ }
+
+ @Test
public void contextNameTest() {
pl.setPattern("%contextName");
lc.setName("aValue");
@@ -168,11 +189,13 @@ public class PatternLayoutTest extends AbstractPatternLayoutBaseTest<ILoggingEve
public void testConversionRuleSupportInPatternLayout() throws JoranException {
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "conversionRule/patternLayout0.xml");
root.getAppender("LIST");
- String msg = "Simon says";
+ String msg = "Simon says";
logger.debug(msg);
- StringListAppender<ILoggingEvent> sla = (StringListAppender<ILoggingEvent>) root.getAppender("LIST");
+ StringListAppender<ILoggingEvent> sla = (StringListAppender<ILoggingEvent>) root.getAppender("LIST");
assertNotNull(sla);
assertEquals(1, sla.strList.size());
- assertEquals(SampleConverter.SAMPLE_STR+" - "+msg, sla.strList.get(0));
+ assertEquals(SampleConverter.SAMPLE_STR + " - " + msg, sla.strList.get(0));
}
+
+
}
diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java
index 16a36c0..1965b1d 100644
--- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java
+++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java
@@ -33,14 +33,16 @@ import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.status.InfoStatus;
import ch.qos.logback.core.testUtil.Env;
+import static org.junit.Assert.fail;
+
public class ReconfigurePerf {
final static int THREAD_COUNT = 50;
- final static int LOOP_LEN = 1000 * 1000;
+ //final static int LOOP_LEN = 1000 * 1000;
// the space in the file name mandated by
// http://jira.qos.ch/browse/LBCORE-119
final static String CONF_FILE_AS_STR = ClassicTestConstants.INPUT_PREFIX
- + "turbo/scan_perf.xml";
+ + "turbo/scan_perf_barebones.xml";
// it actually takes time for Windows to propagate file modification changes
// values below 100 milliseconds can be problematic the same propagation
@@ -60,9 +62,9 @@ public class ReconfigurePerf {
// take into account propagation latency occurs on Linux
if (Env.isLinux()) {
sleepBetweenUpdates = 850;
- totalTestDuration = sleepBetweenUpdates * 5;
+ totalTestDuration = sleepBetweenUpdates * 25;
} else {
- totalTestDuration = sleepBetweenUpdates * 10;
+ totalTestDuration = sleepBetweenUpdates * 50;
}
harness = new MultiThreadedHarness(totalTestDuration);
}
@@ -86,11 +88,11 @@ public class ReconfigurePerf {
public void scan1() throws JoranException, IOException, InterruptedException {
File file = new File(CONF_FILE_AS_STR);
configure(file);
- doRun();
- doRun();
- doRun();
+ //doRun();
+ //doRun();
+ //doRun();
System.out.println("ENTER :");
- System.in.read();
+ //System.in.read();
doRun();
}
@@ -99,28 +101,28 @@ public class ReconfigurePerf {
harness.execute(runnableArray);
}
- ReconfigureOnChangeFilter initROCF() throws MalformedURLException {
- ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter();
- rocf.setContext(loggerContext);
- File file = new File(CONF_FILE_AS_STR);
- loggerContext.putObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN,
- file.toURI().toURL());
- rocf.start();
- return rocf;
- }
-
-
- public double directLoop(ReconfigureOnChangeFilter rocf) {
- long start = System.nanoTime();
- for (int i = 0; i < LOOP_LEN; i++) {
- rocf.decide(null, logger, Level.DEBUG, " ", null, null);
- }
- long end = System.nanoTime();
- return (end - start) / (1.0d * LOOP_LEN);
- }
-
- void addInfo(String msg, Object o) {
- loggerContext.getStatusManager().add(new InfoStatus(msg, o));
- }
+// ReconfigureOnChangeFilter initROCF() throws MalformedURLException {
+// ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter();
+// rocf.setContext(loggerContext);
+// File file = new File(CONF_FILE_AS_STR);
+// loggerContext.putObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN,
+// file.toURI().toURL());
+// rocf.start();
+// return rocf;
+// }
+
+
+// public double directLoop(ReconfigureOnChangeFilter rocf) {
+// long start = System.nanoTime();
+// for (int i = 0; i < LOOP_LEN; i++) {
+// rocf.decide(null, logger, Level.DEBUG, " ", null, null);
+// }
+// long end = System.nanoTime();
+// return (end - start) / (1.0d * LOOP_LEN);
+// }
+//
+// void addInfo(String msg, Object o) {
+// loggerContext.getStatusManager().add(new InfoStatus(msg, o));
+// }
}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java
index cdb0958..14a8033 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java
@@ -15,10 +15,16 @@ package ch.qos.logback.core.pattern;
import java.util.List;
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.spi.ContextAware;
+import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.spi.LifeCycle;
+import ch.qos.logback.core.status.Status;
abstract public class DynamicConverter<E> extends FormattingConverter<E>
- implements LifeCycle {
+ implements LifeCycle, ContextAware {
+
+ ContextAwareBase cab = new ContextAwareBase(this);
// Contains a list of option Strings.
private List<String> optionList;
@@ -67,4 +73,40 @@ abstract public class DynamicConverter<E> extends FormattingConverter<E>
protected List<String> getOptionList() {
return optionList;
}
+
+ public void setContext(Context context) {
+ cab.setContext(context);
+ }
+
+ public Context getContext() {
+ return cab.getContext();
+ }
+
+ public void addStatus(Status status) {
+ cab.addStatus(status);
+ }
+
+ public void addInfo(String msg) {
+ cab.addInfo(msg);
+ }
+
+ public void addInfo(String msg, Throwable ex) {
+ cab.addInfo(msg, ex);
+ }
+
+ public void addWarn(String msg) {
+ cab.addWarn(msg);
+ }
+
+ public void addWarn(String msg, Throwable ex) {
+ cab.addWarn(msg, ex);
+ }
+
+ public void addError(String msg) {
+ cab.addError(msg);
+ }
+
+ public void addError(String msg, Throwable ex) {
+ cab.addError(msg, ex);
+ }
}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
index c5e29ef..55ef3ff 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
@@ -13,19 +13,45 @@
*/
package ch.qos.logback.core.pattern;
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.spi.ContextAware;
+
import java.util.List;
+import java.util.regex.Pattern;
public class ReplacingCompositeConverter<E> extends CompositeConverter<E> {
+ Pattern pattern;
String regex;
- String by;
+ String replacement;
public void start() {
- final List<String> optionList = getOptionList();
- regex = optionList.get(0);
+ final List<String> optionList = getOptionList();
+ if (optionList == null) {
+ addError("at least two options are expected whereas you have declared none");
+ return;
+ }
+
+ int numOpts = optionList.size();
+
+ if (numOpts < 2) {
+ addError("at least two options are expected whereas you have declared only " + numOpts + "as [" + optionList + "]");
+ return;
+ }
+ regex = optionList.get(0);
+ pattern = Pattern.compile(regex);
+
+ //.matcher(this).replaceAll(replacement);
+
+ replacement = optionList.get(1);
+ System.out.println("regex="+regex);
+ super.start();
}
+
@Override
String transform(String in) {
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ if (!started)
+ return in;
+ return pattern.matcher(in).replaceAll(replacement);
}
-}
+}
\ No newline at end of file
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
index ad4c762..369a67f 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
@@ -16,6 +16,7 @@ package ch.qos.logback.core.pattern.parser;
import java.util.ArrayList;
import java.util.List;
+import ch.qos.logback.core.pattern.util.AsIsEscapeUtil;
import ch.qos.logback.core.pattern.util.IEscapeUtil;
import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
@@ -43,7 +44,7 @@ public class OptionTokenizer {
* @param pattern
*/
OptionTokenizer(String pattern) {
- this(pattern, new RegularEscapeUtil());
+ this(pattern, new AsIsEscapeUtil());
}
OptionTokenizer(String pattern, IEscapeUtil escapeUtil) {
@@ -68,6 +69,8 @@ public class OptionTokenizer {
case '\r':
case '\n':
break;
+ case COMMA_CHAR:
+ break;
case SINGLE_QUOTE_CHAR:
case DOUBLE_QUOTE_CHAR:
state = QUOTED_COLLECTING_STATE;
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
index 19d8311..085947a 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
@@ -19,6 +19,7 @@ import java.util.ArrayList;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.pattern.util.IEscapeUtil;
import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
+import ch.qos.logback.core.pattern.util.RestrictedEscapeUtil;
/**
* <p>
@@ -49,11 +50,14 @@ class TokenStream {
private static final int FORMAT_MODIFIER_STATE = 1;
private static final int KEYWORD_STATE = 2;
private static final int OPTION_STATE = 3;
+ private static final int RIGHT_PARENTHESIS_STATE = 4;
final String pattern;
final int patternLength;
final IEscapeUtil escapeUtil;
+ final IEscapeUtil optionEscapeUtil = new RestrictedEscapeUtil();
+
int state = LITERAL_STATE;
int pointer = 0;
@@ -81,30 +85,21 @@ class TokenStream {
pointer++;
switch (state) {
-
case LITERAL_STATE:
handleLiteralState(c, tokenList, buf);
break;
- //
case FORMAT_MODIFIER_STATE:
handleFormatModifierState(c, tokenList, buf);
break;
case OPTION_STATE:
- switch (c) {
- case CURLY_RIGHT:
- addValuedToken(Token.OPTION, buf, tokenList);
- state = LITERAL_STATE;
- break;
- case ESCAPE_CHAR:
- escape("%{}", buf);
- break;
- default:
- buf.append(c);
- }
+ handleOptionState(c, tokenList, buf);
break;
case KEYWORD_STATE:
handleKeywordState(c, tokenList, buf);
break;
+ case RIGHT_PARENTHESIS_STATE:
+ handleRightParenthesisState(c, tokenList, buf);
+ break;
default:
}
@@ -117,7 +112,9 @@ class TokenStream {
break;
case KEYWORD_STATE:
tokenList.add(new Token(Token.SIMPLE_KEYWORD, buf.toString()));
- buf.setLength(0);
+ break;
+ case RIGHT_PARENTHESIS_STATE:
+ tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN);
break;
case FORMAT_MODIFIER_STATE:
@@ -128,6 +125,38 @@ class TokenStream {
return tokenList;
}
+ private void handleRightParenthesisState(char c, List<Token> tokenList, StringBuffer buf) {
+ tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN);
+ switch (c) {
+ case CoreConstants.RIGHT_PARENTHESIS_CHAR:
+ break;
+ case CURLY_LEFT:
+ state = OPTION_STATE;
+ break;
+ case ESCAPE_CHAR:
+ escape("%{}", buf);
+ state = LITERAL_STATE;
+ break;
+ default:
+ buf.append(c);
+ state = LITERAL_STATE;
+ }
+ }
+
+ private void handleOptionState(char c, List<Token> tokenList, StringBuffer buf) {
+ switch (c) {
+ case CURLY_RIGHT:
+ addValuedToken(Token.OPTION, buf, tokenList);
+ state = LITERAL_STATE;
+ break;
+ case ESCAPE_CHAR:
+ optionEscape("}", buf);
+ break;
+ default:
+ buf.append(c);
+ }
+ }
+
private void handleFormatModifierState(char c, List<Token> tokenList, StringBuffer buf) {
if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) {
addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList);
@@ -155,13 +184,8 @@ class TokenStream {
break;
case CoreConstants.RIGHT_PARENTHESIS_CHAR:
- if (buf.length() >= 1 && buf.charAt(buf.length() - 1) == '\\') {
- buf.deleteCharAt(buf.length() - 1);
- buf.append(CoreConstants.RIGHT_PARENTHESIS_CHAR);
- } else {
- addValuedToken(Token.LITERAL, buf, tokenList);
- tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN);
- }
+ addValuedToken(Token.LITERAL, buf, tokenList);
+ state = RIGHT_PARENTHESIS_STATE;
break;
default:
@@ -170,11 +194,12 @@ class TokenStream {
}
private void handleKeywordState(char c, List<Token> tokenList, StringBuffer buf) {
- if (c == CURLY_LEFT) {
+
+ if (Character.isJavaIdentifierPart(c)) {
+ buf.append(c);
+ } else if (c == CURLY_LEFT) {
addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList);
state = OPTION_STATE;
- } else if (Character.isJavaIdentifierPart(c)) {
- buf.append(c);
} else if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) {
addValuedToken(Token.COMPOSITE_KEYWORD, buf, tokenList);
state = LITERAL_STATE;
@@ -182,12 +207,12 @@ class TokenStream {
addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList);
tokenList.add(Token.PERCENT_TOKEN);
state = FORMAT_MODIFIER_STATE;
+ } else if (c == CoreConstants.RIGHT_PARENTHESIS_CHAR) {
+ addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList);
+ state = RIGHT_PARENTHESIS_STATE;
} else {
addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList);
- if (c == CoreConstants.RIGHT_PARENTHESIS_CHAR) {
- // if c is a right parenthesis, then add it as such
- tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN);
- } else if (c == ESCAPE_CHAR) {
+ if (c == ESCAPE_CHAR) {
if ((pointer < patternLength)) {
char next = pattern.charAt(pointer++);
escapeUtil.escape("%()", buf, next, pointer);
@@ -206,6 +231,16 @@ class TokenStream {
}
}
+ void optionEscape(String escapeChars, StringBuffer buf) {
+ if ((pointer < patternLength)) {
+ char next = pattern.charAt(pointer++);
+ optionEscapeUtil.escape(escapeChars, buf, next, pointer);
+ }
+ }
+
+
+
+
private void addValuedToken(int type, StringBuffer buf, List<Token> tokenList) {
if (buf.length() > 0) {
tokenList.add(new Token(type, buf.toString()));
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java
index f9103cd..959c82d 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java
@@ -21,7 +21,7 @@ import ch.qos.logback.core.rolling.helper.FileNamePattern;
*
* @author Ceki Gülcü
*/
-public class AlmostAsIsEscapeUtil implements IEscapeUtil {
+public class AlmostAsIsEscapeUtil extends RestrictedEscapeUtil {
/**
* Do not perform any character escaping, except for '%', and ')'.
@@ -40,16 +40,6 @@ public class AlmostAsIsEscapeUtil implements IEscapeUtil {
*/
public void escape(String escapeChars, StringBuffer buf, char next,
int pointer) {
-
- if (next == CoreConstants.PERCENT_CHAR
- || next == CoreConstants.RIGHT_PARENTHESIS_CHAR) {
- buf.append(next);
- } else {
- // restitute the escape char (because it was consumed
- // before this method was called).
- buf.append("\\");
- // restitute the next character
- buf.append(next);
- }
+ super.escape(""+CoreConstants.PERCENT_CHAR+CoreConstants.RIGHT_PARENTHESIS_CHAR, buf, next, pointer);
}
}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AsIsEscapeUtil.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AsIsEscapeUtil.java
new file mode 100644
index 0000000..224bad9
--- /dev/null
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AsIsEscapeUtil.java
@@ -0,0 +1,38 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ * or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package ch.qos.logback.core.pattern.util;
+
+import ch.qos.logback.core.CoreConstants;
+import ch.qos.logback.core.rolling.helper.FileNamePattern;
+
+/**
+ * @author Ceki Gülcü
+ */
+public class AsIsEscapeUtil implements IEscapeUtil {
+
+ /**
+ * Do not perform any character escaping.
+ * <p/>
+ * Note that this method assumes that it is called after the escape character
+ * has been consumed.
+ */
+ public void escape(String escapeChars, StringBuffer buf, char next,
+ int pointer) {
+ // restitute the escape char (because it was consumed
+ // before this method was called).
+ buf.append("\\");
+ // restitute the next character
+ buf.append(next);
+ }
+}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RestrictedEscapeUtil.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RestrictedEscapeUtil.java
new file mode 100644
index 0000000..219d8ae
--- /dev/null
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RestrictedEscapeUtil.java
@@ -0,0 +1,37 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ * or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package ch.qos.logback.core.pattern.util;
+
+/**
+ * This implementation is intended for use in PatternLayout.
+ *
+ * @author Ceki Gülcü
+ */
+public class RestrictedEscapeUtil implements IEscapeUtil {
+
+ public void escape(String escapeChars, StringBuffer buf, char next,
+ int pointer) {
+ if (escapeChars.indexOf(next) >= 0) {
+ buf.append(next);
+ } else {
+ // restitute the escape char (because it was consumed
+ // before this method was called).
+ buf.append("\\");
+ // restitute the next character
+ buf.append(next);
+ }
+ }
+
+
+}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java b/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java
index 133bbbf..874a03d 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java
@@ -29,6 +29,14 @@ import ch.qos.logback.core.status.WarnStatus;
public class ContextAwareBase implements ContextAware {
private int noContextWarning = 0;
protected Context context;
+ final Object declaredOrigin;
+
+ public ContextAwareBase() {
+ declaredOrigin = this;
+ }
+ public ContextAwareBase(Object declaredOrigin) {
+ this.declaredOrigin = declaredOrigin;
+ }
public void setContext(Context context) {
if (this.context == null) {
@@ -56,7 +64,7 @@ public class ContextAwareBase implements ContextAware {
* @return the declared origin, by default 'this'
*/
protected Object getDeclaredOrigin() {
- return this;
+ return declaredOrigin;
}
public void addStatus(Status status) {
diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java
index e1a3d53..6c8db70 100644
--- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java
+++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java
@@ -118,6 +118,20 @@ public class OptionTokenizerTest {
witness.add("b");
assertEquals(witness, ol);
}
+ {
+ List ol = new OptionTokenizer("'a', b").tokenize();
+ List<String> witness = new ArrayList<String>();
+ witness.add("a");
+ witness.add("b");
+ assertEquals(witness, ol);
+ }
+ {
+ List ol = new OptionTokenizer("'', b").tokenize();
+ List<String> witness = new ArrayList<String>();
+ witness.add("");
+ witness.add("b");
+ assertEquals(witness, ol);
+ }
}
}
\ No newline at end of file
diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java
index c9d12a0..751f515 100644
--- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java
+++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java
@@ -19,6 +19,7 @@ import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.List;
+import org.junit.Ignore;
import org.junit.Test;
import ch.qos.logback.core.pattern.util.AlmostAsIsEscapeUtil;
-----------------------------------------------------------------------
Summary of changes:
.../logback/classic/pattern/ClassicConverter.java | 50 +----------
.../classic/turbo/ReconfigureOnChangeFilter.java | 3 +-
.../ch/qos/logback/classic/PatternLayoutTest.java | 43 +++++++--
.../qos/logback/classic/turbo/ReconfigurePerf.java | 64 +++++++-------
.../qos/logback/core/pattern/DynamicConverter.java | 44 +++++++++-
.../core/pattern/ReplacingCompositeConverter.java | 36 +++++++-
.../core/pattern/parser/OptionTokenizer.java | 5 +-
.../logback/core/pattern/parser/TokenStream.java | 91 ++++++++++++++------
.../core/pattern/util/AlmostAsIsEscapeUtil.java | 14 +---
.../logback/core/pattern/util/AsIsEscapeUtil.java | 38 ++++++++
.../core/pattern/util/RestrictedEscapeUtil.java | 37 ++++++++
.../ch/qos/logback/core/spi/ContextAwareBase.java | 10 ++-
.../core/pattern/parser/OptionTokenizerTest.java | 14 +++
.../core/pattern/parser/TokenStreamTest.java | 1 +
14 files changed, 313 insertions(+), 137 deletions(-)
create mode 100644 logback-core/src/main/java/ch/qos/logback/core/pattern/util/AsIsEscapeUtil.java
create mode 100644 logback-core/src/main/java/ch/qos/logback/core/pattern/util/RestrictedEscapeUtil.java
hooks/post-receive
--
Logback: the generic, reliable, fast and flexible logging framework.
1
0

[GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-42-g2742a97
by git-noreply@pixie.qos.ch 15 Dec '10
by git-noreply@pixie.qos.ch 15 Dec '10
15 Dec '10
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Logback: the generic, reliable, fast and flexible logging framework.".
The branch, master has been updated
via 2742a97de478cd3fc270223816eaa1c24d13cd82 (commit)
from fc4508616906b773dd9d93d4e0d2c45628d3f7b5 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=2742a97de478cd3fc2702238…
http://github.com/ceki/logback/commit/2742a97de478cd3fc270223816eaa1c24d13c…
commit 2742a97de478cd3fc270223816eaa1c24d13cd82
Author: Ceki Gulcu <ceki(a)qos.ch>
Date: Wed Dec 15 19:07:04 2010 +0100
adding support for composite keywords
diff --git a/goscp b/goscp
new file mode 100644
index 0000000..406a6ae
--- /dev/null
+++ b/goscp
@@ -0,0 +1,3 @@
+TARGET=cgulcu@hqchnesoa07:/srv/jboss-eap-4.3.0.GA_CP05/jboss-as/server/nesoa-04-esb-01/lib/
+
+scp logback-core/target/logback-core-0.9.27-SNAPSHOT.jar logback-classic/target/logback-classic-0.9.27-SNAPSHOT.jar logback-access/target/logback-access-0.9.27-SNAPSHOT.jar $TARGET
\ No newline at end of file
diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/DateConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/DateConverter.java
index 84226b5..4f0a449 100644
--- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/DateConverter.java
+++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/DateConverter.java
@@ -29,6 +29,7 @@ public class DateConverter extends ClassicConverter {
public void start() {
+
String datePattern = getFirstOption();
if (datePattern == null) {
datePattern = CoreConstants.ISO8601_PATTERN;
diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java
index 4259f26..546a653 100644
--- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java
+++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java
@@ -179,7 +179,7 @@ public class ReconfigureOnChangeTest {
// we can't have the test succeed under JDK 1.5, punt and require 1.6+
if (Env.isJDK6OrHigher()) {
assertTrue(failMsg,
- (effectiveResets * 1.3) >= (expectedReconfigurations * 1.0));
+ (effectiveResets * 1.4) >= (expectedReconfigurations * 1.0));
}
}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java b/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java
index 0ba51b4..05f1a7b 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java
@@ -210,8 +210,9 @@ public class OutputStreamAppender<E> extends UnsynchronizedAppenderBase<E> {
if (event instanceof DeferredProcessingAware) {
((DeferredProcessingAware) event).prepareForDeferredProcessing();
}
- // the synchronized prevents the OutputStream from being closed while we
- // are writing
+ // the synchronization prevents the OutputStream from being closed while we
+ // are writing. It also prevents multiple thread from entering the same
+ // converter. Converters assume that they are in a synchronized block.
synchronized (lock) {
writeOut(event);
}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java b/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java
index 5ee84d0..af16edf 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java
@@ -83,7 +83,7 @@ public abstract class HTMLLayoutBase<E> extends LayoutBase<E> {
Parser<E> p = new Parser<E>(pattern);
p.setContext(getContext());
Node t = p.parse();
- this.head = p.compile(t, getEffectiveConverterMap());
+ this.head = p.compile(t, getEffectiveConverterMap(), Parser.DEFAULT_COMPOSITE_CONVERTER_MAP);
ConverterUtil.startConverters(this.head);
} catch (ScanException ex) {
addError("Incorrect pattern found", ex);
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/CompositeConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/CompositeConverter.java
index 07e352e..bad3c8c 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/CompositeConverter.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/CompositeConverter.java
@@ -1,6 +1,6 @@
/**
* Logback: the reliable, generic, fast and flexible logging framework.
- * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
+ * Copyright (C) 1999-2010, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
@@ -13,24 +13,22 @@
*/
package ch.qos.logback.core.pattern;
-public class CompositeConverter<E> extends FormattingConverter<E> {
+abstract public class CompositeConverter<E> extends DynamicConverter<E> {
- StringBuilder buf = new StringBuilder();
Converter<E> childConverter;
public String convert(E event) {
- if (buf.capacity() > MAX_CAPACITY) {
- buf = new StringBuilder(INITIAL_BUF_SIZE);
- } else {
- buf.setLength(0);
- }
+ StringBuilder buf = new StringBuilder();
for (Converter<E> c = childConverter; c != null; c = c.next) {
c.write(buf, event);
}
- return buf.toString();
+ String intermediary = buf.toString();
+ return transform(intermediary);
}
+ abstract String transform(String in);
+
public void setChildConverter(Converter<E> child) {
childConverter = child;
}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/ConverterUtil.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/ConverterUtil.java
index 03f65e8..1dc12b2 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/ConverterUtil.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/ConverterUtil.java
@@ -17,25 +17,28 @@ public class ConverterUtil {
/**
* Start converters in the chain of converters.
+ *
* @param head
*/
public static void startConverters(Converter head) {
Converter c = head;
while (c != null) {
- if (c instanceof DynamicConverter) {
- DynamicConverter dc = (DynamicConverter) c;
- dc.start();
- } else if(c instanceof CompositeConverter){
+ // CompositeConverter is a subclass of DynamicConverter
+ if (c instanceof CompositeConverter) {
CompositeConverter cc = (CompositeConverter) c;
Converter childConverter = cc.childConverter;
startConverters(childConverter);
+ cc.start();
+ } else if (c instanceof DynamicConverter) {
+ DynamicConverter dc = (DynamicConverter) c;
+ dc.start();
}
c = c.getNext();
}
}
-
- public static<E> Converter<E> findTail(Converter<E> head) {
+
+ public static <E> Converter<E> findTail(Converter<E> head) {
Converter<E> p = head;
while (p != null) {
Converter<E> next = p.getNext();
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java
index 53eb3b8..cdb0958 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java
@@ -21,7 +21,7 @@ abstract public class DynamicConverter<E> extends FormattingConverter<E>
implements LifeCycle {
// Contains a list of option Strings.
- private List optionList;
+ private List<String> optionList;
/**
* Is this component active?
@@ -46,7 +46,7 @@ abstract public class DynamicConverter<E> extends FormattingConverter<E>
return started;
}
- public void setOptionList(List optionList) {
+ public void setOptionList(List<String> optionList) {
this.optionList = optionList;
}
@@ -60,11 +60,11 @@ abstract public class DynamicConverter<E> extends FormattingConverter<E>
if (optionList == null || optionList.size() == 0) {
return null;
} else {
- return (String) optionList.get(0);
+ return optionList.get(0);
}
}
- protected List getOptionList() {
+ protected List<String> getOptionList() {
return optionList;
}
}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/IdentityCompositeConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/IdentityCompositeConverter.java
new file mode 100644
index 0000000..473ff6c
--- /dev/null
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/IdentityCompositeConverter.java
@@ -0,0 +1,22 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2010, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ * or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package ch.qos.logback.core.pattern;
+
+public class IdentityCompositeConverter<E> extends CompositeConverter<E> {
+
+ @Override
+ String transform(String in) {
+ return in;
+ }
+}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java
index d507887..e60ee6f 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java
@@ -81,7 +81,7 @@ abstract public class PatternLayoutBase<E> extends LayoutBase<E> {
p.setContext(getContext());
}
Node t = p.parse();
- this.head = p.compile(t, getEffectiveConverterMap());
+ this.head = p.compile(t, getEffectiveConverterMap(), Parser.DEFAULT_COMPOSITE_CONVERTER_MAP);
if (postCompileProcessor != null) {
postCompileProcessor.process(head);
}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
new file mode 100644
index 0000000..c5e29ef
--- /dev/null
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
@@ -0,0 +1,31 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2010, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ * or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package ch.qos.logback.core.pattern;
+
+import java.util.List;
+
+public class ReplacingCompositeConverter<E> extends CompositeConverter<E> {
+
+ String regex;
+ String by;
+
+ public void start() {
+ final List<String> optionList = getOptionList();
+ regex = optionList.get(0);
+ }
+ @Override
+ String transform(String in) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java
index bc94153..9bcb1a6 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java
@@ -15,10 +15,7 @@ package ch.qos.logback.core.pattern.parser;
import java.util.Map;
-import ch.qos.logback.core.pattern.CompositeConverter;
-import ch.qos.logback.core.pattern.Converter;
-import ch.qos.logback.core.pattern.DynamicConverter;
-import ch.qos.logback.core.pattern.LiteralConverter;
+import ch.qos.logback.core.pattern.*;
import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.status.ErrorStatus;
import ch.qos.logback.core.util.OptionHelper;
@@ -29,46 +26,49 @@ class Compiler<E> extends ContextAwareBase {
Converter<E> tail;
final Node top;
final Map converterMap;
+ final Map compositeConverterMap;
- Compiler(final Node top, final Map converterMap) {
+ Compiler(final Node top, final Map converterMap, Map compositeConverterMap) {
this.top = top;
this.converterMap = converterMap;
+ this.compositeConverterMap = compositeConverterMap;
}
Converter<E> compile() {
head = tail = null;
for (Node n = top; n != null; n = n.next) {
switch (n.type) {
- case Node.LITERAL:
- addToList(new LiteralConverter<E>((String) n.getValue()));
- break;
- case Node.COMPOSITE:
- CompositeNode cn = (CompositeNode) n;
- CompositeConverter<E> compositeConverter = new CompositeConverter<E>();
- compositeConverter.setFormattingInfo(cn.getFormatInfo());
- Compiler<E> childCompiler = new Compiler<E>(cn.getChildNode(),
- converterMap);
- childCompiler.setContext(context);
- Converter<E> childConverter = childCompiler.compile();
- compositeConverter.setChildConverter(childConverter);
- addToList(compositeConverter);
- break;
- case Node.KEYWORD:
- KeywordNode kn = (KeywordNode) n;
- DynamicConverter<E> dynaConverter = createConverter(kn);
- if (dynaConverter != null) {
- dynaConverter.setFormattingInfo(kn.getFormatInfo());
- dynaConverter.setOptionList(kn.getOptions());
- addToList(dynaConverter);
- } else {
- // if the appropriate dynaconverter cannot be found, then replace
- // it with a dummy LiteralConverter indicating an error.
- Converter<E> errConveter = new LiteralConverter<E>("%PARSER_ERROR["
- + kn.getValue()+"]");
- addStatus(new ErrorStatus("[" + kn.getValue()
- + "] is not a valid conversion word", this));
- addToList(errConveter);
- }
+ case Node.LITERAL:
+ addToList(new LiteralConverter<E>((String) n.getValue()));
+ break;
+ case Node.COMPOSITE_KEYWORD:
+ CompositeNode cn = (CompositeNode) n;
+ CompositeConverter<E> compositeConverter = createCompiteConverter(cn);
+ compositeConverter.setFormattingInfo(cn.getFormatInfo());
+ compositeConverter.setOptionList(cn.getOptions());
+ Compiler<E> childCompiler = new Compiler<E>(cn.getChildNode(),
+ converterMap, compositeConverterMap);
+ childCompiler.setContext(context);
+ Converter<E> childConverter = childCompiler.compile();
+ compositeConverter.setChildConverter(childConverter);
+ addToList(compositeConverter);
+ break;
+ case Node.SIMPLE_KEYWORD:
+ SimpleKeywordNode kn = (SimpleKeywordNode) n;
+ DynamicConverter<E> dynaConverter = createConverter(kn);
+ if (dynaConverter != null) {
+ dynaConverter.setFormattingInfo(kn.getFormatInfo());
+ dynaConverter.setOptionList(kn.getOptions());
+ addToList(dynaConverter);
+ } else {
+ // if the appropriate dynaconverter cannot be found, then replace
+ // it with a dummy LiteralConverter indicating an error.
+ Converter<E> errConveter = new LiteralConverter<E>("%PARSER_ERROR["
+ + kn.getValue() + "]");
+ addStatus(new ErrorStatus("[" + kn.getValue()
+ + "] is not a valid conversion word", this));
+ addToList(errConveter);
+ }
}
}
@@ -87,31 +87,60 @@ class Compiler<E> extends ContextAwareBase {
/**
* Attempt to create a converter using the information found in
* 'converterMap'.
- *
+ *
* @param kn
* @return
*/
@SuppressWarnings("unchecked")
- DynamicConverter<E> createConverter(KeywordNode kn) {
+ DynamicConverter<E> createConverter(SimpleKeywordNode kn) {
String keyword = (String) kn.getValue();
String converterClassStr = (String) converterMap.get(keyword);
if (converterClassStr != null) {
try {
return (DynamicConverter) OptionHelper.instantiateByClassName(
- converterClassStr, DynamicConverter.class, context);
+ converterClassStr, DynamicConverter.class, context);
} catch (Exception e) {
addError("Failed to instantiate converter class [" + converterClassStr
- + "]", e);
+ + "]", e);
return null;
}
} else {
addError("There is no conversion class registered for conversion word ["
- + keyword + "]");
+ + keyword + "]");
return null;
}
}
+ /**
+ * Attempt to create a converter using the information found in
+ * 'compositeConverterMap'.
+ *
+ * @param cn
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ CompositeConverter<E> createCompiteConverter(CompositeNode cn) {
+ String keyword = (String) cn.getValue();
+ String converterClassStr = (String) compositeConverterMap.get(keyword);
+
+ if (converterClassStr != null) {
+ try {
+ return (CompositeConverter) OptionHelper.instantiateByClassName(
+ converterClassStr, CompositeConverter.class, context);
+ } catch (Exception e) {
+ addError("Failed to instantiate converter class [" + converterClassStr
+ + "]", e);
+ return null;
+ }
+ } else {
+ addError("There is no conversion class registered for composite conversion word ["
+ + keyword + "]");
+ return null;
+ }
+ }
+
+
// public void setStatusManager(StatusManager statusManager) {
// this.statusManager = statusManager;
// }
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/CompositeNode.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/CompositeNode.java
index 8fd2029..cf3c402 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/CompositeNode.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/CompositeNode.java
@@ -13,11 +13,12 @@
*/
package ch.qos.logback.core.pattern.parser;
-public class CompositeNode extends FormattingNode {
+public class CompositeNode extends SimpleKeywordNode {
Node childNode;
- CompositeNode() {
- super(Node.COMPOSITE);
+ CompositeNode(String keyword) {
+ super(Node.COMPOSITE_KEYWORD, keyword);
+
}
public Node getChildNode() {
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Node.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Node.java
index 615e2e9..e9bee8b 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Node.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Node.java
@@ -15,8 +15,8 @@ package ch.qos.logback.core.pattern.parser;
public class Node {
static final int LITERAL = 0;
- static final int KEYWORD = 1;
- static final int COMPOSITE = 2;
+ static final int SIMPLE_KEYWORD = 1;
+ static final int COMPOSITE_KEYWORD = 2;
final int type;
final Object value;
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
index 65308db..ad4c762 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
@@ -52,7 +52,7 @@ public class OptionTokenizer {
this.escapeUtil = escapeUtil;
}
- List tokenize() throws ScanException {
+ List<String> tokenize() throws ScanException {
List<String> tokenList = new ArrayList<String>();
StringBuffer buf = new StringBuffer();
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java
index 268edea..510aa7a 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java
@@ -13,18 +13,46 @@
*/
package ch.qos.logback.core.pattern.parser;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ch.qos.logback.core.pattern.Converter;
import ch.qos.logback.core.pattern.FormatInfo;
+import ch.qos.logback.core.pattern.IdentityCompositeConverter;
+import ch.qos.logback.core.pattern.ReplacingCompositeConverter;
import ch.qos.logback.core.pattern.util.IEscapeUtil;
import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
import ch.qos.logback.core.spi.ContextAwareBase;
+// ~=lamda
+// E = TE|T
+
+// Left factorization
+// E = T(E|~)
+// Eopt = E|~
+// replace E|~ with Eopt in E
+// E = TEopt
+
+// T = LITERAL | '%' C | '%' FORMAT_MODIFIER C
+// C = SIMPLE_KEYWORD OPTION | COMPOSITE_KEYWORD COMPOSITE
+// OPTION = {...} | ~
+// COMPOSITE = E ')' OPTION
+
+
public class Parser<E> extends ContextAwareBase {
+ public final static Map<String, String> DEFAULT_COMPOSITE_CONVERTER_MAP = new HashMap<String, String>();
+ public final static String REPLACER_CONVERTER_WORD = "replace";
+ static {
+ DEFAULT_COMPOSITE_CONVERTER_MAP.put(Token.BARE_COMPOSITE_KEYWORD_TOKEN.getValue().toString(),
+ IdentityCompositeConverter.class.getName());
+ DEFAULT_COMPOSITE_CONVERTER_MAP.put(REPLACER_CONVERTER_WORD,
+ ReplacingCompositeConverter.class.getName());
+
+ }
+
final List tokenList;
int pointer = 0;
@@ -32,7 +60,6 @@ public class Parser<E> extends ContextAwareBase {
this.tokenList = ts.tokenize();
}
- // this variant should be used for testing purposes only
public Parser(String pattern) throws ScanException {
this(pattern, new RegularEscapeUtil());
}
@@ -46,40 +73,51 @@ public class Parser<E> extends ContextAwareBase {
}
}
- public Node parse() throws ScanException {
- return E();
- }
-
/**
* When the parsing step is done, the Node list can be transformed into a
* converter chain.
- *
+ *
* @param top
* @param converterMap
* @return
* @throws ScanException
*/
- public Converter<E> compile(final Node top, Map converterMap) {
- Compiler<E> compiler = new Compiler<E>(top, converterMap);
+ public Converter<E> compile(final Node top, Map converterMap, Map compositeConverterMap) {
+ Compiler<E> compiler = new Compiler<E>(top, converterMap, compositeConverterMap);
compiler.setContext(context);
//compiler.setStatusManager(statusManager);
return compiler.compile();
}
+ public Node parse() throws ScanException {
+ return E();
+ }
+
+ // E = TEopt
Node E() throws ScanException {
- // System.out.println("in E()");
Node t = T();
if (t == null) {
return null;
}
Node eOpt = Eopt();
if (eOpt != null) {
- // System.out.println("setting next node to " + eOpt);
t.setNext(eOpt);
}
return t;
}
+ // Eopt = E|~
+ Node Eopt() throws ScanException {
+ // System.out.println("in Eopt()");
+ Token next = getCurentToken();
+ // System.out.println("Current token is " + next);
+ if (next == null) {
+ return null;
+ } else {
+ return E();
+ }
+ }
+
Node T() throws ScanException {
// System.out.println("in T()");
Token t = getCurentToken();
@@ -117,17 +155,6 @@ public class Parser<E> extends ContextAwareBase {
}
- Node Eopt() throws ScanException {
- // System.out.println("in Eopt()");
- Token next = getCurentToken();
- // System.out.println("Current token is " + next);
- if (next == null) {
- return null;
- } else {
- return E();
- }
- }
-
FormattingNode C() throws ScanException {
Token t = getCurentToken();
// System.out.println("in C()");
@@ -135,11 +162,11 @@ public class Parser<E> extends ContextAwareBase {
expectNotNull(t, "a LEFT_PARENTHESIS or KEYWORD");
int type = t.getType();
switch (type) {
- case Token.KEYWORD:
+ case Token.SIMPLE_KEYWORD:
return SINGLE();
- case Token.LEFT_PARENTHESIS:
+ case Token.COMPOSITE_KEYWORD:
advanceTokenPointer();
- return COMPOSITE();
+ return COMPOSITE(t.getValue().toString());
default:
throw new IllegalStateException("Unexpected token " + t);
}
@@ -149,19 +176,19 @@ public class Parser<E> extends ContextAwareBase {
// System.out.println("in SINGLE()");
Token t = getNextToken();
// System.out.println("==" + t);
- KeywordNode keywordNode = new KeywordNode(t.getValue());
+ SimpleKeywordNode keywordNode = new SimpleKeywordNode(t.getValue());
Token ot = getCurentToken();
if (ot != null && ot.getType() == Token.OPTION) {
- List optionList = new OptionTokenizer((String) ot.getValue()).tokenize();
+ List<String> optionList = new OptionTokenizer((String) ot.getValue()).tokenize();
keywordNode.setOptions(optionList);
advanceTokenPointer();
}
return keywordNode;
}
- FormattingNode COMPOSITE() throws ScanException {
- CompositeNode compositeNode = new CompositeNode();
+ FormattingNode COMPOSITE(String keyword) throws ScanException {
+ CompositeNode compositeNode = new CompositeNode(keyword);
Node childNode = E();
// System.out.println("Child node: " + childNode);
@@ -177,6 +204,12 @@ public class Parser<E> extends ContextAwareBase {
} else {
// System.out.println("got expected ')'");
}
+ Token ot = getCurentToken();
+ if (ot != null && ot.getType() == Token.OPTION) {
+ List<String> optionList = new OptionTokenizer((String) ot.getValue()).tokenize();
+ compositeNode.setOptions(optionList);
+ advanceTokenPointer();
+ }
return compositeNode;
}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/KeywordNode.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/SimpleKeywordNode.java
similarity index 71%
rename from logback-core/src/main/java/ch/qos/logback/core/pattern/parser/KeywordNode.java
rename to logback-core/src/main/java/ch/qos/logback/core/pattern/parser/SimpleKeywordNode.java
index 3d2879c..3eda998 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/KeywordNode.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/SimpleKeywordNode.java
@@ -1,60 +1,64 @@
-/**
- * Logback: the reliable, generic, fast and flexible logging framework.
- * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
- *
- * This program and the accompanying materials are dual-licensed under
- * either the terms of the Eclipse Public License v1.0 as published by
- * the Eclipse Foundation
- *
- * or (per the licensee's choosing)
- *
- * under the terms of the GNU Lesser General Public License version 2.1
- * as published by the Free Software Foundation.
- */
-package ch.qos.logback.core.pattern.parser;
-
-import java.util.List;
-
-public class KeywordNode extends FormattingNode {
-
- List optionList;
-
- KeywordNode(Object value) {
- super(Node.KEYWORD, value);
- }
-
- public List getOptions() {
- return optionList;
- }
-
- public void setOptions(List optionList) {
- this.optionList = optionList;
- }
-
- public boolean equals(Object o) {
- // System.out.println("Keyword.equals()");
- if (!super.equals(o)) {
- return false;
- }
-
- if (!(o instanceof KeywordNode)) {
- return false;
- }
- KeywordNode r = (KeywordNode) o;
-
- return (optionList != null ? optionList.equals(r.optionList)
- : r.optionList == null);
- }
-
- public String toString() {
- StringBuffer buf = new StringBuffer();
- if (optionList == null) {
- buf.append("KeyWord(" + value + "," + formatInfo + ")");
- } else {
- buf.append("KeyWord(" + value + ", " + formatInfo + "," + optionList
- + ")");
- }
- buf.append(printNext());
- return buf.toString();
- }
-}
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ * or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package ch.qos.logback.core.pattern.parser;
+
+import java.util.List;
+
+public class SimpleKeywordNode extends FormattingNode {
+
+ List<String> optionList;
+
+ SimpleKeywordNode(Object value) {
+ super(Node.SIMPLE_KEYWORD, value);
+ }
+
+ protected SimpleKeywordNode(int type, Object value) {
+ super(type, value);
+ }
+
+ public List<String> getOptions() {
+ return optionList;
+ }
+
+ public void setOptions(List<String> optionList) {
+ this.optionList = optionList;
+ }
+
+ public boolean equals(Object o) {
+ // System.out.println("Keyword.equals()");
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ if (!(o instanceof SimpleKeywordNode)) {
+ return false;
+ }
+ SimpleKeywordNode r = (SimpleKeywordNode) o;
+
+ return (optionList != null ? optionList.equals(r.optionList)
+ : r.optionList == null);
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ if (optionList == null) {
+ buf.append("KeyWord(" + value + "," + formatInfo + ")");
+ } else {
+ buf.append("KeyWord(" + value + ", " + formatInfo + "," + optionList
+ + ")");
+ }
+ buf.append(printNext());
+ return buf.toString();
+ }
+}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java
index 2965a1c..1e8a385 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java
@@ -16,7 +16,7 @@ package ch.qos.logback.core.pattern.parser;
class Token {
static final int PERCENT = 37;
- static final int LEFT_PARENTHESIS = 40;
+ //static final int LEFT_PARENTHESIS = 40;
static final int RIGHT_PARENTHESIS = 41;
static final int MINUS = 45;
static final int DOT = 46;
@@ -24,14 +24,15 @@ class Token {
static final int CURLY_RIGHT = 125;
static final int LITERAL = 1000;
static final int FORMAT_MODIFIER = 1002;
- static final int KEYWORD = 1004;
+ static final int SIMPLE_KEYWORD = 1004;
+ static final int COMPOSITE_KEYWORD = 1005;
static final int OPTION = 1006;
static final int EOF = Integer.MAX_VALUE;
static Token EOF_TOKEN = new Token(EOF, "EOF");
static Token RIGHT_PARENTHESIS_TOKEN = new Token(RIGHT_PARENTHESIS);
- static Token LEFT_PARENTHESIS_TOKEN = new Token(LEFT_PARENTHESIS);
+ static Token BARE_COMPOSITE_KEYWORD_TOKEN = new Token(COMPOSITE_KEYWORD, "BARE");
static Token PERCENT_TOKEN = new Token(PERCENT);
private final int type;
@@ -72,15 +73,15 @@ class Token {
case OPTION:
typeStr = "OPTION";
break;
- case KEYWORD:
- typeStr = "KEYWORD";
+ case SIMPLE_KEYWORD:
+ typeStr = "SIMPLE_KEYWORD";
break;
+ case COMPOSITE_KEYWORD:
+ typeStr = "COMPOSITE_KEYWORD";
+ break;
case RIGHT_PARENTHESIS:
typeStr = "RIGHT_PARENTHESIS";
break;
- case LEFT_PARENTHESIS:
- typeStr = "LEFT_PARENTHESIS";
- break;
default:
typeStr = "UNKNOWN";
}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
index b0dc881..19d8311 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
@@ -24,17 +24,17 @@ import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
* <p>
* Return a steady stream of tokens.
* <p/>
- *
+ * <p/>
* <p>
- * The returned tokens are one of: LITERAL, '%', FORMAT_MODIFIER, KEYWWORD,
+ * The returned tokens are one of: LITERAL, '%', FORMAT_MODIFIER, SIMPLE_KEYWORD, COMPOSITE_KEYWORD
* OPTION, LEFT_PARENTHESIS, and RIGHT_PARENTHESIS.
* </p>
- *
+ * <p/>
* <p>
* The '\' character is used as escape. It can be used to escape '_', '%', '('
* and '('.
* <p>
- *
+ * <p/>
* <p>
* Note that there is no EOS token returned.
* </p>
@@ -42,7 +42,6 @@ import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
class TokenStream {
private static final char ESCAPE_CHAR = '\\';
- private static final char PERCENT_CHAR = CoreConstants.PERCENT_CHAR;
private static final char CURLY_LEFT = '{';
private static final char CURLY_RIGHT = '}';
@@ -66,7 +65,7 @@ class TokenStream {
TokenStream(String pattern, IEscapeUtil escapeUtil) {
if (pattern == null || pattern.length() == 0) {
throw new IllegalArgumentException(
- "null or empty pattern string not allowed");
+ "null or empty pattern string not allowed");
}
this.pattern = pattern;
patternLength = pattern.length();
@@ -83,105 +82,121 @@ class TokenStream {
switch (state) {
- case LITERAL_STATE:
- switch (c) {
- case ESCAPE_CHAR:
- escape("%()", buf);
+ case LITERAL_STATE:
+ handleLiteralState(c, tokenList, buf);
break;
- case PERCENT_CHAR:
- addValuedToken(Token.LITERAL, buf, tokenList);
- tokenList.add(Token.PERCENT_TOKEN);
- state = FORMAT_MODIFIER_STATE;
+ //
+ case FORMAT_MODIFIER_STATE:
+ handleFormatModifierState(c, tokenList, buf);
break;
-
- case CoreConstants.RIGHT_PARENTHESIS_CHAR:
- if (buf.length() >= 1 && buf.charAt(buf.length() - 1) == '\\') {
- buf.deleteCharAt(buf.length() - 1);
- buf.append(CoreConstants.RIGHT_PARENTHESIS_CHAR);
- } else {
- addValuedToken(Token.LITERAL, buf, tokenList);
- tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN);
+ case OPTION_STATE:
+ switch (c) {
+ case CURLY_RIGHT:
+ addValuedToken(Token.OPTION, buf, tokenList);
+ state = LITERAL_STATE;
+ break;
+ case ESCAPE_CHAR:
+ escape("%{}", buf);
+ break;
+ default:
+ buf.append(c);
}
break;
+ case KEYWORD_STATE:
+ handleKeywordState(c, tokenList, buf);
+ break;
default:
- buf.append(c);
- }
+ }
+ }
+
+ // EOS
+ switch (state) {
+ case LITERAL_STATE:
+ addValuedToken(Token.LITERAL, buf, tokenList);
break;
- //
- case FORMAT_MODIFIER_STATE:
- if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) {
- addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList);
- tokenList.add(Token.LEFT_PARENTHESIS_TOKEN);
- state = LITERAL_STATE;
- } else if (Character.isJavaIdentifierStart(c)) {
- addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList);
- state = KEYWORD_STATE;
- buf.append(c);
- } else {
- buf.append(c);
- }
+ case KEYWORD_STATE:
+ tokenList.add(new Token(Token.SIMPLE_KEYWORD, buf.toString()));
+ buf.setLength(0);
break;
+
+ case FORMAT_MODIFIER_STATE:
case OPTION_STATE:
- switch (c) {
- case CURLY_RIGHT:
- addValuedToken(Token.OPTION, buf, tokenList);
- state = LITERAL_STATE;
- break;
- case ESCAPE_CHAR:
- escape("%{}", buf);
- break;
- default:
- buf.append(c);
- }
+ throw new ScanException("Unexpected end of pattern string");
+ }
+
+ return tokenList;
+ }
+
+ private void handleFormatModifierState(char c, List<Token> tokenList, StringBuffer buf) {
+ if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) {
+ addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList);
+ tokenList.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN);
+ state = LITERAL_STATE;
+ } else if (Character.isJavaIdentifierStart(c)) {
+ addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList);
+ state = KEYWORD_STATE;
+ buf.append(c);
+ } else {
+ buf.append(c);
+ }
+ }
+
+ private void handleLiteralState(char c, List<Token> tokenList, StringBuffer buf) {
+ switch (c) {
+ case ESCAPE_CHAR:
+ escape("%()", buf);
break;
- case KEYWORD_STATE:
- if (c == CURLY_LEFT) {
- addValuedToken(Token.KEYWORD, buf, tokenList);
- state = OPTION_STATE;
- } else if (Character.isJavaIdentifierPart(c)) {
- buf.append(c);
- } else if (c == PERCENT_CHAR) {
- addValuedToken(Token.KEYWORD, buf, tokenList);
- tokenList.add(Token.PERCENT_TOKEN);
- state = FORMAT_MODIFIER_STATE;
+
+ case CoreConstants.PERCENT_CHAR:
+ addValuedToken(Token.LITERAL, buf, tokenList);
+ tokenList.add(Token.PERCENT_TOKEN);
+ state = FORMAT_MODIFIER_STATE;
+ break;
+
+ case CoreConstants.RIGHT_PARENTHESIS_CHAR:
+ if (buf.length() >= 1 && buf.charAt(buf.length() - 1) == '\\') {
+ buf.deleteCharAt(buf.length() - 1);
+ buf.append(CoreConstants.RIGHT_PARENTHESIS_CHAR);
} else {
- addValuedToken(Token.KEYWORD, buf, tokenList);
- if (c == CoreConstants.RIGHT_PARENTHESIS_CHAR) {
- // if c is a right parenthesis, then add it as such
- tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN);
- } else if (c == ESCAPE_CHAR) {
- if ((pointer < patternLength)) {
- char next = pattern.charAt(pointer++);
- escapeUtil.escape("%()", buf, next, pointer);
- }
- } else {
- buf.append(c);
- }
- state = LITERAL_STATE;
+ addValuedToken(Token.LITERAL, buf, tokenList);
+ tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN);
}
break;
default:
- }
+ buf.append(c);
}
+ }
- // EOS
- switch (state) {
- case LITERAL_STATE:
- addValuedToken(Token.LITERAL, buf, tokenList);
- break;
- case KEYWORD_STATE:
- tokenList.add(new Token(Token.KEYWORD, buf.toString()));
- buf.setLength(0);
- break;
-
- case FORMAT_MODIFIER_STATE:
- case OPTION_STATE:
- throw new ScanException("Unexpected end of pattern string");
+ private void handleKeywordState(char c, List<Token> tokenList, StringBuffer buf) {
+ if (c == CURLY_LEFT) {
+ addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList);
+ state = OPTION_STATE;
+ } else if (Character.isJavaIdentifierPart(c)) {
+ buf.append(c);
+ } else if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) {
+ addValuedToken(Token.COMPOSITE_KEYWORD, buf, tokenList);
+ state = LITERAL_STATE;
+ } else if (c == CoreConstants.PERCENT_CHAR) {
+ addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList);
+ tokenList.add(Token.PERCENT_TOKEN);
+ state = FORMAT_MODIFIER_STATE;
+ } else {
+ addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList);
+ if (c == CoreConstants.RIGHT_PARENTHESIS_CHAR) {
+ // if c is a right parenthesis, then add it as such
+ tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN);
+ } else if (c == ESCAPE_CHAR) {
+ if ((pointer < patternLength)) {
+ char next = pattern.charAt(pointer++);
+ escapeUtil.escape("%()", buf, next, pointer);
+ }
+ } else {
+ buf.append(c);
+ }
+ state = LITERAL_STATE;
}
-
- return tokenList;
}
void escape(String escapeChars, StringBuffer buf) {
diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java
index 88adfe6..be3c8b5 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java
@@ -66,7 +66,7 @@ public class FileNamePattern extends ContextAwareBase {
Parser<Object> p = new Parser<Object>(patternForParsing, new AlmostAsIsEscapeUtil());
p.setContext(context);
Node t = p.parse();
- this.headTokenConverter = p.compile(t, CONVERTER_MAP);
+ this.headTokenConverter = p.compile(t, CONVERTER_MAP, Parser.DEFAULT_COMPOSITE_CONVERTER_MAP);
} catch (ScanException sce) {
addError("Failed to parse pattern \"" + pattern + "\".", sce);
diff --git a/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java b/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java
index 1e7cc80..235b30a 100644
--- a/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java
+++ b/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java
@@ -30,7 +30,5 @@ import org.junit.runners.Suite.SuiteClasses;
ch.qos.logback.core.sift.PackageTest.class,
ch.qos.logback.core.encoder.PackageTest.class,
ch.qos.logback.core.recovery.PackageTest.class})
-public class
- AllCoreTest {
-
+public class AllCoreTest {
}
diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java
index 8c64c59..39bb596 100644
--- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java
+++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java
@@ -29,7 +29,7 @@ import ch.qos.logback.core.pattern.Converter123;
import ch.qos.logback.core.pattern.ConverterHello;
import ch.qos.logback.core.status.StatusChecker;
import ch.qos.logback.core.util.StatusPrinter;
-
+import static ch.qos.logback.core.pattern.parser.Parser.DEFAULT_COMPOSITE_CONVERTER_MAP;
public class CompilerTest {
@@ -56,7 +56,7 @@ public class CompilerTest {
public void testLiteral() throws Exception {
Parser<Object> p = new Parser<Object>("hello");
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("hello", result);
}
@@ -67,7 +67,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("abc %hello");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("abc Hello", result);
}
@@ -75,7 +75,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("abc %hello %OTT");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("abc Hello 123", result);
}
@@ -87,7 +87,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("abc %7hello");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("abc Hello", result);
}
@@ -96,7 +96,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("abc %-7hello");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("abc Hello ", result);
}
@@ -105,7 +105,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("abc %.3hello");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("abc llo", result);
}
@@ -114,7 +114,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("abc %.-3hello");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("abc Hel", result);
}
@@ -123,7 +123,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("abc %4.5OTT");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("abc 123", result);
}
@@ -131,7 +131,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("abc %-4.5OTT");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("abc 123 ", result);
}
@@ -139,7 +139,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("abc %3.4hello");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("abc ello", result);
}
@@ -147,7 +147,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("abc %-3.-4hello");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("abc Hell", result);
}
@@ -168,7 +168,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("%(ABC %hello)");
p.setContext(c);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
StatusPrinter.print(c);
assertEquals("ABC Hello", result);
@@ -177,7 +177,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("%(ABC %hello)");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap,DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("ABC Hello", result);
}
@@ -189,7 +189,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("xyz %4.10(ABC)");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("xyz ABC", result);
}
@@ -198,7 +198,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("xyz %-4.10(ABC)");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("xyz ABC ", result);
}
@@ -207,7 +207,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("xyz %.2(ABC %hello)");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("xyz lo", result);
}
@@ -216,7 +216,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("xyz %.-2(ABC)");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("xyz AB", result);
}
@@ -225,7 +225,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("xyz %30.30(ABC %20hello)");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("xyz ABC Hello", result);
}
@@ -236,7 +236,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("%unknown");
p.setContext(context);
Node t = p.parse();
- p.compile(t, converterMap);
+ p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
StatusChecker chercker = new StatusChecker(context.getStatusManager());
assertTrue(chercker
.containsMatch("\\[unknown] is not a valid conversion word"));
@@ -248,7 +248,7 @@ public class CompilerTest {
Parser<Object> p = new Parser<Object>("xyz %hello\\_world");
p.setContext(context);
Node t = p.parse();
- Converter<Object> head = p.compile(t, converterMap);
+ Converter<Object> head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP);
String result = write(head, new Object());
assertEquals("xyz Helloworld", result);
}
diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java
index 6fab0fc..e220964 100644
--- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java
+++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java
@@ -25,6 +25,8 @@ import ch.qos.logback.core.pattern.FormatInfo;
public class ParserTest {
+ String BARE = Token.BARE_COMPOSITE_KEYWORD_TOKEN.getValue().toString();
+
@Test
public void testBasic() throws Exception {
Parser p = new Parser("hello");
@@ -40,7 +42,7 @@ public class ParserTest {
Parser p = new Parser("hello%xyz");
Node t = p.parse();
Node witness = new Node(Node.LITERAL, "hello");
- witness.next = new KeywordNode("xyz");
+ witness.next = new SimpleKeywordNode("xyz");
assertEquals(witness, t);
}
@@ -48,7 +50,7 @@ public class ParserTest {
Parser p = new Parser("hello%xyz{x}");
Node t = p.parse();
Node witness = new Node(Node.LITERAL, "hello");
- KeywordNode n = new KeywordNode("xyz");
+ SimpleKeywordNode n = new SimpleKeywordNode("xyz");
List<String> optionList = new ArrayList<String>();
optionList.add("x");
n.setOptions(optionList);
@@ -64,8 +66,8 @@ public class ParserTest {
Node t = p.parse();
Node witness = new Node(Node.LITERAL, "hello");
- CompositeNode composite = new CompositeNode();
- Node child = new KeywordNode("child");
+ CompositeNode composite = new CompositeNode(BARE);
+ Node child = new SimpleKeywordNode("child");
composite.setChildNode(child);
witness.next = composite;
@@ -81,8 +83,8 @@ public class ParserTest {
Node t = p.parse();
Node witness = new Node(Node.LITERAL, "hello");
- CompositeNode composite = new CompositeNode();
- Node child = new KeywordNode("child");
+ CompositeNode composite = new CompositeNode(BARE);
+ Node child = new SimpleKeywordNode("child");
composite.setChildNode(child);
witness.next = composite;
child.next = new Node(Node.LITERAL, " ");
@@ -93,11 +95,11 @@ public class ParserTest {
Parser p = new Parser("hello%(%child %h)");
Node t = p.parse();
Node witness = new Node(Node.LITERAL, "hello");
- CompositeNode composite = new CompositeNode();
- Node child = new KeywordNode("child");
+ CompositeNode composite = new CompositeNode(BARE);
+ Node child = new SimpleKeywordNode("child");
composite.setChildNode(child);
child.next = new Node(Node.LITERAL, " ");
- child.next.next = new KeywordNode("h");
+ child.next.next = new SimpleKeywordNode("h");
witness.next = composite;
assertEquals(witness, t);
}
@@ -106,14 +108,14 @@ public class ParserTest {
Parser p = new Parser("hello%(%child %h) %m");
Node t = p.parse();
Node witness = new Node(Node.LITERAL, "hello");
- CompositeNode composite = new CompositeNode();
- Node child = new KeywordNode("child");
+ CompositeNode composite = new CompositeNode(BARE);
+ Node child = new SimpleKeywordNode("child");
composite.setChildNode(child);
child.next = new Node(Node.LITERAL, " ");
- child.next.next = new KeywordNode("h");
+ child.next.next = new SimpleKeywordNode("h");
witness.next = composite;
composite.next = new Node(Node.LITERAL, " ");
- composite.next.next = new KeywordNode("m");
+ composite.next.next = new SimpleKeywordNode("m");
assertEquals(witness, t);
}
@@ -121,17 +123,17 @@ public class ParserTest {
Parser p = new Parser("hello%( %child \\(%h\\) ) %m");
Node t = p.parse();
Node witness = new Node(Node.LITERAL, "hello");
- CompositeNode composite = new CompositeNode();
+ CompositeNode composite = new CompositeNode(BARE);
Node child = new Node(Node.LITERAL, " ");
composite.setChildNode(child);
Node c = child;
- c = c.next = new KeywordNode("child");
+ c = c.next = new SimpleKeywordNode("child");
c = c.next = new Node(Node.LITERAL, " (");
- c = c.next = new KeywordNode("h");
+ c = c.next = new SimpleKeywordNode("h");
c = c.next = new Node(Node.LITERAL, ") ");
witness.next = composite;
composite.next = new Node(Node.LITERAL, " ");
- composite.next.next = new KeywordNode("m");
+ composite.next.next = new SimpleKeywordNode("m");
assertEquals(witness, t);
}
@@ -142,15 +144,15 @@ public class ParserTest {
{
Parser p = new Parser("%top %(%child%(%h))");
Node t = p.parse();
- Node witness = new KeywordNode("top");
+ Node witness = new SimpleKeywordNode("top");
Node w = witness.next = new Node(Node.LITERAL, " ");
- CompositeNode composite = new CompositeNode();
+ CompositeNode composite = new CompositeNode(BARE);
w = w.next = composite;
- Node child = new KeywordNode("child");
+ Node child = new SimpleKeywordNode("child");
composite.setChildNode(child);
- composite = new CompositeNode();
+ composite = new CompositeNode(BARE);
child.next = composite;
- composite.setChildNode(new KeywordNode("h"));
+ composite.setChildNode(new SimpleKeywordNode("h"));
assertEquals(witness, t);
}
@@ -161,14 +163,14 @@ public class ParserTest {
{
Parser p = new Parser("%45x");
Node t = p.parse();
- FormattingNode witness = new KeywordNode("x");
+ FormattingNode witness = new SimpleKeywordNode("x");
witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE));
assertEquals(witness, t);
}
{
Parser p = new Parser("%4.5x");
Node t = p.parse();
- FormattingNode witness = new KeywordNode("x");
+ FormattingNode witness = new SimpleKeywordNode("x");
witness.setFormatInfo(new FormatInfo(4, 5));
assertEquals(witness, t);
}
@@ -176,14 +178,14 @@ public class ParserTest {
{
Parser p = new Parser("%-4.5x");
Node t = p.parse();
- FormattingNode witness = new KeywordNode("x");
+ FormattingNode witness = new SimpleKeywordNode("x");
witness.setFormatInfo(new FormatInfo(4, 5, false, true));
assertEquals(witness, t);
}
{
Parser p = new Parser("%-4.-5x");
Node t = p.parse();
- FormattingNode witness = new KeywordNode("x");
+ FormattingNode witness = new SimpleKeywordNode("x");
witness.setFormatInfo(new FormatInfo(4, 5, false, false));
assertEquals(witness, t);
}
@@ -191,10 +193,10 @@ public class ParserTest {
{
Parser p = new Parser("%-4.5x %12y");
Node t = p.parse();
- FormattingNode witness = new KeywordNode("x");
+ FormattingNode witness = new SimpleKeywordNode("x");
witness.setFormatInfo(new FormatInfo(4, 5, false, true));
Node n = witness.next = new Node(Node.LITERAL, " ");
- n = n.next = new KeywordNode("y");
+ n = n.next = new SimpleKeywordNode("y");
((FormattingNode) n).setFormatInfo(new FormatInfo(12, Integer.MAX_VALUE));
assertEquals(witness, t);
}
@@ -205,7 +207,7 @@ public class ParserTest {
{
Parser p = new Parser("%45x{'test '}");
Node t = p.parse();
- KeywordNode witness = new KeywordNode("x");
+ SimpleKeywordNode witness = new SimpleKeywordNode("x");
witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE));
List<String> ol = new ArrayList<String>();
ol.add("test ");
@@ -216,7 +218,7 @@ public class ParserTest {
{
Parser p = new Parser("%45x{a, b}");
Node t = p.parse();
- KeywordNode witness = new KeywordNode("x");
+ SimpleKeywordNode witness = new SimpleKeywordNode("x");
witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE));
List<String> ol = new ArrayList<String>();
ol.add("a");
@@ -232,7 +234,7 @@ public class ParserTest {
{
Parser p = new Parser("%x{}a");
Node t = p.parse();
- KeywordNode witness = new KeywordNode("x");
+ SimpleKeywordNode witness = new SimpleKeywordNode("x");
witness.next = new Node(Node.LITERAL, "a");
assertEquals(witness, t);
}
@@ -246,7 +248,7 @@ public class ParserTest {
Node t = p.parse();
Node witness = new Node(Node.LITERAL, "hello");
- CompositeNode composite = new CompositeNode();
+ CompositeNode composite = new CompositeNode(BARE);
composite.setFormatInfo(new FormatInfo(5, Integer.MAX_VALUE));
Node child = new Node(Node.LITERAL, "XYZ");
composite.setChildNode(child);
diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java
index d737a56..c9d12a0 100644
--- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java
+++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java
@@ -74,7 +74,7 @@ public class TokenStreamTest {
List tl = new TokenStream("%c").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "c"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "c"));
assertEquals(witness, tl);
}
@@ -83,9 +83,9 @@ public class TokenStreamTest {
List tl = new TokenStream("%a%b").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "a"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "a"));
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "b"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "b"));
assertEquals(witness, tl);
}
@@ -96,7 +96,7 @@ public class TokenStreamTest {
witness.add(new Token(Token.LITERAL, "xyz"));
witness.add(Token.PERCENT_TOKEN);
witness.add(new Token(Token.FORMAT_MODIFIER, "-34"));
- witness.add(new Token(Token.KEYWORD, "c"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "c"));
assertEquals(witness, tl);
}
}
@@ -106,15 +106,15 @@ public class TokenStreamTest {
List tl = new TokenStream("%d{1234} [%34.-67toto] %n").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "d"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "d"));
witness.add(new Token(Token.OPTION, "1234"));
witness.add(new Token(Token.LITERAL, " ["));
witness.add(Token.PERCENT_TOKEN);
witness.add(new Token(Token.FORMAT_MODIFIER, "34.-67"));
- witness.add(new Token(Token.KEYWORD, "toto"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "toto"));
witness.add(new Token(Token.LITERAL, "] "));
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "n"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "n"));
assertEquals(witness, tl);
}
@@ -132,7 +132,7 @@ public class TokenStreamTest {
List tl = new TokenStream("%()").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(Token.LEFT_PARENTHESIS_TOKEN);
+ witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN);
witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
assertEquals(witness, tl);
}
@@ -158,7 +158,7 @@ public class TokenStreamTest {
List<Token> witness = new ArrayList<Token>();
witness.add(new Token(Token.LITERAL, "\\"));
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "x"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "x"));
assertEquals(witness, tl);
}
@@ -166,7 +166,7 @@ public class TokenStreamTest {
List tl = new TokenStream("%x\\)").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "x"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "x"));
witness.add(new Token(Token.LITERAL, ")"));
assertEquals(witness, tl);
}
@@ -175,7 +175,7 @@ public class TokenStreamTest {
List tl = new TokenStream("%x\\_a").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "x"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "x"));
witness.add(new Token(Token.LITERAL, "a"));
assertEquals(witness, tl);
}
@@ -183,9 +183,9 @@ public class TokenStreamTest {
List tl = new TokenStream("%x\\_%b").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "x"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "x"));
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "b"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "b"));
assertEquals(witness, tl);
}
}
@@ -196,7 +196,7 @@ public class TokenStreamTest {
List tl = new TokenStream("%x{t}").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "x"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "x"));
witness.add(new Token(Token.OPTION, "t"));
assertEquals(witness, tl);
}
@@ -205,7 +205,7 @@ public class TokenStreamTest {
List tl = new TokenStream("%x{t,y}").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "x"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "x"));
witness.add(new Token(Token.OPTION, "t,y"));
assertEquals(witness, tl);
}
@@ -214,7 +214,7 @@ public class TokenStreamTest {
List tl = new TokenStream("%x{\"hello world.\", \"12y \"}").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "x"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "x"));
witness.add(new Token(Token.OPTION, "\"hello world.\", \"12y \""));
assertEquals(witness, tl);
}
@@ -223,7 +223,7 @@ public class TokenStreamTest {
List tl = new TokenStream("%x{opt\\}}").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "x"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "x"));
witness.add(new Token(Token.OPTION, "opt}"));
assertEquals(witness, tl);
}
@@ -234,10 +234,10 @@ public class TokenStreamTest {
List tl = new TokenStream("%(hello %class{.4?})").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(Token.LEFT_PARENTHESIS_TOKEN);
+ witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN);
witness.add(new Token(Token.LITERAL, "hello "));
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "class"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "class"));
witness.add(new Token(Token.OPTION, ".4?"));
witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
assertEquals(witness, tl);
@@ -249,14 +249,14 @@ public class TokenStreamTest {
List<Token> witness = new ArrayList<Token>();
witness.add(new Token(Token.LITERAL, "X "));
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "a"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "a"));
witness.add(new Token(Token.LITERAL, " "));
witness.add(Token.PERCENT_TOKEN);
witness.add(new Token(Token.FORMAT_MODIFIER, "-12.550"));
- witness.add(Token.LEFT_PARENTHESIS_TOKEN);
+ witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN);
witness.add(new Token(Token.LITERAL, "hello "));
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "class"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "class"));
witness.add(new Token(Token.OPTION, ".4?"));
witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
assertEquals(witness, tl);
@@ -268,18 +268,18 @@ public class TokenStreamTest {
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
witness.add(new Token(Token.FORMAT_MODIFIER, "-1"));
- witness.add(Token.LEFT_PARENTHESIS_TOKEN);
+ witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN);
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "d"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "d"));
witness.add(new Token(Token.LITERAL, " "));
witness.add(Token.PERCENT_TOKEN);
witness.add(new Token(Token.FORMAT_MODIFIER, "45"));
- witness.add(Token.LEFT_PARENTHESIS_TOKEN);
+ witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN);
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "class"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "class"));
witness.add(new Token(Token.LITERAL, " "));
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "file"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "file"));
witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
@@ -291,13 +291,13 @@ public class TokenStreamTest {
List tl = new TokenStream("%(%a%(%b))").tokenize();
List<Token> witness = new ArrayList<Token>();
witness.add(Token.PERCENT_TOKEN);
- witness.add(Token.LEFT_PARENTHESIS_TOKEN);
+ witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN);
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "a"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "a"));
witness.add(Token.PERCENT_TOKEN);
- witness.add(Token.LEFT_PARENTHESIS_TOKEN);
+ witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN);
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "b"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "b"));
witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
@@ -312,7 +312,7 @@ public class TokenStreamTest {
List<Token> witness = new ArrayList<Token>();
witness.add(new Token(Token.LITERAL, "("));
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "h"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "h"));
witness.add(new Token(Token.LITERAL, ")"));
assertEquals(witness, tl);
}
@@ -321,7 +321,7 @@ public class TokenStreamTest {
List<Token> witness = new ArrayList<Token>();
witness.add(new Token(Token.LITERAL, "("));
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "h"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "h"));
witness.add(new Token(Token.LITERAL, ")"));
assertEquals(witness, tl);
}
@@ -329,14 +329,54 @@ public class TokenStreamTest {
@Test
public void testWindowsLikeBackSlashes() throws ScanException {
- {
- List tl = new TokenStream("c:\\hello\\world.%i",
- new AlmostAsIsEscapeUtil()).tokenize();
+ List tl = new TokenStream("c:\\hello\\world.%i",
+ new AlmostAsIsEscapeUtil()).tokenize();
+
+ List<Token> witness = new ArrayList<Token>();
+ witness.add(new Token(Token.LITERAL, "c:\\hello\\world."));
+ witness.add(Token.PERCENT_TOKEN);
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "i"));
+ assertEquals(witness, tl);
+ }
+ @Test
+ public void compositedKeyword() throws ScanException {
+ {
+ List tl = new TokenStream("%d(A)",
+ new AlmostAsIsEscapeUtil()).tokenize();
+ List<Token> witness = new ArrayList<Token>();
+ witness.add(Token.PERCENT_TOKEN);
+ witness.add(new Token(Token.COMPOSITE_KEYWORD, "d"));
+ witness.add(new Token(Token.LITERAL, "A"));
+ witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
+ assertEquals(witness, tl);
+ }
+ {
+ List tl = new TokenStream("a %subst(%b C)",
+ new AlmostAsIsEscapeUtil()).tokenize();
List<Token> witness = new ArrayList<Token>();
- witness.add(new Token(Token.LITERAL, "c:\\hello\\world."));
+ witness.add(new Token(Token.LITERAL, "a "));
+ witness.add(Token.PERCENT_TOKEN);
+ witness.add(new Token(Token.COMPOSITE_KEYWORD, "subst"));
witness.add(Token.PERCENT_TOKEN);
- witness.add(new Token(Token.KEYWORD, "i"));
+ witness.add(new Token(Token.SIMPLE_KEYWORD, "b"));
+ witness.add(new Token(Token.LITERAL, " C"));
+ witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
+ assertEquals(witness, tl);
+ }
+ }
+ @Test
+ public void compositedKeywordFollowedByOptions() throws ScanException {
+ {
+ List tl = new TokenStream("%d(A){o}",
+ new AlmostAsIsEscapeUtil()).tokenize();
+ List<Token> witness = new ArrayList<Token>();
+ witness.add(Token.PERCENT_TOKEN);
+ witness.add(new Token(Token.COMPOSITE_KEYWORD, "d"));
+ witness.add(new Token(Token.LITERAL, "A"));
+ witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
+ witness.add(new Token(Token.OPTION, "o"));
+
assertEquals(witness, tl);
}
}
-----------------------------------------------------------------------
Summary of changes:
goscp | 3 +
.../qos/logback/classic/pattern/DateConverter.java | 1 +
.../classic/turbo/ReconfigureOnChangeTest.java | 2 +-
.../ch/qos/logback/core/OutputStreamAppender.java | 5 +-
.../ch/qos/logback/core/html/HTMLLayoutBase.java | 2 +-
.../logback/core/pattern/CompositeConverter.java | 16 +-
.../ch/qos/logback/core/pattern/ConverterUtil.java | 15 +-
.../qos/logback/core/pattern/DynamicConverter.java | 8 +-
.../core/pattern/IdentityCompositeConverter.java | 13 +-
.../logback/core/pattern/PatternLayoutBase.java | 2 +-
.../core/pattern/ReplacingCompositeConverter.java | 25 ++--
.../qos/logback/core/pattern/parser/Compiler.java | 109 +++++++----
.../logback/core/pattern/parser/CompositeNode.java | 7 +-
.../ch/qos/logback/core/pattern/parser/Node.java | 4 +-
.../core/pattern/parser/OptionTokenizer.java | 2 +-
.../ch/qos/logback/core/pattern/parser/Parser.java | 89 +++++++---
.../{KeywordNode.java => SimpleKeywordNode.java} | 124 +++++++------
.../ch/qos/logback/core/pattern/parser/Token.java | 17 +-
.../logback/core/pattern/parser/TokenStream.java | 189 +++++++++++---------
.../core/rolling/helper/FileNamePattern.java | 2 +-
.../test/java/ch/qos/logback/core/AllCoreTest.java | 4 +-
.../logback/core/pattern/parser/CompilerTest.java | 42 +++---
.../logback/core/pattern/parser/ParserTest.java | 66 ++++----
.../core/pattern/parser/TokenStreamTest.java | 116 ++++++++----
24 files changed, 495 insertions(+), 368 deletions(-)
create mode 100644 goscp
copy logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/NestedType.groovy => logback-core/src/main/java/ch/qos/logback/core/pattern/IdentityCompositeConverter.java (73%)
copy logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/AppenderDelegate.groovy => logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java (53%)
rename logback-core/src/main/java/ch/qos/logback/core/pattern/parser/{KeywordNode.java => SimpleKeywordNode.java} (71%)
hooks/post-receive
--
Logback: the generic, reliable, fast and flexible logging framework.
1
0

[JIRA] Created: (LBCLASSIC-237) create a DelegateAppender which delegates all events to multiple child appenders
by subes (JIRA) 13 Dec '10
by subes (JIRA) 13 Dec '10
13 Dec '10
create a DelegateAppender which delegates all events to multiple child appenders
--------------------------------------------------------------------------------
Key: LBCLASSIC-237
URL: http://jira.qos.ch/browse/LBCLASSIC-237
Project: logback-classic
Issue Type: New Feature
Components: appender
Affects Versions: unspecified
Reporter: subes
Assignee: Logback dev list
Hi,
I'm using LogBack now since some time and got a config that suits me quite well, which i even modularized by merging multiple logback xml files to one and giving that as the configuration to logback. Thats needed because I am building a modular software productline with decentral configuration per module which have their own eclipse project.
I have two default console appenders. One for System.out (level<=INFO) called "stdout" and another one for System.err (level>=WARN) called "stderr".
On top of that I got two default log files. One for all the stuff that goes to both console appenders called "default" and another one for detailed error stacktraces called "error". I do that because I filter stacktraces for console but still want to have access to the complete stacktraces in another log file specific for that purpose. And beside those loggers my modules can create other file appenders like sql.log or messages.log and stuff.
Now to my point: Because I have 4 appenders I almost always use together (2x console and 2x file), i have quite a lot of appender-refs I have to write on my logger definitions. To help with that, I would like to have an appender (called "common") which has the other 4 appenders as children like this:
<appender name="common" class="...logback...DelegatingAppender">
<appender-ref ref="stdout" />
<appender-ref ref="stderr" />
<appender-ref ref="default" />
<appender-ref ref="error" />
<!-- also nice would be to have a hidden appender that can't be directly used in loggers, but not actually required for my purposes -->
<appender name="hiddenAndThusNameShouldNotBeNeeded" class="...SomeClass">
<!-- ... some configuration ... -->
</appender>
</appender>
With that I could either just put "common" on a logger to print to all 4 appenders or I would still have the flexibility to specify only one of those appers.
I tried to implement this on my own, Implementing the appender class itself wasn't a problem, but I don't get how to make joran to understand the appender-ref and insert the delegate appender class into my DelegatingAppender via some setter. It would be nice if you could either include this as a feature into logback-classic or help me out writing it on my own. :)
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
2

[GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-41-gfc45086
by git-noreply@pixie.qos.ch 13 Dec '10
by git-noreply@pixie.qos.ch 13 Dec '10
13 Dec '10
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Logback: the generic, reliable, fast and flexible logging framework.".
The branch, master has been updated
via fc4508616906b773dd9d93d4e0d2c45628d3f7b5 (commit)
from 1c9ce863a577cf5075088eb66ca5353f4de0e209 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=fc4508616906b773dd9d93d4…
http://github.com/ceki/logback/commit/fc4508616906b773dd9d93d4e0d2c45628d3f…
commit fc4508616906b773dd9d93d4e0d2c45628d3f7b5
Author: Ceki Gulcu <ceki(a)qos.ch>
Date: Mon Dec 13 17:17:28 2010 +0100
add support for dynamic destination address computation in SMTPAppender
diff --git a/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java b/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java
index 40917f3..43590ed 100644
--- a/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java
+++ b/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java
@@ -182,5 +182,4 @@ public class PatternLayout extends PatternLayoutBase<AccessEvent> {
}
super.start();
}
-
}
diff --git a/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java b/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java
index 4d48cc8..4584e4f 100644
--- a/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java
+++ b/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java
@@ -79,4 +79,12 @@ public class SMTPAppender extends SMTPAppenderBase<AccessEvent> {
pl.start();
return pl;
}
+
+ protected PatternLayout makeNewToPatternLayout(String toPattern) {
+ PatternLayout pl = new PatternLayout();
+ pl.setPattern(toPattern);
+ return pl;
+ }
+
+
}
diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java b/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java
index a3fc208..3a6442d 100644
--- a/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java
+++ b/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java
@@ -139,5 +139,4 @@ public class PatternLayout extends PatternLayoutBase<ILoggingEvent> {
}
return writeLoopOnConverters(event);
}
-
}
diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java
index c30e24c..262bd91 100644
--- a/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java
+++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java
@@ -101,4 +101,10 @@ public class SMTPAppender extends SMTPAppenderBase<ILoggingEvent> {
pl.start();
return pl;
}
+
+ protected PatternLayout makeNewToPatternLayout(String toPattern) {
+ PatternLayout pl = new PatternLayout();
+ pl.setPattern(toPattern+"%nopex");
+ return pl;
+ }
}
diff --git a/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegateTest.groovy b/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegateTest.groovy
index ea94697..2e5d65f 100644
--- a/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegateTest.groovy
+++ b/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegateTest.groovy
@@ -189,7 +189,7 @@ class ConfigurationDelegateTest {
PatternLayout layout = sa.layout
assertEquals("%m%n", layout.pattern)
- assertEquals(["a", "b"], sa.toList.sort());
+ assertEquals(["a%nopex", "b%nopex"], sa.getToAsListOfString().sort());
}
// test parent injection
diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java
index 5e3f912..53bbc0c 100644
--- a/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java
+++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java
@@ -81,9 +81,7 @@ public class DilutedSMTPAppenderTest {
addressArray = null;
address = null;
- addressArray = appender.getMessage().getAllRecipients();
- address = addressArray[0];
- assertEquals("sebastien.nospam(a)qos.ch", address.toString());
+ assertEquals("sebastien.nospam(a)qos.ch%nopex", appender.getToAsListOfString().get(0));
assertEquals("logging report", appender.getSubject());
diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/PackageTest.java
index 076d7ca..f97ea53 100644
--- a/logback-classic/src/test/java/ch/qos/logback/classic/net/PackageTest.java
+++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/PackageTest.java
@@ -19,6 +19,7 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses( { SyslogAppenderTest.class, DilutedSMTPAppenderTest.class,
- SocketAppenderTest.class, JMSQueueAppenderTest.class, JMSTopicAppenderTest.class })
+ SocketAppenderTest.class, JMSQueueAppenderTest.class, JMSTopicAppenderTest.class,
+ SMTPAppender_GreenTest.class, SMTPAppender_SubethaSMTPTest.class })
public class PackageTest {
}
\ No newline at end of file
diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java
index 6d1ee31..01f9dbe 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java
@@ -35,6 +35,7 @@ import ch.qos.logback.core.Layout;
import ch.qos.logback.core.boolex.EvaluationException;
import ch.qos.logback.core.boolex.EventEvaluator;
import ch.qos.logback.core.helpers.CyclicBuffer;
+import ch.qos.logback.core.pattern.PatternLayoutBase;
import ch.qos.logback.core.sift.DefaultDiscriminator;
import ch.qos.logback.core.sift.Discriminator;
import ch.qos.logback.core.spi.CyclicBufferTracker;
@@ -58,18 +59,21 @@ import ch.qos.logback.core.util.OptionHelper;
*/
public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
-
+ static InternetAddress[] EMPTY_IA_ARRAY = new InternetAddress[0];
// ~ 14 days
static final int MAX_DELAY_BETWEEN_STATUS_MESSAGES = 1228800 * CoreConstants.MILLIS_IN_ONE_SECOND;
long lastTrackerStatusPrint = 0;
int delayBetweenStatusMessages = 300 * CoreConstants.MILLIS_IN_ONE_SECOND;
+
+
+
protected Layout<E> subjectLayout;
protected Layout<E> layout;
- private List<String> toList = new ArrayList<String>();
+ private List<PatternLayoutBase<E>> toPatternLayoutList = new ArrayList<PatternLayoutBase<E>>();
private String from;
private String subjectStr = null;
private String smtpHost;
@@ -150,8 +154,6 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
mimeMsg.setFrom();
}
- mimeMsg.setRecipients(Message.RecipientType.TO, parseAddress(toList));
-
subjectLayout = makeSubjectLayout(subjectStr);
started = true;
@@ -190,7 +192,7 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
if (lastTrackerStatusPrint + delayBetweenStatusMessages < now) {
addInfo("SMTPAppender [" + name + "] is tracking [" + cbTracker.size() + "] buffers");
lastTrackerStatusPrint = now;
- // quadruple 'delay' assuming less than max delay
+ // quadruple 'delay' assuming less than max delay
if (delayBetweenStatusMessages < MAX_DELAY_BETWEEN_STATUS_MESSAGES) {
delayBetweenStatusMessages *= 4;
}
@@ -246,29 +248,35 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
}
}
- InternetAddress[] parseAddress(List<String> addressList) {
+ private List<InternetAddress> parseAddress(E event) {
+ int len = toPatternLayoutList.size();
- InternetAddress[] iaArray = new InternetAddress[addressList.size()];
+ List<InternetAddress> iaList = new ArrayList<InternetAddress>();
- for (int i = 0; i < addressList.size(); i++) {
+ for (int i = 0; i < len; i++) {
try {
- InternetAddress[] tmp = InternetAddress.parse(addressList.get(i), true);
+ PatternLayoutBase<E> emailPL = toPatternLayoutList.get(i);
+ String email = emailPL.doLayout(event);
+ if(email == null || email.length() == 0) {
+ continue;
+ }
+ InternetAddress[] tmp = InternetAddress.parse(email, true);
// one <To> element should contain one email address
- iaArray[i] = tmp[0];
+ iaList.add(tmp[0]);
} catch (AddressException e) {
- addError("Could not parse address [" + addressList.get(i) + "].", e);
- return null;
+ addError("Could not parse email address for [" + toPatternLayoutList.get(i) + "] for event ["+event+"]", e);
+ return iaList;
}
}
- return iaArray;
+ return iaList;
}
/**
* Returns value of the <b>toList</b> option.
*/
- public List<String> getToList() {
- return toList;
+ public List<PatternLayoutBase<E>> getToList() {
+ return toPatternLayoutList;
}
/**
@@ -306,6 +314,13 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
charsetEncoding);
}
+ List<InternetAddress> destinationAddresses = parseAddress(lastEventObject);
+ if(destinationAddresses.isEmpty()) {
+ addInfo("Empty destination address. Aborting email transmission");
+ return;
+ }
+ mimeMsg.setRecipients(Message.RecipientType.TO, destinationAddresses.toArray(EMPTY_IA_ARRAY));
+
String contentType = layout.getContentType();
if (ContentTypeUtil.isTextual(contentType)) {
@@ -326,6 +341,8 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
}
}
+
+
abstract protected void fillBuffer(CyclicBuffer<E> cb, StringBuffer sbuf);
/**
@@ -437,17 +454,28 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
this.discriminator = discriminator;
}
- /**
- * The <b>To</b> option takes a string value which should be an e-mail address
- * of one of the recipients.
- */
public void addTo(String to) {
- this.toList.add(to);
+ if(to == null || to.length() == 0) {
+ throw new IllegalArgumentException("Null or empty <to> property");
+ }
+ PatternLayoutBase plb = makeNewToPatternLayout(to.trim());
+ plb.setContext(context);
+ plb.start();
+ this.toPatternLayoutList.add(plb);
}
- // for testing purpose only
+ abstract protected PatternLayoutBase<E> makeNewToPatternLayout(String toPattern);
+
+ public List<String> getToAsListOfString() {
+ List<String> toList = new ArrayList<String>();
+ for(PatternLayoutBase plb: toPatternLayoutList) {
+ toList.add(plb.getPattern());
+ }
+ return toList;
+ }
- public Message getMessage() {
+ // for testing purpose only
+ public Message getMessage() {
return mimeMsg;
}
diff --git a/logback-site/src/site/pages/recipes/captureHttp.html b/logback-site/src/site/pages/recipes/captureHttp.html
index 244478a..86488e6 100644
--- a/logback-site/src/site/pages/recipes/captureHttp.html
+++ b/logback-site/src/site/pages/recipes/captureHttp.html
@@ -200,11 +200,11 @@ Set-Cookie: JSESSIONID=bgebt99ce9om;path=/logback-demo
probe made by the load-balancer.
</p>
- <p>We need to a way to filter-out these probes so that they are
- no longer contaminate the log output. However, we need a way to
+ <p>We need to a way to filter-out these probes so that they no
+ longer contaminate the log output. In other words, we need to
distinguish probes emanating from the load-balancer from other
- requests that we deem desirable. The contents of the requests
- can give you clues about possible criteria.</p>
+ requests. The contents of the probes can give us clues about
+ possible distinguishing criteria.</p>
<p>Here is a sample probe as logged by logback-access:</p>
@@ -218,16 +218,17 @@ X-Powered-By: Servlet 2.4;
Cache-Control: no-cache
Pragma: No-cache </pre>
- <p>From the above, we can see that the load-blancer probes use
- the <a
+ <p>From the above, we can see that the load-blancer probes
+ employ the <a
href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4">HTTP
HEAD method</a> instead of the usual GET or POST. We can also
see that the request URI for the probes contains the string
"probe".</p>
<p>Here is a <em>logback-access.xml</em> configuration file
- which will deny any access event which uses the HEAD
- method. Note that it is based on Janino.</p>
+ which will deny any <code>AccessEvent</code> where the method is
+ HEAD. Note that events are evaluated using
+ <code>JaninoEventEvaluator</code> which requires Janino.</p>
<pre class="prettyprint source"><configuration>
<!-- always a good idea to install OnConsoleStatusListener -->
-----------------------------------------------------------------------
Summary of changes:
.../java/ch/qos/logback/access/PatternLayout.java | 1 -
.../ch/qos/logback/access/net/SMTPAppender.java | 8 ++
.../java/ch/qos/logback/classic/PatternLayout.java | 1 -
.../ch/qos/logback/classic/net/SMTPAppender.java | 6 ++
.../gaffer/ConfigurationDelegateTest.groovy | 2 +-
.../classic/net/DilutedSMTPAppenderTest.java | 4 +-
.../ch/qos/logback/classic/net/PackageTest.java | 3 +-
.../ch/qos/logback/core/net/SMTPAppenderBase.java | 72 ++++++++++++++------
.../src/site/pages/recipes/captureHttp.html | 17 +++--
9 files changed, 77 insertions(+), 37 deletions(-)
hooks/post-receive
--
Logback: the generic, reliable, fast and flexible logging framework.
1
0

[JIRA] Created: (LBCLASSIC-236) Provide a way to tell wether logback has defaulted to a default configuration.
by Eric Estievenart (JIRA) 11 Dec '10
by Eric Estievenart (JIRA) 11 Dec '10
11 Dec '10
Provide a way to tell wether logback has defaulted to a default configuration.
------------------------------------------------------------------------------
Key: LBCLASSIC-236
URL: http://jira.qos.ch/browse/LBCLASSIC-236
Project: logback-classic
Issue Type: Improvement
Affects Versions: 0.9.26
Reporter: Eric Estievenart
Assignee: Logback dev list
Priority: Minor
There is no way to know if logback is using its default configuration or one supplied explicitly or found in resources.
LoggerContext.getName() returns "default" for the default config or for one which has no name given.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0

[JIRA] Created: (LBCLASSIC-235) Should log an error if -Dlogback.configurationFile but not found, and not attempt default config
by Eric Estievenart (JIRA) 11 Dec '10
by Eric Estievenart (JIRA) 11 Dec '10
11 Dec '10
Should log an error if -Dlogback.configurationFile but not found, and not attempt default config
------------------------------------------------------------------------------------------------
Key: LBCLASSIC-235
URL: http://jira.qos.ch/browse/LBCLASSIC-235
Project: logback-classic
Issue Type: Bug
Affects Versions: 0.9.26
Reporter: Eric Estievenart
Assignee: Logback dev list
$ java -Dlogback.configurationFile=missingfile.xml -cp .... MyClass
>> no output is generated
A status dump says:
16:14:01,778 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [missingfile.xml]
16:14:01,779 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
16:14:01,779 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
16:14:01,780 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
16:14:01,786 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Setting up default configuration.
First, logback should issue an error saying that the explicitely selected 'missingfile' was not found.
Then I don't thing that it should try to load default config files, since one has been requested by the user.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0

[JIRA] Created: (LBCORE-183) race condition when creating log directory in multithreaded environment
by Mats Henrikson (JIRA) 08 Dec '10
by Mats Henrikson (JIRA) 08 Dec '10
08 Dec '10
race condition when creating log directory in multithreaded environment
-----------------------------------------------------------------------
Key: LBCORE-183
URL: http://jira.qos.ch/browse/LBCORE-183
Project: logback-core
Issue Type: Bug
Components: Other
Affects Versions: 0.9.26
Reporter: Mats Henrikson
Assignee: Logback dev list
Attachments: parent_dirs.patch
There is a race condition when multiple threads are trying to create the same parent log directory in logback:
{noformat}
java.lang.IllegalStateException: /path/to/log/dir/2010/2010_12/2010_12_08/file.log should not have existing parent directory
at ch.qos.logback.core.util.FileUtil.createMissingParentDirectories(FileUtil.java:43) ~[logback-core-0.9.26.jar:na]
at ch.qos.logback.core.FileAppender.openFile(FileAppender.java:156) ~[logback-core-0.9.26.jar:na]
at ch.qos.logback.core.FileAppender.start(FileAppender.java:115) ~[logback-core-0.9.26.jar:na]
[...]
{noformat}
It is completely ok for the check to start if the directory is there and then have the directory appear when we actually come around to creating it. This is because you may have multiple threads wanting to log to the same directory, and if they try to create the dir at the same time one will succeed and one will have it already created. This happens for instance in the case above where a new dir is created at midnight every day, and two threads log at the same time.
Will attach a patch that fixes the problem.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
2
3

[JIRA] Created: (LBACCESS-18) NPE is case of desrialized AccessEvent
by Denis Bazhenov (JIRA) 08 Dec '10
by Denis Bazhenov (JIRA) 08 Dec '10
08 Dec '10
NPE is case of desrialized AccessEvent
--------------------------------------
Key: LBACCESS-18
URL: http://jira.qos.ch/browse/LBACCESS-18
Project: logback-access
Issue Type: Bug
Affects Versions: 0.9.26
Environment: Sun Java HotSpot(TM) 64-Bit Server VM (build 16.2-b04, mixed mode)
CentOS Linux 2.6.18-164.el5 #1 SMP Thu Sep 3 03:28:30 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
Reporter: Denis Bazhenov
Assignee: Logback dev list
I'm trying to use SimpleSocketServer (from logback-access) for remote logging of AccessEvent's. The problem I faced is following. When object get deserialized in SocketNode on line 64 it has no httpRequest (it's simply null). There is debugger dump of event:
event = instance of ch.qos.logback.access.spi.AccessEvent(id=932)
Thread-1[1] dump event
event = {
serialVersionUID: 866718993618836343
NA: "-"
NA_STRING_ARRAY: instance of java.lang.String[1] (id=914)
EMPTY: ""
SENTINEL: -1
httpRequest: null
httpResponse: null
requestURI: "/"
requestURL: "GET / HTTP/1.1"
remoteHost: "192.168.20.179"
remoteUser: null
remoteAddr: "192.168.20.179"
protocol: "HTTP/1.1"
method: "GET"
serverName: "jetty-test"
requestContent: ""
responseContent: ""
requestHeaderMap: instance of java.util.TreeMap(id=938)
requestParameterMap: instance of java.util.HashMap(id=939)
responseHeaderMap: instance of java.util.HashMap(id=940)
contentLength: 1288
statusCode: 503
localPort: 8080
serverAdapter: null
timeStamp: 1291621192027
}
So later this gives me NPE in AccessEvent.buildRequestHeaderMap().
I have following logback-access.xml for client
<configuration debug="true">
<appender name="SOCKET" class="ch.qos.logback.access.net.SocketAppender">
<remoteHost>logs.vfarm.loc</remoteHost>
<port>6000</port>
<reconnectionDelay>100</reconnectionDelay>
<includeCallerData>true</includeCallerData>
</appender>
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>/var/log/jetty/access.log</File>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>access.%d{yyyy-MM-dd}.log.zip</FileNamePattern>
</rollingPolicy>
<layout class="ch.qos.logback.access.PatternLayout">
<Pattern>combined</Pattern>
</layout>
</appender>
<appender-ref ref="FILE" />
<appender-ref ref="SOCKET" />
</configuration>
So logs are written locally (sucessfully) and sent over network to logs.vfarm.loc. On logs.vfarm.loc I have running SimpleSocketServer:
java -cp jetty-6.1.24.jar:\
servlet-api-2.5.jar:\
logback-access-0.9.26.jar:\
slf4j-api-1.6.1.jar:\
logback-core-0.9.26.jar \
ch.qos.logback.access.net.SimpleSocketServer 6000 access.xml
with following access.xml
<configuration debug="true">
<!--<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>access.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>access.%d{yyyy-MM-dd}.log.zip</FileNamePattern>
</rollingPolicy>
<encoder class="ch.qos.logback.access.PatternLayoutEncoder">
<Pattern>combined</Pattern>
</encoder>
</appender>-->
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.access.PatternLayoutEncoder">
<Pattern>combined</Pattern>
</encoder>
</appender>
<appender-ref ref="STDOUT" />
<!--<appender-ref ref="FILE" />-->
</configuration>
I think this issue is closely related to LBACCESS-6, but it's still reproducible.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
3

[JIRA] Created: (LBACCESS-21) Report the request duration in logback-access
by Eric Estievenart (JIRA) 06 Dec '10
by Eric Estievenart (JIRA) 06 Dec '10
06 Dec '10
Report the request duration in logback-access
---------------------------------------------
Key: LBACCESS-21
URL: http://jira.qos.ch/browse/LBACCESS-21
Project: logback-access
Issue Type: Improvement
Affects Versions: 0.9.26
Environment: any
Reporter: Eric Estievenart
Assignee: Logback dev list
It would be great if the access valve (and corresponding in jetty/other) also stored the processing duration
of the request within the container.
For example add a %d field which would return this time in ms.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0