[logback-dev] svn commit: r1706 - in logback/trunk: logback-classic/src/main/java/org/slf4j/impl logback-core/src/main/java/ch/qos/logback/core logback-core/src/main/java/ch/qos/logback/core/joran/action logback-core/src/main/java/ch/qos/logback/core/pattern/parser logback-core/src/main/java/ch/qos/logback/core/pattern/util logback-core/src/main/java/ch/qos/logback/core/rolling/helper logback-core/src/main/java/ch/qos/logback/core/util logback-core/src/test/java/ch/qos/logback/core/pattern/parser logback-core/src/test/java/ch/qos/logback/core/rolling/helper
noreply.ceki at qos.ch
noreply.ceki at qos.ch
Mon Jul 14 21:32:00 CEST 2008
Author: ceki
Date: Mon Jul 14 21:31:59 2008
New Revision: 1706
Added:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/IEscapeUtil.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java
- copied, changed from r1704, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/EscapeUtil.java
Removed:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/EscapeUtil.java
Modified:
logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java
Log:
- fixes LBCLASSIC-56
Escaping is implemented selectively. Cerated a new interface called EscapeUtil.
In particular, FileNamePattern now uses AlmostAsIsEscapeUtil.
See also http://jira.qos.ch/browse/LBCLASSIC-56
Modified: logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java (original)
+++ logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java Mon Jul 14 21:31:59 2008
@@ -86,7 +86,10 @@
}
static ContextSelector dynamicalContextSelector(
- LoggerContext defaultLoggerContext, String contextSelectorStr) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
+ LoggerContext defaultLoggerContext, String contextSelectorStr)
+ throws ClassNotFoundException, SecurityException, NoSuchMethodException,
+ IllegalArgumentException, InstantiationException, IllegalAccessException,
+ InvocationTargetException {
Class contextSelectorClass = Loader.loadClass(contextSelectorStr);
Constructor cons = contextSelectorClass
.getConstructor(new Class[] { LoggerContext.class });
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java Mon Jul 14 21:31:59 2008
@@ -44,5 +44,8 @@
* An empty Class array.
*/
public final static Class[] EMPTY_CLASS_ARRAY = new Class[] {};
- static public final String CAUSED_BY = "Caused by: ";
+ public final static String CAUSED_BY = "Caused by: ";
+
+
+ public final static char PERCENT_CHAR = '%';
}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java Mon Jul 14 21:31:59 2008
@@ -12,7 +12,7 @@
import org.xml.sax.Attributes;
import ch.qos.logback.core.joran.spi.InterpretationContext;
-import ch.qos.logback.core.pattern.util.EscapeUtil;
+import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
import ch.qos.logback.core.util.OptionHelper;
@@ -65,7 +65,7 @@
} else if (
!(OptionHelper.isEmpty(name) || OptionHelper.isEmpty(value))
&& OptionHelper.isEmpty(fileName)) {
- value = EscapeUtil.basicEscape(value);
+ value = RegularEscapeUtil.basicEscape(value);
// now remove both leading and trailing spaces
value = value.trim();
setProperty(ec, name, value);
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java Mon Jul 14 21:31:59 2008
@@ -3,7 +3,9 @@
import java.util.ArrayList;
import java.util.List;
-import ch.qos.logback.core.pattern.util.EscapeUtil;
+import ch.qos.logback.core.CoreGlobal;
+import ch.qos.logback.core.pattern.util.IEscapeUtil;
+import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
public class OptionTokenizer {
@@ -16,15 +18,26 @@
private static final char DOUBLE_QUOTE_CHAR = '"';
private static final char SINGLE_QUOTE_CHAR = '\'';
- String pattern;
- int patternLength;
+ final String pattern;
+ final int patternLength;
+ final IEscapeUtil escapeUtil;
+
char quoteChar;
int pointer = 0;
int state = EXPECTING_STATE;
+ /**
+ * This variant is used in tests
+ * @param pattern
+ */
OptionTokenizer(String pattern) {
+ this(pattern, new RegularEscapeUtil());
+ }
+
+ OptionTokenizer(String pattern, IEscapeUtil escapeUtil) {
this.pattern = pattern;
patternLength = pattern.length();
+ this.escapeUtil = escapeUtil;
}
List tokenize() throws ScanException {
@@ -96,7 +109,7 @@
void escape(String escapeChars, StringBuffer buf) {
if ((pointer < patternLength)) {
char next = pattern.charAt(pointer++);
- EscapeUtil.escape(escapeChars, buf, next, pointer);
+ escapeUtil.escape(escapeChars, buf, next, pointer);
}
}
}
\ No newline at end of file
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java Mon Jul 14 21:31:59 2008
@@ -5,6 +5,8 @@
import ch.qos.logback.core.pattern.Converter;
import ch.qos.logback.core.pattern.FormatInfo;
+import ch.qos.logback.core.pattern.util.IEscapeUtil;
+import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
import ch.qos.logback.core.spi.ContextAwareBase;
@@ -12,14 +14,21 @@
final List tokenList;
int pointer = 0;
+ IEscapeUtil escapeUtil;
Parser(TokenStream ts) throws ScanException {
this.tokenList = ts.tokenize();
}
+ // this variant should be used for testing purposes only
public Parser(String pattern) throws ScanException {
+ this(pattern, new RegularEscapeUtil());
+ }
+
+ public Parser(String pattern, IEscapeUtil escapeUtil) throws ScanException {
+ this.escapeUtil = escapeUtil;
try {
- TokenStream ts = new TokenStream(pattern);
+ TokenStream ts = new TokenStream(pattern, escapeUtil);
this.tokenList = ts.tokenize();
} catch (NullPointerException npe) {
throw new ScanException("Failed to initialize Parser", npe);
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java Mon Jul 14 21:31:59 2008
@@ -12,7 +12,11 @@
import java.util.List;
import java.util.ArrayList;
-import ch.qos.logback.core.pattern.util.EscapeUtil;
+import ch.qos.logback.core.CoreGlobal;
+import ch.qos.logback.core.pattern.util.IEscapeUtil;
+import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
+
+
/**
* <p>Return a steady stream of tokens. <p/>
@@ -29,7 +33,7 @@
class TokenStream {
private static final char ESCAPE_CHAR = '\\';
- private static final char PERCENT_CHAR = '%';
+ private static final char PERCENT_CHAR = CoreGlobal.PERCENT_CHAR;
private static final char LEFT_PARENTHESIS = '(';
private static final char RIGHT_PARENTHESIS = ')';
private static final char CURLY_LEFT = '{';
@@ -42,15 +46,23 @@
final String pattern;
final int patternLength;
+ final IEscapeUtil escapeUtil;
+
int state = LITERAL_STATE;
int pointer = 0;
+ // this variant should be used for testing purposes only
TokenStream(String pattern) {
+ this(pattern, new RegularEscapeUtil());
+ }
+
+ TokenStream(String pattern, IEscapeUtil escapeUtil) {
if(pattern == null) {
throw new NullPointerException("null pattern string not allowed");
}
this.pattern = pattern;
patternLength = pattern.length();
+ this.escapeUtil = escapeUtil;
}
List tokenize() throws ScanException {
@@ -133,7 +145,7 @@
} else if (c == ESCAPE_CHAR) {
if ((pointer < patternLength)) {
char next = pattern.charAt(pointer++);
- EscapeUtil.escape("%()", buf, next, pointer);
+ escapeUtil.escape("%()", buf, next, pointer);
}
} else {
buf.append(c);
@@ -167,7 +179,7 @@
void escape(String escapeChars, StringBuffer buf) {
if ((pointer < patternLength)) {
char next = pattern.charAt(pointer++);
- EscapeUtil.escape(escapeChars, buf, next, pointer);
+ escapeUtil.escape(escapeChars, buf, next, pointer);
}
}
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java Mon Jul 14 21:31:59 2008
@@ -0,0 +1,40 @@
+package ch.qos.logback.core.pattern.util;
+
+import ch.qos.logback.core.CoreGlobal;
+import ch.qos.logback.core.rolling.helper.FileNamePattern;
+
+/**
+ * This implementation is intended for use in {@link FileNamePattern}.
+ *
+ * @author Ceki Gülcü
+ */
+public class AlmostAsIsEscapeUtil implements IEscapeUtil {
+
+ /**
+ * Do not perform any character escaping, except for '%'.
+ *
+ * <p>
+ * Here is the rationale. First, filename patterns do not include escape
+ * combinations such as \r or \n. Moreover, characters which have special
+ * meaning in logback parsers, such as '(', ')', '{', or '}' cannot be part of
+ * file names (so me thinks). Thus, the only character that needs escaping is
+ * '%'.
+ *
+ * <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) {
+
+ if (next == CoreGlobal.PERCENT_CHAR) {
+ buf.append(CoreGlobal.PERCENT_CHAR);
+ } else {
+ // restitute the escape char (because it was consumed
+ // before this method was called).
+ buf.append("\\");
+ // restitute the next character
+ buf.append(next);
+ }
+ }
+}
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/IEscapeUtil.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/IEscapeUtil.java Mon Jul 14 21:31:59 2008
@@ -0,0 +1,6 @@
+package ch.qos.logback.core.pattern.util;
+
+public interface IEscapeUtil {
+
+ void escape(String additionalEscapeChars, StringBuffer buf, char next, int pointer);
+}
\ No newline at end of file
Copied: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java (from r1704, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/EscapeUtil.java)
==============================================================================
--- /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/EscapeUtil.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java Mon Jul 14 21:31:59 2008
@@ -1,8 +1,13 @@
package ch.qos.logback.core.pattern.util;
-public class EscapeUtil {
+/**
+ * This implementation is intended for use in PatternLayout.
+ *
+ * @author Ceki Gülcü
+ */
+public class RegularEscapeUtil implements IEscapeUtil {
- public static void escape(String escapeChars, StringBuffer buf, char next,
+ public void escape(String escapeChars, StringBuffer buf, char next,
int pointer) {
if (escapeChars.indexOf(next) >= 0) {
buf.append(next);
@@ -24,16 +29,21 @@
buf.append('\n');
break;
default:
- String echars = "";
- for (int i = 0; i < escapeChars.length(); i++) {
- echars += ", \\" + escapeChars.charAt(i);
- }
+ String commaSeperatedEscapeChars = formatEscapeCharsForListing(escapeChars);
new IllegalArgumentException("Illegal char '" + next + " at column "
- + pointer + ". Only \\\\, \\_" + echars
+ + pointer + ". Only \\\\, \\_" + commaSeperatedEscapeChars
+ ", \\t, \\n, \\r combinations are allowed as escape characters.");
}
}
+ String formatEscapeCharsForListing(String escapeChars) {
+ String commaSeperatedEscapeChars = "";
+ for (int i = 0; i < escapeChars.length(); i++) {
+ commaSeperatedEscapeChars += ", \\" + escapeChars.charAt(i);
+ }
+ return commaSeperatedEscapeChars;
+ }
+
public static String basicEscape(String s) {
char c;
int len = s.length();
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java Mon Jul 14 21:31:59 2008
@@ -20,6 +20,7 @@
import ch.qos.logback.core.pattern.parser.Node;
import ch.qos.logback.core.pattern.parser.Parser;
import ch.qos.logback.core.pattern.parser.ScanException;
+import ch.qos.logback.core.pattern.util.AlmostAsIsEscapeUtil;
import ch.qos.logback.core.spi.ContextAwareBase;
@@ -52,7 +53,7 @@
void parse() {
try {
- Parser<Object> p = new Parser<Object>(pattern);
+ Parser<Object> p = new Parser<Object>(pattern, new AlmostAsIsEscapeUtil());
p.setContext(context);
Node t = p.parse();
this.headTokenConverter = p.compile(t, CONVERTER_MAP);
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java Mon Jul 14 21:31:59 2008
@@ -22,6 +22,7 @@
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import ch.qos.logback.core.spi.ContextAwareBase;
@@ -247,6 +248,20 @@
}
}
}
+
+ <T> boolean isUnequivocallyInstantiable(Class<T> clazz) {
+ if(clazz.isInterface()) {
+ return false;
+ }
+ try {
+ Constructor<T> pubConstructor = clazz.getConstructor();
+ return true;
+ } catch (SecurityException e) {
+ return false;
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ }
public Class getObjClass() {
return objClass;
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java Mon Jul 14 21:31:59 2008
@@ -10,14 +10,12 @@
package ch.qos.logback.core.pattern.parser;
-import junit.framework.*;
-
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
-import ch.qos.logback.core.pattern.parser.ScanException;
-import ch.qos.logback.core.pattern.parser.Token;
-import ch.qos.logback.core.pattern.parser.TokenStream;
+import ch.qos.logback.core.pattern.util.AlmostAsIsEscapeUtil;
+
+import junit.framework.TestCase;
public class TokenStreamTest extends TestCase {
@@ -317,6 +315,18 @@
witness.add(new Token(Token.LITERAL, ")"));
assertEquals(witness, tl);
}
+ }
+ public void testWindowsLikeBackSlashes() throws ScanException {
+ {
+ 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.KEYWORD, "i"));
+ assertEquals(witness, tl);
+ }
}
}
\ No newline at end of file
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java Mon Jul 14 21:31:59 2008
@@ -20,35 +20,33 @@
import ch.qos.logback.core.rolling.helper.FileNamePattern;
import ch.qos.logback.core.util.StatusPrinter;
-
-
/**
* @author Ceki
- *
+ *
*/
public class FileNamePatternTest extends TestCase {
-
+
Context context = new ContextBase();
-
+
public FileNamePatternTest(String arg) {
super(arg);
}
-
- public void test1() {
- //System.out.println("Testing [t]");
+
+
+ public void testSmoke() {
+ // System.out.println("Testing [t]");
FileNamePattern pp = new FileNamePattern("t", context);
assertEquals("t", pp.convertInt(3));
- //System.out.println("Testing [foo]");
+ // System.out.println("Testing [foo]");
pp = new FileNamePattern("foo", context);
assertEquals("foo", pp.convertInt(3));
- //System.out.println("Testing [foo%]");
- //pp = new FileNamePattern("foo%", context);
- //StatusPrinter.print(context.getStatusManager());
- //assertEquals("foo%", pp.convertInt(3));
-
-
+ // System.out.println("Testing [foo%]");
+ // pp = new FileNamePattern("foo%", context);
+ // StatusPrinter.print(context.getStatusManager());
+ // assertEquals("foo%", pp.convertInt(3));
+
pp = new FileNamePattern("%i foo", context);
StatusPrinter.print(context.getStatusManager());
assertEquals("3 foo", pp.convertInt(3));
@@ -62,7 +60,6 @@
pp = new FileNamePattern("foo.%i.log", context);
assertEquals("foo.3.log", pp.convertInt(3));
-
pp = new FileNamePattern("%i.foo\\%", context);
assertEquals("3.foo%", pp.convertInt(3));
@@ -70,15 +67,21 @@
assertEquals("%foo", pp.convertInt(3));
}
- public void test2() {
- //System.out.println("Testing [foo%ibar%i]");
-
- FileNamePattern pp = new FileNamePattern("foo%i\\_bar%i", context);
- assertEquals("foo3bar3", pp.convertInt(3));
-
+ // test ways for dealing with flowing i converter, as in "foo%ix"
+ public void testFlowingI() {
+ // System.out.println("Testing [foo%ibar%i]");
+
+ {
+ FileNamePattern pp = new FileNamePattern("foo%i{}bar%i", context);
+ assertEquals("foo3bar3", pp.convertInt(3));
+ }
+ {
+ FileNamePattern pp = new FileNamePattern("foo%i{}bar%i", context);
+ assertEquals("foo3bar3", pp.convertInt(3));
+ }
}
- public void test3() {
+ public void testDate() {
Calendar cal = Calendar.getInstance();
cal.set(2003, 4, 20, 17, 55);
@@ -90,15 +93,20 @@
assertEquals("foo2003.05.20 17:55", pp.convertDate(cal.getTime()));
pp = new FileNamePattern("%d{yyyy.MM.dd HH:mm} foo", context);
- assertEquals("2003.05.20 17:55 foo", pp.convertDate(cal.getTime()));
+ assertEquals("2003.05.20 17:55 foo", pp.convertDate(cal.getTime()));
}
+
+ public void testWithBackslash() {
+ FileNamePattern pp = new FileNamePattern("c:\\foo\\bar.%i", context);
+ assertEquals("c:\\foo\\bar.3", pp.convertInt(3));
+ }
public static Test xsuite() {
TestSuite suite = new TestSuite();
suite.addTest(new FileNamePatternTest("test1"));
suite.addTest(new FileNamePatternTest("test2"));
- //suite.addTest(new FileNamePatternTestCase("test3"));
+ // suite.addTest(new FileNamePatternTestCase("test3"));
return suite;
}
More information about the logback-dev
mailing list