diff --git a/.gitignore b/.gitignore index 9539fb57edf2cf5094171fa9e2fcba92f1ca260b..6b74944ed9877e6e00248f5b7f1e209cb05633b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -.settings -target -.classpath -.project +.settings +target +.classpath +.project *~ \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt index 046cbb31c570690d7cc4b9ff47a8a2c8d2eeb1ba..68acacea8803eb56f6a8b74777c2ad44d1fecab9 100755 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,15 +1,15 @@ -Logback LICENSE ---------------- - -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. - +Logback LICENSE +--------------- + +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. + diff --git a/README.txt b/README.txt index 362dcb66b986f4d645812446d30121cdef6e61bd..27c3a3e626ef700b64256de0c9c49b33cb41caef 100644 --- a/README.txt +++ b/README.txt @@ -1,22 +1,22 @@ - -Thank you for downloading logback, the reliable, generic, fast and -flexible logging library for Java. - -The Logback documentation can be found under the docs/ directory. - -Building logback -================ - -Building logback is documented at: - - http://logback.qos.ch/manual/introduction.html#BuildingLogback - -In case of problems -=================== - -In case of problems please do not hesitate to post an e-mail message -on the logback-user@qos.ch mailing list. However, please do not -directly e-mail logback developers. The answer to your question might -be useful to other users. Moreover, there are many knowledgeable users -on the logback-user mailing lists who can quickly answer your + +Thank you for downloading logback, the reliable, generic, fast and +flexible logging library for Java. + +The Logback documentation can be found under the docs/ directory. + +Building logback +================ + +Building logback is documented at: + + http://logback.qos.ch/manual/introduction.html#BuildingLogback + +In case of problems +=================== + +In case of problems please do not hesitate to post an e-mail message +on the logback-user@qos.ch mailing list. However, please do not +directly e-mail logback developers. The answer to your question might +be useful to other users. Moreover, there are many knowledgeable users +on the logback-user mailing lists who can quickly answer your questions. \ No newline at end of file diff --git a/codeStyle.xml b/codeStyle.xml index 12c335aa0c1c3c16c62ad14ede2f9c99329eb974..494ae9935a26c6e767d0b7f9b6b62970bad8ed41 100644 --- a/codeStyle.xml +++ b/codeStyle.xml @@ -1,264 +1,264 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/logback-access/LICENSE.txt b/logback-access/LICENSE.txt index 667c2b5dec1895f20ac8ed369045589dc26ff610..d5dac89e45b96875fa0e06a0cf7022e757c4fc52 100644 --- a/logback-access/LICENSE.txt +++ b/logback-access/LICENSE.txt @@ -1,22 +1,22 @@ -Logback LICENSE ---------------- - -Logback: the reliable, generic, fast and flexible logging library for -Java. - -Copyright (C) 2000-2008, QOS.ch - -Source code and binaries for logback, including logback-core, -logback-classic and logback-access modules, are distributed under the -GNU Lesser General Public License Version 2.1, as published by the -Free Software Foundation. - -This library is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as -published by the Free Software Foundation; either version 2.1 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. +Logback LICENSE +--------------- + +Logback: the reliable, generic, fast and flexible logging library for +Java. + +Copyright (C) 2000-2008, QOS.ch + +Source code and binaries for logback, including logback-core, +logback-classic and logback-access modules, are distributed under the +GNU Lesser General Public License Version 2.1, as published by the +Free Software Foundation. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. diff --git a/logback-access/build.xml b/logback-access/build.xml index 522bafb280db907139744674687ab8812994ad64..e7728ead925a71ab540b5aa7884defde670a37b0 100644 --- a/logback-access/build.xml +++ b/logback-access/build.xml @@ -1,90 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - These are the targets supported by this ANT build scpript: - - build - compile all project files, if a certain library is missing, - then the compilation of its dependents are skipped. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
-
-
-
- - -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + These are the targets supported by this ANT build scpript: + + build - compile all project files, if a certain library is missing, + then the compilation of its dependents are skipped. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+
+
+ + +
diff --git a/logback-access/keywords.html b/logback-access/keywords.html index ed9e5875eb0889ff1eaaca18eeb042e2fea12c76..91d456c9fc296c2ffdd04bc34707f6c59b93d7b5 100644 --- a/logback-access/keywords.html +++ b/logback-access/keywords.html @@ -1,222 +1,222 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
keyword LabelJettyResinTomcatObservations
aremote IP addressNANArequest.getRemoteAddr() [S] RemoteIPAddressConverter
Alocal IP address InetAddress.getLocalHost().getHostAddress() [S] LocalIPAddressConverter
bContent lengthrequest.getConnection().getGenerator().getContentWritten();Unless statusCode==304, response.getContentLength()response.getContentCount();JettyContentLengthConverter, ResinContentLengthConverter
cCookierequest cookies (dumps all of them}dumps cookies by name, request cookie first, if - unavailable then response cookierequest cookies, by nameRequestCookieConverter
hremote IP addrrequest.getRemoteAddr() [S]request.printRemoteAddr, IP address string in textual presentationrequest.getRemoteHost() [S]RemoteHostConverter
Hrequest protocolrequest.getProtocol()RequestProtocolConverter
iIncoming headerNArequest.getHeader(name) [S]request.getHeader(header) [S]RequestHeaderConverter
lRemote logical username from identdalways '-'always '-'always '-'NAConverter
nattribute in the ServletRequestNArequest.getAttribute(name) [S] NARequestAttributeConverter, in tomcat %r is used
oresponse headerreponse.getHeader(name) [NS]not implemented altough response.setHeader() method is available
rFirst line of the request (method and request URI)request.getMethod()+ request.getUri() [NS] +request.getProtocol()request.getMethod() + request.getUriBuffer() [NS] + request.getProtocol()request.getMethod() + request.getRequestURI() + request.getQueryString() + '?' + request.getProtocol();RequestURLConverter
{}rattribute in the ServletRequestNANArequest.getAttribute(name) [S]RequestAttributeConverter, in resin %n is used
sstatus coderesponse.getStatus() [NS] response.getStatusCode() [NS]response.getStatus() [NS]suprisingly, not in the Servlet API
{}trequest time stampgetTimeStamp() [NS]based on current timebased on current timeDateConverter
Trequest processing duration in secondsNArequest.getStartTime() - Alarm.getExactTime()Valve measures invocation time
Drequest processing duration in millisrequest.getStartTime() - Alarm.getExactTime()Valve measures invocation time
uremote userrequest.getRemoteUser() [S]request.getRemoteUser() [S]request.getRemoteUser() [S]RemoteUserConverter
URequested URI pathNA request.getRequestURI() [S} request.getRequestURI() [S}RequestURIConverter
- - -Tomcat -====== -%a - Remote IP address -%A - Local IP address -%b - Bytes sent, excluding HTTP headers, or '-' if zero -%B - Bytes sent, excluding HTTP headers -%h - Remote host name (or IP address if resolveHosts is false) -%H - Request protocol -%l - Remote logical username from identd (always returns '-') -%m - Request method (GET, POST, etc.) -%p - Local port on which this request was received -%q - Query string (prepended with a '?' if it exists) -%r - First line of the request (method and request URI) -%s - HTTP status code of the response -%S - User session ID -%t - Date and time, in Common Log Format -%u - Remote user that was authenticated (if any), else '-' -%U - Requested URL path -%v - Local server name -%D - Time taken to process the request, in millis -%T - Time taken to process the request, in seconds - -Resin -===== - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
keyword LabelJettyResinTomcatObservations
aremote IP addressNANArequest.getRemoteAddr() [S] RemoteIPAddressConverter
Alocal IP address InetAddress.getLocalHost().getHostAddress() [S] LocalIPAddressConverter
bContent lengthrequest.getConnection().getGenerator().getContentWritten();Unless statusCode==304, response.getContentLength()response.getContentCount();JettyContentLengthConverter, ResinContentLengthConverter
cCookierequest cookies (dumps all of them}dumps cookies by name, request cookie first, if + unavailable then response cookierequest cookies, by nameRequestCookieConverter
hremote IP addrrequest.getRemoteAddr() [S]request.printRemoteAddr, IP address string in textual presentationrequest.getRemoteHost() [S]RemoteHostConverter
Hrequest protocolrequest.getProtocol()RequestProtocolConverter
iIncoming headerNArequest.getHeader(name) [S]request.getHeader(header) [S]RequestHeaderConverter
lRemote logical username from identdalways '-'always '-'always '-'NAConverter
nattribute in the ServletRequestNArequest.getAttribute(name) [S] NARequestAttributeConverter, in tomcat %r is used
oresponse headerreponse.getHeader(name) [NS]not implemented altough response.setHeader() method is available
rFirst line of the request (method and request URI)request.getMethod()+ request.getUri() [NS] +request.getProtocol()request.getMethod() + request.getUriBuffer() [NS] + request.getProtocol()request.getMethod() + request.getRequestURI() + request.getQueryString() + '?' + request.getProtocol();RequestURLConverter
{}rattribute in the ServletRequestNANArequest.getAttribute(name) [S]RequestAttributeConverter, in resin %n is used
sstatus coderesponse.getStatus() [NS] response.getStatusCode() [NS]response.getStatus() [NS]suprisingly, not in the Servlet API
{}trequest time stampgetTimeStamp() [NS]based on current timebased on current timeDateConverter
Trequest processing duration in secondsNArequest.getStartTime() - Alarm.getExactTime()Valve measures invocation time
Drequest processing duration in millisrequest.getStartTime() - Alarm.getExactTime()Valve measures invocation time
uremote userrequest.getRemoteUser() [S]request.getRemoteUser() [S]request.getRemoteUser() [S]RemoteUserConverter
URequested URI pathNA request.getRequestURI() [S} request.getRequestURI() [S}RequestURIConverter
+ + +Tomcat +====== +%a - Remote IP address +%A - Local IP address +%b - Bytes sent, excluding HTTP headers, or '-' if zero +%B - Bytes sent, excluding HTTP headers +%h - Remote host name (or IP address if resolveHosts is false) +%H - Request protocol +%l - Remote logical username from identd (always returns '-') +%m - Request method (GET, POST, etc.) +%p - Local port on which this request was received +%q - Query string (prepended with a '?' if it exists) +%r - First line of the request (method and request URI) +%s - HTTP status code of the response +%S - User session ID +%t - Date and time, in Common Log Format +%u - Remote user that was authenticated (if any), else '-' +%U - Requested URL path +%v - Local server name +%D - Time taken to process the request, in millis +%T - Time taken to process the request, in seconds + +Resin +===== + + + \ No newline at end of file diff --git a/logback-access/pom.xml b/logback-access/pom.xml index 41cf25db73f555e3893379828e4f9132ba96f9c6..8b9482d22be51f6abd758a548ec5a18036f79b06 100644 --- a/logback-access/pom.xml +++ b/logback-access/pom.xml @@ -1,205 +1,205 @@ - - - - ch.qos.logback - logback-parent - 0.9.18-SNAPSHOT - - - 4.0.0 - - ch.qos.logback - logback-access - ${parent.version} - jar - Logback Access Module - - http://logback.qos.ch - - - Logback: the reliable, generic, fast and flexible logging library for Java. - - - - - Eclipse Public License - v 1.0 - http://www.eclipse.org/legal/epl-v10.html - - - - GNU Lesser General Public License - http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - - - - - - ch.qos.logback - logback-core - compile - - - - ch.qos.logback - logback-core - test-jar - test - - - - tomcat - catalina - compile - true - - - - org.mortbay.jetty - jetty - compile - true - - - - org.mortbay.jetty - servlet-api-2.5 - compile - true - - - - janino - janino - compile - true - - - - hsqldb - hsqldb - test - - - - javax.mail - mail - compile - true - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - - - - - org.apache.maven.plugins - maven-surefire-plugin - - once - plain - true - - **/AllAccessTest.java - **/PackageTest.java - **/SerializationPerfTest.java - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - - - - bundle-test-jar - package - - jar - test-jar - - - - - - org.apache.felix - maven-bundle-plugin - true - - - bundle-manifest - process-classes - - manifest - - - - - - ch.qos.logback.access.* - J2SE-1.5 - - - - - - - - - - - - host-orion - - - - mysql - mysql-connector-java - 5.0.8 - test - - - - postgresql - postgresql - 8.2-507.jdbc3 - - - - - com.microsoft.sqlserver - sqljdbc4 - 2.0 - test - - - - com.oracle - ojdbc14 - 10.2.0.1 - test - - - - - - - - + + + + ch.qos.logback + logback-parent + 0.9.18-SNAPSHOT + + + 4.0.0 + + ch.qos.logback + logback-access + ${parent.version} + jar + Logback Access Module + + http://logback.qos.ch + + + Logback: the reliable, generic, fast and flexible logging library for Java. + + + + + Eclipse Public License - v 1.0 + http://www.eclipse.org/legal/epl-v10.html + + + + GNU Lesser General Public License + http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html + + + + + + ch.qos.logback + logback-core + compile + + + + ch.qos.logback + logback-core + test-jar + test + + + + tomcat + catalina + compile + true + + + + org.mortbay.jetty + jetty + compile + true + + + + org.mortbay.jetty + servlet-api-2.5 + compile + true + + + + janino + janino + compile + true + + + + hsqldb + hsqldb + test + + + + javax.mail + mail + compile + true + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + org.apache.maven.plugins + maven-surefire-plugin + + once + plain + true + + **/AllAccessTest.java + **/PackageTest.java + **/SerializationPerfTest.java + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + bundle-test-jar + package + + jar + test-jar + + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + ch.qos.logback.access.* + J2SE-1.5 + + + + + + + + + + + + host-orion + + + + mysql + mysql-connector-java + 5.0.8 + test + + + + postgresql + postgresql + 8.2-507.jdbc3 + + + + + com.microsoft.sqlserver + sqljdbc4 + 2.0 + test + + + + com.oracle + ojdbc14 + 10.2.0.1 + test + + + + + + + + \ No newline at end of file diff --git a/logback-access/src/main/java/ch/qos/logback/access/AccessConstants.java b/logback-access/src/main/java/ch/qos/logback/access/AccessConstants.java index b79f48928ca6c90155446083a9ce36443eba7976..107b928e60c51e9a513ebfef58642116120a8c23 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/AccessConstants.java +++ b/logback-access/src/main/java/ch/qos/logback/access/AccessConstants.java @@ -1,28 +1,28 @@ -/** - * 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.access; - -public class AccessConstants { - - public final static String LOGBACK_STATUS_MANAGER_KEY = "LOGBACK_STATUS_MANAGER"; - public static final String LB_INPUT_BUFFER = "LB_INPUT_BUFFER"; - public static final String LB_OUTPUT_BUFFER = "LB_OUTPUT_BUFFER"; - - public final static String X_WWW_FORM_URLECODED = "application/x-www-form-urlencoded"; - - public final static String IMAGE_CONTENT_TYPE = "image/"; - public final static String IMAGE_JPEG = "image/jpeg"; - public final static String IMAGE_GIF = "image/gif"; - public final static String IMAGE_PNG = "image/png"; -} +/** + * 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.access; + +public class AccessConstants { + + public final static String LOGBACK_STATUS_MANAGER_KEY = "LOGBACK_STATUS_MANAGER"; + public static final String LB_INPUT_BUFFER = "LB_INPUT_BUFFER"; + public static final String LB_OUTPUT_BUFFER = "LB_OUTPUT_BUFFER"; + + public final static String X_WWW_FORM_URLECODED = "application/x-www-form-urlencoded"; + + public final static String IMAGE_CONTENT_TYPE = "image/"; + public final static String IMAGE_JPEG = "image/jpeg"; + public final static String IMAGE_GIF = "image/gif"; + public final static String IMAGE_PNG = "image/png"; +} 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 e5bbc2e92d322c8c32d0120bd6f5d3ec922f9e0e..40917f364fdad098d66d9234dfbac2ee563c51ed 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 @@ -1,186 +1,186 @@ -/** - * 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.access; - -import java.util.HashMap; -import java.util.Map; - -import ch.qos.logback.access.pattern.ContentLengthConverter; -import ch.qos.logback.access.pattern.DateConverter; -import ch.qos.logback.access.pattern.EnsureLineSeparation; -import ch.qos.logback.access.pattern.FullRequestConverter; -import ch.qos.logback.access.pattern.FullResponseConverter; -import ch.qos.logback.access.pattern.LineSeparatorConverter; -import ch.qos.logback.access.pattern.LocalIPAddressConverter; -import ch.qos.logback.access.pattern.LocalPortConverter; -import ch.qos.logback.access.pattern.NAConverter; -import ch.qos.logback.access.pattern.RemoteHostConverter; -import ch.qos.logback.access.pattern.RemoteIPAddressConverter; -import ch.qos.logback.access.pattern.RemoteUserConverter; -import ch.qos.logback.access.pattern.RequestAttributeConverter; -import ch.qos.logback.access.pattern.RequestContentConverter; -import ch.qos.logback.access.pattern.RequestCookieConverter; -import ch.qos.logback.access.pattern.RequestHeaderConverter; -import ch.qos.logback.access.pattern.RequestMethodConverter; -import ch.qos.logback.access.pattern.RequestParameterConverter; -import ch.qos.logback.access.pattern.RequestProtocolConverter; -import ch.qos.logback.access.pattern.RequestURIConverter; -import ch.qos.logback.access.pattern.RequestURLConverter; -import ch.qos.logback.access.pattern.ResponseContentConverter; -import ch.qos.logback.access.pattern.ResponseHeaderConverter; -import ch.qos.logback.access.pattern.ServerNameConverter; -import ch.qos.logback.access.pattern.StatusCodeConverter; -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.pattern.PatternLayoutBase; - -/** - *

- * This class is a module-specific implementation of - * {@link ch.qos.logback.classic.PatternLayout} to allow http-specific patterns - * to be used. The ch.qos.logback.access.PatternLayout provides a - * way to format the logging output that is just as easy and flexible as the - * usual PatternLayout. - *

- *

- * For more information about this layout, please refer to the online manual at - * http://logback.qos.ch/manual/layouts.html#AccessPatternLayout - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class PatternLayout extends PatternLayoutBase { - - public static final Map defaultConverterMap = new HashMap(); - - public static String CLF_PATTERN = "%h %l %u %t \"%r\" %s %b"; - public static String CLF_PATTERN_NAME = "common"; - public static String CLF_PATTERN_NAME_2 = "clf"; - public static String COMBINED_PATTERN = "%h %l %u %t \"%r\" %s %b \"%i{Referer}\" \"%i{User-Agent}\""; - public static String COMBINED_PATTERN_NAME = "combined"; - - static { - - defaultConverterMap.put("a", RemoteIPAddressConverter.class.getName()); - defaultConverterMap.put("remoteIP", RemoteIPAddressConverter.class - .getName()); - - defaultConverterMap.put("A", LocalIPAddressConverter.class.getName()); - defaultConverterMap.put("localIP", LocalIPAddressConverter.class.getName()); - - defaultConverterMap.put("b", ContentLengthConverter.class.getName()); - defaultConverterMap.put("B", ContentLengthConverter.class.getName()); - defaultConverterMap - .put("bytesSent", ContentLengthConverter.class.getName()); - - defaultConverterMap.put("h", RemoteHostConverter.class.getName()); - defaultConverterMap.put("clientHost", RemoteHostConverter.class.getName()); - - defaultConverterMap.put("H", RequestProtocolConverter.class.getName()); - defaultConverterMap.put("protocol", RequestProtocolConverter.class - .getName()); - - defaultConverterMap.put("i", RequestHeaderConverter.class.getName()); - defaultConverterMap.put("header", RequestHeaderConverter.class.getName()); - - defaultConverterMap.put("l", NAConverter.class.getName()); - - defaultConverterMap.put("m", RequestMethodConverter.class.getName()); - defaultConverterMap.put("requestMethod", RequestMethodConverter.class - .getName()); - - defaultConverterMap.put("r", RequestURLConverter.class.getName()); - defaultConverterMap.put("requestURL", RequestURLConverter.class.getName()); - - defaultConverterMap.put("s", StatusCodeConverter.class.getName()); - defaultConverterMap.put("statusCode", StatusCodeConverter.class.getName()); - - defaultConverterMap.put("t", DateConverter.class.getName()); - defaultConverterMap.put("date", DateConverter.class.getName()); - - defaultConverterMap.put("u", RemoteUserConverter.class.getName()); - defaultConverterMap.put("user", RemoteUserConverter.class.getName()); - - defaultConverterMap.put("U", RequestURIConverter.class.getName()); - defaultConverterMap.put("requestURI", RequestURIConverter.class.getName()); - - defaultConverterMap.put("v", ServerNameConverter.class.getName()); - defaultConverterMap.put("server", ServerNameConverter.class.getName()); - - defaultConverterMap.put("localPort", LocalPortConverter.class.getName()); - - defaultConverterMap.put("requestAttribute", RequestAttributeConverter.class - .getName()); - defaultConverterMap.put("reqAttribute", RequestAttributeConverter.class - .getName()); - - defaultConverterMap - .put("reqCookie", RequestCookieConverter.class.getName()); - defaultConverterMap - .put("requestCookie", RequestCookieConverter.class.getName()); - - - defaultConverterMap.put("responseHeader", ResponseHeaderConverter.class - .getName()); - - - defaultConverterMap.put("requestParameter", RequestParameterConverter.class - .getName()); - defaultConverterMap.put("reqParameter", RequestParameterConverter.class - .getName()); - - defaultConverterMap.put("requestContent", RequestContentConverter.class.getName()); - - defaultConverterMap.put("responseContent", ResponseContentConverter.class.getName()); - - defaultConverterMap.put("fullRequest", FullRequestConverter.class.getName()); - defaultConverterMap.put("fullResponse", FullResponseConverter.class.getName()); - - - defaultConverterMap.put("n", LineSeparatorConverter.class.getName()); - } - - - public PatternLayout() { - // set a default value for pattern - setPattern(CLF_PATTERN); - // by default postCompileProcessor the is an EnsureLineSeparation instance - this.postCompileProcessor = new EnsureLineSeparation(); - } - - /** - * Returns the default converter map for this instance. - */ - public Map getDefaultConverterMap() { - return defaultConverterMap; - } - - public String doLayout(AccessEvent event) { - if (!isStarted()) { - return null; - } - return writeLoopOnConverters(event); - } - - @Override - public void start() { - if (getPattern().equalsIgnoreCase(CLF_PATTERN_NAME) - || getPattern().equalsIgnoreCase(CLF_PATTERN_NAME_2)) { - setPattern(CLF_PATTERN); - } else if (getPattern().equalsIgnoreCase(COMBINED_PATTERN_NAME)) { - setPattern(COMBINED_PATTERN); - } - super.start(); - } - -} +/** + * 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.access; + +import java.util.HashMap; +import java.util.Map; + +import ch.qos.logback.access.pattern.ContentLengthConverter; +import ch.qos.logback.access.pattern.DateConverter; +import ch.qos.logback.access.pattern.EnsureLineSeparation; +import ch.qos.logback.access.pattern.FullRequestConverter; +import ch.qos.logback.access.pattern.FullResponseConverter; +import ch.qos.logback.access.pattern.LineSeparatorConverter; +import ch.qos.logback.access.pattern.LocalIPAddressConverter; +import ch.qos.logback.access.pattern.LocalPortConverter; +import ch.qos.logback.access.pattern.NAConverter; +import ch.qos.logback.access.pattern.RemoteHostConverter; +import ch.qos.logback.access.pattern.RemoteIPAddressConverter; +import ch.qos.logback.access.pattern.RemoteUserConverter; +import ch.qos.logback.access.pattern.RequestAttributeConverter; +import ch.qos.logback.access.pattern.RequestContentConverter; +import ch.qos.logback.access.pattern.RequestCookieConverter; +import ch.qos.logback.access.pattern.RequestHeaderConverter; +import ch.qos.logback.access.pattern.RequestMethodConverter; +import ch.qos.logback.access.pattern.RequestParameterConverter; +import ch.qos.logback.access.pattern.RequestProtocolConverter; +import ch.qos.logback.access.pattern.RequestURIConverter; +import ch.qos.logback.access.pattern.RequestURLConverter; +import ch.qos.logback.access.pattern.ResponseContentConverter; +import ch.qos.logback.access.pattern.ResponseHeaderConverter; +import ch.qos.logback.access.pattern.ServerNameConverter; +import ch.qos.logback.access.pattern.StatusCodeConverter; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.pattern.PatternLayoutBase; + +/** + *

+ * This class is a module-specific implementation of + * {@link ch.qos.logback.classic.PatternLayout} to allow http-specific patterns + * to be used. The ch.qos.logback.access.PatternLayout provides a + * way to format the logging output that is just as easy and flexible as the + * usual PatternLayout. + *

+ *

+ * For more information about this layout, please refer to the online manual at + * http://logback.qos.ch/manual/layouts.html#AccessPatternLayout + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class PatternLayout extends PatternLayoutBase { + + public static final Map defaultConverterMap = new HashMap(); + + public static String CLF_PATTERN = "%h %l %u %t \"%r\" %s %b"; + public static String CLF_PATTERN_NAME = "common"; + public static String CLF_PATTERN_NAME_2 = "clf"; + public static String COMBINED_PATTERN = "%h %l %u %t \"%r\" %s %b \"%i{Referer}\" \"%i{User-Agent}\""; + public static String COMBINED_PATTERN_NAME = "combined"; + + static { + + defaultConverterMap.put("a", RemoteIPAddressConverter.class.getName()); + defaultConverterMap.put("remoteIP", RemoteIPAddressConverter.class + .getName()); + + defaultConverterMap.put("A", LocalIPAddressConverter.class.getName()); + defaultConverterMap.put("localIP", LocalIPAddressConverter.class.getName()); + + defaultConverterMap.put("b", ContentLengthConverter.class.getName()); + defaultConverterMap.put("B", ContentLengthConverter.class.getName()); + defaultConverterMap + .put("bytesSent", ContentLengthConverter.class.getName()); + + defaultConverterMap.put("h", RemoteHostConverter.class.getName()); + defaultConverterMap.put("clientHost", RemoteHostConverter.class.getName()); + + defaultConverterMap.put("H", RequestProtocolConverter.class.getName()); + defaultConverterMap.put("protocol", RequestProtocolConverter.class + .getName()); + + defaultConverterMap.put("i", RequestHeaderConverter.class.getName()); + defaultConverterMap.put("header", RequestHeaderConverter.class.getName()); + + defaultConverterMap.put("l", NAConverter.class.getName()); + + defaultConverterMap.put("m", RequestMethodConverter.class.getName()); + defaultConverterMap.put("requestMethod", RequestMethodConverter.class + .getName()); + + defaultConverterMap.put("r", RequestURLConverter.class.getName()); + defaultConverterMap.put("requestURL", RequestURLConverter.class.getName()); + + defaultConverterMap.put("s", StatusCodeConverter.class.getName()); + defaultConverterMap.put("statusCode", StatusCodeConverter.class.getName()); + + defaultConverterMap.put("t", DateConverter.class.getName()); + defaultConverterMap.put("date", DateConverter.class.getName()); + + defaultConverterMap.put("u", RemoteUserConverter.class.getName()); + defaultConverterMap.put("user", RemoteUserConverter.class.getName()); + + defaultConverterMap.put("U", RequestURIConverter.class.getName()); + defaultConverterMap.put("requestURI", RequestURIConverter.class.getName()); + + defaultConverterMap.put("v", ServerNameConverter.class.getName()); + defaultConverterMap.put("server", ServerNameConverter.class.getName()); + + defaultConverterMap.put("localPort", LocalPortConverter.class.getName()); + + defaultConverterMap.put("requestAttribute", RequestAttributeConverter.class + .getName()); + defaultConverterMap.put("reqAttribute", RequestAttributeConverter.class + .getName()); + + defaultConverterMap + .put("reqCookie", RequestCookieConverter.class.getName()); + defaultConverterMap + .put("requestCookie", RequestCookieConverter.class.getName()); + + + defaultConverterMap.put("responseHeader", ResponseHeaderConverter.class + .getName()); + + + defaultConverterMap.put("requestParameter", RequestParameterConverter.class + .getName()); + defaultConverterMap.put("reqParameter", RequestParameterConverter.class + .getName()); + + defaultConverterMap.put("requestContent", RequestContentConverter.class.getName()); + + defaultConverterMap.put("responseContent", ResponseContentConverter.class.getName()); + + defaultConverterMap.put("fullRequest", FullRequestConverter.class.getName()); + defaultConverterMap.put("fullResponse", FullResponseConverter.class.getName()); + + + defaultConverterMap.put("n", LineSeparatorConverter.class.getName()); + } + + + public PatternLayout() { + // set a default value for pattern + setPattern(CLF_PATTERN); + // by default postCompileProcessor the is an EnsureLineSeparation instance + this.postCompileProcessor = new EnsureLineSeparation(); + } + + /** + * Returns the default converter map for this instance. + */ + public Map getDefaultConverterMap() { + return defaultConverterMap; + } + + public String doLayout(AccessEvent event) { + if (!isStarted()) { + return null; + } + return writeLoopOnConverters(event); + } + + @Override + public void start() { + if (getPattern().equalsIgnoreCase(CLF_PATTERN_NAME) + || getPattern().equalsIgnoreCase(CLF_PATTERN_NAME_2)) { + setPattern(CLF_PATTERN); + } else if (getPattern().equalsIgnoreCase(COMBINED_PATTERN_NAME)) { + setPattern(COMBINED_PATTERN); + } + super.start(); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/ViewStatusMessagesServlet.java b/logback-access/src/main/java/ch/qos/logback/access/ViewStatusMessagesServlet.java index d6ea8adfdba7c4515e961cadf1fc893e9d96d8d3..cc724c4f0e04fa11e1741b0082de7d8eb7f126ee 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/ViewStatusMessagesServlet.java +++ b/logback-access/src/main/java/ch/qos/logback/access/ViewStatusMessagesServlet.java @@ -1,52 +1,52 @@ -/** - * 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.access; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.status.ViewStatusMessagesServletBase; - -public class ViewStatusMessagesServlet extends ViewStatusMessagesServletBase { - - private static final long serialVersionUID = 443878494348593337L; - - @Override - protected StatusManager getStatusManager(HttpServletRequest req, - HttpServletResponse resp) { - - ServletContext sc = getServletContext(); - StatusManager result = (StatusManager) sc - .getAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY); - return result; - -// if (result != null) { -// System.out.println("from ServletContext"); -// return result; -// } else { -// HttpSession httpSession = req.getSession(true); -// -// System.out.println("from httpSession"); -// return (StatusManager) httpSession -// .getAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY); -// } - } - - @Override - protected String getPageTitle(HttpServletRequest req, HttpServletResponse resp) { - return "

Status messages for logback-access

\r\n"; - } -} +/** + * 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.access; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.ViewStatusMessagesServletBase; + +public class ViewStatusMessagesServlet extends ViewStatusMessagesServletBase { + + private static final long serialVersionUID = 443878494348593337L; + + @Override + protected StatusManager getStatusManager(HttpServletRequest req, + HttpServletResponse resp) { + + ServletContext sc = getServletContext(); + StatusManager result = (StatusManager) sc + .getAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY); + return result; + +// if (result != null) { +// System.out.println("from ServletContext"); +// return result; +// } else { +// HttpSession httpSession = req.getSession(true); +// +// System.out.println("from httpSession"); +// return (StatusManager) httpSession +// .getAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY); +// } + } + + @Override + protected String getPageTitle(HttpServletRequest req, HttpServletResponse resp) { + return "

Status messages for logback-access

\r\n"; + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/boolex/JaninoEventEvaluator.java b/logback-access/src/main/java/ch/qos/logback/access/boolex/JaninoEventEvaluator.java index 49b4b1d62a5324198547624caef7f93f859b29f9..0df27655880acd689009d90516463d1177161356 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/boolex/JaninoEventEvaluator.java +++ b/logback-access/src/main/java/ch/qos/logback/access/boolex/JaninoEventEvaluator.java @@ -1,80 +1,80 @@ -/** - * 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.access.boolex; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.boolex.JaninoEventEvaluatorBase; -import ch.qos.logback.core.boolex.Matcher; - -public class JaninoEventEvaluator extends JaninoEventEvaluatorBase { - - public final static List DEFAULT_PARAM_NAME_LIST = new ArrayList(); - public final static List DEFAULT_PARAM_TYPE_LIST = new ArrayList(); - - static { - DEFAULT_PARAM_NAME_LIST.add("event"); - DEFAULT_PARAM_TYPE_LIST.add(AccessEvent.class); - } - - - public JaninoEventEvaluator() { - - } - - protected String getDecoratedExpression() { - return getExpression(); - } - - protected String[] getParameterNames() { - List fullNameList = new ArrayList(); - fullNameList.addAll(DEFAULT_PARAM_NAME_LIST); - - for(int i = 0; i < matcherList.size(); i++) { - Matcher m = (Matcher) matcherList.get(i); - fullNameList.add(m.getName()); - } - - return (String[]) fullNameList.toArray(CoreConstants.EMPTY_STRING_ARRAY); - } - - protected Class[] getParameterTypes() { - List fullTypeList = new ArrayList(); - fullTypeList.addAll(DEFAULT_PARAM_TYPE_LIST); - for(int i = 0; i < matcherList.size(); i++) { - fullTypeList.add(Matcher.class); - } - return (Class[]) fullTypeList.toArray(CoreConstants.EMPTY_CLASS_ARRAY); - } - - protected Object[] getParameterValues(AccessEvent event) { - AccessEvent accessEvent = (AccessEvent) event; - final int matcherListSize = matcherList.size(); - - int i = 0; - Object[] values = new Object[DEFAULT_PARAM_NAME_LIST.size()+matcherListSize]; - - values[i++] = accessEvent; - - for(int j = 0; j < matcherListSize; j++) { - values[i++] = (Matcher) matcherList.get(j); - } - - return values; - } - -} +/** + * 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.access.boolex; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.boolex.JaninoEventEvaluatorBase; +import ch.qos.logback.core.boolex.Matcher; + +public class JaninoEventEvaluator extends JaninoEventEvaluatorBase { + + public final static List DEFAULT_PARAM_NAME_LIST = new ArrayList(); + public final static List DEFAULT_PARAM_TYPE_LIST = new ArrayList(); + + static { + DEFAULT_PARAM_NAME_LIST.add("event"); + DEFAULT_PARAM_TYPE_LIST.add(AccessEvent.class); + } + + + public JaninoEventEvaluator() { + + } + + protected String getDecoratedExpression() { + return getExpression(); + } + + protected String[] getParameterNames() { + List fullNameList = new ArrayList(); + fullNameList.addAll(DEFAULT_PARAM_NAME_LIST); + + for(int i = 0; i < matcherList.size(); i++) { + Matcher m = (Matcher) matcherList.get(i); + fullNameList.add(m.getName()); + } + + return (String[]) fullNameList.toArray(CoreConstants.EMPTY_STRING_ARRAY); + } + + protected Class[] getParameterTypes() { + List fullTypeList = new ArrayList(); + fullTypeList.addAll(DEFAULT_PARAM_TYPE_LIST); + for(int i = 0; i < matcherList.size(); i++) { + fullTypeList.add(Matcher.class); + } + return (Class[]) fullTypeList.toArray(CoreConstants.EMPTY_CLASS_ARRAY); + } + + protected Object[] getParameterValues(AccessEvent event) { + AccessEvent accessEvent = (AccessEvent) event; + final int matcherListSize = matcherList.size(); + + int i = 0; + Object[] values = new Object[DEFAULT_PARAM_NAME_LIST.size()+matcherListSize]; + + values[i++] = accessEvent; + + for(int j = 0; j < matcherListSize; j++) { + values[i++] = (Matcher) matcherList.get(j); + } + + return values; + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/db/dialect/deleteTables.sql b/logback-access/src/main/java/ch/qos/logback/access/db/dialect/deleteTables.sql index 6f7fad5d57f55b2fc09eb4815c9360b3b4edf861..bd7c256de0a5493cb93ada0cf5a384b6b6dab836 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/db/dialect/deleteTables.sql +++ b/logback-access/src/main/java/ch/qos/logback/access/db/dialect/deleteTables.sql @@ -1,3 +1,3 @@ - -delete from access_event_property; -delete from access_event; + +delete from access_event_property; +delete from access_event; diff --git a/logback-access/src/main/java/ch/qos/logback/access/db/package.html b/logback-access/src/main/java/ch/qos/logback/access/db/package.html index 4136cac84e9efe218145beda6e1e4986a2a3a274..b6fab1396dee473c819be04e4fa8512a99603ec8 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/db/package.html +++ b/logback-access/src/main/java/ch/qos/logback/access/db/package.html @@ -1,23 +1,23 @@ - - - - - - - - - -

The ch.qos.logback.access.db package provides means to append access events -into various databases. -

- -

Most popular database systems, such as PostgreSQL, MySQL, Oracle, DB2 and MsSQL -are supported. -

- -

Just as importantly, the way for obtaining JDBC connections is pluggable. Connections can -be obtained through the tradinal way of DriverManager, or alternatively as a DataSource. -A DataSource can be instantiated directly or it can obtained through JNDI. -

- + + + + + + + + + +

The ch.qos.logback.access.db package provides means to append access events +into various databases. +

+ +

Most popular database systems, such as PostgreSQL, MySQL, Oracle, DB2 and MsSQL +are supported. +

+ +

Just as importantly, the way for obtaining JDBC connections is pluggable. Connections can +be obtained through the tradinal way of DriverManager, or alternatively as a DataSource. +A DataSource can be instantiated directly or it can obtained through JNDI. +

+ \ No newline at end of file diff --git a/logback-access/src/main/java/ch/qos/logback/access/filter/CountingFilter.java b/logback-access/src/main/java/ch/qos/logback/access/filter/CountingFilter.java index d88194ac60ff4ab0a2d1418adda05ee79014f11e..ebcc46549e92d4050b2de6b68e1f929d78d44aee 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/filter/CountingFilter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/filter/CountingFilter.java @@ -1,83 +1,83 @@ -/** - * 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.access.filter; - -import ch.qos.logback.core.filter.Filter; -import ch.qos.logback.core.spi.FilterReply; - -import javax.management.MBeanServer; -import javax.management.ObjectName; -import javax.management.StandardMBean; -import java.lang.management.ManagementFactory; - -public class CountingFilter extends Filter { - - long total = 0; - final StatisticalViewImpl accessStatsImpl; - - String domain = "ch.qos.logback.access"; - - public CountingFilter() { - accessStatsImpl = new StatisticalViewImpl(this); - } - - @Override - public FilterReply decide(Object event) { - total++; - accessStatsImpl.update(); - return FilterReply.NEUTRAL; - } - - public long getTotal() { - return total; - } - - - @Override - public void start() { - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - try { - ObjectName on = new ObjectName(domain+":Name="+getName()); - StandardMBean mbean = new StandardMBean(accessStatsImpl, StatisticalView.class); - if (mbs.isRegistered(on)) { - mbs.unregisterMBean(on); - } - mbs.registerMBean(mbean, on); - super.start(); - } catch (Exception e) { - addError("Failed to create mbean", e); - } - } - - @Override - public void stop() { - super.stop(); - try { - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - ObjectName on = new ObjectName("totp:Filter=1"); - mbs.unregisterMBean(on); - } catch(Exception e) { - addError("Failed to unregister mbean", e); - } - } - - public String getDomain() { - return domain; - } - - public void setDomain(String domain) { - this.domain = domain; - } - -} +/** + * 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.access.filter; + +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.spi.FilterReply; + +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.management.StandardMBean; +import java.lang.management.ManagementFactory; + +public class CountingFilter extends Filter { + + long total = 0; + final StatisticalViewImpl accessStatsImpl; + + String domain = "ch.qos.logback.access"; + + public CountingFilter() { + accessStatsImpl = new StatisticalViewImpl(this); + } + + @Override + public FilterReply decide(Object event) { + total++; + accessStatsImpl.update(); + return FilterReply.NEUTRAL; + } + + public long getTotal() { + return total; + } + + + @Override + public void start() { + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + try { + ObjectName on = new ObjectName(domain+":Name="+getName()); + StandardMBean mbean = new StandardMBean(accessStatsImpl, StatisticalView.class); + if (mbs.isRegistered(on)) { + mbs.unregisterMBean(on); + } + mbs.registerMBean(mbean, on); + super.start(); + } catch (Exception e) { + addError("Failed to create mbean", e); + } + } + + @Override + public void stop() { + super.stop(); + try { + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName on = new ObjectName("totp:Filter=1"); + mbs.unregisterMBean(on); + } catch(Exception e) { + addError("Failed to unregister mbean", e); + } + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/filter/PeriodicStats.java b/logback-access/src/main/java/ch/qos/logback/access/filter/PeriodicStats.java index f5de93d9c0f7682c3d715a1761f2f7ac14e2768a..a83b0029a9043c13660dc2b6e6598e103fd40d61 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/filter/PeriodicStats.java +++ b/logback-access/src/main/java/ch/qos/logback/access/filter/PeriodicStats.java @@ -1,65 +1,65 @@ -/** - * 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.access.filter; - - -abstract public class PeriodicStats { - - private long nextPeriodBegins = 0; - private long lastTotal = 0; - private long lastCount = 0; - - private double average; - private int n; - - PeriodicStats() { - this(System.currentTimeMillis()); - } - - PeriodicStats(long now) { - nextPeriodBegins = computeStartOfNextPeriod(now); - } - - void update(long now, long total) { - if (now > nextPeriodBegins) { - lastCount = total - lastTotal; - lastTotal = total; - average = (average * n + lastCount) / (++n); - nextPeriodBegins = computeStartOfNextPeriod(now); - } - } - - public double getAverage() { - return average; - } - - public long getLastCount() { - return lastCount; - } - - void reset(long now) { - nextPeriodBegins = computeStartOfNextPeriod(now); - lastTotal = 0; - lastCount = 0; - average = 0.0; - n = 0; - } - - void reset() { - reset(System.currentTimeMillis()); - } - - abstract long computeStartOfNextPeriod(long now); - -} +/** + * 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.access.filter; + + +abstract public class PeriodicStats { + + private long nextPeriodBegins = 0; + private long lastTotal = 0; + private long lastCount = 0; + + private double average; + private int n; + + PeriodicStats() { + this(System.currentTimeMillis()); + } + + PeriodicStats(long now) { + nextPeriodBegins = computeStartOfNextPeriod(now); + } + + void update(long now, long total) { + if (now > nextPeriodBegins) { + lastCount = total - lastTotal; + lastTotal = total; + average = (average * n + lastCount) / (++n); + nextPeriodBegins = computeStartOfNextPeriod(now); + } + } + + public double getAverage() { + return average; + } + + public long getLastCount() { + return lastCount; + } + + void reset(long now) { + nextPeriodBegins = computeStartOfNextPeriod(now); + lastTotal = 0; + lastCount = 0; + average = 0.0; + n = 0; + } + + void reset() { + reset(System.currentTimeMillis()); + } + + abstract long computeStartOfNextPeriod(long now); + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/filter/StatisticalView.java b/logback-access/src/main/java/ch/qos/logback/access/filter/StatisticalView.java index 4f17e148ebf5f78c862d7e532ef71f1db56b4553..06286f503d18328621fdfe10246414b3b4580408 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/filter/StatisticalView.java +++ b/logback-access/src/main/java/ch/qos/logback/access/filter/StatisticalView.java @@ -1,39 +1,39 @@ -/** - * 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.access.filter; - -public interface StatisticalView { - - - long getTotal(); - - long getLastMinuteCount(); - double getMinuteAverage(); - - - long getLastHoursCount(); - double getHourlyAverage(); - - - long getLastDaysCount(); - double getDailyAverage(); - - - long getLastWeeksCount(); - double getWeeklyAverage(); - - long getLastMonthsCount(); - double getMonthlyAverage(); - -} +/** + * 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.access.filter; + +public interface StatisticalView { + + + long getTotal(); + + long getLastMinuteCount(); + double getMinuteAverage(); + + + long getLastHoursCount(); + double getHourlyAverage(); + + + long getLastDaysCount(); + double getDailyAverage(); + + + long getLastWeeksCount(); + double getWeeklyAverage(); + + long getLastMonthsCount(); + double getMonthlyAverage(); + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/filter/StatisticalViewImpl.java b/logback-access/src/main/java/ch/qos/logback/access/filter/StatisticalViewImpl.java index de9b8ec3b4cb3bf36da2a6f928663b9585fbd6dd..9fd651aaf815f209cd53e21ef64d02cf05f33819 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/filter/StatisticalViewImpl.java +++ b/logback-access/src/main/java/ch/qos/logback/access/filter/StatisticalViewImpl.java @@ -1,116 +1,116 @@ -/** - * 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.access.filter; - -import ch.qos.logback.core.spi.LifeCycle; - -public class StatisticalViewImpl implements StatisticalView, LifeCycle { - - final CountingFilter countingFilter; - boolean started; - - StatsByMinute statsByMinute = new StatsByMinute(); - StatsByHour statsByHour = new StatsByHour(); - StatsByDay statsByDay = new StatsByDay(); - StatsByWeek statsByWeek = new StatsByWeek(); - StatsByMonth statsByMonth = new StatsByMonth(); - - StatisticalViewImpl(CountingFilter countingFilter) { - this.countingFilter = countingFilter; - } - - public double getDailyAverage() { - return statsByDay.getAverage(); - } - - public long getLastDaysCount() { - return statsByDay.getLastCount(); - } - - public double getMonthlyAverage() { - return statsByMonth.getAverage(); - } - - public long getLastMonthsCount() { - return statsByMonth.getLastCount(); - } - - public long getTotal() { - return countingFilter.getTotal(); - } - - public double getWeeklyAverage() { - return statsByWeek.getAverage(); - } - - public long getLastWeeksCount() { - return statsByWeek.getLastCount(); - } - - void update(long now) { - long total = getTotal(); - statsByMinute.update(now, total); - statsByHour.update(now, total); - statsByDay.update(now, total); - statsByWeek.update(now, total); - statsByMonth.update(now, total); - - } - - void update() { - long now = System.currentTimeMillis(); - update(now); - } - - public void start() { - System.out.println("StatisticalViewImpl start called"); - started = true; - long now = System.currentTimeMillis(); - statsByMinute = new StatsByMinute(now); - statsByHour = new StatsByHour(now); - statsByDay = new StatsByDay(now); - statsByWeek = new StatsByWeek(now); - statsByMonth = new StatsByMonth(now); - } - - public boolean isStarted() { - return started; - } - - public void stop() { - started = false; - statsByMinute.reset(); - statsByHour.reset(); - statsByDay.reset(); - statsByWeek.reset(); - statsByMonth.reset(); - } - - public long getLastMinuteCount() { - return statsByMinute.getLastCount(); - } - - public double getMinuteAverage() { - return statsByMinute.getAverage(); - } - - public double getHourlyAverage() { - return statsByHour.getAverage(); - } - - public long getLastHoursCount() { - return statsByHour.getLastCount(); - } - -} +/** + * 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.access.filter; + +import ch.qos.logback.core.spi.LifeCycle; + +public class StatisticalViewImpl implements StatisticalView, LifeCycle { + + final CountingFilter countingFilter; + boolean started; + + StatsByMinute statsByMinute = new StatsByMinute(); + StatsByHour statsByHour = new StatsByHour(); + StatsByDay statsByDay = new StatsByDay(); + StatsByWeek statsByWeek = new StatsByWeek(); + StatsByMonth statsByMonth = new StatsByMonth(); + + StatisticalViewImpl(CountingFilter countingFilter) { + this.countingFilter = countingFilter; + } + + public double getDailyAverage() { + return statsByDay.getAverage(); + } + + public long getLastDaysCount() { + return statsByDay.getLastCount(); + } + + public double getMonthlyAverage() { + return statsByMonth.getAverage(); + } + + public long getLastMonthsCount() { + return statsByMonth.getLastCount(); + } + + public long getTotal() { + return countingFilter.getTotal(); + } + + public double getWeeklyAverage() { + return statsByWeek.getAverage(); + } + + public long getLastWeeksCount() { + return statsByWeek.getLastCount(); + } + + void update(long now) { + long total = getTotal(); + statsByMinute.update(now, total); + statsByHour.update(now, total); + statsByDay.update(now, total); + statsByWeek.update(now, total); + statsByMonth.update(now, total); + + } + + void update() { + long now = System.currentTimeMillis(); + update(now); + } + + public void start() { + System.out.println("StatisticalViewImpl start called"); + started = true; + long now = System.currentTimeMillis(); + statsByMinute = new StatsByMinute(now); + statsByHour = new StatsByHour(now); + statsByDay = new StatsByDay(now); + statsByWeek = new StatsByWeek(now); + statsByMonth = new StatsByMonth(now); + } + + public boolean isStarted() { + return started; + } + + public void stop() { + started = false; + statsByMinute.reset(); + statsByHour.reset(); + statsByDay.reset(); + statsByWeek.reset(); + statsByMonth.reset(); + } + + public long getLastMinuteCount() { + return statsByMinute.getLastCount(); + } + + public double getMinuteAverage() { + return statsByMinute.getAverage(); + } + + public double getHourlyAverage() { + return statsByHour.getAverage(); + } + + public long getLastHoursCount() { + return statsByHour.getLastCount(); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByDay.java b/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByDay.java index 18ebc069746409ebf5393b9756633c3e77f3746d..2e96fc2d078ac9646ba617a4ed0e349c95a86147 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByDay.java +++ b/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByDay.java @@ -1,33 +1,33 @@ -/** - * 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.access.filter; - -import ch.qos.logback.core.util.TimeUtil; - -public class StatsByDay extends PeriodicStats { - - StatsByDay() { - super(); - } - - StatsByDay(long now) { - super(now); - } - - @Override - long computeStartOfNextPeriod(long now) { - return TimeUtil.computeStartOfNextDay(now); - } - -} +/** + * 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.access.filter; + +import ch.qos.logback.core.util.TimeUtil; + +public class StatsByDay extends PeriodicStats { + + StatsByDay() { + super(); + } + + StatsByDay(long now) { + super(now); + } + + @Override + long computeStartOfNextPeriod(long now) { + return TimeUtil.computeStartOfNextDay(now); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByHour.java b/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByHour.java index 8d2c2780c098843b1ff2b393de8b2a92d2a2ce72..25de87f24365122f22d2f310bc619203f2a20bc1 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByHour.java +++ b/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByHour.java @@ -1,33 +1,33 @@ -/** - * 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.access.filter; - -import ch.qos.logback.core.util.TimeUtil; - -public class StatsByHour extends PeriodicStats { - - StatsByHour() { - super(); - } - - StatsByHour(long now) { - super(now); - } - - @Override - long computeStartOfNextPeriod(long now) { - return TimeUtil.computeStartOfNextHour(now); - } - -} +/** + * 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.access.filter; + +import ch.qos.logback.core.util.TimeUtil; + +public class StatsByHour extends PeriodicStats { + + StatsByHour() { + super(); + } + + StatsByHour(long now) { + super(now); + } + + @Override + long computeStartOfNextPeriod(long now) { + return TimeUtil.computeStartOfNextHour(now); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByMinute.java b/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByMinute.java index 5e2cc156e22028ab4d3bcb928d05da29e0372ff9..c878e4b26c4a87180ba14bf18253d5db82f1db2d 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByMinute.java +++ b/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByMinute.java @@ -1,33 +1,33 @@ -/** - * 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.access.filter; - -import ch.qos.logback.core.util.TimeUtil; - -public class StatsByMinute extends PeriodicStats { - - StatsByMinute() { - super(); - } - - StatsByMinute(long now) { - super(now); - } - - @Override - long computeStartOfNextPeriod(long now) { - return TimeUtil.computeStartOfNextMinute(now); - } - -} +/** + * 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.access.filter; + +import ch.qos.logback.core.util.TimeUtil; + +public class StatsByMinute extends PeriodicStats { + + StatsByMinute() { + super(); + } + + StatsByMinute(long now) { + super(now); + } + + @Override + long computeStartOfNextPeriod(long now) { + return TimeUtil.computeStartOfNextMinute(now); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByMonth.java b/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByMonth.java index a7d95396cc8316a43ca99d5d43b5568acec10241..a2142a39e8736bbb28bf3ea18116d46884902630 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByMonth.java +++ b/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByMonth.java @@ -1,33 +1,33 @@ -/** - * 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.access.filter; - -import ch.qos.logback.core.util.TimeUtil; - -public class StatsByMonth extends PeriodicStats { - - StatsByMonth() { - super(); - } - - StatsByMonth(long now) { - super(now); - } - - @Override - long computeStartOfNextPeriod(long now) { - return TimeUtil.computeStartOfNextMonth(now); - } - -} +/** + * 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.access.filter; + +import ch.qos.logback.core.util.TimeUtil; + +public class StatsByMonth extends PeriodicStats { + + StatsByMonth() { + super(); + } + + StatsByMonth(long now) { + super(now); + } + + @Override + long computeStartOfNextPeriod(long now) { + return TimeUtil.computeStartOfNextMonth(now); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByWeek.java b/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByWeek.java index 6407a3d6c3a2d655258b25396259ee1f51a812b8..14de1aba9478e4920bf3bdf0a8d536417052f72a 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByWeek.java +++ b/logback-access/src/main/java/ch/qos/logback/access/filter/StatsByWeek.java @@ -1,32 +1,32 @@ -/** - * 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.access.filter; - -import ch.qos.logback.core.util.TimeUtil; - -public class StatsByWeek extends PeriodicStats { - - StatsByWeek() { - super(); - } - - StatsByWeek(long now) { - super(now); - } - @Override - long computeStartOfNextPeriod(long now) { - return TimeUtil.computeStartOfNextWeek(now); - } - -} +/** + * 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.access.filter; + +import ch.qos.logback.core.util.TimeUtil; + +public class StatsByWeek extends PeriodicStats { + + StatsByWeek() { + super(); + } + + StatsByWeek(long now) { + super(now); + } + @Override + long computeStartOfNextPeriod(long now) { + return TimeUtil.computeStartOfNextWeek(now); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/html/DefaultCssBuilder.java b/logback-access/src/main/java/ch/qos/logback/access/html/DefaultCssBuilder.java index 0f833b731514b7cea7d8664d28fe7e923145f4fc..00150eb5cc40de22971990bc8142a15d2a7422b2 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/html/DefaultCssBuilder.java +++ b/logback-access/src/main/java/ch/qos/logback/access/html/DefaultCssBuilder.java @@ -1,83 +1,83 @@ -/** - * 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.access.html; - -import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; -import ch.qos.logback.core.html.CssBuilder; - -/** - * This class helps the HTMLLayout build the CSS link. It either provides the - * HTMLLayout with a default css file, or builds the link to an external, - * user-specified, file. - * - * @author Sébastien Pennec - */ -public class DefaultCssBuilder implements CssBuilder { - - public DefaultCssBuilder() { - } - - public void addCss(StringBuilder sbuf) { - sbuf.append(""); - } +/** + * 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.access.html; + +import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; +import ch.qos.logback.core.html.CssBuilder; + +/** + * This class helps the HTMLLayout build the CSS link. It either provides the + * HTMLLayout with a default css file, or builds the link to an external, + * user-specified, file. + * + * @author Sébastien Pennec + */ +public class DefaultCssBuilder implements CssBuilder { + + public DefaultCssBuilder() { + } + + public void addCss(StringBuilder sbuf) { + sbuf.append(""); + } } \ No newline at end of file diff --git a/logback-access/src/main/java/ch/qos/logback/access/html/HTMLLayout.java b/logback-access/src/main/java/ch/qos/logback/access/html/HTMLLayout.java index f5b6e9ccbb24561f5a3d1ce19bcea2e0660e7500..e876b757cfa34c6d9660e2fb4bf90c5cd897bda9 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/html/HTMLLayout.java +++ b/logback-access/src/main/java/ch/qos/logback/access/html/HTMLLayout.java @@ -1,99 +1,99 @@ -/** - * 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.access.html; - -import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; - -import java.util.Map; - -import ch.qos.logback.access.PatternLayout; -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.html.HTMLLayoutBase; -import ch.qos.logback.core.pattern.Converter; - -/** - * - * HTMLLayout outputs events in an HTML table. - *

- * The content of the table columns are specified using a conversion pattern. - * See {@link ch.qos.logback.access.PatternLayout} for documentation on the - * available patterns. - *

- * For more information about this layout, please refer to the online manual at - * http://logback.qos.ch/manual/layouts.html#AccessHTMLLayout - * - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class HTMLLayout extends HTMLLayoutBase { - - /** - * Default pattern string for log output. - */ - static final String DEFAULT_CONVERSION_PATTERN = "%h%l%u%t%r%s%b"; - - /** - * Constructs a PatternLayout using the DEFAULT_LAYOUT_PATTERN. - * - */ - public HTMLLayout() { - pattern = DEFAULT_CONVERSION_PATTERN; - cssBuilder = new DefaultCssBuilder(); - } - - @Override - protected Map getDefaultConverterMap() { - return PatternLayout.defaultConverterMap; - } - - public String doLayout(AccessEvent event) { - StringBuilder buf = new StringBuilder(); - startNewTableIfLimitReached(buf); - - boolean odd = true; - if (((counter++) & 1) == 0) { - odd = false; - } - - buf.append(LINE_SEPARATOR); - buf.append(""); - } else { - buf.append(" even\">"); - } - buf.append(LINE_SEPARATOR); - - Converter c = head; - while (c != null) { - appendEventToBuffer(buf, c, event); - c = c.getNext(); - } - buf.append(""); - buf.append(LINE_SEPARATOR); - - return buf.toString(); - } - - private void appendEventToBuffer(StringBuilder buf, Converter c, - AccessEvent event) { - buf.append(""); - buf.append(c.convert(event)); - buf.append(""); - buf.append(LINE_SEPARATOR); - } -} +/** + * 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.access.html; + +import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; + +import java.util.Map; + +import ch.qos.logback.access.PatternLayout; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.html.HTMLLayoutBase; +import ch.qos.logback.core.pattern.Converter; + +/** + * + * HTMLLayout outputs events in an HTML table. + *

+ * The content of the table columns are specified using a conversion pattern. + * See {@link ch.qos.logback.access.PatternLayout} for documentation on the + * available patterns. + *

+ * For more information about this layout, please refer to the online manual at + * http://logback.qos.ch/manual/layouts.html#AccessHTMLLayout + * + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class HTMLLayout extends HTMLLayoutBase { + + /** + * Default pattern string for log output. + */ + static final String DEFAULT_CONVERSION_PATTERN = "%h%l%u%t%r%s%b"; + + /** + * Constructs a PatternLayout using the DEFAULT_LAYOUT_PATTERN. + * + */ + public HTMLLayout() { + pattern = DEFAULT_CONVERSION_PATTERN; + cssBuilder = new DefaultCssBuilder(); + } + + @Override + protected Map getDefaultConverterMap() { + return PatternLayout.defaultConverterMap; + } + + public String doLayout(AccessEvent event) { + StringBuilder buf = new StringBuilder(); + startNewTableIfLimitReached(buf); + + boolean odd = true; + if (((counter++) & 1) == 0) { + odd = false; + } + + buf.append(LINE_SEPARATOR); + buf.append(""); + } else { + buf.append(" even\">"); + } + buf.append(LINE_SEPARATOR); + + Converter c = head; + while (c != null) { + appendEventToBuffer(buf, c, event); + c = c.getNext(); + } + buf.append(""); + buf.append(LINE_SEPARATOR); + + return buf.toString(); + } + + private void appendEventToBuffer(StringBuilder buf, Converter c, + AccessEvent event) { + buf.append(""); + buf.append(c.convert(event)); + buf.append(""); + buf.append(LINE_SEPARATOR); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/html/UrlCssBuilder.java b/logback-access/src/main/java/ch/qos/logback/access/html/UrlCssBuilder.java index 262c00114194432a54ff5204510e54d9e5300c55..569ff773969ed35e288f9c53c9b5402aa0e5117c 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/html/UrlCssBuilder.java +++ b/logback-access/src/main/java/ch/qos/logback/access/html/UrlCssBuilder.java @@ -1,46 +1,46 @@ -/** - * 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.access.html; - -import ch.qos.logback.core.html.CssBuilder; - - -/** - * This class helps the HTMLLayout build the CSS link. - * It either provides the HTMLLayout with a default css file, - * or builds the link to an external, user-specified, file. - * - * @author Sébastien Pennec - */ -public class UrlCssBuilder implements CssBuilder { - - String url = "http://logback.qos.ch/css/access.css"; - - public UrlCssBuilder() { - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public void addCss(StringBuilder sbuf) { - sbuf.append(""); - } -} +/** + * 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.access.html; + +import ch.qos.logback.core.html.CssBuilder; + + +/** + * This class helps the HTMLLayout build the CSS link. + * It either provides the HTMLLayout with a default css file, + * or builds the link to an external, user-specified, file. + * + * @author Sébastien Pennec + */ +public class UrlCssBuilder implements CssBuilder { + + String url = "http://logback.qos.ch/css/access.css"; + + public UrlCssBuilder() { + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public void addCss(StringBuilder sbuf) { + sbuf.append(""); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/html/package.html b/logback-access/src/main/java/ch/qos/logback/access/html/package.html index 39019b9c241c77d08b25fabf46619b6fc12c7255..c988c3f19ec0d4682a4e18a8aa7c169e7dd2bdfe 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/html/package.html +++ b/logback-access/src/main/java/ch/qos/logback/access/html/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains classes to format log output in HTML.

- - + + + + + + + + + +

Contains classes to format log output in HTML.

+ + \ No newline at end of file diff --git a/logback-access/src/main/java/ch/qos/logback/access/jetty/JettyServerAdapter.java b/logback-access/src/main/java/ch/qos/logback/access/jetty/JettyServerAdapter.java index dd774990290a637f8c21b0625fb53de028e44ccf..9741f88b3407529dee8e693d4bc63d372c87079f 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/jetty/JettyServerAdapter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/jetty/JettyServerAdapter.java @@ -1,62 +1,62 @@ -/** - * 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.access.jetty; - -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; - -import org.mortbay.jetty.HttpFields; -import org.mortbay.jetty.Request; -import org.mortbay.jetty.Response; - -import ch.qos.logback.access.spi.ServerAdapter; - -/** - * A jetty specific implementation of the {@link ServerAdapter} interface. - * - * @author Sébastien Pennec - * @author Ceki Gulcu - */ -public class JettyServerAdapter implements ServerAdapter { - - Request request; - Response response; - - public JettyServerAdapter(Request jettyRequest, Response jettyResponse) { - this.request = jettyRequest; - this.response = jettyResponse; - } - - public long getContentLength() { - return response.getContentCount(); - } - - public int getStatusCode() { - return response.getStatus(); - } - - public Map buildResponseHeaderMap() { - Map responseHeaderMap = new HashMap(); - HttpFields httpFields = response.getHttpFields(); - Enumeration e = httpFields.getFieldNames(); - while (e.hasMoreElements()) { - String key = (String) e.nextElement(); - String value = response.getHeader(key); - responseHeaderMap.put(key, value); - } - return responseHeaderMap; - } - -} +/** + * 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.access.jetty; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import org.mortbay.jetty.HttpFields; +import org.mortbay.jetty.Request; +import org.mortbay.jetty.Response; + +import ch.qos.logback.access.spi.ServerAdapter; + +/** + * A jetty specific implementation of the {@link ServerAdapter} interface. + * + * @author Sébastien Pennec + * @author Ceki Gulcu + */ +public class JettyServerAdapter implements ServerAdapter { + + Request request; + Response response; + + public JettyServerAdapter(Request jettyRequest, Response jettyResponse) { + this.request = jettyRequest; + this.response = jettyResponse; + } + + public long getContentLength() { + return response.getContentCount(); + } + + public int getStatusCode() { + return response.getStatus(); + } + + public Map buildResponseHeaderMap() { + Map responseHeaderMap = new HashMap(); + HttpFields httpFields = response.getHttpFields(); + Enumeration e = httpFields.getFieldNames(); + while (e.hasMoreElements()) { + String key = (String) e.nextElement(); + String value = response.getHeader(key); + responseHeaderMap.put(key, value); + } + return responseHeaderMap; + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java b/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java index 6ec1579d90f928164f5d8c2f82d3472eb7ca85e1..b19405025b0b50ef9143f6a88e22e200d3623940 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java +++ b/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java @@ -1,254 +1,254 @@ -/** - * 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.access.jetty; - -import java.io.File; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; - -import org.mortbay.jetty.Request; -import org.mortbay.jetty.RequestLog; -import org.mortbay.jetty.Response; - -import ch.qos.logback.access.joran.JoranConfigurator; -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.filter.Filter; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.spi.AppenderAttachable; -import ch.qos.logback.core.spi.AppenderAttachableImpl; -import ch.qos.logback.core.spi.FilterAttachable; -import ch.qos.logback.core.spi.FilterAttachableImpl; -import ch.qos.logback.core.spi.FilterReply; -import ch.qos.logback.core.status.ErrorStatus; -import ch.qos.logback.core.status.InfoStatus; -import ch.qos.logback.core.status.WarnStatus; -import ch.qos.logback.core.util.OptionHelper; - -/** - * This class is logback's implementation of jetty's RequestLog interface.

- * It can be seen as logback classic's LoggerContext. Appenders can be attached - * directly to RequestLogImpl and RequestLogImpl uses the same StatusManager as - * LoggerContext does. It also provides containers for properties.

To - * configure jetty in order to use RequestLogImpl, the following lines must be - * added to the jetty configuration file, namely etc/jetty.xml: - * - *

- *    <Ref id="requestLog"> 
- *      <Set name="requestLog"> 
- *        <New id="requestLogImpl" class="ch.qos.logback.access.jetty.RequestLogImpl"></New>
- *      </Set> 
- *    </Ref>
- * 
- * - * By default, RequestLogImpl looks for a logback configuration file called - * logback-access.xml, in the same folder where jetty.xml is located, that is - * etc/logback-access.xml. The logback-access.xml file is slightly - * different than the usual logback classic configuration file. Most of it is - * the same: Appenders and Layouts are declared the exact same way. However, - * loggers elements are not allowed.

It is possible to put the logback - * configuration file anywhere, as long as it's path is specified. Here is - * another example, with a path to the logback-access.xml file. - * - *

- *    <Ref id="requestLog"> 
- *      <Set name="requestLog"> 
- *        <New id="requestLogImpl" class="ch.qos.logback.access.jetty.RequestLogImpl"></New>
- *          <Set name="fileName">path/to/logback.xml</Set>
- *      </Set> 
- *    </Ref>
- * 
- * - *

Here is a sample logback-access.xml file that can be used right away: - * - *

- *    <configuration> 
- *      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
- *        <layout class="ch.qos.logback.access.PatternLayout"> 
- *          <param name="Pattern" value="%date %server %remoteIP %clientHost %user %requestURL" />
- *        </layout> 
- *      </appender> 
- *      
- *      <appender-ref ref="STDOUT" /> 
- *    </configuration>
- * 
- * - *

Another configuration file, using SMTPAppender, could be: - * - *

- *    <configuration> 
- *      <appender name="SMTP" class="ch.qos.logback.access.net.SMTPAppender">
- *        <layout class="ch.qos.logback.access.PatternLayout">
- *          <param name="pattern" value="%remoteIP [%date] %requestURL %statusCode %bytesSent" />
- *        </layout>
- *        <param name="From" value="sender@domaine.org" />
- *        <param name="SMTPHost" value="mail.domain.org" />
- *         <param name="Subject" value="Last Event: %statusCode %requestURL" />
- *         <param name="To" value="server_admin@domain.org" />
- *      </appender>
- *      <appender-ref ref="SMTP" /> 
- *    </configuration>
- * 
- * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class RequestLogImpl extends ContextBase implements RequestLog, - AppenderAttachable, FilterAttachable { - - public final static String DEFAULT_CONFIG_FILE = "etc" + File.separatorChar - + "logback-access.xml"; - - AppenderAttachableImpl aai = new AppenderAttachableImpl(); - FilterAttachableImpl fai = new FilterAttachableImpl(); - String filename; - boolean started = false; - - public RequestLogImpl() { - putObject(CoreConstants.EVALUATOR_MAP, new HashMap()); - } - - public void log(Request jettyRequest, Response jettyResponse) { - JettyServerAdapter adapter = new JettyServerAdapter(jettyRequest, - jettyResponse); - AccessEvent accessEvent = new AccessEvent(jettyRequest, jettyResponse, - adapter); - if (getFilterChainDecision(accessEvent) == FilterReply.DENY) { - return; - } - aai.appendLoopOnAppenders(accessEvent); - } - - public void start() { - if (filename == null) { - String jettyHomeProperty = OptionHelper.getSystemProperty("jetty.home"); - - filename = jettyHomeProperty + File.separatorChar + DEFAULT_CONFIG_FILE; - getStatusManager().add( - new WarnStatus("filename property not set. Assuming [" + filename - + "]", this)); - - } - try { - File configFile = new File(filename); - if (configFile.exists()) { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(this); - jc.doConfigure(filename); - - } else { - getStatusManager().add( - new ErrorStatus("[" + filename + "] does not exist", this)); - } - - if (getName() == null) { - setName("LogbackRequestLog"); - } - RequestLogRegistry.register(this); - getStatusManager().add( - new InfoStatus("RequestLog added to RequestLogRegistry with name: " - + getName(), this)); - - started = true; - - } catch (JoranException e) { - // errors have been registered as status messages - } - } - - public void stop() { - aai.detachAndStopAllAppenders(); - started = false; - } - - public boolean isRunning() { - return started; - } - - public void setFileName(String filename) { - this.filename = filename; - } - - public boolean isStarted() { - return started; - } - - public boolean isStarting() { - return false; - } - - public boolean isStopping() { - return false; - } - - public boolean isStopped() { - return !started; - } - - public boolean isFailed() { - return false; - } - - public void addAppender(Appender newAppender) { - aai.addAppender(newAppender); - } - - public Iterator> iteratorForAppenders() { - return aai.iteratorForAppenders(); - } - - public Appender getAppender(String name) { - return aai.getAppender(name); - } - - public boolean isAttached(Appender appender) { - return aai.isAttached(appender); - } - - public void detachAndStopAllAppenders() { - aai.detachAndStopAllAppenders(); - - } - - public boolean detachAppender(Appender appender) { - return aai.detachAppender(appender); - } - - public boolean detachAppender(String name) { - return aai.detachAppender(name); - } - - public void addFilter(Filter newFilter) { - fai.addFilter(newFilter); - } - - public void clearAllFilters() { - fai.clearAllFilters(); - } - - public List> getCopyOfAttachedFiltersList() { - return fai.getCopyOfAttachedFiltersList(); - } - - public FilterReply getFilterChainDecision(AccessEvent event) { - return fai.getFilterChainDecision(event); - } - - public Filter getFirstFilter() { - return fai.getFirstFilter(); - } -} +/** + * 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.access.jetty; + +import java.io.File; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.mortbay.jetty.Request; +import org.mortbay.jetty.RequestLog; +import org.mortbay.jetty.Response; + +import ch.qos.logback.access.joran.JoranConfigurator; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.spi.AppenderAttachable; +import ch.qos.logback.core.spi.AppenderAttachableImpl; +import ch.qos.logback.core.spi.FilterAttachable; +import ch.qos.logback.core.spi.FilterAttachableImpl; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.WarnStatus; +import ch.qos.logback.core.util.OptionHelper; + +/** + * This class is logback's implementation of jetty's RequestLog interface.

+ * It can be seen as logback classic's LoggerContext. Appenders can be attached + * directly to RequestLogImpl and RequestLogImpl uses the same StatusManager as + * LoggerContext does. It also provides containers for properties.

To + * configure jetty in order to use RequestLogImpl, the following lines must be + * added to the jetty configuration file, namely etc/jetty.xml: + * + *

+ *    <Ref id="requestLog"> 
+ *      <Set name="requestLog"> 
+ *        <New id="requestLogImpl" class="ch.qos.logback.access.jetty.RequestLogImpl"></New>
+ *      </Set> 
+ *    </Ref>
+ * 
+ * + * By default, RequestLogImpl looks for a logback configuration file called + * logback-access.xml, in the same folder where jetty.xml is located, that is + * etc/logback-access.xml. The logback-access.xml file is slightly + * different than the usual logback classic configuration file. Most of it is + * the same: Appenders and Layouts are declared the exact same way. However, + * loggers elements are not allowed.

It is possible to put the logback + * configuration file anywhere, as long as it's path is specified. Here is + * another example, with a path to the logback-access.xml file. + * + *

+ *    <Ref id="requestLog"> 
+ *      <Set name="requestLog"> 
+ *        <New id="requestLogImpl" class="ch.qos.logback.access.jetty.RequestLogImpl"></New>
+ *          <Set name="fileName">path/to/logback.xml</Set>
+ *      </Set> 
+ *    </Ref>
+ * 
+ * + *

Here is a sample logback-access.xml file that can be used right away: + * + *

+ *    <configuration> 
+ *      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
+ *        <layout class="ch.qos.logback.access.PatternLayout"> 
+ *          <param name="Pattern" value="%date %server %remoteIP %clientHost %user %requestURL" />
+ *        </layout> 
+ *      </appender> 
+ *      
+ *      <appender-ref ref="STDOUT" /> 
+ *    </configuration>
+ * 
+ * + *

Another configuration file, using SMTPAppender, could be: + * + *

+ *    <configuration> 
+ *      <appender name="SMTP" class="ch.qos.logback.access.net.SMTPAppender">
+ *        <layout class="ch.qos.logback.access.PatternLayout">
+ *          <param name="pattern" value="%remoteIP [%date] %requestURL %statusCode %bytesSent" />
+ *        </layout>
+ *        <param name="From" value="sender@domaine.org" />
+ *        <param name="SMTPHost" value="mail.domain.org" />
+ *         <param name="Subject" value="Last Event: %statusCode %requestURL" />
+ *         <param name="To" value="server_admin@domain.org" />
+ *      </appender>
+ *      <appender-ref ref="SMTP" /> 
+ *    </configuration>
+ * 
+ * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class RequestLogImpl extends ContextBase implements RequestLog, + AppenderAttachable, FilterAttachable { + + public final static String DEFAULT_CONFIG_FILE = "etc" + File.separatorChar + + "logback-access.xml"; + + AppenderAttachableImpl aai = new AppenderAttachableImpl(); + FilterAttachableImpl fai = new FilterAttachableImpl(); + String filename; + boolean started = false; + + public RequestLogImpl() { + putObject(CoreConstants.EVALUATOR_MAP, new HashMap()); + } + + public void log(Request jettyRequest, Response jettyResponse) { + JettyServerAdapter adapter = new JettyServerAdapter(jettyRequest, + jettyResponse); + AccessEvent accessEvent = new AccessEvent(jettyRequest, jettyResponse, + adapter); + if (getFilterChainDecision(accessEvent) == FilterReply.DENY) { + return; + } + aai.appendLoopOnAppenders(accessEvent); + } + + public void start() { + if (filename == null) { + String jettyHomeProperty = OptionHelper.getSystemProperty("jetty.home"); + + filename = jettyHomeProperty + File.separatorChar + DEFAULT_CONFIG_FILE; + getStatusManager().add( + new WarnStatus("filename property not set. Assuming [" + filename + + "]", this)); + + } + try { + File configFile = new File(filename); + if (configFile.exists()) { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(this); + jc.doConfigure(filename); + + } else { + getStatusManager().add( + new ErrorStatus("[" + filename + "] does not exist", this)); + } + + if (getName() == null) { + setName("LogbackRequestLog"); + } + RequestLogRegistry.register(this); + getStatusManager().add( + new InfoStatus("RequestLog added to RequestLogRegistry with name: " + + getName(), this)); + + started = true; + + } catch (JoranException e) { + // errors have been registered as status messages + } + } + + public void stop() { + aai.detachAndStopAllAppenders(); + started = false; + } + + public boolean isRunning() { + return started; + } + + public void setFileName(String filename) { + this.filename = filename; + } + + public boolean isStarted() { + return started; + } + + public boolean isStarting() { + return false; + } + + public boolean isStopping() { + return false; + } + + public boolean isStopped() { + return !started; + } + + public boolean isFailed() { + return false; + } + + public void addAppender(Appender newAppender) { + aai.addAppender(newAppender); + } + + public Iterator> iteratorForAppenders() { + return aai.iteratorForAppenders(); + } + + public Appender getAppender(String name) { + return aai.getAppender(name); + } + + public boolean isAttached(Appender appender) { + return aai.isAttached(appender); + } + + public void detachAndStopAllAppenders() { + aai.detachAndStopAllAppenders(); + + } + + public boolean detachAppender(Appender appender) { + return aai.detachAppender(appender); + } + + public boolean detachAppender(String name) { + return aai.detachAppender(name); + } + + public void addFilter(Filter newFilter) { + fai.addFilter(newFilter); + } + + public void clearAllFilters() { + fai.clearAllFilters(); + } + + public List> getCopyOfAttachedFiltersList() { + return fai.getCopyOfAttachedFiltersList(); + } + + public FilterReply getFilterChainDecision(AccessEvent event) { + return fai.getFilterChainDecision(event); + } + + public Filter getFirstFilter() { + return fai.getFirstFilter(); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogRegistry.java b/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogRegistry.java index e1415bea1d8f682ad98ada3e69fbdccdf13718f9..53d40d28b302fcc1273214afd787b662923aa2e6 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogRegistry.java +++ b/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogRegistry.java @@ -1,31 +1,31 @@ -/** - * 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.access.jetty; - -import java.util.HashMap; -import java.util.Map; - -public class RequestLogRegistry { - - private static Map requestLogRegistry = new HashMap(); - - public static void register(RequestLogImpl requestLogImpl) { - requestLogRegistry.put(requestLogImpl.getName(), requestLogImpl); - } - - public static RequestLogImpl get(String key) { - return requestLogRegistry.get(key); - } - -} +/** + * 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.access.jetty; + +import java.util.HashMap; +import java.util.Map; + +public class RequestLogRegistry { + + private static Map requestLogRegistry = new HashMap(); + + public static void register(RequestLogImpl requestLogImpl) { + requestLogRegistry.put(requestLogImpl.getName(), requestLogImpl); + } + + public static RequestLogImpl get(String key) { + return requestLogRegistry.get(key); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/jetty/package.html b/logback-access/src/main/java/ch/qos/logback/access/jetty/package.html index 67095980f0ca50c149e05c9a88f43aca70509488..20a34c34fdd9e64ed4216b46db0d7d2d76010ec4 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/jetty/package.html +++ b/logback-access/src/main/java/ch/qos/logback/access/jetty/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

This is logback access' implementation for Jetty.

- - + + + + + + + + + +

This is logback access' implementation for Jetty.

+ + \ No newline at end of file diff --git a/logback-access/src/main/java/ch/qos/logback/access/joran/action/ConfigurationAction.java b/logback-access/src/main/java/ch/qos/logback/access/joran/action/ConfigurationAction.java index 25c1551e351ff5020d1c9bd16ed627b55a35ae5f..ed776dc6b8bd3f608b0f3c08cd16f64c2734caea 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/joran/action/ConfigurationAction.java +++ b/logback-access/src/main/java/ch/qos/logback/access/joran/action/ConfigurationAction.java @@ -1,51 +1,51 @@ -/** - * 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.access.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.util.StatusPrinter; - - - -public class ConfigurationAction extends Action { - static final String INTERNAL_DEBUG_ATTR = "debug"; - boolean debugMode = false; - - public void begin(InterpretationContext ec, String name, Attributes attributes) { - String debugAttrib = attributes.getValue(INTERNAL_DEBUG_ATTR); - - if ( - (debugAttrib == null) || debugAttrib.equals("") - || debugAttrib.equals("false") || debugAttrib.equals("null")) { - addInfo("Ignoring " + INTERNAL_DEBUG_ATTR + " attribute."); - } else { - debugMode = true; - } - - // the context is appender attachable, so it is pushed on top of the stack - ec.pushObject(getContext()); - } - - public void end(InterpretationContext ec, String name) { - addInfo("End of configuration."); - if (debugMode) { - StatusPrinter.print(context); - } - - ec.popObject(); - } -} +/** + * 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.access.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.StatusPrinter; + + + +public class ConfigurationAction extends Action { + static final String INTERNAL_DEBUG_ATTR = "debug"; + boolean debugMode = false; + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + String debugAttrib = attributes.getValue(INTERNAL_DEBUG_ATTR); + + if ( + (debugAttrib == null) || debugAttrib.equals("") + || debugAttrib.equals("false") || debugAttrib.equals("null")) { + addInfo("Ignoring " + INTERNAL_DEBUG_ATTR + " attribute."); + } else { + debugMode = true; + } + + // the context is appender attachable, so it is pushed on top of the stack + ec.pushObject(getContext()); + } + + public void end(InterpretationContext ec, String name) { + addInfo("End of configuration."); + if (debugMode) { + StatusPrinter.print(context); + } + + ec.popObject(); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/joran/action/EvaluatorAction.java b/logback-access/src/main/java/ch/qos/logback/access/joran/action/EvaluatorAction.java index 852a88ce95c0b2925e347104eccf1f3908354ae5..7083dec3b4f939c15524d21105d86f3cc7bdd717 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/joran/action/EvaluatorAction.java +++ b/logback-access/src/main/java/ch/qos/logback/access/joran/action/EvaluatorAction.java @@ -1,25 +1,25 @@ -/** - * 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.access.joran.action; - -import ch.qos.logback.access.boolex.JaninoEventEvaluator; -import ch.qos.logback.core.joran.action.AbstractEventEvaluatorAction; - - -public class EvaluatorAction extends AbstractEventEvaluatorAction { - - protected String defaultClassName() { - return JaninoEventEvaluator.class.getName(); - } -} +/** + * 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.access.joran.action; + +import ch.qos.logback.access.boolex.JaninoEventEvaluator; +import ch.qos.logback.core.joran.action.AbstractEventEvaluatorAction; + + +public class EvaluatorAction extends AbstractEventEvaluatorAction { + + protected String defaultClassName() { + return JaninoEventEvaluator.class.getName(); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/joran/package.html b/logback-access/src/main/java/ch/qos/logback/access/joran/package.html index 273b137885afd298c68fd7b83693a21f1c6c5fad..3955b621f0d145c2eb22482c1b74a136bfcf4b04 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/joran/package.html +++ b/logback-access/src/main/java/ch/qos/logback/access/joran/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains the Joran configration classes

- - + + + + + + + + + +

Contains the Joran configration classes

+ + \ No newline at end of file diff --git a/logback-access/src/main/java/ch/qos/logback/access/net/AccessEventPreSerializationTransformer.java b/logback-access/src/main/java/ch/qos/logback/access/net/AccessEventPreSerializationTransformer.java index 280a45433d7a38f709be168b795447988da1ea3a..567867159cd30230f39610591dc115edd1a15510 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/net/AccessEventPreSerializationTransformer.java +++ b/logback-access/src/main/java/ch/qos/logback/access/net/AccessEventPreSerializationTransformer.java @@ -1,28 +1,28 @@ -/** - * 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.access.net; - -import java.io.Serializable; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.spi.PreSerializationTransformer; - -public class AccessEventPreSerializationTransformer implements - PreSerializationTransformer { - - public Serializable transform(AccessEvent event) { - return event; - } - -} +/** + * 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.access.net; + +import java.io.Serializable; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.spi.PreSerializationTransformer; + +public class AccessEventPreSerializationTransformer implements + PreSerializationTransformer { + + public Serializable transform(AccessEvent event) { + return event; + } + +} 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 b54e88b5af57d297e70f7c38f5e5b19650df212a..13477e923330a628fedc12bea8509309f856a9fa 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 @@ -1,105 +1,105 @@ -/** - * 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.access.net; - -import ch.qos.logback.access.PatternLayout; -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.Layout; -import ch.qos.logback.core.boolex.EventEvaluator; -import ch.qos.logback.core.helpers.CyclicBuffer; -import ch.qos.logback.core.net.SMTPAppenderBase; - -/** - * Send an e-mail when a specific access event occurs, typically when - * certain pages are accessed. - * - * For more information about this appender, please refer to the online manual at - * http://logback.qos.ch/manual/appenders.html#AccessSMTPAppender - *

- * @author Ceki Gülcü - * @author Sébastien Pennec - * - */ -public class SMTPAppender extends SMTPAppenderBase { - - static final String DEFAULT_SUBJECT_PATTERN = "%m"; - - private int bufferSize = 512; - protected CyclicBuffer cb = new CyclicBuffer(bufferSize); - - /** - * The default constructor will instantiate the appender with a - * {@link EventEvaluator} that will trigger on events with level - * ERROR or higher. - */ - public SMTPAppender() { - } - - /** - * Use evaluator passed as parameter as the {@link - * EventEvaluator} for this SMTPAppender. - */ - public SMTPAppender(EventEvaluator evaluator) { - this.eventEvaluator = evaluator; - } - - /** - * Perform SMTPAppender specific appending actions, mainly adding the event to - * a cyclic buffer. - */ - protected void subAppend(AccessEvent event) { - cb.add(event); - // addInfo("Added event to the cyclic buffer: " + event.getMessage()); - } - - @Override - protected void fillBuffer(StringBuffer sbuf) { - int len = cb.length(); - for (int i = 0; i < len; i++) { - // sbuf.append(MimeUtility.encodeText(layout.format(cb.get()))); - AccessEvent event = (AccessEvent) cb.get(); - sbuf.append(layout.doLayout(event)); - } - } - - /** - * The BufferSize option takes a positive integer representing the - * maximum number of logging events to collect in a cyclic buffer. When the - * BufferSize is reached, oldest events are deleted as new - * events are added to the buffer. By default the size of the cyclic buffer is - * 512 events. - */ - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - cb.resize(bufferSize); - } - - /** - * Returns value of the BufferSize option. - */ - public int getBufferSize() { - return bufferSize; - } - - @Override - protected Layout makeSubjectLayout(String subjectStr) { - if(subjectStr == null) { - subjectStr = DEFAULT_SUBJECT_PATTERN; - } - PatternLayout pl = new PatternLayout(); - pl.setPattern(subjectStr); - pl.start(); - return pl; - } -} +/** + * 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.access.net; + +import ch.qos.logback.access.PatternLayout; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.helpers.CyclicBuffer; +import ch.qos.logback.core.net.SMTPAppenderBase; + +/** + * Send an e-mail when a specific access event occurs, typically when + * certain pages are accessed. + * + * For more information about this appender, please refer to the online manual at + * http://logback.qos.ch/manual/appenders.html#AccessSMTPAppender + *

+ * @author Ceki Gülcü + * @author Sébastien Pennec + * + */ +public class SMTPAppender extends SMTPAppenderBase { + + static final String DEFAULT_SUBJECT_PATTERN = "%m"; + + private int bufferSize = 512; + protected CyclicBuffer cb = new CyclicBuffer(bufferSize); + + /** + * The default constructor will instantiate the appender with a + * {@link EventEvaluator} that will trigger on events with level + * ERROR or higher. + */ + public SMTPAppender() { + } + + /** + * Use evaluator passed as parameter as the {@link + * EventEvaluator} for this SMTPAppender. + */ + public SMTPAppender(EventEvaluator evaluator) { + this.eventEvaluator = evaluator; + } + + /** + * Perform SMTPAppender specific appending actions, mainly adding the event to + * a cyclic buffer. + */ + protected void subAppend(AccessEvent event) { + cb.add(event); + // addInfo("Added event to the cyclic buffer: " + event.getMessage()); + } + + @Override + protected void fillBuffer(StringBuffer sbuf) { + int len = cb.length(); + for (int i = 0; i < len; i++) { + // sbuf.append(MimeUtility.encodeText(layout.format(cb.get()))); + AccessEvent event = (AccessEvent) cb.get(); + sbuf.append(layout.doLayout(event)); + } + } + + /** + * The BufferSize option takes a positive integer representing the + * maximum number of logging events to collect in a cyclic buffer. When the + * BufferSize is reached, oldest events are deleted as new + * events are added to the buffer. By default the size of the cyclic buffer is + * 512 events. + */ + public void setBufferSize(int bufferSize) { + this.bufferSize = bufferSize; + cb.resize(bufferSize); + } + + /** + * Returns value of the BufferSize option. + */ + public int getBufferSize() { + return bufferSize; + } + + @Override + protected Layout makeSubjectLayout(String subjectStr) { + if(subjectStr == null) { + subjectStr = DEFAULT_SUBJECT_PATTERN; + } + PatternLayout pl = new PatternLayout(); + pl.setPattern(subjectStr); + pl.start(); + return pl; + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/net/URLEvaluator.java b/logback-access/src/main/java/ch/qos/logback/access/net/URLEvaluator.java index e230aa7f4578b12369fddb34bfd0122413b7a918..b20133bb7bdcb12d02d13678976fe1410ee84ebf 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/net/URLEvaluator.java +++ b/logback-access/src/main/java/ch/qos/logback/access/net/URLEvaluator.java @@ -1,72 +1,72 @@ -/** - * 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.access.net; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.boolex.EvaluationException; -import ch.qos.logback.core.boolex.EventEvaluator; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.spi.LifeCycle; - -public class URLEvaluator extends ContextAwareBase implements EventEvaluator, LifeCycle { - - boolean started; - String name; - private List URLList = new ArrayList(); - - public URLEvaluator() { - } - - public void addURL(String url) { - URLList.add(url); - } - - public void start() { - if (URLList.size() == 0) { - addWarn("No URL was given to URLEvaluator"); - } else { - started = true; - } - } - - public boolean evaluate(Object eventObject) throws NullPointerException, EvaluationException { - AccessEvent event = (AccessEvent)eventObject; - String url = event.getRequestURL(); - for(String expected:URLList) { - if (url.contains(expected)) { - return true; - } - } - return false; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public boolean isStarted() { - return started; - } - - public void stop() { - started = false; - } -} +/** + * 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.access.net; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.LifeCycle; + +public class URLEvaluator extends ContextAwareBase implements EventEvaluator, LifeCycle { + + boolean started; + String name; + private List URLList = new ArrayList(); + + public URLEvaluator() { + } + + public void addURL(String url) { + URLList.add(url); + } + + public void start() { + if (URLList.size() == 0) { + addWarn("No URL was given to URLEvaluator"); + } else { + started = true; + } + } + + public boolean evaluate(Object eventObject) throws NullPointerException, EvaluationException { + AccessEvent event = (AccessEvent)eventObject; + String url = event.getRequestURL(); + for(String expected:URLList) { + if (url.contains(expected)) { + return true; + } + } + return false; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isStarted() { + return started; + } + + public void stop() { + started = false; + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/package.html b/logback-access/src/main/java/ch/qos/logback/access/package.html index 012a1e37e5c2348f9d9ea0c5aef9791982e759b0..5755fc496868950e6076d2e6d92f91f04ce88bbc 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/package.html +++ b/logback-access/src/main/java/ch/qos/logback/access/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

This is logback access' main package.

- - + + + + + + + + + +

This is logback access' main package.

+ + \ No newline at end of file diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/AccessConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/AccessConverter.java index 853c84149121d68ebb5c5c0dbf0d6255f5bf261d..341562bb161f9461e2cffd2d9caf835c8964ac80 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/AccessConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/AccessConverter.java @@ -1,67 +1,67 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.pattern.DynamicConverter; -import ch.qos.logback.core.spi.ContextAware; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.status.Status; - - -abstract public class AccessConverter extends DynamicConverter implements ContextAware { - - public final static char SPACE_CHAR = ' '; - public final static char QUESTION_CHAR = '?'; - - ContextAwareBase cab = new ContextAwareBase(); - - 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) { - addError(msg); - } - - public void addError(String msg, Throwable ex) { - addError(msg, ex); - } - -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.pattern.DynamicConverter; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.status.Status; + + +abstract public class AccessConverter extends DynamicConverter implements ContextAware { + + public final static char SPACE_CHAR = ' '; + public final static char QUESTION_CHAR = '?'; + + ContextAwareBase cab = new ContextAwareBase(); + + 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) { + addError(msg); + } + + public void addError(String msg, Throwable ex) { + addError(msg, ex); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/ContentLengthConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/ContentLengthConverter.java index 4453aaa6c04e011ed13a4834296d73b42a6dbc47..c88298c6c5c5dd2bc32a16a6e1be342985765ff2 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/ContentLengthConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/ContentLengthConverter.java @@ -1,29 +1,29 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -public class ContentLengthConverter extends AccessConverter { - - public String convert(AccessEvent accessEvent) { - long len = accessEvent.getContentLength(); - if(len == AccessEvent.SENTINEL) { - return AccessEvent.NA; - } else { - return Long.toString(len); - } - } - -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +public class ContentLengthConverter extends AccessConverter { + + public String convert(AccessEvent accessEvent) { + long len = accessEvent.getContentLength(); + if(len == AccessEvent.SENTINEL) { + return AccessEvent.NA; + } else { + return Long.toString(len); + } + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/DateConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/DateConverter.java index fb6a39e5749025ceb4585d2bd5ee52f31219f8c9..23299bd480b077333241156e2228c1190873bb3d 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/DateConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/DateConverter.java @@ -1,77 +1,77 @@ -/** - * 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.access.pattern; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.TimeZone; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.CoreConstants; - - - -public class DateConverter extends AccessConverter { - - long lastTimestamp = -1; - String timesmapStr = null; - SimpleDateFormat simpleFormat = null; - - public void start() { - - String datePattern = getFirstOption(); - if(datePattern == null) { - datePattern = CoreConstants.CLF_DATE_PATTERN; - } - - if (datePattern.equals(CoreConstants.ISO8601_STR)) { - datePattern = CoreConstants.ISO8601_PATTERN; - } - - try { - simpleFormat = new SimpleDateFormat(datePattern); - //maximumCacheValidity = CachedDateFormat.getMaximumCacheValidity(pattern); - } catch (IllegalArgumentException e) { - addWarn( - "Could not instantiate SimpleDateFormat with pattern " + datePattern, e); - // default to the ISO8601 format - simpleFormat = new SimpleDateFormat(CoreConstants.CLF_DATE_PATTERN); - } - - List optionList = getOptionList(); - - // if the option list contains a TZ option, then set it. - if (optionList != null && optionList.size() > 1) { - TimeZone tz = TimeZone.getTimeZone((String) optionList.get(1)); - simpleFormat.setTimeZone(tz); - } - } - - - public String convert(AccessEvent accessEvent) { - - long timestamp = accessEvent.getTimeStamp(); - - // if called multiple times within the same millisecond - // return old value - if(timestamp == lastTimestamp) { - return timesmapStr; - } else { - lastTimestamp = timestamp; - timesmapStr = simpleFormat.format(new Date(timestamp)); - return timesmapStr; - } - } -} +/** + * 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.access.pattern; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.CoreConstants; + + + +public class DateConverter extends AccessConverter { + + long lastTimestamp = -1; + String timesmapStr = null; + SimpleDateFormat simpleFormat = null; + + public void start() { + + String datePattern = getFirstOption(); + if(datePattern == null) { + datePattern = CoreConstants.CLF_DATE_PATTERN; + } + + if (datePattern.equals(CoreConstants.ISO8601_STR)) { + datePattern = CoreConstants.ISO8601_PATTERN; + } + + try { + simpleFormat = new SimpleDateFormat(datePattern); + //maximumCacheValidity = CachedDateFormat.getMaximumCacheValidity(pattern); + } catch (IllegalArgumentException e) { + addWarn( + "Could not instantiate SimpleDateFormat with pattern " + datePattern, e); + // default to the ISO8601 format + simpleFormat = new SimpleDateFormat(CoreConstants.CLF_DATE_PATTERN); + } + + List optionList = getOptionList(); + + // if the option list contains a TZ option, then set it. + if (optionList != null && optionList.size() > 1) { + TimeZone tz = TimeZone.getTimeZone((String) optionList.get(1)); + simpleFormat.setTimeZone(tz); + } + } + + + public String convert(AccessEvent accessEvent) { + + long timestamp = accessEvent.getTimeStamp(); + + // if called multiple times within the same millisecond + // return old value + if(timestamp == lastTimestamp) { + return timesmapStr; + } else { + lastTimestamp = timestamp; + timesmapStr = simpleFormat.format(new Date(timestamp)); + return timesmapStr; + } + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/EnsureLineSeparation.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/EnsureLineSeparation.java index 725ceda203e53ab2685ea37bee5682defa67c8bc..abc7f99afaeff75b32a40f95fd8acc2d8cca91fb 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/EnsureLineSeparation.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/EnsureLineSeparation.java @@ -1,38 +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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.pattern.Converter; -import ch.qos.logback.core.pattern.ConverterUtil; -import ch.qos.logback.core.pattern.PostCompileProcessor; - -public class EnsureLineSeparation implements PostCompileProcessor { - - /** - * Add a line separator converter so that access event appears on a separate - * line. - */ - public void process(Converter head) { - Converter tail = ConverterUtil.findTail(head); - Converter newLineConverter = new LineSeparatorConverter(); - if (tail == null) { - head = newLineConverter; - } else { - if (!(tail instanceof LineSeparatorConverter)) { - tail.setNext(newLineConverter); - } - } - } -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.pattern.Converter; +import ch.qos.logback.core.pattern.ConverterUtil; +import ch.qos.logback.core.pattern.PostCompileProcessor; + +public class EnsureLineSeparation implements PostCompileProcessor { + + /** + * Add a line separator converter so that access event appears on a separate + * line. + */ + public void process(Converter head) { + Converter tail = ConverterUtil.findTail(head); + Converter newLineConverter = new LineSeparatorConverter(); + if (tail == null) { + head = newLineConverter; + } else { + if (!(tail instanceof LineSeparatorConverter)) { + tail.setNext(newLineConverter); + } + } + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/FullRequestConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/FullRequestConverter.java index 0c4cdc1201ec6de673e48f84fa19d0ab0dd526e6..9ece66b0eee0e826b3f7f126510ed06c15855423 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/FullRequestConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/FullRequestConverter.java @@ -1,51 +1,51 @@ -/** - * 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.access.pattern; - -import java.util.Enumeration; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.CoreConstants; - -/** - * This class is tied to the fullRequest conversion word. - *

- * It has been removed from the {@link ch.qos.logback.access.PatternLayout} since - * it needs further testing before wide use. - *

- * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class FullRequestConverter extends AccessConverter { - - @Override - public String convert(AccessEvent ae) { - StringBuffer buf = new StringBuffer(); - buf.append(ae.getRequestURL()); - buf.append(CoreConstants.LINE_SEPARATOR); - - Enumeration headerNames = ae.getRequestHeaderNames(); - while(headerNames.hasMoreElements()) { - String name = (String) headerNames.nextElement(); - buf.append(name); - buf.append(": "); - buf.append(ae.getRequestHeader(name)); - buf.append(CoreConstants.LINE_SEPARATOR); - } - buf.append(CoreConstants.LINE_SEPARATOR); - buf.append(ae.getRequestContent()); - 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.access.pattern; + +import java.util.Enumeration; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.CoreConstants; + +/** + * This class is tied to the fullRequest conversion word. + *

+ * It has been removed from the {@link ch.qos.logback.access.PatternLayout} since + * it needs further testing before wide use. + *

+ * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class FullRequestConverter extends AccessConverter { + + @Override + public String convert(AccessEvent ae) { + StringBuffer buf = new StringBuffer(); + buf.append(ae.getRequestURL()); + buf.append(CoreConstants.LINE_SEPARATOR); + + Enumeration headerNames = ae.getRequestHeaderNames(); + while(headerNames.hasMoreElements()) { + String name = (String) headerNames.nextElement(); + buf.append(name); + buf.append(": "); + buf.append(ae.getRequestHeader(name)); + buf.append(CoreConstants.LINE_SEPARATOR); + } + buf.append(CoreConstants.LINE_SEPARATOR); + buf.append(ae.getRequestContent()); + return buf.toString(); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/FullResponseConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/FullResponseConverter.java index 34c3e20b993dbaaff1ac9cfe8e7054079c5af80e..de9e25e5baece4e761109b90f5c5e7f3d5b0b380 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/FullResponseConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/FullResponseConverter.java @@ -1,91 +1,91 @@ -/** - * 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.access.pattern; - -import java.util.List; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.CoreConstants; - -public class FullResponseConverter extends AccessConverter { - - @Override - public String convert(AccessEvent ae) { - StringBuffer buf = new StringBuffer(); - - buf.append("HTTP/1.1 "); - int statusCode = ae.getStatusCode(); - buf.append(statusCode); - buf.append(" "); - buf.append(getStatusCodeDescription(statusCode)); - buf.append(CoreConstants.LINE_SEPARATOR); - - List hnList = ae.getResponseHeaderNameList(); - for(String headerName: hnList) { - buf.append(headerName); - buf.append(": "); - buf.append(ae.getResponseHeader(headerName)); - buf.append(CoreConstants.LINE_SEPARATOR); - } - buf.append(CoreConstants.LINE_SEPARATOR); - buf.append(ae.getResponseContent()); - buf.append(CoreConstants.LINE_SEPARATOR); - return buf.toString(); - } - - static String getStatusCodeDescription(int sc) { - switch(sc) { - case 200: return "OK"; - case 201: return "Created"; - case 202: return "Accepted"; - case 203: return "Non-Authoritative Information"; - case 204: return "No Content"; - case 205: return "Reset Content"; - case 206: return "Partial Content"; - case 300: return "Multiple Choices"; - case 301: return "Moved Permanently"; - case 302: return "Found"; - case 303: return "See Other"; - case 304: return "Not Modified"; - case 305: return "Use Proxy"; - case 306: return "(Unused)"; - case 307: return "Temporary Redirect"; - case 400: return "Bad Request"; - case 401: return "Unauthorized"; - case 402: return "Payment Required"; - case 403: return "Forbidden"; - case 404: return "Not Found"; - case 405: return "Method Not Allowed"; - case 406: return "Not Acceptable"; - case 407: return "Proxy Authentication Required"; - case 408: return "Request Timeout"; - case 409: return "Conflict"; - case 410: return "Gone"; - case 411: return "Length Required"; - case 412: return "Precondition Failed"; - case 413: return "Request Entity Too Large"; - case 414: return "Request-URI Too Long"; - case 415: return "Unsupported Media Type"; - case 416: return "Requested Range Not Satisfiable"; - case 417: return "Expectation Failed"; - case 500: return "Internal Server Error"; - case 501: return "Not Implemented"; - case 502: return "Bad Gateway"; - case 503: return "Service Unavailable"; - case 504: return "Gateway Timeout"; - case 505: return "HTTP Version Not Supported"; - default: return "NA"; - } - } -} +/** + * 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.access.pattern; + +import java.util.List; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.CoreConstants; + +public class FullResponseConverter extends AccessConverter { + + @Override + public String convert(AccessEvent ae) { + StringBuffer buf = new StringBuffer(); + + buf.append("HTTP/1.1 "); + int statusCode = ae.getStatusCode(); + buf.append(statusCode); + buf.append(" "); + buf.append(getStatusCodeDescription(statusCode)); + buf.append(CoreConstants.LINE_SEPARATOR); + + List hnList = ae.getResponseHeaderNameList(); + for(String headerName: hnList) { + buf.append(headerName); + buf.append(": "); + buf.append(ae.getResponseHeader(headerName)); + buf.append(CoreConstants.LINE_SEPARATOR); + } + buf.append(CoreConstants.LINE_SEPARATOR); + buf.append(ae.getResponseContent()); + buf.append(CoreConstants.LINE_SEPARATOR); + return buf.toString(); + } + + static String getStatusCodeDescription(int sc) { + switch(sc) { + case 200: return "OK"; + case 201: return "Created"; + case 202: return "Accepted"; + case 203: return "Non-Authoritative Information"; + case 204: return "No Content"; + case 205: return "Reset Content"; + case 206: return "Partial Content"; + case 300: return "Multiple Choices"; + case 301: return "Moved Permanently"; + case 302: return "Found"; + case 303: return "See Other"; + case 304: return "Not Modified"; + case 305: return "Use Proxy"; + case 306: return "(Unused)"; + case 307: return "Temporary Redirect"; + case 400: return "Bad Request"; + case 401: return "Unauthorized"; + case 402: return "Payment Required"; + case 403: return "Forbidden"; + case 404: return "Not Found"; + case 405: return "Method Not Allowed"; + case 406: return "Not Acceptable"; + case 407: return "Proxy Authentication Required"; + case 408: return "Request Timeout"; + case 409: return "Conflict"; + case 410: return "Gone"; + case 411: return "Length Required"; + case 412: return "Precondition Failed"; + case 413: return "Request Entity Too Large"; + case 414: return "Request-URI Too Long"; + case 415: return "Unsupported Media Type"; + case 416: return "Requested Range Not Satisfiable"; + case 417: return "Expectation Failed"; + case 500: return "Internal Server Error"; + case 501: return "Not Implemented"; + case 502: return "Bad Gateway"; + case 503: return "Service Unavailable"; + case 504: return "Gateway Timeout"; + case 505: return "HTTP Version Not Supported"; + default: return "NA"; + } + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/LineSeparatorConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/LineSeparatorConverter.java index bc7016210dfd85bb67f34f3dd61543ab045f5897..11f8d4681dd07c10b344405a68e8a09818095964 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/LineSeparatorConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/LineSeparatorConverter.java @@ -1,25 +1,25 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.CoreConstants; - - -public class LineSeparatorConverter extends AccessConverter { - - public String convert(AccessEvent event) { - return CoreConstants.LINE_SEPARATOR; - } -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.CoreConstants; + + +public class LineSeparatorConverter extends AccessConverter { + + public String convert(AccessEvent event) { + return CoreConstants.LINE_SEPARATOR; + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/LocalIPAddressConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/LocalIPAddressConverter.java index b2a7210f3a8063d086e4d3dc7f51378a4a65fab9..38087aadd35171e40fa79451641e835f9ad7cfa4 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/LocalIPAddressConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/LocalIPAddressConverter.java @@ -1,37 +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.access.pattern; - -import java.net.InetAddress; -import java.net.UnknownHostException; - -import ch.qos.logback.access.spi.AccessEvent; - -public class LocalIPAddressConverter extends AccessConverter { - - String localIPAddressStr; - - public LocalIPAddressConverter() { - try { - localIPAddressStr = InetAddress.getLocalHost().getHostAddress(); - } catch (UnknownHostException uhe) { - localIPAddressStr = "127.0.0.1"; - } - } - - public String convert(AccessEvent accessEvent) { - return localIPAddressStr; - } - -} +/** + * 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.access.pattern; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import ch.qos.logback.access.spi.AccessEvent; + +public class LocalIPAddressConverter extends AccessConverter { + + String localIPAddressStr; + + public LocalIPAddressConverter() { + try { + localIPAddressStr = InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException uhe) { + localIPAddressStr = "127.0.0.1"; + } + } + + public String convert(AccessEvent accessEvent) { + return localIPAddressStr; + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/LocalPortConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/LocalPortConverter.java index dcccb7cbee39295128acfd18f94ab750bf031fc1..8824253ef7d3df20054414a732c4cb3352e4272b 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/LocalPortConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/LocalPortConverter.java @@ -1,24 +1,24 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -public class LocalPortConverter extends AccessConverter { - - - public String convert(AccessEvent accessEvent) { - return Integer.toString(accessEvent.getLocalPort()); - } -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +public class LocalPortConverter extends AccessConverter { + + + public String convert(AccessEvent accessEvent) { + return Integer.toString(accessEvent.getLocalPort()); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/NAConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/NAConverter.java index 7b5e00838c63ba4070bb6b9eb9eaf58c45d4c013..1a1271629b15fe877d212b82bd89b360e8d99d1c 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/NAConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/NAConverter.java @@ -1,30 +1,30 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -/** - * Always returns the NA (not available) string which is "-" in the case - * of access conversions. - * - * @author Ceki Gülcü - */ -public class NAConverter extends AccessConverter { - - public String convert(AccessEvent accessEvent) { - return AccessEvent.NA; - } - -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +/** + * Always returns the NA (not available) string which is "-" in the case + * of access conversions. + * + * @author Ceki Gülcü + */ +public class NAConverter extends AccessConverter { + + public String convert(AccessEvent accessEvent) { + return AccessEvent.NA; + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteHostConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteHostConverter.java index 2188daf815167efbb1b88c2c39b3301f5e3a6471..368a267b040103548a78cdbb049c48cd1e580c3f 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteHostConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteHostConverter.java @@ -1,25 +1,25 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -public class RemoteHostConverter extends AccessConverter { - - - public String convert(AccessEvent accessEvent) { - return accessEvent.getRemoteHost(); - } - -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +public class RemoteHostConverter extends AccessConverter { + + + public String convert(AccessEvent accessEvent) { + return accessEvent.getRemoteHost(); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteIPAddressConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteIPAddressConverter.java index 0c4cf2bd9a3eeb412bdad5cef5f6f610936868ad..caf09db40d2d5e78534be6ff3d618d30533e6dc2 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteIPAddressConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteIPAddressConverter.java @@ -1,24 +1,24 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -public class RemoteIPAddressConverter extends AccessConverter { - - public String convert(AccessEvent accessEvent) { - return accessEvent.getRemoteAddr(); - } - -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +public class RemoteIPAddressConverter extends AccessConverter { + + public String convert(AccessEvent accessEvent) { + return accessEvent.getRemoteAddr(); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteUserConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteUserConverter.java index dde4786c31cfd7276138c5450f56433eb3c950f2..c414e26933dda19c6c169f4018d06044a5b4dfb2 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteUserConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RemoteUserConverter.java @@ -1,31 +1,31 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -public class RemoteUserConverter extends AccessConverter { - - - public String convert(AccessEvent accessEvent) { - - String user = accessEvent.getRemoteUser(); - if(user == null) { - return AccessEvent.NA; - } else { - return user; - } - } - -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +public class RemoteUserConverter extends AccessConverter { + + + public String convert(AccessEvent accessEvent) { + + String user = accessEvent.getRemoteUser(); + if(user == null) { + return AccessEvent.NA; + } else { + return user; + } + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestAttributeConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestAttributeConverter.java index 7630108a7e346afa5c922d32ea6cb99d209f377b..253e47653a017c5034ddbe17df4c052c0811441d 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestAttributeConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestAttributeConverter.java @@ -1,41 +1,41 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.util.OptionHelper; - - -public class RequestAttributeConverter extends AccessConverter { - - String key; - - public void start() { - key = getFirstOption(); - if (OptionHelper.isEmpty(key)) { - addWarn("Missing key for the request attribute"); - } else { - super.start(); - } - } - - public String convert(AccessEvent accessEvent) { - if (!isStarted()) { - return "INACTIVE_REQUEST_ATTRIB_CONV"; - } - - return accessEvent.getAttribute(key); - } - -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.util.OptionHelper; + + +public class RequestAttributeConverter extends AccessConverter { + + String key; + + public void start() { + key = getFirstOption(); + if (OptionHelper.isEmpty(key)) { + addWarn("Missing key for the request attribute"); + } else { + super.start(); + } + } + + public String convert(AccessEvent accessEvent) { + if (!isStarted()) { + return "INACTIVE_REQUEST_ATTRIB_CONV"; + } + + return accessEvent.getAttribute(key); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestContentConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestContentConverter.java index 5683973378932b8b7ac57acfa1ece6fdcdfda40e..0cecce1cc0bd79dd3d5fba3209ccfa56a94e906f 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestContentConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestContentConverter.java @@ -1,34 +1,34 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -/** - * This class is tied to the requestContent conversion word. - *

- * It has been removed from the {@link ch.qos.logback.access.PatternLayout} since - * it needs further testing before wide use. - *

- * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class RequestContentConverter extends AccessConverter { - - @Override - public String convert(AccessEvent accessEvent) { - return accessEvent.getRequestContent(); - } - -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +/** + * This class is tied to the requestContent conversion word. + *

+ * It has been removed from the {@link ch.qos.logback.access.PatternLayout} since + * it needs further testing before wide use. + *

+ * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class RequestContentConverter extends AccessConverter { + + @Override + public String convert(AccessEvent accessEvent) { + return accessEvent.getRequestContent(); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestCookieConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestCookieConverter.java index 466bebea86433ea3cf373c2500e30d6a08eaf628..18f2fd854db12f8fd8f98b55285f68e1970a3ffd 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestCookieConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestCookieConverter.java @@ -1,40 +1,40 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.util.OptionHelper; - - -public class RequestCookieConverter extends AccessConverter { - - String key; - - public void start() { - key = getFirstOption(); - if (OptionHelper.isEmpty(key)) { - addWarn("Missing key for the requested header"); - } else { - super.start(); - } - } - - public String convert(AccessEvent accessEvent) { - if (!isStarted()) { - return "INACTIVE_COOKIE_CONVERTER"; - } - - return accessEvent.getCookie(key); - } -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.util.OptionHelper; + + +public class RequestCookieConverter extends AccessConverter { + + String key; + + public void start() { + key = getFirstOption(); + if (OptionHelper.isEmpty(key)) { + addWarn("Missing key for the requested header"); + } else { + super.start(); + } + } + + public String convert(AccessEvent accessEvent) { + if (!isStarted()) { + return "INACTIVE_COOKIE_CONVERTER"; + } + + return accessEvent.getCookie(key); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestHeaderConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestHeaderConverter.java index 48695fefeb06f1bea5ad2b7dee829ec259935534..222b808b2c761bb7ad775689f93b402e552ec3dc 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestHeaderConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestHeaderConverter.java @@ -1,45 +1,45 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.util.OptionHelper; - - -public class RequestHeaderConverter extends AccessConverter { - - String key; - - public void start() { - key = getFirstOption(); - if (OptionHelper.isEmpty(key)) { - addWarn("Missing key for the requested header. Defaulting to all keys."); - key = null; - } - super.start(); - } - - public String convert(AccessEvent accessEvent) { - if(!isStarted()) { - return "INACTIVE_HEADER_CONV"; - } - - if(key != null) { - return accessEvent.getRequestHeader(key); - } else { - return accessEvent.getRequestHeaderMap().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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.util.OptionHelper; + + +public class RequestHeaderConverter extends AccessConverter { + + String key; + + public void start() { + key = getFirstOption(); + if (OptionHelper.isEmpty(key)) { + addWarn("Missing key for the requested header. Defaulting to all keys."); + key = null; + } + super.start(); + } + + public String convert(AccessEvent accessEvent) { + if(!isStarted()) { + return "INACTIVE_HEADER_CONV"; + } + + if(key != null) { + return accessEvent.getRequestHeader(key); + } else { + return accessEvent.getRequestHeaderMap().toString(); + } + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestMethodConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestMethodConverter.java index 90b863db70e42f853af65ba1ae7cd29fd05aed04..dfd77281891fd152c541ae6661d3b3caa87d3d29 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestMethodConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestMethodConverter.java @@ -1,24 +1,24 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -public class RequestMethodConverter extends AccessConverter { - - - public String convert(AccessEvent accessEvent) { - return accessEvent.getMethod(); - } -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +public class RequestMethodConverter extends AccessConverter { + + + public String convert(AccessEvent accessEvent) { + return accessEvent.getMethod(); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestParameterConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestParameterConverter.java index 491a848b16b3c4135cdc19435513d6cd452a13c0..dee1d01d91501da291cd80fb2035b1691c02a912 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestParameterConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestParameterConverter.java @@ -1,49 +1,49 @@ -/** - * 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.access.pattern; - -import java.util.Arrays; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.util.OptionHelper; - -public class RequestParameterConverter extends AccessConverter { - - String key; - - public void start() { - key = getFirstOption(); - if (OptionHelper.isEmpty(key)) { - addWarn("Missing key for the request parameter"); - } else { - super.start(); - } - } - - public String convert(AccessEvent accessEvent) { - if (!isStarted()) { - return "INACTIVE_REQUEST_PARAM_CONV"; - } - - String[] paramArray = accessEvent.getRequestParameter(key); - if (paramArray.length == 1) { - return paramArray[0]; - } else { - // for an array string {"a", "b"} named 'sa', Array.toString(sa) returns the string - // "[a, b]". - return Arrays.toString(paramArray); - } - } - -} +/** + * 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.access.pattern; + +import java.util.Arrays; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.util.OptionHelper; + +public class RequestParameterConverter extends AccessConverter { + + String key; + + public void start() { + key = getFirstOption(); + if (OptionHelper.isEmpty(key)) { + addWarn("Missing key for the request parameter"); + } else { + super.start(); + } + } + + public String convert(AccessEvent accessEvent) { + if (!isStarted()) { + return "INACTIVE_REQUEST_PARAM_CONV"; + } + + String[] paramArray = accessEvent.getRequestParameter(key); + if (paramArray.length == 1) { + return paramArray[0]; + } else { + // for an array string {"a", "b"} named 'sa', Array.toString(sa) returns the string + // "[a, b]". + return Arrays.toString(paramArray); + } + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestProtocolConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestProtocolConverter.java index 6928cbca5da10ac60659b1ae8e56837372a297c2..06c03fbc52342d7d2eecbd6fb4966c354c28916e 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestProtocolConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestProtocolConverter.java @@ -1,24 +1,24 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -public class RequestProtocolConverter extends AccessConverter { - - - public String convert(AccessEvent accessEvent) { - return accessEvent.getProtocol(); - } -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +public class RequestProtocolConverter extends AccessConverter { + + + public String convert(AccessEvent accessEvent) { + return accessEvent.getProtocol(); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestURIConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestURIConverter.java index 1af9e2cb6fd560138367185f55142acbe09a7596..2216f429a1368618ceb0513eb9f630b3b9be5365 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestURIConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestURIConverter.java @@ -1,29 +1,29 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -/** - * The request URI. - * - * @author Ceki Gülcü - */ -public class RequestURIConverter extends AccessConverter { - - public String convert(AccessEvent accessEvent) { - return accessEvent.getRequestURI(); - } - -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +/** + * The request URI. + * + * @author Ceki Gülcü + */ +public class RequestURIConverter extends AccessConverter { + + public String convert(AccessEvent accessEvent) { + return accessEvent.getRequestURI(); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestURLConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestURLConverter.java index e09e7089e3df61aed96b7cdcd7184321eae9ede0..5b035b7ae54eb4e791cc4517e1ac9e4348d82bc9 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestURLConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestURLConverter.java @@ -1,28 +1,28 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -/** - * The first line of the request. - * - * @author Ceki Gülcü - */ -public class RequestURLConverter extends AccessConverter { - - public String convert(AccessEvent accessEvent) { - return accessEvent.getRequestURL(); - } -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +/** + * The first line of the request. + * + * @author Ceki Gülcü + */ +public class RequestURLConverter extends AccessConverter { + + public String convert(AccessEvent accessEvent) { + return accessEvent.getRequestURL(); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseContentConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseContentConverter.java index 26c9da5f5e8607e47ae72d547c2c8ebd1da9441c..9e0d6e784951d37a1866b4fb9779e08aa79f6a59 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseContentConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseContentConverter.java @@ -1,34 +1,34 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -/** - * This class is tied to the requestContent conversion word. - *

- * It has been removed from the {@link ch.qos.logback.access.PatternLayout} since - * it needs further testing before wide use. - *

- * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class ResponseContentConverter extends AccessConverter { - - @Override - public String convert(AccessEvent accessEvent) { - return accessEvent.getResponseContent(); - } - -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +/** + * This class is tied to the requestContent conversion word. + *

+ * It has been removed from the {@link ch.qos.logback.access.PatternLayout} since + * it needs further testing before wide use. + *

+ * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class ResponseContentConverter extends AccessConverter { + + @Override + public String convert(AccessEvent accessEvent) { + return accessEvent.getResponseContent(); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseHeaderConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseHeaderConverter.java index 5bfb581ba779a487e3d0a13ad42730a52494a3d5..5ebd3693d4b5d3e68ab48fbb8f01676946a996ea 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseHeaderConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseHeaderConverter.java @@ -1,51 +1,51 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.util.OptionHelper; - - -public class ResponseHeaderConverter extends AccessConverter { - - String key; - - public void start() { - key = getFirstOption(); - if (OptionHelper.isEmpty(key)) { - addWarn("Missing key for the response header"); - } else { - super.start(); - } - } - - public String convert(AccessEvent accessEvent) { - if(!isStarted()) { - return "INACTIVE_REPONSE_HEADER_CONV"; - } - - return accessEvent.getResponseHeader(key); - //return null; - -// HttpServletResponse response = accessEvent.getHttpResponse(); -// -// Object value = null; // = response.getHeader(key); -// if (value == null) { -// return AccessConverter.NA; -// } else { -// return value.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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.util.OptionHelper; + + +public class ResponseHeaderConverter extends AccessConverter { + + String key; + + public void start() { + key = getFirstOption(); + if (OptionHelper.isEmpty(key)) { + addWarn("Missing key for the response header"); + } else { + super.start(); + } + } + + public String convert(AccessEvent accessEvent) { + if(!isStarted()) { + return "INACTIVE_REPONSE_HEADER_CONV"; + } + + return accessEvent.getResponseHeader(key); + //return null; + +// HttpServletResponse response = accessEvent.getHttpResponse(); +// +// Object value = null; // = response.getHeader(key); +// if (value == null) { +// return AccessConverter.NA; +// } else { +// return value.toString(); +// } + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/ServerNameConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/ServerNameConverter.java index 5f5f277b0f0aff160db5464df4d6beaa60eabc36..33e1d2c41986e6dd45b92988fe210ab71a480830 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/ServerNameConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/ServerNameConverter.java @@ -1,23 +1,23 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -public class ServerNameConverter extends AccessConverter { - - public String convert(AccessEvent accessEvent) { - return accessEvent.getServerName(); - } -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +public class ServerNameConverter extends AccessConverter { + + public String convert(AccessEvent accessEvent) { + return accessEvent.getServerName(); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/StatusCodeConverter.java b/logback-access/src/main/java/ch/qos/logback/access/pattern/StatusCodeConverter.java index 911ad1b6a455e49642b15bd74d0f5f012fa04c9e..52780028cfe3922d59ea568781d33070e329175d 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/StatusCodeConverter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/StatusCodeConverter.java @@ -1,24 +1,24 @@ -/** - * 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.access.pattern; - -import ch.qos.logback.access.spi.AccessEvent; - -public class StatusCodeConverter extends AccessConverter { - - public String convert(AccessEvent accessEvent) { - return Integer.toString(accessEvent.getStatusCode()); - } - -} +/** + * 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.access.pattern; + +import ch.qos.logback.access.spi.AccessEvent; + +public class StatusCodeConverter extends AccessConverter { + + public String convert(AccessEvent accessEvent) { + return Integer.toString(accessEvent.getStatusCode()); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/pattern/package.html b/logback-access/src/main/java/ch/qos/logback/access/pattern/package.html index de3614cbbe629d846d519d4a769b274f78eb9756..5e4898f941f7b16f49aadc822f2f45730b4cc757 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/pattern/package.html +++ b/logback-access/src/main/java/ch/qos/logback/access/pattern/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Provides classes implementing format specifiers in conversion patterns.

- - + + + + + + + + + +

Provides classes implementing format specifiers in conversion patterns.

+ + \ No newline at end of file diff --git a/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeFilter.java b/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeFilter.java index bfae35ef77adf15d7a3a16e06296c905535fd8ad..346940386b37157cc6f593cb0c50511336121f9a 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeFilter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeFilter.java @@ -1,71 +1,71 @@ -/** - * 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.access.servlet; - -import java.io.IOException; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import ch.qos.logback.access.AccessConstants; - -public class TeeFilter implements Filter { - - public void destroy() { - // NOP - } - - public void doFilter(ServletRequest request, ServletResponse response, - FilterChain filterChain) throws IOException, ServletException { - - if (request instanceof HttpServletRequest) { - try { - TeeHttpServletRequest teeRequest = new TeeHttpServletRequest( - (HttpServletRequest) request); - TeeHttpServletResponse teeResponse = new TeeHttpServletResponse( - (HttpServletResponse) response); - - //System.out.println("BEFORE TeeFilter. filterChain.doFilter()"); - filterChain.doFilter(teeRequest, teeResponse); - //System.out.println("AFTER TeeFilter. filterChain.doFilter()"); - - teeResponse.finish(); - // let the output contents be available for later use by - // logback-access-logging - teeRequest.setAttribute(AccessConstants.LB_OUTPUT_BUFFER, teeResponse - .getOutputBuffer()); - } catch (IOException e) { - e.printStackTrace(); - throw e; - } catch (ServletException e) { - e.printStackTrace(); - throw e; - } - } else { - filterChain.doFilter(request, response); - } - - } - - public void init(FilterConfig arg0) throws ServletException { - // NOP - } - -} +/** + * 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.access.servlet; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import ch.qos.logback.access.AccessConstants; + +public class TeeFilter implements Filter { + + public void destroy() { + // NOP + } + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain filterChain) throws IOException, ServletException { + + if (request instanceof HttpServletRequest) { + try { + TeeHttpServletRequest teeRequest = new TeeHttpServletRequest( + (HttpServletRequest) request); + TeeHttpServletResponse teeResponse = new TeeHttpServletResponse( + (HttpServletResponse) response); + + //System.out.println("BEFORE TeeFilter. filterChain.doFilter()"); + filterChain.doFilter(teeRequest, teeResponse); + //System.out.println("AFTER TeeFilter. filterChain.doFilter()"); + + teeResponse.finish(); + // let the output contents be available for later use by + // logback-access-logging + teeRequest.setAttribute(AccessConstants.LB_OUTPUT_BUFFER, teeResponse + .getOutputBuffer()); + } catch (IOException e) { + e.printStackTrace(); + throw e; + } catch (ServletException e) { + e.printStackTrace(); + throw e; + } + } else { + filterChain.doFilter(request, response); + } + + } + + public void init(FilterConfig arg0) throws ServletException { + // NOP + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeHttpServletRequest.java b/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeHttpServletRequest.java index 414c0c329bbecccfdaae84da3c9ed2b75e7c59a2..0868045f805f85402ddc5562f5ab6dee351087ac 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeHttpServletRequest.java +++ b/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeHttpServletRequest.java @@ -1,82 +1,82 @@ -/** - * 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.access.servlet; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; - -import ch.qos.logback.access.AccessConstants; - -/** - * As the "tee" program on Unix, duplicate the request's input stream. - * - * @author Ceki Gülcü - */ -class TeeHttpServletRequest extends HttpServletRequestWrapper { - - private TeeServletInputStream inStream; - private BufferedReader reader; - boolean postedParametersMode = false; - - TeeHttpServletRequest(HttpServletRequest request) { - super(request); - if (Util.isFormUrlEncoded(request)) { - postedParametersMode = true; - } else { - inStream = new TeeServletInputStream(request); - // add the contents of the input buffer as an attribute of the request - request - .setAttribute(AccessConstants.LB_INPUT_BUFFER, inStream.getInputBuffer()); - reader = new BufferedReader(new InputStreamReader(inStream)); - } - - } - - byte[] getInputBuffer() { - if (postedParametersMode) { - throw new IllegalStateException("Call disallowed in postedParametersMode"); - } - return inStream.getInputBuffer(); - } - - @Override - public ServletInputStream getInputStream() throws IOException { - if (!postedParametersMode) { - return inStream; - } else { - return super.getInputStream(); - } - } - - // - - @Override - public BufferedReader getReader() throws IOException { - if (!postedParametersMode) { - return reader; - } else { - return super.getReader(); - } - } - - public boolean isPostedParametersMode() { - return postedParametersMode; - } - -} +/** + * 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.access.servlet; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +import ch.qos.logback.access.AccessConstants; + +/** + * As the "tee" program on Unix, duplicate the request's input stream. + * + * @author Ceki Gülcü + */ +class TeeHttpServletRequest extends HttpServletRequestWrapper { + + private TeeServletInputStream inStream; + private BufferedReader reader; + boolean postedParametersMode = false; + + TeeHttpServletRequest(HttpServletRequest request) { + super(request); + if (Util.isFormUrlEncoded(request)) { + postedParametersMode = true; + } else { + inStream = new TeeServletInputStream(request); + // add the contents of the input buffer as an attribute of the request + request + .setAttribute(AccessConstants.LB_INPUT_BUFFER, inStream.getInputBuffer()); + reader = new BufferedReader(new InputStreamReader(inStream)); + } + + } + + byte[] getInputBuffer() { + if (postedParametersMode) { + throw new IllegalStateException("Call disallowed in postedParametersMode"); + } + return inStream.getInputBuffer(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + if (!postedParametersMode) { + return inStream; + } else { + return super.getInputStream(); + } + } + + // + + @Override + public BufferedReader getReader() throws IOException { + if (!postedParametersMode) { + return reader; + } else { + return super.getReader(); + } + } + + public boolean isPostedParametersMode() { + return postedParametersMode; + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeHttpServletResponse.java b/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeHttpServletResponse.java index ffe88bd6e1aa19278269e4a1bc5d1ff26a2c46e0..8ea99f03f2c45c158d606e80cf415a826b5b9e56 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeHttpServletResponse.java +++ b/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeHttpServletResponse.java @@ -1,75 +1,75 @@ -/** - * 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.access.servlet; - -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; - -public class TeeHttpServletResponse extends HttpServletResponseWrapper { - - TeeServletOutputStream teeServletOutputStream; - PrintWriter teeWriter; - - public TeeHttpServletResponse(HttpServletResponse httpServletResponse) { - super(httpServletResponse); - } - - @Override - public ServletOutputStream getOutputStream() throws IOException { - if (teeServletOutputStream == null) { - teeServletOutputStream = new TeeServletOutputStream(this.getResponse()); - } - return teeServletOutputStream; - } - - @Override - public PrintWriter getWriter() throws IOException { - if (this.teeWriter == null) { - this.teeWriter = new PrintWriter(new OutputStreamWriter(getOutputStream()), - true); - } - return this.teeWriter; - } - - @Override - public void flushBuffer() { - if (this.teeWriter != null) { - this.teeWriter.flush(); - } - } - - byte[] getOutputBuffer() { - // teeServletOutputStream can be null if the getOutputStream method is never - // called. - if (teeServletOutputStream != null) { - return teeServletOutputStream.getOutputStreamAsByteArray(); - } else { - return null; - } - } - - void finish() throws IOException { - if (this.teeWriter != null) { - this.teeWriter.close(); - } - if (this.teeServletOutputStream != null) { - this.teeServletOutputStream.close(); - } - } -} +/** + * 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.access.servlet; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +public class TeeHttpServletResponse extends HttpServletResponseWrapper { + + TeeServletOutputStream teeServletOutputStream; + PrintWriter teeWriter; + + public TeeHttpServletResponse(HttpServletResponse httpServletResponse) { + super(httpServletResponse); + } + + @Override + public ServletOutputStream getOutputStream() throws IOException { + if (teeServletOutputStream == null) { + teeServletOutputStream = new TeeServletOutputStream(this.getResponse()); + } + return teeServletOutputStream; + } + + @Override + public PrintWriter getWriter() throws IOException { + if (this.teeWriter == null) { + this.teeWriter = new PrintWriter(new OutputStreamWriter(getOutputStream()), + true); + } + return this.teeWriter; + } + + @Override + public void flushBuffer() { + if (this.teeWriter != null) { + this.teeWriter.flush(); + } + } + + byte[] getOutputBuffer() { + // teeServletOutputStream can be null if the getOutputStream method is never + // called. + if (teeServletOutputStream != null) { + return teeServletOutputStream.getOutputStreamAsByteArray(); + } else { + return null; + } + } + + void finish() throws IOException { + if (this.teeWriter != null) { + this.teeWriter.close(); + } + if (this.teeServletOutputStream != null) { + this.teeServletOutputStream.close(); + } + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeServletInputStream.java b/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeServletInputStream.java index ec586b72566c86438262eeffa0a194ca3f1ccfc6..25a9b623583bddeb4f6dde623f856bf49ee1c695 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeServletInputStream.java +++ b/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeServletInputStream.java @@ -1,59 +1,59 @@ -/** - * 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.access.servlet; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; - -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; - -class TeeServletInputStream extends ServletInputStream { - - InputStream in; - byte[] inputBuffer; - - TeeServletInputStream(HttpServletRequest request) { - duplicateInputStream(request); - } - - @Override - public int read() throws IOException { - //System.out.println("zzzzzzzzzz TeeServletInputStream.read called"); - return in.read(); - } - - private void duplicateInputStream(HttpServletRequest request) { - try { - int len = request.getContentLength(); - ServletInputStream originalSIS = request.getInputStream(); - if (len < 0) { - in = originalSIS; - } else { - inputBuffer = new byte[len]; - int n = originalSIS.read(inputBuffer, 0, len); - assert n == len; - this.in = new ByteArrayInputStream(inputBuffer); - originalSIS.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - byte[] getInputBuffer() { - return inputBuffer; - } -} +/** + * 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.access.servlet; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; + +class TeeServletInputStream extends ServletInputStream { + + InputStream in; + byte[] inputBuffer; + + TeeServletInputStream(HttpServletRequest request) { + duplicateInputStream(request); + } + + @Override + public int read() throws IOException { + //System.out.println("zzzzzzzzzz TeeServletInputStream.read called"); + return in.read(); + } + + private void duplicateInputStream(HttpServletRequest request) { + try { + int len = request.getContentLength(); + ServletInputStream originalSIS = request.getInputStream(); + if (len < 0) { + in = originalSIS; + } else { + inputBuffer = new byte[len]; + int n = originalSIS.read(inputBuffer, 0, len); + assert n == len; + this.in = new ByteArrayInputStream(inputBuffer); + originalSIS.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + byte[] getInputBuffer() { + return inputBuffer; + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeServletOutputStream.java b/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeServletOutputStream.java index a707592f887a107dc6fc1675a9c61fdc3c0ba066..6e8e5035aaa6bab83487aee355da0363fee2e2fc 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeServletOutputStream.java +++ b/logback-access/src/main/java/ch/qos/logback/access/servlet/TeeServletOutputStream.java @@ -1,88 +1,88 @@ -/** - * 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.access.servlet; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.ServletResponse; - -public class TeeServletOutputStream extends ServletOutputStream { - - final ServletOutputStream underlyingStream; - final ByteArrayOutputStream baosCopy; - - TeeServletOutputStream(ServletResponse httpServletResponse) - throws IOException { - // System.out.println("TeeServletOutputStream.constructor() called"); - this.underlyingStream = httpServletResponse.getOutputStream(); - baosCopy = new ByteArrayOutputStream(); - } - - byte[] getOutputStreamAsByteArray() { - return baosCopy.toByteArray(); - } - - @Override - public void write(int val) throws IOException { - if (underlyingStream != null) { - underlyingStream.write(val); - baosCopy.write(val); - } - } - - @Override - public void write(byte[] byteArray) throws IOException { - if (underlyingStream == null) { - return; - } - // System.out.println("WRITE TeeServletOutputStream.write(byte[]) called"); - write(byteArray, 0, byteArray.length); - } - - @Override - public void write(byte byteArray[], int offset, int length) - throws IOException { - if (underlyingStream == null) { - return; - } - // System.out.println("WRITE TeeServletOutputStream.write(byte[], int, int) - // called"); - // System.out.println(new String(byteArray, offset, length)); - underlyingStream.write(byteArray, offset, length); - baosCopy.write(byteArray, offset, length); - } - - @Override - public void close() throws IOException { - // System.out.println("CLOSE TeeServletOutputStream.close() called"); - - // If the servlet accessing the stream is using a writer instead of - // an OutputStream, it will probably call os.close() before calling - // writer.close. Thus, the underlying output stream will be called - // before the data sent to the writer could be flushed. - } - - - @Override - public void flush() throws IOException { - if (underlyingStream == null) { - return; - } - // System.out.println("FLUSH TeeServletOutputStream.flush() called"); - underlyingStream.flush(); - baosCopy.flush(); - } -} +/** + * 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.access.servlet; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletResponse; + +public class TeeServletOutputStream extends ServletOutputStream { + + final ServletOutputStream underlyingStream; + final ByteArrayOutputStream baosCopy; + + TeeServletOutputStream(ServletResponse httpServletResponse) + throws IOException { + // System.out.println("TeeServletOutputStream.constructor() called"); + this.underlyingStream = httpServletResponse.getOutputStream(); + baosCopy = new ByteArrayOutputStream(); + } + + byte[] getOutputStreamAsByteArray() { + return baosCopy.toByteArray(); + } + + @Override + public void write(int val) throws IOException { + if (underlyingStream != null) { + underlyingStream.write(val); + baosCopy.write(val); + } + } + + @Override + public void write(byte[] byteArray) throws IOException { + if (underlyingStream == null) { + return; + } + // System.out.println("WRITE TeeServletOutputStream.write(byte[]) called"); + write(byteArray, 0, byteArray.length); + } + + @Override + public void write(byte byteArray[], int offset, int length) + throws IOException { + if (underlyingStream == null) { + return; + } + // System.out.println("WRITE TeeServletOutputStream.write(byte[], int, int) + // called"); + // System.out.println(new String(byteArray, offset, length)); + underlyingStream.write(byteArray, offset, length); + baosCopy.write(byteArray, offset, length); + } + + @Override + public void close() throws IOException { + // System.out.println("CLOSE TeeServletOutputStream.close() called"); + + // If the servlet accessing the stream is using a writer instead of + // an OutputStream, it will probably call os.close() before calling + // writer.close. Thus, the underlying output stream will be called + // before the data sent to the writer could be flushed. + } + + + @Override + public void flush() throws IOException { + if (underlyingStream == null) { + return; + } + // System.out.println("FLUSH TeeServletOutputStream.flush() called"); + underlyingStream.flush(); + baosCopy.flush(); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/servlet/Util.java b/logback-access/src/main/java/ch/qos/logback/access/servlet/Util.java index d04693a9eea758e3cf696c28bcc118c95583670e..bcdde15a722ffdacc6332a0797842a5b240b1a71 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/servlet/Util.java +++ b/logback-access/src/main/java/ch/qos/logback/access/servlet/Util.java @@ -1,42 +1,42 @@ -/** - * 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.access.servlet; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import ch.qos.logback.access.AccessConstants; - -public class Util { - - public static boolean isFormUrlEncoded(HttpServletRequest request) { - if ("POST".equals(request.getMethod()) - && AccessConstants.X_WWW_FORM_URLECODED.equals(request.getContentType())) { - return true; - } else { - return false; - } - } - - public static boolean isImageResponse(HttpServletResponse response) { - - String responseType = response.getContentType(); - - if (responseType != null && responseType.startsWith(AccessConstants.IMAGE_CONTENT_TYPE)) { - return true; - } else { - return false; - } - } -} +/** + * 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.access.servlet; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import ch.qos.logback.access.AccessConstants; + +public class Util { + + public static boolean isFormUrlEncoded(HttpServletRequest request) { + if ("POST".equals(request.getMethod()) + && AccessConstants.X_WWW_FORM_URLECODED.equals(request.getContentType())) { + return true; + } else { + return false; + } + } + + public static boolean isImageResponse(HttpServletResponse response) { + + String responseType = response.getContentType(); + + if (responseType != null && responseType.startsWith(AccessConstants.IMAGE_CONTENT_TYPE)) { + return true; + } else { + return false; + } + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java b/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java index 6d3733bb10ef724e575c9e4c059fe8b7be1a2fdd..610847241874377e7c3ad9183297b70b40be3696 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java +++ b/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java @@ -1,201 +1,201 @@ -/** - * 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.access.sift; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.sift.Discriminator; -import ch.qos.logback.core.spi.ContextAwareBase; - -/** - * - * AccessEventDiscriminator's job is to return the value of a designated field - * in an {@link AccessEvent} instance. - * - *

The field is specified via the {@link FieldName} property. - * - * @author Ceki Gülcü - * - */ -public class AccessEventDiscriminator extends ContextAwareBase implements - Discriminator { - - boolean started = false; - - /** - * At present time the followed fields can be designated: COOKIE, - * REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, - * LOCAL_PORT,REQUEST_URI - * - *

The first three fields require an additional key. For the - * SESSION_ATTRIBUTE field, the additional key named "id" has special meaning - * as it is mapped to the session id of the current http request. - */ - public enum FieldName { - COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, LOCAL_PORT, REQUEST_URI - } - - String defaultValue; - String key; - FieldName fieldName; - String additionalKey; - - public String getDiscriminatingValue(AccessEvent acccessEvent) { - String rawValue = getRawDiscriminatingValue(acccessEvent); - if (rawValue == null || rawValue.length() == 0) { - return defaultValue; - } else { - return rawValue; - } - } - - public String getRawDiscriminatingValue(AccessEvent acccessEvent) { - switch (fieldName) { - case COOKIE: - // tested - return acccessEvent.getCookie(additionalKey); - case LOCAL_PORT: - return String.valueOf(acccessEvent.getLocalPort()); - case REQUEST_ATTRIBUTE: - // tested - return getRequestAttribute(acccessEvent); - case SESSION_ATTRIBUTE: - return getSessionAttribute(acccessEvent); - case REMOTE_ADDRESS: - return acccessEvent.getRemoteAddr(); - case REQUEST_URI: - // tested - return getRequestURI(acccessEvent); - default: - return null; - } - } - - private String getRequestAttribute(AccessEvent acccessEvent) { - String attr = acccessEvent.getAttribute(additionalKey); - if (AccessEvent.NA.equals(attr)) { - return null; - } else { - return attr; - } - } - - private String getRequestURI(AccessEvent acccessEvent) { - String uri = acccessEvent.getRequestURI(); - if (uri != null && uri.length() >= 1 && uri.charAt(0) == '/') { - return uri.substring(1); - } else { - return uri; - } - } - - private String getSessionAttribute(AccessEvent acccessEvent) { - HttpServletRequest req = acccessEvent.getRequest(); - if (req != null) { - HttpSession session = req.getSession(false); - if (session != null) { - if ("id".equalsIgnoreCase(additionalKey)) { - return session.getId(); - } else { - Object v = session.getAttribute(additionalKey); - if (v != null) { - return v.toString(); - } - } - } - } - return null; - } - - public boolean isStarted() { - return started; - } - - public void start() { - - int errorCount = 0; - - if (defaultValue == null) { - addError("\"DefaultValue\" property must be set."); - } - if (fieldName == null) { - addError("\"FieldName\" property must be set."); - errorCount++; - } - - switch (fieldName) { - case SESSION_ATTRIBUTE: - case REQUEST_ATTRIBUTE: - case COOKIE: - if (additionalKey == null) { - addError("\"OptionalKey\" property is mandatory for field name " - + fieldName.toString()); - errorCount++; - } - } - - if (errorCount == 0) { - started = true; - } - } - - public void stop() { - started = false; - } - - public void setFieldName(FieldName fieldName) { - this.fieldName = fieldName; - } - - public FieldName getFieldName() { - return fieldName; - } - - public String getAdditionalKey() { - return additionalKey; - } - - public void setAdditionalKey(String additionalKey) { - this.additionalKey = additionalKey; - } - - /** - * @see #setDefaultValue(String) - * @return - */ - public String getDefaultValue() { - return defaultValue; - } - - /** - * The default value returned by this discriminator in case it cannot compute - * the discriminating value from the access event. - * - * @param defaultValue - */ - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - -} +/** + * 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.access.sift; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.sift.Discriminator; +import ch.qos.logback.core.spi.ContextAwareBase; + +/** + * + * AccessEventDiscriminator's job is to return the value of a designated field + * in an {@link AccessEvent} instance. + * + *

The field is specified via the {@link FieldName} property. + * + * @author Ceki Gülcü + * + */ +public class AccessEventDiscriminator extends ContextAwareBase implements + Discriminator { + + boolean started = false; + + /** + * At present time the followed fields can be designated: COOKIE, + * REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, + * LOCAL_PORT,REQUEST_URI + * + *

The first three fields require an additional key. For the + * SESSION_ATTRIBUTE field, the additional key named "id" has special meaning + * as it is mapped to the session id of the current http request. + */ + public enum FieldName { + COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, LOCAL_PORT, REQUEST_URI + } + + String defaultValue; + String key; + FieldName fieldName; + String additionalKey; + + public String getDiscriminatingValue(AccessEvent acccessEvent) { + String rawValue = getRawDiscriminatingValue(acccessEvent); + if (rawValue == null || rawValue.length() == 0) { + return defaultValue; + } else { + return rawValue; + } + } + + public String getRawDiscriminatingValue(AccessEvent acccessEvent) { + switch (fieldName) { + case COOKIE: + // tested + return acccessEvent.getCookie(additionalKey); + case LOCAL_PORT: + return String.valueOf(acccessEvent.getLocalPort()); + case REQUEST_ATTRIBUTE: + // tested + return getRequestAttribute(acccessEvent); + case SESSION_ATTRIBUTE: + return getSessionAttribute(acccessEvent); + case REMOTE_ADDRESS: + return acccessEvent.getRemoteAddr(); + case REQUEST_URI: + // tested + return getRequestURI(acccessEvent); + default: + return null; + } + } + + private String getRequestAttribute(AccessEvent acccessEvent) { + String attr = acccessEvent.getAttribute(additionalKey); + if (AccessEvent.NA.equals(attr)) { + return null; + } else { + return attr; + } + } + + private String getRequestURI(AccessEvent acccessEvent) { + String uri = acccessEvent.getRequestURI(); + if (uri != null && uri.length() >= 1 && uri.charAt(0) == '/') { + return uri.substring(1); + } else { + return uri; + } + } + + private String getSessionAttribute(AccessEvent acccessEvent) { + HttpServletRequest req = acccessEvent.getRequest(); + if (req != null) { + HttpSession session = req.getSession(false); + if (session != null) { + if ("id".equalsIgnoreCase(additionalKey)) { + return session.getId(); + } else { + Object v = session.getAttribute(additionalKey); + if (v != null) { + return v.toString(); + } + } + } + } + return null; + } + + public boolean isStarted() { + return started; + } + + public void start() { + + int errorCount = 0; + + if (defaultValue == null) { + addError("\"DefaultValue\" property must be set."); + } + if (fieldName == null) { + addError("\"FieldName\" property must be set."); + errorCount++; + } + + switch (fieldName) { + case SESSION_ATTRIBUTE: + case REQUEST_ATTRIBUTE: + case COOKIE: + if (additionalKey == null) { + addError("\"OptionalKey\" property is mandatory for field name " + + fieldName.toString()); + errorCount++; + } + } + + if (errorCount == 0) { + started = true; + } + } + + public void stop() { + started = false; + } + + public void setFieldName(FieldName fieldName) { + this.fieldName = fieldName; + } + + public FieldName getFieldName() { + return fieldName; + } + + public String getAdditionalKey() { + return additionalKey; + } + + public void setAdditionalKey(String additionalKey) { + this.additionalKey = additionalKey; + } + + /** + * @see #setDefaultValue(String) + * @return + */ + public String getDefaultValue() { + return defaultValue; + } + + /** + * The default value returned by this discriminator in case it cannot compute + * the discriminating value from the access event. + * + * @param defaultValue + */ + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/sift/AppenderFactory.java b/logback-access/src/main/java/ch/qos/logback/access/sift/AppenderFactory.java index 3b264669b21e274e4476376a48ac5e2f58aaa9d1..62c2ff3fc70d13993117e98d39162e302a19c151 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/sift/AppenderFactory.java +++ b/logback-access/src/main/java/ch/qos/logback/access/sift/AppenderFactory.java @@ -1,37 +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.access.sift; - -import java.util.List; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.sift.AppenderFactoryBase; -import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase; - -public class AppenderFactory extends AppenderFactoryBase { - - String keyName; - - AppenderFactory(List eventList, String keyName) { - super(eventList); - this.keyName = keyName; - } - - public SiftingJoranConfiguratorBase getSiftingJoranConfigurator( - String keyValue) { - return new SiftingJoranConfigurator(keyName, keyValue); - } - -} +/** + * 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.access.sift; + +import java.util.List; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.sift.AppenderFactoryBase; +import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase; + +public class AppenderFactory extends AppenderFactoryBase { + + String keyName; + + AppenderFactory(List eventList, String keyName) { + super(eventList); + this.keyName = keyName; + } + + public SiftingJoranConfiguratorBase getSiftingJoranConfigurator( + String keyValue) { + return new SiftingJoranConfigurator(keyName, keyValue); + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java b/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java index 5f0dbd2ccd5a0049f123069f7ddab604f5836315..a5735ddc94712be20fd1a627da962dfc4c28afc8 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java +++ b/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java @@ -1,59 +1,59 @@ -/** - * 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.access.sift; - -import java.util.ArrayList; -import java.util.List; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.event.InPlayListener; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; - -public class SiftAction extends Action implements InPlayListener { - List seList; - - @Override - public void begin(InterpretationContext ec, String name, Attributes attributes) - throws ActionException { - seList = new ArrayList(); - ec.addInPlayListener(this); - } - - @Override - public void end(InterpretationContext ec, String name) throws ActionException { - ec.removeInPlayListener(this); - Object o = ec.peekObject(); - if (o instanceof SiftingAppender) { - SiftingAppender siftingAppender = (SiftingAppender) o; - AppenderFactory appenderFactory = new AppenderFactory(seList, siftingAppender.getDiscriminatorKey()); - siftingAppender.setAppenderFactory(appenderFactory); - } - } - - public void inPlay(SaxEvent event) { - seList.add(event); - } - - public List getSeList() { - return seList; - } - - - - -} +/** + * 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.access.sift; + +import java.util.ArrayList; +import java.util.List; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.event.InPlayListener; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; + +public class SiftAction extends Action implements InPlayListener { + List seList; + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + seList = new ArrayList(); + ec.addInPlayListener(this); + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + ec.removeInPlayListener(this); + Object o = ec.peekObject(); + if (o instanceof SiftingAppender) { + SiftingAppender siftingAppender = (SiftingAppender) o; + AppenderFactory appenderFactory = new AppenderFactory(seList, siftingAppender.getDiscriminatorKey()); + siftingAppender.setAppenderFactory(appenderFactory); + } + } + + public void inPlay(SaxEvent event) { + seList.add(event); + } + + public List getSeList() { + return seList; + } + + + + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java b/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java index 72d924d6300d84cd13273a4285039897b0299774..49b909ac3ee70aa4547e47ea1d2235380947e34f 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java +++ b/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java @@ -1,53 +1,53 @@ -/** - * 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.access.sift; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.joran.spi.DefaultClass; -import ch.qos.logback.core.sift.AppenderTracker; -import ch.qos.logback.core.sift.Discriminator; -import ch.qos.logback.core.sift.SiftingAppenderBase; - -/** - * This appender can contains other appenders which it can build dynamically - * depending on MDC values. The built appender is specified as part of a - * configuration file. - * - *

See the logback manual for further details. - * - * - * @author Ceki Gulcu - */ -public class SiftingAppender extends SiftingAppenderBase { - - @Override - public void start() { - super.start(); - } - - AppenderTracker getAppenderTracker() { - return appenderTracker; - } - - @Override - protected long getTimestamp(AccessEvent event) { - return event.getTimeStamp(); - } - - @Override - @DefaultClass(AccessEventDiscriminator.class) - public void setDiscriminator(Discriminator discriminator) { - super.setDiscriminator(discriminator); - } -} +/** + * 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.access.sift; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.joran.spi.DefaultClass; +import ch.qos.logback.core.sift.AppenderTracker; +import ch.qos.logback.core.sift.Discriminator; +import ch.qos.logback.core.sift.SiftingAppenderBase; + +/** + * This appender can contains other appenders which it can build dynamically + * depending on MDC values. The built appender is specified as part of a + * configuration file. + * + *

See the logback manual for further details. + * + * + * @author Ceki Gulcu + */ +public class SiftingAppender extends SiftingAppenderBase { + + @Override + public void start() { + super.start(); + } + + AppenderTracker getAppenderTracker() { + return appenderTracker; + } + + @Override + protected long getTimestamp(AccessEvent event) { + return event.getTimeStamp(); + } + + @Override + @DefaultClass(AccessEventDiscriminator.class) + public void setDiscriminator(Discriminator discriminator) { + super.setDiscriminator(discriminator); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingJoranConfigurator.java b/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingJoranConfigurator.java index ae70acb12d69fe60fc8896cea15604d12648651d..0e0ca006843ab987b27f8adb7813fa50b1a6d15a 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingJoranConfigurator.java +++ b/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingJoranConfigurator.java @@ -1,66 +1,66 @@ -/** - * 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.access.sift; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.joran.action.ActionConst; -import ch.qos.logback.core.joran.action.AppenderAction; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.joran.spi.RuleStore; -import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase; - -public class SiftingJoranConfigurator extends SiftingJoranConfiguratorBase { - - String key; - String value; - - SiftingJoranConfigurator(String key, String value) { - this.key = key; - this.value = value; - } - - @Override - protected Pattern initialPattern() { - return new Pattern("configuration"); - } - - @Override - protected void addInstanceRules(RuleStore rs) { - rs.addRule(new Pattern("configuration/appender"), new AppenderAction()); - } - - @Override - protected void buildInterpreter() { - super.buildInterpreter(); - Map omap = interpreter.getInterpretationContext().getObjectMap(); - omap.put(ActionConst.APPENDER_BAG, new HashMap()); - omap.put(ActionConst.FILTER_CHAIN_BAG, new HashMap()); - Map propertiesMap = new HashMap(); - propertiesMap.put(key, value); - interpreter.setInterpretationContextPropertiesMap(propertiesMap); - } - - @SuppressWarnings("unchecked") - public Appender getAppender() { - Map omap = interpreter.getInterpretationContext().getObjectMap(); - HashMap map = (HashMap) omap.get(ActionConst.APPENDER_BAG); - Collection values = map.values(); - return (Appender) values.iterator().next(); - } -} +/** + * 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.access.sift; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.joran.action.ActionConst; +import ch.qos.logback.core.joran.action.AppenderAction; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.joran.spi.RuleStore; +import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase; + +public class SiftingJoranConfigurator extends SiftingJoranConfiguratorBase { + + String key; + String value; + + SiftingJoranConfigurator(String key, String value) { + this.key = key; + this.value = value; + } + + @Override + protected Pattern initialPattern() { + return new Pattern("configuration"); + } + + @Override + protected void addInstanceRules(RuleStore rs) { + rs.addRule(new Pattern("configuration/appender"), new AppenderAction()); + } + + @Override + protected void buildInterpreter() { + super.buildInterpreter(); + Map omap = interpreter.getInterpretationContext().getObjectMap(); + omap.put(ActionConst.APPENDER_BAG, new HashMap()); + omap.put(ActionConst.FILTER_CHAIN_BAG, new HashMap()); + Map propertiesMap = new HashMap(); + propertiesMap.put(key, value); + interpreter.setInterpretationContextPropertiesMap(propertiesMap); + } + + @SuppressWarnings("unchecked") + public Appender getAppender() { + Map omap = interpreter.getInterpretationContext().getObjectMap(); + HashMap map = (HashMap) omap.get(ActionConst.APPENDER_BAG); + Collection values = map.values(); + return (Appender) values.iterator().next(); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/spi/AccessContext.java b/logback-access/src/main/java/ch/qos/logback/access/spi/AccessContext.java index c8c6d0867172b23d8908cb92126e8f99e76471e0..2c55c6e5d4b1e9332706671b0cd14f4e1a8e2332 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/spi/AccessContext.java +++ b/logback-access/src/main/java/ch/qos/logback/access/spi/AccessContext.java @@ -1,91 +1,91 @@ -/** - * 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.access.spi; - -import java.util.Iterator; -import java.util.List; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.filter.Filter; -import ch.qos.logback.core.spi.AppenderAttachable; -import ch.qos.logback.core.spi.AppenderAttachableImpl; -import ch.qos.logback.core.spi.FilterAttachable; -import ch.qos.logback.core.spi.FilterAttachableImpl; -import ch.qos.logback.core.spi.FilterReply; - -/** - * A minimal context implementation used by certain logback-access components, - * mainly SocketServer. - * - * @author Sébastien Pennec - */ -public class AccessContext extends ContextBase implements - AppenderAttachable, FilterAttachable { - - AppenderAttachableImpl aai = new AppenderAttachableImpl(); - FilterAttachableImpl fai = new FilterAttachableImpl(); - - public void callAppenders(AccessEvent event) { - aai.appendLoopOnAppenders(event); - } - - public void addAppender(Appender newAppender) { - aai.addAppender(newAppender); - } - - public void detachAndStopAllAppenders() { - aai.detachAndStopAllAppenders(); - } - - public boolean detachAppender(Appender appender) { - return aai.detachAppender(appender); - } - - public boolean detachAppender(String name) { - return aai.detachAppender(name); - } - - public Appender getAppender(String name) { - return aai.getAppender(name); - } - - public boolean isAttached(Appender appender) { - return aai.isAttached(appender); - } - - public Iterator> iteratorForAppenders() { - return aai.iteratorForAppenders(); - } - - public void addFilter(Filter newFilter) { - fai.addFilter(newFilter); - } - - public void clearAllFilters() { - fai.clearAllFilters(); - } - - public List> getCopyOfAttachedFiltersList() { - return fai.getCopyOfAttachedFiltersList(); - } - - public FilterReply getFilterChainDecision(AccessEvent event) { - return fai.getFilterChainDecision(event); - } - - public Filter getFirstFilter() { - return fai.getFirstFilter(); - } -} +/** + * 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.access.spi; + +import java.util.Iterator; +import java.util.List; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.spi.AppenderAttachable; +import ch.qos.logback.core.spi.AppenderAttachableImpl; +import ch.qos.logback.core.spi.FilterAttachable; +import ch.qos.logback.core.spi.FilterAttachableImpl; +import ch.qos.logback.core.spi.FilterReply; + +/** + * A minimal context implementation used by certain logback-access components, + * mainly SocketServer. + * + * @author Sébastien Pennec + */ +public class AccessContext extends ContextBase implements + AppenderAttachable, FilterAttachable { + + AppenderAttachableImpl aai = new AppenderAttachableImpl(); + FilterAttachableImpl fai = new FilterAttachableImpl(); + + public void callAppenders(AccessEvent event) { + aai.appendLoopOnAppenders(event); + } + + public void addAppender(Appender newAppender) { + aai.addAppender(newAppender); + } + + public void detachAndStopAllAppenders() { + aai.detachAndStopAllAppenders(); + } + + public boolean detachAppender(Appender appender) { + return aai.detachAppender(appender); + } + + public boolean detachAppender(String name) { + return aai.detachAppender(name); + } + + public Appender getAppender(String name) { + return aai.getAppender(name); + } + + public boolean isAttached(Appender appender) { + return aai.isAttached(appender); + } + + public Iterator> iteratorForAppenders() { + return aai.iteratorForAppenders(); + } + + public void addFilter(Filter newFilter) { + fai.addFilter(newFilter); + } + + public void clearAllFilters() { + fai.clearAllFilters(); + } + + public List> getCopyOfAttachedFiltersList() { + return fai.getCopyOfAttachedFiltersList(); + } + + public FilterReply getFilterChainDecision(AccessEvent event) { + return fai.getFilterChainDecision(event); + } + + public Filter getFirstFilter() { + return fai.getFirstFilter(); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java b/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java index 9eec4efaa119e050198ea0e84a03d30f92bac607..3f50a604d234082ee948ffb8d39a35ba0463f181 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java +++ b/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java @@ -1,493 +1,493 @@ -/** - * 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.access.spi; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Vector; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import ch.qos.logback.access.AccessConstants; -import ch.qos.logback.access.pattern.AccessConverter; -import ch.qos.logback.access.servlet.Util; - -// Contributors: Joern Huxhorn (see also bug #110) - -/** - * The Access module's internal representation of logging events. When the - * logging component instance is called in the container to log then a - * AccessEvent instance is created. This instance is passed - * around to the different logback components. - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class AccessEvent implements Serializable { - - - private static final long serialVersionUID = 866718993618836343L; - - public final static String NA = "-"; - public final static String[] NA_STRING_ARRAY = new String[] { AccessEvent.NA }; - - public final static String EMPTY = ""; - public static final int SENTINEL = -1; - - private transient final HttpServletRequest httpRequest; - private transient final HttpServletResponse httpResponse; - - String requestURI; - String requestURL; - String remoteHost; - String remoteUser; - String remoteAddr; - String protocol; - String method; - String serverName; - String requestContent; - String responseContent; - - Map requestHeaderMap; - Map requestParameterMap; - Map responseHeaderMap; - - long contentLength = SENTINEL; - int statusCode = SENTINEL; - int localPort = SENTINEL; - - transient ServerAdapter serverAdapter; - - /** - * The number of milliseconds elapsed from 1/1/1970 until logging event was - * created. - */ - private long timeStamp = 0; - - public AccessEvent(HttpServletRequest httpRequest, - HttpServletResponse httpResponse, ServerAdapter adapter) { - this.httpRequest = httpRequest; - this.httpResponse = httpResponse; - this.timeStamp = System.currentTimeMillis(); - this.serverAdapter = adapter; - } - - /** - * Returns the underlying HttpServletRequest. After serialization the returned - * value will be null. - * - * @return - */ - public HttpServletRequest getRequest() { - return httpRequest; - } - - /** - * Returns the underlying HttpServletResponse. After serialization the returned - * value will be null. - * - * @return - */ - public HttpServletResponse getResponse() { - return httpResponse; - } - - public long getTimeStamp() { - return timeStamp; - } - - public void setTimeStamp(long timeStamp) { - if (this.timeStamp != 0) { - throw new IllegalStateException( - "timeStamp has been already set for this event."); - } else { - this.timeStamp = timeStamp; - } - } - - public String getRequestURI() { - if (requestURI == null) { - if (httpRequest != null) { - requestURI = httpRequest.getRequestURI(); - } else { - requestURI = AccessEvent.NA; - } - } - return requestURI; - } - - /** - * The first line of the request. - */ - public String getRequestURL() { - if (requestURL == null) { - if (httpRequest != null) { - StringBuffer buf = new StringBuffer(); - buf.append(httpRequest.getMethod()); - buf.append(AccessConverter.SPACE_CHAR); - buf.append(httpRequest.getRequestURI()); - final String qStr = httpRequest.getQueryString(); - if (qStr != null) { - buf.append(AccessConverter.QUESTION_CHAR); - buf.append(qStr); - } - buf.append(AccessConverter.SPACE_CHAR); - buf.append(httpRequest.getProtocol()); - requestURL = buf.toString(); - } else { - requestURL = AccessEvent.NA; - } - } - return requestURL; - } - - public String getRemoteHost() { - if (remoteHost == null) { - if (httpRequest != null) { - // the underlying implementation of HttpServletRequest will - // determine if remote lookup will be performed - remoteHost = httpRequest.getRemoteHost(); - } else { - remoteHost = AccessEvent.NA; - } - } - return remoteHost; - } - - public String getRemoteUser() { - if (remoteUser == null) { - if (httpRequest != null) { - remoteUser = httpRequest.getRemoteUser(); - } else { - remoteUser = AccessEvent.NA; - } - } - return remoteUser; - } - - public String getProtocol() { - if (protocol == null) { - if (httpRequest != null) { - protocol = httpRequest.getProtocol(); - } else { - protocol = AccessEvent.NA; - } - } - return protocol; - } - - public String getMethod() { - if (method == null) { - if (httpRequest != null) { - method = httpRequest.getMethod(); - } else { - method = AccessEvent.NA; - } - } - return method; - } - - public String getServerName() { - if (serverName == null) { - if (httpRequest != null) { - serverName = httpRequest.getServerName(); - } else { - serverName = AccessEvent.NA; - } - } - return serverName; - } - - public String getRemoteAddr() { - if (remoteAddr == null) { - if (httpRequest != null) { - remoteAddr = httpRequest.getRemoteAddr(); - } else { - remoteAddr = AccessEvent.NA; - } - } - return remoteAddr; - } - - public String getRequestHeader(String key) { - String result = null; - if (requestHeaderMap == null) { - if (httpRequest != null) { - buildRequestHeaderMap(); - result = requestHeaderMap.get(key); - } - } else { - result = requestHeaderMap.get(key); - } - - if (result != null) { - return result; - } else { - return AccessEvent.NA; - } - } - - public Enumeration getRequestHeaderNames() { - // post-serialization - if (httpRequest == null) { - Vector list = new Vector(getRequestHeaderMap().keySet()); - return list.elements(); - } - return httpRequest.getHeaderNames(); - - } - - public Map getRequestHeaderMap() { - if (requestHeaderMap == null) { - buildRequestHeaderMap(); - } - return requestHeaderMap; - } - - public void buildRequestHeaderMap() { - requestHeaderMap = new HashMap(); - Enumeration e = httpRequest.getHeaderNames(); - if (e == null) { - return; - } - while (e.hasMoreElements()) { - String key = (String) e.nextElement(); - requestHeaderMap.put(key, httpRequest.getHeader(key)); - } - } - - public void buildRequestParameterMap() { - requestParameterMap = new HashMap(); - Enumeration e = httpRequest.getParameterNames(); - if (e == null) { - return; - } - while (e.hasMoreElements()) { - String key = (String) e.nextElement(); - requestParameterMap.put(key, httpRequest.getParameterValues(key)); - } - } - - public Map getRequestParameterMap() { - if (requestParameterMap == null) { - buildRequestParameterMap(); - } - return requestParameterMap; - } - - /** - * Attributes are not serialized - * - * @param key - */ - public String getAttribute(String key) { - if (httpRequest != null) { - Object value = httpRequest.getAttribute(key); - if (value == null) { - return AccessEvent.NA; - } else { - return value.toString(); - } - } else { - return AccessEvent.NA; - } - } - - public String[] getRequestParameter(String key) { - if (httpRequest != null) { - String[] value = httpRequest.getParameterValues(key); - if (value == null) { - return NA_STRING_ARRAY; - } else { - return value; - } - } else { - return NA_STRING_ARRAY; - } - } - - public String getCookie(String key) { - - if (httpRequest != null) { - Cookie[] cookieArray = httpRequest.getCookies(); - if (cookieArray == null) { - return AccessEvent.NA; - } - - for (Cookie cookie : cookieArray) { - if (key.equals(cookie.getName())) { - return cookie.getValue(); - } - } - } - return AccessEvent.NA; - } - - public long getContentLength() { - if (contentLength == SENTINEL) { - if (httpResponse != null) { - contentLength = serverAdapter.getContentLength(); - return contentLength; - } - } - return contentLength; - } - - public int getStatusCode() { - if (statusCode == SENTINEL) { - if (httpResponse != null) { - statusCode = serverAdapter.getStatusCode(); - } - } - return statusCode; - } - - public String getRequestContent() { - if (requestContent != null) { - return requestContent; - } - - if (Util.isFormUrlEncoded(httpRequest)) { - StringBuffer buf = new StringBuffer(); - - Enumeration pramEnumeration = httpRequest.getParameterNames(); - - // example: id=1234&user=cgu - // number=1233&x=1 - int count = 0; - try { - while (pramEnumeration.hasMoreElements()) { - - String key = (String) pramEnumeration.nextElement(); - if (count++ != 0) { - buf.append("&"); - } - buf.append(key); - buf.append("="); - String val = httpRequest.getParameter(key); - if (val != null) { - buf.append(val); - } else { - buf.append(""); - } - } - } catch (Exception e) { - // FIXME Why is try/catch required? - e.printStackTrace(); - } - requestContent = buf.toString(); - } else { - - // retreive the byte array placed by TeeFilter - byte[] inputBuffer = (byte[]) httpRequest - .getAttribute(AccessConstants.LB_INPUT_BUFFER); - - if (inputBuffer != null) { - requestContent = new String(inputBuffer); - } - - if (requestContent == null || requestContent.length() == 0) { - requestContent = EMPTY; - } - } - - return requestContent; - } - - public String getResponseContent() { - if (responseContent != null) { - return responseContent; - } - - if (Util.isImageResponse(httpResponse)) { - responseContent = "[IMAGE CONTENTS SUPPRESSED]"; - } else { - - // retreive the byte array previously placed by TeeFilter - byte[] outputBuffer = (byte[]) httpRequest - .getAttribute(AccessConstants.LB_OUTPUT_BUFFER); - - if (outputBuffer != null) { - responseContent = new String(outputBuffer); - } - if (responseContent == null || responseContent.length() == 0) { - responseContent = EMPTY; - } - } - - return responseContent; - } - - public int getLocalPort() { - if (localPort == SENTINEL) { - if (httpRequest != null) { - localPort = httpRequest.getLocalPort(); - } - - } - return localPort; - } - - public ServerAdapter getServerAdapter() { - return serverAdapter; - } - - public String getResponseHeader(String key) { - buildResponseHeaderMap(); - return responseHeaderMap.get(key); - } - - void buildResponseHeaderMap() { - if (responseHeaderMap == null) { - responseHeaderMap = serverAdapter.buildResponseHeaderMap(); - } - } - - public Map getResponseHeaderMap() { - buildResponseHeaderMap(); - return responseHeaderMap; - } - - public List getResponseHeaderNameList() { - buildResponseHeaderMap(); - return new ArrayList(responseHeaderMap.keySet()); - } - - public void prepareForDeferredProcessing() { - buildRequestHeaderMap(); - buildRequestParameterMap(); - buildResponseHeaderMap(); - getLocalPort(); - getMethod(); - getProtocol(); - getRemoteAddr(); - getRemoteHost(); - getRemoteUser(); - getRequestURI(); - getRequestURL(); - getServerName(); - getTimeStamp(); - - getStatusCode(); - getContentLength(); - getRequestContent(); - getResponseContent(); - } +/** + * 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.access.spi; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import ch.qos.logback.access.AccessConstants; +import ch.qos.logback.access.pattern.AccessConverter; +import ch.qos.logback.access.servlet.Util; + +// Contributors: Joern Huxhorn (see also bug #110) + +/** + * The Access module's internal representation of logging events. When the + * logging component instance is called in the container to log then a + * AccessEvent instance is created. This instance is passed + * around to the different logback components. + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class AccessEvent implements Serializable { + + + private static final long serialVersionUID = 866718993618836343L; + + public final static String NA = "-"; + public final static String[] NA_STRING_ARRAY = new String[] { AccessEvent.NA }; + + public final static String EMPTY = ""; + public static final int SENTINEL = -1; + + private transient final HttpServletRequest httpRequest; + private transient final HttpServletResponse httpResponse; + + String requestURI; + String requestURL; + String remoteHost; + String remoteUser; + String remoteAddr; + String protocol; + String method; + String serverName; + String requestContent; + String responseContent; + + Map requestHeaderMap; + Map requestParameterMap; + Map responseHeaderMap; + + long contentLength = SENTINEL; + int statusCode = SENTINEL; + int localPort = SENTINEL; + + transient ServerAdapter serverAdapter; + + /** + * The number of milliseconds elapsed from 1/1/1970 until logging event was + * created. + */ + private long timeStamp = 0; + + public AccessEvent(HttpServletRequest httpRequest, + HttpServletResponse httpResponse, ServerAdapter adapter) { + this.httpRequest = httpRequest; + this.httpResponse = httpResponse; + this.timeStamp = System.currentTimeMillis(); + this.serverAdapter = adapter; + } + + /** + * Returns the underlying HttpServletRequest. After serialization the returned + * value will be null. + * + * @return + */ + public HttpServletRequest getRequest() { + return httpRequest; + } + + /** + * Returns the underlying HttpServletResponse. After serialization the returned + * value will be null. + * + * @return + */ + public HttpServletResponse getResponse() { + return httpResponse; + } + + public long getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(long timeStamp) { + if (this.timeStamp != 0) { + throw new IllegalStateException( + "timeStamp has been already set for this event."); + } else { + this.timeStamp = timeStamp; + } + } + + public String getRequestURI() { + if (requestURI == null) { + if (httpRequest != null) { + requestURI = httpRequest.getRequestURI(); + } else { + requestURI = AccessEvent.NA; + } + } + return requestURI; + } + + /** + * The first line of the request. + */ + public String getRequestURL() { + if (requestURL == null) { + if (httpRequest != null) { + StringBuffer buf = new StringBuffer(); + buf.append(httpRequest.getMethod()); + buf.append(AccessConverter.SPACE_CHAR); + buf.append(httpRequest.getRequestURI()); + final String qStr = httpRequest.getQueryString(); + if (qStr != null) { + buf.append(AccessConverter.QUESTION_CHAR); + buf.append(qStr); + } + buf.append(AccessConverter.SPACE_CHAR); + buf.append(httpRequest.getProtocol()); + requestURL = buf.toString(); + } else { + requestURL = AccessEvent.NA; + } + } + return requestURL; + } + + public String getRemoteHost() { + if (remoteHost == null) { + if (httpRequest != null) { + // the underlying implementation of HttpServletRequest will + // determine if remote lookup will be performed + remoteHost = httpRequest.getRemoteHost(); + } else { + remoteHost = AccessEvent.NA; + } + } + return remoteHost; + } + + public String getRemoteUser() { + if (remoteUser == null) { + if (httpRequest != null) { + remoteUser = httpRequest.getRemoteUser(); + } else { + remoteUser = AccessEvent.NA; + } + } + return remoteUser; + } + + public String getProtocol() { + if (protocol == null) { + if (httpRequest != null) { + protocol = httpRequest.getProtocol(); + } else { + protocol = AccessEvent.NA; + } + } + return protocol; + } + + public String getMethod() { + if (method == null) { + if (httpRequest != null) { + method = httpRequest.getMethod(); + } else { + method = AccessEvent.NA; + } + } + return method; + } + + public String getServerName() { + if (serverName == null) { + if (httpRequest != null) { + serverName = httpRequest.getServerName(); + } else { + serverName = AccessEvent.NA; + } + } + return serverName; + } + + public String getRemoteAddr() { + if (remoteAddr == null) { + if (httpRequest != null) { + remoteAddr = httpRequest.getRemoteAddr(); + } else { + remoteAddr = AccessEvent.NA; + } + } + return remoteAddr; + } + + public String getRequestHeader(String key) { + String result = null; + if (requestHeaderMap == null) { + if (httpRequest != null) { + buildRequestHeaderMap(); + result = requestHeaderMap.get(key); + } + } else { + result = requestHeaderMap.get(key); + } + + if (result != null) { + return result; + } else { + return AccessEvent.NA; + } + } + + public Enumeration getRequestHeaderNames() { + // post-serialization + if (httpRequest == null) { + Vector list = new Vector(getRequestHeaderMap().keySet()); + return list.elements(); + } + return httpRequest.getHeaderNames(); + + } + + public Map getRequestHeaderMap() { + if (requestHeaderMap == null) { + buildRequestHeaderMap(); + } + return requestHeaderMap; + } + + public void buildRequestHeaderMap() { + requestHeaderMap = new HashMap(); + Enumeration e = httpRequest.getHeaderNames(); + if (e == null) { + return; + } + while (e.hasMoreElements()) { + String key = (String) e.nextElement(); + requestHeaderMap.put(key, httpRequest.getHeader(key)); + } + } + + public void buildRequestParameterMap() { + requestParameterMap = new HashMap(); + Enumeration e = httpRequest.getParameterNames(); + if (e == null) { + return; + } + while (e.hasMoreElements()) { + String key = (String) e.nextElement(); + requestParameterMap.put(key, httpRequest.getParameterValues(key)); + } + } + + public Map getRequestParameterMap() { + if (requestParameterMap == null) { + buildRequestParameterMap(); + } + return requestParameterMap; + } + + /** + * Attributes are not serialized + * + * @param key + */ + public String getAttribute(String key) { + if (httpRequest != null) { + Object value = httpRequest.getAttribute(key); + if (value == null) { + return AccessEvent.NA; + } else { + return value.toString(); + } + } else { + return AccessEvent.NA; + } + } + + public String[] getRequestParameter(String key) { + if (httpRequest != null) { + String[] value = httpRequest.getParameterValues(key); + if (value == null) { + return NA_STRING_ARRAY; + } else { + return value; + } + } else { + return NA_STRING_ARRAY; + } + } + + public String getCookie(String key) { + + if (httpRequest != null) { + Cookie[] cookieArray = httpRequest.getCookies(); + if (cookieArray == null) { + return AccessEvent.NA; + } + + for (Cookie cookie : cookieArray) { + if (key.equals(cookie.getName())) { + return cookie.getValue(); + } + } + } + return AccessEvent.NA; + } + + public long getContentLength() { + if (contentLength == SENTINEL) { + if (httpResponse != null) { + contentLength = serverAdapter.getContentLength(); + return contentLength; + } + } + return contentLength; + } + + public int getStatusCode() { + if (statusCode == SENTINEL) { + if (httpResponse != null) { + statusCode = serverAdapter.getStatusCode(); + } + } + return statusCode; + } + + public String getRequestContent() { + if (requestContent != null) { + return requestContent; + } + + if (Util.isFormUrlEncoded(httpRequest)) { + StringBuffer buf = new StringBuffer(); + + Enumeration pramEnumeration = httpRequest.getParameterNames(); + + // example: id=1234&user=cgu + // number=1233&x=1 + int count = 0; + try { + while (pramEnumeration.hasMoreElements()) { + + String key = (String) pramEnumeration.nextElement(); + if (count++ != 0) { + buf.append("&"); + } + buf.append(key); + buf.append("="); + String val = httpRequest.getParameter(key); + if (val != null) { + buf.append(val); + } else { + buf.append(""); + } + } + } catch (Exception e) { + // FIXME Why is try/catch required? + e.printStackTrace(); + } + requestContent = buf.toString(); + } else { + + // retreive the byte array placed by TeeFilter + byte[] inputBuffer = (byte[]) httpRequest + .getAttribute(AccessConstants.LB_INPUT_BUFFER); + + if (inputBuffer != null) { + requestContent = new String(inputBuffer); + } + + if (requestContent == null || requestContent.length() == 0) { + requestContent = EMPTY; + } + } + + return requestContent; + } + + public String getResponseContent() { + if (responseContent != null) { + return responseContent; + } + + if (Util.isImageResponse(httpResponse)) { + responseContent = "[IMAGE CONTENTS SUPPRESSED]"; + } else { + + // retreive the byte array previously placed by TeeFilter + byte[] outputBuffer = (byte[]) httpRequest + .getAttribute(AccessConstants.LB_OUTPUT_BUFFER); + + if (outputBuffer != null) { + responseContent = new String(outputBuffer); + } + if (responseContent == null || responseContent.length() == 0) { + responseContent = EMPTY; + } + } + + return responseContent; + } + + public int getLocalPort() { + if (localPort == SENTINEL) { + if (httpRequest != null) { + localPort = httpRequest.getLocalPort(); + } + + } + return localPort; + } + + public ServerAdapter getServerAdapter() { + return serverAdapter; + } + + public String getResponseHeader(String key) { + buildResponseHeaderMap(); + return responseHeaderMap.get(key); + } + + void buildResponseHeaderMap() { + if (responseHeaderMap == null) { + responseHeaderMap = serverAdapter.buildResponseHeaderMap(); + } + } + + public Map getResponseHeaderMap() { + buildResponseHeaderMap(); + return responseHeaderMap; + } + + public List getResponseHeaderNameList() { + buildResponseHeaderMap(); + return new ArrayList(responseHeaderMap.keySet()); + } + + public void prepareForDeferredProcessing() { + buildRequestHeaderMap(); + buildRequestParameterMap(); + buildResponseHeaderMap(); + getLocalPort(); + getMethod(); + getProtocol(); + getRemoteAddr(); + getRemoteHost(); + getRemoteUser(); + getRequestURI(); + getRequestURL(); + getServerName(); + getTimeStamp(); + + getStatusCode(); + getContentLength(); + getRequestContent(); + getResponseContent(); + } } \ No newline at end of file diff --git a/logback-access/src/main/java/ch/qos/logback/access/spi/ServerAdapter.java b/logback-access/src/main/java/ch/qos/logback/access/spi/ServerAdapter.java index a5563f68bb45ada9b4407afb80a66541fd4c89fb..191147413bfd8f198188462cf74e67d779e49a2e 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/spi/ServerAdapter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/spi/ServerAdapter.java @@ -1,34 +1,34 @@ -/** - * 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.access.spi; - -import java.util.Map; - -/** - * An interface to access server-specific methods from - * the server-independent AccessEvent. - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public interface ServerAdapter { - - long getContentLength(); - int getStatusCode(); -// String getResponseHeader(String key); -// List getResponseHeaderNameList(); -// Map getResponseHeaderMap(); - - Map buildResponseHeaderMap(); -} +/** + * 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.access.spi; + +import java.util.Map; + +/** + * An interface to access server-specific methods from + * the server-independent AccessEvent. + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public interface ServerAdapter { + + long getContentLength(); + int getStatusCode(); +// String getResponseHeader(String key); +// List getResponseHeaderNameList(); +// Map getResponseHeaderMap(); + + Map buildResponseHeaderMap(); +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/spi/Util.java b/logback-access/src/main/java/ch/qos/logback/access/spi/Util.java index e86d1896356f20c4bc9118dc421bfaa988c13066..12ae682ca11ad77869865d221cd342024ab5b44d 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/spi/Util.java +++ b/logback-access/src/main/java/ch/qos/logback/access/spi/Util.java @@ -1,35 +1,35 @@ -/** - * 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.access.spi; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -public class Util { - static final int BUF_SIZE= 128; - - public static String readToString(InputStream in) throws IOException { - if(in == null) { - return null; - } - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buf = new byte[BUF_SIZE]; - int n = 0; - while( (n = in.read(buf, 0, BUF_SIZE)) != -1) { - baos.write(buf, 0, n); - } - return baos.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.access.spi; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class Util { + static final int BUF_SIZE= 128; + + public static String readToString(InputStream in) throws IOException { + if(in == null) { + return null; + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buf = new byte[BUF_SIZE]; + int n = 0; + while( (n = in.read(buf, 0, BUF_SIZE)) != -1) { + baos.write(buf, 0, n); + } + return baos.toString(); + } +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/spi/package.html b/logback-access/src/main/java/ch/qos/logback/access/spi/package.html index ae7fcc8f1cd2bd18068e0e907ba48125d9b27503..08b45592c11c95236c8dc4c389e63f83268be205 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/spi/package.html +++ b/logback-access/src/main/java/ch/qos/logback/access/spi/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains the core classes of logback access.

- - + + + + + + + + + +

Contains the core classes of logback access.

+ + \ No newline at end of file diff --git a/logback-access/src/main/java/ch/qos/logback/access/tomcat/LogbackValve.java b/logback-access/src/main/java/ch/qos/logback/access/tomcat/LogbackValve.java index 95347d25e49d5970bf261301686f849200d67c7f..4c39e271d5c2793fac0af6596b6d074d5170c632 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/tomcat/LogbackValve.java +++ b/logback-access/src/main/java/ch/qos/logback/access/tomcat/LogbackValve.java @@ -1,291 +1,291 @@ -/** - * 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.access.tomcat; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; - -import org.apache.catalina.Lifecycle; -import org.apache.catalina.LifecycleListener; -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; -import org.apache.catalina.valves.ValveBase; - -import ch.qos.logback.access.AccessConstants; -import ch.qos.logback.access.joran.JoranConfigurator; -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.BasicStatusManager; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.filter.Filter; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.spi.AppenderAttachable; -import ch.qos.logback.core.spi.AppenderAttachableImpl; -import ch.qos.logback.core.spi.FilterAttachable; -import ch.qos.logback.core.spi.FilterAttachableImpl; -import ch.qos.logback.core.spi.FilterReply; -import ch.qos.logback.core.status.InfoStatus; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.status.WarnStatus; -import ch.qos.logback.core.util.OptionHelper; -import ch.qos.logback.core.util.StatusPrinter; - -/** - * This class is an implementation of tomcat's Valve interface, by extending - * ValveBase. - * - *

For more information on using LogbackValve please refer to the online - * documentation on logback-acces and tomcat. - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class LogbackValve extends ValveBase implements Lifecycle, Context, - AppenderAttachable, FilterAttachable { - - public final static String DEFAULT_CONFIG_FILE = "conf" + File.separatorChar - + "logback-access.xml"; - - private long birthTime = System.currentTimeMillis(); - Object configurationLock = new Object(); - - - // Attributes from ContextBase: - private String name; - StatusManager sm = new BasicStatusManager(); - // TODO propertyMap should be observable so that we can be notified - // when it changes so that a new instance of propertyMap can be - // serialized. For the time being, we ignore this shortcoming. - Map propertyMap = new HashMap(); - Map objectMap = new HashMap(); - private FilterAttachableImpl fai = new FilterAttachableImpl(); - - AppenderAttachableImpl aai = new AppenderAttachableImpl(); - String filename; - boolean quiet; - boolean started; - boolean alreadySetLogbackStatusManager = false; - - public LogbackValve() { - putObject(CoreConstants.EVALUATOR_MAP, new HashMap()); - } - - public void start() { - if (filename == null) { - String tomcatHomeProperty = OptionHelper - .getSystemProperty("catalina.home"); - - filename = tomcatHomeProperty + File.separatorChar + DEFAULT_CONFIG_FILE; - getStatusManager().add( - new InfoStatus("filename property not set. Assuming [" + filename - + "]", this)); - } - File configFile = new File(filename); - if (configFile.exists()) { - try { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(this); - jc.doConfigure(filename); - } catch (JoranException e) { - // TODO can we do better than printing a stack trace on syserr? - e.printStackTrace(); - } - } else { - getStatusManager().add( - new WarnStatus("[" + filename + "] does not exist", this)); - } - - if (!quiet) { - StatusPrinter.print(getStatusManager()); - } - - started = true; - } - - public String getFilename() { - return filename; - } - - public void setFilename(String filename) { - this.filename = filename; - } - - public boolean isQuiet() { - return quiet; - } - - public void setQuiet(boolean quiet) { - this.quiet = quiet; - } - - public void invoke(Request request, Response response) throws IOException, - ServletException { - - try { - - if (!alreadySetLogbackStatusManager) { - alreadySetLogbackStatusManager = true; - org.apache.catalina.Context tomcatContext = request.getContext(); - if (tomcatContext != null) { - ServletContext sc = tomcatContext.getServletContext(); - if (sc != null) { - sc.setAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY, - getStatusManager()); - } - } - } - - getNext().invoke(request, response); - - TomcatServerAdapter adapter = new TomcatServerAdapter(request, response); - AccessEvent accessEvent = new AccessEvent(request, response, adapter); - - if (getFilterChainDecision(accessEvent) == FilterReply.DENY) { - return; - } - - // TODO better exception handling - aai.appendLoopOnAppenders(accessEvent); - } finally { - request - .removeAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY); - } - } - - public void stop() { - started = false; - } - - public void addAppender(Appender newAppender) { - aai.addAppender(newAppender); - } - - public Iterator> iteratorForAppenders() { - return aai.iteratorForAppenders(); - } - - public Appender getAppender(String name) { - return aai.getAppender(name); - } - - public boolean isAttached(Appender appender) { - return aai.isAttached(appender); - } - - public void detachAndStopAllAppenders() { - aai.detachAndStopAllAppenders(); - - } - - public boolean detachAppender(Appender appender) { - return aai.detachAppender(appender); - } - - public boolean detachAppender(String name) { - return aai.detachAppender(name); - } - - public String getInfo() { - return "Logback's implementation of ValveBase"; - } - - // Methods from ContextBase: - public StatusManager getStatusManager() { - return sm; - } - - public Map getPropertyMap() { - return propertyMap; - } - - public void putProperty(String key, String val) { - this.propertyMap.put(key, val); - } - - public String getProperty(String key) { - return (String) this.propertyMap.get(key); - } - - public Object getObject(String key) { - return objectMap.get(key); - } - - public void putObject(String key, Object value) { - objectMap.put(key, value); - } - - public void addFilter(Filter newFilter) { - fai.addFilter(newFilter); - } - - public Filter getFirstFilter() { - return fai.getFirstFilter(); - } - - public void clearAllFilters() { - fai.clearAllFilters(); - } - - public List> getCopyOfAttachedFiltersList() { - return fai.getCopyOfAttachedFiltersList(); - } - - public FilterReply getFilterChainDecision(AccessEvent event) { - return fai.getFilterChainDecision(event); - } - - public String getName() { - return name; - } - - public void setName(String name) { - if (this.name != null) { - throw new IllegalStateException( - "LogbackValve has been already given a name"); - } - this.name = name; - } - - public long getBithTime() { - return birthTime; - } - - public Object getConfigurationLock() { - return configurationLock; - } - - // ====== Methods from catalina Lifecycle ===== - - public void addLifecycleListener(LifecycleListener arg0) { - // dummy NOP implementation - } - - public LifecycleListener[] findLifecycleListeners() { - return new LifecycleListener[0]; - } - - public void removeLifecycleListener(LifecycleListener arg0) { - // dummy NOP implementation - } - -} +/** + * 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.access.tomcat; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleListener; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; + +import ch.qos.logback.access.AccessConstants; +import ch.qos.logback.access.joran.JoranConfigurator; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.BasicStatusManager; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.spi.AppenderAttachable; +import ch.qos.logback.core.spi.AppenderAttachableImpl; +import ch.qos.logback.core.spi.FilterAttachable; +import ch.qos.logback.core.spi.FilterAttachableImpl; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.WarnStatus; +import ch.qos.logback.core.util.OptionHelper; +import ch.qos.logback.core.util.StatusPrinter; + +/** + * This class is an implementation of tomcat's Valve interface, by extending + * ValveBase. + * + *

For more information on using LogbackValve please refer to the online + * documentation on logback-acces and tomcat. + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class LogbackValve extends ValveBase implements Lifecycle, Context, + AppenderAttachable, FilterAttachable { + + public final static String DEFAULT_CONFIG_FILE = "conf" + File.separatorChar + + "logback-access.xml"; + + private long birthTime = System.currentTimeMillis(); + Object configurationLock = new Object(); + + + // Attributes from ContextBase: + private String name; + StatusManager sm = new BasicStatusManager(); + // TODO propertyMap should be observable so that we can be notified + // when it changes so that a new instance of propertyMap can be + // serialized. For the time being, we ignore this shortcoming. + Map propertyMap = new HashMap(); + Map objectMap = new HashMap(); + private FilterAttachableImpl fai = new FilterAttachableImpl(); + + AppenderAttachableImpl aai = new AppenderAttachableImpl(); + String filename; + boolean quiet; + boolean started; + boolean alreadySetLogbackStatusManager = false; + + public LogbackValve() { + putObject(CoreConstants.EVALUATOR_MAP, new HashMap()); + } + + public void start() { + if (filename == null) { + String tomcatHomeProperty = OptionHelper + .getSystemProperty("catalina.home"); + + filename = tomcatHomeProperty + File.separatorChar + DEFAULT_CONFIG_FILE; + getStatusManager().add( + new InfoStatus("filename property not set. Assuming [" + filename + + "]", this)); + } + File configFile = new File(filename); + if (configFile.exists()) { + try { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(this); + jc.doConfigure(filename); + } catch (JoranException e) { + // TODO can we do better than printing a stack trace on syserr? + e.printStackTrace(); + } + } else { + getStatusManager().add( + new WarnStatus("[" + filename + "] does not exist", this)); + } + + if (!quiet) { + StatusPrinter.print(getStatusManager()); + } + + started = true; + } + + public String getFilename() { + return filename; + } + + public void setFilename(String filename) { + this.filename = filename; + } + + public boolean isQuiet() { + return quiet; + } + + public void setQuiet(boolean quiet) { + this.quiet = quiet; + } + + public void invoke(Request request, Response response) throws IOException, + ServletException { + + try { + + if (!alreadySetLogbackStatusManager) { + alreadySetLogbackStatusManager = true; + org.apache.catalina.Context tomcatContext = request.getContext(); + if (tomcatContext != null) { + ServletContext sc = tomcatContext.getServletContext(); + if (sc != null) { + sc.setAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY, + getStatusManager()); + } + } + } + + getNext().invoke(request, response); + + TomcatServerAdapter adapter = new TomcatServerAdapter(request, response); + AccessEvent accessEvent = new AccessEvent(request, response, adapter); + + if (getFilterChainDecision(accessEvent) == FilterReply.DENY) { + return; + } + + // TODO better exception handling + aai.appendLoopOnAppenders(accessEvent); + } finally { + request + .removeAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY); + } + } + + public void stop() { + started = false; + } + + public void addAppender(Appender newAppender) { + aai.addAppender(newAppender); + } + + public Iterator> iteratorForAppenders() { + return aai.iteratorForAppenders(); + } + + public Appender getAppender(String name) { + return aai.getAppender(name); + } + + public boolean isAttached(Appender appender) { + return aai.isAttached(appender); + } + + public void detachAndStopAllAppenders() { + aai.detachAndStopAllAppenders(); + + } + + public boolean detachAppender(Appender appender) { + return aai.detachAppender(appender); + } + + public boolean detachAppender(String name) { + return aai.detachAppender(name); + } + + public String getInfo() { + return "Logback's implementation of ValveBase"; + } + + // Methods from ContextBase: + public StatusManager getStatusManager() { + return sm; + } + + public Map getPropertyMap() { + return propertyMap; + } + + public void putProperty(String key, String val) { + this.propertyMap.put(key, val); + } + + public String getProperty(String key) { + return (String) this.propertyMap.get(key); + } + + public Object getObject(String key) { + return objectMap.get(key); + } + + public void putObject(String key, Object value) { + objectMap.put(key, value); + } + + public void addFilter(Filter newFilter) { + fai.addFilter(newFilter); + } + + public Filter getFirstFilter() { + return fai.getFirstFilter(); + } + + public void clearAllFilters() { + fai.clearAllFilters(); + } + + public List> getCopyOfAttachedFiltersList() { + return fai.getCopyOfAttachedFiltersList(); + } + + public FilterReply getFilterChainDecision(AccessEvent event) { + return fai.getFilterChainDecision(event); + } + + public String getName() { + return name; + } + + public void setName(String name) { + if (this.name != null) { + throw new IllegalStateException( + "LogbackValve has been already given a name"); + } + this.name = name; + } + + public long getBithTime() { + return birthTime; + } + + public Object getConfigurationLock() { + return configurationLock; + } + + // ====== Methods from catalina Lifecycle ===== + + public void addLifecycleListener(LifecycleListener arg0) { + // dummy NOP implementation + } + + public LifecycleListener[] findLifecycleListeners() { + return new LifecycleListener[0]; + } + + public void removeLifecycleListener(LifecycleListener arg0) { + // dummy NOP implementation + } + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/tomcat/TomcatServerAdapter.java b/logback-access/src/main/java/ch/qos/logback/access/tomcat/TomcatServerAdapter.java index 0ee05a12fad15b95efe4b502b5145d97cd7ae8d2..5fab333219e0a76064af929111e15b8850b695c7 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/tomcat/TomcatServerAdapter.java +++ b/logback-access/src/main/java/ch/qos/logback/access/tomcat/TomcatServerAdapter.java @@ -1,59 +1,59 @@ -/** - * 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.access.tomcat; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; - -import ch.qos.logback.access.spi.ServerAdapter; - -/** - * A tomcat specific implementation of the {@link ServerAdapter} interface. - * - * @author Sébastien Pennec - */ -public class TomcatServerAdapter implements ServerAdapter { - - Request request; - Response response; - - public TomcatServerAdapter(Request tomcatRequest, Response tomcatResponse) { - this.request = tomcatRequest; - this.response = tomcatResponse; - } - - public long getContentLength() { - return response.getContentLength(); - } - - public int getStatusCode() { - return response.getStatus(); - } - - - public Map buildResponseHeaderMap() { - Map responseHeaderMap = new HashMap(); - for (String key : response.getHeaderNames()) { - String value = response.getHeader(key); - responseHeaderMap.put(key, value); - } - return responseHeaderMap; - } - - - -} +/** + * 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.access.tomcat; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; + +import ch.qos.logback.access.spi.ServerAdapter; + +/** + * A tomcat specific implementation of the {@link ServerAdapter} interface. + * + * @author Sébastien Pennec + */ +public class TomcatServerAdapter implements ServerAdapter { + + Request request; + Response response; + + public TomcatServerAdapter(Request tomcatRequest, Response tomcatResponse) { + this.request = tomcatRequest; + this.response = tomcatResponse; + } + + public long getContentLength() { + return response.getContentLength(); + } + + public int getStatusCode() { + return response.getStatus(); + } + + + public Map buildResponseHeaderMap() { + Map responseHeaderMap = new HashMap(); + for (String key : response.getHeaderNames()) { + String value = response.getHeader(key); + responseHeaderMap.put(key, value); + } + return responseHeaderMap; + } + + + +} diff --git a/logback-access/src/main/java/ch/qos/logback/access/tomcat/package.html b/logback-access/src/main/java/ch/qos/logback/access/tomcat/package.html index b716f7947d74b24516602124bd3a3ac21fe40366..c96b85259ff4295358615b4d03075072ba8fc9bd 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/tomcat/package.html +++ b/logback-access/src/main/java/ch/qos/logback/access/tomcat/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

This is logback access' implementation for Tomcat.

- - + + + + + + + + + +

This is logback access' implementation for Tomcat.

+ + \ No newline at end of file diff --git a/logback-access/src/test/input/integration/db/mysql-with-driver.xml b/logback-access/src/test/input/integration/db/mysql-with-driver.xml index 0e35e712c028f6c536bbe8f81ada637f5b01daac..81bfdd89b1c4912ca537c45512d6f63eb1f36374 100644 --- a/logback-access/src/test/input/integration/db/mysql-with-driver.xml +++ b/logback-access/src/test/input/integration/db/mysql-with-driver.xml @@ -1,17 +1,17 @@ - - - - - - - com.mysql.jdbc.Driver - jdbc:mysql://localhost:3306/logback - root - - - - - - - + + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/logback + root + + + + + + + diff --git a/logback-access/src/test/input/integration/db/oracle10g-with-driver.xml b/logback-access/src/test/input/integration/db/oracle10g-with-driver.xml index 52a578ef07f83ce101f619eac73931b73a840bc8..bf7dc67b4d27b7e3a881993cfd1c9b5d58debc66 100644 --- a/logback-access/src/test/input/integration/db/oracle10g-with-driver.xml +++ b/logback-access/src/test/input/integration/db/oracle10g-with-driver.xml @@ -1,17 +1,17 @@ - - - - - - - oracle.jdbc.OracleDriver - jdbc:oracle:thin:@localhost:1522:xe - hr - hr - - - - - - + + + + + + + oracle.jdbc.OracleDriver + jdbc:oracle:thin:@localhost:1522:xe + hr + hr + + + + + + diff --git a/logback-access/src/test/input/integration/db/oracle11g-with-driver.xml b/logback-access/src/test/input/integration/db/oracle11g-with-driver.xml index 393189fb53f96a9915bab69c787f58a5ea05b725..8ed022d986d73a280dabd97c96348f21ce0ce4d1 100644 --- a/logback-access/src/test/input/integration/db/oracle11g-with-driver.xml +++ b/logback-access/src/test/input/integration/db/oracle11g-with-driver.xml @@ -1,17 +1,17 @@ - - - - - - - oracle.jdbc.OracleDriver - jdbc:oracle:thin:@localhost:1521:orcl - SCOTT - SCOTT - - - - - - - + + + + + + + oracle.jdbc.OracleDriver + jdbc:oracle:thin:@localhost:1521:orcl + SCOTT + SCOTT + + + + + + + diff --git a/logback-access/src/test/input/integration/db/postgresql-with-driver.xml b/logback-access/src/test/input/integration/db/postgresql-with-driver.xml index fc8dbb63953a05c2655836c52fc363d8d3965f27..8b047abbca00afdacf24d1b879a3c9cd4c38c6a1 100644 --- a/logback-access/src/test/input/integration/db/postgresql-with-driver.xml +++ b/logback-access/src/test/input/integration/db/postgresql-with-driver.xml @@ -1,16 +1,16 @@ - - - - - - - org.postgresql.Driver - jdbc:postgresql://192.168.1.5:5432/test - logback - logback - - - - - - + + + + + + + org.postgresql.Driver + jdbc:postgresql://192.168.1.5:5432/test + logback + logback + + + + + + diff --git a/logback-access/src/test/input/integration/db/sqlserver-with-driver.xml b/logback-access/src/test/input/integration/db/sqlserver-with-driver.xml index 1c49a86e6f84c11ff515ba548bf0f40e056bfc70..85c0ee20b561d1a5be14f0733588a5c7de9dda4e 100644 --- a/logback-access/src/test/input/integration/db/sqlserver-with-driver.xml +++ b/logback-access/src/test/input/integration/db/sqlserver-with-driver.xml @@ -1,16 +1,16 @@ - - - - - - - com.microsoft.sqlserver.jdbc.SQLServerDriver - jdbc:sqlserver://localhost:1987;databaseName=logback; - logback - logback - - - - - - + + + + + + + com.microsoft.sqlserver.jdbc.SQLServerDriver + jdbc:sqlserver://localhost:1987;databaseName=logback; + logback + logback + + + + + + diff --git a/logback-access/src/test/input/jetty/sifting.xml b/logback-access/src/test/input/jetty/sifting.xml index 10dfada9e31555b7a2e1b36f43b8468f2972e1c1..b4b89b63dd86687c45a24b3ce8d04b327a564742 100644 --- a/logback-access/src/test/input/jetty/sifting.xml +++ b/logback-access/src/test/input/jetty/sifting.xml @@ -1,17 +1,17 @@ - - - - - - uri - REQUEST_URI - NA - - - - - - - + + + + + + uri + REQUEST_URI + NA + + + + + + + \ No newline at end of file diff --git a/logback-access/src/test/input/joran/defaultLayout.xml b/logback-access/src/test/input/joran/defaultLayout.xml index 95050e1042c98f0926ad9b8637d28ed8475fe64d..d486bf7856f29a54ea5e47ba252ddc3f4b2183db 100644 --- a/logback-access/src/test/input/joran/defaultLayout.xml +++ b/logback-access/src/test/input/joran/defaultLayout.xml @@ -1,13 +1,13 @@ - - - - - - %requestMethod - - - - + + + + + + %requestMethod + + + + \ No newline at end of file diff --git a/logback-access/src/test/input/joran/smoke.xml b/logback-access/src/test/input/joran/smoke.xml index 69b7375425dc73814a86eeb856007f43c97d6163..a62cdcedbfdac5722833560a64a05144c2729332 100644 --- a/logback-access/src/test/input/joran/smoke.xml +++ b/logback-access/src/test/input/joran/smoke.xml @@ -1,5 +1,5 @@ - - - - + + + + \ No newline at end of file diff --git a/logback-access/src/test/java/ch/qos/logback/access/AllAccessTest.java b/logback-access/src/test/java/ch/qos/logback/access/AllAccessTest.java index dda44b45bfe80778829cadc8e492957e3954cbe8..255c095da42d8c35967647fa2b2b2e2c4391c512 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/AllAccessTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/AllAccessTest.java @@ -1,29 +1,29 @@ -/** - * 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.access; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses( { ch.qos.logback.access.spi.PackageTest.class, - ch.qos.logback.access.net.PackageTest.class, - ch.qos.logback.access.pattern.PackageTest.class, - ch.qos.logback.access.jetty.PackageTest.class, - ch.qos.logback.access.filter.PackageTest.class, - ch.qos.logback.access.sift.PackageTest.class }) -public class AllAccessTest { - -} +/** + * 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.access; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses( { ch.qos.logback.access.spi.PackageTest.class, + ch.qos.logback.access.net.PackageTest.class, + ch.qos.logback.access.pattern.PackageTest.class, + ch.qos.logback.access.jetty.PackageTest.class, + ch.qos.logback.access.filter.PackageTest.class, + ch.qos.logback.access.sift.PackageTest.class }) +public class AllAccessTest { + +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/TeztConstants.java b/logback-access/src/test/java/ch/qos/logback/access/TeztConstants.java index fcd1eb88b668d337f769be6453aa27ee84c9d4f2..d3cd4103497d20c6cd6753c7b2dd6e79808e616f 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/TeztConstants.java +++ b/logback-access/src/test/java/ch/qos/logback/access/TeztConstants.java @@ -1,19 +1,19 @@ -/** - * 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.access; - -public class TeztConstants { - - public static final String TEST_DIR_PREFIX = "src/test/"; -} +/** + * 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.access; + +public class TeztConstants { + + public static final String TEST_DIR_PREFIX = "src/test/"; +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderIntegrationTest.java b/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderIntegrationTest.java index 3874835817ada6a8ced1862e601901891309b41e..6c9b56ede28d7268d42d5a7941d33cd62add5d14 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderIntegrationTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderIntegrationTest.java @@ -1,143 +1,143 @@ -/** - * 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.access.db; - -import static org.junit.Assert.assertEquals; - -import java.net.InetAddress; -import java.util.Random; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; - -import ch.qos.logback.access.dummy.DummyAccessEventBuilder; -import ch.qos.logback.access.joran.JoranConfigurator; -import ch.qos.logback.access.spi.AccessContext; -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.testUtil.Env; -import ch.qos.logback.core.util.StatusPrinter; - -public class DBAppenderIntegrationTest { - - static String LOCAL_HOST_NAME; - static String[] CONFORMING_HOST_LIST = new String[] { "Orion" }; - - int diff = new Random(System.nanoTime()).nextInt(10000); - AccessContext context = new AccessContext(); - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - InetAddress localhostIA = InetAddress.getLocalHost(); - LOCAL_HOST_NAME = localhostIA.getHostName(); - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - } - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - - } - - public void doTest(String configFile) throws JoranException { - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(context); - configurator.doConfigure(configFile); - - Appender appender = context.getAppender("DB"); - - for (int i = 0; i < 10; i++) { - AccessEvent event = DummyAccessEventBuilder.buildNewAccessEvent(); - appender.doAppend(event); - } - - StatusPrinter.print(context); - - // check that there were no errors - assertEquals(Status.INFO, context.getStatusManager().getLevel()); - - } - - static boolean isConformingHostAndJDK16OrHigher() { - if(!Env.isJDK6OrHigher()) { - return false; - } - for (String conformingHost : CONFORMING_HOST_LIST) { - if (conformingHost.equalsIgnoreCase(LOCAL_HOST_NAME)) { - return true; - } - } - return false; - } - - @Test - public void sqlserver() throws Exception { - // perform test only on conforming hosts - if (!isConformingHostAndJDK16OrHigher()) { - return; - } - doTest("src/test/input/integration/db/sqlserver-with-driver.xml"); - } - - @Test - @Ignore - public void oracle10g() throws Exception { - // perform test only on conforming hosts - if (!isConformingHostAndJDK16OrHigher()) { - return; - } - doTest("src/test/input/integration/db/oracle10g-with-driver.xml"); - } - - @Test - @Ignore - public void oracle11g() throws Exception { - // perform test only on conforming hosts - if (!isConformingHostAndJDK16OrHigher()) { - return; - } - doTest("src/test/input/integration/db/oracle11g-with-driver.xml"); - } - - @Test - public void mysql() throws Exception { - // perform test only on conforming hosts - if (!isConformingHostAndJDK16OrHigher()) { - return; - } - doTest("src/test/input/integration/db/mysql-with-driver.xml"); - } - - @Test - public void postgres() throws Exception { - // perform test only on conforming hosts - if (!isConformingHostAndJDK16OrHigher()) { - return; - } - doTest("src/test/input/integration/db/postgresql-with-driver.xml"); - } - -} +/** + * 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.access.db; + +import static org.junit.Assert.assertEquals; + +import java.net.InetAddress; +import java.util.Random; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import ch.qos.logback.access.dummy.DummyAccessEventBuilder; +import ch.qos.logback.access.joran.JoranConfigurator; +import ch.qos.logback.access.spi.AccessContext; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.testUtil.Env; +import ch.qos.logback.core.util.StatusPrinter; + +public class DBAppenderIntegrationTest { + + static String LOCAL_HOST_NAME; + static String[] CONFORMING_HOST_LIST = new String[] { "Orion" }; + + int diff = new Random(System.nanoTime()).nextInt(10000); + AccessContext context = new AccessContext(); + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + InetAddress localhostIA = InetAddress.getLocalHost(); + LOCAL_HOST_NAME = localhostIA.getHostName(); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + + } + + public void doTest(String configFile) throws JoranException { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(context); + configurator.doConfigure(configFile); + + Appender appender = context.getAppender("DB"); + + for (int i = 0; i < 10; i++) { + AccessEvent event = DummyAccessEventBuilder.buildNewAccessEvent(); + appender.doAppend(event); + } + + StatusPrinter.print(context); + + // check that there were no errors + assertEquals(Status.INFO, context.getStatusManager().getLevel()); + + } + + static boolean isConformingHostAndJDK16OrHigher() { + if(!Env.isJDK6OrHigher()) { + return false; + } + for (String conformingHost : CONFORMING_HOST_LIST) { + if (conformingHost.equalsIgnoreCase(LOCAL_HOST_NAME)) { + return true; + } + } + return false; + } + + @Test + public void sqlserver() throws Exception { + // perform test only on conforming hosts + if (!isConformingHostAndJDK16OrHigher()) { + return; + } + doTest("src/test/input/integration/db/sqlserver-with-driver.xml"); + } + + @Test + @Ignore + public void oracle10g() throws Exception { + // perform test only on conforming hosts + if (!isConformingHostAndJDK16OrHigher()) { + return; + } + doTest("src/test/input/integration/db/oracle10g-with-driver.xml"); + } + + @Test + @Ignore + public void oracle11g() throws Exception { + // perform test only on conforming hosts + if (!isConformingHostAndJDK16OrHigher()) { + return; + } + doTest("src/test/input/integration/db/oracle11g-with-driver.xml"); + } + + @Test + public void mysql() throws Exception { + // perform test only on conforming hosts + if (!isConformingHostAndJDK16OrHigher()) { + return; + } + doTest("src/test/input/integration/db/mysql-with-driver.xml"); + } + + @Test + public void postgres() throws Exception { + // perform test only on conforming hosts + if (!isConformingHostAndJDK16OrHigher()) { + return; + } + doTest("src/test/input/integration/db/postgresql-with-driver.xml"); + } + +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderTest.java b/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderTest.java index 62f658ca2db36849e39fc5b5ce83c44327412a68..88c5aa2c0947d93d9261ac5e7e5d83d1d8a731a8 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderTest.java @@ -1,204 +1,204 @@ -/** - * 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.access.db; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import ch.qos.logback.access.dummy.DummyRequest; -import ch.qos.logback.access.dummy.DummyResponse; -import ch.qos.logback.access.dummy.DummyServerAdapter; -import ch.qos.logback.access.spi.AccessContext; -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.db.DriverManagerConnectionSource; -import ch.qos.logback.core.util.StatusPrinter; - -public class DBAppenderTest { - - AccessContext context; - DBAppender appender; - DriverManagerConnectionSource connectionSource; - - static DBAppenderTestFixture DB_APPENDER_TEST_FIXTURE; - - @BeforeClass - static public void fixtureSetUp() throws SQLException { - DB_APPENDER_TEST_FIXTURE = new DBAppenderTestFixture(); - DB_APPENDER_TEST_FIXTURE.setUp(); - } - - @AfterClass - static public void fixtureTearDown() throws SQLException { - DB_APPENDER_TEST_FIXTURE.tearDown(); - } - - @Before - public void setUp() throws SQLException { - context = new AccessContext(); - context.setName("default"); - appender = new DBAppender(); - appender.setName("DB"); - appender.setContext(context); - connectionSource = new DriverManagerConnectionSource(); - connectionSource.setContext(context); - connectionSource.setDriverClass(DBAppenderTestFixture.DRIVER_CLASS); - connectionSource.setUrl(DB_APPENDER_TEST_FIXTURE.url); - connectionSource.setUser(DB_APPENDER_TEST_FIXTURE.user); - connectionSource.setPassword(DB_APPENDER_TEST_FIXTURE.password); - connectionSource.start(); - appender.setConnectionSource(connectionSource); - } - - private void setInsertHeadersAndStart(boolean insert) { - appender.setInsertHeaders(insert); - appender.start(); - } - - @After - public void tearDown() throws SQLException { - context = null; - appender = null; - connectionSource = null; - } - - @Test - public void testAppendAccessEvent() throws SQLException { - setInsertHeadersAndStart(false); - - AccessEvent event = createAccessEvent(); - appender.append(event); - - Statement stmt = connectionSource.getConnection().createStatement(); - ResultSet rs = null; - rs = stmt.executeQuery("SELECT * FROM access_event"); - if (rs.next()) { - assertEquals(event.getTimeStamp(), rs.getLong(1)); - assertEquals(event.getRequestURI(), rs.getString(2)); - assertEquals(event.getRequestURL(), rs.getString(3)); - assertEquals(event.getRemoteHost(), rs.getString(4)); - assertEquals(event.getRemoteUser(), rs.getString(5)); - assertEquals(event.getRemoteAddr(), rs.getString(6)); - assertEquals(event.getProtocol(), rs.getString(7)); - assertEquals(event.getMethod(), rs.getString(8)); - assertEquals(event.getServerName(), rs.getString(9)); - assertEquals(event.getRequestContent(), rs.getString(10)); - } else { - fail("No row was inserted in the database"); - } - - rs.close(); - stmt.close(); - } - - - @Test - public void testCheckNoHeadersAreInserted() throws Exception { - setInsertHeadersAndStart(false); - - AccessEvent event = createAccessEvent(); - appender.append(event); - StatusPrinter.print(context.getStatusManager()); - - //Check that no headers were inserted - Statement stmt = connectionSource.getConnection().createStatement(); - ResultSet rs = null; - rs = stmt.executeQuery("SELECT * FROM access_event_header"); - - assertFalse(rs.next()); - rs.close(); - stmt.close(); - } - - @Test - public void testAppendHeaders() throws SQLException { - setInsertHeadersAndStart(true); - - AccessEvent event = createAccessEvent(); - appender.append(event); - - Statement stmt = connectionSource.getConnection().createStatement(); - ResultSet rs = null; - rs = stmt.executeQuery("SELECT * FROM access_event_header"); - String key; - String value; - if (!rs.next()) { - fail("There should be results to this query"); - } else { - key = rs.getString(2); - value = rs.getString(3); - assertNotNull(key); - assertNotNull(value); - assertEquals(event.getRequestHeader(key), value); - rs.next(); - key = rs.getString(2); - value = rs.getString(3); - assertNotNull(key); - assertNotNull(value); - assertEquals(event.getRequestHeader(key), value); - } - if (rs.next()) { - fail("There should be no more rows available"); - } - - rs.close(); - stmt.close(); - } - - @Test - public void testAppendMultipleEvents() throws SQLException { - String uri = "testAppendMultipleEvents"; - for (int i = 0; i < 10; i++) { - AccessEvent event = createAccessEvent(uri); - appender.append(event); - } - - Statement stmt = connectionSource.getConnection().createStatement(); - ResultSet rs = null; - rs = stmt.executeQuery("SELECT * FROM access_event where requestURI='"+uri+"'"); - int count = 0; - while (rs.next()) { - count++; - } - assertEquals(10, count); - - rs.close(); - stmt.close(); - } - - private AccessEvent createAccessEvent() { - return createAccessEvent(""); - } - - private AccessEvent createAccessEvent(String uri) { - DummyRequest request = new DummyRequest(); - request.setRequestUri(uri); - DummyResponse response = new DummyResponse(); - DummyServerAdapter adapter = new DummyServerAdapter(request, response); - - AccessEvent ae = new AccessEvent(request, response, adapter); - return ae; - } -} +/** + * 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.access.db; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import ch.qos.logback.access.dummy.DummyRequest; +import ch.qos.logback.access.dummy.DummyResponse; +import ch.qos.logback.access.dummy.DummyServerAdapter; +import ch.qos.logback.access.spi.AccessContext; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.db.DriverManagerConnectionSource; +import ch.qos.logback.core.util.StatusPrinter; + +public class DBAppenderTest { + + AccessContext context; + DBAppender appender; + DriverManagerConnectionSource connectionSource; + + static DBAppenderTestFixture DB_APPENDER_TEST_FIXTURE; + + @BeforeClass + static public void fixtureSetUp() throws SQLException { + DB_APPENDER_TEST_FIXTURE = new DBAppenderTestFixture(); + DB_APPENDER_TEST_FIXTURE.setUp(); + } + + @AfterClass + static public void fixtureTearDown() throws SQLException { + DB_APPENDER_TEST_FIXTURE.tearDown(); + } + + @Before + public void setUp() throws SQLException { + context = new AccessContext(); + context.setName("default"); + appender = new DBAppender(); + appender.setName("DB"); + appender.setContext(context); + connectionSource = new DriverManagerConnectionSource(); + connectionSource.setContext(context); + connectionSource.setDriverClass(DBAppenderTestFixture.DRIVER_CLASS); + connectionSource.setUrl(DB_APPENDER_TEST_FIXTURE.url); + connectionSource.setUser(DB_APPENDER_TEST_FIXTURE.user); + connectionSource.setPassword(DB_APPENDER_TEST_FIXTURE.password); + connectionSource.start(); + appender.setConnectionSource(connectionSource); + } + + private void setInsertHeadersAndStart(boolean insert) { + appender.setInsertHeaders(insert); + appender.start(); + } + + @After + public void tearDown() throws SQLException { + context = null; + appender = null; + connectionSource = null; + } + + @Test + public void testAppendAccessEvent() throws SQLException { + setInsertHeadersAndStart(false); + + AccessEvent event = createAccessEvent(); + appender.append(event); + + Statement stmt = connectionSource.getConnection().createStatement(); + ResultSet rs = null; + rs = stmt.executeQuery("SELECT * FROM access_event"); + if (rs.next()) { + assertEquals(event.getTimeStamp(), rs.getLong(1)); + assertEquals(event.getRequestURI(), rs.getString(2)); + assertEquals(event.getRequestURL(), rs.getString(3)); + assertEquals(event.getRemoteHost(), rs.getString(4)); + assertEquals(event.getRemoteUser(), rs.getString(5)); + assertEquals(event.getRemoteAddr(), rs.getString(6)); + assertEquals(event.getProtocol(), rs.getString(7)); + assertEquals(event.getMethod(), rs.getString(8)); + assertEquals(event.getServerName(), rs.getString(9)); + assertEquals(event.getRequestContent(), rs.getString(10)); + } else { + fail("No row was inserted in the database"); + } + + rs.close(); + stmt.close(); + } + + + @Test + public void testCheckNoHeadersAreInserted() throws Exception { + setInsertHeadersAndStart(false); + + AccessEvent event = createAccessEvent(); + appender.append(event); + StatusPrinter.print(context.getStatusManager()); + + //Check that no headers were inserted + Statement stmt = connectionSource.getConnection().createStatement(); + ResultSet rs = null; + rs = stmt.executeQuery("SELECT * FROM access_event_header"); + + assertFalse(rs.next()); + rs.close(); + stmt.close(); + } + + @Test + public void testAppendHeaders() throws SQLException { + setInsertHeadersAndStart(true); + + AccessEvent event = createAccessEvent(); + appender.append(event); + + Statement stmt = connectionSource.getConnection().createStatement(); + ResultSet rs = null; + rs = stmt.executeQuery("SELECT * FROM access_event_header"); + String key; + String value; + if (!rs.next()) { + fail("There should be results to this query"); + } else { + key = rs.getString(2); + value = rs.getString(3); + assertNotNull(key); + assertNotNull(value); + assertEquals(event.getRequestHeader(key), value); + rs.next(); + key = rs.getString(2); + value = rs.getString(3); + assertNotNull(key); + assertNotNull(value); + assertEquals(event.getRequestHeader(key), value); + } + if (rs.next()) { + fail("There should be no more rows available"); + } + + rs.close(); + stmt.close(); + } + + @Test + public void testAppendMultipleEvents() throws SQLException { + String uri = "testAppendMultipleEvents"; + for (int i = 0; i < 10; i++) { + AccessEvent event = createAccessEvent(uri); + appender.append(event); + } + + Statement stmt = connectionSource.getConnection().createStatement(); + ResultSet rs = null; + rs = stmt.executeQuery("SELECT * FROM access_event where requestURI='"+uri+"'"); + int count = 0; + while (rs.next()) { + count++; + } + assertEquals(10, count); + + rs.close(); + stmt.close(); + } + + private AccessEvent createAccessEvent() { + return createAccessEvent(""); + } + + private AccessEvent createAccessEvent(String uri) { + DummyRequest request = new DummyRequest(); + request.setRequestUri(uri); + DummyResponse response = new DummyResponse(); + DummyServerAdapter adapter = new DummyServerAdapter(request, response); + + AccessEvent ae = new AccessEvent(request, response, adapter); + return ae; + } +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderTestFixture.java b/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderTestFixture.java index 828c6c14aa38b489f157146d545ec48148ecac26..4721068f7c4d92fdef13560971117b29b70bd954 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderTestFixture.java +++ b/logback-access/src/test/java/ch/qos/logback/access/db/DBAppenderTestFixture.java @@ -1,128 +1,128 @@ -/** - * 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.access.db; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.sql.Statement; - -import org.hsqldb.Server; - -public class DBAppenderTestFixture { - - public static final String DRIVER_CLASS = "org.hsqldb.jdbcDriver"; - String serverProps; - String url; - String user = "sa"; - String password = ""; - Server server; - boolean isNetwork = true; - - - void setUp() throws SQLException { - if (isNetwork) { - if (url == null) { - url = "jdbc:hsqldb:hsql://localhost/test"; - } - - server = new Server(); - - server.setDatabaseName(0, "test"); - server.setDatabasePath(0, "mem:test;sql.enforce_strict_size=true"); - server.setLogWriter(null); - server.setErrWriter(null); - server.setTrace(false); - server.setSilent(true); - server.start(); - } else { - if (url == null) { - url = "jdbc:hsqldb:file:test;sql.enforce_strict_size=true"; - } - } - - try { - Class.forName(DRIVER_CLASS); - } catch (Exception e) { - e.printStackTrace(); - System.out.println(this + ".setUp() error: " + e.getMessage()); - } - Thread.yield(); - - createTables(); - } - - void tearDown() throws SQLException { - dropTables(); - if (isNetwork) { - server.stop(); - server = null; - } - } - - Connection newConnection() throws SQLException { - return DriverManager.getConnection(url, user, password); - } - - private void createTables() throws SQLException { - Connection conn = newConnection(); - StringBuffer buf = new StringBuffer(); - buf.append("CREATE TABLE access_event ("); - buf.append("timestmp BIGINT NOT NULL,"); - buf.append("requestURI VARCHAR(254),"); - buf.append("requestURL VARCHAR(254),"); - buf.append("remoteHost VARCHAR(254),"); - buf.append("remoteUser VARCHAR(254),"); - buf.append("remoteAddr VARCHAR(254),"); - buf.append("protocol VARCHAR(254),"); - buf.append("method VARCHAR(254),"); - buf.append("serverName VARCHAR(254),"); - buf.append("postContent VARCHAR(254),"); - buf.append("event_id INT NOT NULL IDENTITY);"); - query(conn, buf.toString()); - - buf = new StringBuffer(); - buf.append("CREATE TABLE access_event_header ("); - buf.append("event_id INT NOT NULL,"); - buf.append("header_key VARCHAR(254) NOT NULL,"); - buf.append("header_value LONGVARCHAR,"); - buf.append("PRIMARY KEY(event_id, header_key),"); - buf.append("FOREIGN KEY (event_id) REFERENCES access_event(event_id));"); - query(conn, buf.toString()); - } - - private void dropTables() throws SQLException { - Connection conn = newConnection(); - - StringBuffer buf = new StringBuffer(); - buf.append("DROP TABLE access_event_header IF EXISTS;"); - query(conn, buf.toString()); - - buf = new StringBuffer(); - buf.append("DROP TABLE access_event IF EXISTS;"); - query(conn, buf.toString()); - } - - private void query(Connection conn, String expression) throws SQLException { - Statement st = null; - st = conn.createStatement(); - - int i = st.executeUpdate(expression); - if (i == -1) { - System.out.println("db error : " + expression); - } - - st.close(); - } -} +/** + * 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.access.db; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; + +import org.hsqldb.Server; + +public class DBAppenderTestFixture { + + public static final String DRIVER_CLASS = "org.hsqldb.jdbcDriver"; + String serverProps; + String url; + String user = "sa"; + String password = ""; + Server server; + boolean isNetwork = true; + + + void setUp() throws SQLException { + if (isNetwork) { + if (url == null) { + url = "jdbc:hsqldb:hsql://localhost/test"; + } + + server = new Server(); + + server.setDatabaseName(0, "test"); + server.setDatabasePath(0, "mem:test;sql.enforce_strict_size=true"); + server.setLogWriter(null); + server.setErrWriter(null); + server.setTrace(false); + server.setSilent(true); + server.start(); + } else { + if (url == null) { + url = "jdbc:hsqldb:file:test;sql.enforce_strict_size=true"; + } + } + + try { + Class.forName(DRIVER_CLASS); + } catch (Exception e) { + e.printStackTrace(); + System.out.println(this + ".setUp() error: " + e.getMessage()); + } + Thread.yield(); + + createTables(); + } + + void tearDown() throws SQLException { + dropTables(); + if (isNetwork) { + server.stop(); + server = null; + } + } + + Connection newConnection() throws SQLException { + return DriverManager.getConnection(url, user, password); + } + + private void createTables() throws SQLException { + Connection conn = newConnection(); + StringBuffer buf = new StringBuffer(); + buf.append("CREATE TABLE access_event ("); + buf.append("timestmp BIGINT NOT NULL,"); + buf.append("requestURI VARCHAR(254),"); + buf.append("requestURL VARCHAR(254),"); + buf.append("remoteHost VARCHAR(254),"); + buf.append("remoteUser VARCHAR(254),"); + buf.append("remoteAddr VARCHAR(254),"); + buf.append("protocol VARCHAR(254),"); + buf.append("method VARCHAR(254),"); + buf.append("serverName VARCHAR(254),"); + buf.append("postContent VARCHAR(254),"); + buf.append("event_id INT NOT NULL IDENTITY);"); + query(conn, buf.toString()); + + buf = new StringBuffer(); + buf.append("CREATE TABLE access_event_header ("); + buf.append("event_id INT NOT NULL,"); + buf.append("header_key VARCHAR(254) NOT NULL,"); + buf.append("header_value LONGVARCHAR,"); + buf.append("PRIMARY KEY(event_id, header_key),"); + buf.append("FOREIGN KEY (event_id) REFERENCES access_event(event_id));"); + query(conn, buf.toString()); + } + + private void dropTables() throws SQLException { + Connection conn = newConnection(); + + StringBuffer buf = new StringBuffer(); + buf.append("DROP TABLE access_event_header IF EXISTS;"); + query(conn, buf.toString()); + + buf = new StringBuffer(); + buf.append("DROP TABLE access_event IF EXISTS;"); + query(conn, buf.toString()); + } + + private void query(Connection conn, String expression) throws SQLException { + Statement st = null; + st = conn.createStatement(); + + int i = st.executeUpdate(expression); + if (i == -1) { + System.out.println("db error : " + expression); + } + + st.close(); + } +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/db/PackageTest.java b/logback-access/src/test/java/ch/qos/logback/access/db/PackageTest.java index d1b772475985d751cb12dff199f689bf78dfdca1..1d7a5abac134a6016b8dd618336a42910ff94501 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/db/PackageTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/db/PackageTest.java @@ -1,26 +1,26 @@ -/** - * 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.access.db; - -import junit.framework.*; - -public class PackageTest extends TestCase { - - public static Test suite() { - TestSuite suite = new TestSuite(); - suite.addTest(new JUnit4TestAdapter(DBAppenderTest.class)); - suite.addTest(new JUnit4TestAdapter(DBAppenderIntegrationTest.class)); - return suite; - } +/** + * 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.access.db; + +import junit.framework.*; + +public class PackageTest extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite(); + suite.addTest(new JUnit4TestAdapter(DBAppenderTest.class)); + suite.addTest(new JUnit4TestAdapter(DBAppenderIntegrationTest.class)); + return suite; + } } \ No newline at end of file diff --git a/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyAccessEventBuilder.java b/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyAccessEventBuilder.java index 5ebcb4021fa1d76787f005785372174c8155141e..85595cf5430887b35b2262794985d0d09f8697f3 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyAccessEventBuilder.java +++ b/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyAccessEventBuilder.java @@ -1,30 +1,30 @@ -/** - * 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.access.dummy; - -import ch.qos.logback.access.spi.AccessEvent; - -public class DummyAccessEventBuilder { - - - static public AccessEvent buildNewAccessEvent() { - DummyRequest request = new DummyRequest(); - DummyResponse response = new DummyResponse(); - DummyServerAdapter adapter = new DummyServerAdapter(request, response); - - AccessEvent ae = new AccessEvent(request, response, adapter); - return ae; - } - -} +/** + * 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.access.dummy; + +import ch.qos.logback.access.spi.AccessEvent; + +public class DummyAccessEventBuilder { + + + static public AccessEvent buildNewAccessEvent() { + DummyRequest request = new DummyRequest(); + DummyResponse response = new DummyResponse(); + DummyServerAdapter adapter = new DummyServerAdapter(request, response); + + AccessEvent ae = new AccessEvent(request, response, adapter); + return ae; + } + +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyRequest.java b/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyRequest.java index 76353f35d201e6e870cdf6c912a2181c6d914368..9086fe14b1ae051ea8f4cb1f62d9c0fe6130b6a6 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyRequest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyRequest.java @@ -1,277 +1,277 @@ -/** - * 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.access.dummy; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.Principal; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Locale; -import java.util.Map; - -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletInputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import ch.qos.logback.access.AccessConstants; - -public class DummyRequest implements HttpServletRequest { - - public final static String DUMMY_CONTENT_STRING = "request contents"; - public final static byte[] DUMMY_CONTENT_BYTES = DUMMY_CONTENT_STRING.getBytes(); - - - public static final String DUMMY_RESPONSE_CONTENT_STRING = "response contents"; - public static final byte[] DUMMY_RESPONSE_CONTENT_BYTES =DUMMY_RESPONSE_CONTENT_STRING.getBytes(); - - Hashtable headerNames; - String uri; - - public DummyRequest() { - headerNames = new Hashtable(); - headerNames.put("headerName1", "headerValue1"); - headerNames.put("headerName2", "headerValue2"); - } - - public String getAuthType() { - return null; - } - - public String getContextPath() { - return null; - } - - public Cookie[] getCookies() { - Cookie cookie = new Cookie("testName", "testCookie"); - return new Cookie[] { cookie }; - } - - public long getDateHeader(String arg0) { - return 0; - } - - public String getHeader(String key) { - return headerNames.get(key); - } - - public Enumeration getHeaderNames() { - return headerNames.keys(); - } - - public Enumeration getHeaders(String arg0) { - return null; - } - - public int getIntHeader(String arg0) { - return 0; - } - - public String getMethod() { - return "testMethod"; - } - - public String getPathInfo() { - return null; - } - - public String getPathTranslated() { - return null; - } - - public String getQueryString() { - return null; - } - - public String getRemoteUser() { - return "testUser"; - } - - public String getRequestURI() { - return uri; - } - - public StringBuffer getRequestURL() { - return new StringBuffer(uri); - } - - public String getRequestedSessionId() { - return null; - } - - public String getServletPath() { - return null; - } - - public HttpSession getSession() { - return null; - } - - public HttpSession getSession(boolean arg0) { - return null; - } - - public Principal getUserPrincipal() { - return null; - } - - public boolean isRequestedSessionIdFromCookie() { - return false; - } - - public boolean isRequestedSessionIdFromURL() { - return false; - } - - public boolean isRequestedSessionIdFromUrl() { - return false; - } - - public boolean isRequestedSessionIdValid() { - return false; - } - - public boolean isUserInRole(String arg0) { - return false; - } - - public Object getAttribute(String key) { - if (key.equals("testKey")) { - return "testKey"; - } else if (AccessConstants.LB_INPUT_BUFFER.equals(key)) { - return DUMMY_CONTENT_BYTES; - } else if (AccessConstants.LB_OUTPUT_BUFFER.equals(key)) { - return DUMMY_RESPONSE_CONTENT_BYTES; - } else { - return null; - } - } - - public Enumeration getAttributeNames() { - return null; - } - - public String getCharacterEncoding() { - return null; - } - - public int getContentLength() { - return 0; - } - - public String getContentType() { - return null; - } - - public ServletInputStream getInputStream() throws IOException { - return null; - } - - public String getLocalAddr() { - return null; - } - - public String getLocalName() { - return null; - } - - public int getLocalPort() { - return 11; - } - - public Locale getLocale() { - return null; - } - - public Enumeration getLocales() { - return null; - } - - public String getParameter(String arg0) { - return null; - } - - public Map getParameterMap() { - return null; - } - - public Enumeration getParameterNames() { - return null; - } - - public String[] getParameterValues(String arg0) { - return null; - } - - public String getProtocol() { - return "testProtocol"; - } - - public BufferedReader getReader() throws IOException { - return null; - } - - public String getRealPath(String arg0) { - return null; - } - - public String getRemoteAddr() { - return "testRemoteAddress"; - } - - public String getRemoteHost() { - return "testHost"; - } - - public int getRemotePort() { - return 0; - } - - public RequestDispatcher getRequestDispatcher(String arg0) { - return null; - } - - public String getScheme() { - return null; - } - - public String getServerName() { - return "testServerName"; - } - - public int getServerPort() { - return 0; - } - - public boolean isSecure() { - return false; - } - - public void removeAttribute(String arg0) { - } - - public void setAttribute(String arg0, Object arg1) { - } - - public void setCharacterEncoding(String arg0) - throws UnsupportedEncodingException { - } - - public void setRequestUri(String uri) { - this.uri = uri; - } -} +/** + * 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.access.dummy; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletInputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import ch.qos.logback.access.AccessConstants; + +public class DummyRequest implements HttpServletRequest { + + public final static String DUMMY_CONTENT_STRING = "request contents"; + public final static byte[] DUMMY_CONTENT_BYTES = DUMMY_CONTENT_STRING.getBytes(); + + + public static final String DUMMY_RESPONSE_CONTENT_STRING = "response contents"; + public static final byte[] DUMMY_RESPONSE_CONTENT_BYTES =DUMMY_RESPONSE_CONTENT_STRING.getBytes(); + + Hashtable headerNames; + String uri; + + public DummyRequest() { + headerNames = new Hashtable(); + headerNames.put("headerName1", "headerValue1"); + headerNames.put("headerName2", "headerValue2"); + } + + public String getAuthType() { + return null; + } + + public String getContextPath() { + return null; + } + + public Cookie[] getCookies() { + Cookie cookie = new Cookie("testName", "testCookie"); + return new Cookie[] { cookie }; + } + + public long getDateHeader(String arg0) { + return 0; + } + + public String getHeader(String key) { + return headerNames.get(key); + } + + public Enumeration getHeaderNames() { + return headerNames.keys(); + } + + public Enumeration getHeaders(String arg0) { + return null; + } + + public int getIntHeader(String arg0) { + return 0; + } + + public String getMethod() { + return "testMethod"; + } + + public String getPathInfo() { + return null; + } + + public String getPathTranslated() { + return null; + } + + public String getQueryString() { + return null; + } + + public String getRemoteUser() { + return "testUser"; + } + + public String getRequestURI() { + return uri; + } + + public StringBuffer getRequestURL() { + return new StringBuffer(uri); + } + + public String getRequestedSessionId() { + return null; + } + + public String getServletPath() { + return null; + } + + public HttpSession getSession() { + return null; + } + + public HttpSession getSession(boolean arg0) { + return null; + } + + public Principal getUserPrincipal() { + return null; + } + + public boolean isRequestedSessionIdFromCookie() { + return false; + } + + public boolean isRequestedSessionIdFromURL() { + return false; + } + + public boolean isRequestedSessionIdFromUrl() { + return false; + } + + public boolean isRequestedSessionIdValid() { + return false; + } + + public boolean isUserInRole(String arg0) { + return false; + } + + public Object getAttribute(String key) { + if (key.equals("testKey")) { + return "testKey"; + } else if (AccessConstants.LB_INPUT_BUFFER.equals(key)) { + return DUMMY_CONTENT_BYTES; + } else if (AccessConstants.LB_OUTPUT_BUFFER.equals(key)) { + return DUMMY_RESPONSE_CONTENT_BYTES; + } else { + return null; + } + } + + public Enumeration getAttributeNames() { + return null; + } + + public String getCharacterEncoding() { + return null; + } + + public int getContentLength() { + return 0; + } + + public String getContentType() { + return null; + } + + public ServletInputStream getInputStream() throws IOException { + return null; + } + + public String getLocalAddr() { + return null; + } + + public String getLocalName() { + return null; + } + + public int getLocalPort() { + return 11; + } + + public Locale getLocale() { + return null; + } + + public Enumeration getLocales() { + return null; + } + + public String getParameter(String arg0) { + return null; + } + + public Map getParameterMap() { + return null; + } + + public Enumeration getParameterNames() { + return null; + } + + public String[] getParameterValues(String arg0) { + return null; + } + + public String getProtocol() { + return "testProtocol"; + } + + public BufferedReader getReader() throws IOException { + return null; + } + + public String getRealPath(String arg0) { + return null; + } + + public String getRemoteAddr() { + return "testRemoteAddress"; + } + + public String getRemoteHost() { + return "testHost"; + } + + public int getRemotePort() { + return 0; + } + + public RequestDispatcher getRequestDispatcher(String arg0) { + return null; + } + + public String getScheme() { + return null; + } + + public String getServerName() { + return "testServerName"; + } + + public int getServerPort() { + return 0; + } + + public boolean isSecure() { + return false; + } + + public void removeAttribute(String arg0) { + } + + public void setAttribute(String arg0, Object arg1) { + } + + public void setCharacterEncoding(String arg0) + throws UnsupportedEncodingException { + } + + public void setRequestUri(String uri) { + this.uri = uri; + } +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyResponse.java b/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyResponse.java index fa67980cf3bc117379cd6f506fe3a1150dff9eaa..f26effebfd912984f4491f5c485d1958d0a215d6 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyResponse.java +++ b/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyResponse.java @@ -1,165 +1,165 @@ -/** - * 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.access.dummy; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -public class DummyResponse implements HttpServletResponse { - - public static final int DUMMY_DEFAULT_STATUS = 200; - public static final int DUMMY_DEFAULT_CONTENT_COUNT = 1000; - public static final Map DUMMY_DEFAULT_HDEADER_MAP = new HashMap();; - - static { - DUMMY_DEFAULT_HDEADER_MAP.put("headerName1", "headerValue1"); - DUMMY_DEFAULT_HDEADER_MAP.put("headerName2", "headerValue2"); - } - - int status = DUMMY_DEFAULT_STATUS ; - public Map headerMap; - - public DummyResponse() { - headerMap = DUMMY_DEFAULT_HDEADER_MAP; - } - - public void addCookie(Cookie arg0) { - } - - public void addDateHeader(String arg0, long arg1) { - } - - public void addHeader(String arg0, String arg1) { - } - - public void addIntHeader(String arg0, int arg1) { - } - - public boolean containsHeader(String arg0) { - return false; - } - - public String encodeRedirectURL(String arg0) { - return null; - } - - public String encodeRedirectUrl(String arg0) { - return null; - } - - public String encodeURL(String arg0) { - return null; - } - - public String encodeUrl(String arg0) { - return null; - } - - public void sendError(int arg0) throws IOException { - } - - public void sendError(int arg0, String arg1) throws IOException { - } - - public void sendRedirect(String arg0) throws IOException { - } - - public void setDateHeader(String arg0, long arg1) { - } - - public void setHeader(String arg0, String arg1) { - } - - public void setIntHeader(String arg0, int arg1) { - } - - public void setStatus(int arg0, String arg1) { - } - - public void flushBuffer() throws IOException { - } - - public int getBufferSize() { - return 0; - } - - public String getCharacterEncoding() { - return null; - } - - public String getContentType() { - return null; - } - - public Locale getLocale() { - return null; - } - - public ServletOutputStream getOutputStream() throws IOException { - return null; - } - - public PrintWriter getWriter() throws IOException { - return null; - } - - public boolean isCommitted() { - return false; - } - - public void reset() { - } - - public void resetBuffer() { - } - - public void setBufferSize(int arg0) { - } - - public void setCharacterEncoding(String arg0) { - } - - public void setContentLength(int arg0) { - } - - public void setContentType(String arg0) { - } - - public void setLocale(Locale arg0) { - } - - public String getHeader(String key) { - return headerMap.get(key); - } - - public long getContentCount() { - return DUMMY_DEFAULT_CONTENT_COUNT; - } - - public int getStatus() { - return status; - } - - public void setStatus(int status) { - this.status = status; - } - -} +/** + * 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.access.dummy; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +public class DummyResponse implements HttpServletResponse { + + public static final int DUMMY_DEFAULT_STATUS = 200; + public static final int DUMMY_DEFAULT_CONTENT_COUNT = 1000; + public static final Map DUMMY_DEFAULT_HDEADER_MAP = new HashMap();; + + static { + DUMMY_DEFAULT_HDEADER_MAP.put("headerName1", "headerValue1"); + DUMMY_DEFAULT_HDEADER_MAP.put("headerName2", "headerValue2"); + } + + int status = DUMMY_DEFAULT_STATUS ; + public Map headerMap; + + public DummyResponse() { + headerMap = DUMMY_DEFAULT_HDEADER_MAP; + } + + public void addCookie(Cookie arg0) { + } + + public void addDateHeader(String arg0, long arg1) { + } + + public void addHeader(String arg0, String arg1) { + } + + public void addIntHeader(String arg0, int arg1) { + } + + public boolean containsHeader(String arg0) { + return false; + } + + public String encodeRedirectURL(String arg0) { + return null; + } + + public String encodeRedirectUrl(String arg0) { + return null; + } + + public String encodeURL(String arg0) { + return null; + } + + public String encodeUrl(String arg0) { + return null; + } + + public void sendError(int arg0) throws IOException { + } + + public void sendError(int arg0, String arg1) throws IOException { + } + + public void sendRedirect(String arg0) throws IOException { + } + + public void setDateHeader(String arg0, long arg1) { + } + + public void setHeader(String arg0, String arg1) { + } + + public void setIntHeader(String arg0, int arg1) { + } + + public void setStatus(int arg0, String arg1) { + } + + public void flushBuffer() throws IOException { + } + + public int getBufferSize() { + return 0; + } + + public String getCharacterEncoding() { + return null; + } + + public String getContentType() { + return null; + } + + public Locale getLocale() { + return null; + } + + public ServletOutputStream getOutputStream() throws IOException { + return null; + } + + public PrintWriter getWriter() throws IOException { + return null; + } + + public boolean isCommitted() { + return false; + } + + public void reset() { + } + + public void resetBuffer() { + } + + public void setBufferSize(int arg0) { + } + + public void setCharacterEncoding(String arg0) { + } + + public void setContentLength(int arg0) { + } + + public void setContentType(String arg0) { + } + + public void setLocale(Locale arg0) { + } + + public String getHeader(String key) { + return headerMap.get(key); + } + + public long getContentCount() { + return DUMMY_DEFAULT_CONTENT_COUNT; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyServerAdapter.java b/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyServerAdapter.java index b3c991241b9a36803977c9dc16e24d9d8f9822a1..b25d9b53b1da5f36f00b780f3a37ebb983454fd6 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyServerAdapter.java +++ b/logback-access/src/test/java/ch/qos/logback/access/dummy/DummyServerAdapter.java @@ -1,42 +1,42 @@ -/** - * 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.access.dummy; - -import java.util.Map; - -import ch.qos.logback.access.spi.ServerAdapter; - -public class DummyServerAdapter implements ServerAdapter { - - DummyRequest request; - DummyResponse response; - - public DummyServerAdapter(DummyRequest dummyRequest, DummyResponse dummyResponse) { - this.request = dummyRequest; - this.response = dummyResponse; - } - - public long getContentLength() { - return response.getContentCount(); - } - - public int getStatusCode() { - return response.getStatus(); - } - - public Map buildResponseHeaderMap() { - return response.headerMap; - } - -} +/** + * 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.access.dummy; + +import java.util.Map; + +import ch.qos.logback.access.spi.ServerAdapter; + +public class DummyServerAdapter implements ServerAdapter { + + DummyRequest request; + DummyResponse response; + + public DummyServerAdapter(DummyRequest dummyRequest, DummyResponse dummyResponse) { + this.request = dummyRequest; + this.response = dummyResponse; + } + + public long getContentLength() { + return response.getContentCount(); + } + + public int getStatusCode() { + return response.getStatus(); + } + + public Map buildResponseHeaderMap() { + return response.headerMap; + } + +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java b/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java index 5536ae3af12b448b1bf1497e7cdec3bfb3901016..fec5c5c28e9b5c01899459f7807fe103038a8e32 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java @@ -1,25 +1,25 @@ -/** - * 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.access.filter; - -import junit.framework.TestCase; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({StatsByDayTest.class}) -public class PackageTest extends TestCase { +/** + * 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.access.filter; + +import junit.framework.TestCase; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({StatsByDayTest.class}) +public class PackageTest extends TestCase { } \ No newline at end of file diff --git a/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java b/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java index d90bb76b19c489c5203a2e613c0de763b99a8e21..d3b2025ccd8dcf33cadc9669eaf20b03f8a65b0f 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java @@ -1,76 +1,76 @@ -/** - * 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.access.filter; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import ch.qos.logback.core.util.TimeUtil; - -public class StatsByDayTest { - - @Test - public void testBasic() { - // Tue Nov 21 18:05:36 CET 2006 - long now = 1164128736369L; - StatsByDay statsByDay = new StatsByDay(now); - - int total = 0; - // test fresh start - statsByDay.update(now, 0); - assertEquals(0, statsByDay.getLastCount()); - assertEquals(0, statsByDay.getAverage(), 0.01); - - total++; - statsByDay.update(now, total); - assertEquals(0, statsByDay.getLastCount()); - assertEquals(0.0, statsByDay.getAverage(), 0.01); - - long nextDay0 = TimeUtil.computeStartOfNextDay(now); - nextDay0 += 99; - - // there should be one event the next day, avg should also be 1 - statsByDay.update(nextDay0, total); - assertEquals(1.0, statsByDay.getLastCount(), 0.01); - assertEquals(1.0, statsByDay.getAverage(), 0.01); - - total += 2; - - statsByDay.update(nextDay0, total); - assertEquals(1, statsByDay.getLastCount()); - assertEquals(1.0, statsByDay.getAverage(), 0.01); - - long nextDay1 = TimeUtil.computeStartOfNextDay(nextDay0) + 6747; - statsByDay.update(nextDay1, total); - assertEquals(2, statsByDay.getLastCount()); - assertEquals(1.5, statsByDay.getAverage(), 0.01); - - nextDay1 += 4444; - total += 4; - - statsByDay.update(nextDay1, total); - // values should remain unchanged - assertEquals(2, statsByDay.getLastCount()); - assertEquals(1.5, statsByDay.getAverage(), 0.01); - - long nextDay2 = TimeUtil.computeStartOfNextDay(nextDay1) + 11177; - - statsByDay.update(nextDay2, total); - // values should remain unchanged - assertEquals(4, statsByDay.getLastCount()); - assertEquals(7.0 / 3, statsByDay.getAverage(), 0.01); - } - -} +/** + * 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.access.filter; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import ch.qos.logback.core.util.TimeUtil; + +public class StatsByDayTest { + + @Test + public void testBasic() { + // Tue Nov 21 18:05:36 CET 2006 + long now = 1164128736369L; + StatsByDay statsByDay = new StatsByDay(now); + + int total = 0; + // test fresh start + statsByDay.update(now, 0); + assertEquals(0, statsByDay.getLastCount()); + assertEquals(0, statsByDay.getAverage(), 0.01); + + total++; + statsByDay.update(now, total); + assertEquals(0, statsByDay.getLastCount()); + assertEquals(0.0, statsByDay.getAverage(), 0.01); + + long nextDay0 = TimeUtil.computeStartOfNextDay(now); + nextDay0 += 99; + + // there should be one event the next day, avg should also be 1 + statsByDay.update(nextDay0, total); + assertEquals(1.0, statsByDay.getLastCount(), 0.01); + assertEquals(1.0, statsByDay.getAverage(), 0.01); + + total += 2; + + statsByDay.update(nextDay0, total); + assertEquals(1, statsByDay.getLastCount()); + assertEquals(1.0, statsByDay.getAverage(), 0.01); + + long nextDay1 = TimeUtil.computeStartOfNextDay(nextDay0) + 6747; + statsByDay.update(nextDay1, total); + assertEquals(2, statsByDay.getLastCount()); + assertEquals(1.5, statsByDay.getAverage(), 0.01); + + nextDay1 += 4444; + total += 4; + + statsByDay.update(nextDay1, total); + // values should remain unchanged + assertEquals(2, statsByDay.getLastCount()); + assertEquals(1.5, statsByDay.getAverage(), 0.01); + + long nextDay2 = TimeUtil.computeStartOfNextDay(nextDay1) + 11177; + + statsByDay.update(nextDay2, total); + // values should remain unchanged + assertEquals(4, statsByDay.getLastCount()); + assertEquals(7.0 / 3, statsByDay.getAverage(), 0.01); + } + +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyBasicTest.java b/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyBasicTest.java index ef779a766867739ec76d82d19f443a033a9e9e1e..805db069a46bbcd601e2a9b410074b20295f4102 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyBasicTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyBasicTest.java @@ -1,130 +1,130 @@ -/** - * 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.access.jetty; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.net.HttpURLConnection; -import java.net.URL; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.access.spi.Util; -import ch.qos.logback.access.testUtil.NotifyingListAppender; -import ch.qos.logback.core.testUtil.RandomUtil; - -public class JettyBasicTest { - - static RequestLogImpl REQYEST_LOG_IMPL; - static JettyFixture JETTY_FIXTURE; - - static int RANDOM_SERVER_PORT = RandomUtil.getRandomServerPort(); - - @BeforeClass - static public void startServer() throws Exception { - // System.out.println("*** JettyBasicTest.startServer called"); - REQYEST_LOG_IMPL = new RequestLogImpl(); - JETTY_FIXTURE = new JettyFixture(REQYEST_LOG_IMPL, RANDOM_SERVER_PORT); - JETTY_FIXTURE.start(); - } - - @AfterClass - static public void stopServer() throws Exception { - // System.out.println("*** JettyBasicTest.stopServer called"); - if (JETTY_FIXTURE != null) { - JETTY_FIXTURE.stop(); - } - } - - @Test - public void getRequest() throws Exception { - URL url = new URL("http://localhost:" + RANDOM_SERVER_PORT + "/"); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setDoInput(true); - - String result = Util.readToString(connection.getInputStream()); - - assertEquals("hello world", result); - - NotifyingListAppender listAppender = (NotifyingListAppender) REQYEST_LOG_IMPL - .getAppender("list"); - listAppender.list.clear(); - } - - @Test - public void eventGoesToAppenders() throws Exception { - URL url = new URL(JETTY_FIXTURE.getUrl()); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setDoInput(true); - - String result = Util.readToString(connection.getInputStream()); - - assertEquals("hello world", result); - - NotifyingListAppender listAppender = (NotifyingListAppender) REQYEST_LOG_IMPL - .getAppender("list"); - synchronized (listAppender) { - listAppender.wait(100); - } - - assertTrue(listAppender.list.size() > 0); - AccessEvent event = (AccessEvent) listAppender.list.get(0); - assertEquals("127.0.0.1", event.getRemoteHost()); - assertEquals("localhost", event.getServerName()); - listAppender.list.clear(); - } - - @Test - public void postContentConverter() throws Exception { - URL url = new URL(JETTY_FIXTURE.getUrl()); - String msg = "test message"; - - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - // this line is necessary to make the stream aware of when the message is - // over. - connection.setFixedLengthStreamingMode(msg.getBytes().length); - ((HttpURLConnection) connection).setRequestMethod("POST"); - connection.setDoOutput(true); - connection.setDoInput(true); - connection.setUseCaches(false); - connection.setRequestProperty("Content-Type", "text/plain"); - - PrintWriter output = new PrintWriter(new OutputStreamWriter(connection - .getOutputStream())); - output.print(msg); - output.flush(); - output.close(); - - // StatusPrinter.print(requestLogImpl.getStatusManager()); - - NotifyingListAppender listAppender = (NotifyingListAppender) REQYEST_LOG_IMPL - .getAppender("list"); - - synchronized (listAppender) { - listAppender.wait(100); - } - - @SuppressWarnings("unused") - AccessEvent event = (AccessEvent) listAppender.list.get(0); - - // we should test the contents of the requests - // assertEquals(msg, event.getRequestContent()); - } -} +/** + * 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.access.jetty; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.access.spi.Util; +import ch.qos.logback.access.testUtil.NotifyingListAppender; +import ch.qos.logback.core.testUtil.RandomUtil; + +public class JettyBasicTest { + + static RequestLogImpl REQYEST_LOG_IMPL; + static JettyFixture JETTY_FIXTURE; + + static int RANDOM_SERVER_PORT = RandomUtil.getRandomServerPort(); + + @BeforeClass + static public void startServer() throws Exception { + // System.out.println("*** JettyBasicTest.startServer called"); + REQYEST_LOG_IMPL = new RequestLogImpl(); + JETTY_FIXTURE = new JettyFixture(REQYEST_LOG_IMPL, RANDOM_SERVER_PORT); + JETTY_FIXTURE.start(); + } + + @AfterClass + static public void stopServer() throws Exception { + // System.out.println("*** JettyBasicTest.stopServer called"); + if (JETTY_FIXTURE != null) { + JETTY_FIXTURE.stop(); + } + } + + @Test + public void getRequest() throws Exception { + URL url = new URL("http://localhost:" + RANDOM_SERVER_PORT + "/"); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + + String result = Util.readToString(connection.getInputStream()); + + assertEquals("hello world", result); + + NotifyingListAppender listAppender = (NotifyingListAppender) REQYEST_LOG_IMPL + .getAppender("list"); + listAppender.list.clear(); + } + + @Test + public void eventGoesToAppenders() throws Exception { + URL url = new URL(JETTY_FIXTURE.getUrl()); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + + String result = Util.readToString(connection.getInputStream()); + + assertEquals("hello world", result); + + NotifyingListAppender listAppender = (NotifyingListAppender) REQYEST_LOG_IMPL + .getAppender("list"); + synchronized (listAppender) { + listAppender.wait(100); + } + + assertTrue(listAppender.list.size() > 0); + AccessEvent event = (AccessEvent) listAppender.list.get(0); + assertEquals("127.0.0.1", event.getRemoteHost()); + assertEquals("localhost", event.getServerName()); + listAppender.list.clear(); + } + + @Test + public void postContentConverter() throws Exception { + URL url = new URL(JETTY_FIXTURE.getUrl()); + String msg = "test message"; + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + // this line is necessary to make the stream aware of when the message is + // over. + connection.setFixedLengthStreamingMode(msg.getBytes().length); + ((HttpURLConnection) connection).setRequestMethod("POST"); + connection.setDoOutput(true); + connection.setDoInput(true); + connection.setUseCaches(false); + connection.setRequestProperty("Content-Type", "text/plain"); + + PrintWriter output = new PrintWriter(new OutputStreamWriter(connection + .getOutputStream())); + output.print(msg); + output.flush(); + output.close(); + + // StatusPrinter.print(requestLogImpl.getStatusManager()); + + NotifyingListAppender listAppender = (NotifyingListAppender) REQYEST_LOG_IMPL + .getAppender("list"); + + synchronized (listAppender) { + listAppender.wait(100); + } + + @SuppressWarnings("unused") + AccessEvent event = (AccessEvent) listAppender.list.get(0); + + // we should test the contents of the requests + // assertEquals(msg, event.getRequestContent()); + } +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java b/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java index a93c5e4377de3dfa3486872420c79c8cc64ed814..d6f10bd300d2b8cc910ba5c668bfd44080bd911a 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java +++ b/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java @@ -1,101 +1,101 @@ -/** - * 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.access.jetty; - -import java.io.IOException; -import java.io.OutputStream; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.mortbay.jetty.Handler; -import org.mortbay.jetty.HttpConnection; -import org.mortbay.jetty.Request; -import org.mortbay.jetty.handler.AbstractHandler; -import org.mortbay.util.ByteArrayISO8859Writer; - -import ch.qos.logback.access.PatternLayout; -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.access.testUtil.NotifyingListAppender; -import ch.qos.logback.core.ConsoleAppender; - -public class JettyFixture extends JettyFixtureBase { - - Handler handler = new BasicHandler(); - - public JettyFixture(RequestLogImpl impl, int port) { - super(impl, port); - url = "http://localhost:" + port + "/"; - } - - public void start() throws Exception { - super.start(); - Thread.yield(); - } - - public void stop() throws Exception { - super.stop(); - Thread.sleep(500); - } - - protected void buildContext() { - NotifyingListAppender appender = new NotifyingListAppender(); - appender.setContext(requestLogImpl); - appender.setName("list"); - appender.start(); - - ConsoleAppender console = new ConsoleAppender(); - console.setContext(requestLogImpl); - console.setName("console"); - PatternLayout layout = new PatternLayout(); - layout.setContext(requestLogImpl); - layout.setPattern("%date %server %clientHost"); - console.setLayout(layout); - layout.start(); - console.start(); - - requestLogImpl.addAppender(appender); - requestLogImpl.addAppender(console); - } - - @Override - protected Handler getHandler() { - return handler; - } - -} - -class BasicHandler extends AbstractHandler { - public void handle(String target, HttpServletRequest request, - HttpServletResponse response, int dispatch) throws IOException, - ServletException { - - // String requestContent = Util.readToString(request.getInputStream()); - // System.out.println("request content: " + requestContent); - - OutputStream out = response.getOutputStream(); - ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(); - writer.write("hello world"); - writer.flush(); - response.setContentLength(writer.size()); - writer.writeTo(out); - out.flush(); - - Request base_request = (request instanceof Request) ? (Request) request - : HttpConnection.getCurrentConnection().getRequest(); - base_request.setHandled(true); - - } +/** + * 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.access.jetty; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.mortbay.jetty.Handler; +import org.mortbay.jetty.HttpConnection; +import org.mortbay.jetty.Request; +import org.mortbay.jetty.handler.AbstractHandler; +import org.mortbay.util.ByteArrayISO8859Writer; + +import ch.qos.logback.access.PatternLayout; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.access.testUtil.NotifyingListAppender; +import ch.qos.logback.core.ConsoleAppender; + +public class JettyFixture extends JettyFixtureBase { + + Handler handler = new BasicHandler(); + + public JettyFixture(RequestLogImpl impl, int port) { + super(impl, port); + url = "http://localhost:" + port + "/"; + } + + public void start() throws Exception { + super.start(); + Thread.yield(); + } + + public void stop() throws Exception { + super.stop(); + Thread.sleep(500); + } + + protected void buildContext() { + NotifyingListAppender appender = new NotifyingListAppender(); + appender.setContext(requestLogImpl); + appender.setName("list"); + appender.start(); + + ConsoleAppender console = new ConsoleAppender(); + console.setContext(requestLogImpl); + console.setName("console"); + PatternLayout layout = new PatternLayout(); + layout.setContext(requestLogImpl); + layout.setPattern("%date %server %clientHost"); + console.setLayout(layout); + layout.start(); + console.start(); + + requestLogImpl.addAppender(appender); + requestLogImpl.addAppender(console); + } + + @Override + protected Handler getHandler() { + return handler; + } + +} + +class BasicHandler extends AbstractHandler { + public void handle(String target, HttpServletRequest request, + HttpServletResponse response, int dispatch) throws IOException, + ServletException { + + // String requestContent = Util.readToString(request.getInputStream()); + // System.out.println("request content: " + requestContent); + + OutputStream out = response.getOutputStream(); + ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(); + writer.write("hello world"); + writer.flush(); + response.setContentLength(writer.size()); + writer.writeTo(out); + out.flush(); + + Request base_request = (request instanceof Request) ? (Request) request + : HttpConnection.getCurrentConnection().getRequest(); + base_request.setHandled(true); + + } } \ No newline at end of file diff --git a/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixtureBase.java b/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixtureBase.java index f441f50c28f3c8e93dc95aec6ddd14ee95c28c0a..47dc6f9213ad7ae077eddbea5a91d596e91dff3d 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixtureBase.java +++ b/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixtureBase.java @@ -1,76 +1,76 @@ -/** - * 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.access.jetty; - -import org.mortbay.jetty.Connector; -import org.mortbay.jetty.Handler; -import org.mortbay.jetty.Server; -import org.mortbay.jetty.handler.ContextHandler; -import org.mortbay.jetty.handler.RequestLogHandler; -import org.mortbay.jetty.nio.SelectChannelConnector; - -abstract public class JettyFixtureBase { - protected RequestLogImpl requestLogImpl; - - private final int port; - Server server; - String url; - - public JettyFixtureBase(RequestLogImpl impl, int port) { - requestLogImpl = impl; - this.port = port; - url = "http://localhost:" + port + "/"; - } - - public String getName() { - return "Jetty Test Setup"; - } - - public String getUrl() { - return url; - } - - public void start() throws Exception { - server = new Server(); - Connector connector = new SelectChannelConnector(); - connector.setPort(port); - server.setConnectors(new Connector[] { connector }); - - ContextHandler context = new ContextHandler(); - context.setContextPath("/"); - context.setResourceBase("."); - context.setClassLoader(Thread.currentThread().getContextClassLoader()); - server.addHandler(context); - - RequestLogHandler requestLogHandler = new RequestLogHandler(); - buildContext(); - requestLogHandler.setRequestLog(requestLogImpl); - server.addHandler(requestLogHandler); - - Handler handler = getHandler(); - context.addHandler(handler); - - server.start(); - } - - public void stop() throws Exception { - // System.out.println("into tearDown"); - server.stop(); - server = null; - requestLogImpl = null; - } - - abstract protected void buildContext(); - abstract protected Handler getHandler(); -} +/** + * 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.access.jetty; + +import org.mortbay.jetty.Connector; +import org.mortbay.jetty.Handler; +import org.mortbay.jetty.Server; +import org.mortbay.jetty.handler.ContextHandler; +import org.mortbay.jetty.handler.RequestLogHandler; +import org.mortbay.jetty.nio.SelectChannelConnector; + +abstract public class JettyFixtureBase { + protected RequestLogImpl requestLogImpl; + + private final int port; + Server server; + String url; + + public JettyFixtureBase(RequestLogImpl impl, int port) { + requestLogImpl = impl; + this.port = port; + url = "http://localhost:" + port + "/"; + } + + public String getName() { + return "Jetty Test Setup"; + } + + public String getUrl() { + return url; + } + + public void start() throws Exception { + server = new Server(); + Connector connector = new SelectChannelConnector(); + connector.setPort(port); + server.setConnectors(new Connector[] { connector }); + + ContextHandler context = new ContextHandler(); + context.setContextPath("/"); + context.setResourceBase("."); + context.setClassLoader(Thread.currentThread().getContextClassLoader()); + server.addHandler(context); + + RequestLogHandler requestLogHandler = new RequestLogHandler(); + buildContext(); + requestLogHandler.setRequestLog(requestLogImpl); + server.addHandler(requestLogHandler); + + Handler handler = getHandler(); + context.addHandler(handler); + + server.start(); + } + + public void stop() throws Exception { + // System.out.println("into tearDown"); + server.stop(); + server = null; + requestLogImpl = null; + } + + abstract protected void buildContext(); + abstract protected Handler getHandler(); +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java b/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java index 800f98ae55e2743071398087269388c8ec0cbf8b..5b1f018c5d7aeccf74ab7628a152baa328ec7f25 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java @@ -1,24 +1,24 @@ -/** - * 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.access.jetty; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({JettyBasicTest.class}) -public class PackageTest { - +/** + * 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.access.jetty; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({JettyBasicTest.class}) +public class PackageTest { + } \ No newline at end of file diff --git a/logback-access/src/test/java/ch/qos/logback/access/joran/JoranConfiguratorTest.java b/logback-access/src/test/java/ch/qos/logback/access/joran/JoranConfiguratorTest.java index 71e8c04a44c0082001691dd512a45af8a7e18251..c24d18be8e9e397975eeba173542b13287b91c68 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/joran/JoranConfiguratorTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/joran/JoranConfiguratorTest.java @@ -1,77 +1,77 @@ -/** - * 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.access.joran; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.access.TeztConstants; -import ch.qos.logback.access.dummy.DummyAccessEventBuilder; -import ch.qos.logback.access.spi.AccessContext; -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.read.ListAppender; -import ch.qos.logback.core.testUtil.StringListAppender; - -public class JoranConfiguratorTest { - - AccessContext context = new AccessContext(); - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - void configure(String file) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(context); - jc.doConfigure(file); - } - - @Test - public void smoke() throws Exception { - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/smoke.xml"); - - ListAppender listAppender = (ListAppender) context - .getAppender("LIST"); - AccessEvent event = DummyAccessEventBuilder.buildNewAccessEvent(); - listAppender.doAppend(event); - - assertEquals(1, listAppender.list.size()); - - assertEquals(1, listAppender.list.size()); - AccessEvent ae = (AccessEvent) listAppender.list.get(0); - assertNotNull(ae); - } - - @Test - public void defaultLayout() throws Exception { - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/defaultLayout.xml"); - StringListAppender listAppender = (StringListAppender) context - .getAppender("STR_LIST"); - AccessEvent event = DummyAccessEventBuilder.buildNewAccessEvent(); - listAppender.doAppend(event); - assertEquals(1, listAppender.strList.size()); - // the result contains a line separator at the end - assertTrue(listAppender.strList.get(0).startsWith("testMethod")); - } -} +/** + * 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.access.joran; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.access.TeztConstants; +import ch.qos.logback.access.dummy.DummyAccessEventBuilder; +import ch.qos.logback.access.spi.AccessContext; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.read.ListAppender; +import ch.qos.logback.core.testUtil.StringListAppender; + +public class JoranConfiguratorTest { + + AccessContext context = new AccessContext(); + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + void configure(String file) throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(context); + jc.doConfigure(file); + } + + @Test + public void smoke() throws Exception { + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/smoke.xml"); + + ListAppender listAppender = (ListAppender) context + .getAppender("LIST"); + AccessEvent event = DummyAccessEventBuilder.buildNewAccessEvent(); + listAppender.doAppend(event); + + assertEquals(1, listAppender.list.size()); + + assertEquals(1, listAppender.list.size()); + AccessEvent ae = (AccessEvent) listAppender.list.get(0); + assertNotNull(ae); + } + + @Test + public void defaultLayout() throws Exception { + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/defaultLayout.xml"); + StringListAppender listAppender = (StringListAppender) context + .getAppender("STR_LIST"); + AccessEvent event = DummyAccessEventBuilder.buildNewAccessEvent(); + listAppender.doAppend(event); + assertEquals(1, listAppender.strList.size()); + // the result contains a line separator at the end + assertTrue(listAppender.strList.get(0).startsWith("testMethod")); + } +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/net/MockSocketServer.java b/logback-access/src/test/java/ch/qos/logback/access/net/MockSocketServer.java index dc48676354512bc9613c4a2fc6ea88bf00d5f0a1..b6cfee8baf739d2087f96438a321fd6ee4b8444e 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/net/MockSocketServer.java +++ b/logback-access/src/test/java/ch/qos/logback/access/net/MockSocketServer.java @@ -1,77 +1,77 @@ -/** - * 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.access.net; - -import java.io.BufferedInputStream; -import java.io.ObjectInputStream; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.access.spi.AccessEvent; - - -/** - * @author Sébastien Pennec - */ -public class MockSocketServer extends Thread { - - static final int PORT = 4560; - - final int loopLen; - - List accessEventList = new ArrayList(); - boolean finished = false; - - MockSocketServer(int loopLen) { - super(); - this.loopLen = loopLen; - } - - @Override - public void run() { - ObjectInputStream ois = null; - ServerSocket serverSocket = null; - // Object readObject; - AccessEvent event; - try { - serverSocket = new ServerSocket(PORT); - Socket socket = serverSocket.accept(); - ois = new ObjectInputStream(new BufferedInputStream(socket - .getInputStream())); - for (int i = 0; i < loopLen; i++) { - event = (AccessEvent) ois.readObject(); - accessEventList.add(event); - } - } catch (Exception se) { - se.printStackTrace(); - } finally { - - if (ois != null) { - try { - ois.close(); - } catch (Exception e) { - } - } - if (serverSocket != null) { - try { - serverSocket.close(); - } catch (Exception e) { - } - } - } - finished = true; - } -} +/** + * 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.access.net; + +import java.io.BufferedInputStream; +import java.io.ObjectInputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.access.spi.AccessEvent; + + +/** + * @author Sébastien Pennec + */ +public class MockSocketServer extends Thread { + + static final int PORT = 4560; + + final int loopLen; + + List accessEventList = new ArrayList(); + boolean finished = false; + + MockSocketServer(int loopLen) { + super(); + this.loopLen = loopLen; + } + + @Override + public void run() { + ObjectInputStream ois = null; + ServerSocket serverSocket = null; + // Object readObject; + AccessEvent event; + try { + serverSocket = new ServerSocket(PORT); + Socket socket = serverSocket.accept(); + ois = new ObjectInputStream(new BufferedInputStream(socket + .getInputStream())); + for (int i = 0; i < loopLen; i++) { + event = (AccessEvent) ois.readObject(); + accessEventList.add(event); + } + } catch (Exception se) { + se.printStackTrace(); + } finally { + + if (ois != null) { + try { + ois.close(); + } catch (Exception e) { + } + } + if (serverSocket != null) { + try { + serverSocket.close(); + } catch (Exception e) { + } + } + } + finished = true; + } +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/net/NOPOutputStream.java b/logback-access/src/test/java/ch/qos/logback/access/net/NOPOutputStream.java index d74bcc667e97f4c8dfcd9293ffe643f1de4d31a1..0964530dc73750afe1546d9a6597c14808260bbd 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/net/NOPOutputStream.java +++ b/logback-access/src/test/java/ch/qos/logback/access/net/NOPOutputStream.java @@ -1,27 +1,27 @@ -/** - * 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.access.net; - -import java.io.IOException; -import java.io.OutputStream; - -public class NOPOutputStream extends OutputStream { - - @Override - public void write(int b) throws IOException { - // do nothing - - } - -} +/** + * 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.access.net; + +import java.io.IOException; +import java.io.OutputStream; + +public class NOPOutputStream extends OutputStream { + + @Override + public void write(int b) throws IOException { + // do nothing + + } + +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java b/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java index 018c4b30cfc66995c0024b19246df1ef11231c9b..fe172d08c2a80aed9c7a1bdc5af4e0c34bb08a19 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java @@ -1,25 +1,25 @@ -/** - * 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.access.net; - -import junit.framework.TestCase; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({URLEvaluatorTest.class, SocketAppenderTest.class}) -public class PackageTest extends TestCase { +/** + * 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.access.net; + +import junit.framework.TestCase; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({URLEvaluatorTest.class, SocketAppenderTest.class}) +public class PackageTest extends TestCase { } \ No newline at end of file diff --git a/logback-access/src/test/java/ch/qos/logback/access/net/SerializationPerfTest.java b/logback-access/src/test/java/ch/qos/logback/access/net/SerializationPerfTest.java index 9742a9217db61674f578eca9a804f7e32ec03e73..918b1f4926684599db2bc32028a4e64493966028 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/net/SerializationPerfTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/net/SerializationPerfTest.java @@ -1,108 +1,108 @@ -/** - * 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.access.net; - -import java.io.IOException; -import java.io.ObjectOutputStream; - -import junit.framework.TestCase; -import ch.qos.logback.access.dummy.DummyAccessEventBuilder; -import ch.qos.logback.access.spi.AccessEvent; - -public class SerializationPerfTest extends TestCase { - - ObjectOutputStream oos; - - int loopNumber = 10000; - int resetFrequency = 100; - int pauseFrequency = 10; - long pauseLengthInMillis = 20; - - - public void setUp() throws Exception { - super.setUp(); - oos = new ObjectOutputStream(new NOPOutputStream()); - - } - - public void tearDown() throws Exception { - super.tearDown(); - oos.close(); - oos = null; - } - - public void test1() throws Exception { - // first run for just in time compiler - int resetCounter = 0; - int pauseCounter = 0; - for (int i = 0; i < loopNumber; i++) { - try { - AccessEvent ae = DummyAccessEventBuilder.buildNewAccessEvent(); - //average time for the next method: 5000 nanos - ae.prepareForDeferredProcessing(); - oos.writeObject(ae); - oos.flush(); - if (++resetCounter >= resetFrequency) { - oos.reset(); - resetCounter = 0; - } - if (++pauseCounter >= pauseFrequency) { - Thread.sleep(pauseLengthInMillis); - pauseCounter = 0; - } - - } catch (IOException ex) { - fail(ex.getMessage()); - } - } - - // second run - Long t1; - Long t2; - Long total = 0L; - resetCounter = 0; - pauseCounter = 0; - // System.out.println("Beginning mesured run"); - for (int i = 0; i < loopNumber; i++) { - try { - AccessEvent ae = DummyAccessEventBuilder.buildNewAccessEvent(); - t1 = System.nanoTime(); - //average length of the next method: 4000 nanos - ae.prepareForDeferredProcessing(); - oos.writeObject(ae); - oos.flush(); - t2 = System.nanoTime(); - total += (t2 - t1); - if (++resetCounter >= resetFrequency) { - oos.reset(); - resetCounter = 0; - } - if (++pauseCounter >= pauseFrequency) { - Thread.sleep(pauseLengthInMillis); - pauseCounter = 0; - } - } catch (IOException ex) { - fail(ex.getMessage()); - } - } - - total /= (1000);//nanos -> micros - System.out.println("Loop done : average time = " + total / loopNumber - + " microsecs after " + loopNumber + " writes."); - //average time: 26-30 microsec = 0.030 millis - } - - - -} +/** + * 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.access.net; + +import java.io.IOException; +import java.io.ObjectOutputStream; + +import junit.framework.TestCase; +import ch.qos.logback.access.dummy.DummyAccessEventBuilder; +import ch.qos.logback.access.spi.AccessEvent; + +public class SerializationPerfTest extends TestCase { + + ObjectOutputStream oos; + + int loopNumber = 10000; + int resetFrequency = 100; + int pauseFrequency = 10; + long pauseLengthInMillis = 20; + + + public void setUp() throws Exception { + super.setUp(); + oos = new ObjectOutputStream(new NOPOutputStream()); + + } + + public void tearDown() throws Exception { + super.tearDown(); + oos.close(); + oos = null; + } + + public void test1() throws Exception { + // first run for just in time compiler + int resetCounter = 0; + int pauseCounter = 0; + for (int i = 0; i < loopNumber; i++) { + try { + AccessEvent ae = DummyAccessEventBuilder.buildNewAccessEvent(); + //average time for the next method: 5000 nanos + ae.prepareForDeferredProcessing(); + oos.writeObject(ae); + oos.flush(); + if (++resetCounter >= resetFrequency) { + oos.reset(); + resetCounter = 0; + } + if (++pauseCounter >= pauseFrequency) { + Thread.sleep(pauseLengthInMillis); + pauseCounter = 0; + } + + } catch (IOException ex) { + fail(ex.getMessage()); + } + } + + // second run + Long t1; + Long t2; + Long total = 0L; + resetCounter = 0; + pauseCounter = 0; + // System.out.println("Beginning mesured run"); + for (int i = 0; i < loopNumber; i++) { + try { + AccessEvent ae = DummyAccessEventBuilder.buildNewAccessEvent(); + t1 = System.nanoTime(); + //average length of the next method: 4000 nanos + ae.prepareForDeferredProcessing(); + oos.writeObject(ae); + oos.flush(); + t2 = System.nanoTime(); + total += (t2 - t1); + if (++resetCounter >= resetFrequency) { + oos.reset(); + resetCounter = 0; + } + if (++pauseCounter >= pauseFrequency) { + Thread.sleep(pauseLengthInMillis); + pauseCounter = 0; + } + } catch (IOException ex) { + fail(ex.getMessage()); + } + } + + total /= (1000);//nanos -> micros + System.out.println("Loop done : average time = " + total / loopNumber + + " microsecs after " + loopNumber + " writes."); + //average time: 26-30 microsec = 0.030 millis + } + + + +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java b/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java index 4db1925b6c606e07396e28eadc0dff8b4835c312..f9e7bfdaa0ba0783777ba329dcdf42c51eca3ea0 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java @@ -1,89 +1,89 @@ -/** - * 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.access.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -import ch.qos.logback.access.dummy.DummyRequest; -import ch.qos.logback.access.dummy.DummyResponse; -import ch.qos.logback.access.dummy.DummyServerAdapter; -import ch.qos.logback.access.spi.AccessContext; -import ch.qos.logback.access.spi.AccessEvent; - - -public class SocketAppenderTest { - - private AccessContext context; - private MockSocketServer mockSocketServer; - - @Test - public void testStartFailNoRemoteHost() { - context = new AccessContext(); - SocketAppender appender = new SocketAppender(); - appender.setContext(context); - appender.setPort(123); - appender.start(); - assertEquals(1, context.getStatusManager().getCount()); - } - - @Test - public void testRecieveMessage() throws InterruptedException { - startServer(1); - configureClient(); - - context.callAppenders(buildNewAccessEvent()); - // Wait max 2 seconds for mock server to finish. However, it should - // finish much sooner than that. - mockSocketServer.join(2000); - assertTrue(mockSocketServer.finished); - assertEquals(1, mockSocketServer.accessEventList.size()); - - AccessEvent remoteEvent = mockSocketServer.accessEventList.get(0); - //check that the values are available although the request and response - //objects did not survive serialization - assertEquals("headerValue1", remoteEvent.getRequestHeader("headerName1")); - assertEquals("testHost", remoteEvent.getRemoteHost()); - } - - private void startServer(int expectedEventNumber) throws InterruptedException { - mockSocketServer = new MockSocketServer(expectedEventNumber); - mockSocketServer.start(); - // give MockSocketServer head start - Thread.sleep(100); - } - - private void configureClient() { - context = new AccessContext(); - context.setName("test"); - SocketAppender socketAppender = new SocketAppender(); - socketAppender.setContext(context); - socketAppender.setName("socket"); - socketAppender.setPort(MockSocketServer.PORT); - socketAppender.setRemoteHost("localhost"); - context.addAppender(socketAppender); - socketAppender.start(); - } - - private AccessEvent buildNewAccessEvent() { - DummyRequest request = new DummyRequest(); - DummyResponse response = new DummyResponse(); - DummyServerAdapter adapter = new DummyServerAdapter(request, response); - - AccessEvent ae = new AccessEvent(request, response, adapter); - return ae; - } -} +/** + * 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.access.net; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import ch.qos.logback.access.dummy.DummyRequest; +import ch.qos.logback.access.dummy.DummyResponse; +import ch.qos.logback.access.dummy.DummyServerAdapter; +import ch.qos.logback.access.spi.AccessContext; +import ch.qos.logback.access.spi.AccessEvent; + + +public class SocketAppenderTest { + + private AccessContext context; + private MockSocketServer mockSocketServer; + + @Test + public void testStartFailNoRemoteHost() { + context = new AccessContext(); + SocketAppender appender = new SocketAppender(); + appender.setContext(context); + appender.setPort(123); + appender.start(); + assertEquals(1, context.getStatusManager().getCount()); + } + + @Test + public void testRecieveMessage() throws InterruptedException { + startServer(1); + configureClient(); + + context.callAppenders(buildNewAccessEvent()); + // Wait max 2 seconds for mock server to finish. However, it should + // finish much sooner than that. + mockSocketServer.join(2000); + assertTrue(mockSocketServer.finished); + assertEquals(1, mockSocketServer.accessEventList.size()); + + AccessEvent remoteEvent = mockSocketServer.accessEventList.get(0); + //check that the values are available although the request and response + //objects did not survive serialization + assertEquals("headerValue1", remoteEvent.getRequestHeader("headerName1")); + assertEquals("testHost", remoteEvent.getRemoteHost()); + } + + private void startServer(int expectedEventNumber) throws InterruptedException { + mockSocketServer = new MockSocketServer(expectedEventNumber); + mockSocketServer.start(); + // give MockSocketServer head start + Thread.sleep(100); + } + + private void configureClient() { + context = new AccessContext(); + context.setName("test"); + SocketAppender socketAppender = new SocketAppender(); + socketAppender.setContext(context); + socketAppender.setName("socket"); + socketAppender.setPort(MockSocketServer.PORT); + socketAppender.setRemoteHost("localhost"); + context.addAppender(socketAppender); + socketAppender.start(); + } + + private AccessEvent buildNewAccessEvent() { + DummyRequest request = new DummyRequest(); + DummyResponse response = new DummyResponse(); + DummyServerAdapter adapter = new DummyServerAdapter(request, response); + + AccessEvent ae = new AccessEvent(request, response, adapter); + return ae; + } +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java b/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java index 2c03870bdeb6d11bd9e62f158f10e475465c2c1b..f259f6559213d48709eaf8885e0092f277cc3530 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java @@ -1,82 +1,82 @@ -/** - * 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.access.net; - -import static org.junit.Assert.*; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.access.dummy.DummyRequest; -import ch.qos.logback.access.dummy.DummyResponse; -import ch.qos.logback.access.dummy.DummyServerAdapter; -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.boolex.EvaluationException; - -public class URLEvaluatorTest { - - final String expectedURL1 = "testUrl1"; - final String expectedURL2 = "testUrl2"; - Context context = new ContextBase(); - URLEvaluator evaluator; - DummyRequest request; - DummyResponse response; - DummyServerAdapter serverAdapter; - - @Before - public void setUp() throws Exception { - evaluator = new URLEvaluator(); - evaluator.setContext(context); - evaluator.addURL(expectedURL1); - evaluator.start(); - request = new DummyRequest(); - response = new DummyResponse(); - serverAdapter = new DummyServerAdapter(request, response); - } - - @After - public void tearDown() throws Exception { - evaluator.stop(); - evaluator = null; - request = null; - response = null; - serverAdapter = null; - context = null; - } - - @Test - public void testExpectFalse() throws EvaluationException { - request.setRequestUri("test"); - AccessEvent ae = new AccessEvent(request, response, serverAdapter); - assertFalse(evaluator.evaluate(ae)); - } - - @Test - public void testExpectTrue() throws EvaluationException { - request.setRequestUri(expectedURL1); - AccessEvent ae = new AccessEvent(request, response, serverAdapter); - assertTrue(evaluator.evaluate(ae)); - } - - @Test - public void testExpectTrueMultiple() throws EvaluationException { - evaluator.addURL(expectedURL2); - request.setRequestUri(expectedURL2); - AccessEvent ae = new AccessEvent(request, response, serverAdapter); - assertTrue(evaluator.evaluate(ae)); - } -} +/** + * 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.access.net; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.access.dummy.DummyRequest; +import ch.qos.logback.access.dummy.DummyResponse; +import ch.qos.logback.access.dummy.DummyServerAdapter; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.boolex.EvaluationException; + +public class URLEvaluatorTest { + + final String expectedURL1 = "testUrl1"; + final String expectedURL2 = "testUrl2"; + Context context = new ContextBase(); + URLEvaluator evaluator; + DummyRequest request; + DummyResponse response; + DummyServerAdapter serverAdapter; + + @Before + public void setUp() throws Exception { + evaluator = new URLEvaluator(); + evaluator.setContext(context); + evaluator.addURL(expectedURL1); + evaluator.start(); + request = new DummyRequest(); + response = new DummyResponse(); + serverAdapter = new DummyServerAdapter(request, response); + } + + @After + public void tearDown() throws Exception { + evaluator.stop(); + evaluator = null; + request = null; + response = null; + serverAdapter = null; + context = null; + } + + @Test + public void testExpectFalse() throws EvaluationException { + request.setRequestUri("test"); + AccessEvent ae = new AccessEvent(request, response, serverAdapter); + assertFalse(evaluator.evaluate(ae)); + } + + @Test + public void testExpectTrue() throws EvaluationException { + request.setRequestUri(expectedURL1); + AccessEvent ae = new AccessEvent(request, response, serverAdapter); + assertTrue(evaluator.evaluate(ae)); + } + + @Test + public void testExpectTrueMultiple() throws EvaluationException { + evaluator.addURL(expectedURL2); + request.setRequestUri(expectedURL2); + AccessEvent ae = new AccessEvent(request, response, serverAdapter); + assertTrue(evaluator.evaluate(ae)); + } +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java b/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java index 9b3c8c8c29e26ffe96392d5668d8909665c2f78a..b96b8bcf8f6cf21b3613a316f961b3511d198a98 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java @@ -1,200 +1,200 @@ -/** - * 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.access.pattern; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.http.Cookie; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.access.dummy.DummyRequest; -import ch.qos.logback.access.dummy.DummyResponse; -import ch.qos.logback.access.dummy.DummyServerAdapter; -import ch.qos.logback.access.spi.AccessEvent; - -public class ConverterTest { - - AccessEvent event; - DummyRequest request; - DummyResponse response; - - @Before - public void setUp() throws Exception { - request = new DummyRequest(); - response = new DummyResponse(); - event = createEvent(); - } - - @After - public void tearDown() throws Exception { - event = null; - request = null; - response = null; - } - - @Test - public void testContentLengthConverter() { - ContentLengthConverter converter = new ContentLengthConverter(); - converter.start(); - String result = converter.convert(event); - assertEquals(Long.toString(event.getServerAdapter().getContentLength()), result); - } - - @Test - public void testDateConverter() { - DateConverter converter = new DateConverter(); - converter.start(); - String result = converter.convert(event); - assertEquals(converter.simpleFormat.format(event.getTimeStamp()), result); - } - - public void testLineLocalPortConverter() { - LocalPortConverter converter = new LocalPortConverter(); - converter.start(); - String result = converter.convert(event); - assertEquals(Integer.toString(request.getLocalPort()), result); - } - - @Test - public void testRemoteHostConverter() { - RemoteHostConverter converter = new RemoteHostConverter(); - converter.start(); - String result = converter.convert(event); - assertEquals(request.getRemoteHost(), result); - } - - @Test - public void testRemoteIPAddressConverter() { - RemoteIPAddressConverter converter = new RemoteIPAddressConverter(); - converter.start(); - String result = converter.convert(event); - assertEquals(request.getRemoteAddr(), result); - } - - @Test - public void testRemoteUserConverter() { - RemoteUserConverter converter = new RemoteUserConverter(); - converter.start(); - String result = converter.convert(event); - assertEquals(request.getRemoteUser(), result); - } - - @Test - public void testRequestAttributeConverter() { - RequestAttributeConverter converter = new RequestAttributeConverter(); - List optionList = new ArrayList(); - optionList.add("testKey"); - converter.setOptionList(optionList); - converter.start(); - String result = converter.convert(event); - assertEquals(request.getAttribute("testKey"), result); - } - - @Test - public void testRequestCookieConverter() { - RequestCookieConverter converter = new RequestCookieConverter(); - List optionList = new ArrayList(); - optionList.add("testName"); - converter.setOptionList(optionList); - converter.start(); - String result = converter.convert(event); - Cookie cookie = request.getCookies()[0]; - assertEquals(cookie.getValue(), result); - } - - @Test - public void testRequestHeaderConverter() { - RequestHeaderConverter converter = new RequestHeaderConverter(); - List optionList = new ArrayList(); - optionList.add("headerName1"); - converter.setOptionList(optionList); - converter.start(); - String result = converter.convert(event); - assertEquals(request.getHeader("headerName1"), result); - } - - @Test - public void testRequestMethodConverter() { - RequestMethodConverter converter = new RequestMethodConverter(); - converter.start(); - String result = converter.convert(event); - assertEquals(request.getMethod(), result); - } - - @Test - public void testRequestProtocolConverter() { - RequestProtocolConverter converter = new RequestProtocolConverter(); - converter.start(); - String result = converter.convert(event); - assertEquals(request.getProtocol(), result); - } - - @Test - public void testRequestURIConverter() { - RequestURIConverter converter = new RequestURIConverter(); - converter.start(); - String result = converter.convert(event); - assertEquals(request.getRequestURI(), result); - } - - @Test - public void testRequestURLConverter() { - RequestURLConverter converter = new RequestURLConverter(); - converter.start(); - String result = converter.convert(event); - String expected = request.getMethod() + " " + request.getRequestURI() + " " - + request.getProtocol(); - assertEquals(expected, result); - } - - @Test - public void testResponseHeaderConverter() { - ResponseHeaderConverter converter = new ResponseHeaderConverter(); - List optionList = new ArrayList(); - optionList.add("headerName1"); - converter.setOptionList(optionList); - converter.start(); - String result = converter.convert(event); - assertEquals(request.getHeader("headerName1"), result); - } - - @Test - public void testServerNameConverter() { - ServerNameConverter converter = new ServerNameConverter(); - converter.start(); - String result = converter.convert(event); - assertEquals(request.getServerName(), result); - } - - @Test - public void testStatusCodeConverter() { - StatusCodeConverter converter = new StatusCodeConverter(); - converter.start(); - String result = converter.convert(event); - assertEquals(Integer.toString(event.getServerAdapter().getStatusCode()), result); - } - - private AccessEvent createEvent() { - DummyServerAdapter dummyAdapter = new DummyServerAdapter(request, response); - AccessEvent ae = new AccessEvent(request, response, dummyAdapter); - return ae; - } - -} +/** + * 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.access.pattern; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.Cookie; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.access.dummy.DummyRequest; +import ch.qos.logback.access.dummy.DummyResponse; +import ch.qos.logback.access.dummy.DummyServerAdapter; +import ch.qos.logback.access.spi.AccessEvent; + +public class ConverterTest { + + AccessEvent event; + DummyRequest request; + DummyResponse response; + + @Before + public void setUp() throws Exception { + request = new DummyRequest(); + response = new DummyResponse(); + event = createEvent(); + } + + @After + public void tearDown() throws Exception { + event = null; + request = null; + response = null; + } + + @Test + public void testContentLengthConverter() { + ContentLengthConverter converter = new ContentLengthConverter(); + converter.start(); + String result = converter.convert(event); + assertEquals(Long.toString(event.getServerAdapter().getContentLength()), result); + } + + @Test + public void testDateConverter() { + DateConverter converter = new DateConverter(); + converter.start(); + String result = converter.convert(event); + assertEquals(converter.simpleFormat.format(event.getTimeStamp()), result); + } + + public void testLineLocalPortConverter() { + LocalPortConverter converter = new LocalPortConverter(); + converter.start(); + String result = converter.convert(event); + assertEquals(Integer.toString(request.getLocalPort()), result); + } + + @Test + public void testRemoteHostConverter() { + RemoteHostConverter converter = new RemoteHostConverter(); + converter.start(); + String result = converter.convert(event); + assertEquals(request.getRemoteHost(), result); + } + + @Test + public void testRemoteIPAddressConverter() { + RemoteIPAddressConverter converter = new RemoteIPAddressConverter(); + converter.start(); + String result = converter.convert(event); + assertEquals(request.getRemoteAddr(), result); + } + + @Test + public void testRemoteUserConverter() { + RemoteUserConverter converter = new RemoteUserConverter(); + converter.start(); + String result = converter.convert(event); + assertEquals(request.getRemoteUser(), result); + } + + @Test + public void testRequestAttributeConverter() { + RequestAttributeConverter converter = new RequestAttributeConverter(); + List optionList = new ArrayList(); + optionList.add("testKey"); + converter.setOptionList(optionList); + converter.start(); + String result = converter.convert(event); + assertEquals(request.getAttribute("testKey"), result); + } + + @Test + public void testRequestCookieConverter() { + RequestCookieConverter converter = new RequestCookieConverter(); + List optionList = new ArrayList(); + optionList.add("testName"); + converter.setOptionList(optionList); + converter.start(); + String result = converter.convert(event); + Cookie cookie = request.getCookies()[0]; + assertEquals(cookie.getValue(), result); + } + + @Test + public void testRequestHeaderConverter() { + RequestHeaderConverter converter = new RequestHeaderConverter(); + List optionList = new ArrayList(); + optionList.add("headerName1"); + converter.setOptionList(optionList); + converter.start(); + String result = converter.convert(event); + assertEquals(request.getHeader("headerName1"), result); + } + + @Test + public void testRequestMethodConverter() { + RequestMethodConverter converter = new RequestMethodConverter(); + converter.start(); + String result = converter.convert(event); + assertEquals(request.getMethod(), result); + } + + @Test + public void testRequestProtocolConverter() { + RequestProtocolConverter converter = new RequestProtocolConverter(); + converter.start(); + String result = converter.convert(event); + assertEquals(request.getProtocol(), result); + } + + @Test + public void testRequestURIConverter() { + RequestURIConverter converter = new RequestURIConverter(); + converter.start(); + String result = converter.convert(event); + assertEquals(request.getRequestURI(), result); + } + + @Test + public void testRequestURLConverter() { + RequestURLConverter converter = new RequestURLConverter(); + converter.start(); + String result = converter.convert(event); + String expected = request.getMethod() + " " + request.getRequestURI() + " " + + request.getProtocol(); + assertEquals(expected, result); + } + + @Test + public void testResponseHeaderConverter() { + ResponseHeaderConverter converter = new ResponseHeaderConverter(); + List optionList = new ArrayList(); + optionList.add("headerName1"); + converter.setOptionList(optionList); + converter.start(); + String result = converter.convert(event); + assertEquals(request.getHeader("headerName1"), result); + } + + @Test + public void testServerNameConverter() { + ServerNameConverter converter = new ServerNameConverter(); + converter.start(); + String result = converter.convert(event); + assertEquals(request.getServerName(), result); + } + + @Test + public void testStatusCodeConverter() { + StatusCodeConverter converter = new StatusCodeConverter(); + converter.start(); + String result = converter.convert(event); + assertEquals(Integer.toString(event.getServerAdapter().getStatusCode()), result); + } + + private AccessEvent createEvent() { + DummyServerAdapter dummyAdapter = new DummyServerAdapter(request, response); + AccessEvent ae = new AccessEvent(request, response, dummyAdapter); + return ae; + } + +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java b/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java index b8db3fa8b6b4dc3b66e2463260a285dd6d56bd7f..5b1d84a4287e3a3fcc964c333f64a78e21b760cd 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java @@ -1,25 +1,25 @@ -/** - * 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.access.pattern; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({ConverterTest.class}) -public class PackageTest { - - +/** + * 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.access.pattern; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ConverterTest.class}) +public class PackageTest { + + } \ No newline at end of file diff --git a/logback-access/src/test/java/ch/qos/logback/access/sift/JettyFixture.java b/logback-access/src/test/java/ch/qos/logback/access/sift/JettyFixture.java index 34cd381006c034f22180481499b6fc01860cddb8..72509bdf3f2bd348f727290f25687c859f328114 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/sift/JettyFixture.java +++ b/logback-access/src/test/java/ch/qos/logback/access/sift/JettyFixture.java @@ -1,72 +1,72 @@ -/** - * 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.access.sift; - -import java.io.IOException; -import java.io.OutputStream; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.mortbay.jetty.Handler; -import org.mortbay.jetty.HttpConnection; -import org.mortbay.jetty.Request; -import org.mortbay.jetty.handler.AbstractHandler; -import org.mortbay.util.ByteArrayISO8859Writer; - -import ch.qos.logback.access.jetty.JettyFixtureBase; -import ch.qos.logback.access.jetty.RequestLogImpl; - -public class JettyFixture extends JettyFixtureBase { - - Handler handler = new BasicHandler(); - - public JettyFixture(RequestLogImpl impl, int port) { - super(impl, port); - } - - @Override - protected void buildContext() { - requestLogImpl.start(); - } - - @Override - protected Handler getHandler() { - return handler; - } - - class BasicHandler extends AbstractHandler { - public void handle(String target, HttpServletRequest request, - HttpServletResponse response, int dispatch) throws IOException, - ServletException { - - // String requestContent = Util.readToString(request.getInputStream()); - // System.out.println("request content: " + requestContent); - - OutputStream out = response.getOutputStream(); - ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(); - writer.write("hello world"); - writer.flush(); - response.setContentLength(writer.size()); - writer.writeTo(out); - out.flush(); - - Request base_request = (request instanceof Request) ? (Request) request - : HttpConnection.getCurrentConnection().getRequest(); - base_request.setHandled(true); - - } - } -} +/** + * 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.access.sift; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.mortbay.jetty.Handler; +import org.mortbay.jetty.HttpConnection; +import org.mortbay.jetty.Request; +import org.mortbay.jetty.handler.AbstractHandler; +import org.mortbay.util.ByteArrayISO8859Writer; + +import ch.qos.logback.access.jetty.JettyFixtureBase; +import ch.qos.logback.access.jetty.RequestLogImpl; + +public class JettyFixture extends JettyFixtureBase { + + Handler handler = new BasicHandler(); + + public JettyFixture(RequestLogImpl impl, int port) { + super(impl, port); + } + + @Override + protected void buildContext() { + requestLogImpl.start(); + } + + @Override + protected Handler getHandler() { + return handler; + } + + class BasicHandler extends AbstractHandler { + public void handle(String target, HttpServletRequest request, + HttpServletResponse response, int dispatch) throws IOException, + ServletException { + + // String requestContent = Util.readToString(request.getInputStream()); + // System.out.println("request content: " + requestContent); + + OutputStream out = response.getOutputStream(); + ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(); + writer.write("hello world"); + writer.flush(); + response.setContentLength(writer.size()); + writer.writeTo(out); + out.flush(); + + Request base_request = (request instanceof Request) ? (Request) request + : HttpConnection.getCurrentConnection().getRequest(); + base_request.setHandled(true); + + } + } +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/sift/PackageTest.java b/logback-access/src/test/java/ch/qos/logback/access/sift/PackageTest.java index 457cf53fb5ccb33d5700a3a3c3b6abd117f19662..3b92d2313bec8a6f4f7f5f1ebd626111e24bdfa6 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/sift/PackageTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/sift/PackageTest.java @@ -1,24 +1,24 @@ -/** - * 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.access.sift; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({SiftingAppenderTest.class}) -public class PackageTest { - +/** + * 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.access.sift; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({SiftingAppenderTest.class}) +public class PackageTest { + } \ No newline at end of file diff --git a/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java b/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java index 755b3acd5bd72c99e321e54a4580336d46f501a9..318c02af148f5392d97f42fab03a246b7ab7652a 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java @@ -1,104 +1,104 @@ -/** - * 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.access.sift; - -import static org.junit.Assert.assertEquals; - -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.access.jetty.RequestLogImpl; -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.access.spi.Util; -import ch.qos.logback.core.read.ListAppender; -import ch.qos.logback.core.testUtil.RandomUtil; -import ch.qos.logback.core.util.StatusPrinter; - -public class SiftingAppenderTest { - static final String PREFIX = "src/test/input/jetty/"; - static int RANDOM_SERVER_PORT = RandomUtil.getRandomServerPort(); - - JettyFixture jettyFixture; - RequestLogImpl rli = new RequestLogImpl(); - - @Before - public void startServer() throws Exception { - jettyFixture = new JettyFixture(rli, RANDOM_SERVER_PORT); - - } - - @After - public void stopServer() throws Exception { - if (jettyFixture != null) { - jettyFixture.stop(); - } - } - - @Test - public void test() throws Exception { - rli.setFileName(PREFIX + "sifting.xml"); - jettyFixture.start(); - - - StatusPrinter.print(rli); - invokeServer("/"); - invokeServer("/x"); - invokeServer("/x"); - invokeServer("/y"); - - - SiftingAppender siftingAppender = (SiftingAppender) rli - .getAppender("SIFTING"); - List keyList = siftingAppender.getAppenderTracker().keyList(); - assertEquals(3, keyList.size()); - - List witnessList = new ArrayList(); - witnessList.add("NA"); - witnessList.add("x"); - witnessList.add("y"); - assertEquals(witnessList, keyList); - - long now = System.currentTimeMillis(); - { - ListAppender listAppender = (ListAppender) siftingAppender - .getAppenderTracker().get("NA", now); - assertEquals(1, listAppender.list.size()); - } - - { - ListAppender listAppender = (ListAppender) siftingAppender - .getAppenderTracker().get("x", now); - assertEquals(2, listAppender.list.size()); - } - { - ListAppender listAppender = (ListAppender) siftingAppender - .getAppenderTracker().get("y", now); - assertEquals(1, listAppender.list.size()); - } - } - - void invokeServer(String uri) throws Exception { - URL url = new URL("http://localhost:" + RANDOM_SERVER_PORT + uri); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setDoInput(true); - Util.readToString(connection.getInputStream()); - Thread.sleep(30); - } -} +/** + * 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.access.sift; + +import static org.junit.Assert.assertEquals; + +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.access.jetty.RequestLogImpl; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.access.spi.Util; +import ch.qos.logback.core.read.ListAppender; +import ch.qos.logback.core.testUtil.RandomUtil; +import ch.qos.logback.core.util.StatusPrinter; + +public class SiftingAppenderTest { + static final String PREFIX = "src/test/input/jetty/"; + static int RANDOM_SERVER_PORT = RandomUtil.getRandomServerPort(); + + JettyFixture jettyFixture; + RequestLogImpl rli = new RequestLogImpl(); + + @Before + public void startServer() throws Exception { + jettyFixture = new JettyFixture(rli, RANDOM_SERVER_PORT); + + } + + @After + public void stopServer() throws Exception { + if (jettyFixture != null) { + jettyFixture.stop(); + } + } + + @Test + public void test() throws Exception { + rli.setFileName(PREFIX + "sifting.xml"); + jettyFixture.start(); + + + StatusPrinter.print(rli); + invokeServer("/"); + invokeServer("/x"); + invokeServer("/x"); + invokeServer("/y"); + + + SiftingAppender siftingAppender = (SiftingAppender) rli + .getAppender("SIFTING"); + List keyList = siftingAppender.getAppenderTracker().keyList(); + assertEquals(3, keyList.size()); + + List witnessList = new ArrayList(); + witnessList.add("NA"); + witnessList.add("x"); + witnessList.add("y"); + assertEquals(witnessList, keyList); + + long now = System.currentTimeMillis(); + { + ListAppender listAppender = (ListAppender) siftingAppender + .getAppenderTracker().get("NA", now); + assertEquals(1, listAppender.list.size()); + } + + { + ListAppender listAppender = (ListAppender) siftingAppender + .getAppenderTracker().get("x", now); + assertEquals(2, listAppender.list.size()); + } + { + ListAppender listAppender = (ListAppender) siftingAppender + .getAppenderTracker().get("y", now); + assertEquals(1, listAppender.list.size()); + } + } + + void invokeServer(String uri) throws Exception { + URL url = new URL("http://localhost:" + RANDOM_SERVER_PORT + uri); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + Util.readToString(connection.getInputStream()); + Thread.sleep(30); + } +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/spi/AccessEventSerializationTest.java b/logback-access/src/test/java/ch/qos/logback/access/spi/AccessEventSerializationTest.java index f73e5e8b3cecc2271ef5d0fb935bd00741315798..b486836ddf28a4c943bf92718c762c9fb2324f9f 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/spi/AccessEventSerializationTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/spi/AccessEventSerializationTest.java @@ -1,76 +1,76 @@ -/** - * 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.access.spi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import org.junit.Test; - -import ch.qos.logback.access.dummy.DummyAccessEventBuilder; -import ch.qos.logback.access.dummy.DummyRequest; -import ch.qos.logback.access.dummy.DummyResponse; - -public class AccessEventSerializationTest { - - private Object buildSerializedAccessEvent() throws IOException, - ClassNotFoundException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - AccessEvent ae = DummyAccessEventBuilder.buildNewAccessEvent(); - // average time for the next method: 5000 nanos - ae.prepareForDeferredProcessing(); - oos.writeObject(ae); - oos.flush(); - - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - ObjectInputStream ois = new ObjectInputStream(bais); - - return ois.readObject(); - } - - @Test - public void testSerialization() throws IOException, ClassNotFoundException { - Object o = buildSerializedAccessEvent(); - assertNotNull(o); - AccessEvent aeBack = (AccessEvent) o; - - - assertEquals(DummyResponse.DUMMY_DEFAULT_HDEADER_MAP, aeBack - .getResponseHeaderMap()); - assertEquals(DummyResponse.DUMMY_DEFAULT_HDEADER_MAP.get("x"), aeBack - .getResponseHeader("x")); - assertEquals(DummyResponse.DUMMY_DEFAULT_HDEADER_MAP.get("headerName1"), - aeBack.getResponseHeader("headerName1")); - assertEquals(DummyResponse.DUMMY_DEFAULT_HDEADER_MAP.size(), aeBack - .getResponseHeaderNameList().size()); - assertEquals(DummyResponse.DUMMY_DEFAULT_CONTENT_COUNT, aeBack - .getContentLength()); - assertEquals(DummyResponse.DUMMY_DEFAULT_STATUS, aeBack.getStatusCode()); - - assertEquals(DummyRequest.DUMMY_CONTENT_STRING, aeBack - .getRequestContent()); - - assertEquals(DummyRequest.DUMMY_RESPONSE_CONTENT_STRING, aeBack - .getResponseContent()); - - } - -} +/** + * 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.access.spi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.junit.Test; + +import ch.qos.logback.access.dummy.DummyAccessEventBuilder; +import ch.qos.logback.access.dummy.DummyRequest; +import ch.qos.logback.access.dummy.DummyResponse; + +public class AccessEventSerializationTest { + + private Object buildSerializedAccessEvent() throws IOException, + ClassNotFoundException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + AccessEvent ae = DummyAccessEventBuilder.buildNewAccessEvent(); + // average time for the next method: 5000 nanos + ae.prepareForDeferredProcessing(); + oos.writeObject(ae); + oos.flush(); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + + return ois.readObject(); + } + + @Test + public void testSerialization() throws IOException, ClassNotFoundException { + Object o = buildSerializedAccessEvent(); + assertNotNull(o); + AccessEvent aeBack = (AccessEvent) o; + + + assertEquals(DummyResponse.DUMMY_DEFAULT_HDEADER_MAP, aeBack + .getResponseHeaderMap()); + assertEquals(DummyResponse.DUMMY_DEFAULT_HDEADER_MAP.get("x"), aeBack + .getResponseHeader("x")); + assertEquals(DummyResponse.DUMMY_DEFAULT_HDEADER_MAP.get("headerName1"), + aeBack.getResponseHeader("headerName1")); + assertEquals(DummyResponse.DUMMY_DEFAULT_HDEADER_MAP.size(), aeBack + .getResponseHeaderNameList().size()); + assertEquals(DummyResponse.DUMMY_DEFAULT_CONTENT_COUNT, aeBack + .getContentLength()); + assertEquals(DummyResponse.DUMMY_DEFAULT_STATUS, aeBack.getStatusCode()); + + assertEquals(DummyRequest.DUMMY_CONTENT_STRING, aeBack + .getRequestContent()); + + assertEquals(DummyRequest.DUMMY_RESPONSE_CONTENT_STRING, aeBack + .getResponseContent()); + + } + +} diff --git a/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java b/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java index ba365b29519024c266efe6aa9539af7a82eac091..0e85c0af10ddbd9446952730d70a18223f19f741 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java +++ b/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java @@ -1,25 +1,25 @@ -/** - * 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.access.spi; - -import junit.framework.TestCase; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({AccessEventSerializationTest.class}) -public class PackageTest extends TestCase { +/** + * 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.access.spi; + +import junit.framework.TestCase; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({AccessEventSerializationTest.class}) +public class PackageTest extends TestCase { } \ No newline at end of file diff --git a/logback-access/src/test/java/ch/qos/logback/access/testUtil/NotifyingListAppender.java b/logback-access/src/test/java/ch/qos/logback/access/testUtil/NotifyingListAppender.java index 6d5aae11c0868bf03afabf8e4aa44689e4b6f1fe..950a5ab8f19d0c0526070dbd87953281562d4b92 100644 --- a/logback-access/src/test/java/ch/qos/logback/access/testUtil/NotifyingListAppender.java +++ b/logback-access/src/test/java/ch/qos/logback/access/testUtil/NotifyingListAppender.java @@ -1,32 +1,32 @@ -/** - * 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.access.testUtil; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.access.spi.AccessEvent; -import ch.qos.logback.core.AppenderBase; - -public class NotifyingListAppender extends AppenderBase { - - public List list = new ArrayList(); - - protected void append(AccessEvent e) { - list.add(e); - synchronized (this) { - this.notify(); - } - } -} +/** + * 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.access.testUtil; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.core.AppenderBase; + +public class NotifyingListAppender extends AppenderBase { + + public List list = new ArrayList(); + + protected void append(AccessEvent e) { + list.add(e); + synchronized (this) { + this.notify(); + } + } +} diff --git a/logback-classic/LICENSE.txt b/logback-classic/LICENSE.txt index 667c2b5dec1895f20ac8ed369045589dc26ff610..d5dac89e45b96875fa0e06a0cf7022e757c4fc52 100644 --- a/logback-classic/LICENSE.txt +++ b/logback-classic/LICENSE.txt @@ -1,22 +1,22 @@ -Logback LICENSE ---------------- - -Logback: the reliable, generic, fast and flexible logging library for -Java. - -Copyright (C) 2000-2008, QOS.ch - -Source code and binaries for logback, including logback-core, -logback-classic and logback-access modules, are distributed under the -GNU Lesser General Public License Version 2.1, as published by the -Free Software Foundation. - -This library is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as -published by the Free Software Foundation; either version 2.1 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. +Logback LICENSE +--------------- + +Logback: the reliable, generic, fast and flexible logging library for +Java. + +Copyright (C) 2000-2008, QOS.ch + +Source code and binaries for logback, including logback-core, +logback-classic and logback-access modules, are distributed under the +GNU Lesser General Public License Version 2.1, as published by the +Free Software Foundation. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. diff --git a/logback-classic/performance/records/ArrayListLogger/results.txt b/logback-classic/performance/records/ArrayListLogger/results.txt index 10365cefb235e4cdfa34a3193429cd6a6e0ff4ed..b96a2e020c2f35455382cd0549e1ef4898e6ebba 100644 --- a/logback-classic/performance/records/ArrayListLogger/results.txt +++ b/logback-classic/performance/records/ArrayListLogger/results.txt @@ -1,74 +1,74 @@ - - -- Logger has reference to its parent. It also holds a reference to its - children in an ArrayList. - -- LoggerContext has a cache of existing loggers in a map. This - significantly improves the performance of retrival of existing - loggers. - - -Memomy footprint for 1000 loggers: -================================== - -The memory consumption of various logger implementations are shown -next. - - 400 kB - 6,579 alloc. com.logback.LoggerCreation.tesLOG4JLoggers - 394 kB - 6,821 alloc. com.logback.LoggerCreation.testHashLoggers - 255 kB - 7,505 alloc. com.logback.LoggerCreation.testJULLoggers - 115 kB - 3,308 alloc. com.logback.LoggerCreation.testListLoggers - 75 kB - 2,784 alloc. com.logback.LoggerCreation.testControlLoggers - -One can see that the ArrayList implementation is twice as memory -efficient as the JUL implementation and 4 times as efficient as the -LOG4J implementation. - -The logger cache adds a memory overhead but very significantly -improves the efficiency of retreiving an existing logger. - -The mem foorprint without the logger cache: - - 73 kB - 2,046 alloc. com.logback.LoggerCreation.testListLoggers - - -Speed of retrieval of an existing logger: -========================================== - -Logger 94 nanoseconds per retrieval. -Log4j Logger 2234 nanoseconds per retrieval. -ControlLogger 101 nanoseconds per retrieval. -JUL 165 nanoseconds per retrieval. - -We can see that log4j is particularly bad in this area. This can be -traced back to the fact that o.a.l.Hierarchy instantiates a -CategoryKey for every call to the Hierarchy.getLogger method. - -Speed of creating of a logger: -============================== - -Emtpy logger creation: 1229 nanoseconds per creation. -List logger creation: 13139 nanoseconds per creation. -JUL logger creation: 61990 nanoseconds per creation. -LOG4J logger creation: 23503 nanoseconds per creation. -Contl logger creation: 6746 nanoseconds per creation. -Hash logger creation: 14520 nanoseconds per creation. - -One can see that the ArrayList logger implementation creates loggers -about six times faster than JUL and 2 times faster than LOG4J. - -Cost of a (disabled) debug call: -================================ - -SLF4J List logger 17 nanoseconds per call. -SLF4J Log4j logger 33 nanoseconds per call. -SLF4J JDK14 Logger 33 nanoseconds per call. - -DIRECT List logger: 3 nanoseconds per call. -DIRECT LOG4J logger: 30 nanoseconds per call. -DIRECT JUL logger: 4 nanoseconds per call. - -For direct calls, JUL and ArrayList logger impl are roughly equivalent -(even if LB is a little faster), log4j is about 10 times slower. - -For calls through the SLF4J interface, LB is almost twice as fast. + + +- Logger has reference to its parent. It also holds a reference to its + children in an ArrayList. + +- LoggerContext has a cache of existing loggers in a map. This + significantly improves the performance of retrival of existing + loggers. + + +Memomy footprint for 1000 loggers: +================================== + +The memory consumption of various logger implementations are shown +next. + + 400 kB - 6,579 alloc. com.logback.LoggerCreation.tesLOG4JLoggers + 394 kB - 6,821 alloc. com.logback.LoggerCreation.testHashLoggers + 255 kB - 7,505 alloc. com.logback.LoggerCreation.testJULLoggers + 115 kB - 3,308 alloc. com.logback.LoggerCreation.testListLoggers + 75 kB - 2,784 alloc. com.logback.LoggerCreation.testControlLoggers + +One can see that the ArrayList implementation is twice as memory +efficient as the JUL implementation and 4 times as efficient as the +LOG4J implementation. + +The logger cache adds a memory overhead but very significantly +improves the efficiency of retreiving an existing logger. + +The mem foorprint without the logger cache: + + 73 kB - 2,046 alloc. com.logback.LoggerCreation.testListLoggers + + +Speed of retrieval of an existing logger: +========================================== + +Logger 94 nanoseconds per retrieval. +Log4j Logger 2234 nanoseconds per retrieval. +ControlLogger 101 nanoseconds per retrieval. +JUL 165 nanoseconds per retrieval. + +We can see that log4j is particularly bad in this area. This can be +traced back to the fact that o.a.l.Hierarchy instantiates a +CategoryKey for every call to the Hierarchy.getLogger method. + +Speed of creating of a logger: +============================== + +Emtpy logger creation: 1229 nanoseconds per creation. +List logger creation: 13139 nanoseconds per creation. +JUL logger creation: 61990 nanoseconds per creation. +LOG4J logger creation: 23503 nanoseconds per creation. +Contl logger creation: 6746 nanoseconds per creation. +Hash logger creation: 14520 nanoseconds per creation. + +One can see that the ArrayList logger implementation creates loggers +about six times faster than JUL and 2 times faster than LOG4J. + +Cost of a (disabled) debug call: +================================ + +SLF4J List logger 17 nanoseconds per call. +SLF4J Log4j logger 33 nanoseconds per call. +SLF4J JDK14 Logger 33 nanoseconds per call. + +DIRECT List logger: 3 nanoseconds per call. +DIRECT LOG4J logger: 30 nanoseconds per call. +DIRECT JUL logger: 4 nanoseconds per call. + +For direct calls, JUL and ArrayList logger impl are roughly equivalent +(even if LB is a little faster), log4j is about 10 times slower. + +For calls through the SLF4J interface, LB is almost twice as fast. diff --git a/logback-classic/performance/records/HashtableInLogger/description.txt b/logback-classic/performance/records/HashtableInLogger/description.txt index a5db51fc064a55be2cc9847f366d670cf536fa1f..6b48719c4cd067a53a9159d5ff98d1387aa131c7 100644 --- a/logback-classic/performance/records/HashtableInLogger/description.txt +++ b/logback-classic/performance/records/HashtableInLogger/description.txt @@ -1,46 +1,46 @@ - - -- Logger has a hashtable keeping track of its children. - -- LoggerContext has reference to root logger and no other data -structure. - - -- Results are based on calling testReal() with the value 1'000. - - static public void testReal() { - LoggerContext lc = new LoggerContext(); - Scenario s = ScenarioMaker.makeType1Scenario(len); - List actionList = s.getActionList(); - int size = actionList.size(); - for (int i = 0; i < size; i++) { - Action action = (Action) actionList.get(i); - if (action instanceof CreateLogger) { - CreateLogger cl = (CreateLogger) action; - lc.getLogger(cl.getLoggerName()); - } - } - } - - Other parameters of interest: - - private final static int AVERAGE_ID_LEN = 16; - private final static int AVERAGE_ID_DEV = 8; - private final static int AVERAGE_LOGGER_DEPTH = 4; - private final static int LOGGER_DEPT_DEV = 2; - -java.lang.String 8,291 198,984 -char[ ] 6,961 412,296 -java.util.HashMap$Entry 3,847 92,328 -com.logback.Logger 3,824 152,960 -[ ] 3,144 262,304 -java.util.HashMap 2,862 114,480 - - -Each Logger instance takes up about 152 bytes of memory. -Each Logger instance takes up about 16 bytes of memory. - -CPU Usage: -========== - -22.5% or 901ms spent in LoggerContext.getLogger(). + + +- Logger has a hashtable keeping track of its children. + +- LoggerContext has reference to root logger and no other data +structure. + + +- Results are based on calling testReal() with the value 1'000. + + static public void testReal() { + LoggerContext lc = new LoggerContext(); + Scenario s = ScenarioMaker.makeType1Scenario(len); + List actionList = s.getActionList(); + int size = actionList.size(); + for (int i = 0; i < size; i++) { + Action action = (Action) actionList.get(i); + if (action instanceof CreateLogger) { + CreateLogger cl = (CreateLogger) action; + lc.getLogger(cl.getLoggerName()); + } + } + } + + Other parameters of interest: + + private final static int AVERAGE_ID_LEN = 16; + private final static int AVERAGE_ID_DEV = 8; + private final static int AVERAGE_LOGGER_DEPTH = 4; + private final static int LOGGER_DEPT_DEV = 2; + +java.lang.String 8,291 198,984 +char[ ] 6,961 412,296 +java.util.HashMap$Entry 3,847 92,328 +com.logback.Logger 3,824 152,960 +[ ] 3,144 262,304 +java.util.HashMap 2,862 114,480 + + +Each Logger instance takes up about 152 bytes of memory. +Each Logger instance takes up about 16 bytes of memory. + +CPU Usage: +========== + +22.5% or 901ms spent in LoggerContext.getLogger(). diff --git a/logback-classic/performance/src/java/ch/qos/logback/classic/LoggerCreation.java b/logback-classic/performance/src/java/ch/qos/logback/classic/LoggerCreation.java index eb84c1d70b61980e5dec2c50a60625d452599c25..bdd4ba14ba06a1ba63ad5b8ed19c232da7c9eef5 100644 --- a/logback-classic/performance/src/java/ch/qos/logback/classic/LoggerCreation.java +++ b/logback-classic/performance/src/java/ch/qos/logback/classic/LoggerCreation.java @@ -1,152 +1,152 @@ -/** - * LOGBack: the reliable, fast and flexible logging library for Java. - * - * Copyright (C) 1999-2005, QOS.ch, LOGBack.com - * - * This library is free software, you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation. - */ -package ch.qos.logback.classic; - -import java.io.IOException; -import java.util.List; - -import org.apache.log4j.Hierarchy; -import org.apache.log4j.spi.RootLogger; - -import ch.qos.logback.classic.HLoggerContext; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.control.ControlLoggerContext; -import ch.qos.logback.classic.control.CreateLogger; -import ch.qos.logback.classic.control.Scenario; -import ch.qos.logback.classic.control.ScenarioMaker; -import ch.qos.logback.classic.control.TestAction; - - - -public class LoggerCreation { - static LoggerContext listLoggerContext = new LoggerContext(); - static HLoggerContext hashLoggerContext = new HLoggerContext(); - static ControlLoggerContext controlContext = new ControlLoggerContext(); - static Hierarchy log4jHierarchy = new Hierarchy(new RootLogger(org.apache.log4j.Level.OFF)); - - public static void main(String[] args) throws IOException, InterruptedException { - - Scenario s = ScenarioMaker.makeTypeBScenario(3000); - System.err.print("Press a key to continue: "); - System.in.read(); - - - testEmptyLoggers(s); - testListLoggers(s); - testJULLoggers(s); - tesLOG4JLoggers(s); - testControlLoggers(s); - testHashLoggers(s); - - } - - - static void testEmptyLoggers(Scenario s) { - - List actionList = s.getActionList(); - int size = actionList.size(); - long start = System.nanoTime(); - CreateLogger cl = null; - for (int i = 0; i < size; i++) { - TestAction action = (TestAction) actionList.get(i); - if (action instanceof CreateLogger) { - cl = (CreateLogger) action; - } - } - if(cl == null) { - // bogus if block to keep eclipse happy - } - long result = System.nanoTime() - start; - System.out.println("Average (in nanos) Emtpy logger creation: " + (result / s.size())); - - } - - static void testListLoggers(Scenario s) { - - List actionList = s.getActionList(); - int size = actionList.size(); - long start = System.nanoTime(); - for (int i = 0; i < size; i++) { - TestAction action = (TestAction) actionList.get(i); - if (action instanceof CreateLogger) { - CreateLogger cl = (CreateLogger) action; - listLoggerContext.getLogger(cl.getLoggerName()); - } - } - long result = System.nanoTime() - start; - System.out.println("Average (in nanos) List logger creation: " + (result / s.size())); - - } - - static void testHashLoggers(Scenario s) { - List actionList = s.getActionList(); - int size = actionList.size(); - long start = System.nanoTime(); - for (int i = 0; i < size; i++) { - TestAction action = (TestAction) actionList.get(i); - if (action instanceof CreateLogger) { - CreateLogger cl = (CreateLogger) action; - hashLoggerContext.getLogger(cl.getLoggerName()); - } - } - long result = System.nanoTime() - start; - System.out.println("Average (in nanos) Hash logger creation: " + (result / s.size())); - - } - - static void testControlLoggers(Scenario s) { - - List actionList = s.getActionList(); - int size = actionList.size(); - long start = System.nanoTime(); - for (int i = 0; i < size; i++) { - TestAction action = (TestAction) actionList.get(i); - if (action instanceof CreateLogger) { - CreateLogger cl = (CreateLogger) action; - controlContext.getLogger(cl.getLoggerName()); - } - } - long result = System.nanoTime() - start; - System.out.println("Average (in nanos) Control logger creation: " + (result / s.size())); - } - - static void tesLOG4JLoggers(Scenario s) { - - List actionList = s.getActionList(); - int size = actionList.size(); - long start = System.nanoTime(); - for (int i = 0; i < size; i++) { - TestAction action = (TestAction) actionList.get(i); - if (action instanceof CreateLogger) { - CreateLogger cl = (CreateLogger) action; - log4jHierarchy.getLogger(cl.getLoggerName()); - } - } - long result = System.nanoTime() - start; - System.out.println("Average (in nanos) LOG4J logger creation: " + (result / s.size())); - } - - static void testJULLoggers(Scenario s) { - - List actionList = s.getActionList(); - int size = actionList.size(); - long start = System.nanoTime(); - for (int i = 0; i < size; i++) { - TestAction action = (TestAction) actionList.get(i); - if (action instanceof CreateLogger) { - CreateLogger cl = (CreateLogger) action; - java.util.logging.Logger.getLogger(cl.getLoggerName()); - } - } - long result = System.nanoTime() - start; - System.out.println("Average (in nanos) JUL logger creation: " + (result / s.size())); - } - -} +/** + * LOGBack: the reliable, fast and flexible logging library for Java. + * + * Copyright (C) 1999-2005, QOS.ch, LOGBack.com + * + * This library is free software, you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation. + */ +package ch.qos.logback.classic; + +import java.io.IOException; +import java.util.List; + +import org.apache.log4j.Hierarchy; +import org.apache.log4j.spi.RootLogger; + +import ch.qos.logback.classic.HLoggerContext; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.control.ControlLoggerContext; +import ch.qos.logback.classic.control.CreateLogger; +import ch.qos.logback.classic.control.Scenario; +import ch.qos.logback.classic.control.ScenarioMaker; +import ch.qos.logback.classic.control.TestAction; + + + +public class LoggerCreation { + static LoggerContext listLoggerContext = new LoggerContext(); + static HLoggerContext hashLoggerContext = new HLoggerContext(); + static ControlLoggerContext controlContext = new ControlLoggerContext(); + static Hierarchy log4jHierarchy = new Hierarchy(new RootLogger(org.apache.log4j.Level.OFF)); + + public static void main(String[] args) throws IOException, InterruptedException { + + Scenario s = ScenarioMaker.makeTypeBScenario(3000); + System.err.print("Press a key to continue: "); + System.in.read(); + + + testEmptyLoggers(s); + testListLoggers(s); + testJULLoggers(s); + tesLOG4JLoggers(s); + testControlLoggers(s); + testHashLoggers(s); + + } + + + static void testEmptyLoggers(Scenario s) { + + List actionList = s.getActionList(); + int size = actionList.size(); + long start = System.nanoTime(); + CreateLogger cl = null; + for (int i = 0; i < size; i++) { + TestAction action = (TestAction) actionList.get(i); + if (action instanceof CreateLogger) { + cl = (CreateLogger) action; + } + } + if(cl == null) { + // bogus if block to keep eclipse happy + } + long result = System.nanoTime() - start; + System.out.println("Average (in nanos) Emtpy logger creation: " + (result / s.size())); + + } + + static void testListLoggers(Scenario s) { + + List actionList = s.getActionList(); + int size = actionList.size(); + long start = System.nanoTime(); + for (int i = 0; i < size; i++) { + TestAction action = (TestAction) actionList.get(i); + if (action instanceof CreateLogger) { + CreateLogger cl = (CreateLogger) action; + listLoggerContext.getLogger(cl.getLoggerName()); + } + } + long result = System.nanoTime() - start; + System.out.println("Average (in nanos) List logger creation: " + (result / s.size())); + + } + + static void testHashLoggers(Scenario s) { + List actionList = s.getActionList(); + int size = actionList.size(); + long start = System.nanoTime(); + for (int i = 0; i < size; i++) { + TestAction action = (TestAction) actionList.get(i); + if (action instanceof CreateLogger) { + CreateLogger cl = (CreateLogger) action; + hashLoggerContext.getLogger(cl.getLoggerName()); + } + } + long result = System.nanoTime() - start; + System.out.println("Average (in nanos) Hash logger creation: " + (result / s.size())); + + } + + static void testControlLoggers(Scenario s) { + + List actionList = s.getActionList(); + int size = actionList.size(); + long start = System.nanoTime(); + for (int i = 0; i < size; i++) { + TestAction action = (TestAction) actionList.get(i); + if (action instanceof CreateLogger) { + CreateLogger cl = (CreateLogger) action; + controlContext.getLogger(cl.getLoggerName()); + } + } + long result = System.nanoTime() - start; + System.out.println("Average (in nanos) Control logger creation: " + (result / s.size())); + } + + static void tesLOG4JLoggers(Scenario s) { + + List actionList = s.getActionList(); + int size = actionList.size(); + long start = System.nanoTime(); + for (int i = 0; i < size; i++) { + TestAction action = (TestAction) actionList.get(i); + if (action instanceof CreateLogger) { + CreateLogger cl = (CreateLogger) action; + log4jHierarchy.getLogger(cl.getLoggerName()); + } + } + long result = System.nanoTime() - start; + System.out.println("Average (in nanos) LOG4J logger creation: " + (result / s.size())); + } + + static void testJULLoggers(Scenario s) { + + List actionList = s.getActionList(); + int size = actionList.size(); + long start = System.nanoTime(); + for (int i = 0; i < size; i++) { + TestAction action = (TestAction) actionList.get(i); + if (action instanceof CreateLogger) { + CreateLogger cl = (CreateLogger) action; + java.util.logging.Logger.getLogger(cl.getLoggerName()); + } + } + long result = System.nanoTime() - start; + System.out.println("Average (in nanos) JUL logger creation: " + (result / s.size())); + } + +} diff --git a/logback-classic/performance/src/java/ch/qos/logback/classic/LoggerEventCreationTest.java b/logback-classic/performance/src/java/ch/qos/logback/classic/LoggerEventCreationTest.java index cd9b92ba8c3b0b7ea33065644540b314945ab463..43e3c216cf1710dff49261087e894821d1bb8726 100644 --- a/logback-classic/performance/src/java/ch/qos/logback/classic/LoggerEventCreationTest.java +++ b/logback-classic/performance/src/java/ch/qos/logback/classic/LoggerEventCreationTest.java @@ -1,65 +1,65 @@ -package ch.qos.logback.classic; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.spi.LoggingEvent; -import junit.framework.TestCase; - - -// it takes about 250 nanos to create a LoggingEvent -public class LoggerEventCreationTest extends TestCase { - - public LoggerEventCreationTest(String arg0) { - super(arg0); - } - - protected void setUp() throws Exception { - super.setUp(); - } - - protected void tearDown() throws Exception { - super.tearDown(); - } - - public void testEventLoop() { - long len = 10000000; - System.out.println((eventLoop(len))/len); - } - - public void testFfilterMethod() { - long len = 10000000; - System.out.println((methodCalLoop(len))/len); - } - - long eventLoop(long len) { - Logger logger = (Logger) LoggerFactory.getLogger(this.getClass()); - LoggingEvent le = null; - long start = System.nanoTime(); - for(long i = 0; i < len; i++) { - le = new LoggingEvent("", logger, Level.DEBUG, "asdasdasd", null, null); - } - le.getLevel(); - long end = System.nanoTime(); - return end-start; - } - - long methodCalLoop(long len) { - Logger logger = (Logger) LoggerFactory.getLogger(this.getClass()); - long start = System.nanoTime(); - for(long i = 0; i < len; i++) { - filterMethod(logger, Level.DEBUG, "asdasdasd", null, null); - } - long end = System.nanoTime(); - return end-start; - } - - int filterMethod(Logger logger, Level level, String msg, Object[] params, Exception e) { - if(level.levelInt < 100) { - return 1; - } else { - return 0; - } - } -} +package ch.qos.logback.classic; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.LoggingEvent; +import junit.framework.TestCase; + + +// it takes about 250 nanos to create a LoggingEvent +public class LoggerEventCreationTest extends TestCase { + + public LoggerEventCreationTest(String arg0) { + super(arg0); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testEventLoop() { + long len = 10000000; + System.out.println((eventLoop(len))/len); + } + + public void testFfilterMethod() { + long len = 10000000; + System.out.println((methodCalLoop(len))/len); + } + + long eventLoop(long len) { + Logger logger = (Logger) LoggerFactory.getLogger(this.getClass()); + LoggingEvent le = null; + long start = System.nanoTime(); + for(long i = 0; i < len; i++) { + le = new LoggingEvent("", logger, Level.DEBUG, "asdasdasd", null, null); + } + le.getLevel(); + long end = System.nanoTime(); + return end-start; + } + + long methodCalLoop(long len) { + Logger logger = (Logger) LoggerFactory.getLogger(this.getClass()); + long start = System.nanoTime(); + for(long i = 0; i < len; i++) { + filterMethod(logger, Level.DEBUG, "asdasdasd", null, null); + } + long end = System.nanoTime(); + return end-start; + } + + int filterMethod(Logger logger, Level level, String msg, Object[] params, Exception e) { + if(level.levelInt < 100) { + return 1; + } else { + return 0; + } + } +} diff --git a/logback-classic/performance/src/java/ch/qos/logback/classic/RetreivalOfExistingLoggerSpeed.java b/logback-classic/performance/src/java/ch/qos/logback/classic/RetreivalOfExistingLoggerSpeed.java index 7d127ebf0dbb27ee3a43f088e3af0ff225ee694b..01dbab7228444554e5573ce1631aa1ae525c423c 100644 --- a/logback-classic/performance/src/java/ch/qos/logback/classic/RetreivalOfExistingLoggerSpeed.java +++ b/logback-classic/performance/src/java/ch/qos/logback/classic/RetreivalOfExistingLoggerSpeed.java @@ -1,94 +1,94 @@ -/** - * LOGBack: the reliable, fast and flexible logging library for Java. - * - * Copyright (C) 1999-2005, QOS.ch, LOGBack.com - * - * This library is free software, you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation. - */ -package ch.qos.logback.classic; - -import java.io.IOException; - -import org.apache.log4j.Hierarchy; -import org.apache.log4j.spi.RootLogger; - -import ch.qos.logback.classic.HLoggerContext; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.control.ControlLoggerContext; -import ch.qos.logback.classic.control.CreateLogger; -import ch.qos.logback.classic.control.Scenario; -import ch.qos.logback.classic.control.ScenarioMaker; - - - -public class RetreivalOfExistingLoggerSpeed { - static final LoggerContext listLoggerContext = new LoggerContext(); - static final HLoggerContext hashLoggerContext = new HLoggerContext(); - static final ControlLoggerContext controlContext = new ControlLoggerContext(); - static final Hierarchy log4jHierarchy = new Hierarchy(new RootLogger(org.apache.log4j.Level.OFF)); - - static String X; - - public static void main(String[] args) throws IOException { - - Scenario s = ScenarioMaker.makeTypeBScenario(2000); - - X = ((CreateLogger) s.get(1000)).getLoggerName(); - System.out.println("name:"+X); - System.err.print("Press a key to continue: "); - System.in.read(); - int x1 = 100000; - for (int i = 0; i < 1; i++) { - x1 *= 2; - getLoggerSpeed(x1); - //getHLoggerSpeed(x1); - getLog4jLoggerSpeed(x1); - getContolLoggerSpeed(x1); - getJULSpeed(x1); - } - } - - static void getLoggerSpeed(final int len) { - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - listLoggerContext.getLogger(X); - } - long result = System.nanoTime() - start; - System.out.println(("Logger ") + (result / len)); - } - - static void getHLoggerSpeed(final int len) { - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - hashLoggerContext.getLogger(X); - } - long result = System.nanoTime() - start; - System.out.println(("HLogger ") + (result / len)); - } - static void getContolLoggerSpeed(final int len) { - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - controlContext.getLogger(X); - } - long result = System.nanoTime() - start; - System.out.println(("ControlLogger ") + (result / len)); - } - static void getJULSpeed(final int len) { - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - java.util.logging.Logger.getLogger(X); - } - long result = System.nanoTime() - start; - System.out.println(("JUL ") + (result / len)); - } - static void getLog4jLoggerSpeed(final int len) { - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - log4jHierarchy.getLogger(X); - } - long result = System.nanoTime() - start; - System.out.println(("Log4j Logger ") + (result / len)); - } -} +/** + * LOGBack: the reliable, fast and flexible logging library for Java. + * + * Copyright (C) 1999-2005, QOS.ch, LOGBack.com + * + * This library is free software, you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation. + */ +package ch.qos.logback.classic; + +import java.io.IOException; + +import org.apache.log4j.Hierarchy; +import org.apache.log4j.spi.RootLogger; + +import ch.qos.logback.classic.HLoggerContext; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.control.ControlLoggerContext; +import ch.qos.logback.classic.control.CreateLogger; +import ch.qos.logback.classic.control.Scenario; +import ch.qos.logback.classic.control.ScenarioMaker; + + + +public class RetreivalOfExistingLoggerSpeed { + static final LoggerContext listLoggerContext = new LoggerContext(); + static final HLoggerContext hashLoggerContext = new HLoggerContext(); + static final ControlLoggerContext controlContext = new ControlLoggerContext(); + static final Hierarchy log4jHierarchy = new Hierarchy(new RootLogger(org.apache.log4j.Level.OFF)); + + static String X; + + public static void main(String[] args) throws IOException { + + Scenario s = ScenarioMaker.makeTypeBScenario(2000); + + X = ((CreateLogger) s.get(1000)).getLoggerName(); + System.out.println("name:"+X); + System.err.print("Press a key to continue: "); + System.in.read(); + int x1 = 100000; + for (int i = 0; i < 1; i++) { + x1 *= 2; + getLoggerSpeed(x1); + //getHLoggerSpeed(x1); + getLog4jLoggerSpeed(x1); + getContolLoggerSpeed(x1); + getJULSpeed(x1); + } + } + + static void getLoggerSpeed(final int len) { + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + listLoggerContext.getLogger(X); + } + long result = System.nanoTime() - start; + System.out.println(("Logger ") + (result / len)); + } + + static void getHLoggerSpeed(final int len) { + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + hashLoggerContext.getLogger(X); + } + long result = System.nanoTime() - start; + System.out.println(("HLogger ") + (result / len)); + } + static void getContolLoggerSpeed(final int len) { + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + controlContext.getLogger(X); + } + long result = System.nanoTime() - start; + System.out.println(("ControlLogger ") + (result / len)); + } + static void getJULSpeed(final int len) { + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + java.util.logging.Logger.getLogger(X); + } + long result = System.nanoTime() - start; + System.out.println(("JUL ") + (result / len)); + } + static void getLog4jLoggerSpeed(final int len) { + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + log4jHierarchy.getLogger(X); + } + long result = System.nanoTime() - start; + System.out.println(("Log4j Logger ") + (result / len)); + } +} diff --git a/logback-classic/performance/src/java/ch/qos/logback/classic/SpeedOfDisabledDebug.java b/logback-classic/performance/src/java/ch/qos/logback/classic/SpeedOfDisabledDebug.java index bbf9afe53ac98db0292c9139e4d716d6dcf6373e..2ed5912afdf60b551e9909e93f9dc13ad2717588 100644 --- a/logback-classic/performance/src/java/ch/qos/logback/classic/SpeedOfDisabledDebug.java +++ b/logback-classic/performance/src/java/ch/qos/logback/classic/SpeedOfDisabledDebug.java @@ -1,144 +1,144 @@ -/** - * LOGBack: the reliable, fast and flexible logging library for Java. - * - * Copyright (C) 1999-2005, QOS.ch, LOGBack.com - * - * This library is free software, you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation. - */ -package ch.qos.logback.classic; - -import java.io.IOException; - -import org.apache.log4j.Hierarchy; -import org.apache.log4j.spi.RootLogger; -//import org.slf4j.impl.JDK14LoggerFactory; - -import ch.qos.logback.classic.HLogger; -import ch.qos.logback.classic.HLoggerContext; -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.control.ControlLogger; -import ch.qos.logback.classic.control.ControlLoggerContext; -import ch.qos.logback.classic.control.CreateLogger; -import ch.qos.logback.classic.control.Scenario; -import ch.qos.logback.classic.control.ScenarioMaker; - - - -public class SpeedOfDisabledDebug { - static LoggerContext loggerContext = new LoggerContext(); - static HLoggerContext hashLoggerContext = new HLoggerContext(); - static ControlLoggerContext controlContext = new ControlLoggerContext(); - static Hierarchy log4jHierarchy = new Hierarchy(new RootLogger(org.apache.log4j.Level.OFF)); - //static JDK14LoggerFactory jdk14FA = new JDK14LoggerFactory(); - static String loggerName; - - public static void main(String[] args) throws IOException { - loggerContext.getLogger(LoggerContext.ROOT_NAME).setLevel(Level.OFF); - hashLoggerContext.getRootLogger().setLevel(Level.OFF); - controlContext.getRootLogger().setLevel(Level.OFF); - //LogManager - //jdk14FA.getLogger("").setLevel(java.util.logging.Level.OFF); - - Scenario s = ScenarioMaker.makeTypeBScenario(1000); - loggerName = ((CreateLogger) s.get(1000)).getLoggerName(); - System.out.println("Logger name is "+loggerName); - - final org.slf4j.Logger slf4jLogger = loggerContext.getLogger(loggerName); - final HLogger hashLogger = hashLoggerContext.getLogger(loggerName); - final ControlLogger controlLogger = controlContext.getLogger(loggerName); - //final org.apache.log4j.Logger log4jLogger = log4jHierarchy.getLogger(loggerName); - //final java.util.logging.Logger jdk14Logger = java.util.logging.Logger.getLogger(loggerName); - int x1 = 1000*1000; - for (int i = 0; i < 2; i++) { - x1 *= 2; - System.out.println("======= len=" + x1); - - speedTestSLF4JLogger(hashLogger, x1, "Hash logger "); - speedTestSLF4JLogger(slf4jLogger, x1, "Logback logger "); - - speedTestSLF4JLogger(controlLogger, x1, "Control logger "); - //speedTestSLF4JLogger(log4jLogger, x1, "Log4j logger "); - //speedTestSLF4JLogger(jdk14Logger, x1, "JDK14 Logger "); - speedTestHashLogger(x1); - speedTestListLogger(x1); - speedTestControlLogger(x1); - speedTestLOG4JLogger(x1); - speedTestJULLogger(x1); - } - } - - - static void speedTestSLF4JLogger(final org.slf4j.Logger logger, final int len, String loggerType) { - logger.debug("some message"); - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - logger.debug("some message"); - } - long result = System.nanoTime() - start; - System.out.println(("SLF4J: " + loggerType) + (result / len)); - } - - static void speedTestListLogger(final int len) { - final Logger logger = loggerContext.getLogger(loggerName); - - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - logger.debug("some message"); - } - long result = System.nanoTime() - start; - System.out.println("DIRECT logback logger: " + (result / len)); - } - - static void speedTestHashLogger(final int len) { - final HLogger logger = hashLoggerContext.getLogger(loggerName); - - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - logger.debug("some message"); - } - long result = System.nanoTime() - start; - System.out.println("DIRECT Hash logger: " + (result / len)); - } - - static void speedTestLOG4JLogger(final int len) { - final org.apache.log4j.Logger logger = log4jHierarchy.getLogger(loggerName); - log4jHierarchy.getLogger("xgssmieubdshsdty"); - log4jHierarchy.getLogger("xgssmieubdshsdty.aqvdsmxzraszxybtrcslsvatbvswq"); - log4jHierarchy.getLogger("xgssmieubdshsdty.aqvdsmxzraszxybtrcslsvatbvswq.yvchlwo"); - log4jHierarchy.getLogger("xgssmieubdshsdty.aqvdsmxzraszxybtrcslsvatbvswq.yvchlwo.xlmoezu"); - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - logger.debug("some message"); - } - long result = System.nanoTime() - start; - System.out.println("DIRECT LOG4J logger " + result / len); - } - - static void speedTestJULLogger(final int len) { - final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(loggerName); - final java.util.logging.Logger root = java.util.logging.Logger.getLogger(""); - root.setLevel(java.util.logging.Level.OFF); - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - logger.fine("some message"); - } - long result = System.nanoTime() - start; - System.out.println("DIRECT JUL logger " + result / len); - } - - static void speedTestControlLogger(final int len) { - final ControlLogger logger = controlContext.getLogger(loggerName); - - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - logger.debug("some message"); - } - long result = System.nanoTime() - start; - System.out.println("DIRECT Control logger: " + result / len); - } - -} +/** + * LOGBack: the reliable, fast and flexible logging library for Java. + * + * Copyright (C) 1999-2005, QOS.ch, LOGBack.com + * + * This library is free software, you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation. + */ +package ch.qos.logback.classic; + +import java.io.IOException; + +import org.apache.log4j.Hierarchy; +import org.apache.log4j.spi.RootLogger; +//import org.slf4j.impl.JDK14LoggerFactory; + +import ch.qos.logback.classic.HLogger; +import ch.qos.logback.classic.HLoggerContext; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.control.ControlLogger; +import ch.qos.logback.classic.control.ControlLoggerContext; +import ch.qos.logback.classic.control.CreateLogger; +import ch.qos.logback.classic.control.Scenario; +import ch.qos.logback.classic.control.ScenarioMaker; + + + +public class SpeedOfDisabledDebug { + static LoggerContext loggerContext = new LoggerContext(); + static HLoggerContext hashLoggerContext = new HLoggerContext(); + static ControlLoggerContext controlContext = new ControlLoggerContext(); + static Hierarchy log4jHierarchy = new Hierarchy(new RootLogger(org.apache.log4j.Level.OFF)); + //static JDK14LoggerFactory jdk14FA = new JDK14LoggerFactory(); + static String loggerName; + + public static void main(String[] args) throws IOException { + loggerContext.getLogger(LoggerContext.ROOT_NAME).setLevel(Level.OFF); + hashLoggerContext.getRootLogger().setLevel(Level.OFF); + controlContext.getRootLogger().setLevel(Level.OFF); + //LogManager + //jdk14FA.getLogger("").setLevel(java.util.logging.Level.OFF); + + Scenario s = ScenarioMaker.makeTypeBScenario(1000); + loggerName = ((CreateLogger) s.get(1000)).getLoggerName(); + System.out.println("Logger name is "+loggerName); + + final org.slf4j.Logger slf4jLogger = loggerContext.getLogger(loggerName); + final HLogger hashLogger = hashLoggerContext.getLogger(loggerName); + final ControlLogger controlLogger = controlContext.getLogger(loggerName); + //final org.apache.log4j.Logger log4jLogger = log4jHierarchy.getLogger(loggerName); + //final java.util.logging.Logger jdk14Logger = java.util.logging.Logger.getLogger(loggerName); + int x1 = 1000*1000; + for (int i = 0; i < 2; i++) { + x1 *= 2; + System.out.println("======= len=" + x1); + + speedTestSLF4JLogger(hashLogger, x1, "Hash logger "); + speedTestSLF4JLogger(slf4jLogger, x1, "Logback logger "); + + speedTestSLF4JLogger(controlLogger, x1, "Control logger "); + //speedTestSLF4JLogger(log4jLogger, x1, "Log4j logger "); + //speedTestSLF4JLogger(jdk14Logger, x1, "JDK14 Logger "); + speedTestHashLogger(x1); + speedTestListLogger(x1); + speedTestControlLogger(x1); + speedTestLOG4JLogger(x1); + speedTestJULLogger(x1); + } + } + + + static void speedTestSLF4JLogger(final org.slf4j.Logger logger, final int len, String loggerType) { + logger.debug("some message"); + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + logger.debug("some message"); + } + long result = System.nanoTime() - start; + System.out.println(("SLF4J: " + loggerType) + (result / len)); + } + + static void speedTestListLogger(final int len) { + final Logger logger = loggerContext.getLogger(loggerName); + + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + logger.debug("some message"); + } + long result = System.nanoTime() - start; + System.out.println("DIRECT logback logger: " + (result / len)); + } + + static void speedTestHashLogger(final int len) { + final HLogger logger = hashLoggerContext.getLogger(loggerName); + + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + logger.debug("some message"); + } + long result = System.nanoTime() - start; + System.out.println("DIRECT Hash logger: " + (result / len)); + } + + static void speedTestLOG4JLogger(final int len) { + final org.apache.log4j.Logger logger = log4jHierarchy.getLogger(loggerName); + log4jHierarchy.getLogger("xgssmieubdshsdty"); + log4jHierarchy.getLogger("xgssmieubdshsdty.aqvdsmxzraszxybtrcslsvatbvswq"); + log4jHierarchy.getLogger("xgssmieubdshsdty.aqvdsmxzraszxybtrcslsvatbvswq.yvchlwo"); + log4jHierarchy.getLogger("xgssmieubdshsdty.aqvdsmxzraszxybtrcslsvatbvswq.yvchlwo.xlmoezu"); + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + logger.debug("some message"); + } + long result = System.nanoTime() - start; + System.out.println("DIRECT LOG4J logger " + result / len); + } + + static void speedTestJULLogger(final int len) { + final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(loggerName); + final java.util.logging.Logger root = java.util.logging.Logger.getLogger(""); + root.setLevel(java.util.logging.Level.OFF); + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + logger.fine("some message"); + } + long result = System.nanoTime() - start; + System.out.println("DIRECT JUL logger " + result / len); + } + + static void speedTestControlLogger(final int len) { + final ControlLogger logger = controlContext.getLogger(loggerName); + + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + logger.debug("some message"); + } + long result = System.nanoTime() - start; + System.out.println("DIRECT Control logger: " + result / len); + } + +} diff --git a/logback-classic/performance/src/java/ch/qos/logback/classic/pattern/ClassNameAbbreviatorSpeed.java b/logback-classic/performance/src/java/ch/qos/logback/classic/pattern/ClassNameAbbreviatorSpeed.java index b8f7e4ebbdc28f97def977f8b04de33635e58bc6..de11a38b4ae3e2accd9548478997c67653b861eb 100644 --- a/logback-classic/performance/src/java/ch/qos/logback/classic/pattern/ClassNameAbbreviatorSpeed.java +++ b/logback-classic/performance/src/java/ch/qos/logback/classic/pattern/ClassNameAbbreviatorSpeed.java @@ -1,33 +1,33 @@ -/** - * LOGBack: the reliable, fast and flexible logging library for Java. - * - * Copyright (C) 1999-2006, QOS.ch - * - * This library is free software, you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation. - */ -package ch.qos.logback.classic.pattern; - -import ch.qos.logback.classic.pattern.ClassNameAbbreviator; - -public class ClassNameAbbreviatorSpeed { - - static ClassNameAbbreviator abbreviator = new ClassNameAbbreviator(21); - static String name = "com.logback.wombat.alligator.tomato.Foobar"; - - public static void main(String[] args) { - loop(1000); - loop(10000); - loop(100000); - } - - static void loop(final int size) { - long start = System.nanoTime(); - for (int i = 0; i < size; i++) { - abbreviator.abbreviate(name); - } - long result = System.nanoTime() - start; - System.out.println("Average abbrev speed: " + (result / size) + " nanos"); - } -} +/** + * LOGBack: the reliable, fast and flexible logging library for Java. + * + * Copyright (C) 1999-2006, QOS.ch + * + * This library is free software, you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation. + */ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.pattern.ClassNameAbbreviator; + +public class ClassNameAbbreviatorSpeed { + + static ClassNameAbbreviator abbreviator = new ClassNameAbbreviator(21); + static String name = "com.logback.wombat.alligator.tomato.Foobar"; + + public static void main(String[] args) { + loop(1000); + loop(10000); + loop(100000); + } + + static void loop(final int size) { + long start = System.nanoTime(); + for (int i = 0; i < size; i++) { + abbreviator.abbreviate(name); + } + long result = System.nanoTime() - start; + System.out.println("Average abbrev speed: " + (result / size) + " nanos"); + } +} diff --git a/logback-classic/performance/src/java/ch/qos/logback/classic/pattern/WriteSpeed.java b/logback-classic/performance/src/java/ch/qos/logback/classic/pattern/WriteSpeed.java index cfcf18905e7443768eee30e1b6bc6a776e85e411..fbede5e6f9fa135554e087cbbc47d57a4fb90ff6 100644 --- a/logback-classic/performance/src/java/ch/qos/logback/classic/pattern/WriteSpeed.java +++ b/logback-classic/performance/src/java/ch/qos/logback/classic/pattern/WriteSpeed.java @@ -1,122 +1,122 @@ -/** - * LOGBack: the reliable, fast and flexible logging library for Java. - * - * Copyright (C) 1999-2005, QOS.ch, LOGBack.com - * - * This library is free software, you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation. - */ -package ch.qos.logback.classic.pattern; - -import java.io.FileOutputStream; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.ArrayList; - -import org.apache.log4j.FileAppender; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; -import org.apache.log4j.PatternLayout; - -public class WriteSpeed { - static final String MSG = "some xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmedium length message sadf;-90123lklkhasdfl lkahjqdlsfh"; - - static final ByteBuffer[] BB = new ByteBuffer[0]; - - public static void main(String[] args) throws Exception { - - long size = 100 * 1000; - nio(size); - oldPattern(size); - } - - - static void oldPattern(long size) throws Exception { - PatternLayout layout = new PatternLayout("%r [%t] %p %c - %m%n"); - FileAppender appender = new FileAppender(layout, "toto.log", false); - - Logger logger = LogManager.getRootLogger(); - logger.removeAllAppenders(); - logger.addAppender(appender); - - long start = System.nanoTime(); - for (int i = 0; i < size; i++) { - logger.info(MSG); - } - long result = System.nanoTime() - start; - System.out.println("Average OLD write speed: " + (result / size) + " nanos"); - } - - static void nio(long size) throws Exception { - - //Charset cs = Charset.forName("ISO-8859-1"); - //Charset cs = Charset.forName("US-ASCII"); - //CharsetEncoder encoder = cs.newEncoder(); - //String str = "1081 [main] INFO root -" + MSG + "\r\n"; - - - //CharBuffer cbuf = CharBuffer.wrap(str); - //ByteBuffer buf = ByteBuffer.wrap(str.getBytes()); - FileOutputStream fos = new FileOutputStream("niototo.log", false); - FileChannel channel = fos.getChannel(); - - //CoderResult cr; - //long s = size*(cbuf.length())/(8*1024); - ByteBuffer[] BALL = new ByteBuffer[] {all}; - long start = System.nanoTime(); - for (int i = 0; i < size; i++) { - - channel.write(BALL); - all.rewind(); -// for (int j = 0; j < al.size(); j++) { -// ByteBuffer bb = (ByteBuffer) al.get(j); -// bb.rewind(); -// } - } - //buf.flip(); - //channel.write(buf); - - long result = System.nanoTime() - start; - System.out.println("NIO Average write speed: " + (result / size) + " nanos"); - - - channel.close(); - - - } - - static ByteBuffer x1 = ByteBuffer.wrap(" [".getBytes()); - static ByteBuffer x2 = ByteBuffer.wrap("] ".getBytes()); - static ByteBuffer x3 = ByteBuffer.wrap("INFO".getBytes()); - static ByteBuffer x4 = ByteBuffer.wrap(" ".getBytes()); - static ByteBuffer x5 = ByteBuffer.wrap(" -".getBytes()); - - static ArrayList bbList = new ArrayList(); - - static ByteBuffer z1 = ByteBuffer.wrap("1081".getBytes()); - static ByteBuffer z2 = ByteBuffer.wrap("main".getBytes()); - static ByteBuffer z3 = ByteBuffer.wrap(MSG.getBytes()); - static ByteBuffer z4 = ByteBuffer.wrap("\r\n".getBytes()); - - static String s = "1081 [main] INFO root - " + MSG + "\r\n"; - static ByteBuffer all = ByteBuffer.wrap(s.getBytes()); - - static ArrayList makeList() { - - // "1081 [main] INFO root -" + MSG + "\r\n"; - bbList.clear(); - bbList.add(all); -// bbList.add(z1); -// bbList.add(x1); -// bbList.add(z2); -// bbList.add(x2); -// bbList.add(x3); -// bbList.add(x4); -// bbList.add(x5); -// bbList.add(z3); -// bbList.add(z4); - return bbList; - - } -} +/** + * LOGBack: the reliable, fast and flexible logging library for Java. + * + * Copyright (C) 1999-2005, QOS.ch, LOGBack.com + * + * This library is free software, you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation. + */ +package ch.qos.logback.classic.pattern; + +import java.io.FileOutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.util.ArrayList; + +import org.apache.log4j.FileAppender; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.apache.log4j.PatternLayout; + +public class WriteSpeed { + static final String MSG = "some xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmedium length message sadf;-90123lklkhasdfl lkahjqdlsfh"; + + static final ByteBuffer[] BB = new ByteBuffer[0]; + + public static void main(String[] args) throws Exception { + + long size = 100 * 1000; + nio(size); + oldPattern(size); + } + + + static void oldPattern(long size) throws Exception { + PatternLayout layout = new PatternLayout("%r [%t] %p %c - %m%n"); + FileAppender appender = new FileAppender(layout, "toto.log", false); + + Logger logger = LogManager.getRootLogger(); + logger.removeAllAppenders(); + logger.addAppender(appender); + + long start = System.nanoTime(); + for (int i = 0; i < size; i++) { + logger.info(MSG); + } + long result = System.nanoTime() - start; + System.out.println("Average OLD write speed: " + (result / size) + " nanos"); + } + + static void nio(long size) throws Exception { + + //Charset cs = Charset.forName("ISO-8859-1"); + //Charset cs = Charset.forName("US-ASCII"); + //CharsetEncoder encoder = cs.newEncoder(); + //String str = "1081 [main] INFO root -" + MSG + "\r\n"; + + + //CharBuffer cbuf = CharBuffer.wrap(str); + //ByteBuffer buf = ByteBuffer.wrap(str.getBytes()); + FileOutputStream fos = new FileOutputStream("niototo.log", false); + FileChannel channel = fos.getChannel(); + + //CoderResult cr; + //long s = size*(cbuf.length())/(8*1024); + ByteBuffer[] BALL = new ByteBuffer[] {all}; + long start = System.nanoTime(); + for (int i = 0; i < size; i++) { + + channel.write(BALL); + all.rewind(); +// for (int j = 0; j < al.size(); j++) { +// ByteBuffer bb = (ByteBuffer) al.get(j); +// bb.rewind(); +// } + } + //buf.flip(); + //channel.write(buf); + + long result = System.nanoTime() - start; + System.out.println("NIO Average write speed: " + (result / size) + " nanos"); + + + channel.close(); + + + } + + static ByteBuffer x1 = ByteBuffer.wrap(" [".getBytes()); + static ByteBuffer x2 = ByteBuffer.wrap("] ".getBytes()); + static ByteBuffer x3 = ByteBuffer.wrap("INFO".getBytes()); + static ByteBuffer x4 = ByteBuffer.wrap(" ".getBytes()); + static ByteBuffer x5 = ByteBuffer.wrap(" -".getBytes()); + + static ArrayList bbList = new ArrayList(); + + static ByteBuffer z1 = ByteBuffer.wrap("1081".getBytes()); + static ByteBuffer z2 = ByteBuffer.wrap("main".getBytes()); + static ByteBuffer z3 = ByteBuffer.wrap(MSG.getBytes()); + static ByteBuffer z4 = ByteBuffer.wrap("\r\n".getBytes()); + + static String s = "1081 [main] INFO root - " + MSG + "\r\n"; + static ByteBuffer all = ByteBuffer.wrap(s.getBytes()); + + static ArrayList makeList() { + + // "1081 [main] INFO root -" + MSG + "\r\n"; + bbList.clear(); + bbList.add(all); +// bbList.add(z1); +// bbList.add(x1); +// bbList.add(z2); +// bbList.add(x2); +// bbList.add(x3); +// bbList.add(x4); +// bbList.add(x5); +// bbList.add(z3); +// bbList.add(z4); + return bbList; + + } +} diff --git a/logback-classic/performance/src/java/ch/qos/logback/reflect/Fruit.java b/logback-classic/performance/src/java/ch/qos/logback/reflect/Fruit.java index 6d2dceefa5797f225fb7ae05b9cce079400ff4a3..13ccca01e78e3e98cd565923109a975dd21cd804 100644 --- a/logback-classic/performance/src/java/ch/qos/logback/reflect/Fruit.java +++ b/logback-classic/performance/src/java/ch/qos/logback/reflect/Fruit.java @@ -1,27 +1,27 @@ -package ch.qos.logback.reflect; - -public class Fruit { - - String color; - boolean sweet; - - Fruit( String color, boolean sweet) { - this.color = color; - this.sweet = sweet; - } - - public String getColor() { - return color; - } - public void setColor(String color) { - this.color = color; - } - public boolean isSweet() { - return sweet; - } - public void setSweet(boolean sweet) { - this.sweet = sweet; - } - - -} +package ch.qos.logback.reflect; + +public class Fruit { + + String color; + boolean sweet; + + Fruit( String color, boolean sweet) { + this.color = color; + this.sweet = sweet; + } + + public String getColor() { + return color; + } + public void setColor(String color) { + this.color = color; + } + public boolean isSweet() { + return sweet; + } + public void setSweet(boolean sweet) { + this.sweet = sweet; + } + + +} diff --git a/logback-classic/performance/src/java/ch/qos/logback/reflect/JEXLTest.java b/logback-classic/performance/src/java/ch/qos/logback/reflect/JEXLTest.java index 868a1d7874d5224e9f6922179e478fb5e8e4d94e..53102e4cfe0848aec9e98cf23112b63dc9a28379 100644 --- a/logback-classic/performance/src/java/ch/qos/logback/reflect/JEXLTest.java +++ b/logback-classic/performance/src/java/ch/qos/logback/reflect/JEXLTest.java @@ -1,66 +1,66 @@ -package ch.qos.logback.reflect; - -import org.apache.commons.jexl.Expression; -import org.apache.commons.jexl.ExpressionFactory; -import org.apache.commons.jexl.JexlContext; -import org.apache.commons.jexl.JexlHelper; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.LoggingEvent; - - -public class JEXLTest { - - /** - * @param args - */ - public static void main(String[] args) throws Exception { - - LoggerContext lc = new LoggerContext(); - Logger logger = lc.getLogger(JaninoTest.class); - LoggingEvent loggingEvent = new LoggingEvent("toto", logger, Level.INFO, - "hi", null); - - // Create an expression object - String jexlExp = "e.message == 'hix'"; - Expression e = ExpressionFactory.createExpression(jexlExp); - - // Create a context and add data - JexlContext jc = JexlHelper.createContext(); - jc.getVars().put("e", loggingEvent); - - // Now evaluate the expression, getting the result - Object o = e.evaluate(jc); - System.out.println("==" + o); - - //loop(e, jc); - - findClassLoop("java.lang.Exception", "java.net.UnknownHostException"); - } - - static void loop(Expression e, JexlContext jc) - throws Exception { - final long start = System.nanoTime(); - final long LEN = 1000 * 1000; - for (int i = 0; i < LEN; i++) { - e.evaluate(jc); - } - final long end = System.nanoTime(); - System.out.println("JEXL avg: " + (end - start) / LEN + " nanos"); - } - - static void findClassLoop(String superClassStr, String childClassStr) throws ClassNotFoundException { - final long start = System.nanoTime(); - final long LEN = 1000 * 1000; - Class superClass = Class.forName(superClassStr); - - for (int i = 0; i < LEN; i++) { - Class childClass = Class.forName(childClassStr); - superClass.isAssignableFrom(childClass); - } - final long end = System.nanoTime(); - System.out.println("FIND CLA avg: " + (end - start) / LEN + " nanos"); - } -} +package ch.qos.logback.reflect; + +import org.apache.commons.jexl.Expression; +import org.apache.commons.jexl.ExpressionFactory; +import org.apache.commons.jexl.JexlContext; +import org.apache.commons.jexl.JexlHelper; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.LoggingEvent; + + +public class JEXLTest { + + /** + * @param args + */ + public static void main(String[] args) throws Exception { + + LoggerContext lc = new LoggerContext(); + Logger logger = lc.getLogger(JaninoTest.class); + LoggingEvent loggingEvent = new LoggingEvent("toto", logger, Level.INFO, + "hi", null); + + // Create an expression object + String jexlExp = "e.message == 'hix'"; + Expression e = ExpressionFactory.createExpression(jexlExp); + + // Create a context and add data + JexlContext jc = JexlHelper.createContext(); + jc.getVars().put("e", loggingEvent); + + // Now evaluate the expression, getting the result + Object o = e.evaluate(jc); + System.out.println("==" + o); + + //loop(e, jc); + + findClassLoop("java.lang.Exception", "java.net.UnknownHostException"); + } + + static void loop(Expression e, JexlContext jc) + throws Exception { + final long start = System.nanoTime(); + final long LEN = 1000 * 1000; + for (int i = 0; i < LEN; i++) { + e.evaluate(jc); + } + final long end = System.nanoTime(); + System.out.println("JEXL avg: " + (end - start) / LEN + " nanos"); + } + + static void findClassLoop(String superClassStr, String childClassStr) throws ClassNotFoundException { + final long start = System.nanoTime(); + final long LEN = 1000 * 1000; + Class superClass = Class.forName(superClassStr); + + for (int i = 0; i < LEN; i++) { + Class childClass = Class.forName(childClassStr); + superClass.isAssignableFrom(childClass); + } + final long end = System.nanoTime(); + System.out.println("FIND CLA avg: " + (end - start) / LEN + " nanos"); + } +} diff --git a/logback-classic/performance/src/java/ch/qos/logback/reflect/JaninoTest.java b/logback-classic/performance/src/java/ch/qos/logback/reflect/JaninoTest.java index 268bdbd09c02f2274fe9e98415093589cd5d435e..63ed41451a4810e14c9f29aff2e9a477721a14d3 100644 --- a/logback-classic/performance/src/java/ch/qos/logback/reflect/JaninoTest.java +++ b/logback-classic/performance/src/java/ch/qos/logback/reflect/JaninoTest.java @@ -1,76 +1,76 @@ -package ch.qos.logback.reflect; - -import org.codehaus.janino.ExpressionEvaluator; -import org.codehaus.janino.Parser.ParseException; -import org.codehaus.janino.Scanner.ScanException; -import org.codehaus.janino.samples.DemoBase; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.LoggingEvent; - - -public class JaninoTest { - - /** - * @param args - * @throws ScanException - * @throws ParseException - * @throws Exception - */ - public static void main(String[] args) throws Exception { - String expression = "import ch.qos.logback.classic.Level; e.getLevel().levelInt <= Level.INFO.levelInt"; - Class optionalExpressionType = boolean.class; - String[] parameterNames = {"e"}; - Class[] parameterTypes = {LoggingEvent.class}; - Class[] thrownExceptions = new Class[0]; - - // Create "ExpressionEvaluator" object. - ExpressionEvaluator ee = new ExpressionEvaluator(expression, - optionalExpressionType, parameterNames, parameterTypes, - thrownExceptions, null // optionalClassLoader - ); - - Object[] parameterValues = new Object[1]; - LoggerContext lc = new LoggerContext(); - - Logger logger = lc.getLogger(JaninoTest.class); - LoggingEvent loggingEvent = new LoggingEvent("toto", logger, Level.INFO, "hi", null); - parameterValues[0] = loggingEvent; - - Object res = ee.evaluate(parameterValues); - - // Print expression result. - System.out.println("Result = " + DemoBase.toString(res)); - System.out.println("Type = " + res.getClass().getName()); - loop(ee, parameterValues); - - // loggingEvent.getMarker() - - expression = "import ch.qos.logback.classic.Level; (e.getMarker() != null) && (e.getMarker().contains(\"yo\"))"; - ee = new ExpressionEvaluator(expression, - optionalExpressionType, parameterNames, parameterTypes, - thrownExceptions, null); - res = ee.evaluate(parameterValues); - - // Print expression result. - System.out.println("Result = " + DemoBase.toString(res)); - System.out.println("Type = " + res.getClass().getName()); - loop(ee, parameterValues); - - } - - static void loop(ExpressionEvaluator ee, Object[] parameterValues) - throws Exception { - final long start = System.nanoTime(); - final long LEN = 1000 * 1000; - for (int i = 0; i < LEN; i++) { - ee.evaluate(parameterValues); - } - final long end = System.nanoTime(); - System.out.println("abg: " + (end - start) / LEN + " nanos"); - - } - -} +package ch.qos.logback.reflect; + +import org.codehaus.janino.ExpressionEvaluator; +import org.codehaus.janino.Parser.ParseException; +import org.codehaus.janino.Scanner.ScanException; +import org.codehaus.janino.samples.DemoBase; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.LoggingEvent; + + +public class JaninoTest { + + /** + * @param args + * @throws ScanException + * @throws ParseException + * @throws Exception + */ + public static void main(String[] args) throws Exception { + String expression = "import ch.qos.logback.classic.Level; e.getLevel().levelInt <= Level.INFO.levelInt"; + Class optionalExpressionType = boolean.class; + String[] parameterNames = {"e"}; + Class[] parameterTypes = {LoggingEvent.class}; + Class[] thrownExceptions = new Class[0]; + + // Create "ExpressionEvaluator" object. + ExpressionEvaluator ee = new ExpressionEvaluator(expression, + optionalExpressionType, parameterNames, parameterTypes, + thrownExceptions, null // optionalClassLoader + ); + + Object[] parameterValues = new Object[1]; + LoggerContext lc = new LoggerContext(); + + Logger logger = lc.getLogger(JaninoTest.class); + LoggingEvent loggingEvent = new LoggingEvent("toto", logger, Level.INFO, "hi", null); + parameterValues[0] = loggingEvent; + + Object res = ee.evaluate(parameterValues); + + // Print expression result. + System.out.println("Result = " + DemoBase.toString(res)); + System.out.println("Type = " + res.getClass().getName()); + loop(ee, parameterValues); + + // loggingEvent.getMarker() + + expression = "import ch.qos.logback.classic.Level; (e.getMarker() != null) && (e.getMarker().contains(\"yo\"))"; + ee = new ExpressionEvaluator(expression, + optionalExpressionType, parameterNames, parameterTypes, + thrownExceptions, null); + res = ee.evaluate(parameterValues); + + // Print expression result. + System.out.println("Result = " + DemoBase.toString(res)); + System.out.println("Type = " + res.getClass().getName()); + loop(ee, parameterValues); + + } + + static void loop(ExpressionEvaluator ee, Object[] parameterValues) + throws Exception { + final long start = System.nanoTime(); + final long LEN = 1000 * 1000; + for (int i = 0; i < LEN; i++) { + ee.evaluate(parameterValues); + } + final long end = System.nanoTime(); + System.out.println("abg: " + (end - start) / LEN + " nanos"); + + } + +} diff --git a/logback-classic/performance/src/java/ch/qos/logback/reflect/ReflectionSpeed.java b/logback-classic/performance/src/java/ch/qos/logback/reflect/ReflectionSpeed.java index 504e1505a806318b1d3f73b4ac15a8a0c92c646e..81f6c6af8fd78ff3c7e9811ea74919b839cab0b5 100644 --- a/logback-classic/performance/src/java/ch/qos/logback/reflect/ReflectionSpeed.java +++ b/logback-classic/performance/src/java/ch/qos/logback/reflect/ReflectionSpeed.java @@ -1,35 +1,35 @@ -package ch.qos.logback.reflect; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -public class ReflectionSpeed { - - static final Class[] EMPTY_CLASS_PARAM = new Class[] {}; - static final Object[] EMPTY_OBJECT_PARAM = new Object[] {}; - - public static void main(String[] args) throws Exception { - - Fruit f = new Fruit("red", true); - - Class fruitClass = Fruit.class; - Method getColorMethod = fruitClass.getDeclaredMethod("getColor", EMPTY_CLASS_PARAM); - loop(getColorMethod, f); - loop(getColorMethod, f); - loop(getColorMethod, f); - } - - static void loop(Method getColorMethod, Fruit fruit) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - final int LEN = 100*1000; - - long start = System.nanoTime(); - for(int i = 0; i < LEN; i++) { - getColorMethod.invoke(fruit, EMPTY_OBJECT_PARAM ); - } - - long end = System.nanoTime(); - System.out.println("avg: "+((end-start)/LEN)+" nanos"); - } - - -} +package ch.qos.logback.reflect; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class ReflectionSpeed { + + static final Class[] EMPTY_CLASS_PARAM = new Class[] {}; + static final Object[] EMPTY_OBJECT_PARAM = new Object[] {}; + + public static void main(String[] args) throws Exception { + + Fruit f = new Fruit("red", true); + + Class fruitClass = Fruit.class; + Method getColorMethod = fruitClass.getDeclaredMethod("getColor", EMPTY_CLASS_PARAM); + loop(getColorMethod, f); + loop(getColorMethod, f); + loop(getColorMethod, f); + } + + static void loop(Method getColorMethod, Fruit fruit) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + final int LEN = 100*1000; + + long start = System.nanoTime(); + for(int i = 0; i < LEN; i++) { + getColorMethod.invoke(fruit, EMPTY_OBJECT_PARAM ); + } + + long end = System.nanoTime(); + System.out.println("avg: "+((end-start)/LEN)+" nanos"); + } + + +} diff --git a/logback-classic/pom.xml b/logback-classic/pom.xml index cbb6beaf0adf90dd668cab5c84fb09e9918fa7e0..c6a1a895662aee16de0661fb393a6647252cf559 100644 --- a/logback-classic/pom.xml +++ b/logback-classic/pom.xml @@ -1,274 +1,274 @@ - - - - ch.qos.logback - logback-parent - 0.9.18-SNAPSHOT - - - 4.0.0 - - ch.qos.logback - logback-classic - ${parent.version} - jar - Logback Classic Module - - http://logback.qos.ch - - Logback: the reliable, generic, fast and flexible logging library for Java. - - - - - Eclipse Public License - v 1.0 - http://www.eclipse.org/legal/epl-v10.html - - - - GNU Lesser General Public License - http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - - - - - - ch.qos.logback - logback-core - compile - - - - org.slf4j - slf4j-api - compile - - - - org.slf4j - slf4j-ext - ${slf4j.version} - test - - - - org.slf4j - slf4j-api - test-jar - ${slf4j.version} - test - - - - org.slf4j - log4j-over-slf4j - ${slf4j.version} - test - - - - - dom4j - dom4j - test - - - - hsqldb - hsqldb - test - - - - javax.mail - mail - compile - true - - - - janino - janino - compile - true - - - - ch.qos.logback - logback-core - test-jar - test - - - - org.apache.geronimo.specs - geronimo-jms_1.1_spec - compile - true - - - - javax.servlet - servlet-api - compile - true - - - - com.icegreen - greenmail - 1.3 - test - - - - org.subethamail - subethasmtp - 2.1.0 - test - - - org.slf4j - slf4j-api - - - - - - joda-time - joda-time - 1.6 - test - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - - - - - bundle-test-jar - package - - jar - test-jar - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - once - plain - false - - **/AllClassicTest.java - **/PackageTest.java - **/TestConstants.java - **/SerializationPerfsTest.java - - - - - org.apache.felix - maven-bundle-plugin - true - - - bundle-manifest - process-classes - - manifest - - - - - - ch.qos.logback.classic*, org.slf4j.impl;version=${slf4j.version} - - - - sun.reflect;resolution:=optional, - javax.*;resolution:=optional, - org.xml.*;resolution:=optional, - ch.qos.logback.core.rolling, - ch.qos.logback.core.rolling.helper, - * - - - J2SE-1.5 - - - - - - - - - - - - host-orion - - - - mysql - mysql-connector-java - 5.0.8 - test - - - - postgresql - postgresql - 8.2-507.jdbc3 - - - - - com.microsoft.sqlserver - sqljdbc4 - 2.0 - test - - - - com.oracle - ojdbc14 - 10.2.0.1 - test - - - - - - - + + + + ch.qos.logback + logback-parent + 0.9.18-SNAPSHOT + + + 4.0.0 + + ch.qos.logback + logback-classic + ${parent.version} + jar + Logback Classic Module + + http://logback.qos.ch + + Logback: the reliable, generic, fast and flexible logging library for Java. + + + + + Eclipse Public License - v 1.0 + http://www.eclipse.org/legal/epl-v10.html + + + + GNU Lesser General Public License + http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html + + + + + + ch.qos.logback + logback-core + compile + + + + org.slf4j + slf4j-api + compile + + + + org.slf4j + slf4j-ext + ${slf4j.version} + test + + + + org.slf4j + slf4j-api + test-jar + ${slf4j.version} + test + + + + org.slf4j + log4j-over-slf4j + ${slf4j.version} + test + + + + + dom4j + dom4j + test + + + + hsqldb + hsqldb + test + + + + javax.mail + mail + compile + true + + + + janino + janino + compile + true + + + + ch.qos.logback + logback-core + test-jar + test + + + + org.apache.geronimo.specs + geronimo-jms_1.1_spec + compile + true + + + + javax.servlet + servlet-api + compile + true + + + + com.icegreen + greenmail + 1.3 + test + + + + org.subethamail + subethasmtp + 2.1.0 + test + + + org.slf4j + slf4j-api + + + + + + joda-time + joda-time + 1.6 + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + + bundle-test-jar + package + + jar + test-jar + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + once + plain + false + + **/AllClassicTest.java + **/PackageTest.java + **/TestConstants.java + **/SerializationPerfsTest.java + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + ch.qos.logback.classic*, org.slf4j.impl;version=${slf4j.version} + + + + sun.reflect;resolution:=optional, + javax.*;resolution:=optional, + org.xml.*;resolution:=optional, + ch.qos.logback.core.rolling, + ch.qos.logback.core.rolling.helper, + * + + + J2SE-1.5 + + + + + + + + + + + + host-orion + + + + mysql + mysql-connector-java + 5.0.8 + test + + + + postgresql + postgresql + 8.2-507.jdbc3 + + + + + com.microsoft.sqlserver + sqljdbc4 + 2.0 + test + + + + com.oracle + ojdbc14 + 10.2.0.1 + test + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/BasicConfigurator.java b/logback-classic/src/main/java/ch/qos/logback/classic/BasicConfigurator.java index 5e2af51daf690141f527e7330232dd00fcf914d1..6d7a9cef32fd32bf27c5b38b3c36280e5554e2e9 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/BasicConfigurator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/BasicConfigurator.java @@ -1,61 +1,61 @@ -/** - * 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.classic; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.ConsoleAppender; -import ch.qos.logback.core.status.InfoStatus; -import ch.qos.logback.core.status.StatusManager; - -/** - * BasicConfigurator configures logback-classic by attaching a - * {@link ConsoleAppender} to the root logger. The console appender's layout - * is set to a {@link PatternLayout} with the pattern - * "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n". - * - * @author Ceki Gulcu - */ -public class BasicConfigurator { - - final static BasicConfigurator hiddenSingleton = new BasicConfigurator(); - - private BasicConfigurator() { - } - - public static void configure(LoggerContext lc) { - StatusManager sm = lc.getStatusManager(); - if(sm != null) { - sm.add(new InfoStatus("Setting up default configuration.", lc)); - } - ConsoleAppender ca = new ConsoleAppender(); - ca.setContext(lc); - ca.setName("console"); - PatternLayout pl = new PatternLayout(); - pl.setContext(lc); - pl.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"); - pl.start(); - - ca.setLayout(pl); - ca.start(); - Logger rootLogger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - rootLogger.addAppender(ca); - } - - public static void configureDefaultContext() { - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - configure(lc); - } -} +/** + * 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.classic; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.ConsoleAppender; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.StatusManager; + +/** + * BasicConfigurator configures logback-classic by attaching a + * {@link ConsoleAppender} to the root logger. The console appender's layout + * is set to a {@link PatternLayout} with the pattern + * "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n". + * + * @author Ceki Gulcu + */ +public class BasicConfigurator { + + final static BasicConfigurator hiddenSingleton = new BasicConfigurator(); + + private BasicConfigurator() { + } + + public static void configure(LoggerContext lc) { + StatusManager sm = lc.getStatusManager(); + if(sm != null) { + sm.add(new InfoStatus("Setting up default configuration.", lc)); + } + ConsoleAppender ca = new ConsoleAppender(); + ca.setContext(lc); + ca.setName("console"); + PatternLayout pl = new PatternLayout(); + pl.setContext(lc); + pl.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"); + pl.start(); + + ca.setLayout(pl); + ca.start(); + Logger rootLogger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + rootLogger.addAppender(ca); + } + + public static void configureDefaultContext() { + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + configure(lc); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java b/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java index b2a9fe5a21d9acf1825a464cfdb941e266d694e5..8f06e53041bc6cb59b4e42b94a3b96480bbee47e 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java @@ -1,35 +1,35 @@ -/** - * 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.classic; - -public class ClassicConstants { - static public final String USER_MDC_KEY = "user"; - - public static final String LOGBACK_CONTEXT_SELECTOR = "logback.ContextSelector"; - public static String JNDI_CONFIGURATION_RESOURCE = "java:comp/env/logback/configuration-resource"; - public static String JNDI_CONTEXT_NAME = "java:comp/env/logback/context-name"; - - /** - * The maximum number of package separators (dots) that abbreviation - * algorithms can handle. Class or logger names with more separators will have - * their first MAX_DOTS parts shortened. - * - */ - public static final int MAX_DOTS = 16; - - /** - * The default stack data depth computed during caller data extraction. - */ - public static final int DEFAULT_MAX_CALLEDER_DATA_DEPTH = 8; -} +/** + * 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.classic; + +public class ClassicConstants { + static public final String USER_MDC_KEY = "user"; + + public static final String LOGBACK_CONTEXT_SELECTOR = "logback.ContextSelector"; + public static String JNDI_CONFIGURATION_RESOURCE = "java:comp/env/logback/configuration-resource"; + public static String JNDI_CONTEXT_NAME = "java:comp/env/logback/context-name"; + + /** + * The maximum number of package separators (dots) that abbreviation + * algorithms can handle. Class or logger names with more separators will have + * their first MAX_DOTS parts shortened. + * + */ + public static final int MAX_DOTS = 16; + + /** + * The default stack data depth computed during caller data extraction. + */ + public static final int DEFAULT_MAX_CALLEDER_DATA_DEPTH = 8; +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/Level.java b/logback-classic/src/main/java/ch/qos/logback/classic/Level.java index 1dd95dff3c340387fd836b53050cd5e39d6dd4a5..7a3798e92aedad51b7c3b9794f25e0619c14953f 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/Level.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/Level.java @@ -1,236 +1,236 @@ -/** - * 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.classic; - -/** - * Defines the set of levels recognized by logback-classic, that is {@link #OFF}, - * {@link #ERROR}, {@link #WARN}, {@link #INFO}, {@link #DEBUG}, - * {@link #TRACE} and {@link #ALL}.

The Level class is - * final and cannot be sub-classed. - *

- */ -public final class Level implements java.io.Serializable { - - private static final long serialVersionUID = -814092767334282137L; - - public static final int OFF_INT = Integer.MAX_VALUE; - public static final int ERROR_INT = 40000; - public static final int WARN_INT = 30000; - public static final int INFO_INT = 20000; - public static final int DEBUG_INT = 10000; - public static final int TRACE_INT = 5000; - public static final int ALL_INT = Integer.MIN_VALUE; - - public static final Integer OFF_INTEGER = new Integer(OFF_INT); - public static final Integer ERROR_INTEGER = new Integer(ERROR_INT); - public static final Integer WARN_INTEGER = new Integer(WARN_INT); - public static final Integer INFO_INTEGER = new Integer(INFO_INT); - public static final Integer DEBUG_INTEGER = new Integer(DEBUG_INT); - public static final Integer TRACE_INTEGER = new Integer(DEBUG_INT); - public static final Integer ALL_INTEGER = new Integer(ALL_INT); - - /** - * The OFF is used to turn off logging. - */ - public static final Level OFF = new Level(OFF_INT, "OFF"); - - /** - * The ERROR level designates error events which may or not - * be fatal to the application. - */ - public static final Level ERROR = new Level(ERROR_INT, "ERROR"); - - /** - * The WARN level designates potentially harmful situations. - */ - public static final Level WARN = new Level(WARN_INT, "WARN"); - - /** - * The INFO level designates informational messages - * highlighting overall progress of the application. - */ - public static final Level INFO = new Level(INFO_INT, "INFO"); - - /** - * The DEBUG level designates informational events of lower - * importance. - */ - public static final Level DEBUG = new Level(DEBUG_INT, "DEBUG"); - - /** - * The TRACE level designates informational events of very low - * importance. - */ - public static final Level TRACE = new Level(TRACE_INT, "TRACE"); - - /** - * The ALL is used to turn on all logging. - */ - public static final Level ALL = new Level(ALL_INT, "ALL"); - - public final int levelInt; - public final String levelStr; - - /** - * Instantiate a Level object. - */ - private Level(int levelInt, String levelStr) { - this.levelInt = levelInt; - this.levelStr = levelStr; - } - - /** - * Returns the string representation of this Level. - */ - public final String toString() { - return levelStr; - } - - /** - * Returns the integer representation of this Level. - */ - public final int toInt() { - return levelInt; - } - - /** - * Convert a Level to an Integer object. - * - * @return This level's Integer mapping. - */ - public final Integer toInteger() { - switch (levelInt) { - case ALL_INT: - return ALL_INTEGER; - case TRACE_INT: - return TRACE_INTEGER; - case DEBUG_INT: - return DEBUG_INTEGER; - case INFO_INT: - return INFO_INTEGER; - case WARN_INT: - return WARN_INTEGER; - case ERROR_INT: - return ERROR_INTEGER; - case OFF_INT: - return OFF_INTEGER; - default: - throw new IllegalStateException("Level " + levelStr + ", " + levelInt - + " is unknown."); - } - } - - /** - * Returns true if this Level has a higher or equal Level than - * the Level passed as argument, false otherwise. - */ - public boolean isGreaterOrEqual(Level r) { - return levelInt >= r.levelInt; - } - - /** - * Convert the string passed as argument to a Level. If the conversion fails, - * then this method returns {@link #DEBUG}. - */ - public static Level toLevel(String sArg) { - return toLevel(sArg, Level.DEBUG); - } - - - /** - * This method exists in order to comply with Joran's valueOf convention. - * @param sArg - * @return - */ - public static Level valueOf(String sArg) { - return toLevel(sArg, Level.DEBUG); - } - - - /** - * Convert an integer passed as argument to a Level. If the conversion fails, - * then this method returns {@link #DEBUG}. - */ - public static Level toLevel(int val) { - return toLevel(val, Level.DEBUG); - } - - /** - * Convert an integer passed as argument to a Level. If the conversion fails, - * then this method returns the specified default. - */ - public static Level toLevel(int val, Level defaultLevel) { - switch (val) { - case ALL_INT: - return ALL; - case TRACE_INT: - return TRACE; - case DEBUG_INT: - return DEBUG; - case INFO_INT: - return INFO; - case WARN_INT: - return WARN; - case ERROR_INT: - return ERROR; - case OFF_INT: - return OFF; - default: - return defaultLevel; - } - } - - /** - * Convert the string passed as argument to a Level. If the conversion fails, - * then this method returns the value of defaultLevel. - */ - public static Level toLevel(String sArg, Level defaultLevel) { - if (sArg == null) { - return defaultLevel; - } - - if (sArg.equalsIgnoreCase("ALL")) { - return Level.ALL; - } - if (sArg.equalsIgnoreCase("TRACE")) { - return Level.TRACE; - } - if (sArg.equalsIgnoreCase("DEBUG")) { - return Level.DEBUG; - } - if (sArg.equalsIgnoreCase("INFO")) { - return Level.INFO; - } - if (sArg.equalsIgnoreCase("WARN")) { - return Level.WARN; - } - if (sArg.equalsIgnoreCase("ERROR")) { - return Level.ERROR; - } - if (sArg.equalsIgnoreCase("OFF")) { - return Level.OFF; - } - return defaultLevel; - } - - /** - * Return the flyweight instance of the level received through serizalization, - * i.e. 'this'. - * - * @return The appropriate flyweight instance - */ - private Object readResolve() { - return toLevel(this.levelInt); - } -} +/** + * 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.classic; + +/** + * Defines the set of levels recognized by logback-classic, that is {@link #OFF}, + * {@link #ERROR}, {@link #WARN}, {@link #INFO}, {@link #DEBUG}, + * {@link #TRACE} and {@link #ALL}.

The Level class is + * final and cannot be sub-classed. + *

+ */ +public final class Level implements java.io.Serializable { + + private static final long serialVersionUID = -814092767334282137L; + + public static final int OFF_INT = Integer.MAX_VALUE; + public static final int ERROR_INT = 40000; + public static final int WARN_INT = 30000; + public static final int INFO_INT = 20000; + public static final int DEBUG_INT = 10000; + public static final int TRACE_INT = 5000; + public static final int ALL_INT = Integer.MIN_VALUE; + + public static final Integer OFF_INTEGER = new Integer(OFF_INT); + public static final Integer ERROR_INTEGER = new Integer(ERROR_INT); + public static final Integer WARN_INTEGER = new Integer(WARN_INT); + public static final Integer INFO_INTEGER = new Integer(INFO_INT); + public static final Integer DEBUG_INTEGER = new Integer(DEBUG_INT); + public static final Integer TRACE_INTEGER = new Integer(DEBUG_INT); + public static final Integer ALL_INTEGER = new Integer(ALL_INT); + + /** + * The OFF is used to turn off logging. + */ + public static final Level OFF = new Level(OFF_INT, "OFF"); + + /** + * The ERROR level designates error events which may or not + * be fatal to the application. + */ + public static final Level ERROR = new Level(ERROR_INT, "ERROR"); + + /** + * The WARN level designates potentially harmful situations. + */ + public static final Level WARN = new Level(WARN_INT, "WARN"); + + /** + * The INFO level designates informational messages + * highlighting overall progress of the application. + */ + public static final Level INFO = new Level(INFO_INT, "INFO"); + + /** + * The DEBUG level designates informational events of lower + * importance. + */ + public static final Level DEBUG = new Level(DEBUG_INT, "DEBUG"); + + /** + * The TRACE level designates informational events of very low + * importance. + */ + public static final Level TRACE = new Level(TRACE_INT, "TRACE"); + + /** + * The ALL is used to turn on all logging. + */ + public static final Level ALL = new Level(ALL_INT, "ALL"); + + public final int levelInt; + public final String levelStr; + + /** + * Instantiate a Level object. + */ + private Level(int levelInt, String levelStr) { + this.levelInt = levelInt; + this.levelStr = levelStr; + } + + /** + * Returns the string representation of this Level. + */ + public final String toString() { + return levelStr; + } + + /** + * Returns the integer representation of this Level. + */ + public final int toInt() { + return levelInt; + } + + /** + * Convert a Level to an Integer object. + * + * @return This level's Integer mapping. + */ + public final Integer toInteger() { + switch (levelInt) { + case ALL_INT: + return ALL_INTEGER; + case TRACE_INT: + return TRACE_INTEGER; + case DEBUG_INT: + return DEBUG_INTEGER; + case INFO_INT: + return INFO_INTEGER; + case WARN_INT: + return WARN_INTEGER; + case ERROR_INT: + return ERROR_INTEGER; + case OFF_INT: + return OFF_INTEGER; + default: + throw new IllegalStateException("Level " + levelStr + ", " + levelInt + + " is unknown."); + } + } + + /** + * Returns true if this Level has a higher or equal Level than + * the Level passed as argument, false otherwise. + */ + public boolean isGreaterOrEqual(Level r) { + return levelInt >= r.levelInt; + } + + /** + * Convert the string passed as argument to a Level. If the conversion fails, + * then this method returns {@link #DEBUG}. + */ + public static Level toLevel(String sArg) { + return toLevel(sArg, Level.DEBUG); + } + + + /** + * This method exists in order to comply with Joran's valueOf convention. + * @param sArg + * @return + */ + public static Level valueOf(String sArg) { + return toLevel(sArg, Level.DEBUG); + } + + + /** + * Convert an integer passed as argument to a Level. If the conversion fails, + * then this method returns {@link #DEBUG}. + */ + public static Level toLevel(int val) { + return toLevel(val, Level.DEBUG); + } + + /** + * Convert an integer passed as argument to a Level. If the conversion fails, + * then this method returns the specified default. + */ + public static Level toLevel(int val, Level defaultLevel) { + switch (val) { + case ALL_INT: + return ALL; + case TRACE_INT: + return TRACE; + case DEBUG_INT: + return DEBUG; + case INFO_INT: + return INFO; + case WARN_INT: + return WARN; + case ERROR_INT: + return ERROR; + case OFF_INT: + return OFF; + default: + return defaultLevel; + } + } + + /** + * Convert the string passed as argument to a Level. If the conversion fails, + * then this method returns the value of defaultLevel. + */ + public static Level toLevel(String sArg, Level defaultLevel) { + if (sArg == null) { + return defaultLevel; + } + + if (sArg.equalsIgnoreCase("ALL")) { + return Level.ALL; + } + if (sArg.equalsIgnoreCase("TRACE")) { + return Level.TRACE; + } + if (sArg.equalsIgnoreCase("DEBUG")) { + return Level.DEBUG; + } + if (sArg.equalsIgnoreCase("INFO")) { + return Level.INFO; + } + if (sArg.equalsIgnoreCase("WARN")) { + return Level.WARN; + } + if (sArg.equalsIgnoreCase("ERROR")) { + return Level.ERROR; + } + if (sArg.equalsIgnoreCase("OFF")) { + return Level.OFF; + } + return defaultLevel; + } + + /** + * Return the flyweight instance of the level received through serizalization, + * i.e. 'this'. + * + * @return The appropriate flyweight instance + */ + private Object readResolve() { + return toLevel(this.levelInt); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java b/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java index 50d6de9ec60f2cd833b22a7eb03a6eecb7c96128..0d2957f89ffd00c34ff0c51f2f968b361c31f4ef 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java @@ -1,852 +1,852 @@ -/** - * 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.classic; - -import java.io.ObjectStreamException; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.slf4j.LoggerFactory; -import org.slf4j.Marker; -import org.slf4j.spi.LocationAwareLogger; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggerRemoteView; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.spi.AppenderAttachable; -import ch.qos.logback.core.spi.AppenderAttachableImpl; -import ch.qos.logback.core.spi.FilterReply; - -public final class Logger implements org.slf4j.Logger, LocationAwareLogger, - AppenderAttachable, Serializable { - - /** - * - */ - private static final long serialVersionUID = 5454405123156820674L; - - /** - * The fully qualified name of this class. Used in gathering caller - * information. - */ - public static final String FQCN = ch.qos.logback.classic.Logger.class - .getName(); - - static int instanceCount = 0; - - /** - * The name of this logger - */ - private String name; - - // The assigned levelInt of this logger. Can be null. - private Level level; - - // The effective levelInt is the assigned levelInt and if null, a levelInt is - // inherited form a parent. - private int effectiveLevelInt; - - /** - * The parent of this category. All categories have at least one ancestor - * which is the root category. - */ - private Logger parent; - - /** - * The children of this logger. A logger may have zero or more children. - */ - private List childrenList; - - /** - * It is assumed that once the 'aai' variable is set to a non-null value, it - * will never be reset to null. it is further assumed that only place where - * the 'aai'ariable is set is within the addAppender method. This method is - * synchronized on 'this' (Logger) protecting against simultaneous - * re-configuration of this logger (a very unlikely scenario). - * - *

It is further assumed that the AppenderAttachableImpl is responsible - * for its internal synchronization and thread safety. Thus, we can get away - * with *not* synchronizing on the 'aai' (check null/ read) because

1) the - * 'aai' variable is immutable once set to non-null

2) 'aai' is getAndSet - * only within addAppender which is synchronized

3) all the other methods - * check whether 'aai' is null

4) AppenderAttachableImpl is thread safe - */ - private transient AppenderAttachableImpl aai; - /** - * Additivity is set to true by default, that is children inherit the - * appenders of their ancestors by default. If this variable is set to - * false then the appenders located in the ancestors of this - * logger will not be used. However, the children of this logger will inherit - * its appenders, unless the children have their additivity flag set to - * false too. See the user manual for more details. - */ - private boolean additive = true; - - final transient LoggerContext loggerContext; - // loggerRemoteView cannot be final because it may change as a consequence - // of changes in LoggerContext - LoggerRemoteView loggerRemoteView; - - Logger(String name, Logger parent, LoggerContext loggerContext) { - this.name = name; - this.parent = parent; - this.loggerContext = loggerContext; - buildRemoteView(); - instanceCount++; - } - - public final Level getEffectiveLevel() { - return Level.toLevel(effectiveLevelInt); - } - - int getEffectiveLevelInt() { - return effectiveLevelInt; - } - - public Level getLevel() { - return level; - } - - public String getName() { - return name; - } - - private final boolean isRootLogger() { - // only the root logger has a null parent - return parent == null; - } - - // Logger getChildBySuffix(final String suffix) method was here and got - // removed. - - Logger getChildByName(final String childName) { - if (childrenList == null) { - return null; - } else { - int len = this.childrenList.size(); - for (int i = 0; i < len; i++) { - final Logger childLogger_i = (Logger) childrenList.get(i); - final String childName_i = childLogger_i.getName(); - - if (childName.equals(childName_i)) { - return childLogger_i; - } - } - // no child found - return null; - } - } - - public synchronized void setLevel(Level newLevel) { - if (level == newLevel) { - // nothing to do; - return; - } - if(newLevel == null && isRootLogger()) { - throw new IllegalArgumentException("The level of the root logger cannot be set to null"); - } - - level = newLevel; - if (newLevel == null) { - effectiveLevelInt = parent.effectiveLevelInt; - } else { - effectiveLevelInt = newLevel.levelInt; - } - - if (childrenList != null) { - int len = childrenList.size(); - for (int i = 0; i < len; i++) { - Logger child = (Logger) childrenList.get(i); - // tell child to handle parent levelInt change - child.handleParentLevelChange(effectiveLevelInt); - } - } - } - - /** - * This method is invoked by parent logger to let this logger know that the - * prent's levelInt changed. - * - * @param newParentLevel - */ - private synchronized void handleParentLevelChange(int newParentLevelInt) { - // changes in the parent levelInt affect children only if their levelInt is - // null - if (level == null) { - effectiveLevelInt = newParentLevelInt; - - // propagate the parent levelInt change to this logger's children - if (childrenList != null) { - int len = childrenList.size(); - for (int i = 0; i < len; i++) { - Logger child = (Logger) childrenList.get(i); - child.handleParentLevelChange(newParentLevelInt); - } - } - } - } - - /** - * Remove all previously added appenders from this logger instance.

This - * is useful when re-reading configuration information. - */ - public void detachAndStopAllAppenders() { - if (aai != null) { - aai.detachAndStopAllAppenders(); - } - } - - public boolean detachAppender(String name) { - if (aai == null) { - return false; - } - return aai.detachAppender(name); - } - - // this method MUST be synchronized. See comments on 'aai' field for further - // details. - public synchronized void addAppender(Appender newAppender) { - if (aai == null) { - aai = new AppenderAttachableImpl(); - } - aai.addAppender(newAppender); - } - - public boolean isAttached(Appender appender) { - if (aai == null) { - return false; - } - return aai.isAttached(appender); - } - - @SuppressWarnings("unchecked") - public Iterator> iteratorForAppenders() { - if (aai == null) { - return Collections.EMPTY_LIST.iterator(); - } - return aai.iteratorForAppenders(); - } - - public Appender getAppender(String name) { - if (aai == null) { - return null; - } - return aai.getAppender(name); - } - - /** - * Invoke all the appenders of this logger. - * - * @param event - * The event to log - */ - public void callAppenders(ILoggingEvent event) { - int writes = 0; - for (Logger l = this; l != null; l = l.parent) { - writes += l.appendLoopOnAppenders(event); - if (!l.additive) { - break; - } - } - // No appenders in hierarchy - if (writes == 0) { - loggerContext.noAppenderDefinedWarning(this); - } - } - - private int appendLoopOnAppenders(ILoggingEvent event) { - if (aai != null) { - return aai.appendLoopOnAppenders(event); - } else { - return 0; - } - } - - /** - * Remove the appender passed as parameter form the list of appenders. - */ - public boolean detachAppender(Appender appender) { - if (aai == null) { - return false; - } - return aai.detachAppender(appender); - } - - static int getSeparatorIndexOf(String name) { - return getSeparatorIndexOf(name, 0); - } - - /** - * Get the position of the separator character, if any, starting at position - * 'fromIndex'. - * - * @param name - * @param fromIndex - * @return - */ - static int getSeparatorIndexOf(String name, int fromIndex) { - int i = name.indexOf(CoreConstants.DOT, fromIndex); - if(i != -1) { - return i; - } else { - return name.indexOf(CoreConstants.DOLLAR, fromIndex); - } - } - - /** - * Create a child of this logger by suffix, that is, the part of the name - * extending this logger. For example, if this logger is named "x.y" and the - * lastPart is "z", then the created child logger will be named "x.y.z". - * - *

IMPORTANT: Calls to this method must be within a synchronized block on - * this logger. - * - * @param lastPart - * the suffix (i.e. last part) of the child logger name. This - * parameter may not include dots, i.e. the logger separator - * character. - * @return - */ - Logger createChildByLastNamePart(final String lastPart) { - int i_index = getSeparatorIndexOf(lastPart); - if (i_index != -1) { - throw new IllegalArgumentException("Child name [" + lastPart - + " passed as parameter, may not include [" - + CoreConstants.DOT + "]"); - } - - if (childrenList == null) { - childrenList = new ArrayList(); - } - Logger childLogger; - if (this.isRootLogger()) { - childLogger = new Logger(lastPart, this, this.loggerContext); - } else { - childLogger = new Logger( - name + CoreConstants.DOT + lastPart, this, - this.loggerContext); - } - childrenList.add(childLogger); - childLogger.effectiveLevelInt = this.effectiveLevelInt; - return childLogger; - } - - private void localLevelReset() { - effectiveLevelInt = Level.DEBUG_INT; - if(isRootLogger()) { - level = Level.DEBUG; - } else { - level = null; - } - } - - void recursiveReset() { - detachAndStopAllAppenders(); - localLevelReset(); - additive = true; - if (childrenList == null) { - return; - } - for (Logger childLogger : childrenList) { - childLogger.recursiveReset(); - } - } - - /** - * The default size of child list arrays. The JDK 1.5 default is 10. We use a - * smaller value to save a little space. - */ - static private final int DEFAULT_CHILD_ARRAY_SIZE = 5; - - Logger createChildByName(final String childName) { - int i_index = getSeparatorIndexOf(childName, this.name - .length() + 1); - if (i_index != -1) { - throw new IllegalArgumentException("For logger [" + this.name - + "] child name [" + childName - + " passed as parameter, may not include '.' after index" - + (this.name.length() + 1)); - } - - if (childrenList == null) { - childrenList = new ArrayList(DEFAULT_CHILD_ARRAY_SIZE); - } - Logger childLogger; - childLogger = new Logger(childName, this, this.loggerContext); - childrenList.add(childLogger); - childLogger.effectiveLevelInt = this.effectiveLevelInt; - return childLogger; - } - - /** - * The next methods are not merged into one because of the time we gain by not - * creating a new Object[] with the params. This reduces the cost of not - * logging by about 20 nanoseconds. - */ - - private final void filterAndLog_0_Or3Plus(final String localFQCN, - final Marker marker, final Level level, final String msg, - final Object[] params, final Throwable t) { - - final FilterReply decision = loggerContext - .getTurboFilterChainDecision_0_3OrMore(marker, this, level, msg, - params, t); - - if (decision == FilterReply.NEUTRAL) { - if (effectiveLevelInt > level.levelInt) { - return; - } - } else if (decision == FilterReply.DENY) { - return; - } - - buildLoggingEventAndAppend(localFQCN, marker, level, msg, params, t); - } - - private final void filterAndLog_1(final String localFQCN, - final Marker marker, final Level level, final String msg, - final Object param, final Throwable t) { - - final FilterReply decision = loggerContext.getTurboFilterChainDecision_1( - marker, this, level, msg, param, t); - - if (decision == FilterReply.NEUTRAL) { - if (effectiveLevelInt > level.levelInt) { - return; - } - } else if (decision == FilterReply.DENY) { - return; - } - - buildLoggingEventAndAppend(localFQCN, marker, level, msg, - new Object[] { param }, t); - } - - private final void filterAndLog_2(final String localFQCN, - final Marker marker, final Level level, final String msg, - final Object param1, final Object param2, final Throwable t) { - - final FilterReply decision = loggerContext.getTurboFilterChainDecision_2( - marker, this, level, msg, param1, param2, t); - - if (decision == FilterReply.NEUTRAL) { - if (effectiveLevelInt > level.levelInt) { - return; - } - } else if (decision == FilterReply.DENY) { - return; - } - - buildLoggingEventAndAppend(localFQCN, marker, level, msg, new Object[] { - param1, param2 }, t); - } - - private void buildLoggingEventAndAppend(final String localFQCN, - final Marker marker, final Level level, final String msg, - final Object[] params, final Throwable t) { - LoggingEvent le = new LoggingEvent(localFQCN, this, level, msg, t, params); - le.setMarker(marker); - callAppenders(le); - } - - public void trace(String msg) { - filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, null); - } - - public final void trace(String format, Object arg) { - filterAndLog_1(FQCN, null, Level.TRACE, format, arg, null); - } - - public void trace(String format, Object arg1, Object arg2) { - filterAndLog_2(FQCN, null, Level.TRACE, format, arg1, arg2, null); - } - - public void trace(String format, Object[] argArray) { - filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, format, argArray, null); - } - - public void trace(String msg, Throwable t) { - filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, t); - } - - public final void trace(Marker marker, String msg) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, null); - } - - public void trace(Marker marker, String format, Object arg) { - filterAndLog_1(FQCN, marker, Level.TRACE, format, arg, null); - } - - public void trace(Marker marker, String format, Object arg1, Object arg2) { - filterAndLog_2(FQCN, marker, Level.TRACE, format, arg1, arg2, null); - } - - public void trace(Marker marker, String format, Object[] argArray) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, format, argArray, null); - } - - public void trace(Marker marker, String msg, Throwable t) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, t); - } - - final public boolean isDebugEnabled() { - return isDebugEnabled(null); - } - - final public boolean isDebugEnabled(Marker marker) { - final FilterReply decision = callTurboFilters(marker, Level.DEBUG); - if (decision == FilterReply.NEUTRAL) { - return effectiveLevelInt <= Level.DEBUG_INT; - } else if (decision == FilterReply.DENY) { - return false; - } else if (decision == FilterReply.ACCEPT) { - return true; - } else { - throw new IllegalStateException("Unknown FilterReply value: " + decision); - } - } - - final public void debug(String msg) { - filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, null); - } - - final public void debug(String format, Object arg) { - filterAndLog_1(FQCN, null, Level.DEBUG, format, arg, null); - } - - final public void debug(String format, Object arg1, Object arg2) { - filterAndLog_2(FQCN, null, Level.DEBUG, format, arg1, arg2, null); - } - - final public void debug(String format, Object[] argArray) { - filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, format, argArray, null); - } - - public void debug(String msg, Throwable t) { - filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, t); - } - - public final void debug(Marker marker, String msg) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, null); - } - - public void debug(Marker marker, String format, Object arg) { - filterAndLog_1(FQCN, marker, Level.DEBUG, format, arg, null); - } - - public void debug(Marker marker, String format, Object arg1, Object arg2) { - filterAndLog_2(FQCN, marker, Level.DEBUG, format, arg1, arg2, null); - } - - public void debug(Marker marker, String format, Object[] argArray) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, format, argArray, null); - } - - public void debug(Marker marker, String msg, Throwable t) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, t); - } - - public void error(String msg) { - filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, null); - } - - public void error(String format, Object arg) { - filterAndLog_1(FQCN, null, Level.ERROR, format, arg, null); - } - - public void error(String format, Object arg1, Object arg2) { - filterAndLog_2(FQCN, null, Level.ERROR, format, arg1, arg2, null); - } - - public void error(String format, Object[] argArray) { - filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, format, argArray, null); - } - - public void error(String msg, Throwable t) { - filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, t); - } - - public void error(Marker marker, String msg) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, null); - } - - public void error(Marker marker, String format, Object arg) { - filterAndLog_1(FQCN, marker, Level.ERROR, format, arg, null); - } - - public void error(Marker marker, String format, Object arg1, Object arg2) { - filterAndLog_2(FQCN, marker, Level.ERROR, format, arg1, arg2, null); - } - - public void error(Marker marker, String format, Object[] argArray) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, format, argArray, null); - } - - public void error(Marker marker, String msg, Throwable t) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, t); - } - - public boolean isInfoEnabled() { - return isInfoEnabled(null); - } - - public boolean isInfoEnabled(Marker marker) { - FilterReply decision = callTurboFilters(marker, Level.INFO); - if (decision == FilterReply.NEUTRAL) { - return effectiveLevelInt <= Level.INFO_INT; - } else if (decision == FilterReply.DENY) { - return false; - } else if (decision == FilterReply.ACCEPT) { - return true; - } else { - throw new IllegalStateException("Unknown FilterReply value: " + decision); - } - } - - public void info(String msg) { - filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, null); - } - - public void info(String format, Object arg) { - filterAndLog_1(FQCN, null, Level.INFO, format, arg, null); - } - - public void info(String format, Object arg1, Object arg2) { - filterAndLog_2(FQCN, null, Level.INFO, format, arg1, arg2, null); - } - - public void info(String format, Object[] argArray) { - filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, format, argArray, null); - } - - public void info(String msg, Throwable t) { - filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, t); - } - - public void info(Marker marker, String msg) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, null); - } - - public void info(Marker marker, String format, Object arg) { - filterAndLog_1(FQCN, marker, Level.INFO, format, arg, null); - } - - public void info(Marker marker, String format, Object arg1, Object arg2) { - filterAndLog_2(FQCN, marker, Level.INFO, format, arg1, arg2, null); - } - - public void info(Marker marker, String format, Object[] argArray) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, format, argArray, null); - } - - public void info(Marker marker, String msg, Throwable t) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, t); - } - - public final boolean isTraceEnabled() { - return isTraceEnabled(null); - } - - public boolean isTraceEnabled(Marker marker) { - final FilterReply decision = callTurboFilters(marker, Level.TRACE); - if (decision == FilterReply.NEUTRAL) { - return effectiveLevelInt <= Level.TRACE_INT; - } else if (decision == FilterReply.DENY) { - return false; - } else if (decision == FilterReply.ACCEPT) { - return true; - } else { - throw new IllegalStateException("Unknown FilterReply value: " + decision); - } - } - - public final boolean isErrorEnabled() { - return isErrorEnabled(null); - } - - public boolean isErrorEnabled(Marker marker) { - FilterReply decision = callTurboFilters(marker, Level.ERROR); - if (decision == FilterReply.NEUTRAL) { - return effectiveLevelInt <= Level.ERROR_INT; - } else if (decision == FilterReply.DENY) { - return false; - } else if (decision == FilterReply.ACCEPT) { - return true; - } else { - throw new IllegalStateException("Unknown FilterReply value: " + decision); - } - } - - public boolean isWarnEnabled() { - return isWarnEnabled(null); - } - - public boolean isWarnEnabled(Marker marker) { - FilterReply decision = callTurboFilters(marker, Level.WARN); - if (decision == FilterReply.NEUTRAL) { - return effectiveLevelInt <= Level.WARN_INT; - } else if (decision == FilterReply.DENY) { - return false; - } else if (decision == FilterReply.ACCEPT) { - return true; - } else { - throw new IllegalStateException("Unknown FilterReply value: " + decision); - } - - } - - public boolean isEnabledFor(Marker marker, Level level) { - FilterReply decision = callTurboFilters(marker, level); - if (decision == FilterReply.NEUTRAL) { - return effectiveLevelInt <= level.levelInt; - } else if (decision == FilterReply.DENY) { - return false; - } else if (decision == FilterReply.ACCEPT) { - return true; - } else { - throw new IllegalStateException("Unknown FilterReply value: " + decision); - } - } - - public boolean isEnabledFor(Level level) { - return isEnabledFor(null, level); - } - - public void warn(String msg) { - filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, null); - } - - public void warn(String msg, Throwable t) { - filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, t); - } - - public void warn(String format, Object arg) { - filterAndLog_1(FQCN, null, Level.WARN, format, arg, null); - } - - public void warn(String format, Object arg1, Object arg2) { - filterAndLog_2(FQCN, null, Level.WARN, format, arg1, arg2, null); - } - - public void warn(String format, Object[] argArray) { - filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, format, argArray, null); - } - - public void warn(Marker marker, String msg) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, null); - } - - public void warn(Marker marker, String format, Object arg) { - filterAndLog_1(FQCN, marker, Level.WARN, format, arg, null); - } - - public void warn(Marker marker, String format, Object[] argArray) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, format, argArray, null); - } - - public void warn(Marker marker, String format, Object arg1, Object arg2) { - filterAndLog_2(FQCN, marker, Level.WARN, format, arg1, arg2, null); - } - - public void warn(Marker marker, String msg, Throwable t) { - filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, t); - } - - public boolean isAdditive() { - return additive; - } - - public void setAdditive(boolean additive) { - this.additive = additive; - } - - public String toString() { - return "Logger[" + name + "]"; - } - - /** - * Method that calls the attached TurboFilter objects based on the logger and - * the level. - * - * It is used by isYYYEnabled() methods. - * - * It returns the typical FilterReply values: ACCEPT, NEUTRAL or DENY. - * - * @param level - * @return the reply given by the TurboFilters - */ - private FilterReply callTurboFilters(Marker marker, Level level) { - return loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, - level, null, null, null); - } - - /** - * Return the context for this logger. - * - * @return the context - */ - public LoggerContext getLoggerContext() { - return loggerContext; - } - - public LoggerRemoteView getLoggerRemoteView() { - return loggerRemoteView; - } - - void buildRemoteView() { - this.loggerRemoteView = new LoggerRemoteView(name, loggerContext); - } - - public void log(Marker marker, String fqcn, int levelInt, String message, - Throwable t) { - Level level = null; - switch (levelInt) { - case LocationAwareLogger.TRACE_INT: - level = Level.TRACE; - break; - case LocationAwareLogger.DEBUG_INT: - level = Level.DEBUG; - break; - case LocationAwareLogger.INFO_INT: - level = Level.INFO; - break; - case LocationAwareLogger.WARN_INT: - level = Level.WARN; - break; - case LocationAwareLogger.ERROR_INT: - level = Level.ERROR; - break; - default: - throw new IllegalArgumentException(levelInt + " not a valid level value"); - } - filterAndLog_0_Or3Plus(fqcn, marker, level, message, null, t); - } - - /** - * After serialization, the logger instance does not know its LoggerContext. - * The best we can do here, is to return a logger with the same name as - * generated by LoggerFactory. - * - * @return Logger instance with the same name - * @throws ObjectStreamException - */ - protected Object readResolve() throws ObjectStreamException { - return LoggerFactory.getLogger(getName()); - } -} +/** + * 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.classic; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.slf4j.LoggerFactory; +import org.slf4j.Marker; +import org.slf4j.spi.LocationAwareLogger; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggerRemoteView; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.spi.AppenderAttachable; +import ch.qos.logback.core.spi.AppenderAttachableImpl; +import ch.qos.logback.core.spi.FilterReply; + +public final class Logger implements org.slf4j.Logger, LocationAwareLogger, + AppenderAttachable, Serializable { + + /** + * + */ + private static final long serialVersionUID = 5454405123156820674L; + + /** + * The fully qualified name of this class. Used in gathering caller + * information. + */ + public static final String FQCN = ch.qos.logback.classic.Logger.class + .getName(); + + static int instanceCount = 0; + + /** + * The name of this logger + */ + private String name; + + // The assigned levelInt of this logger. Can be null. + private Level level; + + // The effective levelInt is the assigned levelInt and if null, a levelInt is + // inherited form a parent. + private int effectiveLevelInt; + + /** + * The parent of this category. All categories have at least one ancestor + * which is the root category. + */ + private Logger parent; + + /** + * The children of this logger. A logger may have zero or more children. + */ + private List childrenList; + + /** + * It is assumed that once the 'aai' variable is set to a non-null value, it + * will never be reset to null. it is further assumed that only place where + * the 'aai'ariable is set is within the addAppender method. This method is + * synchronized on 'this' (Logger) protecting against simultaneous + * re-configuration of this logger (a very unlikely scenario). + * + *

It is further assumed that the AppenderAttachableImpl is responsible + * for its internal synchronization and thread safety. Thus, we can get away + * with *not* synchronizing on the 'aai' (check null/ read) because

1) the + * 'aai' variable is immutable once set to non-null

2) 'aai' is getAndSet + * only within addAppender which is synchronized

3) all the other methods + * check whether 'aai' is null

4) AppenderAttachableImpl is thread safe + */ + private transient AppenderAttachableImpl aai; + /** + * Additivity is set to true by default, that is children inherit the + * appenders of their ancestors by default. If this variable is set to + * false then the appenders located in the ancestors of this + * logger will not be used. However, the children of this logger will inherit + * its appenders, unless the children have their additivity flag set to + * false too. See the user manual for more details. + */ + private boolean additive = true; + + final transient LoggerContext loggerContext; + // loggerRemoteView cannot be final because it may change as a consequence + // of changes in LoggerContext + LoggerRemoteView loggerRemoteView; + + Logger(String name, Logger parent, LoggerContext loggerContext) { + this.name = name; + this.parent = parent; + this.loggerContext = loggerContext; + buildRemoteView(); + instanceCount++; + } + + public final Level getEffectiveLevel() { + return Level.toLevel(effectiveLevelInt); + } + + int getEffectiveLevelInt() { + return effectiveLevelInt; + } + + public Level getLevel() { + return level; + } + + public String getName() { + return name; + } + + private final boolean isRootLogger() { + // only the root logger has a null parent + return parent == null; + } + + // Logger getChildBySuffix(final String suffix) method was here and got + // removed. + + Logger getChildByName(final String childName) { + if (childrenList == null) { + return null; + } else { + int len = this.childrenList.size(); + for (int i = 0; i < len; i++) { + final Logger childLogger_i = (Logger) childrenList.get(i); + final String childName_i = childLogger_i.getName(); + + if (childName.equals(childName_i)) { + return childLogger_i; + } + } + // no child found + return null; + } + } + + public synchronized void setLevel(Level newLevel) { + if (level == newLevel) { + // nothing to do; + return; + } + if(newLevel == null && isRootLogger()) { + throw new IllegalArgumentException("The level of the root logger cannot be set to null"); + } + + level = newLevel; + if (newLevel == null) { + effectiveLevelInt = parent.effectiveLevelInt; + } else { + effectiveLevelInt = newLevel.levelInt; + } + + if (childrenList != null) { + int len = childrenList.size(); + for (int i = 0; i < len; i++) { + Logger child = (Logger) childrenList.get(i); + // tell child to handle parent levelInt change + child.handleParentLevelChange(effectiveLevelInt); + } + } + } + + /** + * This method is invoked by parent logger to let this logger know that the + * prent's levelInt changed. + * + * @param newParentLevel + */ + private synchronized void handleParentLevelChange(int newParentLevelInt) { + // changes in the parent levelInt affect children only if their levelInt is + // null + if (level == null) { + effectiveLevelInt = newParentLevelInt; + + // propagate the parent levelInt change to this logger's children + if (childrenList != null) { + int len = childrenList.size(); + for (int i = 0; i < len; i++) { + Logger child = (Logger) childrenList.get(i); + child.handleParentLevelChange(newParentLevelInt); + } + } + } + } + + /** + * Remove all previously added appenders from this logger instance.

This + * is useful when re-reading configuration information. + */ + public void detachAndStopAllAppenders() { + if (aai != null) { + aai.detachAndStopAllAppenders(); + } + } + + public boolean detachAppender(String name) { + if (aai == null) { + return false; + } + return aai.detachAppender(name); + } + + // this method MUST be synchronized. See comments on 'aai' field for further + // details. + public synchronized void addAppender(Appender newAppender) { + if (aai == null) { + aai = new AppenderAttachableImpl(); + } + aai.addAppender(newAppender); + } + + public boolean isAttached(Appender appender) { + if (aai == null) { + return false; + } + return aai.isAttached(appender); + } + + @SuppressWarnings("unchecked") + public Iterator> iteratorForAppenders() { + if (aai == null) { + return Collections.EMPTY_LIST.iterator(); + } + return aai.iteratorForAppenders(); + } + + public Appender getAppender(String name) { + if (aai == null) { + return null; + } + return aai.getAppender(name); + } + + /** + * Invoke all the appenders of this logger. + * + * @param event + * The event to log + */ + public void callAppenders(ILoggingEvent event) { + int writes = 0; + for (Logger l = this; l != null; l = l.parent) { + writes += l.appendLoopOnAppenders(event); + if (!l.additive) { + break; + } + } + // No appenders in hierarchy + if (writes == 0) { + loggerContext.noAppenderDefinedWarning(this); + } + } + + private int appendLoopOnAppenders(ILoggingEvent event) { + if (aai != null) { + return aai.appendLoopOnAppenders(event); + } else { + return 0; + } + } + + /** + * Remove the appender passed as parameter form the list of appenders. + */ + public boolean detachAppender(Appender appender) { + if (aai == null) { + return false; + } + return aai.detachAppender(appender); + } + + static int getSeparatorIndexOf(String name) { + return getSeparatorIndexOf(name, 0); + } + + /** + * Get the position of the separator character, if any, starting at position + * 'fromIndex'. + * + * @param name + * @param fromIndex + * @return + */ + static int getSeparatorIndexOf(String name, int fromIndex) { + int i = name.indexOf(CoreConstants.DOT, fromIndex); + if(i != -1) { + return i; + } else { + return name.indexOf(CoreConstants.DOLLAR, fromIndex); + } + } + + /** + * Create a child of this logger by suffix, that is, the part of the name + * extending this logger. For example, if this logger is named "x.y" and the + * lastPart is "z", then the created child logger will be named "x.y.z". + * + *

IMPORTANT: Calls to this method must be within a synchronized block on + * this logger. + * + * @param lastPart + * the suffix (i.e. last part) of the child logger name. This + * parameter may not include dots, i.e. the logger separator + * character. + * @return + */ + Logger createChildByLastNamePart(final String lastPart) { + int i_index = getSeparatorIndexOf(lastPart); + if (i_index != -1) { + throw new IllegalArgumentException("Child name [" + lastPart + + " passed as parameter, may not include [" + + CoreConstants.DOT + "]"); + } + + if (childrenList == null) { + childrenList = new ArrayList(); + } + Logger childLogger; + if (this.isRootLogger()) { + childLogger = new Logger(lastPart, this, this.loggerContext); + } else { + childLogger = new Logger( + name + CoreConstants.DOT + lastPart, this, + this.loggerContext); + } + childrenList.add(childLogger); + childLogger.effectiveLevelInt = this.effectiveLevelInt; + return childLogger; + } + + private void localLevelReset() { + effectiveLevelInt = Level.DEBUG_INT; + if(isRootLogger()) { + level = Level.DEBUG; + } else { + level = null; + } + } + + void recursiveReset() { + detachAndStopAllAppenders(); + localLevelReset(); + additive = true; + if (childrenList == null) { + return; + } + for (Logger childLogger : childrenList) { + childLogger.recursiveReset(); + } + } + + /** + * The default size of child list arrays. The JDK 1.5 default is 10. We use a + * smaller value to save a little space. + */ + static private final int DEFAULT_CHILD_ARRAY_SIZE = 5; + + Logger createChildByName(final String childName) { + int i_index = getSeparatorIndexOf(childName, this.name + .length() + 1); + if (i_index != -1) { + throw new IllegalArgumentException("For logger [" + this.name + + "] child name [" + childName + + " passed as parameter, may not include '.' after index" + + (this.name.length() + 1)); + } + + if (childrenList == null) { + childrenList = new ArrayList(DEFAULT_CHILD_ARRAY_SIZE); + } + Logger childLogger; + childLogger = new Logger(childName, this, this.loggerContext); + childrenList.add(childLogger); + childLogger.effectiveLevelInt = this.effectiveLevelInt; + return childLogger; + } + + /** + * The next methods are not merged into one because of the time we gain by not + * creating a new Object[] with the params. This reduces the cost of not + * logging by about 20 nanoseconds. + */ + + private final void filterAndLog_0_Or3Plus(final String localFQCN, + final Marker marker, final Level level, final String msg, + final Object[] params, final Throwable t) { + + final FilterReply decision = loggerContext + .getTurboFilterChainDecision_0_3OrMore(marker, this, level, msg, + params, t); + + if (decision == FilterReply.NEUTRAL) { + if (effectiveLevelInt > level.levelInt) { + return; + } + } else if (decision == FilterReply.DENY) { + return; + } + + buildLoggingEventAndAppend(localFQCN, marker, level, msg, params, t); + } + + private final void filterAndLog_1(final String localFQCN, + final Marker marker, final Level level, final String msg, + final Object param, final Throwable t) { + + final FilterReply decision = loggerContext.getTurboFilterChainDecision_1( + marker, this, level, msg, param, t); + + if (decision == FilterReply.NEUTRAL) { + if (effectiveLevelInt > level.levelInt) { + return; + } + } else if (decision == FilterReply.DENY) { + return; + } + + buildLoggingEventAndAppend(localFQCN, marker, level, msg, + new Object[] { param }, t); + } + + private final void filterAndLog_2(final String localFQCN, + final Marker marker, final Level level, final String msg, + final Object param1, final Object param2, final Throwable t) { + + final FilterReply decision = loggerContext.getTurboFilterChainDecision_2( + marker, this, level, msg, param1, param2, t); + + if (decision == FilterReply.NEUTRAL) { + if (effectiveLevelInt > level.levelInt) { + return; + } + } else if (decision == FilterReply.DENY) { + return; + } + + buildLoggingEventAndAppend(localFQCN, marker, level, msg, new Object[] { + param1, param2 }, t); + } + + private void buildLoggingEventAndAppend(final String localFQCN, + final Marker marker, final Level level, final String msg, + final Object[] params, final Throwable t) { + LoggingEvent le = new LoggingEvent(localFQCN, this, level, msg, t, params); + le.setMarker(marker); + callAppenders(le); + } + + public void trace(String msg) { + filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, null); + } + + public final void trace(String format, Object arg) { + filterAndLog_1(FQCN, null, Level.TRACE, format, arg, null); + } + + public void trace(String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, null, Level.TRACE, format, arg1, arg2, null); + } + + public void trace(String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, format, argArray, null); + } + + public void trace(String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, t); + } + + public final void trace(Marker marker, String msg) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, null); + } + + public void trace(Marker marker, String format, Object arg) { + filterAndLog_1(FQCN, marker, Level.TRACE, format, arg, null); + } + + public void trace(Marker marker, String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, marker, Level.TRACE, format, arg1, arg2, null); + } + + public void trace(Marker marker, String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, format, argArray, null); + } + + public void trace(Marker marker, String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, t); + } + + final public boolean isDebugEnabled() { + return isDebugEnabled(null); + } + + final public boolean isDebugEnabled(Marker marker) { + final FilterReply decision = callTurboFilters(marker, Level.DEBUG); + if (decision == FilterReply.NEUTRAL) { + return effectiveLevelInt <= Level.DEBUG_INT; + } else if (decision == FilterReply.DENY) { + return false; + } else if (decision == FilterReply.ACCEPT) { + return true; + } else { + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + } + + final public void debug(String msg) { + filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, null); + } + + final public void debug(String format, Object arg) { + filterAndLog_1(FQCN, null, Level.DEBUG, format, arg, null); + } + + final public void debug(String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, null, Level.DEBUG, format, arg1, arg2, null); + } + + final public void debug(String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, format, argArray, null); + } + + public void debug(String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, t); + } + + public final void debug(Marker marker, String msg) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, null); + } + + public void debug(Marker marker, String format, Object arg) { + filterAndLog_1(FQCN, marker, Level.DEBUG, format, arg, null); + } + + public void debug(Marker marker, String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, marker, Level.DEBUG, format, arg1, arg2, null); + } + + public void debug(Marker marker, String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, format, argArray, null); + } + + public void debug(Marker marker, String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, t); + } + + public void error(String msg) { + filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, null); + } + + public void error(String format, Object arg) { + filterAndLog_1(FQCN, null, Level.ERROR, format, arg, null); + } + + public void error(String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, null, Level.ERROR, format, arg1, arg2, null); + } + + public void error(String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, format, argArray, null); + } + + public void error(String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, t); + } + + public void error(Marker marker, String msg) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, null); + } + + public void error(Marker marker, String format, Object arg) { + filterAndLog_1(FQCN, marker, Level.ERROR, format, arg, null); + } + + public void error(Marker marker, String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, marker, Level.ERROR, format, arg1, arg2, null); + } + + public void error(Marker marker, String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, format, argArray, null); + } + + public void error(Marker marker, String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, t); + } + + public boolean isInfoEnabled() { + return isInfoEnabled(null); + } + + public boolean isInfoEnabled(Marker marker) { + FilterReply decision = callTurboFilters(marker, Level.INFO); + if (decision == FilterReply.NEUTRAL) { + return effectiveLevelInt <= Level.INFO_INT; + } else if (decision == FilterReply.DENY) { + return false; + } else if (decision == FilterReply.ACCEPT) { + return true; + } else { + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + } + + public void info(String msg) { + filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, null); + } + + public void info(String format, Object arg) { + filterAndLog_1(FQCN, null, Level.INFO, format, arg, null); + } + + public void info(String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, null, Level.INFO, format, arg1, arg2, null); + } + + public void info(String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, format, argArray, null); + } + + public void info(String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, t); + } + + public void info(Marker marker, String msg) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, null); + } + + public void info(Marker marker, String format, Object arg) { + filterAndLog_1(FQCN, marker, Level.INFO, format, arg, null); + } + + public void info(Marker marker, String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, marker, Level.INFO, format, arg1, arg2, null); + } + + public void info(Marker marker, String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, format, argArray, null); + } + + public void info(Marker marker, String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, t); + } + + public final boolean isTraceEnabled() { + return isTraceEnabled(null); + } + + public boolean isTraceEnabled(Marker marker) { + final FilterReply decision = callTurboFilters(marker, Level.TRACE); + if (decision == FilterReply.NEUTRAL) { + return effectiveLevelInt <= Level.TRACE_INT; + } else if (decision == FilterReply.DENY) { + return false; + } else if (decision == FilterReply.ACCEPT) { + return true; + } else { + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + } + + public final boolean isErrorEnabled() { + return isErrorEnabled(null); + } + + public boolean isErrorEnabled(Marker marker) { + FilterReply decision = callTurboFilters(marker, Level.ERROR); + if (decision == FilterReply.NEUTRAL) { + return effectiveLevelInt <= Level.ERROR_INT; + } else if (decision == FilterReply.DENY) { + return false; + } else if (decision == FilterReply.ACCEPT) { + return true; + } else { + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + } + + public boolean isWarnEnabled() { + return isWarnEnabled(null); + } + + public boolean isWarnEnabled(Marker marker) { + FilterReply decision = callTurboFilters(marker, Level.WARN); + if (decision == FilterReply.NEUTRAL) { + return effectiveLevelInt <= Level.WARN_INT; + } else if (decision == FilterReply.DENY) { + return false; + } else if (decision == FilterReply.ACCEPT) { + return true; + } else { + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + + } + + public boolean isEnabledFor(Marker marker, Level level) { + FilterReply decision = callTurboFilters(marker, level); + if (decision == FilterReply.NEUTRAL) { + return effectiveLevelInt <= level.levelInt; + } else if (decision == FilterReply.DENY) { + return false; + } else if (decision == FilterReply.ACCEPT) { + return true; + } else { + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + } + + public boolean isEnabledFor(Level level) { + return isEnabledFor(null, level); + } + + public void warn(String msg) { + filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, null); + } + + public void warn(String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, t); + } + + public void warn(String format, Object arg) { + filterAndLog_1(FQCN, null, Level.WARN, format, arg, null); + } + + public void warn(String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, null, Level.WARN, format, arg1, arg2, null); + } + + public void warn(String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, format, argArray, null); + } + + public void warn(Marker marker, String msg) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, null); + } + + public void warn(Marker marker, String format, Object arg) { + filterAndLog_1(FQCN, marker, Level.WARN, format, arg, null); + } + + public void warn(Marker marker, String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, format, argArray, null); + } + + public void warn(Marker marker, String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, marker, Level.WARN, format, arg1, arg2, null); + } + + public void warn(Marker marker, String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, t); + } + + public boolean isAdditive() { + return additive; + } + + public void setAdditive(boolean additive) { + this.additive = additive; + } + + public String toString() { + return "Logger[" + name + "]"; + } + + /** + * Method that calls the attached TurboFilter objects based on the logger and + * the level. + * + * It is used by isYYYEnabled() methods. + * + * It returns the typical FilterReply values: ACCEPT, NEUTRAL or DENY. + * + * @param level + * @return the reply given by the TurboFilters + */ + private FilterReply callTurboFilters(Marker marker, Level level) { + return loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, + level, null, null, null); + } + + /** + * Return the context for this logger. + * + * @return the context + */ + public LoggerContext getLoggerContext() { + return loggerContext; + } + + public LoggerRemoteView getLoggerRemoteView() { + return loggerRemoteView; + } + + void buildRemoteView() { + this.loggerRemoteView = new LoggerRemoteView(name, loggerContext); + } + + public void log(Marker marker, String fqcn, int levelInt, String message, + Throwable t) { + Level level = null; + switch (levelInt) { + case LocationAwareLogger.TRACE_INT: + level = Level.TRACE; + break; + case LocationAwareLogger.DEBUG_INT: + level = Level.DEBUG; + break; + case LocationAwareLogger.INFO_INT: + level = Level.INFO; + break; + case LocationAwareLogger.WARN_INT: + level = Level.WARN; + break; + case LocationAwareLogger.ERROR_INT: + level = Level.ERROR; + break; + default: + throw new IllegalArgumentException(levelInt + " not a valid level value"); + } + filterAndLog_0_Or3Plus(fqcn, marker, level, message, null, t); + } + + /** + * After serialization, the logger instance does not know its LoggerContext. + * The best we can do here, is to return a logger with the same name as + * generated by LoggerFactory. + * + * @return Logger instance with the same name + * @throws ObjectStreamException + */ + protected Object readResolve() throws ObjectStreamException { + return LoggerFactory.getLogger(getName()); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/LoggerContext.java b/logback-classic/src/main/java/ch/qos/logback/classic/LoggerContext.java index 36ed7af662e3d6182d84d88f00ed27b51689044f..578a8a4802ea2d617c67db3a36f48ebef86ba654 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/LoggerContext.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/LoggerContext.java @@ -1,354 +1,354 @@ -/** - * 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.classic; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.List; - -import org.slf4j.ILoggerFactory; -import org.slf4j.Marker; - -import ch.qos.logback.classic.spi.LoggerComparator; -import ch.qos.logback.classic.spi.LoggerContextListener; -import ch.qos.logback.classic.spi.LoggerContextVO; -import ch.qos.logback.classic.spi.TurboFilterList; -import ch.qos.logback.classic.turbo.TurboFilter; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.spi.FilterReply; -import ch.qos.logback.core.spi.LifeCycle; -import ch.qos.logback.core.status.StatusListener; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.status.WarnStatus; - -/** - * LoggerContext glues many of the logback-classic components together. In - * principle, every logback-classic component instance is attached either - * directly or indirecty to a LoggerContext instance. Just as importantly - * LoggerContext implements the {@link ILoggerFactory} acting as the - * manufacturing source of {@link Logger} instances. - * - * @author Ceki Gulcu - */ -public class LoggerContext extends ContextBase implements ILoggerFactory, - LifeCycle { - - final Logger root; - private int size; - private int noAppenderWarning = 0; - final private List loggerContextListenerList = new ArrayList(); - - // We want loggerCache to be synchronized so Hashtable is a good choice. In - // practice, it performs a little faster than the map returned by - // Collections.synchronizedMap at the cost of a very slightly higher memory - // footprint. - private Hashtable loggerCache; - - private LoggerContextVO loggerContextRemoteView; - private final TurboFilterList turboFilterList = new TurboFilterList(); - private boolean packagingDataEnabled = true; - - private int maxCallerDataDepth = ClassicConstants.DEFAULT_MAX_CALLEDER_DATA_DEPTH; - - boolean started = false; - - int resetCount = 0; - - public LoggerContext() { - super(); - this.loggerCache = new Hashtable(); - this.loggerContextRemoteView = new LoggerContextVO(this); - this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this); - this.root.setLevel(Level.DEBUG); - loggerCache.put(Logger.ROOT_LOGGER_NAME, root); - putObject(CoreConstants.EVALUATOR_MAP, new HashMap()); - size = 1; - } - - /** - * A new instance of LoggerContextRemoteView needs to be created each time the - * name or propertyMap (including keys or values) changes. - */ - private void syncRemoteView() { - loggerContextRemoteView = new LoggerContextVO(this); - for (Logger logger : loggerCache.values()) { - logger.buildRemoteView(); - } - } - - @Override - public void putProperty(String key, String val) { - super.putProperty(key, val); - syncRemoteView(); - } - - @Override - public void setName(String name) { - super.setName(name); - syncRemoteView(); - } - - public final Logger getLogger(final Class clazz) { - return getLogger(clazz.getName()); - } - - public final Logger getLogger(final String name) { - - if (name == null) { - throw new IllegalArgumentException("name argument cannot be null"); - } - - // if we are asking for the root logger, then let us return it without - // wasting time - if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) { - return root; - } - - int i = 0; - Logger logger = root; - - // check if the desired logger exists, if it does, return it - // without further ado. - Logger childLogger = (Logger) loggerCache.get(name); - // if we have the child, then let us return it without wasting time - if (childLogger != null) { - return childLogger; - } - - // if the desired logger does not exist, them create all the loggers - // in between as well (if they don't already exist) - String childName; - while (true) { - int h = Logger.getSeparatorIndexOf(name, i); - if (h == -1) { - childName = name; - } else { - childName = name.substring(0, h); - } - // move i left of the last point - i = h + 1; - synchronized (logger) { - childLogger = logger.getChildByName(childName); - if (childLogger == null) { - childLogger = logger.createChildByName(childName); - loggerCache.put(childName, childLogger); - incSize(); - } - } - logger = childLogger; - if (h == -1) { - return childLogger; - } - } - } - - private void incSize() { - size++; - } - - int size() { - return size; - } - - /** - * Check if the named logger exists in the hierarchy. If so return its - * reference, otherwise returns null. - * - * @param name - * the name of the logger to search for. - */ - public Logger exists(String name) { - return (Logger) loggerCache.get(name); - } - - final void noAppenderDefinedWarning(final Logger logger) { - if (noAppenderWarning++ == 0) { - getStatusManager().add( - new WarnStatus("No appenders present in context [" + getName() - + "] for logger [" + logger.getName() + "].", logger)); - } - } - - public List getLoggerList() { - Collection collection = loggerCache.values(); - List loggerList = new ArrayList(collection); - Collections.sort(loggerList, new LoggerComparator()); - return loggerList; - } - - public LoggerContextVO getLoggerContextRemoteView() { - return loggerContextRemoteView; - } - - public void setPackagingDataEnabled(boolean packagingDataEnabled) { - this.packagingDataEnabled = packagingDataEnabled; - } - - public boolean isPackagingDataEnabled() { - return packagingDataEnabled; - } - - /** - * This method clears all internal properties, closes all appenders, removes - * any turboFilters, fires an OnReset event, removes all status listeners, - * removes all context listeners (except those which are reset resistant). - */ - @Override - public void reset() { - resetCount++; - super.reset(); - root.recursiveReset(); - resetTurboFilterList(); - fireOnReset(); - resetListenersExceptResetResistant(); - resetStatusListeners(); - } - - private void resetStatusListeners() { - StatusManager sm = getStatusManager(); - for (StatusListener sl : sm.getCopyOfStatusListenerList()) { - sm.remove(sl); - } - } - - public TurboFilterList getTurboFilterList() { - return turboFilterList; - } - - public void addTurboFilter(TurboFilter newFilter) { - turboFilterList.add(newFilter); - } - - /** - * First stop all registered turbo filters and then clear the registration - * list. - */ - public void resetTurboFilterList() { - for (TurboFilter tf : turboFilterList) { - tf.stop(); - } - turboFilterList.clear(); - } - - final FilterReply getTurboFilterChainDecision_0_3OrMore(final Marker marker, - final Logger logger, final Level level, final String format, - final Object[] params, final Throwable t) { - if (turboFilterList.size() == 0) { - return FilterReply.NEUTRAL; - } - return turboFilterList.getTurboFilterChainDecision(marker, logger, level, - format, params, t); - } - - final FilterReply getTurboFilterChainDecision_1(final Marker marker, - final Logger logger, final Level level, final String format, - final Object param, final Throwable t) { - if (turboFilterList.size() == 0) { - return FilterReply.NEUTRAL; - } - return turboFilterList.getTurboFilterChainDecision(marker, logger, level, - format, new Object[] { param }, t); - } - - final FilterReply getTurboFilterChainDecision_2(final Marker marker, - final Logger logger, final Level level, final String format, - final Object param1, final Object param2, final Throwable t) { - if (turboFilterList.size() == 0) { - return FilterReply.NEUTRAL; - } - return turboFilterList.getTurboFilterChainDecision(marker, logger, level, - format, new Object[] { param1, param2 }, t); - } - - // === start listeners ============================================== - public void addListener(LoggerContextListener listener) { - loggerContextListenerList.add(listener); - } - - public void removeListener(LoggerContextListener listener) { - loggerContextListenerList.remove(listener); - } - - private void resetListenersExceptResetResistant() { - List toRetain = new ArrayList(); - - for (LoggerContextListener lcl : loggerContextListenerList) { - if (lcl.isResetResistant()) { - toRetain.add(lcl); - } - } - loggerContextListenerList.retainAll(toRetain); - } - - private void resetAllListeners() { - loggerContextListenerList.clear(); - } - - public List getCopyOfListenerList() { - return new ArrayList(loggerContextListenerList); - } - - private void fireOnReset() { - for (LoggerContextListener listener : loggerContextListenerList) { - listener.onReset(this); - } - } - - private void fireOnStart() { - for (LoggerContextListener listener : loggerContextListenerList) { - listener.onStart(this); - } - } - - private void fireOnStop() { - for (LoggerContextListener listener : loggerContextListenerList) { - listener.onStop(this); - } - } - - // === end listeners ============================================== - - public boolean isStarted() { - return started; - } - - public void start() { - started = true; - fireOnStart(); - } - - public void stop() { - reset(); - fireOnStop(); - resetAllListeners(); - started = false; - } - - @Override - public String toString() { - return this.getClass().getName() + "[" + getName() + "]"; - } - - public int getMaxCallerDataDepth() { - return maxCallerDataDepth; - } - - public void setMaxCallerDataDepth(int maxCallerDataDepth) { - this.maxCallerDataDepth = maxCallerDataDepth; - } -} +/** + * 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.classic; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; + +import org.slf4j.ILoggerFactory; +import org.slf4j.Marker; + +import ch.qos.logback.classic.spi.LoggerComparator; +import ch.qos.logback.classic.spi.LoggerContextListener; +import ch.qos.logback.classic.spi.LoggerContextVO; +import ch.qos.logback.classic.spi.TurboFilterList; +import ch.qos.logback.classic.turbo.TurboFilter; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.WarnStatus; + +/** + * LoggerContext glues many of the logback-classic components together. In + * principle, every logback-classic component instance is attached either + * directly or indirecty to a LoggerContext instance. Just as importantly + * LoggerContext implements the {@link ILoggerFactory} acting as the + * manufacturing source of {@link Logger} instances. + * + * @author Ceki Gulcu + */ +public class LoggerContext extends ContextBase implements ILoggerFactory, + LifeCycle { + + final Logger root; + private int size; + private int noAppenderWarning = 0; + final private List loggerContextListenerList = new ArrayList(); + + // We want loggerCache to be synchronized so Hashtable is a good choice. In + // practice, it performs a little faster than the map returned by + // Collections.synchronizedMap at the cost of a very slightly higher memory + // footprint. + private Hashtable loggerCache; + + private LoggerContextVO loggerContextRemoteView; + private final TurboFilterList turboFilterList = new TurboFilterList(); + private boolean packagingDataEnabled = true; + + private int maxCallerDataDepth = ClassicConstants.DEFAULT_MAX_CALLEDER_DATA_DEPTH; + + boolean started = false; + + int resetCount = 0; + + public LoggerContext() { + super(); + this.loggerCache = new Hashtable(); + this.loggerContextRemoteView = new LoggerContextVO(this); + this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this); + this.root.setLevel(Level.DEBUG); + loggerCache.put(Logger.ROOT_LOGGER_NAME, root); + putObject(CoreConstants.EVALUATOR_MAP, new HashMap()); + size = 1; + } + + /** + * A new instance of LoggerContextRemoteView needs to be created each time the + * name or propertyMap (including keys or values) changes. + */ + private void syncRemoteView() { + loggerContextRemoteView = new LoggerContextVO(this); + for (Logger logger : loggerCache.values()) { + logger.buildRemoteView(); + } + } + + @Override + public void putProperty(String key, String val) { + super.putProperty(key, val); + syncRemoteView(); + } + + @Override + public void setName(String name) { + super.setName(name); + syncRemoteView(); + } + + public final Logger getLogger(final Class clazz) { + return getLogger(clazz.getName()); + } + + public final Logger getLogger(final String name) { + + if (name == null) { + throw new IllegalArgumentException("name argument cannot be null"); + } + + // if we are asking for the root logger, then let us return it without + // wasting time + if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) { + return root; + } + + int i = 0; + Logger logger = root; + + // check if the desired logger exists, if it does, return it + // without further ado. + Logger childLogger = (Logger) loggerCache.get(name); + // if we have the child, then let us return it without wasting time + if (childLogger != null) { + return childLogger; + } + + // if the desired logger does not exist, them create all the loggers + // in between as well (if they don't already exist) + String childName; + while (true) { + int h = Logger.getSeparatorIndexOf(name, i); + if (h == -1) { + childName = name; + } else { + childName = name.substring(0, h); + } + // move i left of the last point + i = h + 1; + synchronized (logger) { + childLogger = logger.getChildByName(childName); + if (childLogger == null) { + childLogger = logger.createChildByName(childName); + loggerCache.put(childName, childLogger); + incSize(); + } + } + logger = childLogger; + if (h == -1) { + return childLogger; + } + } + } + + private void incSize() { + size++; + } + + int size() { + return size; + } + + /** + * Check if the named logger exists in the hierarchy. If so return its + * reference, otherwise returns null. + * + * @param name + * the name of the logger to search for. + */ + public Logger exists(String name) { + return (Logger) loggerCache.get(name); + } + + final void noAppenderDefinedWarning(final Logger logger) { + if (noAppenderWarning++ == 0) { + getStatusManager().add( + new WarnStatus("No appenders present in context [" + getName() + + "] for logger [" + logger.getName() + "].", logger)); + } + } + + public List getLoggerList() { + Collection collection = loggerCache.values(); + List loggerList = new ArrayList(collection); + Collections.sort(loggerList, new LoggerComparator()); + return loggerList; + } + + public LoggerContextVO getLoggerContextRemoteView() { + return loggerContextRemoteView; + } + + public void setPackagingDataEnabled(boolean packagingDataEnabled) { + this.packagingDataEnabled = packagingDataEnabled; + } + + public boolean isPackagingDataEnabled() { + return packagingDataEnabled; + } + + /** + * This method clears all internal properties, closes all appenders, removes + * any turboFilters, fires an OnReset event, removes all status listeners, + * removes all context listeners (except those which are reset resistant). + */ + @Override + public void reset() { + resetCount++; + super.reset(); + root.recursiveReset(); + resetTurboFilterList(); + fireOnReset(); + resetListenersExceptResetResistant(); + resetStatusListeners(); + } + + private void resetStatusListeners() { + StatusManager sm = getStatusManager(); + for (StatusListener sl : sm.getCopyOfStatusListenerList()) { + sm.remove(sl); + } + } + + public TurboFilterList getTurboFilterList() { + return turboFilterList; + } + + public void addTurboFilter(TurboFilter newFilter) { + turboFilterList.add(newFilter); + } + + /** + * First stop all registered turbo filters and then clear the registration + * list. + */ + public void resetTurboFilterList() { + for (TurboFilter tf : turboFilterList) { + tf.stop(); + } + turboFilterList.clear(); + } + + final FilterReply getTurboFilterChainDecision_0_3OrMore(final Marker marker, + final Logger logger, final Level level, final String format, + final Object[] params, final Throwable t) { + if (turboFilterList.size() == 0) { + return FilterReply.NEUTRAL; + } + return turboFilterList.getTurboFilterChainDecision(marker, logger, level, + format, params, t); + } + + final FilterReply getTurboFilterChainDecision_1(final Marker marker, + final Logger logger, final Level level, final String format, + final Object param, final Throwable t) { + if (turboFilterList.size() == 0) { + return FilterReply.NEUTRAL; + } + return turboFilterList.getTurboFilterChainDecision(marker, logger, level, + format, new Object[] { param }, t); + } + + final FilterReply getTurboFilterChainDecision_2(final Marker marker, + final Logger logger, final Level level, final String format, + final Object param1, final Object param2, final Throwable t) { + if (turboFilterList.size() == 0) { + return FilterReply.NEUTRAL; + } + return turboFilterList.getTurboFilterChainDecision(marker, logger, level, + format, new Object[] { param1, param2 }, t); + } + + // === start listeners ============================================== + public void addListener(LoggerContextListener listener) { + loggerContextListenerList.add(listener); + } + + public void removeListener(LoggerContextListener listener) { + loggerContextListenerList.remove(listener); + } + + private void resetListenersExceptResetResistant() { + List toRetain = new ArrayList(); + + for (LoggerContextListener lcl : loggerContextListenerList) { + if (lcl.isResetResistant()) { + toRetain.add(lcl); + } + } + loggerContextListenerList.retainAll(toRetain); + } + + private void resetAllListeners() { + loggerContextListenerList.clear(); + } + + public List getCopyOfListenerList() { + return new ArrayList(loggerContextListenerList); + } + + private void fireOnReset() { + for (LoggerContextListener listener : loggerContextListenerList) { + listener.onReset(this); + } + } + + private void fireOnStart() { + for (LoggerContextListener listener : loggerContextListenerList) { + listener.onStart(this); + } + } + + private void fireOnStop() { + for (LoggerContextListener listener : loggerContextListenerList) { + listener.onStop(this); + } + } + + // === end listeners ============================================== + + public boolean isStarted() { + return started; + } + + public void start() { + started = true; + fireOnStart(); + } + + public void stop() { + reset(); + fireOnStop(); + resetAllListeners(); + started = false; + } + + @Override + public String toString() { + return this.getClass().getName() + "[" + getName() + "]"; + } + + public int getMaxCallerDataDepth() { + return maxCallerDataDepth; + } + + public void setMaxCallerDataDepth(int maxCallerDataDepth) { + this.maxCallerDataDepth = maxCallerDataDepth; + } +} 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 e61361690a2cef7b1cf9bd9641df899b8aea4d5c..a3fc208bc655cd0b2899d9a5b978754173dcc412 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 @@ -1,143 +1,143 @@ -/** - * 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.classic; - -import java.util.HashMap; -import java.util.Map; - -import ch.qos.logback.classic.joran.action.ContextNameAction; -import ch.qos.logback.classic.pattern.CallerDataConverter; -import ch.qos.logback.classic.pattern.ClassOfCallerConverter; -import ch.qos.logback.classic.pattern.ContextNameConverter; -import ch.qos.logback.classic.pattern.PropertyConverter; -import ch.qos.logback.classic.pattern.DateConverter; -import ch.qos.logback.classic.pattern.EnsureExceptionHandling; -import ch.qos.logback.classic.pattern.ExtendedThrowableProxyConverter; -import ch.qos.logback.classic.pattern.FileOfCallerConverter; -import ch.qos.logback.classic.pattern.LevelConverter; -import ch.qos.logback.classic.pattern.LineOfCallerConverter; -import ch.qos.logback.classic.pattern.LineSeparatorConverter; -import ch.qos.logback.classic.pattern.LoggerConverter; -import ch.qos.logback.classic.pattern.MDCConverter; -import ch.qos.logback.classic.pattern.MarkerConverter; -import ch.qos.logback.classic.pattern.MessageConverter; -import ch.qos.logback.classic.pattern.MethodOfCallerConverter; -import ch.qos.logback.classic.pattern.NopThrowableInformationConverter; -import ch.qos.logback.classic.pattern.RelativeTimeConverter; -import ch.qos.logback.classic.pattern.ThreadConverter; -import ch.qos.logback.classic.pattern.ThrowableProxyConverter; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.pattern.PatternLayoutBase; - -/** - *

- * A flexible layout configurable with pattern string. The goal of this class is - * to {@link #format format} a {@link ILoggingEvent} and return the results in a - * {#link String}. The format of the result depends on the - * conversion pattern. - *

- * For more information about this layout, please refer to the online manual at - * http://logback.qos.ch/manual/layouts.html#PatternLayout - * - */ - -public class PatternLayout extends PatternLayoutBase { - - public static final Map defaultConverterMap = new HashMap(); - - static { - - defaultConverterMap.put("d", DateConverter.class.getName()); - defaultConverterMap.put("date", DateConverter.class.getName()); - - defaultConverterMap.put("r", RelativeTimeConverter.class.getName()); - defaultConverterMap.put("relative", RelativeTimeConverter.class.getName()); - - defaultConverterMap.put("level", LevelConverter.class.getName()); - defaultConverterMap.put("le", LevelConverter.class.getName()); - defaultConverterMap.put("p", LevelConverter.class.getName()); - - defaultConverterMap.put("t", ThreadConverter.class.getName()); - defaultConverterMap.put("thread", ThreadConverter.class.getName()); - - defaultConverterMap.put("lo", LoggerConverter.class.getName()); - defaultConverterMap.put("logger", LoggerConverter.class.getName()); - defaultConverterMap.put("c", LoggerConverter.class.getName()); - - defaultConverterMap.put("m", MessageConverter.class.getName()); - defaultConverterMap.put("msg", MessageConverter.class.getName()); - defaultConverterMap.put("message", MessageConverter.class.getName()); - - defaultConverterMap.put("C", ClassOfCallerConverter.class.getName()); - defaultConverterMap.put("class", ClassOfCallerConverter.class.getName()); - - defaultConverterMap.put("M", MethodOfCallerConverter.class.getName()); - defaultConverterMap.put("method", MethodOfCallerConverter.class.getName()); - - defaultConverterMap.put("L", LineOfCallerConverter.class.getName()); - defaultConverterMap.put("line", LineOfCallerConverter.class.getName()); - - defaultConverterMap.put("F", FileOfCallerConverter.class.getName()); - defaultConverterMap.put("file", FileOfCallerConverter.class.getName()); - - defaultConverterMap.put("X", MDCConverter.class.getName()); - defaultConverterMap.put("mdc", MDCConverter.class.getName()); - - defaultConverterMap.put("ex", ThrowableProxyConverter.class.getName()); - defaultConverterMap.put("exception", ThrowableProxyConverter.class - .getName()); - defaultConverterMap.put("throwable", ThrowableProxyConverter.class - .getName()); - - defaultConverterMap.put("xEx", ExtendedThrowableProxyConverter.class.getName()); - defaultConverterMap.put("xException", ExtendedThrowableProxyConverter.class - .getName()); - defaultConverterMap.put("xThrowable", ExtendedThrowableProxyConverter.class - .getName()); - - defaultConverterMap.put("nopex", NopThrowableInformationConverter.class - .getName()); - defaultConverterMap.put("nopexception", - NopThrowableInformationConverter.class.getName()); - - defaultConverterMap.put("cn", ContextNameAction.class.getName()); - defaultConverterMap.put("contextName", ContextNameConverter.class.getName()); - - defaultConverterMap.put("caller", CallerDataConverter.class.getName()); - - defaultConverterMap.put("marker", MarkerConverter.class.getName()); - - defaultConverterMap.put("property", PropertyConverter.class.getName()); - - - defaultConverterMap.put("n", LineSeparatorConverter.class.getName()); - } - - public PatternLayout() { - this.postCompileProcessor = new EnsureExceptionHandling(); - } - - public Map getDefaultConverterMap() { - return defaultConverterMap; - } - - public String doLayout(ILoggingEvent event) { - if (!isStarted()) { - return CoreConstants.EMPTY_STRING; - } - return writeLoopOnConverters(event); - } - -} +/** + * 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.classic; + +import java.util.HashMap; +import java.util.Map; + +import ch.qos.logback.classic.joran.action.ContextNameAction; +import ch.qos.logback.classic.pattern.CallerDataConverter; +import ch.qos.logback.classic.pattern.ClassOfCallerConverter; +import ch.qos.logback.classic.pattern.ContextNameConverter; +import ch.qos.logback.classic.pattern.PropertyConverter; +import ch.qos.logback.classic.pattern.DateConverter; +import ch.qos.logback.classic.pattern.EnsureExceptionHandling; +import ch.qos.logback.classic.pattern.ExtendedThrowableProxyConverter; +import ch.qos.logback.classic.pattern.FileOfCallerConverter; +import ch.qos.logback.classic.pattern.LevelConverter; +import ch.qos.logback.classic.pattern.LineOfCallerConverter; +import ch.qos.logback.classic.pattern.LineSeparatorConverter; +import ch.qos.logback.classic.pattern.LoggerConverter; +import ch.qos.logback.classic.pattern.MDCConverter; +import ch.qos.logback.classic.pattern.MarkerConverter; +import ch.qos.logback.classic.pattern.MessageConverter; +import ch.qos.logback.classic.pattern.MethodOfCallerConverter; +import ch.qos.logback.classic.pattern.NopThrowableInformationConverter; +import ch.qos.logback.classic.pattern.RelativeTimeConverter; +import ch.qos.logback.classic.pattern.ThreadConverter; +import ch.qos.logback.classic.pattern.ThrowableProxyConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.pattern.PatternLayoutBase; + +/** + *

+ * A flexible layout configurable with pattern string. The goal of this class is + * to {@link #format format} a {@link ILoggingEvent} and return the results in a + * {#link String}. The format of the result depends on the + * conversion pattern. + *

+ * For more information about this layout, please refer to the online manual at + * http://logback.qos.ch/manual/layouts.html#PatternLayout + * + */ + +public class PatternLayout extends PatternLayoutBase { + + public static final Map defaultConverterMap = new HashMap(); + + static { + + defaultConverterMap.put("d", DateConverter.class.getName()); + defaultConverterMap.put("date", DateConverter.class.getName()); + + defaultConverterMap.put("r", RelativeTimeConverter.class.getName()); + defaultConverterMap.put("relative", RelativeTimeConverter.class.getName()); + + defaultConverterMap.put("level", LevelConverter.class.getName()); + defaultConverterMap.put("le", LevelConverter.class.getName()); + defaultConverterMap.put("p", LevelConverter.class.getName()); + + defaultConverterMap.put("t", ThreadConverter.class.getName()); + defaultConverterMap.put("thread", ThreadConverter.class.getName()); + + defaultConverterMap.put("lo", LoggerConverter.class.getName()); + defaultConverterMap.put("logger", LoggerConverter.class.getName()); + defaultConverterMap.put("c", LoggerConverter.class.getName()); + + defaultConverterMap.put("m", MessageConverter.class.getName()); + defaultConverterMap.put("msg", MessageConverter.class.getName()); + defaultConverterMap.put("message", MessageConverter.class.getName()); + + defaultConverterMap.put("C", ClassOfCallerConverter.class.getName()); + defaultConverterMap.put("class", ClassOfCallerConverter.class.getName()); + + defaultConverterMap.put("M", MethodOfCallerConverter.class.getName()); + defaultConverterMap.put("method", MethodOfCallerConverter.class.getName()); + + defaultConverterMap.put("L", LineOfCallerConverter.class.getName()); + defaultConverterMap.put("line", LineOfCallerConverter.class.getName()); + + defaultConverterMap.put("F", FileOfCallerConverter.class.getName()); + defaultConverterMap.put("file", FileOfCallerConverter.class.getName()); + + defaultConverterMap.put("X", MDCConverter.class.getName()); + defaultConverterMap.put("mdc", MDCConverter.class.getName()); + + defaultConverterMap.put("ex", ThrowableProxyConverter.class.getName()); + defaultConverterMap.put("exception", ThrowableProxyConverter.class + .getName()); + defaultConverterMap.put("throwable", ThrowableProxyConverter.class + .getName()); + + defaultConverterMap.put("xEx", ExtendedThrowableProxyConverter.class.getName()); + defaultConverterMap.put("xException", ExtendedThrowableProxyConverter.class + .getName()); + defaultConverterMap.put("xThrowable", ExtendedThrowableProxyConverter.class + .getName()); + + defaultConverterMap.put("nopex", NopThrowableInformationConverter.class + .getName()); + defaultConverterMap.put("nopexception", + NopThrowableInformationConverter.class.getName()); + + defaultConverterMap.put("cn", ContextNameAction.class.getName()); + defaultConverterMap.put("contextName", ContextNameConverter.class.getName()); + + defaultConverterMap.put("caller", CallerDataConverter.class.getName()); + + defaultConverterMap.put("marker", MarkerConverter.class.getName()); + + defaultConverterMap.put("property", PropertyConverter.class.getName()); + + + defaultConverterMap.put("n", LineSeparatorConverter.class.getName()); + } + + public PatternLayout() { + this.postCompileProcessor = new EnsureExceptionHandling(); + } + + public Map getDefaultConverterMap() { + return defaultConverterMap; + } + + public String doLayout(ILoggingEvent event) { + if (!isStarted()) { + return CoreConstants.EMPTY_STRING; + } + return writeLoopOnConverters(event); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/ViewStatusMessagesServlet.java b/logback-classic/src/main/java/ch/qos/logback/classic/ViewStatusMessagesServlet.java index acde75be48c784a2d3f308126c76933880b270d5..d02ebccf08b72e6729ef45d177e8d38b09560b5b 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/ViewStatusMessagesServlet.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/ViewStatusMessagesServlet.java @@ -1,42 +1,42 @@ -/** - * 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.classic; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.status.ViewStatusMessagesServletBase; - -public class ViewStatusMessagesServlet extends ViewStatusMessagesServletBase { - - private static final long serialVersionUID = 443878494348593337L; - - - @Override - protected StatusManager getStatusManager(HttpServletRequest req, HttpServletResponse resp) { - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - return lc.getStatusManager(); - } - - @Override - protected String getPageTitle(HttpServletRequest req, HttpServletResponse resp) { - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - return "

Status messages for LoggerContext named [" - + lc.getName() + "]

\r\n"; - } - -} +/** + * 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.classic; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.ViewStatusMessagesServletBase; + +public class ViewStatusMessagesServlet extends ViewStatusMessagesServletBase { + + private static final long serialVersionUID = 443878494348593337L; + + + @Override + protected StatusManager getStatusManager(HttpServletRequest req, HttpServletResponse resp) { + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + return lc.getStatusManager(); + } + + @Override + protected String getPageTitle(HttpServletRequest req, HttpServletResponse resp) { + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + return "

Status messages for LoggerContext named [" + + lc.getName() + "]

\r\n"; + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java b/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java index 0bfd020e0b6f0d1c508080c325ce65153c653bce..4d9d37425041a587d58c0d83eeab10f697b99862 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java @@ -1,151 +1,151 @@ -/** - * 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.classic.boolex; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.slf4j.Marker; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.IThrowableProxy; -import ch.qos.logback.classic.spi.LoggerContextVO; -import ch.qos.logback.classic.spi.ThrowableProxy; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.boolex.JaninoEventEvaluatorBase; -import ch.qos.logback.core.boolex.Matcher; - -public class JaninoEventEvaluator extends - JaninoEventEvaluatorBase { - - public final static String IMPORT_LEVEL = "import ch.qos.logback.classic.Level;\r\n"; - - public final static List DEFAULT_PARAM_NAME_LIST = new ArrayList(); - public final static List DEFAULT_PARAM_TYPE_LIST = new ArrayList(); - - static { - DEFAULT_PARAM_NAME_LIST.add("DEBUG"); - DEFAULT_PARAM_NAME_LIST.add("INFO"); - DEFAULT_PARAM_NAME_LIST.add("WARN"); - DEFAULT_PARAM_NAME_LIST.add("ERROR"); - - DEFAULT_PARAM_NAME_LIST.add("event"); - DEFAULT_PARAM_NAME_LIST.add("message"); - - DEFAULT_PARAM_NAME_LIST.add("formattedMessage"); - DEFAULT_PARAM_NAME_LIST.add("logger"); - DEFAULT_PARAM_NAME_LIST.add("loggerContext"); - DEFAULT_PARAM_NAME_LIST.add("level"); - DEFAULT_PARAM_NAME_LIST.add("timeStamp"); - DEFAULT_PARAM_NAME_LIST.add("marker"); - DEFAULT_PARAM_NAME_LIST.add("mdc"); - DEFAULT_PARAM_NAME_LIST.add("throwableProxy"); - DEFAULT_PARAM_NAME_LIST.add("throwable"); - - DEFAULT_PARAM_TYPE_LIST.add(int.class); - DEFAULT_PARAM_TYPE_LIST.add(int.class); - DEFAULT_PARAM_TYPE_LIST.add(int.class); - DEFAULT_PARAM_TYPE_LIST.add(int.class); - - DEFAULT_PARAM_TYPE_LIST.add(ILoggingEvent.class); - DEFAULT_PARAM_TYPE_LIST.add(String.class); - DEFAULT_PARAM_TYPE_LIST.add(String.class); - DEFAULT_PARAM_TYPE_LIST.add(String.class); - DEFAULT_PARAM_TYPE_LIST.add(LoggerContextVO.class); - DEFAULT_PARAM_TYPE_LIST.add(int.class); - DEFAULT_PARAM_TYPE_LIST.add(long.class); - DEFAULT_PARAM_TYPE_LIST.add(Marker.class); - DEFAULT_PARAM_TYPE_LIST.add(Map.class); - DEFAULT_PARAM_TYPE_LIST.add(IThrowableProxy.class); - DEFAULT_PARAM_TYPE_LIST.add(Throwable.class); - } - - public JaninoEventEvaluator() { - - } - - protected String getDecoratedExpression() { - return IMPORT_LEVEL + getExpression(); - } - - protected String[] getParameterNames() { - List fullNameList = new ArrayList(); - fullNameList.addAll(DEFAULT_PARAM_NAME_LIST); - - for (int i = 0; i < matcherList.size(); i++) { - Matcher m = (Matcher) matcherList.get(i); - fullNameList.add(m.getName()); - } - - return (String[]) fullNameList.toArray(CoreConstants.EMPTY_STRING_ARRAY); - } - - protected Class[] getParameterTypes() { - List fullTypeList = new ArrayList(); - fullTypeList.addAll(DEFAULT_PARAM_TYPE_LIST); - for (int i = 0; i < matcherList.size(); i++) { - fullTypeList.add(Matcher.class); - } - return (Class[]) fullTypeList.toArray(CoreConstants.EMPTY_CLASS_ARRAY); - } - - protected Object[] getParameterValues(ILoggingEvent loggingEvent) { - final int matcherListSize = matcherList.size(); - - int i = 0; - Object[] values = new Object[DEFAULT_PARAM_NAME_LIST.size() - + matcherListSize]; - - values[i++] = Level.DEBUG_INTEGER; - values[i++] = Level.INFO_INTEGER; - values[i++] = Level.WARN_INTEGER; - values[i++] = Level.ERROR_INTEGER; - - values[i++] = loggingEvent; - values[i++] = loggingEvent.getMessage(); - values[i++] = loggingEvent.getFormattedMessage(); - values[i++] = loggingEvent.getLoggerName(); - values[i++] = loggingEvent.getLoggerContextVO(); - values[i++] = loggingEvent.getLevel().toInteger(); - values[i++] = new Long(loggingEvent.getTimeStamp()); - // In order to avoid NullPointerException, we could push a dummy marker if - // the event's marker is null. However, this would surprise user who - // expect to see a null marker instead of a dummy one. - values[i++] = loggingEvent.getMarker(); - values[i++] = loggingEvent.getMDCPropertyMap(); - - IThrowableProxy iThrowableProxy = loggingEvent.getThrowableProxy(); - - if (iThrowableProxy != null) { - values[i++] = iThrowableProxy; - if (iThrowableProxy instanceof ThrowableProxy) { - values[i++] = ((ThrowableProxy) iThrowableProxy).getThrowable(); - } else { - values[i++] = null; - } - } else { - values[i++] = null; - values[i++] = null; - } - - for (int j = 0; j < matcherListSize; j++) { - values[i++] = (Matcher) matcherList.get(j); - } - - return values; - } - -} +/** + * 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.classic.boolex; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.slf4j.Marker; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.LoggerContextVO; +import ch.qos.logback.classic.spi.ThrowableProxy; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.boolex.JaninoEventEvaluatorBase; +import ch.qos.logback.core.boolex.Matcher; + +public class JaninoEventEvaluator extends + JaninoEventEvaluatorBase { + + public final static String IMPORT_LEVEL = "import ch.qos.logback.classic.Level;\r\n"; + + public final static List DEFAULT_PARAM_NAME_LIST = new ArrayList(); + public final static List DEFAULT_PARAM_TYPE_LIST = new ArrayList(); + + static { + DEFAULT_PARAM_NAME_LIST.add("DEBUG"); + DEFAULT_PARAM_NAME_LIST.add("INFO"); + DEFAULT_PARAM_NAME_LIST.add("WARN"); + DEFAULT_PARAM_NAME_LIST.add("ERROR"); + + DEFAULT_PARAM_NAME_LIST.add("event"); + DEFAULT_PARAM_NAME_LIST.add("message"); + + DEFAULT_PARAM_NAME_LIST.add("formattedMessage"); + DEFAULT_PARAM_NAME_LIST.add("logger"); + DEFAULT_PARAM_NAME_LIST.add("loggerContext"); + DEFAULT_PARAM_NAME_LIST.add("level"); + DEFAULT_PARAM_NAME_LIST.add("timeStamp"); + DEFAULT_PARAM_NAME_LIST.add("marker"); + DEFAULT_PARAM_NAME_LIST.add("mdc"); + DEFAULT_PARAM_NAME_LIST.add("throwableProxy"); + DEFAULT_PARAM_NAME_LIST.add("throwable"); + + DEFAULT_PARAM_TYPE_LIST.add(int.class); + DEFAULT_PARAM_TYPE_LIST.add(int.class); + DEFAULT_PARAM_TYPE_LIST.add(int.class); + DEFAULT_PARAM_TYPE_LIST.add(int.class); + + DEFAULT_PARAM_TYPE_LIST.add(ILoggingEvent.class); + DEFAULT_PARAM_TYPE_LIST.add(String.class); + DEFAULT_PARAM_TYPE_LIST.add(String.class); + DEFAULT_PARAM_TYPE_LIST.add(String.class); + DEFAULT_PARAM_TYPE_LIST.add(LoggerContextVO.class); + DEFAULT_PARAM_TYPE_LIST.add(int.class); + DEFAULT_PARAM_TYPE_LIST.add(long.class); + DEFAULT_PARAM_TYPE_LIST.add(Marker.class); + DEFAULT_PARAM_TYPE_LIST.add(Map.class); + DEFAULT_PARAM_TYPE_LIST.add(IThrowableProxy.class); + DEFAULT_PARAM_TYPE_LIST.add(Throwable.class); + } + + public JaninoEventEvaluator() { + + } + + protected String getDecoratedExpression() { + return IMPORT_LEVEL + getExpression(); + } + + protected String[] getParameterNames() { + List fullNameList = new ArrayList(); + fullNameList.addAll(DEFAULT_PARAM_NAME_LIST); + + for (int i = 0; i < matcherList.size(); i++) { + Matcher m = (Matcher) matcherList.get(i); + fullNameList.add(m.getName()); + } + + return (String[]) fullNameList.toArray(CoreConstants.EMPTY_STRING_ARRAY); + } + + protected Class[] getParameterTypes() { + List fullTypeList = new ArrayList(); + fullTypeList.addAll(DEFAULT_PARAM_TYPE_LIST); + for (int i = 0; i < matcherList.size(); i++) { + fullTypeList.add(Matcher.class); + } + return (Class[]) fullTypeList.toArray(CoreConstants.EMPTY_CLASS_ARRAY); + } + + protected Object[] getParameterValues(ILoggingEvent loggingEvent) { + final int matcherListSize = matcherList.size(); + + int i = 0; + Object[] values = new Object[DEFAULT_PARAM_NAME_LIST.size() + + matcherListSize]; + + values[i++] = Level.DEBUG_INTEGER; + values[i++] = Level.INFO_INTEGER; + values[i++] = Level.WARN_INTEGER; + values[i++] = Level.ERROR_INTEGER; + + values[i++] = loggingEvent; + values[i++] = loggingEvent.getMessage(); + values[i++] = loggingEvent.getFormattedMessage(); + values[i++] = loggingEvent.getLoggerName(); + values[i++] = loggingEvent.getLoggerContextVO(); + values[i++] = loggingEvent.getLevel().toInteger(); + values[i++] = new Long(loggingEvent.getTimeStamp()); + // In order to avoid NullPointerException, we could push a dummy marker if + // the event's marker is null. However, this would surprise user who + // expect to see a null marker instead of a dummy one. + values[i++] = loggingEvent.getMarker(); + values[i++] = loggingEvent.getMDCPropertyMap(); + + IThrowableProxy iThrowableProxy = loggingEvent.getThrowableProxy(); + + if (iThrowableProxy != null) { + values[i++] = iThrowableProxy; + if (iThrowableProxy instanceof ThrowableProxy) { + values[i++] = ((ThrowableProxy) iThrowableProxy).getThrowable(); + } else { + values[i++] = null; + } + } else { + values[i++] = null; + values[i++] = null; + } + + for (int j = 0; j < matcherListSize; j++) { + values[i++] = (Matcher) matcherList.get(j); + } + + return values; + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/boolex/OnErrorEvaluator.java b/logback-classic/src/main/java/ch/qos/logback/classic/boolex/OnErrorEvaluator.java index 7b4eb7db4ee01068df1878c738463ac1426423f4..8b80f7d428398cb52050bc9e30bac1d614e18763 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/boolex/OnErrorEvaluator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/boolex/OnErrorEvaluator.java @@ -1,38 +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.classic.boolex; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.boolex.EvaluationException; -import ch.qos.logback.core.boolex.EventEvaluatorBase; - -/** - * Evaluates to true when the logging event passed as parameter has level ERROR - * or higher. - * - * @author Ceki Gülcü - * - */ -public class OnErrorEvaluator extends EventEvaluatorBase { - - /** - * Return true if event passed as parameter has level ERROR or higher, returns - * false otherwise. - */ - public boolean evaluate(ILoggingEvent event) throws NullPointerException, - EvaluationException { - return event.getLevel().levelInt >= Level.ERROR_INT; - } -} +/** + * 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.classic.boolex; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluatorBase; + +/** + * Evaluates to true when the logging event passed as parameter has level ERROR + * or higher. + * + * @author Ceki Gülcü + * + */ +public class OnErrorEvaluator extends EventEvaluatorBase { + + /** + * Return true if event passed as parameter has level ERROR or higher, returns + * false otherwise. + */ + public boolean evaluate(ILoggingEvent event) throws NullPointerException, + EvaluationException { + return event.getLevel().levelInt >= Level.ERROR_INT; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/deleteTables.sql b/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/deleteTables.sql index 6f7fad5d57f55b2fc09eb4815c9360b3b4edf861..bd7c256de0a5493cb93ada0cf5a384b6b6dab836 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/deleteTables.sql +++ b/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/deleteTables.sql @@ -1,3 +1,3 @@ - -delete from access_event_property; -delete from access_event; + +delete from access_event_property; +delete from access_event; diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/db/package.html b/logback-classic/src/main/java/ch/qos/logback/classic/db/package.html index 38905a8f8db68b6a798d9a76ec341f4812d1bcb0..a696aa0d83e2fb05a1d2424a89c9e65f03c49c6e 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/db/package.html +++ b/logback-classic/src/main/java/ch/qos/logback/classic/db/package.html @@ -1,23 +1,23 @@ - - - - - - - - - -

The ch.qos.logback.classic.db package provides means to append logging events -into various databases. -

- -

Most popular database systems, such as PostgreSQL, MySQL, Oracle, DB2 and MsSQL -are supported. -

- -

Just as importantly, the way for obtaining JDBC connections is pluggable. Connections can -be obtained through the tradinal way of DriverManager, or alternatively as a DataSource. -A DataSource can be instantiated directly or it can obtained through JNDI. -

- + + + + + + + + + +

The ch.qos.logback.classic.db package provides means to append logging events +into various databases. +

+ +

Most popular database systems, such as PostgreSQL, MySQL, Oracle, DB2 and MsSQL +are supported. +

+ +

Just as importantly, the way for obtaining JDBC connections is pluggable. Connections can +be obtained through the tradinal way of DriverManager, or alternatively as a DataSource. +A DataSource can be instantiated directly or it can obtained through JNDI. +

+ \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/filter/LevelFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/filter/LevelFilter.java index 336f13cd82609705309e90c32b6488b9b249b854..5bc712f7d32d07d93edf8173e444893f61c3cb01 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/filter/LevelFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/filter/LevelFilter.java @@ -1,57 +1,57 @@ -/** - * 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.classic.filter; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.filter.AbstractMatcherFilter; -import ch.qos.logback.core.spi.FilterReply; - -/** - * A class that filters events by the level equality. - - *

- * For more information about this filter, please refer to the online manual at - * http://logback.qos.ch/manual/filters.html#levelFilter - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class LevelFilter extends AbstractMatcherFilter { - - Level level; - - @Override - public FilterReply decide(ILoggingEvent event) { - if (!isStarted()) { - return FilterReply.NEUTRAL; - } - - if (event.getLevel().equals(level)) { - return onMatch; - } else { - return onMismatch; - } - } - - public void setLevel(String level) { - this.level = Level.toLevel(level); - } - - public void start() { - if (this.level != null) { - super.start(); - } - } -} +/** + * 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.classic.filter; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.filter.AbstractMatcherFilter; +import ch.qos.logback.core.spi.FilterReply; + +/** + * A class that filters events by the level equality. + + *

+ * For more information about this filter, please refer to the online manual at + * http://logback.qos.ch/manual/filters.html#levelFilter + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class LevelFilter extends AbstractMatcherFilter { + + Level level; + + @Override + public FilterReply decide(ILoggingEvent event) { + if (!isStarted()) { + return FilterReply.NEUTRAL; + } + + if (event.getLevel().equals(level)) { + return onMatch; + } else { + return onMismatch; + } + } + + public void setLevel(String level) { + this.level = Level.toLevel(level); + } + + public void start() { + if (this.level != null) { + super.start(); + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/filter/ThresholdFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/filter/ThresholdFilter.java index 9bf1c2fd546babc153c96b2dfab2190dd33553e4..e85de8f4874cf6510ff9e0828aa77c38da7a4695 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/filter/ThresholdFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/filter/ThresholdFilter.java @@ -1,61 +1,61 @@ -/** - * 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.classic.filter; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.filter.Filter; -import ch.qos.logback.core.spi.FilterReply; - -/** - * Filters events below the threshold level. - * - * Events with a level below the specified - * level will be denied, while events with a level - * equal or above the specified level will trigger a - * FilterReply.NEUTRAL result, to allow the rest of the - * filter chain process the event. - * - * For more information about filters, please refer to the online manual at - * http://logback.qos.ch/manual/filters.html#thresholdFilter - * - * @author Sébastien Pennec - */ -public class ThresholdFilter extends Filter { - - Level level; - - @Override - public FilterReply decide(ILoggingEvent event) { - if (!isStarted()) { - return FilterReply.NEUTRAL; - } - - if (event.getLevel().isGreaterOrEqual(level)) { - return FilterReply.NEUTRAL; - } else { - return FilterReply.DENY; - } - } - - public void setLevel(String level) { - this.level = Level.toLevel(level); - } - - public void start() { - if (this.level != null) { - super.start(); - } - } -} +/** + * 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.classic.filter; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.spi.FilterReply; + +/** + * Filters events below the threshold level. + * + * Events with a level below the specified + * level will be denied, while events with a level + * equal or above the specified level will trigger a + * FilterReply.NEUTRAL result, to allow the rest of the + * filter chain process the event. + * + * For more information about filters, please refer to the online manual at + * http://logback.qos.ch/manual/filters.html#thresholdFilter + * + * @author Sébastien Pennec + */ +public class ThresholdFilter extends Filter { + + Level level; + + @Override + public FilterReply decide(ILoggingEvent event) { + if (!isStarted()) { + return FilterReply.NEUTRAL; + } + + if (event.getLevel().isGreaterOrEqual(level)) { + return FilterReply.NEUTRAL; + } else { + return FilterReply.DENY; + } + } + + public void setLevel(String level) { + this.level = Level.toLevel(level); + } + + public void start() { + if (this.level != null) { + super.start(); + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/helpers/package.html b/logback-classic/src/main/java/ch/qos/logback/classic/helpers/package.html index b58c0277f4730633dcd1d1a42db78171c43a5fe6..4caced844cccc6b281003835e81239f7c772c3fa 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/helpers/package.html +++ b/logback-classic/src/main/java/ch/qos/logback/classic/helpers/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains helpers.

- - + + + + + + + + + +

Contains helpers.

+ + \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultCssBuilder.java b/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultCssBuilder.java index 8b8bc1da464980ea2d1545d8e7d9e92165066e42..07f68eadb10f70870eb1a4e7cd9e7ab8f42264a3 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultCssBuilder.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultCssBuilder.java @@ -1,78 +1,78 @@ -/** - * 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.classic.html; - - -import ch.qos.logback.core.CoreConstants; -import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; -import ch.qos.logback.core.html.CssBuilder; - -/** - * This class helps the HTMLLayout build the CSS link. It either provides the - * HTMLLayout with a default css file, or builds the link to an external, - * user-specified, file. - * - * @author Sébastien Pennec - */ -public class DefaultCssBuilder implements CssBuilder { - - public DefaultCssBuilder() { - } - - public void addCss(StringBuilder sbuf) { - sbuf.append(""); - sbuf.append(LINE_SEPARATOR); - } -} +/** + * 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.classic.html; + + +import ch.qos.logback.core.CoreConstants; +import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; +import ch.qos.logback.core.html.CssBuilder; + +/** + * This class helps the HTMLLayout build the CSS link. It either provides the + * HTMLLayout with a default css file, or builds the link to an external, + * user-specified, file. + * + * @author Sébastien Pennec + */ +public class DefaultCssBuilder implements CssBuilder { + + public DefaultCssBuilder() { + } + + public void addCss(StringBuilder sbuf) { + sbuf.append(""); + sbuf.append(LINE_SEPARATOR); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java b/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java index 042f04542772aebdb01ba20d5bdfeefea58f251c..c2aaeeb3efcce7c57746a26d74d0a1806ffd0cac 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java @@ -1,71 +1,71 @@ -/** - * 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.classic.html; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.IThrowableProxy; -import ch.qos.logback.classic.spi.StackTraceElementProxy; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.helpers.Transform; -import ch.qos.logback.core.html.IThrowableRenderer; - -public class DefaultThrowableRenderer implements - IThrowableRenderer { - - static final String TRACE_PREFIX = "
    "; - - public DefaultThrowableRenderer() { - } - - public void render(StringBuilder sbuf, ILoggingEvent event) { - IThrowableProxy tp = event.getThrowableProxy(); - sbuf.append(""); - while (tp != null) { - render(sbuf, tp); - tp = tp.getCause(); - } - sbuf.append(""); - } - - void render(StringBuilder sbuf, IThrowableProxy tp) { - printFirstLine(sbuf, tp); - - int commonFrames = tp.getCommonFrames(); - StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); - - for (int i = 0; i < stepArray.length - commonFrames; i++) { - StackTraceElementProxy step = stepArray[i]; - sbuf.append(TRACE_PREFIX); - sbuf.append(Transform.escapeTags(step.toString())); - sbuf.append(CoreConstants.LINE_SEPARATOR); - } - - if (commonFrames > 0) { - sbuf.append(TRACE_PREFIX); - sbuf.append("\t... " + commonFrames).append(" common frames omitted") - .append(CoreConstants.LINE_SEPARATOR); - } - } - - public void printFirstLine(StringBuilder sb, IThrowableProxy tp) { - int commonFrames = tp.getCommonFrames(); - if (commonFrames > 0) { - sb.append("
").append(CoreConstants.CAUSED_BY); - } - sb.append(tp.getClassName()).append(": ").append( - Transform.escapeTags(tp.getMessage())); - sb.append(CoreConstants.LINE_SEPARATOR); - } - -} +/** + * 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.classic.html; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.helpers.Transform; +import ch.qos.logback.core.html.IThrowableRenderer; + +public class DefaultThrowableRenderer implements + IThrowableRenderer { + + static final String TRACE_PREFIX = "
    "; + + public DefaultThrowableRenderer() { + } + + public void render(StringBuilder sbuf, ILoggingEvent event) { + IThrowableProxy tp = event.getThrowableProxy(); + sbuf.append(""); + while (tp != null) { + render(sbuf, tp); + tp = tp.getCause(); + } + sbuf.append(""); + } + + void render(StringBuilder sbuf, IThrowableProxy tp) { + printFirstLine(sbuf, tp); + + int commonFrames = tp.getCommonFrames(); + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + + for (int i = 0; i < stepArray.length - commonFrames; i++) { + StackTraceElementProxy step = stepArray[i]; + sbuf.append(TRACE_PREFIX); + sbuf.append(Transform.escapeTags(step.toString())); + sbuf.append(CoreConstants.LINE_SEPARATOR); + } + + if (commonFrames > 0) { + sbuf.append(TRACE_PREFIX); + sbuf.append("\t... " + commonFrames).append(" common frames omitted") + .append(CoreConstants.LINE_SEPARATOR); + } + } + + public void printFirstLine(StringBuilder sb, IThrowableProxy tp) { + int commonFrames = tp.getCommonFrames(); + if (commonFrames > 0) { + sb.append("
").append(CoreConstants.CAUSED_BY); + } + sb.append(tp.getClassName()).append(": ").append( + Transform.escapeTags(tp.getMessage())); + sb.append(CoreConstants.LINE_SEPARATOR); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java b/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java index 8eb50c039d335107dad27356dea6b93abd316813..ddfe5af0bf5481eb100bfba1f952d418aba12191 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java @@ -1,126 +1,126 @@ -/** - * 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.classic.html; - -import java.util.Map; - -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.html.DefaultCssBuilder; -import ch.qos.logback.core.html.HTMLLayoutBase; -import ch.qos.logback.core.html.IThrowableRenderer; -import ch.qos.logback.core.pattern.Converter; -import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; - -/** - * - * HTMLLayout outputs events in an HTML table.

The content of the table - * columns are specified using a conversion pattern. See - * {@link ch.qos.logback.classic.PatternLayout} for documentation on the - * available patterns.

For more information about this layout, please refer - * to the online manual at - * http://logback.qos.ch/manual/layouts.html#ClassicHTMLLayout - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class HTMLLayout extends HTMLLayoutBase { - - /** - * Default pattern string for log output. - */ - static final String DEFAULT_CONVERSION_PATTERN = "%date%thread%level%logger%mdc%msg"; - - IThrowableRenderer throwableRenderer; - - /** - * Constructs a PatternLayout using the DEFAULT_LAYOUT_PATTERN. - * - * The default pattern just produces the application supplied message. - */ - public HTMLLayout() { - pattern = DEFAULT_CONVERSION_PATTERN; - throwableRenderer = new DefaultThrowableRenderer(); - cssBuilder = new DefaultCssBuilder(); - } - - @Override - public void start() { - int errorCount = 0; - if (throwableRenderer == null) { - addError("ThrowableRender cannot be null."); - errorCount++; - } - if (errorCount == 0) { - super.start(); - } - } - - protected Map getDefaultConverterMap() { - return PatternLayout.defaultConverterMap; - } - - public String doLayout(ILoggingEvent event) { - StringBuilder buf = new StringBuilder(); - startNewTableIfLimitReached(buf); - - boolean odd = true; - if (((counter++) & 1) == 0) { - odd = false; - } - - String level = event.getLevel().toString().toLowerCase(); - - buf.append(LINE_SEPARATOR); - buf.append(""); - } else { - buf.append(" even\">"); - } - buf.append(LINE_SEPARATOR); - - Converter c = head; - while (c != null) { - appendEventToBuffer(buf, c, event); - c = c.getNext(); - } - buf.append(""); - buf.append(LINE_SEPARATOR); - - if (event.getThrowableProxy() != null) { - throwableRenderer.render(buf, event); - } - return buf.toString(); - } - - private void appendEventToBuffer(StringBuilder buf, - Converter c, ILoggingEvent event) { - buf.append(""); - buf.append(c.convert(event)); - buf.append(""); - buf.append(LINE_SEPARATOR); - } - - public IThrowableRenderer getThrowableRenderer() { - return throwableRenderer; - } - - public void setThrowableRenderer(IThrowableRenderer throwableRenderer) { - this.throwableRenderer = throwableRenderer; - } -} +/** + * 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.classic.html; + +import java.util.Map; + +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.html.DefaultCssBuilder; +import ch.qos.logback.core.html.HTMLLayoutBase; +import ch.qos.logback.core.html.IThrowableRenderer; +import ch.qos.logback.core.pattern.Converter; +import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; + +/** + * + * HTMLLayout outputs events in an HTML table.

The content of the table + * columns are specified using a conversion pattern. See + * {@link ch.qos.logback.classic.PatternLayout} for documentation on the + * available patterns.

For more information about this layout, please refer + * to the online manual at + * http://logback.qos.ch/manual/layouts.html#ClassicHTMLLayout + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class HTMLLayout extends HTMLLayoutBase { + + /** + * Default pattern string for log output. + */ + static final String DEFAULT_CONVERSION_PATTERN = "%date%thread%level%logger%mdc%msg"; + + IThrowableRenderer throwableRenderer; + + /** + * Constructs a PatternLayout using the DEFAULT_LAYOUT_PATTERN. + * + * The default pattern just produces the application supplied message. + */ + public HTMLLayout() { + pattern = DEFAULT_CONVERSION_PATTERN; + throwableRenderer = new DefaultThrowableRenderer(); + cssBuilder = new DefaultCssBuilder(); + } + + @Override + public void start() { + int errorCount = 0; + if (throwableRenderer == null) { + addError("ThrowableRender cannot be null."); + errorCount++; + } + if (errorCount == 0) { + super.start(); + } + } + + protected Map getDefaultConverterMap() { + return PatternLayout.defaultConverterMap; + } + + public String doLayout(ILoggingEvent event) { + StringBuilder buf = new StringBuilder(); + startNewTableIfLimitReached(buf); + + boolean odd = true; + if (((counter++) & 1) == 0) { + odd = false; + } + + String level = event.getLevel().toString().toLowerCase(); + + buf.append(LINE_SEPARATOR); + buf.append(""); + } else { + buf.append(" even\">"); + } + buf.append(LINE_SEPARATOR); + + Converter c = head; + while (c != null) { + appendEventToBuffer(buf, c, event); + c = c.getNext(); + } + buf.append(""); + buf.append(LINE_SEPARATOR); + + if (event.getThrowableProxy() != null) { + throwableRenderer.render(buf, event); + } + return buf.toString(); + } + + private void appendEventToBuffer(StringBuilder buf, + Converter c, ILoggingEvent event) { + buf.append(""); + buf.append(c.convert(event)); + buf.append(""); + buf.append(LINE_SEPARATOR); + } + + public IThrowableRenderer getThrowableRenderer() { + return throwableRenderer; + } + + public void setThrowableRenderer(IThrowableRenderer throwableRenderer) { + this.throwableRenderer = throwableRenderer; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/html/UrlCssBuilder.java b/logback-classic/src/main/java/ch/qos/logback/classic/html/UrlCssBuilder.java index df8239ce54d669d2127a8f84f80916bcbfddf7db..324234107c4bd36b0b9b5fb28c88da08b5b4ac95 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/html/UrlCssBuilder.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/html/UrlCssBuilder.java @@ -1,46 +1,46 @@ -/** - * 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.classic.html; - -import ch.qos.logback.core.html.CssBuilder; - - -/** - * This class helps the HTMLLayout build the CSS link. - * It either provides the HTMLLayout with a default css file, - * or builds the link to an external, user-specified, file. - * - * @author Sébastien Pennec - */ -public class UrlCssBuilder implements CssBuilder { - - String url = "http://logback.qos.ch/css/classic.css"; - - public UrlCssBuilder() { - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public void addCss(StringBuilder sbuf) { - sbuf.append(""); - } -} +/** + * 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.classic.html; + +import ch.qos.logback.core.html.CssBuilder; + + +/** + * This class helps the HTMLLayout build the CSS link. + * It either provides the HTMLLayout with a default css file, + * or builds the link to an external, user-specified, file. + * + * @author Sébastien Pennec + */ +public class UrlCssBuilder implements CssBuilder { + + String url = "http://logback.qos.ch/css/classic.css"; + + public UrlCssBuilder() { + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public void addCss(StringBuilder sbuf) { + sbuf.append(""); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/html/package.html b/logback-classic/src/main/java/ch/qos/logback/classic/html/package.html index 39019b9c241c77d08b25fabf46619b6fc12c7255..c988c3f19ec0d4682a4e18a8aa7c169e7dd2bdfe 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/html/package.html +++ b/logback-classic/src/main/java/ch/qos/logback/classic/html/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains classes to format log output in HTML.

- - + + + + + + + + + +

Contains classes to format log output in HTML.

+ + \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/jmx/JMXConfigurator.java b/logback-classic/src/main/java/ch/qos/logback/classic/jmx/JMXConfigurator.java index bedd7cf9bc22a3ddb0b6b98929ad9a2c1b348d10..89f2415b481c405ffa8899952106156d6f28a168 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/jmx/JMXConfigurator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/jmx/JMXConfigurator.java @@ -1,296 +1,296 @@ -/** - * 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.classic.jmx; - -import java.io.File; -import java.io.FileNotFoundException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.management.InstanceNotFoundException; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.ObjectName; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.spi.LoggerContextListener; -import ch.qos.logback.classic.util.ContextInitializer; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusListener; -import ch.qos.logback.core.status.StatusListenerAsList; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.util.StatusPrinter; - -/** - * A class that provides access to logback components via JMX. - * - *

Since this class implements {@link JMXConfiguratorMBean} it has to be - * named as Configurator}. - * - * @author Ceki Gülcü - * @author Sébastien Pennec - * - * Contributor: Sebastian Davids See http://bugzilla.qos.ch/show_bug.cgi?id=35 - */ -public class JMXConfigurator extends ContextAwareBase implements - JMXConfiguratorMBean, LoggerContextListener { - - private static String EMPTY = ""; - - LoggerContext loggerContext; - MBeanServer mbs; - ObjectName objectName; - String objectNameAsString; - - // whether to output status events on the console when reloading the - // configuration - boolean debug = true; - - boolean started; - - public JMXConfigurator(LoggerContext loggerContext, MBeanServer mbs, - ObjectName objectName) { - started = true; - this.context = loggerContext; - this.loggerContext = loggerContext; - this.mbs = mbs; - this.objectName = objectName; - this.objectNameAsString = objectName.toString(); - if (previouslyRegisteredListenerWithSameObjectName()) { - addError("Previously registered JMXConfigurator named [" - + objectNameAsString + "] in the logger context named [" - + loggerContext.getName() + "]"); - } else { - // register as a listener only if there are no homonyms - loggerContext.addListener(this); - } - } - - private boolean previouslyRegisteredListenerWithSameObjectName() { - List lcll = loggerContext.getCopyOfListenerList(); - for (LoggerContextListener lcl : lcll) { - if (lcl instanceof JMXConfigurator) { - JMXConfigurator jmxConfigurator = (JMXConfigurator) lcl; - if (objectName.equals(jmxConfigurator.objectName)) { - return true; - } - } - } - return false; - } - - public void reloadDefaultConfiguration() throws JoranException { - ContextInitializer ci = new ContextInitializer(loggerContext); - URL url = ci.findURLOfDefaultConfigurationFile(true); - reloadByURL(url); - } - - public void reloadByFileName(String fileName) throws JoranException, - FileNotFoundException { - File f = new File(fileName); - if (f.exists() && f.isFile()) { - URL url; - try { - url = f.toURI().toURL(); - reloadByURL(url); - } catch (MalformedURLException e) { - throw new RuntimeException( - "Unexpected MalformedURLException occured. See nexted cause.", e); - } - - } else { - String errMsg = "Could not find [" + fileName + "]"; - addInfo(errMsg); - throw new FileNotFoundException(errMsg); - } - } - - void addStatusListener(StatusListener statusListener) { - StatusManager sm = loggerContext.getStatusManager(); - sm.add(statusListener); - } - - void removeStatusListener(StatusListener statusListener) { - StatusManager sm = loggerContext.getStatusManager(); - sm.remove(statusListener); - } - - public void reloadByURL(URL url) throws JoranException { - StatusListenerAsList statusListenerAsList = new StatusListenerAsList(); - - addStatusListener(statusListenerAsList); - addInfo("Resetting context: " + loggerContext.getName()); - loggerContext.reset(); - // after a reset the statusListenerAsList gets removed as a listener - addStatusListener(statusListenerAsList); - - try { - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(loggerContext); - configurator.doConfigure(url); - addInfo("Context: " + loggerContext.getName() + " reloaded."); - } finally { - removeStatusListener(statusListenerAsList); - if (debug) { - StatusPrinter.print(statusListenerAsList.getStatusList()); - } - } - } - - public void setLoggerLevel(String loggerName, String levelStr) { - if (loggerName == null) { - return; - } - if (levelStr == null) { - return; - } - loggerName = loggerName.trim(); - levelStr = levelStr.trim(); - - addInfo("Trying to set level " + levelStr + " to logger " + loggerName); - LoggerContext lc = (LoggerContext) context; - - Logger logger = lc.getLogger(loggerName); - if ("null".equalsIgnoreCase(levelStr)) { - logger.setLevel(null); - } else { - Level level = Level.toLevel(levelStr, null); - if (level != null) { - logger.setLevel(level); - } - } - } - - public String getLoggerLevel(String loggerName) { - if (loggerName == null) { - return EMPTY; - } - - loggerName = loggerName.trim(); - - LoggerContext lc = (LoggerContext) context; - Logger logger = lc.exists(loggerName); - if (logger != null && logger.getLevel() != null) { - return logger.getLevel().toString(); - } else { - return EMPTY; - } - } - - public String getLoggerEffectiveLevel(String loggerName) { - if (loggerName == null) { - return EMPTY; - } - - loggerName = loggerName.trim(); - - LoggerContext lc = (LoggerContext) context; - Logger logger = lc.exists(loggerName); - if (logger != null) { - return logger.getEffectiveLevel().toString(); - } else { - return EMPTY; - } - } - - public List getLoggerList() { - LoggerContext lc = (LoggerContext) context; - List strList = new ArrayList(); - Iterator it = lc.getLoggerList().iterator(); - while (it.hasNext()) { - Logger log = it.next(); - strList.add(log.getName()); - } - return strList; - } - - public List getStatuses() { - List list = new ArrayList(); - Iterator it = context.getStatusManager().getCopyOfStatusList() - .iterator(); - while (it.hasNext()) { - list.add(it.next().toString()); - } - return list; - } - - /** - * When the associated LoggerContext is stopped, this configurator must be - * unregistered - */ - public void onStop(LoggerContext context) { - if (!started) { - addInfo("onStop() method called on a stopped JMXActivator [" - + objectNameAsString + "]"); - return; - } - if (mbs.isRegistered(objectName)) { - try { - addInfo("Unregistering mbean [" + objectNameAsString + "]"); - mbs.unregisterMBean(objectName); - } catch (InstanceNotFoundException e) { - // this is theoretically impossible - addError("Unable to find a verifiably registered mbean [" - + objectNameAsString + "]", e); - } catch (MBeanRegistrationException e) { - addError("Failed to unregister [" + objectNameAsString + "]", e); - } - } else { - addInfo("mbean [" + objectNameAsString - + "] was not in the mbean registry. This is OK."); - } - stop(); - } - - public void onReset(LoggerContext context) { - addInfo("onReset() method called JMXActivator [" + objectNameAsString + "]"); - } - - /** - * JMXConfigrator should not be removed subsequent to a LoggerContext reset. - * - * @return - */ - public boolean isResetResistant() { - return true; - } - - private void clearFields() { - mbs = null; - objectName = null; - loggerContext = null; - } - - private void stop() { - started = false; - clearFields(); - } - - public void onStart(LoggerContext context) { - // nop - } - - @Override - public String toString() { - return this.getClass().getName() + "(" + context.getName() + ")"; - } -} +/** + * 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.classic.jmx; + +import java.io.File; +import java.io.FileNotFoundException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.management.InstanceNotFoundException; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.spi.LoggerContextListener; +import ch.qos.logback.classic.util.ContextInitializer; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.status.StatusListenerAsList; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.StatusPrinter; + +/** + * A class that provides access to logback components via JMX. + * + *

Since this class implements {@link JMXConfiguratorMBean} it has to be + * named as Configurator}. + * + * @author Ceki Gülcü + * @author Sébastien Pennec + * + * Contributor: Sebastian Davids See http://bugzilla.qos.ch/show_bug.cgi?id=35 + */ +public class JMXConfigurator extends ContextAwareBase implements + JMXConfiguratorMBean, LoggerContextListener { + + private static String EMPTY = ""; + + LoggerContext loggerContext; + MBeanServer mbs; + ObjectName objectName; + String objectNameAsString; + + // whether to output status events on the console when reloading the + // configuration + boolean debug = true; + + boolean started; + + public JMXConfigurator(LoggerContext loggerContext, MBeanServer mbs, + ObjectName objectName) { + started = true; + this.context = loggerContext; + this.loggerContext = loggerContext; + this.mbs = mbs; + this.objectName = objectName; + this.objectNameAsString = objectName.toString(); + if (previouslyRegisteredListenerWithSameObjectName()) { + addError("Previously registered JMXConfigurator named [" + + objectNameAsString + "] in the logger context named [" + + loggerContext.getName() + "]"); + } else { + // register as a listener only if there are no homonyms + loggerContext.addListener(this); + } + } + + private boolean previouslyRegisteredListenerWithSameObjectName() { + List lcll = loggerContext.getCopyOfListenerList(); + for (LoggerContextListener lcl : lcll) { + if (lcl instanceof JMXConfigurator) { + JMXConfigurator jmxConfigurator = (JMXConfigurator) lcl; + if (objectName.equals(jmxConfigurator.objectName)) { + return true; + } + } + } + return false; + } + + public void reloadDefaultConfiguration() throws JoranException { + ContextInitializer ci = new ContextInitializer(loggerContext); + URL url = ci.findURLOfDefaultConfigurationFile(true); + reloadByURL(url); + } + + public void reloadByFileName(String fileName) throws JoranException, + FileNotFoundException { + File f = new File(fileName); + if (f.exists() && f.isFile()) { + URL url; + try { + url = f.toURI().toURL(); + reloadByURL(url); + } catch (MalformedURLException e) { + throw new RuntimeException( + "Unexpected MalformedURLException occured. See nexted cause.", e); + } + + } else { + String errMsg = "Could not find [" + fileName + "]"; + addInfo(errMsg); + throw new FileNotFoundException(errMsg); + } + } + + void addStatusListener(StatusListener statusListener) { + StatusManager sm = loggerContext.getStatusManager(); + sm.add(statusListener); + } + + void removeStatusListener(StatusListener statusListener) { + StatusManager sm = loggerContext.getStatusManager(); + sm.remove(statusListener); + } + + public void reloadByURL(URL url) throws JoranException { + StatusListenerAsList statusListenerAsList = new StatusListenerAsList(); + + addStatusListener(statusListenerAsList); + addInfo("Resetting context: " + loggerContext.getName()); + loggerContext.reset(); + // after a reset the statusListenerAsList gets removed as a listener + addStatusListener(statusListenerAsList); + + try { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(loggerContext); + configurator.doConfigure(url); + addInfo("Context: " + loggerContext.getName() + " reloaded."); + } finally { + removeStatusListener(statusListenerAsList); + if (debug) { + StatusPrinter.print(statusListenerAsList.getStatusList()); + } + } + } + + public void setLoggerLevel(String loggerName, String levelStr) { + if (loggerName == null) { + return; + } + if (levelStr == null) { + return; + } + loggerName = loggerName.trim(); + levelStr = levelStr.trim(); + + addInfo("Trying to set level " + levelStr + " to logger " + loggerName); + LoggerContext lc = (LoggerContext) context; + + Logger logger = lc.getLogger(loggerName); + if ("null".equalsIgnoreCase(levelStr)) { + logger.setLevel(null); + } else { + Level level = Level.toLevel(levelStr, null); + if (level != null) { + logger.setLevel(level); + } + } + } + + public String getLoggerLevel(String loggerName) { + if (loggerName == null) { + return EMPTY; + } + + loggerName = loggerName.trim(); + + LoggerContext lc = (LoggerContext) context; + Logger logger = lc.exists(loggerName); + if (logger != null && logger.getLevel() != null) { + return logger.getLevel().toString(); + } else { + return EMPTY; + } + } + + public String getLoggerEffectiveLevel(String loggerName) { + if (loggerName == null) { + return EMPTY; + } + + loggerName = loggerName.trim(); + + LoggerContext lc = (LoggerContext) context; + Logger logger = lc.exists(loggerName); + if (logger != null) { + return logger.getEffectiveLevel().toString(); + } else { + return EMPTY; + } + } + + public List getLoggerList() { + LoggerContext lc = (LoggerContext) context; + List strList = new ArrayList(); + Iterator it = lc.getLoggerList().iterator(); + while (it.hasNext()) { + Logger log = it.next(); + strList.add(log.getName()); + } + return strList; + } + + public List getStatuses() { + List list = new ArrayList(); + Iterator it = context.getStatusManager().getCopyOfStatusList() + .iterator(); + while (it.hasNext()) { + list.add(it.next().toString()); + } + return list; + } + + /** + * When the associated LoggerContext is stopped, this configurator must be + * unregistered + */ + public void onStop(LoggerContext context) { + if (!started) { + addInfo("onStop() method called on a stopped JMXActivator [" + + objectNameAsString + "]"); + return; + } + if (mbs.isRegistered(objectName)) { + try { + addInfo("Unregistering mbean [" + objectNameAsString + "]"); + mbs.unregisterMBean(objectName); + } catch (InstanceNotFoundException e) { + // this is theoretically impossible + addError("Unable to find a verifiably registered mbean [" + + objectNameAsString + "]", e); + } catch (MBeanRegistrationException e) { + addError("Failed to unregister [" + objectNameAsString + "]", e); + } + } else { + addInfo("mbean [" + objectNameAsString + + "] was not in the mbean registry. This is OK."); + } + stop(); + } + + public void onReset(LoggerContext context) { + addInfo("onReset() method called JMXActivator [" + objectNameAsString + "]"); + } + + /** + * JMXConfigrator should not be removed subsequent to a LoggerContext reset. + * + * @return + */ + public boolean isResetResistant() { + return true; + } + + private void clearFields() { + mbs = null; + objectName = null; + loggerContext = null; + } + + private void stop() { + started = false; + clearFields(); + } + + public void onStart(LoggerContext context) { + // nop + } + + @Override + public String toString() { + return this.getClass().getName() + "(" + context.getName() + ")"; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/jmx/JMXConfiguratorMBean.java b/logback-classic/src/main/java/ch/qos/logback/classic/jmx/JMXConfiguratorMBean.java index fe84b1e9fa872b3db240a07d68cb27d9d1bf63f7..5d153418fdd87dac43af73bcfe3f903bac47d714 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/jmx/JMXConfiguratorMBean.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/jmx/JMXConfiguratorMBean.java @@ -1,39 +1,39 @@ -/** - * 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.classic.jmx; - -import java.io.FileNotFoundException; -import java.net.URL; -import java.util.List; - -import ch.qos.logback.core.joran.spi.JoranException; - -public interface JMXConfiguratorMBean { - - public void reloadDefaultConfiguration() throws JoranException; - - public void reloadByFileName(String fileName) throws JoranException, FileNotFoundException; - - public void reloadByURL(URL url) throws JoranException; - - public void setLoggerLevel(String loggerName, String levelStr); - - public String getLoggerLevel(String loggerName); - - public String getLoggerEffectiveLevel(String loggerName); - - public List getLoggerList(); - - public List getStatuses(); -} +/** + * 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.classic.jmx; + +import java.io.FileNotFoundException; +import java.net.URL; +import java.util.List; + +import ch.qos.logback.core.joran.spi.JoranException; + +public interface JMXConfiguratorMBean { + + public void reloadDefaultConfiguration() throws JoranException; + + public void reloadByFileName(String fileName) throws JoranException, FileNotFoundException; + + public void reloadByURL(URL url) throws JoranException; + + public void setLoggerLevel(String loggerName, String levelStr); + + public String getLoggerLevel(String loggerName); + + public String getLoggerEffectiveLevel(String loggerName); + + public List getLoggerList(); + + public List getStatuses(); +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/jmx/MBeanUtil.java b/logback-classic/src/main/java/ch/qos/logback/classic/jmx/MBeanUtil.java index 8c5885c963f628ced2e8cc345aff53f98d0ba414..5460c3ada0306f7aa71ed724063f67b2a73adad8 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/jmx/MBeanUtil.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/jmx/MBeanUtil.java @@ -1,87 +1,87 @@ -/** - * 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.classic.jmx; - -import javax.management.InstanceNotFoundException; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.status.StatusUtil; - -public class MBeanUtil { - - static final String DOMAIN = "ch.qos.logback.classic"; - - static public String getObjectNameFor(String contextName, Class type) { - String objectNameAsStr = DOMAIN + ":Name=" + contextName + ",Type=" - + type.getName(); - return objectNameAsStr; - } - - public static ObjectName string2ObjectName(Context context, Object caller, - String objectNameAsStr) { - String msg = "Failed to convert [" + objectNameAsStr + "] to ObjectName"; - - try { - return new ObjectName(objectNameAsStr); - } catch (MalformedObjectNameException e) { - StatusUtil.addError(context, caller, msg, e); - return null; - } catch (NullPointerException e) { - StatusUtil.addError(context, caller, msg, e); - return null; - } - } - - public static boolean isRegistered(MBeanServer mbs, ObjectName objectName) { - return mbs.isRegistered(objectName); - } - - public static void createAndRegisterJMXConfigurator( - MBeanServer mbs, LoggerContext loggerContext, - JMXConfigurator jmxConfigurator, ObjectName objectName, Object caller) { - try { - mbs.registerMBean(jmxConfigurator, objectName); - } catch (Exception e) { - StatusUtil.addError(loggerContext, caller, "Failed to create mbean", e); - } - } - - public static void unregister(LoggerContext loggerContext, MBeanServer mbs, - ObjectName objectName, Object caller) { - if (mbs.isRegistered(objectName)) { - try { - StatusUtil.addInfo(loggerContext, caller, "Unregistering mbean [" - + objectName + "]"); - mbs.unregisterMBean(objectName); - } catch (InstanceNotFoundException e) { - // this is theoretically impossible - StatusUtil.addError(loggerContext, caller, "Failed to unregister mbean" - + objectName, e); - } catch (MBeanRegistrationException e) { - // this is theoretically impossible - StatusUtil.addError(loggerContext, caller, "Failed to unregister mbean" - + objectName, e); - } - } else { - StatusUtil.addInfo(loggerContext, caller, "mbean [" + objectName - + "] does not seem to be registered"); - } - } - -} +/** + * 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.classic.jmx; + +import javax.management.InstanceNotFoundException; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.status.StatusUtil; + +public class MBeanUtil { + + static final String DOMAIN = "ch.qos.logback.classic"; + + static public String getObjectNameFor(String contextName, Class type) { + String objectNameAsStr = DOMAIN + ":Name=" + contextName + ",Type=" + + type.getName(); + return objectNameAsStr; + } + + public static ObjectName string2ObjectName(Context context, Object caller, + String objectNameAsStr) { + String msg = "Failed to convert [" + objectNameAsStr + "] to ObjectName"; + + try { + return new ObjectName(objectNameAsStr); + } catch (MalformedObjectNameException e) { + StatusUtil.addError(context, caller, msg, e); + return null; + } catch (NullPointerException e) { + StatusUtil.addError(context, caller, msg, e); + return null; + } + } + + public static boolean isRegistered(MBeanServer mbs, ObjectName objectName) { + return mbs.isRegistered(objectName); + } + + public static void createAndRegisterJMXConfigurator( + MBeanServer mbs, LoggerContext loggerContext, + JMXConfigurator jmxConfigurator, ObjectName objectName, Object caller) { + try { + mbs.registerMBean(jmxConfigurator, objectName); + } catch (Exception e) { + StatusUtil.addError(loggerContext, caller, "Failed to create mbean", e); + } + } + + public static void unregister(LoggerContext loggerContext, MBeanServer mbs, + ObjectName objectName, Object caller) { + if (mbs.isRegistered(objectName)) { + try { + StatusUtil.addInfo(loggerContext, caller, "Unregistering mbean [" + + objectName + "]"); + mbs.unregisterMBean(objectName); + } catch (InstanceNotFoundException e) { + // this is theoretically impossible + StatusUtil.addError(loggerContext, caller, "Failed to unregister mbean" + + objectName, e); + } catch (MBeanRegistrationException e) { + // this is theoretically impossible + StatusUtil.addError(loggerContext, caller, "Failed to unregister mbean" + + objectName, e); + } + } else { + StatusUtil.addInfo(loggerContext, caller, "mbean [" + objectName + + "] does not seem to be registered"); + } + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConfigurationAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConfigurationAction.java index 98d527efacbb36b9d402b1069b4f840cb824ed76..647577866f7579c5b210ffa4cb37c03b3f837d67 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConfigurationAction.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConfigurationAction.java @@ -1,89 +1,89 @@ -/** - * 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.classic.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.turbo.ReconfigureOnChangeFilter; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.util.Duration; -import ch.qos.logback.core.util.OptionHelper; -import ch.qos.logback.core.util.StatusPrinter; - -public class ConfigurationAction extends Action { - static final String INTERNAL_DEBUG_ATTR = "debug"; - static final String SCAN_ATTR = "scan"; - static final String SCAN_PERIOD_ATTR = "scanPeriod"; - - boolean debugMode = false; - - public void begin(InterpretationContext ec, String name, Attributes attributes) { - String debugAttrib = attributes.getValue(INTERNAL_DEBUG_ATTR); - - if (OptionHelper.isEmpty(debugAttrib) - || debugAttrib.equalsIgnoreCase("false") - || debugAttrib.equalsIgnoreCase("null")) { - addInfo(INTERNAL_DEBUG_ATTR + " attribute not set"); - } else { - // LoggerContext loggerContext = (LoggerContext) context; - // ConfiguratorBase.attachTemporaryConsoleAppender(context); - - debugMode = true; - } - - processScanAttrib(attributes); - - // the context is turbo filter attachable, so it is pushed on top of the - // stack - ec.pushObject(getContext()); - } - - void processScanAttrib(Attributes attributes) { - String scanAttrib = attributes.getValue(SCAN_ATTR); - if (!OptionHelper.isEmpty(scanAttrib) - && !"false".equalsIgnoreCase(scanAttrib)) { - ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter(); - rocf.setContext(context); - String scanPeriodAttrib = attributes.getValue(SCAN_PERIOD_ATTR); - if (!OptionHelper.isEmpty(scanPeriodAttrib)) { - try { - Duration duration = Duration.valueOf(scanPeriodAttrib); - rocf.setRefreshPeriod(duration.getMilliseconds()); - addInfo("Setting ReconfigureOnChangeFilter scanning period to " - + duration); - } catch (NumberFormatException nfe) { - addError("Error while converting [" + scanAttrib + "] to long", nfe); - } - } - rocf.start(); - LoggerContext lc = (LoggerContext) context; - addInfo("Adding ReconfigureOnChangeFilter as a turbo filter"); - lc.addTurboFilter(rocf); - } - } - - public void end(InterpretationContext ec, String name) { - if (debugMode) { - addInfo("End of configuration."); - LoggerContext loggerContext = (LoggerContext) context; - StatusPrinter.print(loggerContext); - - // LoggerContext loggerContext = (LoggerContext) context; - // ConfiguratorBase.detachTemporaryConsoleAppender(repository, errorList); - } - ec.popObject(); - } -} +/** + * 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.classic.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.turbo.ReconfigureOnChangeFilter; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.Duration; +import ch.qos.logback.core.util.OptionHelper; +import ch.qos.logback.core.util.StatusPrinter; + +public class ConfigurationAction extends Action { + static final String INTERNAL_DEBUG_ATTR = "debug"; + static final String SCAN_ATTR = "scan"; + static final String SCAN_PERIOD_ATTR = "scanPeriod"; + + boolean debugMode = false; + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + String debugAttrib = attributes.getValue(INTERNAL_DEBUG_ATTR); + + if (OptionHelper.isEmpty(debugAttrib) + || debugAttrib.equalsIgnoreCase("false") + || debugAttrib.equalsIgnoreCase("null")) { + addInfo(INTERNAL_DEBUG_ATTR + " attribute not set"); + } else { + // LoggerContext loggerContext = (LoggerContext) context; + // ConfiguratorBase.attachTemporaryConsoleAppender(context); + + debugMode = true; + } + + processScanAttrib(attributes); + + // the context is turbo filter attachable, so it is pushed on top of the + // stack + ec.pushObject(getContext()); + } + + void processScanAttrib(Attributes attributes) { + String scanAttrib = attributes.getValue(SCAN_ATTR); + if (!OptionHelper.isEmpty(scanAttrib) + && !"false".equalsIgnoreCase(scanAttrib)) { + ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter(); + rocf.setContext(context); + String scanPeriodAttrib = attributes.getValue(SCAN_PERIOD_ATTR); + if (!OptionHelper.isEmpty(scanPeriodAttrib)) { + try { + Duration duration = Duration.valueOf(scanPeriodAttrib); + rocf.setRefreshPeriod(duration.getMilliseconds()); + addInfo("Setting ReconfigureOnChangeFilter scanning period to " + + duration); + } catch (NumberFormatException nfe) { + addError("Error while converting [" + scanAttrib + "] to long", nfe); + } + } + rocf.start(); + LoggerContext lc = (LoggerContext) context; + addInfo("Adding ReconfigureOnChangeFilter as a turbo filter"); + lc.addTurboFilter(rocf); + } + } + + public void end(InterpretationContext ec, String name) { + if (debugMode) { + addInfo("End of configuration."); + LoggerContext loggerContext = (LoggerContext) context; + StatusPrinter.print(loggerContext); + + // LoggerContext loggerContext = (LoggerContext) context; + // ConfiguratorBase.detachTemporaryConsoleAppender(repository, errorList); + } + ec.popObject(); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConsolePluginAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConsolePluginAction.java index d1196ddfc6646ea8250984d6380419cb5b1b4c3a..d8beb7d464fdc103c0fcb0a1941c918d69ad4e18 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConsolePluginAction.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ConsolePluginAction.java @@ -1,64 +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.classic.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.net.SocketAppender; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; - -public class ConsolePluginAction extends Action { - - private static final String PORT_ATTR = "port"; - private static final Integer DEFAULT_PORT = 4321; - - @Override - public void begin(InterpretationContext ec, String name, Attributes attributes) - throws ActionException { - String portStr = attributes.getValue(PORT_ATTR); - Integer port = null; - - if (portStr == null) { - port = DEFAULT_PORT; - } else { - try { - port = Integer.valueOf(portStr); - } catch (NumberFormatException ex) { - addError("Port " + portStr - + " in ConsolePlugin config is not a correct number"); - } - } - - LoggerContext lc = (LoggerContext)ec.getContext(); - SocketAppender appender = new SocketAppender(); - appender.setContext(lc); - appender.setIncludeCallerData(true); - appender.setRemoteHost("localhost"); - appender.setPort(port.intValue()); - appender.start(); - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - root.addAppender(appender); - - addInfo("Sending LoggingEvents to the plugin using port " + port); - } - - @Override - public void end(InterpretationContext ec, String name) throws ActionException { - - } -} +/** + * 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.classic.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.net.SocketAppender; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; + +public class ConsolePluginAction extends Action { + + private static final String PORT_ATTR = "port"; + private static final Integer DEFAULT_PORT = 4321; + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + String portStr = attributes.getValue(PORT_ATTR); + Integer port = null; + + if (portStr == null) { + port = DEFAULT_PORT; + } else { + try { + port = Integer.valueOf(portStr); + } catch (NumberFormatException ex) { + addError("Port " + portStr + + " in ConsolePlugin config is not a correct number"); + } + } + + LoggerContext lc = (LoggerContext)ec.getContext(); + SocketAppender appender = new SocketAppender(); + appender.setContext(lc); + appender.setIncludeCallerData(true); + appender.setRemoteHost("localhost"); + appender.setPort(port.intValue()); + appender.start(); + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + root.addAppender(appender); + + addInfo("Sending LoggingEvents to the plugin using port " + port); + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ContextNameAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ContextNameAction.java index 0485130480a73a56ab30781d8e47c86b6498f02c..78ffc303b9cb50e54a2944f0b985991d34970759 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ContextNameAction.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/ContextNameAction.java @@ -1,40 +1,40 @@ -/** - * 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.classic.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.InterpretationContext; - -public class ContextNameAction extends Action { - - public void begin(InterpretationContext ec, String name, Attributes attributes) { - } - - public void body(InterpretationContext ec, String body) { - - String finalBody = ec.subst(body); - addInfo("Setting logger context name as [" + finalBody + "]"); - try { - context.setName(finalBody); - } catch (IllegalStateException e) { - addError("Failed to rename context [" + context.getName() + "] as [" - + finalBody + "]", e); - } - } - - public void end(InterpretationContext ec, String name) { - } -} +/** + * 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.classic.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; + +public class ContextNameAction extends Action { + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + } + + public void body(InterpretationContext ec, String body) { + + String finalBody = ec.subst(body); + addInfo("Setting logger context name as [" + finalBody + "]"); + try { + context.setName(finalBody); + } catch (IllegalStateException e) { + addError("Failed to rename context [" + context.getName() + "] as [" + + finalBody + "]", e); + } + } + + public void end(InterpretationContext ec, String name) { + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/EvaluatorAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/EvaluatorAction.java index 3880d08b11496c75269dd37247aa35b0ac7a7ab0..7bca6f707fc928470b41b96c97a1aa472593218a 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/EvaluatorAction.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/EvaluatorAction.java @@ -1,23 +1,23 @@ -/** - * 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.classic.joran.action; - -import ch.qos.logback.classic.boolex.JaninoEventEvaluator; -import ch.qos.logback.core.joran.action.AbstractEventEvaluatorAction; - -public class EvaluatorAction extends AbstractEventEvaluatorAction { - protected String defaultClassName() { - return JaninoEventEvaluator.class.getName(); - } -} +/** + * 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.classic.joran.action; + +import ch.qos.logback.classic.boolex.JaninoEventEvaluator; +import ch.qos.logback.core.joran.action.AbstractEventEvaluatorAction; + +public class EvaluatorAction extends AbstractEventEvaluatorAction { + protected String defaultClassName() { + return JaninoEventEvaluator.class.getName(); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/InsertFromJNDIAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/InsertFromJNDIAction.java index 314f8f1c811a56924cc64b6eb93b79e28cd9f87e..abe86281a8b8c6b701e378e6d1c3553caf66d148 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/InsertFromJNDIAction.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/InsertFromJNDIAction.java @@ -1,78 +1,78 @@ -/** - * 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.classic.joran.action; - -import javax.naming.Context; -import javax.naming.NamingException; - -import org.xml.sax.Attributes; - -import ch.qos.logback.classic.util.JNDIUtil; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.util.OptionHelper; - -/** - * Insert an env-entry found in JNDI as a new context variable - - * @author Ceki Gulcu - * - */ -public class InsertFromJNDIAction extends Action { - - public static String ENV_ENTRY_NAME_ATTR="env-entry-name"; - public static String AS_ATTR="as"; - - public void begin(InterpretationContext ec, String name, Attributes attributes) { - - int errorCount = 0; - String envEntryName = attributes.getValue(ENV_ENTRY_NAME_ATTR); - String asName = attributes.getValue(AS_ATTR); - String envEntryValue; - - if(OptionHelper.isEmpty(envEntryName)) { - String lineColStr = getLineColStr(ec); - addError("["+ENV_ENTRY_NAME_ATTR+"] missing, around "+lineColStr); - errorCount++; - } - - if(OptionHelper.isEmpty(asName)) { - String lineColStr = getLineColStr(ec); - addError("["+AS_ATTR+"] missing, around "+lineColStr); - errorCount++; - } - - if(errorCount != 0) { - return; - } - - try { - Context ctx = JNDIUtil.getInitialContext(); - envEntryValue = JNDIUtil.lookup(ctx, envEntryName); - if(OptionHelper.isEmpty(envEntryValue)) { - addError("["+envEntryName+"] has null or empty value"); - } else { - addInfo("Setting context variable ["+asName+"] to ["+envEntryValue+"]"); - context.putProperty(asName, envEntryValue); - } - } catch (NamingException e) { - addError("Failed to lookup JNDI env-entry ["+envEntryName+"]"); - } - - - } - - public void end(InterpretationContext ec, String name) { - } -} +/** + * 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.classic.joran.action; + +import javax.naming.Context; +import javax.naming.NamingException; + +import org.xml.sax.Attributes; + +import ch.qos.logback.classic.util.JNDIUtil; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; + +/** + * Insert an env-entry found in JNDI as a new context variable + + * @author Ceki Gulcu + * + */ +public class InsertFromJNDIAction extends Action { + + public static String ENV_ENTRY_NAME_ATTR="env-entry-name"; + public static String AS_ATTR="as"; + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + + int errorCount = 0; + String envEntryName = attributes.getValue(ENV_ENTRY_NAME_ATTR); + String asName = attributes.getValue(AS_ATTR); + String envEntryValue; + + if(OptionHelper.isEmpty(envEntryName)) { + String lineColStr = getLineColStr(ec); + addError("["+ENV_ENTRY_NAME_ATTR+"] missing, around "+lineColStr); + errorCount++; + } + + if(OptionHelper.isEmpty(asName)) { + String lineColStr = getLineColStr(ec); + addError("["+AS_ATTR+"] missing, around "+lineColStr); + errorCount++; + } + + if(errorCount != 0) { + return; + } + + try { + Context ctx = JNDIUtil.getInitialContext(); + envEntryValue = JNDIUtil.lookup(ctx, envEntryName); + if(OptionHelper.isEmpty(envEntryValue)) { + addError("["+envEntryName+"] has null or empty value"); + } else { + addInfo("Setting context variable ["+asName+"] to ["+envEntryValue+"]"); + context.putProperty(asName, envEntryValue); + } + } catch (NamingException e) { + addError("Failed to lookup JNDI env-entry ["+envEntryName+"]"); + } + + + } + + public void end(InterpretationContext ec, String name) { + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/JMXConfiguratorAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/JMXConfiguratorAction.java index 20af5f183e45a597426d720ebf08f885c7425b31..5f77002290e40f0d7b05934500406945ad26bd63 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/JMXConfiguratorAction.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/JMXConfiguratorAction.java @@ -1,89 +1,89 @@ -/** - * 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.classic.joran.action; - -import java.lang.management.ManagementFactory; - -import javax.management.MBeanServer; -import javax.management.ObjectName; - -import org.xml.sax.Attributes; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.jmx.JMXConfigurator; -import ch.qos.logback.classic.jmx.MBeanUtil; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.util.OptionHelper; - -public class JMXConfiguratorAction extends Action { - - static final String OBJECT_NAME_ATTRIBUTE_NAME = "objectName"; - static final String CONTEXT_NAME_ATTRIBUTE_NAME = "contextName"; - static final char JMX_NAME_SEPARATOR = ','; - - @Override - public void begin(InterpretationContext ec, String name, Attributes attributes) - throws ActionException { - addInfo("begin"); - - - String contextName = context.getName(); - String contextNameAttributeVal = attributes - .getValue(CONTEXT_NAME_ATTRIBUTE_NAME); - if(!OptionHelper.isEmpty(contextNameAttributeVal)) { - contextName = contextNameAttributeVal; - } - - String objectNameAsStr; - String objectNameAttributeVal = attributes - .getValue(OBJECT_NAME_ATTRIBUTE_NAME); - if (OptionHelper.isEmpty(objectNameAttributeVal)) { - objectNameAsStr = MBeanUtil.getObjectNameFor(contextName, - JMXConfigurator.class); - } else { - objectNameAsStr = objectNameAttributeVal; - } - - ObjectName objectName = MBeanUtil.string2ObjectName(context, this, - objectNameAsStr); - if (objectName == null) { - addError("Failed to for ObjectName for ["+objectNameAsStr+"]"); - return; - } - - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - if(!MBeanUtil.isRegistered(mbs, objectName)) { - // register only of the named JMXConfigurator has not been previously - // registered. Unregistering an MBean within invocation of itself - // caused jconsole to throw an NPE. (This occurs when the reload* method - // unregisters the - JMXConfigurator jmxConfigurator = new JMXConfigurator((LoggerContext) context, mbs, - objectName); - try { - mbs.registerMBean(jmxConfigurator, objectName); - } catch (Exception e) { - addError("Failed to create mbean", e); - } - } - - } - - @Override - public void end(InterpretationContext ec, String name) throws ActionException { - - } - -} +/** + * 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.classic.joran.action; + +import java.lang.management.ManagementFactory; + +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.xml.sax.Attributes; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.jmx.JMXConfigurator; +import ch.qos.logback.classic.jmx.MBeanUtil; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; + +public class JMXConfiguratorAction extends Action { + + static final String OBJECT_NAME_ATTRIBUTE_NAME = "objectName"; + static final String CONTEXT_NAME_ATTRIBUTE_NAME = "contextName"; + static final char JMX_NAME_SEPARATOR = ','; + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + addInfo("begin"); + + + String contextName = context.getName(); + String contextNameAttributeVal = attributes + .getValue(CONTEXT_NAME_ATTRIBUTE_NAME); + if(!OptionHelper.isEmpty(contextNameAttributeVal)) { + contextName = contextNameAttributeVal; + } + + String objectNameAsStr; + String objectNameAttributeVal = attributes + .getValue(OBJECT_NAME_ATTRIBUTE_NAME); + if (OptionHelper.isEmpty(objectNameAttributeVal)) { + objectNameAsStr = MBeanUtil.getObjectNameFor(contextName, + JMXConfigurator.class); + } else { + objectNameAsStr = objectNameAttributeVal; + } + + ObjectName objectName = MBeanUtil.string2ObjectName(context, this, + objectNameAsStr); + if (objectName == null) { + addError("Failed to for ObjectName for ["+objectNameAsStr+"]"); + return; + } + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + if(!MBeanUtil.isRegistered(mbs, objectName)) { + // register only of the named JMXConfigurator has not been previously + // registered. Unregistering an MBean within invocation of itself + // caused jconsole to throw an NPE. (This occurs when the reload* method + // unregisters the + JMXConfigurator jmxConfigurator = new JMXConfigurator((LoggerContext) context, mbs, + objectName); + try { + mbs.registerMBean(jmxConfigurator, objectName); + } catch (Exception e) { + addError("Failed to create mbean", e); + } + } + + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LevelAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LevelAction.java index 0d5f2e645d475f515df97a94d8bbf17b92ea5f83..6162e8d74fe886bb64a6bf1951d7a3e2ed8d5da3 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LevelAction.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LevelAction.java @@ -1,67 +1,67 @@ -/** - * 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.classic.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.action.ActionConst; -import ch.qos.logback.core.joran.spi.InterpretationContext; - -/** - * Action to handle the element nested within element. - * - *

This action is deprecated. Use the level attribute within the logger - * element. - * - * @author Ceki Gulcu - */ -public class LevelAction extends Action { - - boolean inError = false; - - public void begin(InterpretationContext ec, String name, Attributes attributes) { - Object o = ec.peekObject(); - - if (!(o instanceof Logger)) { - inError = true; - addError("For element , could not find a logger at the top of execution stack."); - return; - } - - Logger l = (Logger) o; - - String loggerName = l.getName(); - - String levelStr = ec.subst(attributes.getValue(ActionConst.VALUE_ATTR)); - //addInfo("Encapsulating logger name is [" + loggerName - // + "], level value is [" + levelStr + "]."); - - if (ActionConst.INHERITED.equalsIgnoreCase(levelStr) || ActionConst.NULL.equalsIgnoreCase(levelStr)) { - l.setLevel(null); - } else { - l.setLevel(Level.toLevel(levelStr, Level.DEBUG)); - } - - addInfo(loggerName + " level set to " + l.getLevel()); - } - - public void finish(InterpretationContext ec) { - } - - public void end(InterpretationContext ec, String e) { - } -} +/** + * 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.classic.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.action.ActionConst; +import ch.qos.logback.core.joran.spi.InterpretationContext; + +/** + * Action to handle the element nested within element. + * + *

This action is deprecated. Use the level attribute within the logger + * element. + * + * @author Ceki Gulcu + */ +public class LevelAction extends Action { + + boolean inError = false; + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + Object o = ec.peekObject(); + + if (!(o instanceof Logger)) { + inError = true; + addError("For element , could not find a logger at the top of execution stack."); + return; + } + + Logger l = (Logger) o; + + String loggerName = l.getName(); + + String levelStr = ec.subst(attributes.getValue(ActionConst.VALUE_ATTR)); + //addInfo("Encapsulating logger name is [" + loggerName + // + "], level value is [" + levelStr + "]."); + + if (ActionConst.INHERITED.equalsIgnoreCase(levelStr) || ActionConst.NULL.equalsIgnoreCase(levelStr)) { + l.setLevel(null); + } else { + l.setLevel(Level.toLevel(levelStr, Level.DEBUG)); + } + + addInfo(loggerName + " level set to " + l.getLevel()); + } + + public void finish(InterpretationContext ec) { + } + + public void end(InterpretationContext ec, String e) { + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LoggerAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LoggerAction.java index b2f3df4cae5fd0caf094c890651c3246354b76f2..f99b65197bf61cf1b4c603b3b611992823730ddc 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LoggerAction.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LoggerAction.java @@ -1,95 +1,95 @@ -/** - * 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.classic.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.action.ActionConst; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.util.OptionHelper; - -/** - * Action which handles elements in configuration files. - * - * @author Ceki Gulcu - */ -public class LoggerAction extends Action { - public static final String LEVEL_ATTRIBUTE = "level"; - - boolean inError = false; - Logger logger; - public void begin(InterpretationContext ec, String name, Attributes attributes) { - // Let us forget about previous errors (in this object) - inError = false; - logger = null; - - LoggerContext loggerContext = (LoggerContext) this.context; - - String loggerName = attributes.getValue(NAME_ATTRIBUTE); - - if (OptionHelper.isEmpty(loggerName)) { - inError = true; - String aroundLine = getLineColStr(ec); - String errorMsg = "No 'name' attribute in element " + name + ", around " +aroundLine; - addError(errorMsg); - return; - } - - logger = loggerContext.getLogger(loggerName); - - String levelStr = ec.subst(attributes.getValue(LEVEL_ATTRIBUTE)); - - if (!OptionHelper.isEmpty(levelStr)) { - if (ActionConst.INHERITED.equalsIgnoreCase(levelStr) - || ActionConst.NULL.equalsIgnoreCase(levelStr)) { - addInfo("Setting level of logger [" + loggerName - + "] to null, i.e. INHERITED"); - logger.setLevel(null); - } else { - Level level = Level.toLevel(levelStr); - addInfo("Setting level of logger [" + loggerName + "] to " + level); - logger.setLevel(level); - } - } - - if (!OptionHelper.isEmpty(ActionConst.ADDITIVITY_ATTRIBUTE)) { - boolean additive = OptionHelper.toBoolean(attributes - .getValue(ActionConst.ADDITIVITY_ATTRIBUTE), true); - addInfo("Setting additivity of logger [" + loggerName + "] to " - + additive); - logger.setAdditive(additive); - } - ec.pushObject(logger); - } - - public void end(InterpretationContext ec, String e) { - if (inError) { - return; - } - Object o = ec.peekObject(); - if (o != logger) { - addWarn("The object on the top the of the stack is not "+logger+" pushed earlier"); - addWarn("It is: " + o); - } else { - ec.popObject(); - } - } - - public void finish(InterpretationContext ec) { - } -} +/** + * 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.classic.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.action.ActionConst; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; + +/** + * Action which handles elements in configuration files. + * + * @author Ceki Gulcu + */ +public class LoggerAction extends Action { + public static final String LEVEL_ATTRIBUTE = "level"; + + boolean inError = false; + Logger logger; + public void begin(InterpretationContext ec, String name, Attributes attributes) { + // Let us forget about previous errors (in this object) + inError = false; + logger = null; + + LoggerContext loggerContext = (LoggerContext) this.context; + + String loggerName = attributes.getValue(NAME_ATTRIBUTE); + + if (OptionHelper.isEmpty(loggerName)) { + inError = true; + String aroundLine = getLineColStr(ec); + String errorMsg = "No 'name' attribute in element " + name + ", around " +aroundLine; + addError(errorMsg); + return; + } + + logger = loggerContext.getLogger(loggerName); + + String levelStr = ec.subst(attributes.getValue(LEVEL_ATTRIBUTE)); + + if (!OptionHelper.isEmpty(levelStr)) { + if (ActionConst.INHERITED.equalsIgnoreCase(levelStr) + || ActionConst.NULL.equalsIgnoreCase(levelStr)) { + addInfo("Setting level of logger [" + loggerName + + "] to null, i.e. INHERITED"); + logger.setLevel(null); + } else { + Level level = Level.toLevel(levelStr); + addInfo("Setting level of logger [" + loggerName + "] to " + level); + logger.setLevel(level); + } + } + + if (!OptionHelper.isEmpty(ActionConst.ADDITIVITY_ATTRIBUTE)) { + boolean additive = OptionHelper.toBoolean(attributes + .getValue(ActionConst.ADDITIVITY_ATTRIBUTE), true); + addInfo("Setting additivity of logger [" + loggerName + "] to " + + additive); + logger.setAdditive(additive); + } + ec.pushObject(logger); + } + + public void end(InterpretationContext ec, String e) { + if (inError) { + return; + } + Object o = ec.peekObject(); + if (o != logger) { + addWarn("The object on the top the of the stack is not "+logger+" pushed earlier"); + addWarn("It is: " + o); + } else { + ec.popObject(); + } + } + + public void finish(InterpretationContext ec) { + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/RootLoggerAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/RootLoggerAction.java index 4ca671163e89c7007af2c9116082f5a61f8ca87e..047269b90d5af107e68d23ae425324e8ffd6b3cb 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/RootLoggerAction.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/RootLoggerAction.java @@ -1,62 +1,62 @@ -/** - * 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.classic.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.action.ActionConst; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.util.OptionHelper; - -public class RootLoggerAction extends Action { - - Logger root; - boolean inError = false; - - public void begin(InterpretationContext ec, String name, Attributes attributes) { - inError = false; - - LoggerContext loggerContext = (LoggerContext) this.context; - root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME); - - String levelStr = ec.subst(attributes.getValue(ActionConst.LEVEL_ATTRIBUTE)); - if (!OptionHelper.isEmpty(levelStr)) { - Level level = Level.toLevel(levelStr); - addInfo("Setting level of ROOT logger to " + level); - root.setLevel(level); - } - - ec.pushObject(root); - } - - public void end(InterpretationContext ec, String name) { - if (inError) { - return; - } - Object o = ec.peekObject(); - if (o != root) { - addWarn("The object on the top the of the stack is not the root logger"); - addWarn("It is: " + o); - } else { - ec.popObject(); - } - } - - public void finish(InterpretationContext ec) { - } -} +/** + * 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.classic.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.action.ActionConst; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; + +public class RootLoggerAction extends Action { + + Logger root; + boolean inError = false; + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + inError = false; + + LoggerContext loggerContext = (LoggerContext) this.context; + root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME); + + String levelStr = ec.subst(attributes.getValue(ActionConst.LEVEL_ATTRIBUTE)); + if (!OptionHelper.isEmpty(levelStr)) { + Level level = Level.toLevel(levelStr); + addInfo("Setting level of ROOT logger to " + level); + root.setLevel(level); + } + + ec.pushObject(root); + } + + public void end(InterpretationContext ec, String name) { + if (inError) { + return; + } + Object o = ec.peekObject(); + if (o != root) { + addWarn("The object on the top the of the stack is not the root logger"); + addWarn("It is: " + o); + } else { + ec.popObject(); + } + } + + public void finish(InterpretationContext ec) { + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/package.html b/logback-classic/src/main/java/ch/qos/logback/classic/joran/package.html index 93578185093ec98b865766ceeed823425b4b1c0b..26491f9d7921f30b14a1e22a0fa9f49389a7978f 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/package.html +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains Joran configuration classes.

- - + + + + + + + + + +

Contains Joran configuration classes.

+ + \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/log4j/XMLLayout.java b/logback-classic/src/main/java/ch/qos/logback/classic/log4j/XMLLayout.java index 60bcf6d450c9bcabc7ec7c3c95b3703ef36ba371..dc54c97340f736c68f24daa722a926498a8b1f60 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/log4j/XMLLayout.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/log4j/XMLLayout.java @@ -1,189 +1,189 @@ -/** - * 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.classic.log4j; - -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.IThrowableProxy; -import ch.qos.logback.classic.spi.StackTraceElementProxy; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.LayoutBase; -import ch.qos.logback.core.helpers.Transform; - -// Code is based on revision 309623 of org.apache.log4j.xml.XMLLayout dated "Wed -// Jul 31 09:25:14 2002 UTC" as authored by Ceki Gulcu. -// See also http://tinyurl.com/dch9mr - -/** - * - * Generates log4j.dtd compliant XML documents. - * - * - * @author Ceki Gülcü - */ -public class XMLLayout extends LayoutBase { - - private final int DEFAULT_SIZE = 256; - private final int UPPER_LIMIT = 2048; - - private StringBuilder buf = new StringBuilder(DEFAULT_SIZE); - private boolean locationInfo = false; - private boolean properties = false; - - @Override - public void start() { - super.start(); - } - - /** - * The LocationInfo option takes a boolean value. By default, it is - * set to false which means there will be no location information output by - * this layout. If the the option is set to true, then the file name and line - * number of the statement at the origin of the log statement will be output. - * - *

If you are embedding this layout within an {@link - * org.apache.log4j.net.SMTPAppender} then make sure to set the - * LocationInfo option of that appender as well. - */ - public void setLocationInfo(boolean flag) { - locationInfo = flag; - } - - /** - * Returns the current value of the LocationInfo option. - */ - public boolean getLocationInfo() { - return locationInfo; - } - - /** - * Sets whether MDC key-value pairs should be output, default false. - * - * @param flag - * new value. - * @since 1.2.15 - */ - public void setProperties(final boolean flag) { - properties = flag; - } - - /** - * Gets whether MDC key-value pairs should be output. - * - * @return true if MDC key-value pairs are output. - * @since 1.2.15 - */ - public boolean getProperties() { - return properties; - } - - /** - * Formats a {@link ILoggingEvent} in conformity with the log4j.dtd. - */ - public String doLayout(ILoggingEvent event) { - - // Reset working buffer. If the buffer is too large, then we need a new - // one in order to avoid the penalty of creating a large array. - if (buf.capacity() > UPPER_LIMIT) { - buf = new StringBuilder(DEFAULT_SIZE); - } else { - buf.setLength(0); - } - - // We yield to the \r\n heresy. - - buf.append("\r\n"); - - buf.append(" \r\n"); - - // logback does not support NDC - // String ndc = event.getNDC(); - - - IThrowableProxy tp = event.getThrowableProxy(); - if (tp != null) { - StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); - buf.append(" \r\n"); - } - - if (locationInfo) { - StackTraceElement[] callerDataArray = event.getCallerData(); - if (callerDataArray != null && callerDataArray.length > 0) { - StackTraceElement immediateCallerData = callerDataArray[0]; - buf.append(" \r\n"); - } - } - - /* - * - * - */ - if (this.getProperties()) { - Map propertyMap = event.getMDCPropertyMap(); - - if ((propertyMap != null) && (propertyMap.size() != 0)) { - Set> entrySet = propertyMap.entrySet(); - buf.append(" "); - for (Entry entry : entrySet) { - buf.append("\r\n "); - } - buf.append("\r\n "); - } - } - - buf.append("\r\n\r\n\r\n"); - - return buf.toString(); - } - - @Override - public String getContentType() { - return "text/xml"; - } - -} +/** + * 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.classic.log4j; + +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.LayoutBase; +import ch.qos.logback.core.helpers.Transform; + +// Code is based on revision 309623 of org.apache.log4j.xml.XMLLayout dated "Wed +// Jul 31 09:25:14 2002 UTC" as authored by Ceki Gulcu. +// See also http://tinyurl.com/dch9mr + +/** + * + * Generates log4j.dtd compliant XML documents. + * + * + * @author Ceki Gülcü + */ +public class XMLLayout extends LayoutBase { + + private final int DEFAULT_SIZE = 256; + private final int UPPER_LIMIT = 2048; + + private StringBuilder buf = new StringBuilder(DEFAULT_SIZE); + private boolean locationInfo = false; + private boolean properties = false; + + @Override + public void start() { + super.start(); + } + + /** + * The LocationInfo option takes a boolean value. By default, it is + * set to false which means there will be no location information output by + * this layout. If the the option is set to true, then the file name and line + * number of the statement at the origin of the log statement will be output. + * + *

If you are embedding this layout within an {@link + * org.apache.log4j.net.SMTPAppender} then make sure to set the + * LocationInfo option of that appender as well. + */ + public void setLocationInfo(boolean flag) { + locationInfo = flag; + } + + /** + * Returns the current value of the LocationInfo option. + */ + public boolean getLocationInfo() { + return locationInfo; + } + + /** + * Sets whether MDC key-value pairs should be output, default false. + * + * @param flag + * new value. + * @since 1.2.15 + */ + public void setProperties(final boolean flag) { + properties = flag; + } + + /** + * Gets whether MDC key-value pairs should be output. + * + * @return true if MDC key-value pairs are output. + * @since 1.2.15 + */ + public boolean getProperties() { + return properties; + } + + /** + * Formats a {@link ILoggingEvent} in conformity with the log4j.dtd. + */ + public String doLayout(ILoggingEvent event) { + + // Reset working buffer. If the buffer is too large, then we need a new + // one in order to avoid the penalty of creating a large array. + if (buf.capacity() > UPPER_LIMIT) { + buf = new StringBuilder(DEFAULT_SIZE); + } else { + buf.setLength(0); + } + + // We yield to the \r\n heresy. + + buf.append("\r\n"); + + buf.append(" \r\n"); + + // logback does not support NDC + // String ndc = event.getNDC(); + + + IThrowableProxy tp = event.getThrowableProxy(); + if (tp != null) { + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + buf.append(" \r\n"); + } + + if (locationInfo) { + StackTraceElement[] callerDataArray = event.getCallerData(); + if (callerDataArray != null && callerDataArray.length > 0) { + StackTraceElement immediateCallerData = callerDataArray[0]; + buf.append(" \r\n"); + } + } + + /* + * + * + */ + if (this.getProperties()) { + Map propertyMap = event.getMDCPropertyMap(); + + if ((propertyMap != null) && (propertyMap.size() != 0)) { + Set> entrySet = propertyMap.entrySet(); + buf.append(" "); + for (Entry entry : entrySet) { + buf.append("\r\n "); + } + buf.append("\r\n "); + } + } + + buf.append("\r\n\r\n\r\n"); + + return buf.toString(); + } + + @Override + public String getContentType() { + return "text/xml"; + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/log4j/package.html b/logback-classic/src/main/java/ch/qos/logback/classic/log4j/package.html index f1c8f94fa08cb68608824ec9954c9ab6bc5d7ee7..3538b1ead485b3d1a69ab4095c48389ac810e323 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/log4j/package.html +++ b/logback-classic/src/main/java/ch/qos/logback/classic/log4j/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains support for log4j output formats.

- - + + + + + + + + + +

Contains support for log4j output formats.

+ + \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueAppender.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueAppender.java index ff8848e28be8a68b508e6288c3a874c04e5d428b..635ce677efed47fa5b89bef3372d8184b31c0f7c 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueAppender.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueAppender.java @@ -1,214 +1,214 @@ -/** - * 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.classic.net; - -import java.io.Serializable; - -import javax.jms.ObjectMessage; -import javax.jms.Queue; -import javax.jms.QueueConnection; -import javax.jms.QueueConnectionFactory; -import javax.jms.QueueSender; -import javax.jms.QueueSession; -import javax.jms.Session; -import javax.naming.Context; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; -import ch.qos.logback.core.net.JMSAppenderBase; -import ch.qos.logback.core.spi.PreSerializationTransformer; - -/** - * A simple appender that publishes events to a JMS Queue. The events are - * serialized and transmitted as JMS message type {@link - * javax.jms.ObjectMessage}. - *

- * For more information about this appender, please refer to: - * http://logback.qos.ch/manual/appenders.html#JMSQueueAppender - * - * @author Ceki Gülcü - */ -public class JMSQueueAppender extends JMSAppenderBase { - - static int SUCCESSIVE_FAILURE_LIMIT = 3; - - String queueBindingName; - String qcfBindingName; - QueueConnection queueConnection; - QueueSession queueSession; - QueueSender queueSender; - - int successiveFailureCount = 0; - - private PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); - - public JMSQueueAppender() { - } - - /** - * The QueueConnectionFactoryBindingName option takes a string value. - * Its value will be used to lookup the appropriate - * QueueConnectionFactory from the JNDI context. - */ - public void setQueueConnectionFactoryBindingName(String qcfBindingName) { - this.qcfBindingName = qcfBindingName; - } - - /** - * Returns the value of the QueueConnectionFactoryBindingName option. - */ - public String getQueueConnectionFactoryBindingName() { - return qcfBindingName; - } - - /** - * The QueueBindingName option takes a string value. Its value will be - * used to lookup the appropriate Queue from the JNDI context. - */ - public void setQueueBindingName(String queueBindingName) { - this.queueBindingName = queueBindingName; - } - - /** - * Returns the value of the QueueBindingName option. - */ - public String getQueueBindingName() { - return queueBindingName; - } - - /** - * Options are activated and become effective only after calling this method. - */ - public void start() { - QueueConnectionFactory queueConnectionFactory; - - try { - Context jndi = buildJNDIContext(); - - // addInfo("Looking up [" + qcfBindingName + "]"); - queueConnectionFactory = (QueueConnectionFactory) lookup(jndi, - qcfBindingName); - // addInfo("About to create QueueConnection."); - if (userName != null) { - this.queueConnection = queueConnectionFactory.createQueueConnection( - userName, password); - } else { - this.queueConnection = queueConnectionFactory.createQueueConnection(); - } - - // addInfo( - // "Creating QueueSession, non-transactional, " - // + "in AUTO_ACKNOWLEDGE mode."); - this.queueSession = queueConnection.createQueueSession(false, - Session.AUTO_ACKNOWLEDGE); - - // addInfo("Looking up queue name [" + queueBindingName + "]."); - Queue queue = (Queue) lookup(jndi, queueBindingName); - - // addInfo("Creating QueueSender."); - this.queueSender = queueSession.createSender(queue); - - // addInfo("Starting QueueConnection."); - queueConnection.start(); - - jndi.close(); - } catch (Exception e) { - addError("Error while activating options for appender named [" + name - + "].", e); - } - - if (this.queueConnection != null && this.queueSession != null - && this.queueSender != null) { - super.start(); - } - } - - /** - * Close this JMSAppender. Closing releases all resources used by the - * appender. A closed appender cannot be re-opened. - */ - public synchronized void stop() { - // The synchronized modifier avoids concurrent append and close operations - if (!this.started) { - return; - } - - this.started = false; - - try { - if (queueSession != null) { - queueSession.close(); - } - if (queueConnection != null) { - queueConnection.close(); - } - } catch (Exception e) { - addError("Error while closing JMSAppender [" + name + "].", e); - } - - // Help garbage collection - queueSender = null; - queueSession = null; - queueConnection = null; - } - - /** - * This method called by {@link AppenderBase#doAppend} method to do most - * of the real appending work. - */ - public void append(ILoggingEvent event) { - if (!isStarted()) { - return; - } - - try { - ObjectMessage msg = queueSession.createObjectMessage(); - Serializable so = pst.transform(event); - msg.setObject(so); - queueSender.send(msg); - successiveFailureCount = 0; - } catch (Exception e) { - successiveFailureCount++; - if (successiveFailureCount > SUCCESSIVE_FAILURE_LIMIT) { - stop(); - } - addError("Could not send message in JMSQueueAppender [" + name + "].", e); - - } - } - - /** - * Returns the QueueConnection used for this appender. Only valid after - * start() method has been invoked. - */ - protected QueueConnection getQueueConnection() { - return queueConnection; - } - - /** - * Returns the QueueSession used for this appender. Only valid after start() - * method has been invoked. - */ - protected QueueSession getQueueSession() { - return queueSession; - } - - /** - * Returns the QueueSender used for this appender. Only valid after start() - * method has been invoked. - */ - protected QueueSender getQueueSender() { - return queueSender; - } -} +/** + * 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.classic.net; + +import java.io.Serializable; + +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.jms.QueueSender; +import javax.jms.QueueSession; +import javax.jms.Session; +import javax.naming.Context; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.net.JMSAppenderBase; +import ch.qos.logback.core.spi.PreSerializationTransformer; + +/** + * A simple appender that publishes events to a JMS Queue. The events are + * serialized and transmitted as JMS message type {@link + * javax.jms.ObjectMessage}. + *

+ * For more information about this appender, please refer to: + * http://logback.qos.ch/manual/appenders.html#JMSQueueAppender + * + * @author Ceki Gülcü + */ +public class JMSQueueAppender extends JMSAppenderBase { + + static int SUCCESSIVE_FAILURE_LIMIT = 3; + + String queueBindingName; + String qcfBindingName; + QueueConnection queueConnection; + QueueSession queueSession; + QueueSender queueSender; + + int successiveFailureCount = 0; + + private PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); + + public JMSQueueAppender() { + } + + /** + * The QueueConnectionFactoryBindingName option takes a string value. + * Its value will be used to lookup the appropriate + * QueueConnectionFactory from the JNDI context. + */ + public void setQueueConnectionFactoryBindingName(String qcfBindingName) { + this.qcfBindingName = qcfBindingName; + } + + /** + * Returns the value of the QueueConnectionFactoryBindingName option. + */ + public String getQueueConnectionFactoryBindingName() { + return qcfBindingName; + } + + /** + * The QueueBindingName option takes a string value. Its value will be + * used to lookup the appropriate Queue from the JNDI context. + */ + public void setQueueBindingName(String queueBindingName) { + this.queueBindingName = queueBindingName; + } + + /** + * Returns the value of the QueueBindingName option. + */ + public String getQueueBindingName() { + return queueBindingName; + } + + /** + * Options are activated and become effective only after calling this method. + */ + public void start() { + QueueConnectionFactory queueConnectionFactory; + + try { + Context jndi = buildJNDIContext(); + + // addInfo("Looking up [" + qcfBindingName + "]"); + queueConnectionFactory = (QueueConnectionFactory) lookup(jndi, + qcfBindingName); + // addInfo("About to create QueueConnection."); + if (userName != null) { + this.queueConnection = queueConnectionFactory.createQueueConnection( + userName, password); + } else { + this.queueConnection = queueConnectionFactory.createQueueConnection(); + } + + // addInfo( + // "Creating QueueSession, non-transactional, " + // + "in AUTO_ACKNOWLEDGE mode."); + this.queueSession = queueConnection.createQueueSession(false, + Session.AUTO_ACKNOWLEDGE); + + // addInfo("Looking up queue name [" + queueBindingName + "]."); + Queue queue = (Queue) lookup(jndi, queueBindingName); + + // addInfo("Creating QueueSender."); + this.queueSender = queueSession.createSender(queue); + + // addInfo("Starting QueueConnection."); + queueConnection.start(); + + jndi.close(); + } catch (Exception e) { + addError("Error while activating options for appender named [" + name + + "].", e); + } + + if (this.queueConnection != null && this.queueSession != null + && this.queueSender != null) { + super.start(); + } + } + + /** + * Close this JMSAppender. Closing releases all resources used by the + * appender. A closed appender cannot be re-opened. + */ + public synchronized void stop() { + // The synchronized modifier avoids concurrent append and close operations + if (!this.started) { + return; + } + + this.started = false; + + try { + if (queueSession != null) { + queueSession.close(); + } + if (queueConnection != null) { + queueConnection.close(); + } + } catch (Exception e) { + addError("Error while closing JMSAppender [" + name + "].", e); + } + + // Help garbage collection + queueSender = null; + queueSession = null; + queueConnection = null; + } + + /** + * This method called by {@link AppenderBase#doAppend} method to do most + * of the real appending work. + */ + public void append(ILoggingEvent event) { + if (!isStarted()) { + return; + } + + try { + ObjectMessage msg = queueSession.createObjectMessage(); + Serializable so = pst.transform(event); + msg.setObject(so); + queueSender.send(msg); + successiveFailureCount = 0; + } catch (Exception e) { + successiveFailureCount++; + if (successiveFailureCount > SUCCESSIVE_FAILURE_LIMIT) { + stop(); + } + addError("Could not send message in JMSQueueAppender [" + name + "].", e); + + } + } + + /** + * Returns the QueueConnection used for this appender. Only valid after + * start() method has been invoked. + */ + protected QueueConnection getQueueConnection() { + return queueConnection; + } + + /** + * Returns the QueueSession used for this appender. Only valid after start() + * method has been invoked. + */ + protected QueueSession getQueueSession() { + return queueSession; + } + + /** + * Returns the QueueSender used for this appender. Only valid after start() + * method has been invoked. + */ + protected QueueSender getQueueSender() { + return queueSender; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueSink.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueSink.java index 3e254b1fbdd8a8ce07f17800953ce6d2fa9691de..45dab04e16120dcaa62dcb3cbeb8dba704196ff2 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueSink.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueSink.java @@ -1,152 +1,152 @@ -/** - * 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.classic.net; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.util.Properties; - -import javax.jms.JMSException; -import javax.jms.MessageConsumer; -import javax.jms.ObjectMessage; -import javax.jms.Queue; -import javax.jms.QueueConnection; -import javax.jms.QueueConnectionFactory; -import javax.jms.QueueSession; -import javax.jms.Session; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NameNotFoundException; -import javax.naming.NamingException; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.util.ContextInitializer; - -/** - * A simple application that consumes logging events sent by a {@link - * JMSQueueAppender}. - * - * @author Ceki Gülcü - */ -public class JMSQueueSink implements javax.jms.MessageListener { - - private Logger logger = (Logger)LoggerFactory.getLogger(JMSTopicSink.class); - - static public void main(String[] args) throws Exception { - if (args.length < 2) { - usage("Wrong number of arguments."); - } - - String qcfBindingName = args[0]; - String queueBindingName = args[1]; - String username = null; - String password = null; - if (args.length == 4) { - username = args[2]; - password = args[3]; - } - - LoggerContext loggerContext = (LoggerContext) LoggerFactory - .getILoggerFactory(); - new ContextInitializer(loggerContext).autoConfig(); - - new JMSQueueSink(qcfBindingName, queueBindingName, username, password); - - BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); - // Loop until the word "exit" is typed - System.out.println("Type \"exit\" to quit JMSQueueSink."); - while (true) { - String s = stdin.readLine(); - if (s.equalsIgnoreCase("exit")) { - System.out.println("Exiting. Kill the application if it does not exit " - + "due to daemon threads."); - return; - } - } - } - - public JMSQueueSink(String qcfBindingName, String queueBindingName, - String username, String password) { - - try { - Properties env = new Properties(); - env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory"); - env.put(Context.PROVIDER_URL, "tcp://localhost:61616"); - Context ctx = new InitialContext(env); - QueueConnectionFactory queueConnectionFactory; - queueConnectionFactory = (QueueConnectionFactory) lookup(ctx, - qcfBindingName); - System.out.println("Queue Cnx Factory found"); - Queue queue = (Queue) ctx.lookup(queueBindingName); - System.out.println("Queue found: " + queue.getQueueName()); - - QueueConnection queueConnection = queueConnectionFactory - .createQueueConnection(username, password); - System.out.println("Queue Connection created"); - - QueueSession queueSession = queueConnection.createQueueSession(false, - Session.AUTO_ACKNOWLEDGE); - - MessageConsumer queueConsumer = queueSession.createConsumer(queue); - - queueConsumer.setMessageListener(this); - - queueConnection.start(); - System.out.println("Queue Connection started"); - - } catch (Exception e) { - logger.error("Could not read JMS message.", e); - } - } - - public void onMessage(javax.jms.Message message) { - ILoggingEvent event; - try { - if (message instanceof ObjectMessage) { - ObjectMessage objectMessage = (ObjectMessage) message; - event = (ILoggingEvent) objectMessage.getObject(); - Logger log = (Logger) LoggerFactory.getLogger(event.getLoggerName()); - log.callAppenders(event); - } else { - logger.warn("Received message is of type " + message.getJMSType() - + ", was expecting ObjectMessage."); - } - } catch (JMSException jmse) { - logger.error("Exception thrown while processing incoming message.", jmse); - } - } - - protected Object lookup(Context ctx, String name) - throws NamingException { - try { - return ctx.lookup(name); - } catch (NameNotFoundException e) { - logger.error("Could not find name [" + name + "]."); - throw e; - } - } - - static void usage(String msg) { - System.err.println(msg); - System.err - .println("Usage: java " - + JMSQueueSink.class.getName() - + " QueueConnectionFactoryBindingName QueueBindingName Username Password"); - System.exit(1); - } -} +/** + * 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.classic.net; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.Properties; + +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.jms.QueueSession; +import javax.jms.Session; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.util.ContextInitializer; + +/** + * A simple application that consumes logging events sent by a {@link + * JMSQueueAppender}. + * + * @author Ceki Gülcü + */ +public class JMSQueueSink implements javax.jms.MessageListener { + + private Logger logger = (Logger)LoggerFactory.getLogger(JMSTopicSink.class); + + static public void main(String[] args) throws Exception { + if (args.length < 2) { + usage("Wrong number of arguments."); + } + + String qcfBindingName = args[0]; + String queueBindingName = args[1]; + String username = null; + String password = null; + if (args.length == 4) { + username = args[2]; + password = args[3]; + } + + LoggerContext loggerContext = (LoggerContext) LoggerFactory + .getILoggerFactory(); + new ContextInitializer(loggerContext).autoConfig(); + + new JMSQueueSink(qcfBindingName, queueBindingName, username, password); + + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + // Loop until the word "exit" is typed + System.out.println("Type \"exit\" to quit JMSQueueSink."); + while (true) { + String s = stdin.readLine(); + if (s.equalsIgnoreCase("exit")) { + System.out.println("Exiting. Kill the application if it does not exit " + + "due to daemon threads."); + return; + } + } + } + + public JMSQueueSink(String qcfBindingName, String queueBindingName, + String username, String password) { + + try { + Properties env = new Properties(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory"); + env.put(Context.PROVIDER_URL, "tcp://localhost:61616"); + Context ctx = new InitialContext(env); + QueueConnectionFactory queueConnectionFactory; + queueConnectionFactory = (QueueConnectionFactory) lookup(ctx, + qcfBindingName); + System.out.println("Queue Cnx Factory found"); + Queue queue = (Queue) ctx.lookup(queueBindingName); + System.out.println("Queue found: " + queue.getQueueName()); + + QueueConnection queueConnection = queueConnectionFactory + .createQueueConnection(username, password); + System.out.println("Queue Connection created"); + + QueueSession queueSession = queueConnection.createQueueSession(false, + Session.AUTO_ACKNOWLEDGE); + + MessageConsumer queueConsumer = queueSession.createConsumer(queue); + + queueConsumer.setMessageListener(this); + + queueConnection.start(); + System.out.println("Queue Connection started"); + + } catch (Exception e) { + logger.error("Could not read JMS message.", e); + } + } + + public void onMessage(javax.jms.Message message) { + ILoggingEvent event; + try { + if (message instanceof ObjectMessage) { + ObjectMessage objectMessage = (ObjectMessage) message; + event = (ILoggingEvent) objectMessage.getObject(); + Logger log = (Logger) LoggerFactory.getLogger(event.getLoggerName()); + log.callAppenders(event); + } else { + logger.warn("Received message is of type " + message.getJMSType() + + ", was expecting ObjectMessage."); + } + } catch (JMSException jmse) { + logger.error("Exception thrown while processing incoming message.", jmse); + } + } + + protected Object lookup(Context ctx, String name) + throws NamingException { + try { + return ctx.lookup(name); + } catch (NameNotFoundException e) { + logger.error("Could not find name [" + name + "]."); + throw e; + } + } + + static void usage(String msg) { + System.err.println(msg); + System.err + .println("Usage: java " + + JMSQueueSink.class.getName() + + " QueueConnectionFactoryBindingName QueueBindingName Username Password"); + System.exit(1); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicAppender.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicAppender.java index 5034010c0c7a6c07df73431b634376386106dd8b..9502a417cf223b936a84cf25027eb167e21b3edf 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicAppender.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicAppender.java @@ -1,214 +1,214 @@ -/** - * 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.classic.net; - -import java.io.Serializable; - -import javax.jms.ObjectMessage; -import javax.jms.Session; -import javax.jms.Topic; -import javax.jms.TopicConnection; -import javax.jms.TopicConnectionFactory; -import javax.jms.TopicPublisher; -import javax.jms.TopicSession; -import javax.naming.Context; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; -import ch.qos.logback.core.net.JMSAppenderBase; -import ch.qos.logback.core.spi.PreSerializationTransformer; - -/** - * A simple appender that publishes events to a JMS Topic. The events are - * serialized and transmitted as JMS message type {@link - * javax.jms.ObjectMessage}. - * - * For more information about this appender, please refer to - * http://logback.qos.ch/manual/appenders.html#JMSTopicAppender - * - * @author Ceki Gülcü - */ -public class JMSTopicAppender extends JMSAppenderBase { - - static int SUCCESSIVE_FAILURE_LIMIT = 3; - - String topicBindingName; - String tcfBindingName; - TopicConnection topicConnection; - TopicSession topicSession; - TopicPublisher topicPublisher; - - int successiveFailureCount = 0; - - private PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); - - public JMSTopicAppender() { - } - - /** - * The TopicConnectionFactoryBindingName option takes a string value. - * Its value will be used to lookup the appropriate - * TopicConnectionFactory from the JNDI context. - */ - public void setTopicConnectionFactoryBindingName(String tcfBindingName) { - this.tcfBindingName = tcfBindingName; - } - - /** - * Returns the value of the TopicConnectionFactoryBindingName option. - */ - public String getTopicConnectionFactoryBindingName() { - return tcfBindingName; - } - - /** - * The TopicBindingName option takes a string value. Its value will be - * used to lookup the appropriate Topic from the JNDI context. - */ - public void setTopicBindingName(String topicBindingName) { - this.topicBindingName = topicBindingName; - } - - /** - * Returns the value of the TopicBindingName option. - */ - public String getTopicBindingName() { - return topicBindingName; - } - - /** - * Options are activated and become effective only after calling this method. - */ - public void start() { - TopicConnectionFactory topicConnectionFactory; - - try { - Context jndi = buildJNDIContext(); - - // addInfo("Looking up [" + tcfBindingName + "]"); - topicConnectionFactory = (TopicConnectionFactory) lookup(jndi, - tcfBindingName); - // addInfo("About to create TopicConnection."); - if (userName != null) { - this.topicConnection = topicConnectionFactory.createTopicConnection( - userName, password); - } else { - this.topicConnection = topicConnectionFactory.createTopicConnection(); - } - - // addInfo( - // "Creating TopicSession, non-transactional, " - // + "in AUTO_ACKNOWLEDGE mode."); - this.topicSession = topicConnection.createTopicSession(false, - Session.AUTO_ACKNOWLEDGE); - - // addInfo("Looking up topic name [" + topicBindingName + "]."); - Topic topic = (Topic) lookup(jndi, topicBindingName); - - // addInfo("Creating TopicPublisher."); - this.topicPublisher = topicSession.createPublisher(topic); - - // addInfo("Starting TopicConnection."); - topicConnection.start(); - - jndi.close(); - } catch (Exception e) { - addError("Error while activating options for appender named [" + name - + "].", e); - } - - if (this.topicConnection != null && this.topicSession != null - && this.topicPublisher != null) { - super.start(); - } - } - - /** - * Close this JMSAppender. Closing releases all resources used by the - * appender. A closed appender cannot be re-opened. - */ - public synchronized void stop() { - // The synchronized modifier avoids concurrent append and close operations - if (!this.started) { - return; - } - - this.started = false; - - try { - if (topicSession != null) { - topicSession.close(); - } - if (topicConnection != null) { - topicConnection.close(); - } - } catch (Exception e) { - addError("Error while closing JMSAppender [" + name + "].", e); - } - - // Help garbage collection - topicPublisher = null; - topicSession = null; - topicConnection = null; - } - - - /** - * This method called by {@link AppenderBase#doAppend} method to do most - * of the real appending work. - */ - public void append(ILoggingEvent event) { - if (!isStarted()) { - return; - } - - try { - ObjectMessage msg = topicSession.createObjectMessage(); - Serializable so = pst.transform(event); - msg.setObject(so); - topicPublisher.publish(msg); - successiveFailureCount = 0; - } catch (Exception e) { - successiveFailureCount++; - if (successiveFailureCount > SUCCESSIVE_FAILURE_LIMIT) { - stop(); - } - addError("Could not publish message in JMSTopicAppender [" + name + "].", e); - } - } - - /** - * Returns the TopicConnection used for this appender. Only valid after - * start() method has been invoked. - */ - protected TopicConnection getTopicConnection() { - return topicConnection; - } - - /** - * Returns the TopicSession used for this appender. Only valid after start() - * method has been invoked. - */ - protected TopicSession getTopicSession() { - return topicSession; - } - - /** - * Returns the TopicPublisher used for this appender. Only valid after start() - * method has been invoked. - */ - protected TopicPublisher getTopicPublisher() { - return topicPublisher; - } -} +/** + * 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.classic.net; + +import java.io.Serializable; + +import javax.jms.ObjectMessage; +import javax.jms.Session; +import javax.jms.Topic; +import javax.jms.TopicConnection; +import javax.jms.TopicConnectionFactory; +import javax.jms.TopicPublisher; +import javax.jms.TopicSession; +import javax.naming.Context; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.net.JMSAppenderBase; +import ch.qos.logback.core.spi.PreSerializationTransformer; + +/** + * A simple appender that publishes events to a JMS Topic. The events are + * serialized and transmitted as JMS message type {@link + * javax.jms.ObjectMessage}. + * + * For more information about this appender, please refer to + * http://logback.qos.ch/manual/appenders.html#JMSTopicAppender + * + * @author Ceki Gülcü + */ +public class JMSTopicAppender extends JMSAppenderBase { + + static int SUCCESSIVE_FAILURE_LIMIT = 3; + + String topicBindingName; + String tcfBindingName; + TopicConnection topicConnection; + TopicSession topicSession; + TopicPublisher topicPublisher; + + int successiveFailureCount = 0; + + private PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); + + public JMSTopicAppender() { + } + + /** + * The TopicConnectionFactoryBindingName option takes a string value. + * Its value will be used to lookup the appropriate + * TopicConnectionFactory from the JNDI context. + */ + public void setTopicConnectionFactoryBindingName(String tcfBindingName) { + this.tcfBindingName = tcfBindingName; + } + + /** + * Returns the value of the TopicConnectionFactoryBindingName option. + */ + public String getTopicConnectionFactoryBindingName() { + return tcfBindingName; + } + + /** + * The TopicBindingName option takes a string value. Its value will be + * used to lookup the appropriate Topic from the JNDI context. + */ + public void setTopicBindingName(String topicBindingName) { + this.topicBindingName = topicBindingName; + } + + /** + * Returns the value of the TopicBindingName option. + */ + public String getTopicBindingName() { + return topicBindingName; + } + + /** + * Options are activated and become effective only after calling this method. + */ + public void start() { + TopicConnectionFactory topicConnectionFactory; + + try { + Context jndi = buildJNDIContext(); + + // addInfo("Looking up [" + tcfBindingName + "]"); + topicConnectionFactory = (TopicConnectionFactory) lookup(jndi, + tcfBindingName); + // addInfo("About to create TopicConnection."); + if (userName != null) { + this.topicConnection = topicConnectionFactory.createTopicConnection( + userName, password); + } else { + this.topicConnection = topicConnectionFactory.createTopicConnection(); + } + + // addInfo( + // "Creating TopicSession, non-transactional, " + // + "in AUTO_ACKNOWLEDGE mode."); + this.topicSession = topicConnection.createTopicSession(false, + Session.AUTO_ACKNOWLEDGE); + + // addInfo("Looking up topic name [" + topicBindingName + "]."); + Topic topic = (Topic) lookup(jndi, topicBindingName); + + // addInfo("Creating TopicPublisher."); + this.topicPublisher = topicSession.createPublisher(topic); + + // addInfo("Starting TopicConnection."); + topicConnection.start(); + + jndi.close(); + } catch (Exception e) { + addError("Error while activating options for appender named [" + name + + "].", e); + } + + if (this.topicConnection != null && this.topicSession != null + && this.topicPublisher != null) { + super.start(); + } + } + + /** + * Close this JMSAppender. Closing releases all resources used by the + * appender. A closed appender cannot be re-opened. + */ + public synchronized void stop() { + // The synchronized modifier avoids concurrent append and close operations + if (!this.started) { + return; + } + + this.started = false; + + try { + if (topicSession != null) { + topicSession.close(); + } + if (topicConnection != null) { + topicConnection.close(); + } + } catch (Exception e) { + addError("Error while closing JMSAppender [" + name + "].", e); + } + + // Help garbage collection + topicPublisher = null; + topicSession = null; + topicConnection = null; + } + + + /** + * This method called by {@link AppenderBase#doAppend} method to do most + * of the real appending work. + */ + public void append(ILoggingEvent event) { + if (!isStarted()) { + return; + } + + try { + ObjectMessage msg = topicSession.createObjectMessage(); + Serializable so = pst.transform(event); + msg.setObject(so); + topicPublisher.publish(msg); + successiveFailureCount = 0; + } catch (Exception e) { + successiveFailureCount++; + if (successiveFailureCount > SUCCESSIVE_FAILURE_LIMIT) { + stop(); + } + addError("Could not publish message in JMSTopicAppender [" + name + "].", e); + } + } + + /** + * Returns the TopicConnection used for this appender. Only valid after + * start() method has been invoked. + */ + protected TopicConnection getTopicConnection() { + return topicConnection; + } + + /** + * Returns the TopicSession used for this appender. Only valid after start() + * method has been invoked. + */ + protected TopicSession getTopicSession() { + return topicSession; + } + + /** + * Returns the TopicPublisher used for this appender. Only valid after start() + * method has been invoked. + */ + protected TopicPublisher getTopicPublisher() { + return topicPublisher; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicSink.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicSink.java index a26972045c1afcffd6aa95fc04c1a8f54a24ef79..7cddcf0f025be8fb582f347c6b1362afd3eed8af 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicSink.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicSink.java @@ -1,152 +1,152 @@ -/** - * 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.classic.net; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.util.Properties; - -import javax.jms.JMSException; -import javax.jms.ObjectMessage; -import javax.jms.Session; -import javax.jms.Topic; -import javax.jms.TopicConnection; -import javax.jms.TopicConnectionFactory; -import javax.jms.TopicSession; -import javax.jms.TopicSubscriber; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NameNotFoundException; -import javax.naming.NamingException; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.util.ContextInitializer; - -/** - * A simple application that consumes logging events sent by a {@link - * JMSTopicAppender}. - * - * @author Ceki Gülcü - */ -public class JMSTopicSink implements javax.jms.MessageListener { - - private Logger logger = (Logger)LoggerFactory.getLogger(JMSTopicSink.class); - - static public void main(String[] args) throws Exception { - if (args.length < 2) { - usage("Wrong number of arguments."); - } - - String tcfBindingName = args[0]; - String topicBindingName = args[1]; - String username = null; - String password = null; - if (args.length == 4) { - username = args[2]; - password = args[3]; - } - - LoggerContext loggerContext = (LoggerContext) LoggerFactory - .getILoggerFactory(); - new ContextInitializer(loggerContext).autoConfig(); - - new JMSTopicSink(tcfBindingName, topicBindingName, username, password); - - BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); - // Loop until the word "exit" is typed - System.out.println("Type \"exit\" to quit JMSTopicSink."); - while (true) { - String s = stdin.readLine(); - if (s.equalsIgnoreCase("exit")) { - System.out.println("Exiting. Kill the application if it does not exit " - + "due to daemon threads."); - return; - } - } - } - - public JMSTopicSink(String tcfBindingName, String topicBindingName, - String username, String password) { - - try { - Properties env = new Properties(); - env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory"); - env.put(Context.PROVIDER_URL, "tcp://localhost:61616"); - Context ctx = new InitialContext(env); - TopicConnectionFactory topicConnectionFactory; - topicConnectionFactory = (TopicConnectionFactory) lookup(ctx, - tcfBindingName); - System.out.println("Topic Cnx Factory found"); - Topic topic = (Topic) ctx.lookup(topicBindingName); - System.out.println("Topic found: " + topic.getTopicName()); - - TopicConnection topicConnection = topicConnectionFactory - .createTopicConnection(username, password); - System.out.println("Topic Connection created"); - - TopicSession topicSession = topicConnection.createTopicSession(false, - Session.AUTO_ACKNOWLEDGE); - - TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic); - - topicSubscriber.setMessageListener(this); - - topicConnection.start(); - System.out.println("Topic Connection started"); - - } catch (Exception e) { - logger.error("Could not read JMS message.", e); - } - } - - public void onMessage(javax.jms.Message message) { - ILoggingEvent event; - try { - if (message instanceof ObjectMessage) { - ObjectMessage objectMessage = (ObjectMessage) message; - event = (ILoggingEvent) objectMessage.getObject(); - Logger log = (Logger) LoggerFactory.getLogger(event.getLoggerName()); - log.callAppenders(event); - } else { - logger.warn("Received message is of type " + message.getJMSType() - + ", was expecting ObjectMessage."); - } - } catch (JMSException jmse) { - logger.error("Exception thrown while processing incoming message.", jmse); - } - } - - protected Object lookup(Context ctx, String name) - throws NamingException { - try { - return ctx.lookup(name); - } catch (NameNotFoundException e) { - logger.error("Could not find name [" + name + "]."); - throw e; - } - } - - static void usage(String msg) { - System.err.println(msg); - System.err - .println("Usage: java " - + JMSTopicSink.class.getName() - + " TopicConnectionFactoryBindingName TopicBindingName Username Password"); - System.exit(1); - } -} +/** + * 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.classic.net; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.Properties; + +import javax.jms.JMSException; +import javax.jms.ObjectMessage; +import javax.jms.Session; +import javax.jms.Topic; +import javax.jms.TopicConnection; +import javax.jms.TopicConnectionFactory; +import javax.jms.TopicSession; +import javax.jms.TopicSubscriber; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.util.ContextInitializer; + +/** + * A simple application that consumes logging events sent by a {@link + * JMSTopicAppender}. + * + * @author Ceki Gülcü + */ +public class JMSTopicSink implements javax.jms.MessageListener { + + private Logger logger = (Logger)LoggerFactory.getLogger(JMSTopicSink.class); + + static public void main(String[] args) throws Exception { + if (args.length < 2) { + usage("Wrong number of arguments."); + } + + String tcfBindingName = args[0]; + String topicBindingName = args[1]; + String username = null; + String password = null; + if (args.length == 4) { + username = args[2]; + password = args[3]; + } + + LoggerContext loggerContext = (LoggerContext) LoggerFactory + .getILoggerFactory(); + new ContextInitializer(loggerContext).autoConfig(); + + new JMSTopicSink(tcfBindingName, topicBindingName, username, password); + + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + // Loop until the word "exit" is typed + System.out.println("Type \"exit\" to quit JMSTopicSink."); + while (true) { + String s = stdin.readLine(); + if (s.equalsIgnoreCase("exit")) { + System.out.println("Exiting. Kill the application if it does not exit " + + "due to daemon threads."); + return; + } + } + } + + public JMSTopicSink(String tcfBindingName, String topicBindingName, + String username, String password) { + + try { + Properties env = new Properties(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory"); + env.put(Context.PROVIDER_URL, "tcp://localhost:61616"); + Context ctx = new InitialContext(env); + TopicConnectionFactory topicConnectionFactory; + topicConnectionFactory = (TopicConnectionFactory) lookup(ctx, + tcfBindingName); + System.out.println("Topic Cnx Factory found"); + Topic topic = (Topic) ctx.lookup(topicBindingName); + System.out.println("Topic found: " + topic.getTopicName()); + + TopicConnection topicConnection = topicConnectionFactory + .createTopicConnection(username, password); + System.out.println("Topic Connection created"); + + TopicSession topicSession = topicConnection.createTopicSession(false, + Session.AUTO_ACKNOWLEDGE); + + TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic); + + topicSubscriber.setMessageListener(this); + + topicConnection.start(); + System.out.println("Topic Connection started"); + + } catch (Exception e) { + logger.error("Could not read JMS message.", e); + } + } + + public void onMessage(javax.jms.Message message) { + ILoggingEvent event; + try { + if (message instanceof ObjectMessage) { + ObjectMessage objectMessage = (ObjectMessage) message; + event = (ILoggingEvent) objectMessage.getObject(); + Logger log = (Logger) LoggerFactory.getLogger(event.getLoggerName()); + log.callAppenders(event); + } else { + logger.warn("Received message is of type " + message.getJMSType() + + ", was expecting ObjectMessage."); + } + } catch (JMSException jmse) { + logger.error("Exception thrown while processing incoming message.", jmse); + } + } + + protected Object lookup(Context ctx, String name) + throws NamingException { + try { + return ctx.lookup(name); + } catch (NameNotFoundException e) { + logger.error("Could not find name [" + name + "]."); + throw e; + } + } + + static void usage(String msg) { + System.err.println(msg); + System.err + .println("Usage: java " + + JMSTopicSink.class.getName() + + " TopicConnectionFactoryBindingName TopicBindingName Username Password"); + System.exit(1); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/LoggingEventPreSerializationTransformer.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/LoggingEventPreSerializationTransformer.java index da751ac33caa5aae3a20e4352ac3d761d1e04058..bf38c9328f06b93af76fb452a04d3923931f0b16 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/LoggingEventPreSerializationTransformer.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/LoggingEventPreSerializationTransformer.java @@ -1,39 +1,39 @@ -/** - * 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.classic.net; - -import java.io.Serializable; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.classic.spi.LoggingEventVO; -import ch.qos.logback.core.spi.PreSerializationTransformer; - -public class LoggingEventPreSerializationTransformer implements - PreSerializationTransformer { - - public Serializable transform(ILoggingEvent event) { - if(event == null) { - return null; - } - if (event instanceof LoggingEvent) { - return LoggingEventVO.build(event); - } else if (event instanceof LoggingEventVO) { - return (LoggingEventVO) event; - } else { - throw new IllegalArgumentException("Unsupported type "+event.getClass().getName()); - } - } - -} +/** + * 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.classic.net; + +import java.io.Serializable; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.classic.spi.LoggingEventVO; +import ch.qos.logback.core.spi.PreSerializationTransformer; + +public class LoggingEventPreSerializationTransformer implements + PreSerializationTransformer { + + public Serializable transform(ILoggingEvent event) { + if(event == null) { + return null; + } + if (event instanceof LoggingEvent) { + return LoggingEventVO.build(event); + } else if (event instanceof LoggingEventVO) { + return (LoggingEventVO) event; + } else { + throw new IllegalArgumentException("Unsupported type "+event.getClass().getName()); + } + } + +} 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 5869f06d793cb337fe438d92ed470f691ea92925..caf00365703a58b2af2b19b780720c697c58c54e 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 @@ -1,125 +1,125 @@ -/** - * 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.classic.net; - -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.boolex.OnErrorEvaluator; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.Layout; -import ch.qos.logback.core.boolex.EventEvaluator; -import ch.qos.logback.core.helpers.CyclicBuffer; -import ch.qos.logback.core.net.SMTPAppenderBase; - -/** - * Send an e-mail when a specific logging event occurs, typically on errors or - * fatal errors. - * - * For more information about this appender, please refer to the online manual at - * http://logback.qos.ch/manual/appenders.html#SMTPAppender - * - * @author Ceki Gülcü - * @author Sébastien Pennec - * - */ -public class SMTPAppender extends SMTPAppenderBase { - - // value "%logger{20} - %m" is referenced in the docs! - static final String DEFAULT_SUBJECT_PATTERN = "%logger{20} - %m"; - - private int bufferSize = 512; - protected CyclicBuffer cb = new CyclicBuffer(bufferSize); - - /** - * The default constructor will instantiate the appender with a - * {@link EventEvaluator} that will trigger on events with level - * ERROR or higher. - */ - public SMTPAppender() { - - } - - public void start() { - if (eventEvaluator == null) { - OnErrorEvaluator onError = new OnErrorEvaluator(); - onError.setContext(getContext()); - onError.setName("onError"); - onError.start(); - this.eventEvaluator = onError; - } - super.start(); - } - - /** - * Use the parameter as the {@link - * EventEvaluator} for this SMTPAppender. - */ - public SMTPAppender(EventEvaluator eventEvaluator) { - this.eventEvaluator = eventEvaluator; - } - - /** - * Perform SMTPAppender specific appending actions, mainly adding the event to - * a cyclic buffer. - */ - protected void subAppend(ILoggingEvent event) { - event.prepareForDeferredProcessing(); - cb.add(event); - // addInfo("Added event to the cyclic buffer: " + event.getMessage()); - } - - @Override - protected void fillBuffer(StringBuffer sbuf) { - int len = cb.length(); - for (int i = 0; i < len; i++) { - // sbuf.append(MimeUtility.encodeText(layout.format(cb.get()))); - ILoggingEvent event = cb.get(); - sbuf.append(layout.doLayout(event)); - } - } - - /** - * The BufferSize option takes a positive integer representing the - * maximum number of logging events to collect in a cyclic buffer. When the - * BufferSize is reached, oldest events are deleted as new - * events are added to the buffer. By default the size of the cyclic buffer is - * 512 events. - */ - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - cb.resize(bufferSize); - } - - /** - * Returns value of the BufferSize option. - */ - public int getBufferSize() { - return bufferSize; - } - - @Override - protected Layout makeSubjectLayout(String subjectStr) { - if(subjectStr == null) { - subjectStr = DEFAULT_SUBJECT_PATTERN; - } - PatternLayout pl = new PatternLayout(); - pl.setContext(getContext()); - pl.setPattern(subjectStr); - // we don't want a ThrowableInformationConverter appended - // to the end of the converter chain - // This fixes issue LBCLASSIC-67 - pl.setPostCompileProcessor(null); - pl.start(); - return pl; - } -} +/** + * 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.classic.net; + +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.boolex.OnErrorEvaluator; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.helpers.CyclicBuffer; +import ch.qos.logback.core.net.SMTPAppenderBase; + +/** + * Send an e-mail when a specific logging event occurs, typically on errors or + * fatal errors. + * + * For more information about this appender, please refer to the online manual at + * http://logback.qos.ch/manual/appenders.html#SMTPAppender + * + * @author Ceki Gülcü + * @author Sébastien Pennec + * + */ +public class SMTPAppender extends SMTPAppenderBase { + + // value "%logger{20} - %m" is referenced in the docs! + static final String DEFAULT_SUBJECT_PATTERN = "%logger{20} - %m"; + + private int bufferSize = 512; + protected CyclicBuffer cb = new CyclicBuffer(bufferSize); + + /** + * The default constructor will instantiate the appender with a + * {@link EventEvaluator} that will trigger on events with level + * ERROR or higher. + */ + public SMTPAppender() { + + } + + public void start() { + if (eventEvaluator == null) { + OnErrorEvaluator onError = new OnErrorEvaluator(); + onError.setContext(getContext()); + onError.setName("onError"); + onError.start(); + this.eventEvaluator = onError; + } + super.start(); + } + + /** + * Use the parameter as the {@link + * EventEvaluator} for this SMTPAppender. + */ + public SMTPAppender(EventEvaluator eventEvaluator) { + this.eventEvaluator = eventEvaluator; + } + + /** + * Perform SMTPAppender specific appending actions, mainly adding the event to + * a cyclic buffer. + */ + protected void subAppend(ILoggingEvent event) { + event.prepareForDeferredProcessing(); + cb.add(event); + // addInfo("Added event to the cyclic buffer: " + event.getMessage()); + } + + @Override + protected void fillBuffer(StringBuffer sbuf) { + int len = cb.length(); + for (int i = 0; i < len; i++) { + // sbuf.append(MimeUtility.encodeText(layout.format(cb.get()))); + ILoggingEvent event = cb.get(); + sbuf.append(layout.doLayout(event)); + } + } + + /** + * The BufferSize option takes a positive integer representing the + * maximum number of logging events to collect in a cyclic buffer. When the + * BufferSize is reached, oldest events are deleted as new + * events are added to the buffer. By default the size of the cyclic buffer is + * 512 events. + */ + public void setBufferSize(int bufferSize) { + this.bufferSize = bufferSize; + cb.resize(bufferSize); + } + + /** + * Returns value of the BufferSize option. + */ + public int getBufferSize() { + return bufferSize; + } + + @Override + protected Layout makeSubjectLayout(String subjectStr) { + if(subjectStr == null) { + subjectStr = DEFAULT_SUBJECT_PATTERN; + } + PatternLayout pl = new PatternLayout(); + pl.setContext(getContext()); + pl.setPattern(subjectStr); + // we don't want a ThrowableInformationConverter appended + // to the end of the converter chain + // This fixes issue LBCLASSIC-67 + pl.setPostCompileProcessor(null); + pl.start(); + return pl; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketAcceptor.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketAcceptor.java index 2075ca807f5f1e1e90fdb70d0c53284b400d97cf..6e367368d038ee9e035f1d70af771f592ce1d2af 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketAcceptor.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketAcceptor.java @@ -1,23 +1,23 @@ -/** - * 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.classic.net; - -class SocketAcceptor extends Thread { - - - @Override - public void run() { - - } -} +/** + * 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.classic.net; + +class SocketAcceptor extends Thread { + + + @Override + public void run() { + + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/SyslogAppender.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/SyslogAppender.java index f5149bc38defda6d56d6399db706a5277de0598f..7c066da3c10161d48f6f03af4ccc128b7ceb34cf 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/SyslogAppender.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/SyslogAppender.java @@ -1,99 +1,99 @@ -/** - * 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.classic.net; - -import java.io.IOException; - -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.pattern.SyslogStartConverter; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.IThrowableProxy; -import ch.qos.logback.classic.spi.StackTraceElementProxy; -import ch.qos.logback.classic.util.LevelToSyslogSeverity; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.Layout; -import ch.qos.logback.core.net.SyslogAppenderBase; -import ch.qos.logback.core.net.SyslogWriter; - -/** - * This appender can be used to send messages to a remote syslog daemon.

For - * more information about this appender, please refer to the online manual at - * http://logback.qos.ch/manual/appenders.html#SyslogAppender - * - * @author Ceki Gülcü - */ -public class SyslogAppender extends SyslogAppenderBase { - - static final public String DEFAULT_SUFFIX_PATTERN = "[%thread] %logger %msg"; - - PatternLayout prefixLayout = new PatternLayout(); - - public Layout buildLayout(String facilityStr) { - String prefixPattern = "%syslogStart{" + facilityStr + "}%nopex"; - - prefixLayout.getInstanceConverterMap().put("syslogStart", - SyslogStartConverter.class.getName()); - prefixLayout.setPattern(prefixPattern); - prefixLayout.setContext(getContext()); - prefixLayout.start(); - - PatternLayout fullLayout = new PatternLayout(); - fullLayout.getInstanceConverterMap().put("syslogStart", - SyslogStartConverter.class.getName()); - - if (suffixPattern == null) { - suffixPattern = DEFAULT_SUFFIX_PATTERN; - } - - fullLayout.setPattern(prefixPattern + suffixPattern); - fullLayout.setContext(getContext()); - fullLayout.start(); - return fullLayout; - } - - /* - * Convert a level to equivalent syslog severity. Only levels for printing - * methods i.e DEBUG, WARN, INFO and ERROR are converted. - * - * @see ch.qos.logback.core.net.SyslogAppenderBase#getSeverityForEvent(java.lang.Object) - */ - @Override - public int getSeverityForEvent(Object eventObject) { - ILoggingEvent event = (ILoggingEvent) eventObject; - return LevelToSyslogSeverity.convert(event); - } - - @Override - protected void postProcess(Object eventObject, SyslogWriter sw) { - ILoggingEvent event = (ILoggingEvent) eventObject; - - String prefix = prefixLayout.doLayout(event); - - IThrowableProxy tp = event.getThrowableProxy(); - while (tp != null) { - StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); - try { - for (StackTraceElementProxy step : stepArray) { - sw.write(prefix); - sw.write(CoreConstants.TAB); - sw.write(step.toString()); - sw.flush(); - } - } catch (IOException e) { - break; - } - tp = tp.getCause(); - } - } -} +/** + * 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.classic.net; + +import java.io.IOException; + +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.pattern.SyslogStartConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.classic.util.LevelToSyslogSeverity; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.net.SyslogAppenderBase; +import ch.qos.logback.core.net.SyslogWriter; + +/** + * This appender can be used to send messages to a remote syslog daemon.

For + * more information about this appender, please refer to the online manual at + * http://logback.qos.ch/manual/appenders.html#SyslogAppender + * + * @author Ceki Gülcü + */ +public class SyslogAppender extends SyslogAppenderBase { + + static final public String DEFAULT_SUFFIX_PATTERN = "[%thread] %logger %msg"; + + PatternLayout prefixLayout = new PatternLayout(); + + public Layout buildLayout(String facilityStr) { + String prefixPattern = "%syslogStart{" + facilityStr + "}%nopex"; + + prefixLayout.getInstanceConverterMap().put("syslogStart", + SyslogStartConverter.class.getName()); + prefixLayout.setPattern(prefixPattern); + prefixLayout.setContext(getContext()); + prefixLayout.start(); + + PatternLayout fullLayout = new PatternLayout(); + fullLayout.getInstanceConverterMap().put("syslogStart", + SyslogStartConverter.class.getName()); + + if (suffixPattern == null) { + suffixPattern = DEFAULT_SUFFIX_PATTERN; + } + + fullLayout.setPattern(prefixPattern + suffixPattern); + fullLayout.setContext(getContext()); + fullLayout.start(); + return fullLayout; + } + + /* + * Convert a level to equivalent syslog severity. Only levels for printing + * methods i.e DEBUG, WARN, INFO and ERROR are converted. + * + * @see ch.qos.logback.core.net.SyslogAppenderBase#getSeverityForEvent(java.lang.Object) + */ + @Override + public int getSeverityForEvent(Object eventObject) { + ILoggingEvent event = (ILoggingEvent) eventObject; + return LevelToSyslogSeverity.convert(event); + } + + @Override + protected void postProcess(Object eventObject, SyslogWriter sw) { + ILoggingEvent event = (ILoggingEvent) eventObject; + + String prefix = prefixLayout.doLayout(event); + + IThrowableProxy tp = event.getThrowableProxy(); + while (tp != null) { + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + try { + for (StackTraceElementProxy step : stepArray) { + sw.write(prefix); + sw.write(CoreConstants.TAB); + sw.write(step.toString()); + sw.flush(); + } + } catch (IOException e) { + break; + } + tp = tp.getCause(); + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/package.html b/logback-classic/src/main/java/ch/qos/logback/classic/net/package.html index c117b90ffc9f27ac5a88edc272f3576ea1e41d70..acf2027244f79f3124fa794cc4f3016a0db506dc 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/package.html +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/package.html @@ -1,12 +1,12 @@ - - - - - - - - - -

Contains classes used to log through a network

- + + + + + + + + + +

Contains classes used to log through a network

+ \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/package.html b/logback-classic/src/main/java/ch/qos/logback/classic/package.html index 71cc8aefae6cf6c9b9aef12f43eef667bb116702..814f44c7ec60340a0db9614df72ff43009d7b53c 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/package.html +++ b/logback-classic/src/main/java/ch/qos/logback/classic/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains logback classic main classes.

- - + + + + + + + + + +

Contains logback classic main classes.

+ + \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Abbreviator.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Abbreviator.java index b345003d8489d9605553cb9a296bbb5d9d131c29..affc5ef4e7fd88dc588222760b0ea3640c127411 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Abbreviator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Abbreviator.java @@ -1,24 +1,24 @@ -/** - * 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.classic.pattern; - -/** - * An interface used for abbreviating strings according to different policies. - * - * @author Ceki Gulcu - */ -public interface Abbreviator { - - public String abbreviate(String in); -} +/** + * 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.classic.pattern; + +/** + * An interface used for abbreviating strings according to different policies. + * + * @author Ceki Gulcu + */ +public interface Abbreviator { + + public String abbreviate(String in); +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/CallerDataConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/CallerDataConverter.java index e2ba5ce7610c25710a45e6144a54569c7ccb48da..fdccdfa0025d7052ecc582264394727c9c22f9c8 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/CallerDataConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/CallerDataConverter.java @@ -1,132 +1,132 @@ -/** - * 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.classic.pattern; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import ch.qos.logback.classic.spi.CallerData; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.boolex.EvaluationException; -import ch.qos.logback.core.boolex.EventEvaluator; -import ch.qos.logback.core.status.ErrorStatus; - -/** - * This converter outputs caller data depending on depth and marker data. - * - * @author Ceki Gulcu - */ -public class CallerDataConverter extends ClassicConverter { - - int depth = 5; - List> evaluatorList = null; - - final int MAX_ERROR_COUNT = 4; - int errorCount = 0; - - @SuppressWarnings("unchecked") - public void start() { - String depthStr = getFirstOption(); - if (depthStr == null) { - return; - } - - try { - depth = Integer.parseInt(depthStr); - } catch (NumberFormatException nfe) { - addError(""); - } - - final List optionList = getOptionList(); - - if (optionList != null && optionList.size() > 1) { - final int optionListSize = optionList.size(); - for (int i = 1; i < optionListSize; i++) { - String evaluatorStr = (String) optionList.get(i); - Context context = getContext(); - if (context != null) { - Map evaluatorMap = (Map) context - .getObject(CoreConstants.EVALUATOR_MAP); - EventEvaluator ee = (EventEvaluator) evaluatorMap - .get(evaluatorStr); - if (ee != null) { - addEvaluator(ee); - } - } - } - } - } - - private void addEvaluator(EventEvaluator ee) { - if (evaluatorList == null) { - evaluatorList = new ArrayList>(); - } - evaluatorList.add(ee); - } - - public String convert(ILoggingEvent le) { - StringBuilder buf = new StringBuilder(); - - if (evaluatorList != null) { - boolean printCallerData = false; - for (int i = 0; i < evaluatorList.size(); i++) { - EventEvaluator ee = evaluatorList.get(i); - try { - if (ee.evaluate(le)) { - printCallerData = true; - break; - } - } catch (EvaluationException eex) { - errorCount++; - if (errorCount < MAX_ERROR_COUNT) { - addError("Exception thrown for evaluator named [" + ee.getName() - + "]", eex); - } else if (errorCount == MAX_ERROR_COUNT) { - ErrorStatus errorStatus = new ErrorStatus( - "Exception thrown for evaluator named [" + ee.getName() + "].", - this, eex); - errorStatus.add(new ErrorStatus( - "This was the last warning about this evaluator's errors." - + "We don't want the StatusManager to get flooded.", this)); - addStatus(errorStatus); - } - - } - } - - if (!printCallerData) { - return CoreConstants.EMPTY_STRING; - } - } - - StackTraceElement[] cda = le.getCallerData(); - if (cda != null && cda.length > 0) { - int limit = depth < cda.length ? depth : cda.length; - - for (int i = 0; i < limit; i++) { - buf.append("Caller+"); - buf.append(i); - buf.append("\t at "); - buf.append(cda[i]); - buf.append(CoreConstants.LINE_SEPARATOR); - } - return buf.toString(); - } else { - return CallerData.CALLER_DATA_NA; - } - } -} +/** + * 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.classic.pattern; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import ch.qos.logback.classic.spi.CallerData; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.status.ErrorStatus; + +/** + * This converter outputs caller data depending on depth and marker data. + * + * @author Ceki Gulcu + */ +public class CallerDataConverter extends ClassicConverter { + + int depth = 5; + List> evaluatorList = null; + + final int MAX_ERROR_COUNT = 4; + int errorCount = 0; + + @SuppressWarnings("unchecked") + public void start() { + String depthStr = getFirstOption(); + if (depthStr == null) { + return; + } + + try { + depth = Integer.parseInt(depthStr); + } catch (NumberFormatException nfe) { + addError(""); + } + + final List optionList = getOptionList(); + + if (optionList != null && optionList.size() > 1) { + final int optionListSize = optionList.size(); + for (int i = 1; i < optionListSize; i++) { + String evaluatorStr = (String) optionList.get(i); + Context context = getContext(); + if (context != null) { + Map evaluatorMap = (Map) context + .getObject(CoreConstants.EVALUATOR_MAP); + EventEvaluator ee = (EventEvaluator) evaluatorMap + .get(evaluatorStr); + if (ee != null) { + addEvaluator(ee); + } + } + } + } + } + + private void addEvaluator(EventEvaluator ee) { + if (evaluatorList == null) { + evaluatorList = new ArrayList>(); + } + evaluatorList.add(ee); + } + + public String convert(ILoggingEvent le) { + StringBuilder buf = new StringBuilder(); + + if (evaluatorList != null) { + boolean printCallerData = false; + for (int i = 0; i < evaluatorList.size(); i++) { + EventEvaluator ee = evaluatorList.get(i); + try { + if (ee.evaluate(le)) { + printCallerData = true; + break; + } + } catch (EvaluationException eex) { + errorCount++; + if (errorCount < MAX_ERROR_COUNT) { + addError("Exception thrown for evaluator named [" + ee.getName() + + "]", eex); + } else if (errorCount == MAX_ERROR_COUNT) { + ErrorStatus errorStatus = new ErrorStatus( + "Exception thrown for evaluator named [" + ee.getName() + "].", + this, eex); + errorStatus.add(new ErrorStatus( + "This was the last warning about this evaluator's errors." + + "We don't want the StatusManager to get flooded.", this)); + addStatus(errorStatus); + } + + } + } + + if (!printCallerData) { + return CoreConstants.EMPTY_STRING; + } + } + + StackTraceElement[] cda = le.getCallerData(); + if (cda != null && cda.length > 0) { + int limit = depth < cda.length ? depth : cda.length; + + for (int i = 0; i < limit; i++) { + buf.append("Caller+"); + buf.append(i); + buf.append("\t at "); + buf.append(cda[i]); + buf.append(CoreConstants.LINE_SEPARATOR); + } + return buf.toString(); + } else { + return CallerData.CALLER_DATA_NA; + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassNameOnlyAbbreviator.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassNameOnlyAbbreviator.java index 7f761e202b8446252326ddd8396019d3d1d017d5..6546c2d26ce3e103dec59c2bf2c85d4b76187f0a 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassNameOnlyAbbreviator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassNameOnlyAbbreviator.java @@ -1,37 +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.classic.pattern; - -import ch.qos.logback.core.CoreConstants; - -/** - * This abbreviator returns the class name from a fully qualified class name, - * removing the leading package name. - * - * @author Ceki Gülcü - */ -public class ClassNameOnlyAbbreviator implements Abbreviator { - - public String abbreviate(String fqClassName) { - // we ignore the fact that the separator character can also be a dollar - // If the inner class is org.good.AClass#Inner, returning - // AClass#Inner seems most appropriate - int lastIndex = fqClassName.lastIndexOf(CoreConstants.DOT); - if (lastIndex != -1) { - return fqClassName.substring(lastIndex + 1, fqClassName.length()); - } else { - return fqClassName; - } - } -} +/** + * 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.classic.pattern; + +import ch.qos.logback.core.CoreConstants; + +/** + * This abbreviator returns the class name from a fully qualified class name, + * removing the leading package name. + * + * @author Ceki Gülcü + */ +public class ClassNameOnlyAbbreviator implements Abbreviator { + + public String abbreviate(String fqClassName) { + // we ignore the fact that the separator character can also be a dollar + // If the inner class is org.good.AClass#Inner, returning + // AClass#Inner seems most appropriate + int lastIndex = fqClassName.lastIndexOf(CoreConstants.DOT); + if (lastIndex != -1) { + return fqClassName.substring(lastIndex + 1, fqClassName.length()); + } else { + return fqClassName; + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassOfCallerConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassOfCallerConverter.java index 5c03900893c5403a4667102d51f69c9c5841751c..4adb2eb3572d028f00e9003a8da0d3a888dbe68b 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassOfCallerConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassOfCallerConverter.java @@ -1,30 +1,30 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.CallerData; -import ch.qos.logback.classic.spi.ILoggingEvent; - -public class ClassOfCallerConverter extends NamedConverter { - - protected String getFullyQualifiedName(ILoggingEvent event) { - - StackTraceElement[] cda = event.getCallerData(); - if (cda != null && cda.length > 0) { - return cda[0].getClassName(); - } else { - return CallerData.NA; - } - } -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.CallerData; +import ch.qos.logback.classic.spi.ILoggingEvent; + +public class ClassOfCallerConverter extends NamedConverter { + + protected String getFullyQualifiedName(ILoggingEvent event) { + + StackTraceElement[] cda = event.getCallerData(); + if (cda != null && cda.length > 0) { + return cda[0].getClassName(); + } else { + return CallerData.NA; + } + } +} 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 bb16999b9b80811e6ff78462cfdaeb92fc612cea..89337338b0b8687a57740268ab06eaaa013450ff 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 @@ -1,76 +1,76 @@ -/** - * 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.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; -import ch.qos.logback.core.pattern.DynamicConverter; -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}. - * - * @author Ceki Gulcu - */ -abstract public class ClassicConverter extends DynamicConverter 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); - } - -} +/** + * 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.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; +import ch.qos.logback.core.pattern.DynamicConverter; +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}. + * + * @author Ceki Gulcu + */ +abstract public class ClassicConverter extends DynamicConverter 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); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ContextNameConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ContextNameConverter.java index 29a3d293a4a330791063816944ddd59d675b8219..5a57dd85bc92e580d611b9306f59fbb06b5470b8 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ContextNameConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ContextNameConverter.java @@ -1,32 +1,32 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.ILoggingEvent; - -/** - * Converts an event to the logger context's name. - * - * @author Ceki Gülcü - */ -public class ContextNameConverter extends ClassicConverter { - - /** - * Return the name of the logger context's name. - */ - public String convert(ILoggingEvent event) { - return event.getLoggerContextVO().getName(); - } - -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +/** + * Converts an event to the logger context's name. + * + * @author Ceki Gülcü + */ +public class ContextNameConverter extends ClassicConverter { + + /** + * Return the name of the logger context's name. + */ + public String convert(ILoggingEvent event) { + return event.getLoggerContextVO().getName(); + } + +} 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 d0492ed41f58901f3bbaa866bc71d03941a7584a..84226b5cfcd2d6da8504cef745c13780bb393fd8 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 @@ -1,78 +1,78 @@ -/** - * 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.classic.pattern; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.TimeZone; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.CoreConstants; - -public class DateConverter extends ClassicConverter { - - long lastTimestamp = -1; - String timestampStrCache = null; - SimpleDateFormat simpleFormat = null; - - public void start() { - - String datePattern = getFirstOption(); - if (datePattern == null) { - datePattern = CoreConstants.ISO8601_PATTERN; - } - - if (datePattern.equals(CoreConstants.ISO8601_STR)) { - datePattern = CoreConstants.ISO8601_PATTERN; - } - - try { - simpleFormat = new SimpleDateFormat(datePattern); - // maximumCacheValidity = - // CachedDateFormat.getMaximumCacheValidity(pattern); - } catch (IllegalArgumentException e) { - addWarn("Could not instantiate SimpleDateFormat with pattern " - + datePattern, e); - // default to the ISO8601 format - simpleFormat = new SimpleDateFormat(CoreConstants.ISO8601_PATTERN); - } - - List optionList = getOptionList(); - - // if the option list contains a TZ option, then set it. - if (optionList != null && optionList.size() > 1) { - TimeZone tz = TimeZone.getTimeZone((String) optionList.get(1)); - simpleFormat.setTimeZone(tz); - } - } - - public String convert(ILoggingEvent le) { - long timestamp = le.getTimeStamp(); - - synchronized (this) { - // if called multiple times within the same millisecond - // return cache value - if (timestamp == lastTimestamp) { - return timestampStrCache; - } else { - lastTimestamp = timestamp; - // SimpleDateFormat is not thread safe. - // See also http://jira.qos.ch/browse/LBCLASSIC-36 - timestampStrCache = simpleFormat.format(new Date(timestamp)); - return timestampStrCache; - } - } - } -} +/** + * 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.classic.pattern; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.CoreConstants; + +public class DateConverter extends ClassicConverter { + + long lastTimestamp = -1; + String timestampStrCache = null; + SimpleDateFormat simpleFormat = null; + + public void start() { + + String datePattern = getFirstOption(); + if (datePattern == null) { + datePattern = CoreConstants.ISO8601_PATTERN; + } + + if (datePattern.equals(CoreConstants.ISO8601_STR)) { + datePattern = CoreConstants.ISO8601_PATTERN; + } + + try { + simpleFormat = new SimpleDateFormat(datePattern); + // maximumCacheValidity = + // CachedDateFormat.getMaximumCacheValidity(pattern); + } catch (IllegalArgumentException e) { + addWarn("Could not instantiate SimpleDateFormat with pattern " + + datePattern, e); + // default to the ISO8601 format + simpleFormat = new SimpleDateFormat(CoreConstants.ISO8601_PATTERN); + } + + List optionList = getOptionList(); + + // if the option list contains a TZ option, then set it. + if (optionList != null && optionList.size() > 1) { + TimeZone tz = TimeZone.getTimeZone((String) optionList.get(1)); + simpleFormat.setTimeZone(tz); + } + } + + public String convert(ILoggingEvent le) { + long timestamp = le.getTimeStamp(); + + synchronized (this) { + // if called multiple times within the same millisecond + // return cache value + if (timestamp == lastTimestamp) { + return timestampStrCache; + } else { + lastTimestamp = timestamp; + // SimpleDateFormat is not thread safe. + // See also http://jira.qos.ch/browse/LBCLASSIC-36 + timestampStrCache = simpleFormat.format(new Date(timestamp)); + return timestampStrCache; + } + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/EnsureExceptionHandling.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/EnsureExceptionHandling.java index c7d9068f006984bce794f94025e7e4446f37468a..99a4a586ab780156b7e4c0287f713d8a0f97c0aa 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/EnsureExceptionHandling.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/EnsureExceptionHandling.java @@ -1,69 +1,69 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.pattern.Converter; -import ch.qos.logback.core.pattern.ConverterUtil; -import ch.qos.logback.core.pattern.PostCompileProcessor; - -public class EnsureExceptionHandling implements - PostCompileProcessor { - - /** - * This implementation checks if any of the converters in the chain handles - * exceptions. If not, then this method adds a - * {@link ExtendedThrowableProxyConverter} instance to the end of the chain. - *

- * This allows appenders using this layout to output exception information - * event if the user forgets to add %ex to the pattern. Note that the - * appenders defined in the Core package are not aware of exceptions nor - * LoggingEvents. - *

- * If for some reason the user wishes to NOT print exceptions, then she can - * add %nopex to the pattern. - * - * - */ - public void process(Converter head) { - if (!chainHandlesThrowable(head)) { - Converter tail = ConverterUtil.findTail(head); - Converter exConverter = new ExtendedThrowableProxyConverter(); - if (tail == null) { - head = exConverter; - } else { - tail.setNext(exConverter); - } - } - } - - /** - * This method computes whether a chain of converters handles exceptions or - * not. - * - * @param head - * The first element of the chain - * @return true if can handle throwables contained in logging events - */ - public boolean chainHandlesThrowable(Converter head) { - Converter c = head; - while (c != null) { - if (c instanceof ThrowableHandlingConverter) { - return true; - } - c = c.getNext(); - } - return false; - } -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.pattern.Converter; +import ch.qos.logback.core.pattern.ConverterUtil; +import ch.qos.logback.core.pattern.PostCompileProcessor; + +public class EnsureExceptionHandling implements + PostCompileProcessor { + + /** + * This implementation checks if any of the converters in the chain handles + * exceptions. If not, then this method adds a + * {@link ExtendedThrowableProxyConverter} instance to the end of the chain. + *

+ * This allows appenders using this layout to output exception information + * event if the user forgets to add %ex to the pattern. Note that the + * appenders defined in the Core package are not aware of exceptions nor + * LoggingEvents. + *

+ * If for some reason the user wishes to NOT print exceptions, then she can + * add %nopex to the pattern. + * + * + */ + public void process(Converter head) { + if (!chainHandlesThrowable(head)) { + Converter tail = ConverterUtil.findTail(head); + Converter exConverter = new ExtendedThrowableProxyConverter(); + if (tail == null) { + head = exConverter; + } else { + tail.setNext(exConverter); + } + } + } + + /** + * This method computes whether a chain of converters handles exceptions or + * not. + * + * @param head + * The first element of the chain + * @return true if can handle throwables contained in logging events + */ + public boolean chainHandlesThrowable(Converter head) { + Converter c = head; + while (c != null) { + if (c instanceof ThrowableHandlingConverter) { + return true; + } + c = c.getNext(); + } + return false; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverter.java index aa7159b4f49562fcf920ce538c158ddf060af609..a7e545c5a14d3ce385d68b799b8f7e3410969349 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverter.java @@ -1,38 +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.classic.pattern; - -import ch.qos.logback.classic.spi.ClassPackagingData; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.StackTraceElementProxy; - -public class ExtendedThrowableProxyConverter extends ThrowableProxyConverter { - - @Override - protected void extraData(StringBuilder builder, StackTraceElementProxy step) { - - if (step != null) { - ClassPackagingData pi = step.getClassPackagingData(); - if (pi != null) { - builder.append(" [").append(pi.getCodeLocation()).append(':').append( - pi.getVersion()).append(']'); - } - } - } - - protected void prepareLoggingEvent(ILoggingEvent event) { - - } - -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.ClassPackagingData; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.StackTraceElementProxy; + +public class ExtendedThrowableProxyConverter extends ThrowableProxyConverter { + + @Override + protected void extraData(StringBuilder builder, StackTraceElementProxy step) { + + if (step != null) { + ClassPackagingData pi = step.getClassPackagingData(); + if (pi != null) { + builder.append(" [").append(pi.getCodeLocation()).append(':').append( + pi.getVersion()).append(']'); + } + } + } + + protected void prepareLoggingEvent(ILoggingEvent event) { + + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/FileOfCallerConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/FileOfCallerConverter.java index 460ed4578689b29e6d7fbcdc2f05f72f0e598a96..dcfa793a28b36fe0f8d1429a0eb3501982ae214c 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/FileOfCallerConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/FileOfCallerConverter.java @@ -1,30 +1,30 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.CallerData; -import ch.qos.logback.classic.spi.ILoggingEvent; - -public class FileOfCallerConverter extends ClassicConverter { - - public String convert(ILoggingEvent le) { - StackTraceElement[] cda = le.getCallerData(); - if (cda != null && cda.length > 0) { - return cda[0].getFileName(); - } else { - return CallerData.NA; - } - } - -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.CallerData; +import ch.qos.logback.classic.spi.ILoggingEvent; + +public class FileOfCallerConverter extends ClassicConverter { + + public String convert(ILoggingEvent le) { + StackTraceElement[] cda = le.getCallerData(); + if (cda != null && cda.length > 0) { + return cda[0].getFileName(); + } else { + return CallerData.NA; + } + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LRUCache.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LRUCache.java index ba1bc9fc28575da4cfaa7773c5fbd2d0746ab41f..c2b426afe9da3e7633edde683870cdaa5cb1cd3b 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LRUCache.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LRUCache.java @@ -1,51 +1,51 @@ -/** - * 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.classic.pattern; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * An lru cache based on Java's LinkedHashMap. - * - * @author Ceki Gulcu - * - * @param - * @param - */ -public class LRUCache extends LinkedHashMap { - private static final long serialVersionUID = -6592964689843698200L; - - final int cacheSize; - - public LRUCache(int cacheSize) { - super((int) (cacheSize*(4.0f/3)), 0.75f, true); - if(cacheSize < 1) { - throw new IllegalArgumentException("Cache size cannnot be smaller than 1"); - } - this.cacheSize = cacheSize; - } - - protected boolean removeEldestEntry(Map.Entry eldest) { - return (size() > cacheSize); - } - - List keyList() { - ArrayList al = new ArrayList(); - al.addAll(keySet()); - return al; - } -} +/** + * 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.classic.pattern; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * An lru cache based on Java's LinkedHashMap. + * + * @author Ceki Gulcu + * + * @param + * @param + */ +public class LRUCache extends LinkedHashMap { + private static final long serialVersionUID = -6592964689843698200L; + + final int cacheSize; + + public LRUCache(int cacheSize) { + super((int) (cacheSize*(4.0f/3)), 0.75f, true); + if(cacheSize < 1) { + throw new IllegalArgumentException("Cache size cannnot be smaller than 1"); + } + this.cacheSize = cacheSize; + } + + protected boolean removeEldestEntry(Map.Entry eldest) { + return (size() > cacheSize); + } + + List keyList() { + ArrayList al = new ArrayList(); + al.addAll(keySet()); + return al; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LevelConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LevelConverter.java index 749e39f6bee8541da537a7689c733844b7d95bca..f296cdbc7264dab083ea920332f68168cd34722d 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LevelConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LevelConverter.java @@ -1,29 +1,29 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.ILoggingEvent; - -/** - * Return the event's level. - * - * @author Ceki Gülcü - */ -public class LevelConverter extends ClassicConverter { - - public String convert(ILoggingEvent le) { - return le.getLevel().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.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +/** + * Return the event's level. + * + * @author Ceki Gülcü + */ +public class LevelConverter extends ClassicConverter { + + public String convert(ILoggingEvent le) { + return le.getLevel().toString(); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LineOfCallerConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LineOfCallerConverter.java index 258996d2d0b8539d72e7dea0511440a19cfb547a..6abb17092e6db7d770b0d0afe90f7db9b8ebd85f 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LineOfCallerConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LineOfCallerConverter.java @@ -1,30 +1,30 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.CallerData; -import ch.qos.logback.classic.spi.ILoggingEvent; - -public class LineOfCallerConverter extends ClassicConverter { - - public String convert(ILoggingEvent le) { - StackTraceElement[] cda = le.getCallerData(); - if (cda != null && cda.length > 0) { - return Integer.toString(cda[0].getLineNumber()); - } else { - return CallerData.NA; - } - } - -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.CallerData; +import ch.qos.logback.classic.spi.ILoggingEvent; + +public class LineOfCallerConverter extends ClassicConverter { + + public String convert(ILoggingEvent le) { + StackTraceElement[] cda = le.getCallerData(); + if (cda != null && cda.length > 0) { + return Integer.toString(cda[0].getLineNumber()); + } else { + return CallerData.NA; + } + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LineSeparatorConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LineSeparatorConverter.java index efcdb32a9946bc35e56bfecc42a1545acffc3caf..ad5d14ca032c4fa837d531f5d0060c5832c4d8d6 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LineSeparatorConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LineSeparatorConverter.java @@ -1,25 +1,25 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.CoreConstants; - -public class LineSeparatorConverter extends ClassicConverter { - - public String convert(ILoggingEvent event) { - return CoreConstants.LINE_SEPARATOR; - } - -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.CoreConstants; + +public class LineSeparatorConverter extends ClassicConverter { + + public String convert(ILoggingEvent event) { + return CoreConstants.LINE_SEPARATOR; + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LoggerConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LoggerConverter.java index 7f29543ec2500bd20be4ece7e8a8d04124d77396..7dad506d86d8aaa1b2837d1af9f3dd2e538af6d3 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LoggerConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/LoggerConverter.java @@ -1,23 +1,23 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.ILoggingEvent; - -public class LoggerConverter extends NamedConverter { - - protected String getFullyQualifiedName(ILoggingEvent event) { - return event.getLoggerName(); - } -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +public class LoggerConverter extends NamedConverter { + + protected String getFullyQualifiedName(ILoggingEvent event) { + return event.getLoggerName(); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MDCConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MDCConverter.java index 6c6caac3b6a06fd6f615b337cee344529fdde281..abee6bf45fd1fb5e2c54eaae71c88737d766a031 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MDCConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MDCConverter.java @@ -1,77 +1,77 @@ -/** - * 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.classic.pattern; - -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import ch.qos.logback.classic.spi.ILoggingEvent; - -public class MDCConverter extends ClassicConverter { - - String key; - private static final String EMPTY_STRING = ""; - - public MDCConverter() { - } - - @Override - public void start() { - key = getFirstOption(); - super.start(); - } - - @Override - public void stop() { - key = null; - super.stop(); - } - - @Override - public String convert(ILoggingEvent event) { - Map mdcPropertyMap = event.getMDCPropertyMap(); - - if (mdcPropertyMap == null) { - return EMPTY_STRING; - } - - if (key == null) { - // if no key is specified, return all the - // values present in the MDC, separated with a single space. - StringBuilder buf = new StringBuilder(); - Set keys = mdcPropertyMap.keySet(); - Iterator it = keys.iterator(); - String tmpKey; - String tmpValue; - while (it.hasNext()) { - tmpKey = (String)it.next(); - tmpValue = (String)mdcPropertyMap.get(tmpKey); - //format: {testeKey=testValue, testKey2=testValue2} - buf.append(tmpKey).append('=').append(tmpValue); - if (it.hasNext()) { - buf.append(", "); - } - } - return buf.toString(); - } - - String value = event.getMDCPropertyMap().get(key); - if (value != null) { - return value; - } else { - return EMPTY_STRING; - } - } -} +/** + * 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.classic.pattern; + +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +public class MDCConverter extends ClassicConverter { + + String key; + private static final String EMPTY_STRING = ""; + + public MDCConverter() { + } + + @Override + public void start() { + key = getFirstOption(); + super.start(); + } + + @Override + public void stop() { + key = null; + super.stop(); + } + + @Override + public String convert(ILoggingEvent event) { + Map mdcPropertyMap = event.getMDCPropertyMap(); + + if (mdcPropertyMap == null) { + return EMPTY_STRING; + } + + if (key == null) { + // if no key is specified, return all the + // values present in the MDC, separated with a single space. + StringBuilder buf = new StringBuilder(); + Set keys = mdcPropertyMap.keySet(); + Iterator it = keys.iterator(); + String tmpKey; + String tmpValue; + while (it.hasNext()) { + tmpKey = (String)it.next(); + tmpValue = (String)mdcPropertyMap.get(tmpKey); + //format: {testeKey=testValue, testKey2=testValue2} + buf.append(tmpKey).append('=').append(tmpValue); + if (it.hasNext()) { + buf.append(", "); + } + } + return buf.toString(); + } + + String value = event.getMDCPropertyMap().get(key); + if (value != null) { + return value; + } else { + return EMPTY_STRING; + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MarkerConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MarkerConverter.java index 1bea1d83c15480987d4a9c22a4d5135e63bb9631..caccc0ca2192c21fd18ec242c455fbd1f8803bcb 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MarkerConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MarkerConverter.java @@ -1,38 +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.classic.pattern; - -import org.slf4j.Marker; - -import ch.qos.logback.classic.spi.ILoggingEvent; - -/** - * Return the event's marker value(s). - * - * @author Sébastien Pennec - */ -public class MarkerConverter extends ClassicConverter { - - private static String EMPTY = ""; - - public String convert(ILoggingEvent le) { - Marker marker = le.getMarker(); - if (marker == null) { - return EMPTY; - } else { - return marker.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.classic.pattern; + +import org.slf4j.Marker; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +/** + * Return the event's marker value(s). + * + * @author Sébastien Pennec + */ +public class MarkerConverter extends ClassicConverter { + + private static String EMPTY = ""; + + public String convert(ILoggingEvent le) { + Marker marker = le.getMarker(); + if (marker == null) { + return EMPTY; + } else { + return marker.toString(); + } + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MessageConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MessageConverter.java index f233e08d29c71fb2e42bdaf43d28bca0e0aa7d5a..e14db4f5529a60c67e9bf5000441dde77c687710 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MessageConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MessageConverter.java @@ -1,29 +1,29 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.ILoggingEvent; - -/** - * Return the event's message. - * - * @author Ceki Gülcü - */ -public class MessageConverter extends ClassicConverter { - - public String convert(ILoggingEvent event) { - return event.getFormattedMessage(); - } - -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +/** + * Return the event's message. + * + * @author Ceki Gülcü + */ +public class MessageConverter extends ClassicConverter { + + public String convert(ILoggingEvent event) { + return event.getFormattedMessage(); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MethodOfCallerConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MethodOfCallerConverter.java index 61af5b18cec3267c29cd1c32ff5a5ff099121a3e..690259482be1f8ab39c00cfa52ff09e20734a479 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MethodOfCallerConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/MethodOfCallerConverter.java @@ -1,30 +1,30 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.CallerData; -import ch.qos.logback.classic.spi.ILoggingEvent; - -public class MethodOfCallerConverter extends ClassicConverter { - - public String convert(ILoggingEvent le) { - StackTraceElement[] cda = le.getCallerData(); - if (cda != null && cda.length > 0) { - return cda[0].getMethodName(); - } else { - return CallerData.NA; - } - } - -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.CallerData; +import ch.qos.logback.classic.spi.ILoggingEvent; + +public class MethodOfCallerConverter extends ClassicConverter { + + public String convert(ILoggingEvent le) { + StackTraceElement[] cda = le.getCallerData(); + if (cda != null && cda.length > 0) { + return cda[0].getMethodName(); + } else { + return CallerData.NA; + } + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/NamedConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/NamedConverter.java index c7429946a5c00abe6783fb209423d9ea5ee6c122..3f6646de572fadafc537c23e5f8953742f0d6f9c 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/NamedConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/NamedConverter.java @@ -1,56 +1,56 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.ILoggingEvent; - -public abstract class NamedConverter extends ClassicConverter { - - Abbreviator abbreviator = null; - - /** - * Gets fully qualified name from event. - * - * @param event - * The LoggingEvent to process, cannot not be null. - * @return name, must not be null. - */ - protected abstract String getFullyQualifiedName(final ILoggingEvent event); - - public void start() { - String optStr = getFirstOption(); - if (optStr != null) { - try { - int targetLen = Integer.parseInt(optStr); - if (targetLen == 0) { - abbreviator = new ClassNameOnlyAbbreviator(); - } else if (targetLen > 0) { - abbreviator = new TargetLengthBasedClassNameAbbreviator(targetLen); - } - } catch (NumberFormatException nfe) { - // FIXME: better error reporting - } - } - } - - public String convert(ILoggingEvent event) { - String fqn = getFullyQualifiedName(event); - - if (abbreviator == null) { - return fqn; - } else { - return abbreviator.abbreviate(fqn); - } - } -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +public abstract class NamedConverter extends ClassicConverter { + + Abbreviator abbreviator = null; + + /** + * Gets fully qualified name from event. + * + * @param event + * The LoggingEvent to process, cannot not be null. + * @return name, must not be null. + */ + protected abstract String getFullyQualifiedName(final ILoggingEvent event); + + public void start() { + String optStr = getFirstOption(); + if (optStr != null) { + try { + int targetLen = Integer.parseInt(optStr); + if (targetLen == 0) { + abbreviator = new ClassNameOnlyAbbreviator(); + } else if (targetLen > 0) { + abbreviator = new TargetLengthBasedClassNameAbbreviator(targetLen); + } + } catch (NumberFormatException nfe) { + // FIXME: better error reporting + } + } + } + + public String convert(ILoggingEvent event) { + String fqn = getFullyQualifiedName(event); + + if (abbreviator == null) { + return fqn; + } else { + return abbreviator.abbreviate(fqn); + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/NopThrowableInformationConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/NopThrowableInformationConverter.java index 3459f19a905270e8aed45c0e05a528c48e5db162..c4dd14ba85513cd9b68b1fb0f22491561c08de7e 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/NopThrowableInformationConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/NopThrowableInformationConverter.java @@ -1,43 +1,43 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.CoreConstants; - - - -/** - * Always returns an empty string. - *

- * This converter is useful to pretend that the converter chain for - * PatternLayout actually handles exceptions, when in fact it does not. - * By adding %nopex to the conversion pattern, the user can bypass - * the automatic addition of %ex conversion pattern for patterns - * which do not contain a converter handling exceptions. - * - *

Users can ignore the existence of this converter, unless they - * want to suppress the automatic printing of exceptions by - * {@link PatternLayout}. - * - * @author Ceki Gülcü - */ -public class NopThrowableInformationConverter extends ThrowableHandlingConverter { - - public String convert(ILoggingEvent event) { - return CoreConstants.EMPTY_STRING; - } - -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.CoreConstants; + + + +/** + * Always returns an empty string. + *

+ * This converter is useful to pretend that the converter chain for + * PatternLayout actually handles exceptions, when in fact it does not. + * By adding %nopex to the conversion pattern, the user can bypass + * the automatic addition of %ex conversion pattern for patterns + * which do not contain a converter handling exceptions. + * + *

Users can ignore the existence of this converter, unless they + * want to suppress the automatic printing of exceptions by + * {@link PatternLayout}. + * + * @author Ceki Gülcü + */ +public class NopThrowableInformationConverter extends ThrowableHandlingConverter { + + public String convert(ILoggingEvent event) { + return CoreConstants.EMPTY_STRING; + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/PropertyConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/PropertyConverter.java index 927d81bdd64317936ea20acfd6c96875fe8335d3..c2da073217708862b9df6b0a35578898d02da208 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/PropertyConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/PropertyConverter.java @@ -1,47 +1,47 @@ -/** - * 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.classic.pattern; - -import java.util.Map; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggerContextVO; - -public final class PropertyConverter extends ClassicConverter { - - String key; - - public void start() { - String optStr = getFirstOption(); - if (optStr != null) { - key = optStr; - super.start(); - } - } - - public String convert(ILoggingEvent event) { - if (key == null) { - return "Property_HAS_NO_KEY"; - } else { - LoggerContextVO lcvo = event.getLoggerContextVO(); - Map map = lcvo.getPropertyMap(); - String val = map.get(key); - if (val != null) { - return val; - } else { - return System.getProperty(key); - } - } - } -} +/** + * 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.classic.pattern; + +import java.util.Map; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggerContextVO; + +public final class PropertyConverter extends ClassicConverter { + + String key; + + public void start() { + String optStr = getFirstOption(); + if (optStr != null) { + key = optStr; + super.start(); + } + } + + public String convert(ILoggingEvent event) { + if (key == null) { + return "Property_HAS_NO_KEY"; + } else { + LoggerContextVO lcvo = event.getLoggerContextVO(); + Map map = lcvo.getPropertyMap(); + String val = map.get(key); + if (val != null) { + return val; + } else { + return System.getProperty(key); + } + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/RelativeTimeConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/RelativeTimeConverter.java index 1c70fe781d64717334088cfcdb40979a102698f3..9aca4301906f60712925525ac0ebf79019307702 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/RelativeTimeConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/RelativeTimeConverter.java @@ -1,35 +1,35 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.ILoggingEvent; - -public class RelativeTimeConverter extends ClassicConverter { - - long lastTimestamp = -1; - String timesmapCache = null; - - public String convert(ILoggingEvent event) { - long now = event.getTimeStamp(); - - synchronized (this) { - // update timesmapStrCache only if now != lastTimestamp - if (now != lastTimestamp) { - lastTimestamp = now; - timesmapCache = Long.toString(now - event.getLoggerContextVO().getBirthTime()); - } - return timesmapCache; - } - } -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +public class RelativeTimeConverter extends ClassicConverter { + + long lastTimestamp = -1; + String timesmapCache = null; + + public String convert(ILoggingEvent event) { + long now = event.getTimeStamp(); + + synchronized (this) { + // update timesmapStrCache only if now != lastTimestamp + if (now != lastTimestamp) { + lastTimestamp = now; + timesmapCache = Long.toString(now - event.getLoggerContextVO().getBirthTime()); + } + return timesmapCache; + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/SyslogStartConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/SyslogStartConverter.java index e70ba630fdea7a7cade0a81f4da88aff7e0e1f68..da4d44384be99dcf21a3a726322ed6b2b8843ef2 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/SyslogStartConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/SyslogStartConverter.java @@ -1,101 +1,101 @@ -/** - * 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.classic.pattern; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.text.DateFormatSymbols; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.util.LevelToSyslogSeverity; -import ch.qos.logback.core.net.SyslogAppenderBase; - -public class SyslogStartConverter extends ClassicConverter { - - long lastTimestamp = -1; - String timesmapStr = null; - SimpleDateFormat simpleFormat; - String localHostName; - int facility; - - public void start() { - int errorCount = 0; - - String facilityStr = getFirstOption(); - if (facilityStr == null) { - addError("was expecting a facility string as an option"); - return; - } - - facility = SyslogAppenderBase.facilityStringToint(facilityStr); - - localHostName = getLocalHostname(); - try { - // hours should be in 0-23, see also http://jira.qos.ch/browse/LBCLASSIC-48 - simpleFormat = new SimpleDateFormat("MMM dd HH:mm:ss", new DateFormatSymbols(Locale.US)); - } catch (IllegalArgumentException e) { - addError("Could not instantiate SimpleDateFormat", e); - errorCount++; - } - - if(errorCount == 0) { - super.start(); - } - } - - public String convert(ILoggingEvent event) { - StringBuilder sb = new StringBuilder(); - - int pri = facility + LevelToSyslogSeverity.convert(event); - - sb.append("<"); - sb.append(pri); - sb.append(">"); - sb.append(computeTimeStampString(event.getTimeStamp())); - sb.append(' '); - sb.append(localHostName); - sb.append(' '); - - return sb.toString(); - } - - /** - * This method gets the network name of the machine we are running on. - * Returns "UNKNOWN_LOCALHOST" in the unlikely case where the host name - * cannot be found. - * @return String the name of the local host - */ - public String getLocalHostname() { - try { - InetAddress addr = InetAddress.getLocalHost(); - return addr.getHostName(); - } catch (UnknownHostException uhe) { - addError("Could not determine local host name", uhe); - return "UNKNOWN_LOCALHOST"; - } - } - - String computeTimeStampString(long now) { - synchronized (this) { - if (now != lastTimestamp) { - lastTimestamp = now; - timesmapStr = simpleFormat.format(new Date(now)); - } - return timesmapStr; - } - } -} +/** + * 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.classic.pattern; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.text.DateFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.util.LevelToSyslogSeverity; +import ch.qos.logback.core.net.SyslogAppenderBase; + +public class SyslogStartConverter extends ClassicConverter { + + long lastTimestamp = -1; + String timesmapStr = null; + SimpleDateFormat simpleFormat; + String localHostName; + int facility; + + public void start() { + int errorCount = 0; + + String facilityStr = getFirstOption(); + if (facilityStr == null) { + addError("was expecting a facility string as an option"); + return; + } + + facility = SyslogAppenderBase.facilityStringToint(facilityStr); + + localHostName = getLocalHostname(); + try { + // hours should be in 0-23, see also http://jira.qos.ch/browse/LBCLASSIC-48 + simpleFormat = new SimpleDateFormat("MMM dd HH:mm:ss", new DateFormatSymbols(Locale.US)); + } catch (IllegalArgumentException e) { + addError("Could not instantiate SimpleDateFormat", e); + errorCount++; + } + + if(errorCount == 0) { + super.start(); + } + } + + public String convert(ILoggingEvent event) { + StringBuilder sb = new StringBuilder(); + + int pri = facility + LevelToSyslogSeverity.convert(event); + + sb.append("<"); + sb.append(pri); + sb.append(">"); + sb.append(computeTimeStampString(event.getTimeStamp())); + sb.append(' '); + sb.append(localHostName); + sb.append(' '); + + return sb.toString(); + } + + /** + * This method gets the network name of the machine we are running on. + * Returns "UNKNOWN_LOCALHOST" in the unlikely case where the host name + * cannot be found. + * @return String the name of the local host + */ + public String getLocalHostname() { + try { + InetAddress addr = InetAddress.getLocalHost(); + return addr.getHostName(); + } catch (UnknownHostException uhe) { + addError("Could not determine local host name", uhe); + return "UNKNOWN_LOCALHOST"; + } + } + + String computeTimeStampString(long now) { + synchronized (this) { + if (now != lastTimestamp) { + lastTimestamp = now; + timesmapStr = simpleFormat.format(new Date(now)); + } + return timesmapStr; + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviator.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviator.java index f4aac29a04aa6b7c8316998c10e3fbe24a41fa33..5c5e22feaf25a8dfce6ab70ca376cbde35d3c750 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviator.java @@ -1,128 +1,128 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.ClassicConstants; -import ch.qos.logback.core.CoreConstants; - -public class TargetLengthBasedClassNameAbbreviator implements Abbreviator { - - final int targetLength; - - public TargetLengthBasedClassNameAbbreviator(int targetLength) { - this.targetLength = targetLength; - } - - public String abbreviate(String fqClassName) { - StringBuilder buf = new StringBuilder(targetLength); - if (fqClassName == null) { - throw new IllegalArgumentException("Class name may not be null"); - } - - int inLen = fqClassName.length(); - if (inLen < targetLength) { - return fqClassName; - } - - int[] dotIndexesArray = new int[ClassicConstants.MAX_DOTS]; - // a.b.c contains 2 dots but 2+1 parts. - // see also http://jira.qos.ch/browse/LBCLASSIC-110 - int[] lengthArray = new int[ClassicConstants.MAX_DOTS + 1]; - - int dotCount = computeDotIndexes(fqClassName, dotIndexesArray); - - // System.out.println(); - // System.out.println("Dot count for [" + className + "] is " + dotCount); - // if there are not dots than abbreviation is not possible - if (dotCount == 0) { - return fqClassName; - } - // printArray("dotArray: ", dotArray); - computeLengthArray(fqClassName, dotIndexesArray, lengthArray, dotCount); - // printArray("lengthArray: ", lengthArray); - for (int i = 0; i <= dotCount; i++) { - if (i == 0) { - buf.append(fqClassName.substring(0, lengthArray[i] - 1)); - } else { - buf.append(fqClassName.substring(dotIndexesArray[i - 1], - dotIndexesArray[i - 1] + lengthArray[i])); - } - // System.out.println("i=" + i + ", buf=" + buf); - } - - return buf.toString(); - } - - static int computeDotIndexes(final String className, int[] dotArray) { - int dotCount = 0; - int k = 0; - while (true) { - // ignore the $ separator in our computations. This is both convenient - // and sensible. - k = className.indexOf(CoreConstants.DOT, k); - if (k != -1 && dotCount < ClassicConstants.MAX_DOTS) { - dotArray[dotCount] = k; - dotCount++; - k++; - } else { - break; - } - } - return dotCount; - } - - void computeLengthArray(final String className, int[] dotArray, - int[] lengthArray, int dotCount) { - int toTrim = className.length() - targetLength; - // System.out.println("toTrim=" + toTrim); - - // int toTrimAvarage = 0; - - int len; - for (int i = 0; i < dotCount; i++) { - int previousDotPosition = -1; - if (i > 0) { - previousDotPosition = dotArray[i - 1]; - } - int available = dotArray[i] - previousDotPosition - 1; - // System.out.println("i=" + i + ", available = " + available); - - len = (available < 1) ? available : 1; - // System.out.println("i=" + i + ", toTrim = " + toTrim); - - if (toTrim > 0) { - len = (available < 1) ? available : 1; - } else { - len = available; - } - toTrim -= (available - len); - lengthArray[i] = len + 1; - } - - int lastDotIndex = dotCount - 1; - lengthArray[dotCount] = className.length() - dotArray[lastDotIndex]; - } - - static void printArray(String msg, int[] ia) { - System.out.print(msg); - for (int i = 0; i < ia.length; i++) { - if (i == 0) { - System.out.print(ia[i]); - } else { - System.out.print(", " + ia[i]); - } - } - System.out.println(); - } +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.ClassicConstants; +import ch.qos.logback.core.CoreConstants; + +public class TargetLengthBasedClassNameAbbreviator implements Abbreviator { + + final int targetLength; + + public TargetLengthBasedClassNameAbbreviator(int targetLength) { + this.targetLength = targetLength; + } + + public String abbreviate(String fqClassName) { + StringBuilder buf = new StringBuilder(targetLength); + if (fqClassName == null) { + throw new IllegalArgumentException("Class name may not be null"); + } + + int inLen = fqClassName.length(); + if (inLen < targetLength) { + return fqClassName; + } + + int[] dotIndexesArray = new int[ClassicConstants.MAX_DOTS]; + // a.b.c contains 2 dots but 2+1 parts. + // see also http://jira.qos.ch/browse/LBCLASSIC-110 + int[] lengthArray = new int[ClassicConstants.MAX_DOTS + 1]; + + int dotCount = computeDotIndexes(fqClassName, dotIndexesArray); + + // System.out.println(); + // System.out.println("Dot count for [" + className + "] is " + dotCount); + // if there are not dots than abbreviation is not possible + if (dotCount == 0) { + return fqClassName; + } + // printArray("dotArray: ", dotArray); + computeLengthArray(fqClassName, dotIndexesArray, lengthArray, dotCount); + // printArray("lengthArray: ", lengthArray); + for (int i = 0; i <= dotCount; i++) { + if (i == 0) { + buf.append(fqClassName.substring(0, lengthArray[i] - 1)); + } else { + buf.append(fqClassName.substring(dotIndexesArray[i - 1], + dotIndexesArray[i - 1] + lengthArray[i])); + } + // System.out.println("i=" + i + ", buf=" + buf); + } + + return buf.toString(); + } + + static int computeDotIndexes(final String className, int[] dotArray) { + int dotCount = 0; + int k = 0; + while (true) { + // ignore the $ separator in our computations. This is both convenient + // and sensible. + k = className.indexOf(CoreConstants.DOT, k); + if (k != -1 && dotCount < ClassicConstants.MAX_DOTS) { + dotArray[dotCount] = k; + dotCount++; + k++; + } else { + break; + } + } + return dotCount; + } + + void computeLengthArray(final String className, int[] dotArray, + int[] lengthArray, int dotCount) { + int toTrim = className.length() - targetLength; + // System.out.println("toTrim=" + toTrim); + + // int toTrimAvarage = 0; + + int len; + for (int i = 0; i < dotCount; i++) { + int previousDotPosition = -1; + if (i > 0) { + previousDotPosition = dotArray[i - 1]; + } + int available = dotArray[i] - previousDotPosition - 1; + // System.out.println("i=" + i + ", available = " + available); + + len = (available < 1) ? available : 1; + // System.out.println("i=" + i + ", toTrim = " + toTrim); + + if (toTrim > 0) { + len = (available < 1) ? available : 1; + } else { + len = available; + } + toTrim -= (available - len); + lengthArray[i] = len + 1; + } + + int lastDotIndex = dotCount - 1; + lengthArray[dotCount] = className.length() - dotArray[lastDotIndex]; + } + + static void printArray(String msg, int[] ia) { + System.out.print(msg); + for (int i = 0; i < ia.length; i++) { + if (i == 0) { + System.out.print(ia[i]); + } else { + System.out.print(", " + ia[i]); + } + } + System.out.println(); + } } \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThreadConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThreadConverter.java index 6e26632dd076ee2c8f0495006919280bbc7b6a8e..0c546db25a548112d7d11ed8b9a1dd7ed65ecb3e 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThreadConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThreadConverter.java @@ -1,29 +1,29 @@ -/** - * 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.classic.pattern; - -import ch.qos.logback.classic.spi.ILoggingEvent; - -/** - * Return the events thread (usually the current thread). - * - * @author Ceki Gülcü - */ -public class ThreadConverter extends ClassicConverter { - - public String convert(ILoggingEvent event) { - return event.getThreadName(); - } - -} +/** + * 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.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +/** + * Return the events thread (usually the current thread). + * + * @author Ceki Gülcü + */ +public class ThreadConverter extends ClassicConverter { + + public String convert(ILoggingEvent event) { + return event.getThreadName(); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java index ce3e4dacb984de1eb6e443c83dc1d50ca3c01927..6e9ff40f99746d575e73c7dff50e614f75c4b16e 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java @@ -1,27 +1,27 @@ -/** - * 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.classic.pattern; - - - -/** - * Converter which handle throwables should be derived from this class. - * - */ -public abstract class ThrowableHandlingConverter extends ClassicConverter { - - boolean handlesThrowable() { - return true; - } -} +/** + * 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.classic.pattern; + + + +/** + * Converter which handle throwables should be derived from this class. + * + */ +public abstract class ThrowableHandlingConverter extends ClassicConverter { + + boolean handlesThrowable() { + return true; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java index cf2e9854632fd9894f6f42c6b7cc4b3665d73e18..2b20c857f6da32a33581aeb2119c400e3a1c2528 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java @@ -1,174 +1,174 @@ -/** - * 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.classic.pattern; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.IThrowableProxy; -import ch.qos.logback.classic.spi.StackTraceElementProxy; -import ch.qos.logback.classic.spi.ThrowableProxyUtil; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.boolex.EvaluationException; -import ch.qos.logback.core.boolex.EventEvaluator; -import ch.qos.logback.core.status.ErrorStatus; - -/** - * Add a stack trace in case the event contains a Throwable. - * - * @author Ceki Gülcü - */ -public class ThrowableProxyConverter extends ThrowableHandlingConverter { - - int lengthOption; - List> evaluatorList = null; - - final int MAX_ERROR_COUNT = 4; - int errorCount = 0; - - @SuppressWarnings("unchecked") - public void start() { - - String lengthStr = getFirstOption(); - - if (lengthStr == null) { - lengthOption = Integer.MAX_VALUE; - } else { - lengthStr = lengthStr.toLowerCase(); - if ("full".equals(lengthStr)) { - lengthOption = Integer.MAX_VALUE; - } else if ("short".equals(lengthStr)) { - lengthOption = 2; - } else { - try { - // we add one because, printing starts at offset 1 - lengthOption = Integer.parseInt(lengthStr) + 1; - } catch (NumberFormatException nfe) { - addError("Could not parser [" + lengthStr + " as an integer"); - lengthOption = Integer.MAX_VALUE; - } - } - } - - final List optionList = getOptionList(); - - if (optionList != null && optionList.size() > 1) { - final int optionListSize = optionList.size(); - for (int i = 1; i < optionListSize; i++) { - String evaluatorStr = (String) optionList.get(i); - Context context = getContext(); - Map evaluatorMap = (Map) context.getObject(CoreConstants.EVALUATOR_MAP); - EventEvaluator ee = (EventEvaluator) evaluatorMap - .get(evaluatorStr); - addEvaluator(ee); - } - } - super.start(); - } - - private void addEvaluator(EventEvaluator ee) { - if (evaluatorList == null) { - evaluatorList = new ArrayList>(); - } - evaluatorList.add(ee); - } - - public void stop() { - evaluatorList = null; - super.stop(); - } - - protected void extraData(StringBuilder builder, StackTraceElementProxy step) { - // nop - } - - public String convert(ILoggingEvent event) { - StringBuilder buf = new StringBuilder(32); - - IThrowableProxy tp = event.getThrowableProxy(); - if (tp == null) { - return CoreConstants.EMPTY_STRING; - } - - // an evaluator match will cause stack printing to be skipped - if (evaluatorList != null) { - boolean printStack = true; - for (int i = 0; i < evaluatorList.size(); i++) { - EventEvaluator ee = evaluatorList.get(i); - try { - if (ee.evaluate(event)) { - printStack = false; - break; - } - } catch (EvaluationException eex) { - errorCount++; - if (errorCount < MAX_ERROR_COUNT) { - addError("Exception thrown for evaluator named [" + ee.getName() - + "]", eex); - } else if (errorCount == MAX_ERROR_COUNT) { - ErrorStatus errorStatus = new ErrorStatus( - "Exception thrown for evaluator named [" + ee.getName() + "].", - this, eex); - errorStatus.add(new ErrorStatus( - "This was the last warning about this evaluator's errors." - + "We don't want the StatusManager to get flooded.", this)); - addStatus(errorStatus); - } - } - } - - if (!printStack) { - return CoreConstants.EMPTY_STRING; - } - } - - while (tp != null) { - printThrowableProxy(buf, tp); - tp = tp.getCause(); - } - return buf.toString(); - } - - void printThrowableProxy(StringBuilder buf, IThrowableProxy tp) { - ThrowableProxyUtil.printFirstLine(buf, tp); - buf.append(CoreConstants.LINE_SEPARATOR); - StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); - int commonFrames = tp.getCommonFrames(); - - boolean unrestrictedPrinting = lengthOption > stepArray.length; - int length = (unrestrictedPrinting) ? stepArray.length : lengthOption; - - - int maxIndex = length; - if (commonFrames > 0 && unrestrictedPrinting) { - maxIndex -= commonFrames; - } - - for (int i = 0; i < maxIndex; i++) { - String string = stepArray[i].toString(); - buf.append(CoreConstants.TAB); - buf.append(string); - extraData(buf, stepArray[i]); // allow other data to be added - buf.append(CoreConstants.LINE_SEPARATOR); - } - - if (commonFrames > 0 && unrestrictedPrinting) { - buf.append("\t... " + tp.getCommonFrames()).append( - " common frames omitted").append(CoreConstants.LINE_SEPARATOR); - } - } -} +/** + * 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.classic.pattern; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.classic.spi.ThrowableProxyUtil; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.status.ErrorStatus; + +/** + * Add a stack trace in case the event contains a Throwable. + * + * @author Ceki Gülcü + */ +public class ThrowableProxyConverter extends ThrowableHandlingConverter { + + int lengthOption; + List> evaluatorList = null; + + final int MAX_ERROR_COUNT = 4; + int errorCount = 0; + + @SuppressWarnings("unchecked") + public void start() { + + String lengthStr = getFirstOption(); + + if (lengthStr == null) { + lengthOption = Integer.MAX_VALUE; + } else { + lengthStr = lengthStr.toLowerCase(); + if ("full".equals(lengthStr)) { + lengthOption = Integer.MAX_VALUE; + } else if ("short".equals(lengthStr)) { + lengthOption = 2; + } else { + try { + // we add one because, printing starts at offset 1 + lengthOption = Integer.parseInt(lengthStr) + 1; + } catch (NumberFormatException nfe) { + addError("Could not parser [" + lengthStr + " as an integer"); + lengthOption = Integer.MAX_VALUE; + } + } + } + + final List optionList = getOptionList(); + + if (optionList != null && optionList.size() > 1) { + final int optionListSize = optionList.size(); + for (int i = 1; i < optionListSize; i++) { + String evaluatorStr = (String) optionList.get(i); + Context context = getContext(); + Map evaluatorMap = (Map) context.getObject(CoreConstants.EVALUATOR_MAP); + EventEvaluator ee = (EventEvaluator) evaluatorMap + .get(evaluatorStr); + addEvaluator(ee); + } + } + super.start(); + } + + private void addEvaluator(EventEvaluator ee) { + if (evaluatorList == null) { + evaluatorList = new ArrayList>(); + } + evaluatorList.add(ee); + } + + public void stop() { + evaluatorList = null; + super.stop(); + } + + protected void extraData(StringBuilder builder, StackTraceElementProxy step) { + // nop + } + + public String convert(ILoggingEvent event) { + StringBuilder buf = new StringBuilder(32); + + IThrowableProxy tp = event.getThrowableProxy(); + if (tp == null) { + return CoreConstants.EMPTY_STRING; + } + + // an evaluator match will cause stack printing to be skipped + if (evaluatorList != null) { + boolean printStack = true; + for (int i = 0; i < evaluatorList.size(); i++) { + EventEvaluator ee = evaluatorList.get(i); + try { + if (ee.evaluate(event)) { + printStack = false; + break; + } + } catch (EvaluationException eex) { + errorCount++; + if (errorCount < MAX_ERROR_COUNT) { + addError("Exception thrown for evaluator named [" + ee.getName() + + "]", eex); + } else if (errorCount == MAX_ERROR_COUNT) { + ErrorStatus errorStatus = new ErrorStatus( + "Exception thrown for evaluator named [" + ee.getName() + "].", + this, eex); + errorStatus.add(new ErrorStatus( + "This was the last warning about this evaluator's errors." + + "We don't want the StatusManager to get flooded.", this)); + addStatus(errorStatus); + } + } + } + + if (!printStack) { + return CoreConstants.EMPTY_STRING; + } + } + + while (tp != null) { + printThrowableProxy(buf, tp); + tp = tp.getCause(); + } + return buf.toString(); + } + + void printThrowableProxy(StringBuilder buf, IThrowableProxy tp) { + ThrowableProxyUtil.printFirstLine(buf, tp); + buf.append(CoreConstants.LINE_SEPARATOR); + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + int commonFrames = tp.getCommonFrames(); + + boolean unrestrictedPrinting = lengthOption > stepArray.length; + int length = (unrestrictedPrinting) ? stepArray.length : lengthOption; + + + int maxIndex = length; + if (commonFrames > 0 && unrestrictedPrinting) { + maxIndex -= commonFrames; + } + + for (int i = 0; i < maxIndex; i++) { + String string = stepArray[i].toString(); + buf.append(CoreConstants.TAB); + buf.append(string); + extraData(buf, stepArray[i]); // allow other data to be added + buf.append(CoreConstants.LINE_SEPARATOR); + } + + if (commonFrames > 0 && unrestrictedPrinting) { + buf.append("\t... " + tp.getCommonFrames()).append( + " common frames omitted").append(CoreConstants.LINE_SEPARATOR); + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Util.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Util.java index afb49bb60a2530997667bc5eef794524808b5c56..df3b8b0f4f478c5bc22fdf407e7a0f7e5652d4d2 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Util.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Util.java @@ -1,50 +1,50 @@ -/** - * 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.classic.pattern; - -import java.util.HashMap; -import java.util.Map; - -import org.slf4j.Marker; - -import ch.qos.logback.classic.spi.ClassPackagingData; - -/** - * - * @author Ceki Gulcu - */ -public class Util { - - static Map cache = new HashMap(); - - static public boolean match(Marker marker, Marker[] markerArray) { - if (markerArray == null) { - throw new IllegalArgumentException("markerArray should not be null"); - } - - // System.out.println("event marker="+marker); - - final int size = markerArray.length; - for (int i = 0; i < size; i++) { - // System.out.println("other:"+markerArray[i]); - - if (marker.contains(markerArray[i])) { - return true; - } - } - return false; - } - - -} +/** + * 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.classic.pattern; + +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Marker; + +import ch.qos.logback.classic.spi.ClassPackagingData; + +/** + * + * @author Ceki Gulcu + */ +public class Util { + + static Map cache = new HashMap(); + + static public boolean match(Marker marker, Marker[] markerArray) { + if (markerArray == null) { + throw new IllegalArgumentException("markerArray should not be null"); + } + + // System.out.println("event marker="+marker); + + final int size = markerArray.length; + for (int i = 0; i < size; i++) { + // System.out.println("other:"+markerArray[i]); + + if (marker.contains(markerArray[i])) { + return true; + } + } + return false; + } + + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/package.html b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/package.html index de3614cbbe629d846d519d4a769b274f78eb9756..5e4898f941f7b16f49aadc822f2f45730b4cc757 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/package.html +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Provides classes implementing format specifiers in conversion patterns.

- - + + + + + + + + + +

Provides classes implementing format specifiers in conversion patterns.

+ + \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextJNDISelector.java b/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextJNDISelector.java index e0df12d6ae6a8b87f9ad44fc45e73dde00550980..546074e43b2cc8f50dda2d8cbb24bce0d557dbee 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextJNDISelector.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextJNDISelector.java @@ -1,202 +1,202 @@ -/** - * 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.classic.selector; - -import static ch.qos.logback.classic.ClassicConstants.JNDI_CONFIGURATION_RESOURCE; -import static ch.qos.logback.classic.ClassicConstants.JNDI_CONTEXT_NAME; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.naming.Context; -import javax.naming.NamingException; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.util.ContextInitializer; -import ch.qos.logback.classic.util.JNDIUtil; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.status.InfoStatus; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.status.WarnStatus; -import ch.qos.logback.core.util.Loader; -import ch.qos.logback.core.util.StatusPrinter; - -/** - * A class that allows the LoggerFactory to access an environment-based - * LoggerContext. - * - * To add in catalina.sh - * - * JAVA_OPTS="$JAVA_OPTS "-Dlogback.ContextSelector=JNDI"" - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class ContextJNDISelector implements ContextSelector { - - private final Map synchronizedContextMap; - private final LoggerContext defaultContext; - - private static final ThreadLocal threadLocal = new ThreadLocal(); - - public ContextJNDISelector(LoggerContext context) { - synchronizedContextMap = Collections - .synchronizedMap(new HashMap()); - defaultContext = context; - } - - public LoggerContext getDefaultLoggerContext() { - return defaultContext; - } - - public LoggerContext detachLoggerContext(String loggerContextName) { - return synchronizedContextMap.remove(loggerContextName); - } - - public LoggerContext getLoggerContext() { - String contextName = null; - Context ctx = null; - - // First check if ThreadLocal has been set already - LoggerContext lc = threadLocal.get(); - if (lc != null) { - return lc; - } - - try { - // We first try to find the name of our - // environment's LoggerContext - ctx = JNDIUtil.getInitialContext(); - contextName = (String) JNDIUtil.lookup(ctx, JNDI_CONTEXT_NAME); - } catch (NamingException ne) { - // We can't log here - } - - if (contextName == null) { - // We return the default context - return defaultContext; - } else { - // Let's see if we already know such a context - LoggerContext loggerContext = synchronizedContextMap.get(contextName); - - if (loggerContext == null) { - // We have to create a new LoggerContext - loggerContext = new LoggerContext(); - loggerContext.setName(contextName); - synchronizedContextMap.put(contextName, loggerContext); - URL url = findConfigFileURL(ctx, loggerContext); - if (url != null) { - configureLoggerContextByURL(loggerContext, url); - } else { - try { - new ContextInitializer(loggerContext).autoConfig(); - } catch (JoranException je) { - } - } - StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); - } - return loggerContext; - } - } - - private String conventionalConfigFileName(String contextName) { - return "logback-" + contextName + ".xml"; - } - - private URL findConfigFileURL(Context ctx, LoggerContext loggerContext) { - StatusManager sm = loggerContext.getStatusManager(); - - String jndiEntryForConfigResource = JNDIUtil.lookup(ctx, - JNDI_CONFIGURATION_RESOURCE); - // Do we have a dedicated configuration file? - if (jndiEntryForConfigResource != null) { - sm.add(new InfoStatus("Searching for [" + jndiEntryForConfigResource - + "]", this)); - URL url = urlByResourceName(sm, jndiEntryForConfigResource); - if (url == null) { - String msg = "The jndi resource [" + jndiEntryForConfigResource - + "] for context [" + loggerContext.getName() - + "] does not lead to a valid file"; - sm.add(new WarnStatus(msg, this)); - } - return url; - } else { - String resourceByConvention = conventionalConfigFileName(loggerContext - .getName()); - return urlByResourceName(sm, resourceByConvention); - } - } - - private URL urlByResourceName(StatusManager sm, String resourceName) { - sm.add(new InfoStatus("Searching for [" + resourceName + "]", - this)); - URL url = Loader.getResource(resourceName, Loader.getTCL()); - if (url != null) { - return url; - } - return Loader.getResourceBySelfClassLoader(resourceName); - } - - private void configureLoggerContextByURL(LoggerContext context, URL url) { - try { - JoranConfigurator configurator = new JoranConfigurator(); - context.reset(); - configurator.setContext(context); - configurator.doConfigure(url); - } catch (JoranException e) { - } - StatusPrinter.printInCaseOfErrorsOrWarnings(context); - } - - public List getContextNames() { - List list = new ArrayList(); - list.addAll(synchronizedContextMap.keySet()); - return list; - } - - public LoggerContext getLoggerContext(String name) { - return synchronizedContextMap.get(name); - } - - /** - * Returns the number of managed contexts Used for testing purposes - * - * @return the number of managed contexts - */ - public int getCount() { - return synchronizedContextMap.size(); - } - - /** - * These methods are used by the LoggerContextFilter. - * - * They provide a way to tell the selector which context to use, thus saving - * the cost of a JNDI call at each new request. - * - * @param context - */ - public void setLocalContext(LoggerContext context) { - threadLocal.set(context); - } - - public void removeLocalContext() { - threadLocal.remove(); - } - -} +/** + * 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.classic.selector; + +import static ch.qos.logback.classic.ClassicConstants.JNDI_CONFIGURATION_RESOURCE; +import static ch.qos.logback.classic.ClassicConstants.JNDI_CONTEXT_NAME; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.naming.Context; +import javax.naming.NamingException; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.util.ContextInitializer; +import ch.qos.logback.classic.util.JNDIUtil; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.WarnStatus; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.StatusPrinter; + +/** + * A class that allows the LoggerFactory to access an environment-based + * LoggerContext. + * + * To add in catalina.sh + * + * JAVA_OPTS="$JAVA_OPTS "-Dlogback.ContextSelector=JNDI"" + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class ContextJNDISelector implements ContextSelector { + + private final Map synchronizedContextMap; + private final LoggerContext defaultContext; + + private static final ThreadLocal threadLocal = new ThreadLocal(); + + public ContextJNDISelector(LoggerContext context) { + synchronizedContextMap = Collections + .synchronizedMap(new HashMap()); + defaultContext = context; + } + + public LoggerContext getDefaultLoggerContext() { + return defaultContext; + } + + public LoggerContext detachLoggerContext(String loggerContextName) { + return synchronizedContextMap.remove(loggerContextName); + } + + public LoggerContext getLoggerContext() { + String contextName = null; + Context ctx = null; + + // First check if ThreadLocal has been set already + LoggerContext lc = threadLocal.get(); + if (lc != null) { + return lc; + } + + try { + // We first try to find the name of our + // environment's LoggerContext + ctx = JNDIUtil.getInitialContext(); + contextName = (String) JNDIUtil.lookup(ctx, JNDI_CONTEXT_NAME); + } catch (NamingException ne) { + // We can't log here + } + + if (contextName == null) { + // We return the default context + return defaultContext; + } else { + // Let's see if we already know such a context + LoggerContext loggerContext = synchronizedContextMap.get(contextName); + + if (loggerContext == null) { + // We have to create a new LoggerContext + loggerContext = new LoggerContext(); + loggerContext.setName(contextName); + synchronizedContextMap.put(contextName, loggerContext); + URL url = findConfigFileURL(ctx, loggerContext); + if (url != null) { + configureLoggerContextByURL(loggerContext, url); + } else { + try { + new ContextInitializer(loggerContext).autoConfig(); + } catch (JoranException je) { + } + } + StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); + } + return loggerContext; + } + } + + private String conventionalConfigFileName(String contextName) { + return "logback-" + contextName + ".xml"; + } + + private URL findConfigFileURL(Context ctx, LoggerContext loggerContext) { + StatusManager sm = loggerContext.getStatusManager(); + + String jndiEntryForConfigResource = JNDIUtil.lookup(ctx, + JNDI_CONFIGURATION_RESOURCE); + // Do we have a dedicated configuration file? + if (jndiEntryForConfigResource != null) { + sm.add(new InfoStatus("Searching for [" + jndiEntryForConfigResource + + "]", this)); + URL url = urlByResourceName(sm, jndiEntryForConfigResource); + if (url == null) { + String msg = "The jndi resource [" + jndiEntryForConfigResource + + "] for context [" + loggerContext.getName() + + "] does not lead to a valid file"; + sm.add(new WarnStatus(msg, this)); + } + return url; + } else { + String resourceByConvention = conventionalConfigFileName(loggerContext + .getName()); + return urlByResourceName(sm, resourceByConvention); + } + } + + private URL urlByResourceName(StatusManager sm, String resourceName) { + sm.add(new InfoStatus("Searching for [" + resourceName + "]", + this)); + URL url = Loader.getResource(resourceName, Loader.getTCL()); + if (url != null) { + return url; + } + return Loader.getResourceBySelfClassLoader(resourceName); + } + + private void configureLoggerContextByURL(LoggerContext context, URL url) { + try { + JoranConfigurator configurator = new JoranConfigurator(); + context.reset(); + configurator.setContext(context); + configurator.doConfigure(url); + } catch (JoranException e) { + } + StatusPrinter.printInCaseOfErrorsOrWarnings(context); + } + + public List getContextNames() { + List list = new ArrayList(); + list.addAll(synchronizedContextMap.keySet()); + return list; + } + + public LoggerContext getLoggerContext(String name) { + return synchronizedContextMap.get(name); + } + + /** + * Returns the number of managed contexts Used for testing purposes + * + * @return the number of managed contexts + */ + public int getCount() { + return synchronizedContextMap.size(); + } + + /** + * These methods are used by the LoggerContextFilter. + * + * They provide a way to tell the selector which context to use, thus saving + * the cost of a JNDI call at each new request. + * + * @param context + */ + public void setLocalContext(LoggerContext context) { + threadLocal.set(context); + } + + public void removeLocalContext() { + threadLocal.remove(); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextSelector.java b/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextSelector.java index 8978a00020907342296d1b777067bb8b04e6a831..5c004239d1f2a2919bcee53ad7d92f5422d6043a 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextSelector.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextSelector.java @@ -1,40 +1,40 @@ -/** - * 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.classic.selector; - -import java.util.List; - -import ch.qos.logback.classic.LoggerContext; - -/** - * An interface that provides access to different contexts. - * - * It is used by the LoggerFactory to access the context - * it will use to retrieve loggers. - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public interface ContextSelector { - - public LoggerContext getLoggerContext(); - - public LoggerContext getLoggerContext(String name); - - public LoggerContext getDefaultLoggerContext(); - - public LoggerContext detachLoggerContext(String loggerContextName); - - public List getContextNames(); -} +/** + * 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.classic.selector; + +import java.util.List; + +import ch.qos.logback.classic.LoggerContext; + +/** + * An interface that provides access to different contexts. + * + * It is used by the LoggerFactory to access the context + * it will use to retrieve loggers. + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public interface ContextSelector { + + public LoggerContext getLoggerContext(); + + public LoggerContext getLoggerContext(String name); + + public LoggerContext getDefaultLoggerContext(); + + public LoggerContext detachLoggerContext(String loggerContextName); + + public List getContextNames(); +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/selector/DefaultContextSelector.java b/logback-classic/src/main/java/ch/qos/logback/classic/selector/DefaultContextSelector.java index bc525dcc1219a7cfada17c6ce91038058bc0985e..9f698edffbbe56256dbc5054ddbecd4b32af9966 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/selector/DefaultContextSelector.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/selector/DefaultContextSelector.java @@ -1,52 +1,52 @@ -/** - * 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.classic.selector; - -import java.util.Arrays; -import java.util.List; - -import ch.qos.logback.classic.LoggerContext; - -public class DefaultContextSelector implements ContextSelector { - - private LoggerContext context; - - public DefaultContextSelector(LoggerContext context) { - this.context = context; - } - - public LoggerContext getLoggerContext() { - return getDefaultLoggerContext(); - } - - public LoggerContext getDefaultLoggerContext() { - return context; - } - - public LoggerContext detachLoggerContext(String loggerContextName) { - return context; - } - - public List getContextNames() { - return Arrays.asList(context.getName()); - } - - public LoggerContext getLoggerContext(String name) { - if (context.getName().equals(name)) { - return context; - } else { - return null; - } - } -} +/** + * 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.classic.selector; + +import java.util.Arrays; +import java.util.List; + +import ch.qos.logback.classic.LoggerContext; + +public class DefaultContextSelector implements ContextSelector { + + private LoggerContext context; + + public DefaultContextSelector(LoggerContext context) { + this.context = context; + } + + public LoggerContext getLoggerContext() { + return getDefaultLoggerContext(); + } + + public LoggerContext getDefaultLoggerContext() { + return context; + } + + public LoggerContext detachLoggerContext(String loggerContextName) { + return context; + } + + public List getContextNames() { + return Arrays.asList(context.getName()); + } + + public LoggerContext getLoggerContext(String name) { + if (context.getName().equals(name)) { + return context; + } else { + return null; + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/ContextDetachingSCL.java b/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/ContextDetachingSCL.java index 6409d7c29c8b3c08bbb5eebf3489d2de2ca50410..fdfc23ba03415e1f8471d9902a78de4d2229f769 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/ContextDetachingSCL.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/ContextDetachingSCL.java @@ -1,61 +1,61 @@ -/** - * 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.classic.selector.servlet; - -import static ch.qos.logback.classic.ClassicConstants.JNDI_CONTEXT_NAME; - -import javax.naming.Context; -import javax.naming.NamingException; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; - -import org.slf4j.Logger; -import org.slf4j.impl.StaticLoggerBinder; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.selector.ContextSelector; -import ch.qos.logback.classic.util.JNDIUtil; - -public class ContextDetachingSCL implements ServletContextListener { - - public void contextDestroyed(ServletContextEvent servletContextEvent) { - String loggerContextName = null; - - try { - Context ctx = JNDIUtil.getInitialContext(); - loggerContextName = (String) JNDIUtil.lookup(ctx, JNDI_CONTEXT_NAME); - } catch (NamingException ne) { - } - - if (loggerContextName != null) { - System.out.println("About to detach context named " + loggerContextName); - - ContextSelector selector = StaticLoggerBinder.getSingleton().getContextSelector(); - LoggerContext context = selector.detachLoggerContext(loggerContextName); - if (context != null) { - Logger logger = context.getLogger(Logger.ROOT_LOGGER_NAME); - logger.warn("Stopping logger context " + loggerContextName); - // when the web-app is destroyed, its logger context should be stopped - context.stop(); - } else { - System.out.println("No context named " + loggerContextName + " was found."); - } - } - } - - public void contextInitialized(ServletContextEvent arg0) { - // do nothing - } - -} +/** + * 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.classic.selector.servlet; + +import static ch.qos.logback.classic.ClassicConstants.JNDI_CONTEXT_NAME; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.slf4j.Logger; +import org.slf4j.impl.StaticLoggerBinder; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.selector.ContextSelector; +import ch.qos.logback.classic.util.JNDIUtil; + +public class ContextDetachingSCL implements ServletContextListener { + + public void contextDestroyed(ServletContextEvent servletContextEvent) { + String loggerContextName = null; + + try { + Context ctx = JNDIUtil.getInitialContext(); + loggerContextName = (String) JNDIUtil.lookup(ctx, JNDI_CONTEXT_NAME); + } catch (NamingException ne) { + } + + if (loggerContextName != null) { + System.out.println("About to detach context named " + loggerContextName); + + ContextSelector selector = StaticLoggerBinder.getSingleton().getContextSelector(); + LoggerContext context = selector.detachLoggerContext(loggerContextName); + if (context != null) { + Logger logger = context.getLogger(Logger.ROOT_LOGGER_NAME); + logger.warn("Stopping logger context " + loggerContextName); + // when the web-app is destroyed, its logger context should be stopped + context.stop(); + } else { + System.out.println("No context named " + loggerContextName + " was found."); + } + } + } + + public void contextInitialized(ServletContextEvent arg0) { + // do nothing + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/LoggerContextFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/LoggerContextFilter.java index f85d1dd32e1ee2c4aa6f259049560a5273c69f10..e9e7af661a31929385656f669842ed574addc255 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/LoggerContextFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/LoggerContextFilter.java @@ -1,83 +1,83 @@ -/** - * 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.classic.selector.servlet; - -import java.io.IOException; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; - -import org.slf4j.LoggerFactory; -import org.slf4j.impl.StaticLoggerBinder; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.selector.ContextJNDISelector; -import ch.qos.logback.classic.selector.ContextSelector; - -/** - * A servlet filter that puts the environment-dependend - * LoggerContext in a Threadlocal variable. - * - * It removes it after the request is processed. - * - * To use it, add the following lines to a web.xml file - * - * - * LoggerContextFilter - * - * ch.qos.userApp.LoggerContextFilter - * - * - * - * LoggerContextFilter - * /* - * - * - * @author Sébastien Pennec - */ -public class LoggerContextFilter implements Filter { - - public void destroy() { - //do nothing - } - - public void doFilter(ServletRequest request, ServletResponse response, - FilterChain chain) throws IOException, ServletException { - - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - ContextSelector selector = StaticLoggerBinder.getSingleton().getContextSelector(); - ContextJNDISelector sel = null; - - if (selector instanceof ContextJNDISelector) { - sel = (ContextJNDISelector)selector; - sel.setLocalContext(lc); - } - - try { - chain.doFilter(request, response); - } finally { - if (sel != null) { - sel.removeLocalContext(); - } - } - } - - public void init(FilterConfig arg0) throws ServletException { - //do nothing - } -} +/** + * 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.classic.selector.servlet; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +import org.slf4j.LoggerFactory; +import org.slf4j.impl.StaticLoggerBinder; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.selector.ContextJNDISelector; +import ch.qos.logback.classic.selector.ContextSelector; + +/** + * A servlet filter that puts the environment-dependend + * LoggerContext in a Threadlocal variable. + * + * It removes it after the request is processed. + * + * To use it, add the following lines to a web.xml file + * + * + * LoggerContextFilter + * + * ch.qos.userApp.LoggerContextFilter + * + * + * + * LoggerContextFilter + * /* + * + * + * @author Sébastien Pennec + */ +public class LoggerContextFilter implements Filter { + + public void destroy() { + //do nothing + } + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + ContextSelector selector = StaticLoggerBinder.getSingleton().getContextSelector(); + ContextJNDISelector sel = null; + + if (selector instanceof ContextJNDISelector) { + sel = (ContextJNDISelector)selector; + sel.setLocalContext(lc); + } + + try { + chain.doFilter(request, response); + } finally { + if (sel != null) { + sel.removeLocalContext(); + } + } + } + + public void init(FilterConfig arg0) throws ServletException { + //do nothing + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java b/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java index 0614ab161130aaf142383e76adba380a16272a90..d7f7501519fef10f5dcf89d12f9933584980d2df 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java @@ -1,36 +1,36 @@ -/** - * 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.classic.sift; - -import java.util.List; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.sift.AppenderFactoryBase; -import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase; - -public class AppenderFactory extends AppenderFactoryBase{ - - String key; - - AppenderFactory(List eventList, String key) { - super(eventList); - this.key = key; - } - - public SiftingJoranConfiguratorBase getSiftingJoranConfigurator(String discriminatingValue) { - return new SiftingJoranConfigurator(key, discriminatingValue); - } - -} +/** + * 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.classic.sift; + +import java.util.List; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.sift.AppenderFactoryBase; +import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase; + +public class AppenderFactory extends AppenderFactoryBase{ + + String key; + + AppenderFactory(List eventList, String key) { + super(eventList); + this.key = key; + } + + public SiftingJoranConfiguratorBase getSiftingJoranConfigurator(String discriminatingValue) { + return new SiftingJoranConfigurator(key, discriminatingValue); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/sift/ContextBasedDiscriminator.java b/logback-classic/src/main/java/ch/qos/logback/classic/sift/ContextBasedDiscriminator.java index 4b1278103307e06000bd0eeb3d46a3327bd4f63d..03e6205bb962911a861abd6dc62c3fe5cbbc4bfb 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/sift/ContextBasedDiscriminator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/sift/ContextBasedDiscriminator.java @@ -1,89 +1,89 @@ -/** - * 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.classic.sift; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.sift.Discriminator; -import ch.qos.logback.core.spi.ContextAwareBase; - -/** - * This discriminator essentially returns the value mapped to an MDC key. If the - * said value is null, then a default value is returned. - * - *

Both Key and the DefaultValue are user specified properties. - * - * @author Ceki Gülcü - * - */ -public class ContextBasedDiscriminator extends ContextAwareBase implements - Discriminator { - - private static final String KEY = "contextName"; - private String defaultValue; - private boolean started = false; - - public ContextBasedDiscriminator() { - } - - /** - * Return the name of the current context name as found in the logging event. - */ - public String getDiscriminatingValue(ILoggingEvent event) { - String contextName = event.getLoggerContextVO().getName(); - - if (contextName == null) { - return defaultValue; - } else { - return contextName; - } - } - - public boolean isStarted() { - return started; - } - - public void start() { - started = true; - } - - public void stop() { - started = false; - } - - public String getKey() { - return KEY; - } - - public void setKey(String key) { - throw new UnsupportedOperationException("Key cannot be set. Using fixed key "+KEY); - } - - /** - * @see #setDefaultValue(String) - * @return - */ - public String getDefaultValue() { - return defaultValue; - } - - /** - * The default context name in case the context name is not set for the - * current logging event. - * - * @param defaultValue - */ - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } -} +/** + * 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.classic.sift; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.sift.Discriminator; +import ch.qos.logback.core.spi.ContextAwareBase; + +/** + * This discriminator essentially returns the value mapped to an MDC key. If the + * said value is null, then a default value is returned. + * + *

Both Key and the DefaultValue are user specified properties. + * + * @author Ceki Gülcü + * + */ +public class ContextBasedDiscriminator extends ContextAwareBase implements + Discriminator { + + private static final String KEY = "contextName"; + private String defaultValue; + private boolean started = false; + + public ContextBasedDiscriminator() { + } + + /** + * Return the name of the current context name as found in the logging event. + */ + public String getDiscriminatingValue(ILoggingEvent event) { + String contextName = event.getLoggerContextVO().getName(); + + if (contextName == null) { + return defaultValue; + } else { + return contextName; + } + } + + public boolean isStarted() { + return started; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + + public String getKey() { + return KEY; + } + + public void setKey(String key) { + throw new UnsupportedOperationException("Key cannot be set. Using fixed key "+KEY); + } + + /** + * @see #setDefaultValue(String) + * @return + */ + public String getDefaultValue() { + return defaultValue; + } + + /** + * The default context name in case the context name is not set for the + * current logging event. + * + * @param defaultValue + */ + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java b/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java index adef825f1a3dc4e03a9a1d88f65ce00aadf6320a..3e840b7f809e8f5afd8b90d4cbadeb7a03843f50 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java @@ -1,108 +1,108 @@ -/** - * 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.classic.sift; - -import org.slf4j.MDC; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.sift.Discriminator; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.util.OptionHelper; - -/** - * MDCBasedDiscriminator essentially returns the value mapped to an MDC key. If - * the said value is null, then a default value is returned. - * - *

Both Key and the DefaultValue are user specified properties. - * - * @author Ceki Gülcü - * - */ -public class MDCBasedDiscriminator extends ContextAwareBase implements - Discriminator { - - private String key; - private String defaultValue; - private boolean started = false; - - public MDCBasedDiscriminator() { - } - - /** - * Return the value associated with an MDC entry designated by the Key - * property. If that value is null, then return the value assigned to the - * DefaultValue property. - */ - public String getDiscriminatingValue(ILoggingEvent event) { - String mdcValue = MDC.get(key); - if (mdcValue == null) { - return defaultValue; - } else { - return mdcValue; - } - } - - public boolean isStarted() { - return started; - } - - public void start() { - int errors = 0; - if (OptionHelper.isEmpty(key)) { - errors++; - addError("The \"Key\" property must be set"); - } - if (OptionHelper.isEmpty(defaultValue)) { - errors++; - addError("The \"DefaultValue\" property must be set"); - } - if (errors == 0) { - started = true; - } - } - - public void stop() { - started = false; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - /** - * @see #setDefaultValue(String) - * @return - */ - public String getDefaultValue() { - return defaultValue; - } - - /** - * The default MDC value in case the MDC is not set for - * {@link #setKey(String) mdcKey}. - * - *

For example, if {@link #setKey(String) Key} is set to the value - * "someKey", and the MDC is not set for "someKey", then this appender will - * use the default value, which you can set with the help of this method. - * - * @param defaultValue - */ - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } -} +/** + * 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.classic.sift; + +import org.slf4j.MDC; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.sift.Discriminator; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.util.OptionHelper; + +/** + * MDCBasedDiscriminator essentially returns the value mapped to an MDC key. If + * the said value is null, then a default value is returned. + * + *

Both Key and the DefaultValue are user specified properties. + * + * @author Ceki Gülcü + * + */ +public class MDCBasedDiscriminator extends ContextAwareBase implements + Discriminator { + + private String key; + private String defaultValue; + private boolean started = false; + + public MDCBasedDiscriminator() { + } + + /** + * Return the value associated with an MDC entry designated by the Key + * property. If that value is null, then return the value assigned to the + * DefaultValue property. + */ + public String getDiscriminatingValue(ILoggingEvent event) { + String mdcValue = MDC.get(key); + if (mdcValue == null) { + return defaultValue; + } else { + return mdcValue; + } + } + + public boolean isStarted() { + return started; + } + + public void start() { + int errors = 0; + if (OptionHelper.isEmpty(key)) { + errors++; + addError("The \"Key\" property must be set"); + } + if (OptionHelper.isEmpty(defaultValue)) { + errors++; + addError("The \"DefaultValue\" property must be set"); + } + if (errors == 0) { + started = true; + } + } + + public void stop() { + started = false; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + /** + * @see #setDefaultValue(String) + * @return + */ + public String getDefaultValue() { + return defaultValue; + } + + /** + * The default MDC value in case the MDC is not set for + * {@link #setKey(String) mdcKey}. + * + *

For example, if {@link #setKey(String) Key} is set to the value + * "someKey", and the MDC is not set for "someKey", then this appender will + * use the default value, which you can set with the help of this method. + * + * @param defaultValue + */ + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftAction.java index d631c6f901df0dde1ec5f797258c91b7740a87e0..0a32964a62526981f3cb472ad7fa5f10f3ad4999 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftAction.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftAction.java @@ -1,57 +1,57 @@ -/** - * 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.classic.sift; - -import java.util.ArrayList; -import java.util.List; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.event.InPlayListener; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; - -public class SiftAction extends Action implements InPlayListener { - List seList; - - @Override - public void begin(InterpretationContext ec, String name, Attributes attributes) - throws ActionException { - seList = new ArrayList(); - ec.addInPlayListener(this); - } - - @Override - public void end(InterpretationContext ec, String name) throws ActionException { - ec.removeInPlayListener(this); - Object o = ec.peekObject(); - if (o instanceof SiftingAppender) { - SiftingAppender sa = (SiftingAppender) o; - AppenderFactory appenderFactory = new AppenderFactory(seList, sa - .getDiscriminatorKey()); - sa.setAppenderFactory(appenderFactory); - } - } - - public void inPlay(SaxEvent event) { - seList.add(event); - } - - public List getSeList() { - return seList; - } - -} +/** + * 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.classic.sift; + +import java.util.ArrayList; +import java.util.List; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.event.InPlayListener; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; + +public class SiftAction extends Action implements InPlayListener { + List seList; + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + seList = new ArrayList(); + ec.addInPlayListener(this); + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + ec.removeInPlayListener(this); + Object o = ec.peekObject(); + if (o instanceof SiftingAppender) { + SiftingAppender sa = (SiftingAppender) o; + AppenderFactory appenderFactory = new AppenderFactory(seList, sa + .getDiscriminatorKey()); + sa.setAppenderFactory(appenderFactory); + } + } + + public void inPlay(SaxEvent event) { + seList.add(event); + } + + public List getSeList() { + return seList; + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java b/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java index a9d1cbdd6281162a5819e2ca40d1d41246917a17..52451463587c0ada47eff45bb6693faea4b8177f 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java @@ -1,50 +1,50 @@ -/** - * 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.classic.sift; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.joran.spi.DefaultClass; -import ch.qos.logback.core.sift.AppenderTracker; -import ch.qos.logback.core.sift.Discriminator; -import ch.qos.logback.core.sift.SiftingAppenderBase; - -/** - * This appender can contains other appenders which it can build dynamically - * depending on MDC values. The built appender is specified as part of a - * configuration file. - * - *

See the logback manual for further details. - * - * - * @author Ceki Gulcu - */ -public class SiftingAppender extends SiftingAppenderBase { - - AppenderTracker getAppenderTracker() { - return appenderTracker; - } - - @Override - protected long getTimestamp(ILoggingEvent event) { - return event.getTimeStamp(); - } - - - @Override - @DefaultClass(MDCBasedDiscriminator.class) - public void setDiscriminator(Discriminator discriminator) { - super.setDiscriminator(discriminator); - } - -} +/** + * 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.classic.sift; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.joran.spi.DefaultClass; +import ch.qos.logback.core.sift.AppenderTracker; +import ch.qos.logback.core.sift.Discriminator; +import ch.qos.logback.core.sift.SiftingAppenderBase; + +/** + * This appender can contains other appenders which it can build dynamically + * depending on MDC values. The built appender is specified as part of a + * configuration file. + * + *

See the logback manual for further details. + * + * + * @author Ceki Gulcu + */ +public class SiftingAppender extends SiftingAppenderBase { + + AppenderTracker getAppenderTracker() { + return appenderTracker; + } + + @Override + protected long getTimestamp(ILoggingEvent event) { + return event.getTimeStamp(); + } + + + @Override + @DefaultClass(MDCBasedDiscriminator.class) + public void setDiscriminator(Discriminator discriminator) { + super.setDiscriminator(discriminator); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingJoranConfigurator.java b/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingJoranConfigurator.java index 1dff09cc62fbc239f6d44e8970a77f1559fb4d0b..66309cb4caeadae313b310e37f3f1c9f605abe85 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingJoranConfigurator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingJoranConfigurator.java @@ -1,75 +1,75 @@ -/** - * 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.classic.sift; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.util.DefaultNestedComponentRules; -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.joran.action.ActionConst; -import ch.qos.logback.core.joran.action.AppenderAction; -import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.joran.spi.RuleStore; -import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase; - -public class SiftingJoranConfigurator extends SiftingJoranConfiguratorBase { - - String key; - String value; - - SiftingJoranConfigurator(String key, String value) { - this.key = key; - this.value = value; - } - - @Override - protected Pattern initialPattern() { - return new Pattern("configuration"); - } - - @Override - protected void addInstanceRules(RuleStore rs) { - rs.addRule(new Pattern("configuration/appender"), new AppenderAction()); - } - - - @Override - protected void addDefaultNestedComponentRegistryRules( - DefaultNestedComponentRegistry registry) { - DefaultNestedComponentRules.addDefaultNestedComponentRegistryRules(registry); - } - - @Override - protected void buildInterpreter() { - super.buildInterpreter(); - Map omap = interpreter.getInterpretationContext().getObjectMap(); - omap.put(ActionConst.APPENDER_BAG, new HashMap()); - omap.put(ActionConst.FILTER_CHAIN_BAG, new HashMap()); - Map propertiesMap = new HashMap(); - propertiesMap.put(key, value); - interpreter.setInterpretationContextPropertiesMap(propertiesMap); - } - - @SuppressWarnings("unchecked") - public Appender getAppender() { - Map omap = interpreter.getInterpretationContext().getObjectMap(); - HashMap map = (HashMap) omap.get(ActionConst.APPENDER_BAG); - Collection values = map.values(); - return (Appender) values.iterator().next(); - } -} +/** + * 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.classic.sift; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.util.DefaultNestedComponentRules; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.joran.action.ActionConst; +import ch.qos.logback.core.joran.action.AppenderAction; +import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.joran.spi.RuleStore; +import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase; + +public class SiftingJoranConfigurator extends SiftingJoranConfiguratorBase { + + String key; + String value; + + SiftingJoranConfigurator(String key, String value) { + this.key = key; + this.value = value; + } + + @Override + protected Pattern initialPattern() { + return new Pattern("configuration"); + } + + @Override + protected void addInstanceRules(RuleStore rs) { + rs.addRule(new Pattern("configuration/appender"), new AppenderAction()); + } + + + @Override + protected void addDefaultNestedComponentRegistryRules( + DefaultNestedComponentRegistry registry) { + DefaultNestedComponentRules.addDefaultNestedComponentRegistryRules(registry); + } + + @Override + protected void buildInterpreter() { + super.buildInterpreter(); + Map omap = interpreter.getInterpretationContext().getObjectMap(); + omap.put(ActionConst.APPENDER_BAG, new HashMap()); + omap.put(ActionConst.FILTER_CHAIN_BAG, new HashMap()); + Map propertiesMap = new HashMap(); + propertiesMap.put(key, value); + interpreter.setInterpretationContextPropertiesMap(propertiesMap); + } + + @SuppressWarnings("unchecked") + public Appender getAppender() { + Map omap = interpreter.getInterpretationContext().getObjectMap(); + HashMap map = (HashMap) omap.get(ActionConst.APPENDER_BAG); + Collection values = map.values(); + return (Appender) values.iterator().next(); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/CallerData.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/CallerData.java index 316223d8f8e396267e1f3a265acb44b336556176..2c8a58f1009d557a1ec2f4dd4397fe2acb6ba2a4 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/CallerData.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/CallerData.java @@ -1,104 +1,104 @@ -/** - * 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.classic.spi; - -import ch.qos.logback.core.CoreConstants; - -/** - * This class computes caller data returning the result in the form - * of a StackTraceElement array. - * - * @author Ceki Gülcü - */ -public class CallerData { - - - /** - * When caller information is not available this constant is used for file - * name, method name, etc. - */ - public static final String NA = "?"; - - // All logger call's in log4j-over-slf4j use the Category class - private static final String LOG4J_CATEGORY = "org.apache.log4j.Category"; - - /** - * When caller information is not available this constant is used for the line - * number. - */ - public static final int LINE_NA = -1; - - public static String CALLER_DATA_NA = "?#?:?" + CoreConstants.LINE_SEPARATOR; - - /** - * This value is returned in case no caller data could be extracted. - */ - public static StackTraceElement[] EMPTY_CALLER_DATA_ARRAY = new StackTraceElement[0]; - - - /** - * Extract caller data information as an array based on a Throwable passed as - * parameter - */ - public static StackTraceElement[] extract(Throwable t, - String fqnOfInvokingClass, final int maxDepth) { - if (t == null) { - return null; - } - - StackTraceElement[] steArray = t.getStackTrace(); - StackTraceElement[] callerDataArray; - - int found = LINE_NA; - for (int i = 0; i < steArray.length; i++) { - if (isDirectlyInvokingClass(steArray[i].getClassName(), - fqnOfInvokingClass)) { - // the caller is assumed to be the next stack frame, hence the +1. - found = i + 1; - } else { - if (found != LINE_NA) { - break; - } - } - } - - // we failed to extract caller data - if (found == LINE_NA) { - return EMPTY_CALLER_DATA_ARRAY; - } - - int availableDepth = steArray.length - found; - int desiredDepth = maxDepth < (availableDepth) ? maxDepth : availableDepth; - - callerDataArray = new StackTraceElement[desiredDepth]; - for (int i = 0; i < desiredDepth; i++) { - callerDataArray[i] = steArray[found + i]; - } - return callerDataArray; - } - - public static boolean isDirectlyInvokingClass(String currentClass, - String fqnOfInvokingClass) { - // the check for org.apachje.log4j.Category class is intended to support - // log4j-over-slf4j - // it solves http://bugzilla.slf4j.org/show_bug.cgi?id=66 - if (currentClass.equals(fqnOfInvokingClass) - || currentClass.equals(LOG4J_CATEGORY)) { - return true; - } else { - return false; - } - } - -} +/** + * 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.classic.spi; + +import ch.qos.logback.core.CoreConstants; + +/** + * This class computes caller data returning the result in the form + * of a StackTraceElement array. + * + * @author Ceki Gülcü + */ +public class CallerData { + + + /** + * When caller information is not available this constant is used for file + * name, method name, etc. + */ + public static final String NA = "?"; + + // All logger call's in log4j-over-slf4j use the Category class + private static final String LOG4J_CATEGORY = "org.apache.log4j.Category"; + + /** + * When caller information is not available this constant is used for the line + * number. + */ + public static final int LINE_NA = -1; + + public static String CALLER_DATA_NA = "?#?:?" + CoreConstants.LINE_SEPARATOR; + + /** + * This value is returned in case no caller data could be extracted. + */ + public static StackTraceElement[] EMPTY_CALLER_DATA_ARRAY = new StackTraceElement[0]; + + + /** + * Extract caller data information as an array based on a Throwable passed as + * parameter + */ + public static StackTraceElement[] extract(Throwable t, + String fqnOfInvokingClass, final int maxDepth) { + if (t == null) { + return null; + } + + StackTraceElement[] steArray = t.getStackTrace(); + StackTraceElement[] callerDataArray; + + int found = LINE_NA; + for (int i = 0; i < steArray.length; i++) { + if (isDirectlyInvokingClass(steArray[i].getClassName(), + fqnOfInvokingClass)) { + // the caller is assumed to be the next stack frame, hence the +1. + found = i + 1; + } else { + if (found != LINE_NA) { + break; + } + } + } + + // we failed to extract caller data + if (found == LINE_NA) { + return EMPTY_CALLER_DATA_ARRAY; + } + + int availableDepth = steArray.length - found; + int desiredDepth = maxDepth < (availableDepth) ? maxDepth : availableDepth; + + callerDataArray = new StackTraceElement[desiredDepth]; + for (int i = 0; i < desiredDepth; i++) { + callerDataArray[i] = steArray[found + i]; + } + return callerDataArray; + } + + public static boolean isDirectlyInvokingClass(String currentClass, + String fqnOfInvokingClass) { + // the check for org.apachje.log4j.Category class is intended to support + // log4j-over-slf4j + // it solves http://bugzilla.slf4j.org/show_bug.cgi?id=66 + if (currentClass.equals(fqnOfInvokingClass) + || currentClass.equals(LOG4J_CATEGORY)) { + return true; + } else { + return false; + } + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/ClassPackagingData.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/ClassPackagingData.java index 2a8a73b789cd6c365e4d351720d62fe4cb23a272..50704c18464396c2fd6e56618c529959700cbb46 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/ClassPackagingData.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/ClassPackagingData.java @@ -1,81 +1,81 @@ -/** - * 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.classic.spi; - -import java.io.Serializable; - -public class ClassPackagingData implements Serializable { - - private static final long serialVersionUID = -804643281218337001L; - final String codeLocation; - final String version; - private final boolean exact; - - public ClassPackagingData(String codeLocation, String version) { - this.codeLocation = codeLocation; - this.version = version; - this.exact = true; - } - - public ClassPackagingData(String classLocation, String version, boolean exact) { - this.codeLocation = classLocation; - this.version = version; - this.exact = exact; - } - - public String getCodeLocation() { - return codeLocation; - } - - public String getVersion() { - return version; - } - - public boolean isExact() { - return exact; - } - - @Override - public int hashCode() { - final int PRIME = 31; - int result = 1; - result = PRIME * result + ((codeLocation == null) ? 0 : codeLocation.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final ClassPackagingData other = (ClassPackagingData) obj; - if (codeLocation == null) { - if (other.codeLocation != null) - return false; - } else if (!codeLocation.equals(other.codeLocation)) - return false; - if (exact != other.exact) - return false; - if (version == null) { - if (other.version != null) - return false; - } else if (!version.equals(other.version)) - return false; - return true; - } - -} +/** + * 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.classic.spi; + +import java.io.Serializable; + +public class ClassPackagingData implements Serializable { + + private static final long serialVersionUID = -804643281218337001L; + final String codeLocation; + final String version; + private final boolean exact; + + public ClassPackagingData(String codeLocation, String version) { + this.codeLocation = codeLocation; + this.version = version; + this.exact = true; + } + + public ClassPackagingData(String classLocation, String version, boolean exact) { + this.codeLocation = classLocation; + this.version = version; + this.exact = exact; + } + + public String getCodeLocation() { + return codeLocation; + } + + public String getVersion() { + return version; + } + + public boolean isExact() { + return exact; + } + + @Override + public int hashCode() { + final int PRIME = 31; + int result = 1; + result = PRIME * result + ((codeLocation == null) ? 0 : codeLocation.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final ClassPackagingData other = (ClassPackagingData) obj; + if (codeLocation == null) { + if (other.codeLocation != null) + return false; + } else if (!codeLocation.equals(other.codeLocation)) + return false; + if (exact != other.exact) + return false; + if (version == null) { + if (other.version != null) + return false; + } else if (!version.equals(other.version)) + return false; + return true; + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/ILoggingEvent.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/ILoggingEvent.java index 16b659c3d3a39931b69449fd2ee9d0de77c41ba1..f2a0b0c4a9b638709db42facc00951582b46bdaa 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/ILoggingEvent.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/ILoggingEvent.java @@ -1,77 +1,77 @@ -/** - * 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.classic.spi; - -import java.util.Map; - -import org.slf4j.Marker; - -import ch.qos.logback.classic.Level; - -/** - * The central interface in logback-classic. In a nutshell, logback-classic is - * nothing more than a processing chain built around this interface. - * - * @author Ceki Gülcü - * @since 0.9.16 - */ -public interface ILoggingEvent { - - public String getThreadName(); - - public Level getLevel(); - - public String getMessage(); - - public Object[] getArgumentArray(); - - public String getFormattedMessage(); - - public String getLoggerName(); - - public LoggerContextVO getLoggerContextVO(); - - public IThrowableProxy getThrowableProxy(); - - /** - * Return caller data associated with this event. Note that calling this event - * may trigger the computation of caller data. - * - * @return the caller data associated with this event. - * - * @see #hasCallerData() - */ - public StackTraceElement[] getCallerData(); - - /** - * If this event has caller data, then true is returned. Otherwise the - * returned value is null. - * - *

Logback components wishing to use caller data if available without - * causing it to be computed can invoke this method before invoking - * {@link #getCallerData()}. - * - * @return whether this event has caller data - */ - public boolean hasCallerData(); - - public Marker getMarker(); - - public Map getMDCPropertyMap(); - - public long getTimeStamp(); - - public void prepareForDeferredProcessing(); - -} +/** + * 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.classic.spi; + +import java.util.Map; + +import org.slf4j.Marker; + +import ch.qos.logback.classic.Level; + +/** + * The central interface in logback-classic. In a nutshell, logback-classic is + * nothing more than a processing chain built around this interface. + * + * @author Ceki Gülcü + * @since 0.9.16 + */ +public interface ILoggingEvent { + + public String getThreadName(); + + public Level getLevel(); + + public String getMessage(); + + public Object[] getArgumentArray(); + + public String getFormattedMessage(); + + public String getLoggerName(); + + public LoggerContextVO getLoggerContextVO(); + + public IThrowableProxy getThrowableProxy(); + + /** + * Return caller data associated with this event. Note that calling this event + * may trigger the computation of caller data. + * + * @return the caller data associated with this event. + * + * @see #hasCallerData() + */ + public StackTraceElement[] getCallerData(); + + /** + * If this event has caller data, then true is returned. Otherwise the + * returned value is null. + * + *

Logback components wishing to use caller data if available without + * causing it to be computed can invoke this method before invoking + * {@link #getCallerData()}. + * + * @return whether this event has caller data + */ + public boolean hasCallerData(); + + public Marker getMarker(); + + public Map getMDCPropertyMap(); + + public long getTimeStamp(); + + public void prepareForDeferredProcessing(); + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/IThrowableProxy.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/IThrowableProxy.java index 3bb0f69bd85f784d331044a35df8004c079359df..309dd75c370ce41a94762554a675f02ef2a7a8a5 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/IThrowableProxy.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/IThrowableProxy.java @@ -1,22 +1,22 @@ -/** - * 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.classic.spi; - -public interface IThrowableProxy { - public String getMessage(); - public String getClassName(); - public StackTraceElementProxy[] getStackTraceElementProxyArray(); - public int getCommonFrames(); - public IThrowableProxy getCause(); +/** + * 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.classic.spi; + +public interface IThrowableProxy { + public String getMessage(); + public String getClassName(); + public StackTraceElementProxy[] getStackTraceElementProxyArray(); + public int getCommonFrames(); + public IThrowableProxy getCause(); } \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerComparator.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerComparator.java index 5da5ec03e54178925430af7b7371c6638c2a0091..c78de25cacbf8e520e4f6624793f21f8827dd068 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerComparator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerComparator.java @@ -1,35 +1,35 @@ -/** - * 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.classic.spi; - -import java.util.Comparator; - -import ch.qos.logback.classic.Logger; - -public class LoggerComparator implements Comparator { - - public int compare(Logger l1, Logger l2) { - if (l1.getName().equals(l2.getName())) { - return 0; - } - if (l1.getName().equals(Logger.ROOT_LOGGER_NAME)) { - return -1; - } - if (l2.getName().equals(Logger.ROOT_LOGGER_NAME)) { - return 1; - } - return l1.getName().compareTo(l2.getName()); - } - -} +/** + * 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.classic.spi; + +import java.util.Comparator; + +import ch.qos.logback.classic.Logger; + +public class LoggerComparator implements Comparator { + + public int compare(Logger l1, Logger l2) { + if (l1.getName().equals(l2.getName())) { + return 0; + } + if (l1.getName().equals(Logger.ROOT_LOGGER_NAME)) { + return -1; + } + if (l2.getName().equals(Logger.ROOT_LOGGER_NAME)) { + return 1; + } + return l1.getName().compareTo(l2.getName()); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextAware.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextAware.java index 17884c02e2dbe132fdfb7b1d667e1b32e8c197f6..4280a7efd130b04b06760038bc894b4a8b58cc77 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextAware.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextAware.java @@ -1,33 +1,33 @@ -/** - * 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.classic.spi; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.spi.ContextAware; - - -public interface LoggerContextAware extends ContextAware { - - - /** - * Set owning logger context for this component. This operation can - * only be performed once. Once set, the owning context cannot be changed. - * - * @param context The context where this component is attached. - * @throws IllegalStateException If you try to change the context after it - * has been set. - **/ - public void setLoggerContext(LoggerContext context); - -} +/** + * 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.classic.spi; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.spi.ContextAware; + + +public interface LoggerContextAware extends ContextAware { + + + /** + * Set owning logger context for this component. This operation can + * only be performed once. Once set, the owning context cannot be changed. + * + * @param context The context where this component is attached. + * @throws IllegalStateException If you try to change the context after it + * has been set. + **/ + public void setLoggerContext(LoggerContext context); + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextAwareBase.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextAwareBase.java index ba4f7370e28367ef121c231492057ac04b9c03c3..b018fa6457a853e2d24a06a4c0877ab2d4708d6d 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextAwareBase.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextAwareBase.java @@ -1,50 +1,50 @@ -/** - * 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.classic.spi; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.spi.ContextAwareBase; - - -public class LoggerContextAwareBase extends ContextAwareBase implements LoggerContextAware { - - /** - * Set the owning context. The owning context cannot be set more than - * once. - */ - public void setLoggerContext(LoggerContext context) { - super.setContext(context); - } - - public void setContext(Context context) { - // check that the context is of type LoggerContext. Otherwise, throw an exception - // Context == null is a degenarate case but nonetheless permitted. - if(context instanceof LoggerContext || context == null) { - super.setContext(context); - } else { - throw new IllegalArgumentException("LoggerContextAwareBase only accepts contexts of type c.l.classic.LoggerContext"); - } - } - - /** - * Return the {@link LoggerContext} this component is attached to. - * - * @return The owning LoggerContext - */ - public LoggerContext getLoggerContext() { - return (LoggerContext) context; - } - -} +/** + * 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.classic.spi; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAwareBase; + + +public class LoggerContextAwareBase extends ContextAwareBase implements LoggerContextAware { + + /** + * Set the owning context. The owning context cannot be set more than + * once. + */ + public void setLoggerContext(LoggerContext context) { + super.setContext(context); + } + + public void setContext(Context context) { + // check that the context is of type LoggerContext. Otherwise, throw an exception + // Context == null is a degenarate case but nonetheless permitted. + if(context instanceof LoggerContext || context == null) { + super.setContext(context); + } else { + throw new IllegalArgumentException("LoggerContextAwareBase only accepts contexts of type c.l.classic.LoggerContext"); + } + } + + /** + * Return the {@link LoggerContext} this component is attached to. + * + * @return The owning LoggerContext + */ + public LoggerContext getLoggerContext() { + return (LoggerContext) context; + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextListener.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextListener.java index 3d9e790a4b1e59dbc2dc0e2aaecb32818d823a6f..58fdf4882d7a1ea4ebc6066d77ad9abd50c69e1a 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextListener.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextListener.java @@ -1,30 +1,30 @@ -/** - * 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.classic.spi; - -import ch.qos.logback.classic.LoggerContext; - -public interface LoggerContextListener { - - - /** - * Some listeners should not be removed when the LoggerContext is - * reset. Such listeners are said to be reset resistant. - * @return whether this listener is reset resistant or not. - */ - public boolean isResetResistant(); - public void onStart(LoggerContext context); - public void onReset(LoggerContext context); - public void onStop(LoggerContext context); -} +/** + * 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.classic.spi; + +import ch.qos.logback.classic.LoggerContext; + +public interface LoggerContextListener { + + + /** + * Some listeners should not be removed when the LoggerContext is + * reset. Such listeners are said to be reset resistant. + * @return whether this listener is reset resistant or not. + */ + public boolean isResetResistant(); + public void onStart(LoggerContext context); + public void onReset(LoggerContext context); + public void onStop(LoggerContext context); +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextVO.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextVO.java index e6cbe180bd0143cd38c01719372e3d74e76ecc0a..5289051286f379a88265cd3f62eaac42ddb3ecb8 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextVO.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerContextVO.java @@ -1,61 +1,61 @@ -/** - * 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.classic.spi; - -import java.io.Serializable; -import java.util.Map; - -import ch.qos.logback.classic.LoggerContext; - -/** - * LoggerContextVO offers a restricted view of LoggerContext intended to be - * exposed by LoggingEvent to remote systems. This restricted view is optimized - * for serialization. - * - *

- * Some of the LoggerContext or Logger attributes MUST not survive - * serialization, e.g appenders, level values etc, as these attributes may have - * other values on the remote platform. LoggerContextVO class exposes the - * minimal and relevant attributes to the remote host, instead of having to deal - * with an incomplete LoggerContext with many null references. - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class LoggerContextVO implements Serializable { - - private static final long serialVersionUID = 5488023392483144387L; - - final String name; - final Map propertyMap; - final long birthTime; - - public LoggerContextVO(LoggerContext lc) { - this.name = lc.getName(); - this.propertyMap = lc.getCopyOfPropertyMap(); - this.birthTime = lc.getBithTime(); - } - - public String getName() { - return name; - } - - public Map getPropertyMap() { - return propertyMap; - } - - public long getBirthTime() { - return birthTime; - } -} +/** + * 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.classic.spi; + +import java.io.Serializable; +import java.util.Map; + +import ch.qos.logback.classic.LoggerContext; + +/** + * LoggerContextVO offers a restricted view of LoggerContext intended to be + * exposed by LoggingEvent to remote systems. This restricted view is optimized + * for serialization. + * + *

+ * Some of the LoggerContext or Logger attributes MUST not survive + * serialization, e.g appenders, level values etc, as these attributes may have + * other values on the remote platform. LoggerContextVO class exposes the + * minimal and relevant attributes to the remote host, instead of having to deal + * with an incomplete LoggerContext with many null references. + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class LoggerContextVO implements Serializable { + + private static final long serialVersionUID = 5488023392483144387L; + + final String name; + final Map propertyMap; + final long birthTime; + + public LoggerContextVO(LoggerContext lc) { + this.name = lc.getName(); + this.propertyMap = lc.getCopyOfPropertyMap(); + this.birthTime = lc.getBithTime(); + } + + public String getName() { + return name; + } + + public Map getPropertyMap() { + return propertyMap; + } + + public long getBirthTime() { + return birthTime; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerRemoteView.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerRemoteView.java index 731d1e7f47cca243142d8a1401bb9de36a439545..1028c35d06448534465d67e5d649e5ceb7f511db 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerRemoteView.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggerRemoteView.java @@ -1,51 +1,51 @@ -/** - * 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.classic.spi; - -import java.io.Serializable; - -import ch.qos.logback.classic.LoggerContext; - -/** - * An interface that allows Logger objects and LoggerSer objects to be used the - * same way be client of the LoggingEvent object. - *

- * See {@link LoggerContextVO} for the rationale of this class. - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class LoggerRemoteView implements Serializable { - - private static final long serialVersionUID = 5028223666108713696L; - - final LoggerContextVO loggerContextView; - final String name; - - public LoggerRemoteView(String name, LoggerContext lc) { - this.name = name; - assert lc.getLoggerContextRemoteView() != null; - loggerContextView = lc.getLoggerContextRemoteView(); - } - - public LoggerContextVO getLoggerContextView() { - return loggerContextView; - } - - public String getName() { - return name; - } - - -} +/** + * 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.classic.spi; + +import java.io.Serializable; + +import ch.qos.logback.classic.LoggerContext; + +/** + * An interface that allows Logger objects and LoggerSer objects to be used the + * same way be client of the LoggingEvent object. + *

+ * See {@link LoggerContextVO} for the rationale of this class. + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class LoggerRemoteView implements Serializable { + + private static final long serialVersionUID = 5028223666108713696L; + + final LoggerContextVO loggerContextView; + final String name; + + public LoggerRemoteView(String name, LoggerContext lc) { + this.name = name; + assert lc.getLoggerContextRemoteView() != null; + loggerContextView = lc.getLoggerContextRemoteView(); + } + + public LoggerContextVO getLoggerContextView() { + return loggerContextView; + } + + public String getName() { + return name; + } + + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEvent.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEvent.java index f8f248fac98fed816f52aa1fef4329ff1c025df5..b5ac66e0a112d91044357b60606e1f719136683c 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEvent.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEvent.java @@ -1,308 +1,308 @@ -/** - * 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.classic.spi; - -import java.util.HashMap; -import java.util.Map; - -import org.slf4j.MDC; -import org.slf4j.Marker; -import org.slf4j.helpers.MessageFormatter; -import org.slf4j.impl.LogbackMDCAdapter; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; - -/** - * The internal representation of logging events. When an affirmative decision - * is made to log then a LoggingEvent instance is created. This - * instance is passed around to the different logback-classic components. - * - *

Writers of logback-classic components such as appenders should be aware - * of that some of the LoggingEvent fields are initialized lazily. Therefore, an - * appender wishing to output data to be later correctly read by a receiver, - * must initialize "lazy" fields prior to writing them out. See the - * {@link #prepareForDeferredProcessing()} method for the exact list.

- * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class LoggingEvent implements ILoggingEvent { - - /** - * Fully qualified name of the calling Logger class. This field does not - * survive serialization. - * - *

Note that the getCallerInformation() method relies on this fact. - */ - transient String fqnOfLoggerClass; - - /** - * The name of thread in which this logging event was generated. - */ - private String threadName; - - private String loggerName; - private LoggerContext loggerContext; - private LoggerContextVO loggerContextVO; - - /** - * Level of logging event. - * - *

This field should not be accessed directly. You shoud use the {@link - * #getLevel} method instead.

- * - */ - private transient Level level; - - private String message; - - // we gain significant space at serialization time by marking - // formattedMessage as transient and constructing it lazily in - // getFormmatedMessage() - private transient String formattedMessage; - - private transient Object[] argumentArray; - - private ThrowableProxy throwableProxy; - - private StackTraceElement[] callerDataArray; - - private Marker marker; - - private Map mdcPropertyMap; - - /** - * The number of milliseconds elapsed from 1/1/1970 until logging event was - * created. - */ - private long timeStamp; - - public LoggingEvent() { - } - - public LoggingEvent(String fqcn, Logger logger, Level level, String message, - Throwable throwable, Object[] argArray) { - this.fqnOfLoggerClass = fqcn; - this.loggerName = logger.getName(); - this.loggerContext = logger.getLoggerContext(); - this.loggerContextVO = loggerContext.getLoggerContextRemoteView(); - this.level = level; - - this.message = message; - - if (throwable != null) { - this.throwableProxy = new ThrowableProxy(throwable); - LoggerContext lc = logger.getLoggerContext(); - if (lc.isPackagingDataEnabled()) { - this.throwableProxy.calculatePackagingData(); - } - } - - // bug 85 (we previously failed to set this.argumentArray) - this.argumentArray = argArray; - - timeStamp = System.currentTimeMillis(); - - // the case is ugly but under the circumstances acceptable - LogbackMDCAdapter logbackMDCAdapter = (LogbackMDCAdapter) MDC - .getMDCAdapter(); - mdcPropertyMap = logbackMDCAdapter.getPropertyMap(); - } - - public void setArgumentArray(Object[] argArray) { - if (this.argumentArray != null) { - throw new IllegalStateException("argArray has been already set"); - } - this.argumentArray = argArray; - } - - public Object[] getArgumentArray() { - return this.argumentArray; - } - - public Level getLevel() { - return level; - } - - public String getLoggerName() { - return loggerName; - } - - public void setLoggerName(String loggerName) { - this.loggerName = loggerName; - } - - public String getThreadName() { - if (threadName == null) { - threadName = (Thread.currentThread()).getName(); - } - return threadName; - } - - /** - * @param threadName - * The threadName to set. - * @throws IllegalStateException - * If threadName has been already set. - */ - public void setThreadName(String threadName) throws IllegalStateException { - if (this.threadName != null) { - throw new IllegalStateException("threadName has been already set"); - } - this.threadName = threadName; - } - - /** - * Returns the throwable information contained within this event. May be - * null if there is no such information. - */ - public IThrowableProxy getThrowableProxy() { - return throwableProxy; - } - - /** - * Set this event's throwable information. - */ - public void setThrowableProxy(ThrowableProxy tp) { - if (throwableProxy != null) { - throw new IllegalStateException("ThrowableProxy has been already set."); - } else { - throwableProxy = tp; - } - } - - /** - * This method should be called prior to serializing an event. It should also - * be called when using asynchronous or deferred logging. - * - *

Note that due to performance concerns, this method does NOT extract - * caller data. It is the responsibility of the caller to extract caller - * information. - */ - public void prepareForDeferredProcessing() { - this.getThreadName(); - // fixes http://jira.qos.ch/browse/LBCLASSIC-104 - if (mdcPropertyMap != null) { - mdcPropertyMap = new HashMap(mdcPropertyMap); - } - } - - public LoggerContextVO getLoggerContextVO() { - return loggerContextVO; - } - - public void setLoggerContextRemoteView(LoggerContextVO loggerContextVO) { - this.loggerContextVO = loggerContextVO; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - if (this.message != null) { - throw new IllegalStateException( - "The message for this event has been set already."); - } - this.message = message; - } - - public long getTimeStamp() { - return timeStamp; - } - - public void setTimeStamp(long timeStamp) { - this.timeStamp = timeStamp; - } - - public void setLevel(Level level) { - if (this.level != null) { - throw new IllegalStateException( - "The level has been already set for this event."); - } - this.level = level; - } - - /** - * Get the caller information for this logging event. If caller information is - * null at the time of its invocation, this method extracts location - * information. The collected information is cached for future use. - * - *

Note that after serialization it is impossible to correctly extract - * caller information.

- */ - public StackTraceElement[] getCallerData() { - if (callerDataArray == null) { - callerDataArray = CallerData.extract(new Throwable(), fqnOfLoggerClass, - loggerContext.getMaxCallerDataDepth()); - } - return callerDataArray; - } - - public boolean hasCallerData() { - return (callerDataArray != null); - } - - public void setCallerData(StackTraceElement[] callerDataArray) { - this.callerDataArray = callerDataArray; - } - - public Marker getMarker() { - return marker; - } - - public void setMarker(Marker marker) { - if (this.marker != null) { - throw new IllegalStateException( - "The marker has been already set for this event."); - } - this.marker = marker; - } - - public long getContextBirthTime() { - return loggerContextVO.getBirthTime(); - } - - // computer formatted lazy as suggested in - // http://jira.qos.ch/browse/LBCLASSIC-47 - public String getFormattedMessage() { - if (formattedMessage != null) { - return formattedMessage; - } - - if (argumentArray != null) { - formattedMessage = MessageFormatter.arrayFormat(message, argumentArray); - } else { - formattedMessage = message; - } - - return formattedMessage; - } - - public Map getMDCPropertyMap() { - return mdcPropertyMap; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('['); - sb.append(level).append("] "); - sb.append(getFormattedMessage()); - return sb.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.classic.spi; + +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.helpers.MessageFormatter; +import org.slf4j.impl.LogbackMDCAdapter; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; + +/** + * The internal representation of logging events. When an affirmative decision + * is made to log then a LoggingEvent instance is created. This + * instance is passed around to the different logback-classic components. + * + *

Writers of logback-classic components such as appenders should be aware + * of that some of the LoggingEvent fields are initialized lazily. Therefore, an + * appender wishing to output data to be later correctly read by a receiver, + * must initialize "lazy" fields prior to writing them out. See the + * {@link #prepareForDeferredProcessing()} method for the exact list.

+ * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class LoggingEvent implements ILoggingEvent { + + /** + * Fully qualified name of the calling Logger class. This field does not + * survive serialization. + * + *

Note that the getCallerInformation() method relies on this fact. + */ + transient String fqnOfLoggerClass; + + /** + * The name of thread in which this logging event was generated. + */ + private String threadName; + + private String loggerName; + private LoggerContext loggerContext; + private LoggerContextVO loggerContextVO; + + /** + * Level of logging event. + * + *

This field should not be accessed directly. You shoud use the {@link + * #getLevel} method instead.

+ * + */ + private transient Level level; + + private String message; + + // we gain significant space at serialization time by marking + // formattedMessage as transient and constructing it lazily in + // getFormmatedMessage() + private transient String formattedMessage; + + private transient Object[] argumentArray; + + private ThrowableProxy throwableProxy; + + private StackTraceElement[] callerDataArray; + + private Marker marker; + + private Map mdcPropertyMap; + + /** + * The number of milliseconds elapsed from 1/1/1970 until logging event was + * created. + */ + private long timeStamp; + + public LoggingEvent() { + } + + public LoggingEvent(String fqcn, Logger logger, Level level, String message, + Throwable throwable, Object[] argArray) { + this.fqnOfLoggerClass = fqcn; + this.loggerName = logger.getName(); + this.loggerContext = logger.getLoggerContext(); + this.loggerContextVO = loggerContext.getLoggerContextRemoteView(); + this.level = level; + + this.message = message; + + if (throwable != null) { + this.throwableProxy = new ThrowableProxy(throwable); + LoggerContext lc = logger.getLoggerContext(); + if (lc.isPackagingDataEnabled()) { + this.throwableProxy.calculatePackagingData(); + } + } + + // bug 85 (we previously failed to set this.argumentArray) + this.argumentArray = argArray; + + timeStamp = System.currentTimeMillis(); + + // the case is ugly but under the circumstances acceptable + LogbackMDCAdapter logbackMDCAdapter = (LogbackMDCAdapter) MDC + .getMDCAdapter(); + mdcPropertyMap = logbackMDCAdapter.getPropertyMap(); + } + + public void setArgumentArray(Object[] argArray) { + if (this.argumentArray != null) { + throw new IllegalStateException("argArray has been already set"); + } + this.argumentArray = argArray; + } + + public Object[] getArgumentArray() { + return this.argumentArray; + } + + public Level getLevel() { + return level; + } + + public String getLoggerName() { + return loggerName; + } + + public void setLoggerName(String loggerName) { + this.loggerName = loggerName; + } + + public String getThreadName() { + if (threadName == null) { + threadName = (Thread.currentThread()).getName(); + } + return threadName; + } + + /** + * @param threadName + * The threadName to set. + * @throws IllegalStateException + * If threadName has been already set. + */ + public void setThreadName(String threadName) throws IllegalStateException { + if (this.threadName != null) { + throw new IllegalStateException("threadName has been already set"); + } + this.threadName = threadName; + } + + /** + * Returns the throwable information contained within this event. May be + * null if there is no such information. + */ + public IThrowableProxy getThrowableProxy() { + return throwableProxy; + } + + /** + * Set this event's throwable information. + */ + public void setThrowableProxy(ThrowableProxy tp) { + if (throwableProxy != null) { + throw new IllegalStateException("ThrowableProxy has been already set."); + } else { + throwableProxy = tp; + } + } + + /** + * This method should be called prior to serializing an event. It should also + * be called when using asynchronous or deferred logging. + * + *

Note that due to performance concerns, this method does NOT extract + * caller data. It is the responsibility of the caller to extract caller + * information. + */ + public void prepareForDeferredProcessing() { + this.getThreadName(); + // fixes http://jira.qos.ch/browse/LBCLASSIC-104 + if (mdcPropertyMap != null) { + mdcPropertyMap = new HashMap(mdcPropertyMap); + } + } + + public LoggerContextVO getLoggerContextVO() { + return loggerContextVO; + } + + public void setLoggerContextRemoteView(LoggerContextVO loggerContextVO) { + this.loggerContextVO = loggerContextVO; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + if (this.message != null) { + throw new IllegalStateException( + "The message for this event has been set already."); + } + this.message = message; + } + + public long getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(long timeStamp) { + this.timeStamp = timeStamp; + } + + public void setLevel(Level level) { + if (this.level != null) { + throw new IllegalStateException( + "The level has been already set for this event."); + } + this.level = level; + } + + /** + * Get the caller information for this logging event. If caller information is + * null at the time of its invocation, this method extracts location + * information. The collected information is cached for future use. + * + *

Note that after serialization it is impossible to correctly extract + * caller information.

+ */ + public StackTraceElement[] getCallerData() { + if (callerDataArray == null) { + callerDataArray = CallerData.extract(new Throwable(), fqnOfLoggerClass, + loggerContext.getMaxCallerDataDepth()); + } + return callerDataArray; + } + + public boolean hasCallerData() { + return (callerDataArray != null); + } + + public void setCallerData(StackTraceElement[] callerDataArray) { + this.callerDataArray = callerDataArray; + } + + public Marker getMarker() { + return marker; + } + + public void setMarker(Marker marker) { + if (this.marker != null) { + throw new IllegalStateException( + "The marker has been already set for this event."); + } + this.marker = marker; + } + + public long getContextBirthTime() { + return loggerContextVO.getBirthTime(); + } + + // computer formatted lazy as suggested in + // http://jira.qos.ch/browse/LBCLASSIC-47 + public String getFormattedMessage() { + if (formattedMessage != null) { + return formattedMessage; + } + + if (argumentArray != null) { + formattedMessage = MessageFormatter.arrayFormat(message, argumentArray); + } else { + formattedMessage = message; + } + + return formattedMessage; + } + + public Map getMDCPropertyMap() { + return mdcPropertyMap; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append('['); + sb.append(level).append("] "); + sb.append(getFormattedMessage()); + return sb.toString(); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEventVO.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEventVO.java index aee068d152f4ab5cea4ceb34978fc674f18ff132..32c57083c7f6dc883537ef0163d588d168a53367 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEventVO.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEventVO.java @@ -1,247 +1,247 @@ -/** - * 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.classic.spi; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.Map; - -import org.slf4j.Marker; -import org.slf4j.helpers.MessageFormatter; - -import ch.qos.logback.classic.Level; - -// http://www.riehle.org/computer-science/research/1998/ubilab-tr-1998-10-1.html - -/** - * A read-only and serializable implementation of {@link ILoggingEvent}. - * - * @author Ceki Gülcü - * @since 0.9.16 - */ -public class LoggingEventVO implements ILoggingEvent, Serializable { - - private static final long serialVersionUID = 6553722650255690312L; - - private static final int NULL_ARGUMENT_ARRAY = -1; - private static final String NULL_ARGUMENT_ARRAY_ELEMENT = "NULL_ARGUMENT_ARRAY_ELEMENT"; - - private String threadName; - private String loggerName; - private LoggerContextVO loggerContextVO; - - private transient Level level; - private String message; - - // we gain significant space at serialization time by marking - // formattedMessage as transient and constructing it lazily in - // getFormmatedMessage() - private transient String formattedMessage; - - private transient Object[] argumentArray; - - private ThrowableProxyVO throwableProxy; - private StackTraceElement[] callerDataArray; - private Marker marker; - private Map mdcPropertyMap; - private long timeStamp; - - public static LoggingEventVO build(ILoggingEvent le) { - LoggingEventVO ledo = new LoggingEventVO(); - ledo.loggerName = le.getLoggerName(); - ledo.loggerContextVO = le.getLoggerContextVO(); - ledo.threadName = le.getThreadName(); - ledo.level = (le.getLevel()); - ledo.message = (le.getMessage()); - ledo.argumentArray = (le.getArgumentArray()); - ledo.marker = le.getMarker(); - ledo.mdcPropertyMap = le.getMDCPropertyMap(); - ledo.timeStamp = le.getTimeStamp(); - ledo.throwableProxy = ThrowableProxyVO.build(le.getThrowableProxy()); - // add caller data only if it is there already - // fixes http://jira.qos.ch/browse/LBCLASSIC-145 - if(le.hasCallerData()) { - ledo.callerDataArray = le.getCallerData(); - } - return ledo; - } - - public String getThreadName() { - return threadName; - } - - public LoggerContextVO getLoggerContextVO() { - return loggerContextVO; - } - - public String getLoggerName() { - return loggerName; - } - - public Level getLevel() { - return level; - } - - public String getMessage() { - return message; - } - - public String getFormattedMessage() { - if (formattedMessage != null) { - return formattedMessage; - } - - if (argumentArray != null) { - formattedMessage = MessageFormatter.arrayFormat(message, argumentArray); - } else { - formattedMessage = message; - } - - return formattedMessage; - } - - public Object[] getArgumentArray() { - return argumentArray; - } - - public IThrowableProxy getThrowableProxy() { - return throwableProxy; - } - - public StackTraceElement[] getCallerData() { - return callerDataArray; - } - - public boolean hasCallerData() { - return callerDataArray != null; - } - - public Marker getMarker() { - return marker; - } - - public long getTimeStamp() { - return timeStamp; - } - - - - public long getContextBirthTime() { - return loggerContextVO.getBirthTime(); - } - - public LoggerContextVO getContextLoggerRemoteView() { - return loggerContextVO; - } - - public Map getMDCPropertyMap() { - return mdcPropertyMap; - } - - public void prepareForDeferredProcessing() { - } - - private void writeObject(ObjectOutputStream out) throws IOException { - out.defaultWriteObject(); - out.writeInt(level.levelInt); - if (argumentArray != null) { - int len = argumentArray.length; - out.writeInt(len); - for (int i = 0; i < argumentArray.length; i++) { - if (argumentArray[i] != null) { - out.writeObject(argumentArray[i].toString()); - } else { - out.writeObject(NULL_ARGUMENT_ARRAY_ELEMENT); - } - } - } else { - out.writeInt(NULL_ARGUMENT_ARRAY); - } - - } - - private void readObject(ObjectInputStream in) throws IOException, - ClassNotFoundException { - in.defaultReadObject(); - int levelInt = in.readInt(); - level = Level.toLevel(levelInt); - - int argArrayLen = in.readInt(); - if (argArrayLen != NULL_ARGUMENT_ARRAY) { - argumentArray = new String[argArrayLen]; - for (int i = 0; i < argArrayLen; i++) { - Object val = in.readObject(); - if (!NULL_ARGUMENT_ARRAY_ELEMENT.equals(val)) { - argumentArray[i] = val; - } - } - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((message == null) ? 0 : message.hashCode()); - result = prime * result - + ((threadName == null) ? 0 : threadName.hashCode()); - result = prime * result + (int) (timeStamp ^ (timeStamp >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final LoggingEventVO other = (LoggingEventVO) obj; - if (message == null) { - if (other.message != null) - return false; - } else if (!message.equals(other.message)) - return false; - - if (loggerName == null) { - if (other.loggerName != null) - return false; - } else if (!loggerName.equals(other.loggerName)) - return false; - - if (threadName == null) { - if (other.threadName != null) - return false; - } else if (!threadName.equals(other.threadName)) - return false; - if (timeStamp != other.timeStamp) - return false; - - if (marker == null) { - if (other.marker != null) - return false; - } else if (!marker.equals(other.marker)) - return false; - - if (mdcPropertyMap == null) { - if (other.mdcPropertyMap != null) - return false; - } else if (!mdcPropertyMap.equals(other.mdcPropertyMap)) - return false; - return true; - } -} +/** + * 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.classic.spi; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Map; + +import org.slf4j.Marker; +import org.slf4j.helpers.MessageFormatter; + +import ch.qos.logback.classic.Level; + +// http://www.riehle.org/computer-science/research/1998/ubilab-tr-1998-10-1.html + +/** + * A read-only and serializable implementation of {@link ILoggingEvent}. + * + * @author Ceki Gülcü + * @since 0.9.16 + */ +public class LoggingEventVO implements ILoggingEvent, Serializable { + + private static final long serialVersionUID = 6553722650255690312L; + + private static final int NULL_ARGUMENT_ARRAY = -1; + private static final String NULL_ARGUMENT_ARRAY_ELEMENT = "NULL_ARGUMENT_ARRAY_ELEMENT"; + + private String threadName; + private String loggerName; + private LoggerContextVO loggerContextVO; + + private transient Level level; + private String message; + + // we gain significant space at serialization time by marking + // formattedMessage as transient and constructing it lazily in + // getFormmatedMessage() + private transient String formattedMessage; + + private transient Object[] argumentArray; + + private ThrowableProxyVO throwableProxy; + private StackTraceElement[] callerDataArray; + private Marker marker; + private Map mdcPropertyMap; + private long timeStamp; + + public static LoggingEventVO build(ILoggingEvent le) { + LoggingEventVO ledo = new LoggingEventVO(); + ledo.loggerName = le.getLoggerName(); + ledo.loggerContextVO = le.getLoggerContextVO(); + ledo.threadName = le.getThreadName(); + ledo.level = (le.getLevel()); + ledo.message = (le.getMessage()); + ledo.argumentArray = (le.getArgumentArray()); + ledo.marker = le.getMarker(); + ledo.mdcPropertyMap = le.getMDCPropertyMap(); + ledo.timeStamp = le.getTimeStamp(); + ledo.throwableProxy = ThrowableProxyVO.build(le.getThrowableProxy()); + // add caller data only if it is there already + // fixes http://jira.qos.ch/browse/LBCLASSIC-145 + if(le.hasCallerData()) { + ledo.callerDataArray = le.getCallerData(); + } + return ledo; + } + + public String getThreadName() { + return threadName; + } + + public LoggerContextVO getLoggerContextVO() { + return loggerContextVO; + } + + public String getLoggerName() { + return loggerName; + } + + public Level getLevel() { + return level; + } + + public String getMessage() { + return message; + } + + public String getFormattedMessage() { + if (formattedMessage != null) { + return formattedMessage; + } + + if (argumentArray != null) { + formattedMessage = MessageFormatter.arrayFormat(message, argumentArray); + } else { + formattedMessage = message; + } + + return formattedMessage; + } + + public Object[] getArgumentArray() { + return argumentArray; + } + + public IThrowableProxy getThrowableProxy() { + return throwableProxy; + } + + public StackTraceElement[] getCallerData() { + return callerDataArray; + } + + public boolean hasCallerData() { + return callerDataArray != null; + } + + public Marker getMarker() { + return marker; + } + + public long getTimeStamp() { + return timeStamp; + } + + + + public long getContextBirthTime() { + return loggerContextVO.getBirthTime(); + } + + public LoggerContextVO getContextLoggerRemoteView() { + return loggerContextVO; + } + + public Map getMDCPropertyMap() { + return mdcPropertyMap; + } + + public void prepareForDeferredProcessing() { + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeInt(level.levelInt); + if (argumentArray != null) { + int len = argumentArray.length; + out.writeInt(len); + for (int i = 0; i < argumentArray.length; i++) { + if (argumentArray[i] != null) { + out.writeObject(argumentArray[i].toString()); + } else { + out.writeObject(NULL_ARGUMENT_ARRAY_ELEMENT); + } + } + } else { + out.writeInt(NULL_ARGUMENT_ARRAY); + } + + } + + private void readObject(ObjectInputStream in) throws IOException, + ClassNotFoundException { + in.defaultReadObject(); + int levelInt = in.readInt(); + level = Level.toLevel(levelInt); + + int argArrayLen = in.readInt(); + if (argArrayLen != NULL_ARGUMENT_ARRAY) { + argumentArray = new String[argArrayLen]; + for (int i = 0; i < argArrayLen; i++) { + Object val = in.readObject(); + if (!NULL_ARGUMENT_ARRAY_ELEMENT.equals(val)) { + argumentArray[i] = val; + } + } + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((message == null) ? 0 : message.hashCode()); + result = prime * result + + ((threadName == null) ? 0 : threadName.hashCode()); + result = prime * result + (int) (timeStamp ^ (timeStamp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final LoggingEventVO other = (LoggingEventVO) obj; + if (message == null) { + if (other.message != null) + return false; + } else if (!message.equals(other.message)) + return false; + + if (loggerName == null) { + if (other.loggerName != null) + return false; + } else if (!loggerName.equals(other.loggerName)) + return false; + + if (threadName == null) { + if (other.threadName != null) + return false; + } else if (!threadName.equals(other.threadName)) + return false; + if (timeStamp != other.timeStamp) + return false; + + if (marker == null) { + if (other.marker != null) + return false; + } else if (!marker.equals(other.marker)) + return false; + + if (mdcPropertyMap == null) { + if (other.mdcPropertyMap != null) + return false; + } else if (!mdcPropertyMap.equals(other.mdcPropertyMap)) + return false; + return true; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java index 8371e91e34a9f4f2af8086b5dd4af5e3ab4d3518..654a5dce6cf2a9124d40ba2bb8329edaf453cc3c 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java @@ -1,244 +1,244 @@ -/** - * 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.classic.spi; - -import java.net.URL; -import java.util.HashMap; - -import sun.reflect.Reflection; - -/** - * - * Given a classname locate associated PackageInfo (jar name, version name). - * - * @author James Strachan - * @Ceki Gülcü - */ -public class PackagingDataCalculator { - - final static StackTraceElementProxy[] STEP_ARRAY_TEMPLATE = new StackTraceElementProxy[0]; - - HashMap cache = new HashMap(); - - private static boolean GET_CALLER_CLASS_METHOD_AVAILABLE = false; - - static { - // if either the Reflection class or the getCallerClass method - // are unavailable, then we won't invoke Reflection.getCallerClass() - // This approach ensures that this class will *run* on JDK's lacking - // sun.reflect.Reflection class. However, this class will *not compile* - // on JDKs lacking sun.reflect.Reflection. - try { - Reflection.getCallerClass(2); - GET_CALLER_CLASS_METHOD_AVAILABLE = true; - } catch (NoClassDefFoundError e) { - } catch (NoSuchMethodError e) { - } catch (Throwable e) { - System.err.println("Unexpected exception"); - e.printStackTrace(); - } - } - - public PackagingDataCalculator() { - } - - public void calculate(IThrowableProxy tp) { - while (tp != null) { - populateFrames(tp.getStackTraceElementProxyArray()); - tp = tp.getCause(); - } - } - - void populateFrames(StackTraceElementProxy[] stepArray) { - // in the initial part of this method we populate package information for - // common stack frames - final Throwable t = new Throwable("local stack reference"); - final StackTraceElement[] localteSTEArray = t.getStackTrace(); - final int commonFrames = STEUtil.findNumberOfCommonFrames(localteSTEArray, - stepArray); - final int localFirstCommon = localteSTEArray.length - commonFrames; - final int stepFirstCommon = stepArray.length - commonFrames; - - ClassLoader lastExactClassLoader = null; - ClassLoader firsExactClassLoader = null; - - int missfireCount = 0; - for (int i = 0; i < commonFrames; i++) { - Class callerClass = null; - if (GET_CALLER_CLASS_METHOD_AVAILABLE) { - callerClass = Reflection.getCallerClass(localFirstCommon + i - - missfireCount + 1); - } - StackTraceElementProxy step = stepArray[stepFirstCommon + i]; - String stepClassname = step.ste.getClassName(); - - if (callerClass != null && stepClassname.equals(callerClass.getName())) { - lastExactClassLoader = callerClass.getClassLoader(); - if (firsExactClassLoader == null) { - firsExactClassLoader = callerClass.getClassLoader(); - } - ClassPackagingData pi = calculateByExactType(callerClass); - step.setClassPackagingData(pi); - } else { - missfireCount++; - ClassPackagingData pi = computeBySTEP(step, lastExactClassLoader); - step.setClassPackagingData(pi); - } - } - populateUncommonFrames(commonFrames, stepArray, firsExactClassLoader); - } - - void populateUncommonFrames(int commonFrames, - StackTraceElementProxy[] stepArray, ClassLoader firstExactClassLoader) { - int uncommonFrames = stepArray.length - commonFrames; - for (int i = 0; i < uncommonFrames; i++) { - StackTraceElementProxy step = stepArray[i]; - ClassPackagingData pi = computeBySTEP(step, firstExactClassLoader); - step.setClassPackagingData(pi); - } - } - - private ClassPackagingData calculateByExactType(Class type) { - String className = type.getName(); - ClassPackagingData cpd = cache.get(className); - if (cpd != null) { - return cpd; - } - String version = getImplementationVersion(type); - String codeLocation = getCodeLocation(type); - cpd = new ClassPackagingData(codeLocation, version); - cache.put(className, cpd); - return cpd; - } - - private ClassPackagingData computeBySTEP(StackTraceElementProxy step, - ClassLoader lastExactClassLoader) { - String className = step.ste.getClassName(); - ClassPackagingData cpd = cache.get(className); - if (cpd != null) { - return cpd; - } - Class type = bestEffortLoadClass(lastExactClassLoader, className); - String version = getImplementationVersion(type); - String codeLocation = getCodeLocation(type); - cpd = new ClassPackagingData(codeLocation, version, false); - cache.put(className, cpd); - return cpd; - } - - String getImplementationVersion(Class type) { - if (type == null) { - return "na"; - } - Package aPackage = type.getPackage(); - if (aPackage != null) { - String v = aPackage.getImplementationVersion(); - if (v == null) { - return "na"; - } else { - return v; - } - } - return "na"; - - } - - String getCodeLocation(Class type) { - try { - if (type != null) { - // file:/C:/java/maven-2.0.8/repo/com/icegreen/greenmail/1.3/greenmail-1.3.jar - URL resource = type.getProtectionDomain().getCodeSource().getLocation(); - if (resource != null) { - String locationStr = resource.toString(); - // now lets remove all but the file name - String result = getCodeLocation(locationStr, '/'); - if (result != null) { - return result; - } - return getCodeLocation(locationStr, '\\'); - } - } - } catch (Exception e) { - // ignore - } - return "na"; - } - - private String getCodeLocation(String locationStr, char separator) { - int idx = locationStr.lastIndexOf(separator); - if (isFolder(idx, locationStr)) { - idx = locationStr.lastIndexOf(separator, idx - 1); - return locationStr.substring(idx + 1); - } else if (idx > 0) { - return locationStr.substring(idx + 1); - } - return null; - } - - private boolean isFolder(int idx, String text) { - return (idx != -1 && idx + 1 == text.length()); - } - - private Class loadClass(ClassLoader cl, String className) { - if (cl == null) { - return null; - } - try { - return cl.loadClass(className); - } catch (ClassNotFoundException e1) { - return null; - } catch (NoClassDefFoundError e1) { - return null; - } catch (Exception e) { - e.printStackTrace(); // this is unexpected - return null; - } - - } - - /** - * - * @param lastGuaranteedClassLoader - * may be null - * - * @param className - * @return - */ - private Class bestEffortLoadClass(ClassLoader lastGuaranteedClassLoader, - String className) { - Class result = loadClass(lastGuaranteedClassLoader, className); - if (result != null) { - return result; - } - ClassLoader tccl = Thread.currentThread().getContextClassLoader(); - if (tccl != lastGuaranteedClassLoader) { - result = loadClass(tccl, className); - } - if (result != null) { - return result; - } - - try { - return Class.forName(className); - } catch (ClassNotFoundException e1) { - return null; - } catch (NoClassDefFoundError e1) { - return null; - } catch (Exception e) { - e.printStackTrace(); // this is unexpected - return null; - } - } - -} +/** + * 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.classic.spi; + +import java.net.URL; +import java.util.HashMap; + +import sun.reflect.Reflection; + +/** + * + * Given a classname locate associated PackageInfo (jar name, version name). + * + * @author James Strachan + * @Ceki Gülcü + */ +public class PackagingDataCalculator { + + final static StackTraceElementProxy[] STEP_ARRAY_TEMPLATE = new StackTraceElementProxy[0]; + + HashMap cache = new HashMap(); + + private static boolean GET_CALLER_CLASS_METHOD_AVAILABLE = false; + + static { + // if either the Reflection class or the getCallerClass method + // are unavailable, then we won't invoke Reflection.getCallerClass() + // This approach ensures that this class will *run* on JDK's lacking + // sun.reflect.Reflection class. However, this class will *not compile* + // on JDKs lacking sun.reflect.Reflection. + try { + Reflection.getCallerClass(2); + GET_CALLER_CLASS_METHOD_AVAILABLE = true; + } catch (NoClassDefFoundError e) { + } catch (NoSuchMethodError e) { + } catch (Throwable e) { + System.err.println("Unexpected exception"); + e.printStackTrace(); + } + } + + public PackagingDataCalculator() { + } + + public void calculate(IThrowableProxy tp) { + while (tp != null) { + populateFrames(tp.getStackTraceElementProxyArray()); + tp = tp.getCause(); + } + } + + void populateFrames(StackTraceElementProxy[] stepArray) { + // in the initial part of this method we populate package information for + // common stack frames + final Throwable t = new Throwable("local stack reference"); + final StackTraceElement[] localteSTEArray = t.getStackTrace(); + final int commonFrames = STEUtil.findNumberOfCommonFrames(localteSTEArray, + stepArray); + final int localFirstCommon = localteSTEArray.length - commonFrames; + final int stepFirstCommon = stepArray.length - commonFrames; + + ClassLoader lastExactClassLoader = null; + ClassLoader firsExactClassLoader = null; + + int missfireCount = 0; + for (int i = 0; i < commonFrames; i++) { + Class callerClass = null; + if (GET_CALLER_CLASS_METHOD_AVAILABLE) { + callerClass = Reflection.getCallerClass(localFirstCommon + i + - missfireCount + 1); + } + StackTraceElementProxy step = stepArray[stepFirstCommon + i]; + String stepClassname = step.ste.getClassName(); + + if (callerClass != null && stepClassname.equals(callerClass.getName())) { + lastExactClassLoader = callerClass.getClassLoader(); + if (firsExactClassLoader == null) { + firsExactClassLoader = callerClass.getClassLoader(); + } + ClassPackagingData pi = calculateByExactType(callerClass); + step.setClassPackagingData(pi); + } else { + missfireCount++; + ClassPackagingData pi = computeBySTEP(step, lastExactClassLoader); + step.setClassPackagingData(pi); + } + } + populateUncommonFrames(commonFrames, stepArray, firsExactClassLoader); + } + + void populateUncommonFrames(int commonFrames, + StackTraceElementProxy[] stepArray, ClassLoader firstExactClassLoader) { + int uncommonFrames = stepArray.length - commonFrames; + for (int i = 0; i < uncommonFrames; i++) { + StackTraceElementProxy step = stepArray[i]; + ClassPackagingData pi = computeBySTEP(step, firstExactClassLoader); + step.setClassPackagingData(pi); + } + } + + private ClassPackagingData calculateByExactType(Class type) { + String className = type.getName(); + ClassPackagingData cpd = cache.get(className); + if (cpd != null) { + return cpd; + } + String version = getImplementationVersion(type); + String codeLocation = getCodeLocation(type); + cpd = new ClassPackagingData(codeLocation, version); + cache.put(className, cpd); + return cpd; + } + + private ClassPackagingData computeBySTEP(StackTraceElementProxy step, + ClassLoader lastExactClassLoader) { + String className = step.ste.getClassName(); + ClassPackagingData cpd = cache.get(className); + if (cpd != null) { + return cpd; + } + Class type = bestEffortLoadClass(lastExactClassLoader, className); + String version = getImplementationVersion(type); + String codeLocation = getCodeLocation(type); + cpd = new ClassPackagingData(codeLocation, version, false); + cache.put(className, cpd); + return cpd; + } + + String getImplementationVersion(Class type) { + if (type == null) { + return "na"; + } + Package aPackage = type.getPackage(); + if (aPackage != null) { + String v = aPackage.getImplementationVersion(); + if (v == null) { + return "na"; + } else { + return v; + } + } + return "na"; + + } + + String getCodeLocation(Class type) { + try { + if (type != null) { + // file:/C:/java/maven-2.0.8/repo/com/icegreen/greenmail/1.3/greenmail-1.3.jar + URL resource = type.getProtectionDomain().getCodeSource().getLocation(); + if (resource != null) { + String locationStr = resource.toString(); + // now lets remove all but the file name + String result = getCodeLocation(locationStr, '/'); + if (result != null) { + return result; + } + return getCodeLocation(locationStr, '\\'); + } + } + } catch (Exception e) { + // ignore + } + return "na"; + } + + private String getCodeLocation(String locationStr, char separator) { + int idx = locationStr.lastIndexOf(separator); + if (isFolder(idx, locationStr)) { + idx = locationStr.lastIndexOf(separator, idx - 1); + return locationStr.substring(idx + 1); + } else if (idx > 0) { + return locationStr.substring(idx + 1); + } + return null; + } + + private boolean isFolder(int idx, String text) { + return (idx != -1 && idx + 1 == text.length()); + } + + private Class loadClass(ClassLoader cl, String className) { + if (cl == null) { + return null; + } + try { + return cl.loadClass(className); + } catch (ClassNotFoundException e1) { + return null; + } catch (NoClassDefFoundError e1) { + return null; + } catch (Exception e) { + e.printStackTrace(); // this is unexpected + return null; + } + + } + + /** + * + * @param lastGuaranteedClassLoader + * may be null + * + * @param className + * @return + */ + private Class bestEffortLoadClass(ClassLoader lastGuaranteedClassLoader, + String className) { + Class result = loadClass(lastGuaranteedClassLoader, className); + if (result != null) { + return result; + } + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + if (tccl != lastGuaranteedClassLoader) { + result = loadClass(tccl, className); + } + if (result != null) { + return result; + } + + try { + return Class.forName(className); + } catch (ClassNotFoundException e1) { + return null; + } catch (NoClassDefFoundError e1) { + return null; + } catch (Exception e) { + e.printStackTrace(); // this is unexpected + return null; + } + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/PlatformInfo.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/PlatformInfo.java index 7f2f4e548af85e856ed5e00fc264b37fa78aa2af..1b69d96db2fae182468cfe26f59a66428b112401 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/PlatformInfo.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/PlatformInfo.java @@ -1,38 +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.classic.spi; - -/** - * This class provides information about the runtime platform. - * - * @author Ceki Gulcu - * */ -public class PlatformInfo { - - private static final int UNINITIALIZED = -1; - - private static int hasJMXObjectName = UNINITIALIZED; - - public static boolean hasJMXObjectName() { - if (hasJMXObjectName == UNINITIALIZED) { - try { - Class.forName("javax.management.ObjectName"); - hasJMXObjectName = 1; - } catch (Throwable e) { - hasJMXObjectName = 0; - } - } - return (hasJMXObjectName == 1); - } -} +/** + * 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.classic.spi; + +/** + * This class provides information about the runtime platform. + * + * @author Ceki Gulcu + * */ +public class PlatformInfo { + + private static final int UNINITIALIZED = -1; + + private static int hasJMXObjectName = UNINITIALIZED; + + public static boolean hasJMXObjectName() { + if (hasJMXObjectName == UNINITIALIZED) { + try { + Class.forName("javax.management.ObjectName"); + hasJMXObjectName = 1; + } catch (Throwable e) { + hasJMXObjectName = 0; + } + } + return (hasJMXObjectName == 1); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/STEUtil.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/STEUtil.java index 66b7b87c56b07fd3813077d417828ffd9799a12b..50bb9f8b183c6b74e92a2c6281a673cd93d2fdc6 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/STEUtil.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/STEUtil.java @@ -1,61 +1,61 @@ -/** - * 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.classic.spi; - -public class STEUtil { - - - static int UNUSED_findNumberOfCommonFrames(StackTraceElement[] steArray, - StackTraceElement[] otherSTEArray) { - if (otherSTEArray == null) { - return 0; - } - - int steIndex = steArray.length - 1; - int parentIndex = otherSTEArray.length - 1; - int count = 0; - while (steIndex >= 0 && parentIndex >= 0) { - if (steArray[steIndex].equals(otherSTEArray[parentIndex])) { - count++; - } else { - break; - } - steIndex--; - parentIndex--; - } - return count; - } - - - static int findNumberOfCommonFrames(StackTraceElement[] steArray, - StackTraceElementProxy[] otherSTEPArray) { - if (otherSTEPArray == null) { - return 0; - } - - int steIndex = steArray.length - 1; - int parentIndex = otherSTEPArray.length - 1; - int count = 0; - while (steIndex >= 0 && parentIndex >= 0) { - if (steArray[steIndex].equals(otherSTEPArray[parentIndex].ste)) { - count++; - } else { - break; - } - steIndex--; - parentIndex--; - } - return count; - } -} +/** + * 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.classic.spi; + +public class STEUtil { + + + static int UNUSED_findNumberOfCommonFrames(StackTraceElement[] steArray, + StackTraceElement[] otherSTEArray) { + if (otherSTEArray == null) { + return 0; + } + + int steIndex = steArray.length - 1; + int parentIndex = otherSTEArray.length - 1; + int count = 0; + while (steIndex >= 0 && parentIndex >= 0) { + if (steArray[steIndex].equals(otherSTEArray[parentIndex])) { + count++; + } else { + break; + } + steIndex--; + parentIndex--; + } + return count; + } + + + static int findNumberOfCommonFrames(StackTraceElement[] steArray, + StackTraceElementProxy[] otherSTEPArray) { + if (otherSTEPArray == null) { + return 0; + } + + int steIndex = steArray.length - 1; + int parentIndex = otherSTEPArray.length - 1; + int count = 0; + while (steIndex >= 0 && parentIndex >= 0) { + if (steArray[steIndex].equals(otherSTEPArray[parentIndex].ste)) { + count++; + } else { + break; + } + steIndex--; + parentIndex--; + } + return count; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/StackTraceElementProxy.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/StackTraceElementProxy.java index bdde5fa4c0810d39b74d641ee6eaf0a3d299c315..3884f89d7819b6a7c18d6b38f9d606bcb47ab70a 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/StackTraceElementProxy.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/StackTraceElementProxy.java @@ -1,90 +1,90 @@ -/** - * 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.classic.spi; - -import java.io.Serializable; - -public class StackTraceElementProxy implements Serializable { - - private static final long serialVersionUID = -2374374378980555982L; - - final StackTraceElement ste; - // save a byte or two during serialization, as we can - // reconstruct this field from 'ste' - transient private String steAsString; - private ClassPackagingData cpd; - - public StackTraceElementProxy(StackTraceElement ste) { - if (ste == null) { - throw new IllegalArgumentException("ste cannot be null"); - } - this.ste = ste; - } - - - public String getSTEAsString() { - if (steAsString == null) { - steAsString = "at " + ste.toString(); - } - return steAsString; - } - - public StackTraceElement getStackTraceElement() { - return ste; - } - - public void setClassPackagingData(ClassPackagingData cpd) { - if(this.cpd != null) { - throw new IllegalStateException("Packaging data has been already set"); - } - this.cpd = cpd; - } - - public ClassPackagingData getClassPackagingData() { - return cpd; - } - - @Override - public int hashCode() { - return ste.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final StackTraceElementProxy other = (StackTraceElementProxy) obj; - - if (!ste.equals(other.ste)) { - return false; - } - if (cpd == null) { - if (other.cpd != null) { - return false; - } - } else if (!cpd.equals(other.cpd)) { - return false; - } - return true; - } - - @Override - public String toString() { - return getSTEAsString(); - } -} +/** + * 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.classic.spi; + +import java.io.Serializable; + +public class StackTraceElementProxy implements Serializable { + + private static final long serialVersionUID = -2374374378980555982L; + + final StackTraceElement ste; + // save a byte or two during serialization, as we can + // reconstruct this field from 'ste' + transient private String steAsString; + private ClassPackagingData cpd; + + public StackTraceElementProxy(StackTraceElement ste) { + if (ste == null) { + throw new IllegalArgumentException("ste cannot be null"); + } + this.ste = ste; + } + + + public String getSTEAsString() { + if (steAsString == null) { + steAsString = "at " + ste.toString(); + } + return steAsString; + } + + public StackTraceElement getStackTraceElement() { + return ste; + } + + public void setClassPackagingData(ClassPackagingData cpd) { + if(this.cpd != null) { + throw new IllegalStateException("Packaging data has been already set"); + } + this.cpd = cpd; + } + + public ClassPackagingData getClassPackagingData() { + return cpd; + } + + @Override + public int hashCode() { + return ste.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final StackTraceElementProxy other = (StackTraceElementProxy) obj; + + if (!ste.equals(other.ste)) { + return false; + } + if (cpd == null) { + if (other.cpd != null) { + return false; + } + } else if (!cpd.equals(other.cpd)) { + return false; + } + return true; + } + + @Override + public String toString() { + return getSTEAsString(); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxy.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxy.java index 9b0cecf9b507e70909fd41b143dc15d3a05c9b6d..a6098fbc57e582e8df8f7b0bd9f8f9d657f22192 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxy.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxy.java @@ -1,118 +1,118 @@ -/** - * 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.classic.spi; - -import ch.qos.logback.core.CoreConstants; - -public class ThrowableProxy implements IThrowableProxy { - - Throwable throwable; - String className; - String message; - StackTraceElementProxy[] stackTraceElementProxyArray; - int commonFrames; - ThrowableProxy cause; - - private transient PackagingDataCalculator packagingDataCalculator; - private boolean calculatedPackageData = false; - - public ThrowableProxy(Throwable throwable) { - - this.throwable = throwable; - this.className = throwable.getClass().getName(); - this.message = throwable.getMessage(); - this.stackTraceElementProxyArray = ThrowableProxyUtil.steArrayToStepArray(throwable - .getStackTrace()); - - Throwable nested = throwable.getCause(); - - if (nested != null) { - this.cause = new ThrowableProxy(nested); - this.cause.commonFrames = ThrowableProxyUtil - .findNumberOfCommonFrames(nested.getStackTrace(), - stackTraceElementProxyArray); - } - } - - - public Throwable getThrowable() { - return throwable; - } - - public String getMessage() { - return message; - } - - /* - * (non-Javadoc) - * - * @see ch.qos.logback.classic.spi.IThrowableProxy#getClassName() - */ - public String getClassName() { - return className; - } - - public StackTraceElementProxy[] getStackTraceElementProxyArray() { - return stackTraceElementProxyArray; - } - - public int getCommonFrames() { - return commonFrames; - } - - /* - * (non-Javadoc) - * - * @see ch.qos.logback.classic.spi.IThrowableProxy#getCause() - */ - public IThrowableProxy getCause() { - return cause; - } - - public PackagingDataCalculator getPackagingDataCalculator() { - // if original instance (non-deserialized), and packagingDataCalculator - // is not already initialized, then create an instance. - // here we assume that (throwable == null) for deserialized instances - if (throwable != null && packagingDataCalculator == null) { - packagingDataCalculator = new PackagingDataCalculator(); - } - return packagingDataCalculator; - } - - public void calculatePackagingData() { - if (calculatedPackageData) { - return; - } - PackagingDataCalculator pdc = this.getPackagingDataCalculator(); - if (pdc != null) { - calculatedPackageData = true; - pdc.calculate(this); - } - } - - - - public void fullDump() { - StringBuilder builder = new StringBuilder(); - for (StackTraceElementProxy step : stackTraceElementProxyArray) { - String string = step.toString(); - builder.append(CoreConstants.TAB).append(string); - ThrowableProxyUtil.appendPackagingData(builder, step); - builder.append(CoreConstants.LINE_SEPARATOR); - } - System.out.println(builder.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.classic.spi; + +import ch.qos.logback.core.CoreConstants; + +public class ThrowableProxy implements IThrowableProxy { + + Throwable throwable; + String className; + String message; + StackTraceElementProxy[] stackTraceElementProxyArray; + int commonFrames; + ThrowableProxy cause; + + private transient PackagingDataCalculator packagingDataCalculator; + private boolean calculatedPackageData = false; + + public ThrowableProxy(Throwable throwable) { + + this.throwable = throwable; + this.className = throwable.getClass().getName(); + this.message = throwable.getMessage(); + this.stackTraceElementProxyArray = ThrowableProxyUtil.steArrayToStepArray(throwable + .getStackTrace()); + + Throwable nested = throwable.getCause(); + + if (nested != null) { + this.cause = new ThrowableProxy(nested); + this.cause.commonFrames = ThrowableProxyUtil + .findNumberOfCommonFrames(nested.getStackTrace(), + stackTraceElementProxyArray); + } + } + + + public Throwable getThrowable() { + return throwable; + } + + public String getMessage() { + return message; + } + + /* + * (non-Javadoc) + * + * @see ch.qos.logback.classic.spi.IThrowableProxy#getClassName() + */ + public String getClassName() { + return className; + } + + public StackTraceElementProxy[] getStackTraceElementProxyArray() { + return stackTraceElementProxyArray; + } + + public int getCommonFrames() { + return commonFrames; + } + + /* + * (non-Javadoc) + * + * @see ch.qos.logback.classic.spi.IThrowableProxy#getCause() + */ + public IThrowableProxy getCause() { + return cause; + } + + public PackagingDataCalculator getPackagingDataCalculator() { + // if original instance (non-deserialized), and packagingDataCalculator + // is not already initialized, then create an instance. + // here we assume that (throwable == null) for deserialized instances + if (throwable != null && packagingDataCalculator == null) { + packagingDataCalculator = new PackagingDataCalculator(); + } + return packagingDataCalculator; + } + + public void calculatePackagingData() { + if (calculatedPackageData) { + return; + } + PackagingDataCalculator pdc = this.getPackagingDataCalculator(); + if (pdc != null) { + calculatedPackageData = true; + pdc.calculate(this); + } + } + + + + public void fullDump() { + StringBuilder builder = new StringBuilder(); + for (StackTraceElementProxy step : stackTraceElementProxyArray) { + String string = step.toString(); + builder.append(CoreConstants.TAB).append(string); + ThrowableProxyUtil.appendPackagingData(builder, step); + builder.append(CoreConstants.LINE_SEPARATOR); + } + System.out.println(builder.toString()); + } + + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxyUtil.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxyUtil.java index b1d690f6a8abb1428afdfb9aa88a61b392f84186..5b45359c6c783d4123b156ec1281aa0c5281279d 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxyUtil.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxyUtil.java @@ -1,130 +1,130 @@ -/** - * 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.classic.spi; - -import ch.qos.logback.core.CoreConstants; - -/** - * Convert a throwable into an array of ThrowableDataPoint objects. - * - * - * @author Ceki Gülcü - */ -public class ThrowableProxyUtil { - - static public void build(ThrowableProxy nestedTP, Throwable nestedThrowable, - ThrowableProxy parentTP) { - - StackTraceElement[] nestedSTE = nestedThrowable.getStackTrace(); - - int commonFramesCount = -1; - if (parentTP != null) { - commonFramesCount = findNumberOfCommonFrames(nestedSTE, parentTP - .getStackTraceElementProxyArray()); - } - - nestedTP.commonFrames = commonFramesCount; - nestedTP.stackTraceElementProxyArray = steArrayToStepArray(nestedSTE); - } - - static StackTraceElementProxy[] steArrayToStepArray(StackTraceElement[] stea) { - StackTraceElementProxy[] stepa = new StackTraceElementProxy[stea.length]; - for (int i = 0; i < stepa.length; i++) { - stepa[i] = new StackTraceElementProxy(stea[i]); - } - return stepa; - } - - static int findNumberOfCommonFrames(StackTraceElement[] steArray, - StackTraceElementProxy[] parentSTEPArray) { - if (parentSTEPArray == null) { - return 0; - } - - int steIndex = steArray.length - 1; - int parentIndex = parentSTEPArray.length - 1; - int count = 0; - while (steIndex >= 0 && parentIndex >= 0) { - StackTraceElement ste = steArray[steIndex]; - StackTraceElement otherSte = parentSTEPArray[parentIndex].ste; - if (ste.equals(otherSte)) { - count++; - } else { - break; - } - steIndex--; - parentIndex--; - } - return count; - } - - static public String asString(IThrowableProxy tp) { - StringBuilder sb = new StringBuilder(); - - while (tp != null) { - printFirstLine(sb, tp); - sb.append(CoreConstants.LINE_SEPARATOR); - printSTEPArray(sb, tp); - tp = tp.getCause(); - } - return sb.toString(); - } - - static void appendPackagingData(StringBuilder builder, StackTraceElementProxy step) { - if (step != null) { - ClassPackagingData cpd = step.getClassPackagingData(); - if (cpd != null) { - if (!cpd.isExact()) { - builder.append(" ~["); - } else { - builder.append(" ["); - } - - builder.append(cpd.getCodeLocation()).append(':').append( - cpd.getVersion()).append(']'); - } - } - } - - static public void printSTEP(StringBuilder sb, StackTraceElementProxy step) { - sb.append(step.toString()); - appendPackagingData(sb, step); - } - - static public void printSTEPArray(StringBuilder sb, IThrowableProxy tp) { - StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); - int commonFrames = tp.getCommonFrames(); - - for (int i = 0; i < stepArray.length - commonFrames; i++) { - StackTraceElementProxy step = stepArray[i]; - sb.append(CoreConstants.TAB); - printSTEP(sb, step); - sb.append(CoreConstants.LINE_SEPARATOR); - } - - if (commonFrames > 0) { - sb.append("\t... " + commonFrames).append(" common frames omitted") - .append(CoreConstants.LINE_SEPARATOR); - } - - } - - static public void printFirstLine(StringBuilder buf, IThrowableProxy tp) { - int commonFrames = tp.getCommonFrames(); - if (commonFrames > 0) { - buf.append(CoreConstants.CAUSED_BY); - } - buf.append(tp.getClassName()).append(": ").append(tp.getMessage()); - } -} +/** + * 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.classic.spi; + +import ch.qos.logback.core.CoreConstants; + +/** + * Convert a throwable into an array of ThrowableDataPoint objects. + * + * + * @author Ceki Gülcü + */ +public class ThrowableProxyUtil { + + static public void build(ThrowableProxy nestedTP, Throwable nestedThrowable, + ThrowableProxy parentTP) { + + StackTraceElement[] nestedSTE = nestedThrowable.getStackTrace(); + + int commonFramesCount = -1; + if (parentTP != null) { + commonFramesCount = findNumberOfCommonFrames(nestedSTE, parentTP + .getStackTraceElementProxyArray()); + } + + nestedTP.commonFrames = commonFramesCount; + nestedTP.stackTraceElementProxyArray = steArrayToStepArray(nestedSTE); + } + + static StackTraceElementProxy[] steArrayToStepArray(StackTraceElement[] stea) { + StackTraceElementProxy[] stepa = new StackTraceElementProxy[stea.length]; + for (int i = 0; i < stepa.length; i++) { + stepa[i] = new StackTraceElementProxy(stea[i]); + } + return stepa; + } + + static int findNumberOfCommonFrames(StackTraceElement[] steArray, + StackTraceElementProxy[] parentSTEPArray) { + if (parentSTEPArray == null) { + return 0; + } + + int steIndex = steArray.length - 1; + int parentIndex = parentSTEPArray.length - 1; + int count = 0; + while (steIndex >= 0 && parentIndex >= 0) { + StackTraceElement ste = steArray[steIndex]; + StackTraceElement otherSte = parentSTEPArray[parentIndex].ste; + if (ste.equals(otherSte)) { + count++; + } else { + break; + } + steIndex--; + parentIndex--; + } + return count; + } + + static public String asString(IThrowableProxy tp) { + StringBuilder sb = new StringBuilder(); + + while (tp != null) { + printFirstLine(sb, tp); + sb.append(CoreConstants.LINE_SEPARATOR); + printSTEPArray(sb, tp); + tp = tp.getCause(); + } + return sb.toString(); + } + + static void appendPackagingData(StringBuilder builder, StackTraceElementProxy step) { + if (step != null) { + ClassPackagingData cpd = step.getClassPackagingData(); + if (cpd != null) { + if (!cpd.isExact()) { + builder.append(" ~["); + } else { + builder.append(" ["); + } + + builder.append(cpd.getCodeLocation()).append(':').append( + cpd.getVersion()).append(']'); + } + } + } + + static public void printSTEP(StringBuilder sb, StackTraceElementProxy step) { + sb.append(step.toString()); + appendPackagingData(sb, step); + } + + static public void printSTEPArray(StringBuilder sb, IThrowableProxy tp) { + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + int commonFrames = tp.getCommonFrames(); + + for (int i = 0; i < stepArray.length - commonFrames; i++) { + StackTraceElementProxy step = stepArray[i]; + sb.append(CoreConstants.TAB); + printSTEP(sb, step); + sb.append(CoreConstants.LINE_SEPARATOR); + } + + if (commonFrames > 0) { + sb.append("\t... " + commonFrames).append(" common frames omitted") + .append(CoreConstants.LINE_SEPARATOR); + } + + } + + static public void printFirstLine(StringBuilder buf, IThrowableProxy tp) { + int commonFrames = tp.getCommonFrames(); + if (commonFrames > 0) { + buf.append(CoreConstants.CAUSED_BY); + } + buf.append(tp.getClassName()).append(": ").append(tp.getMessage()); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxyVO.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxyVO.java index 67c23f0878e5c1f3368531e95152031d010b4e67..f77560275fcbb28458d25dc2660fd97ecd52724b 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxyVO.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxyVO.java @@ -1,101 +1,101 @@ -/** - * 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.classic.spi; - -import java.io.Serializable; -import java.util.Arrays; - -public class ThrowableProxyVO implements IThrowableProxy, Serializable { - - private static final long serialVersionUID = 685387990886325422L; - - private String className; - private String message; - private int commonFramesCount; - private StackTraceElementProxy[] stackTraceElementProxyArray; - private IThrowableProxy cause; - - - public String getMessage() { - return message; - } - - public String getClassName() { - return className; - } - - public int getCommonFrames() { - return commonFramesCount; - } - - public IThrowableProxy getCause() { - return cause; - } - - public StackTraceElementProxy[] getStackTraceElementProxyArray() { - return stackTraceElementProxyArray; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((className == null) ? 0 : className.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final ThrowableProxyVO other = (ThrowableProxyVO) obj; - - if (className == null) { - if (other.className != null) - return false; - } else if (!className.equals(other.className)) - return false; - - if (!Arrays.equals(stackTraceElementProxyArray, other.stackTraceElementProxyArray)) - return false; - - if (cause == null) { - if (other.cause != null) - return false; - } else if (!cause.equals(other.cause)) - return false; - - return true; - } - - public static ThrowableProxyVO build(IThrowableProxy throwableProxy) { - if(throwableProxy == null) { - return null; - } - ThrowableProxyVO tpvo = new ThrowableProxyVO(); - tpvo.className = throwableProxy.getClassName(); - tpvo.message = throwableProxy.getMessage(); - tpvo.commonFramesCount = throwableProxy.getCommonFrames(); - tpvo.stackTraceElementProxyArray = throwableProxy.getStackTraceElementProxyArray(); - if(throwableProxy.getCause() != null) { - tpvo.cause = ThrowableProxyVO.build(throwableProxy.getCause()); - } - return tpvo; - } -} +/** + * 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.classic.spi; + +import java.io.Serializable; +import java.util.Arrays; + +public class ThrowableProxyVO implements IThrowableProxy, Serializable { + + private static final long serialVersionUID = 685387990886325422L; + + private String className; + private String message; + private int commonFramesCount; + private StackTraceElementProxy[] stackTraceElementProxyArray; + private IThrowableProxy cause; + + + public String getMessage() { + return message; + } + + public String getClassName() { + return className; + } + + public int getCommonFrames() { + return commonFramesCount; + } + + public IThrowableProxy getCause() { + return cause; + } + + public StackTraceElementProxy[] getStackTraceElementProxyArray() { + return stackTraceElementProxyArray; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((className == null) ? 0 : className.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final ThrowableProxyVO other = (ThrowableProxyVO) obj; + + if (className == null) { + if (other.className != null) + return false; + } else if (!className.equals(other.className)) + return false; + + if (!Arrays.equals(stackTraceElementProxyArray, other.stackTraceElementProxyArray)) + return false; + + if (cause == null) { + if (other.cause != null) + return false; + } else if (!cause.equals(other.cause)) + return false; + + return true; + } + + public static ThrowableProxyVO build(IThrowableProxy throwableProxy) { + if(throwableProxy == null) { + return null; + } + ThrowableProxyVO tpvo = new ThrowableProxyVO(); + tpvo.className = throwableProxy.getClassName(); + tpvo.message = throwableProxy.getMessage(); + tpvo.commonFramesCount = throwableProxy.getCommonFrames(); + tpvo.stackTraceElementProxyArray = throwableProxy.getStackTraceElementProxyArray(); + if(throwableProxy.getCause() != null) { + tpvo.cause = ThrowableProxyVO.build(throwableProxy.getCause()); + } + return tpvo; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterList.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterList.java index ef81f4414f12d139483e2a27237175192bb83741..d104ff47d67aa5215b1ddd514be4f204c4becb28 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterList.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterList.java @@ -1,82 +1,82 @@ -/** - * 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.classic.spi; - -import java.util.concurrent.CopyOnWriteArrayList; - -import org.slf4j.Marker; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.turbo.TurboFilter; -import ch.qos.logback.core.spi.FilterReply; - -/** - * Implementation of TurboFilterAttachable. - * - * @author Ceki Gülcü - */ -final public class TurboFilterList extends CopyOnWriteArrayList { - - private static final long serialVersionUID = 1L; - - /** - * Loop through the filters in the chain. As soon as a filter decides on - * ACCEPT or DENY, then that value is returned. If all of the filters return - * NEUTRAL, then NEUTRAL is returned. - */ - public final FilterReply getTurboFilterChainDecision(final Marker marker, - final Logger logger, final Level level, final String format, - final Object[] params, final Throwable t) { - - - final int size = size(); -// if (size == 0) { -// return FilterReply.NEUTRAL; -// } - if (size == 1) { - try { - TurboFilter tf = get(0); - return tf.decide(marker, logger, level, format, params, t); - } catch (IndexOutOfBoundsException iobe) { - return FilterReply.NEUTRAL; - } - } - - Object[] tfa = toArray(); - final int len = tfa.length; - for (int i = 0; i < len; i++) { - //for (TurboFilter tf : this) { - final TurboFilter tf = (TurboFilter) tfa[i]; - final FilterReply r = tf.decide(marker, logger, level, format, params, t); - if (r == FilterReply.DENY || r == FilterReply.ACCEPT) { - return r; - } - } - return FilterReply.NEUTRAL; - } - - // public boolean remove(TurboFilter turboFilter) { - // return tfList.remove(turboFilter); - // } - // - // public TurboFilter remove(int index) { - // return tfList.remove(index); - // } - // - // final public int size() { - // return tfList.size(); - // } - -} +/** + * 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.classic.spi; + +import java.util.concurrent.CopyOnWriteArrayList; + +import org.slf4j.Marker; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.turbo.TurboFilter; +import ch.qos.logback.core.spi.FilterReply; + +/** + * Implementation of TurboFilterAttachable. + * + * @author Ceki Gülcü + */ +final public class TurboFilterList extends CopyOnWriteArrayList { + + private static final long serialVersionUID = 1L; + + /** + * Loop through the filters in the chain. As soon as a filter decides on + * ACCEPT or DENY, then that value is returned. If all of the filters return + * NEUTRAL, then NEUTRAL is returned. + */ + public final FilterReply getTurboFilterChainDecision(final Marker marker, + final Logger logger, final Level level, final String format, + final Object[] params, final Throwable t) { + + + final int size = size(); +// if (size == 0) { +// return FilterReply.NEUTRAL; +// } + if (size == 1) { + try { + TurboFilter tf = get(0); + return tf.decide(marker, logger, level, format, params, t); + } catch (IndexOutOfBoundsException iobe) { + return FilterReply.NEUTRAL; + } + } + + Object[] tfa = toArray(); + final int len = tfa.length; + for (int i = 0; i < len; i++) { + //for (TurboFilter tf : this) { + final TurboFilter tf = (TurboFilter) tfa[i]; + final FilterReply r = tf.decide(marker, logger, level, format, params, t); + if (r == FilterReply.DENY || r == FilterReply.ACCEPT) { + return r; + } + } + return FilterReply.NEUTRAL; + } + + // public boolean remove(TurboFilter turboFilter) { + // return tfList.remove(turboFilter); + // } + // + // public TurboFilter remove(int index) { + // return tfList.remove(index); + // } + // + // final public int size() { + // return tfList.size(); + // } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/package.html b/logback-classic/src/main/java/ch/qos/logback/classic/spi/package.html index f869e52013c88089e9641a068a1182a3fa185666..460c189441ccc7b520cccbce86935e119422cdc0 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/package.html +++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains core classes of logback classic.

- - + + + + + + + + + +

Contains core classes of logback classic.

+ + \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java index 8393f6719466621d13db6895f2c3b0c920813679..939a7d3e53261972f7adcf9a4b5ed5f5e50206da 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java @@ -1,91 +1,91 @@ -/** - * 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.classic.turbo; - -import org.slf4j.Marker; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.core.spi.FilterReply; - -/** - * - * See {@link http://logback.qos.ch/manual/filters.html#DuplicateMessageFilter} - * for details. - * - * @author Ceki Gulcu - * - */ -public class DuplicateMessageFilter extends TurboFilter { - - /** - * The default cache size. - */ - public static final int DEFAULT_CACHE_SIZE = 100; - /** - * The default number of allows repetitions. - */ - public static final int DEFAULT_ALLOWED_REPETITIONS = 5; - - public int allowedRepetitions = DEFAULT_ALLOWED_REPETITIONS; - public int cacheSize = DEFAULT_CACHE_SIZE; - - private LRUMessageCache msgCache; - - @Override - public void start() { - msgCache = new LRUMessageCache(cacheSize); - super.start(); - } - - @Override - public void stop() { - msgCache.clear(); - msgCache = null; - super.stop(); - } - - @Override - public FilterReply decide(Marker marker, Logger logger, Level level, - String format, Object[] params, Throwable t) { - int count = msgCache.getMessageCountAndThenIncrement(format); - if (count <= allowedRepetitions) { - return FilterReply.NEUTRAL; - } else { - return FilterReply.DENY; - } - } - - public int getAllowedRepetitions() { - return allowedRepetitions; - } - - /** - * The allowed number of repetitions before - * - * @param allowedRepetitions - */ - public void setAllowedRepetitions(int allowedRepetitions) { - this.allowedRepetitions = allowedRepetitions; - } - - public int getCacheSize() { - return cacheSize; - } - - public void setCacheSize(int cacheSize) { - this.cacheSize = cacheSize; - } - -} +/** + * 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.classic.turbo; + +import org.slf4j.Marker; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.spi.FilterReply; + +/** + * + * See {@link http://logback.qos.ch/manual/filters.html#DuplicateMessageFilter} + * for details. + * + * @author Ceki Gulcu + * + */ +public class DuplicateMessageFilter extends TurboFilter { + + /** + * The default cache size. + */ + public static final int DEFAULT_CACHE_SIZE = 100; + /** + * The default number of allows repetitions. + */ + public static final int DEFAULT_ALLOWED_REPETITIONS = 5; + + public int allowedRepetitions = DEFAULT_ALLOWED_REPETITIONS; + public int cacheSize = DEFAULT_CACHE_SIZE; + + private LRUMessageCache msgCache; + + @Override + public void start() { + msgCache = new LRUMessageCache(cacheSize); + super.start(); + } + + @Override + public void stop() { + msgCache.clear(); + msgCache = null; + super.stop(); + } + + @Override + public FilterReply decide(Marker marker, Logger logger, Level level, + String format, Object[] params, Throwable t) { + int count = msgCache.getMessageCountAndThenIncrement(format); + if (count <= allowedRepetitions) { + return FilterReply.NEUTRAL; + } else { + return FilterReply.DENY; + } + } + + public int getAllowedRepetitions() { + return allowedRepetitions; + } + + /** + * The allowed number of repetitions before + * + * @param allowedRepetitions + */ + public void setAllowedRepetitions(int allowedRepetitions) { + this.allowedRepetitions = allowedRepetitions; + } + + public int getCacheSize() { + return cacheSize; + } + + public void setCacheSize(int cacheSize) { + this.cacheSize = cacheSize; + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DynamicThresholdFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DynamicThresholdFilter.java index 57bb4c345b17af96fa9560f42e431b56b6f6a127..eb617028cdacd3c9ff001f17da7d8f2464e22d6d 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DynamicThresholdFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DynamicThresholdFilter.java @@ -1,257 +1,257 @@ -/** - * 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.classic.turbo; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.Level; -import ch.qos.logback.core.spi.FilterReply; -import org.slf4j.Marker; -import org.slf4j.MDC; - -import java.util.Map; -import java.util.HashMap; - -/** - * This filter allows for efficient course grained filtering based on criteria - * such as product name or company name that would be associated with requests - * as they are processed. - * - *

This filter will allow you to associate threshold levels to a key put in - * the MDC. This key can be any value specified by the user. Furthermore, you - * can pass MDC value and level threshold associations, which are then looked up - * to find the level threshold to apply to the current logging request. If no - * level threshold could be found, then a 'default' value specified by the user - * is applied. We call this value 'levelAssociatedWithMDCValue'. - * - *

If 'levelAssociatedWithMDCValue' is higher or equal to the level of the - * current logger request, the - * {@link #decide(Marker, Logger, Level, String, Object[], Throwable) decide()} - * method returns the value of {@link #getOnHigherOrEqual() onHigherOrEqual}, - * if it is lower then the value of {@link #getOnLower() onLower} is returned. - * Both 'onHigherOrEqual' and 'onLower' can be set by the user. By default, - * 'onHigherOrEqual' is set to NEUTRAL and 'onLower' is set to DENY. Thus, if - * the current logger request's level is lower than - * 'levelAssociatedWithMDCValue', then the request is denied, and if it is - * higher or equal, then this filter decides NEUTRAL letting subsequent filters - * to make the decision on the fate of the logging request. - * - *

The example below illustrates how logging could be enabled for only - * individual users. In this example all events for logger names matching - * "com.mycompany" will be logged if they are for 'user1' and at a level higher - * than equals to DEBUG, and for 'user2' if they are at a level higher than or - * equal to TRACE, and for other users only if they are at level ERROR or - * higher. Events issued by loggers other than "com.mycompany" will only be - * logged if they are at level ERROR or higher since that is all the root logger - * allows. - * - *

- * <configuration>
- *   <appender name="STDOUT"
- *             class="ch.qos.logback.core.ConsoleAppender">
- *     <layout class="ch.qos.logback.classic.PatternLayout">
- *       <Pattern>TEST %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
- *     </layout>
- *   </appender>
- *   
- *   <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
- *     <Key>userId</Key>
- *     <DefaultTheshold>ERROR</DefaultTheshold>
- *     <MDCValueLevelPair>
- *       <value>user1</value>
- *       <level>DEBUG</level>
- *     </MDCValueLevelPair>
- *     <MDCValueLevelPair>
- *       <value>user2</value>
- *       <level>TRACE</level>
- *     </MDCValueLevelPair>
- *   </turboFilter>
- *   
- *   <logger name="com.mycompany" level="TRACE"/>
- *   
- *   <root level="ERROR" >
- *     <appender-ref ref="STDOUT" />
- *   </root>
- * </configuration>
- * 
- * - * In the next configuration events from user1 and user2 will be logged - * regardless of the logger levels. Events for other users and records without a - * userid in the MDC will be logged if they are ERROR level messages. With this - * configuration, the root level is never checked since DynamicThresholdFilter - * will either accept or deny all records. - * - *
- * <configuration>
- *   <appender name="STDOUT"
- *             class="ch.qos.logback.core.ConsoleAppender">
- *     <layout class="ch.qos.logback.classic.PatternLayout">
- *        <Pattern>TEST %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
- *     </layout>
- *   </appender>
- *   
- *   <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
- *     <Key>userId</Key>
- *     <DefaultTheshold>ERROR</DefaultTheshold>
- *     <OnHigherOrEqual>ACCEPT</OnHigherOrEqual>
- *     <OnLower>DENY</OnLower>
- *     <MDCValueLevelPair>
- *       <value>user1</value>
- *       <level>TRACE</level>
- *     </MDCValueLevelPair>
- *     <MDCValueLevelPair>
- *       <value>user2</value>
- *       <level>TRACE</level>
- *     </MDCValueLevelPair>
- *   </turboFilter>
- *   
- *   <root level="DEBUG" >
- *     <appender-ref ref="STDOUT" />
- *   </root>
- * </configuration>
- * 
- * - * @author Raplh Goers - * @author Ceki Gülcü - */ -public class DynamicThresholdFilter extends TurboFilter { - private Map valueLevelMap = new HashMap(); - private Level defaultThreshold = Level.ERROR; - private String key; - - private FilterReply onHigherOrEqual = FilterReply.NEUTRAL; - private FilterReply onLower = FilterReply.DENY; - - /** - * Get the MDC key whose value will be used as a level threshold - * - * @return the name of the MDC key. - */ - public String getKey() { - return this.key; - } - - /** - * @see setKey - */ - public void setKey(String key) { - this.key = key; - } - - /** - * Get the default threshold value when the MDC key is not set. - * - * @return the default threshold value in the absence of a set MDC key - */ - public Level getDefaultThreshold() { - return defaultThreshold; - } - - public void setDefaultThreshold(Level defaultThreshold) { - this.defaultThreshold = defaultThreshold; - } - - /** - * Get the FilterReply when the effective level is higher or equal to the - * level of current logging request - * - * @return FilterReply - */ - public FilterReply getOnHigherOrEqual() { - return onHigherOrEqual; - } - - public void setOnHigherOrEqual(FilterReply onHigherOrEqual) { - this.onHigherOrEqual = onHigherOrEqual; - } - - /** - * Get the FilterReply when the effective level is lower than the level of - * current logging request - * - * @return FilterReply - */ - public FilterReply getOnLower() { - return onLower; - } - - public void setOnLower(FilterReply onLower) { - this.onLower = onLower; - } - - /** - * Add a new MDCValuePair - */ - public void addMDCValueLevelPair(MDCValueLevelPair mdcValueLevelPair) { - if (valueLevelMap.containsKey(mdcValueLevelPair.getValue())) { - addError(mdcValueLevelPair.getValue() + " has been already set"); - } else { - valueLevelMap.put(mdcValueLevelPair.getValue(), mdcValueLevelPair - .getLevel()); - } - } - - /** - * - */ - @Override - public void start() { - if (this.key == null) { - addError("No key name was specified"); - } - super.start(); - } - - /** - * This method first finds the MDC value for 'key'. It then finds the level - * threshold associated with this MDC value from the list of MDCValueLevelPair - * passed to this filter. This value is stored in a variable called - * 'levelAssociatedWithMDCValue'. If it null, then it is set to the - * - * @{link #defaultThreshold} value. - * - * If no such value exists, then - * - * - * @param marker - * @param logger - * @param level - * @param s - * @param objects - * @param throwable - * - * @return FilterReply - this filter's decision - */ - @Override - public FilterReply decide(Marker marker, Logger logger, Level level, - String s, Object[] objects, Throwable throwable) { - - String mdcValue = MDC.get(this.key); - if (!isStarted()) { - return FilterReply.NEUTRAL; - } - - Level levelAssociatedWithMDCValue = null; - if (mdcValue != null) { - levelAssociatedWithMDCValue = valueLevelMap.get(mdcValue); - } - if (levelAssociatedWithMDCValue == null) { - levelAssociatedWithMDCValue = defaultThreshold; - } - if (level.isGreaterOrEqual(levelAssociatedWithMDCValue)) { - return onHigherOrEqual; - } else { - return onLower; - } - } -} +/** + * 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.classic.turbo; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.Level; +import ch.qos.logback.core.spi.FilterReply; +import org.slf4j.Marker; +import org.slf4j.MDC; + +import java.util.Map; +import java.util.HashMap; + +/** + * This filter allows for efficient course grained filtering based on criteria + * such as product name or company name that would be associated with requests + * as they are processed. + * + *

This filter will allow you to associate threshold levels to a key put in + * the MDC. This key can be any value specified by the user. Furthermore, you + * can pass MDC value and level threshold associations, which are then looked up + * to find the level threshold to apply to the current logging request. If no + * level threshold could be found, then a 'default' value specified by the user + * is applied. We call this value 'levelAssociatedWithMDCValue'. + * + *

If 'levelAssociatedWithMDCValue' is higher or equal to the level of the + * current logger request, the + * {@link #decide(Marker, Logger, Level, String, Object[], Throwable) decide()} + * method returns the value of {@link #getOnHigherOrEqual() onHigherOrEqual}, + * if it is lower then the value of {@link #getOnLower() onLower} is returned. + * Both 'onHigherOrEqual' and 'onLower' can be set by the user. By default, + * 'onHigherOrEqual' is set to NEUTRAL and 'onLower' is set to DENY. Thus, if + * the current logger request's level is lower than + * 'levelAssociatedWithMDCValue', then the request is denied, and if it is + * higher or equal, then this filter decides NEUTRAL letting subsequent filters + * to make the decision on the fate of the logging request. + * + *

The example below illustrates how logging could be enabled for only + * individual users. In this example all events for logger names matching + * "com.mycompany" will be logged if they are for 'user1' and at a level higher + * than equals to DEBUG, and for 'user2' if they are at a level higher than or + * equal to TRACE, and for other users only if they are at level ERROR or + * higher. Events issued by loggers other than "com.mycompany" will only be + * logged if they are at level ERROR or higher since that is all the root logger + * allows. + * + *

+ * <configuration>
+ *   <appender name="STDOUT"
+ *             class="ch.qos.logback.core.ConsoleAppender">
+ *     <layout class="ch.qos.logback.classic.PatternLayout">
+ *       <Pattern>TEST %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+ *     </layout>
+ *   </appender>
+ *   
+ *   <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
+ *     <Key>userId</Key>
+ *     <DefaultTheshold>ERROR</DefaultTheshold>
+ *     <MDCValueLevelPair>
+ *       <value>user1</value>
+ *       <level>DEBUG</level>
+ *     </MDCValueLevelPair>
+ *     <MDCValueLevelPair>
+ *       <value>user2</value>
+ *       <level>TRACE</level>
+ *     </MDCValueLevelPair>
+ *   </turboFilter>
+ *   
+ *   <logger name="com.mycompany" level="TRACE"/>
+ *   
+ *   <root level="ERROR" >
+ *     <appender-ref ref="STDOUT" />
+ *   </root>
+ * </configuration>
+ * 
+ * + * In the next configuration events from user1 and user2 will be logged + * regardless of the logger levels. Events for other users and records without a + * userid in the MDC will be logged if they are ERROR level messages. With this + * configuration, the root level is never checked since DynamicThresholdFilter + * will either accept or deny all records. + * + *
+ * <configuration>
+ *   <appender name="STDOUT"
+ *             class="ch.qos.logback.core.ConsoleAppender">
+ *     <layout class="ch.qos.logback.classic.PatternLayout">
+ *        <Pattern>TEST %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+ *     </layout>
+ *   </appender>
+ *   
+ *   <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
+ *     <Key>userId</Key>
+ *     <DefaultTheshold>ERROR</DefaultTheshold>
+ *     <OnHigherOrEqual>ACCEPT</OnHigherOrEqual>
+ *     <OnLower>DENY</OnLower>
+ *     <MDCValueLevelPair>
+ *       <value>user1</value>
+ *       <level>TRACE</level>
+ *     </MDCValueLevelPair>
+ *     <MDCValueLevelPair>
+ *       <value>user2</value>
+ *       <level>TRACE</level>
+ *     </MDCValueLevelPair>
+ *   </turboFilter>
+ *   
+ *   <root level="DEBUG" >
+ *     <appender-ref ref="STDOUT" />
+ *   </root>
+ * </configuration>
+ * 
+ * + * @author Raplh Goers + * @author Ceki Gülcü + */ +public class DynamicThresholdFilter extends TurboFilter { + private Map valueLevelMap = new HashMap(); + private Level defaultThreshold = Level.ERROR; + private String key; + + private FilterReply onHigherOrEqual = FilterReply.NEUTRAL; + private FilterReply onLower = FilterReply.DENY; + + /** + * Get the MDC key whose value will be used as a level threshold + * + * @return the name of the MDC key. + */ + public String getKey() { + return this.key; + } + + /** + * @see setKey + */ + public void setKey(String key) { + this.key = key; + } + + /** + * Get the default threshold value when the MDC key is not set. + * + * @return the default threshold value in the absence of a set MDC key + */ + public Level getDefaultThreshold() { + return defaultThreshold; + } + + public void setDefaultThreshold(Level defaultThreshold) { + this.defaultThreshold = defaultThreshold; + } + + /** + * Get the FilterReply when the effective level is higher or equal to the + * level of current logging request + * + * @return FilterReply + */ + public FilterReply getOnHigherOrEqual() { + return onHigherOrEqual; + } + + public void setOnHigherOrEqual(FilterReply onHigherOrEqual) { + this.onHigherOrEqual = onHigherOrEqual; + } + + /** + * Get the FilterReply when the effective level is lower than the level of + * current logging request + * + * @return FilterReply + */ + public FilterReply getOnLower() { + return onLower; + } + + public void setOnLower(FilterReply onLower) { + this.onLower = onLower; + } + + /** + * Add a new MDCValuePair + */ + public void addMDCValueLevelPair(MDCValueLevelPair mdcValueLevelPair) { + if (valueLevelMap.containsKey(mdcValueLevelPair.getValue())) { + addError(mdcValueLevelPair.getValue() + " has been already set"); + } else { + valueLevelMap.put(mdcValueLevelPair.getValue(), mdcValueLevelPair + .getLevel()); + } + } + + /** + * + */ + @Override + public void start() { + if (this.key == null) { + addError("No key name was specified"); + } + super.start(); + } + + /** + * This method first finds the MDC value for 'key'. It then finds the level + * threshold associated with this MDC value from the list of MDCValueLevelPair + * passed to this filter. This value is stored in a variable called + * 'levelAssociatedWithMDCValue'. If it null, then it is set to the + * + * @{link #defaultThreshold} value. + * + * If no such value exists, then + * + * + * @param marker + * @param logger + * @param level + * @param s + * @param objects + * @param throwable + * + * @return FilterReply - this filter's decision + */ + @Override + public FilterReply decide(Marker marker, Logger logger, Level level, + String s, Object[] objects, Throwable throwable) { + + String mdcValue = MDC.get(this.key); + if (!isStarted()) { + return FilterReply.NEUTRAL; + } + + Level levelAssociatedWithMDCValue = null; + if (mdcValue != null) { + levelAssociatedWithMDCValue = valueLevelMap.get(mdcValue); + } + if (levelAssociatedWithMDCValue == null) { + levelAssociatedWithMDCValue = defaultThreshold; + } + if (level.isGreaterOrEqual(levelAssociatedWithMDCValue)) { + return onHigherOrEqual; + } else { + return onLower; + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java index c71d1b126ff8fb7d0d86b25b7c4ba65565ffa3b5..90cd274364ba57f45e979a4c7602d52e46909f0a 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java @@ -1,54 +1,54 @@ -/** - * 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.classic.turbo; - -import java.util.LinkedHashMap; -import java.util.Map; - -class LRUMessageCache extends LinkedHashMap { - - // LinkedHashMap permits null elements to be inserted - - private static final long serialVersionUID = 1L; - - final int cacheSize; - - LRUMessageCache(int cacheSize) { - super((int) (cacheSize * (4.0f / 3)), 0.75f, true); - if (cacheSize < 1) { - throw new IllegalArgumentException("Cache size cannnot be smaller than 1"); - } - this.cacheSize = cacheSize; - } - - int getMessageCountAndThenIncrement(String msg) { - // don't insert null elements - if(msg == null) { - return 0; - } - - Integer i = super.get(msg); - if(i == null) { - i = 0; - } else { - i = new Integer(i.intValue()+1); - } - super.put(msg, i); - return i; - } - - protected boolean removeEldestEntry(Map.Entry eldest) { - return (size() > cacheSize); - } -} +/** + * 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.classic.turbo; + +import java.util.LinkedHashMap; +import java.util.Map; + +class LRUMessageCache extends LinkedHashMap { + + // LinkedHashMap permits null elements to be inserted + + private static final long serialVersionUID = 1L; + + final int cacheSize; + + LRUMessageCache(int cacheSize) { + super((int) (cacheSize * (4.0f / 3)), 0.75f, true); + if (cacheSize < 1) { + throw new IllegalArgumentException("Cache size cannnot be smaller than 1"); + } + this.cacheSize = cacheSize; + } + + int getMessageCountAndThenIncrement(String msg) { + // don't insert null elements + if(msg == null) { + return 0; + } + + Integer i = super.get(msg); + if(i == null) { + i = 0; + } else { + i = new Integer(i.intValue()+1); + } + super.put(msg, i); + return i; + } + + protected boolean removeEldestEntry(Map.Entry eldest) { + return (size() > cacheSize); + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MDCFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MDCFilter.java index d14461381b7d6b47292147bd52b89d7bcbe53b80..111db11f40006ea605a856bbf5404bdbc5004e64 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MDCFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MDCFilter.java @@ -1,72 +1,72 @@ -/** - * 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.classic.turbo; - -import org.slf4j.MDC; -import org.slf4j.Marker; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.core.spi.FilterReply; - -/** - * This class allows output for a given MDC value. - * - *

- * When the given value is identified by this TubroFilter, - * the reply is based on the OnMatch option. - * The information is taken from the MDC. For this TurboFilter to work, - * one must set the key that will be used to - * access the information in the MDC. - * - *

- * To allow output for the value, set the OnMatch option - * to ACCEPT. To disable output for the given value, set - * the OnMatch option to DENY. - * - *

- * By default, values of the OnMatch and OnMisMatch - * options are set to NEUTRAL. - * - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class MDCFilter extends MatchingFilter { - - String MDCKey; - String value; - - @Override - public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) { - if (MDCKey == null) { - return FilterReply.NEUTRAL; - } - - String value = MDC.get(MDCKey); - if (this.value.equals(value)) { - return onMatch; - } - return onMismatch; - } - - public void setValue(String value) { - this.value = value; - } - - public void setMDCKey(String MDCKey) { - this.MDCKey = MDCKey; - } - -} +/** + * 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.classic.turbo; + +import org.slf4j.MDC; +import org.slf4j.Marker; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.spi.FilterReply; + +/** + * This class allows output for a given MDC value. + * + *

+ * When the given value is identified by this TubroFilter, + * the reply is based on the OnMatch option. + * The information is taken from the MDC. For this TurboFilter to work, + * one must set the key that will be used to + * access the information in the MDC. + * + *

+ * To allow output for the value, set the OnMatch option + * to ACCEPT. To disable output for the given value, set + * the OnMatch option to DENY. + * + *

+ * By default, values of the OnMatch and OnMisMatch + * options are set to NEUTRAL. + * + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class MDCFilter extends MatchingFilter { + + String MDCKey; + String value; + + @Override + public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) { + if (MDCKey == null) { + return FilterReply.NEUTRAL; + } + + String value = MDC.get(MDCKey); + if (this.value.equals(value)) { + return onMatch; + } + return onMismatch; + } + + public void setValue(String value) { + this.value = value; + } + + public void setMDCKey(String MDCKey) { + this.MDCKey = MDCKey; + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MDCValueLevelPair.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MDCValueLevelPair.java index 737695c7e4ab363ee090b43c7755982cf2e7d2d3..df0d7efafb721245eb9e66e822a40aba0adba286 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MDCValueLevelPair.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MDCValueLevelPair.java @@ -1,44 +1,44 @@ -/** - * 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.classic.turbo; - -import ch.qos.logback.classic.Level; - - -/** - * Bean pairing an MDC value with a log level. - * - * @author Raplh Goers - * @author Ceki Gülcü - */ -public class MDCValueLevelPair { - private String value; - private Level level; - - public String getValue() { - return value; - } - - public void setValue(String name) { - this.value = name; - } - - public Level getLevel() { - return level; - } - - public void setLevel(Level level) { - this.level = level; - } -} +/** + * 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.classic.turbo; + +import ch.qos.logback.classic.Level; + + +/** + * Bean pairing an MDC value with a log level. + * + * @author Raplh Goers + * @author Ceki Gülcü + */ +public class MDCValueLevelPair { + private String value; + private Level level; + + public String getValue() { + return value; + } + + public void setValue(String name) { + this.value = name; + } + + public Level getLevel() { + return level; + } + + public void setLevel(Level level) { + this.level = level; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MarkerFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MarkerFilter.java index c12ec605b3cc8269b1b7652ed985da9334e653d2..8e133cb95597da73d9359cbf021e571b842a881e 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MarkerFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MarkerFilter.java @@ -1,67 +1,67 @@ -/** - * 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.classic.turbo; - -import org.slf4j.Marker; -import org.slf4j.MarkerFactory; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.core.spi.FilterReply; - -/** - * Checks whether the marker in the event matches the marker specified by the - * user. - */ -public class MarkerFilter extends MatchingFilter { - - Marker markerToMatch; - - @Override - public void start() { - if(markerToMatch != null) { - super.start(); - } else { - addError("The marker property must be set for ["+getName()+"]"); - } - } - - @Override - public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) { - if(!isStarted()) { - return FilterReply.NEUTRAL; - } - - if(marker == null) { - return onMismatch; - } - - if(markerToMatch.contains(marker)) { - return onMatch; - } else { - return onMismatch; - } - } - - /** - * The marker to match in the event. - * - * @param markerToMatch - */ - public void setMarker(String markerStr) { - if(markerStr != null) { - this.markerToMatch = MarkerFactory.getMarker(markerStr); - } - } -} +/** + * 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.classic.turbo; + +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.spi.FilterReply; + +/** + * Checks whether the marker in the event matches the marker specified by the + * user. + */ +public class MarkerFilter extends MatchingFilter { + + Marker markerToMatch; + + @Override + public void start() { + if(markerToMatch != null) { + super.start(); + } else { + addError("The marker property must be set for ["+getName()+"]"); + } + } + + @Override + public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) { + if(!isStarted()) { + return FilterReply.NEUTRAL; + } + + if(marker == null) { + return onMismatch; + } + + if(markerToMatch.contains(marker)) { + return onMatch; + } else { + return onMismatch; + } + } + + /** + * The marker to match in the event. + * + * @param markerToMatch + */ + public void setMarker(String markerStr) { + if(markerStr != null) { + this.markerToMatch = MarkerFactory.getMarker(markerStr); + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MatchingFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MatchingFilter.java index 154e545a79f5b142c0294a7bab231a2a9548dcdf..a4da3a96690f3a4d490e9345aebeb9e6205d47b3 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MatchingFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MatchingFilter.java @@ -1,48 +1,48 @@ -/** - * 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.classic.turbo; - -import ch.qos.logback.core.spi.FilterReply; - -/** - * An abstract class containing support for {@link #onMatch} on {@link #onMismatch} - * attributes, shared by many but not all tubo filters. - * - * @author Ceki Gulcu - */ -public abstract class MatchingFilter extends TurboFilter { - - protected FilterReply onMatch = FilterReply.NEUTRAL; - protected FilterReply onMismatch = FilterReply.NEUTRAL; - - final public void setOnMatch(String action) { - if ("NEUTRAL".equals(action)) { - onMatch = FilterReply.NEUTRAL; - } else if ("ACCEPT".equals(action)) { - onMatch = FilterReply.ACCEPT; - } else if ("DENY".equals(action)) { - onMatch = FilterReply.DENY; - } - } - - final public void setOnMismatch(String action) { - if ("NEUTRAL".equals(action)) { - onMismatch = FilterReply.NEUTRAL; - } else if ("ACCEPT".equals(action)) { - onMismatch = FilterReply.ACCEPT; - } else if ("DENY".equals(action)) { - onMismatch = FilterReply.DENY; - } - } -} +/** + * 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.classic.turbo; + +import ch.qos.logback.core.spi.FilterReply; + +/** + * An abstract class containing support for {@link #onMatch} on {@link #onMismatch} + * attributes, shared by many but not all tubo filters. + * + * @author Ceki Gulcu + */ +public abstract class MatchingFilter extends TurboFilter { + + protected FilterReply onMatch = FilterReply.NEUTRAL; + protected FilterReply onMismatch = FilterReply.NEUTRAL; + + final public void setOnMatch(String action) { + if ("NEUTRAL".equals(action)) { + onMatch = FilterReply.NEUTRAL; + } else if ("ACCEPT".equals(action)) { + onMatch = FilterReply.ACCEPT; + } else if ("DENY".equals(action)) { + onMatch = FilterReply.DENY; + } + } + + final public void setOnMismatch(String action) { + if ("NEUTRAL".equals(action)) { + onMismatch = FilterReply.NEUTRAL; + } else if ("ACCEPT".equals(action)) { + onMismatch = FilterReply.ACCEPT; + } else if ("DENY".equals(action)) { + onMismatch = FilterReply.DENY; + } + } +} 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 ce82a6fec676da836d0ca83250a7c4988f6af002..af5bc6a6cc8fc2e499526e694521f1cd45fb707a 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 @@ -1,170 +1,170 @@ -/** - * 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.classic.turbo; - -import java.io.File; -import java.net.URL; -import java.net.URLDecoder; - -import org.slf4j.Marker; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.spi.FilterReply; - -/** - * Reconfigure a LoggerContext when the configuration file changes. - * - * @author Ceki Gulcu - * - */ -public class ReconfigureOnChangeFilter extends TurboFilter { - - final static long INIT = System.currentTimeMillis(); - final static long SENTINEL = Long.MAX_VALUE; - - /** - * Scan for changes in configuration file once every minute. - */ - // 1 minute - value mentioned in documentation - public final static long DEFAULT_REFRESH_PERIOD = 60 * 1000; - - long refreshPeriod = DEFAULT_REFRESH_PERIOD; - File fileToScan; - protected long nextCheck; - long lastModified; - - @Override - public void start() { - URL url = (URL) context - .getObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN); - if (url != null) { - fileToScan = convertToFile(url); - if (fileToScan != null) { - synchronized (context.getConfigurationLock()) { - long inSeconds = refreshPeriod / 1000; - addInfo("Will scan for changes in file [" + fileToScan + "] every " - + inSeconds + " seconds. "); - lastModified = fileToScan.lastModified(); - updateNextCheck(System.currentTimeMillis()); - } - super.start(); - } - } else { - addError("Could not find URL of file to scan."); - } - } - - @SuppressWarnings("deprecation") - File convertToFile(URL url) { - String protocol = url.getProtocol(); - if ("file".equals(protocol)) { - File file = new File(URLDecoder.decode(url.getFile())); - return file; - } else { - addError("URL [" + url + "] is not of type file"); - return null; - } - } - - // The next fields counts the number of time the decide method is called - // - // IMPORTANT: This field can be updated by multiple threads. It follows that - // 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; - - @Override - public FilterReply decide(Marker marker, Logger logger, Level level, - String format, Object[] params, Throwable t) { - if (!isStarted()) { - return FilterReply.NEUTRAL; - } - - // for performance reasons, check for changes every 16 invocations - if (((invocationCounter++) & 0xF) != 0xF) { - return FilterReply.NEUTRAL; - } - - synchronized (context.getConfigurationLock()) { - boolean changed = changeDetected(); - if (changed) { - addInfo("Detected change in [" + fileToScan + "]"); - addInfo("Resetting and reconfiguring context [" + context.getName() - + "]"); - reconfigure(); - } - } - return FilterReply.NEUTRAL; - } - - void updateNextCheck(long now) { - nextCheck = now + refreshPeriod; - } - -// String stem() { -// return currentThreadName() + ", context " + context.getName() -// + ", nextCheck=" + (nextCheck - INIT); -// } - - // This method is synchronized to prevent near-simultaneous re-configurations - protected boolean changeDetected() { - long now = System.currentTimeMillis(); - if (now >= nextCheck) { - updateNextCheck(now); - return (lastModified != fileToScan.lastModified() && lastModified != SENTINEL); - } - return false; - } - - String currentThreadName() { - return Thread.currentThread().getName(); - } - - void disableSubsequentRecofiguration() { - lastModified = SENTINEL; - } - - protected void reconfigure() { - // Even though this method resets the loggerContext, which clears the list - // of turbo filters including this instance, it is still possible for this - // instance to be subsequently invoked by another thread if it was already - // executing when the context was reset. - // We prevent multiple reconfigurations (for the same file change event) by - // setting an appropriate sentinel value for lastMofidied field. - disableSubsequentRecofiguration(); - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(context); - LoggerContext lc = (LoggerContext) context; - lc.reset(); - try { - jc.doConfigure(fileToScan); - } catch (JoranException e) { - addError("Failure during reconfiguration", e); - } - } - - public long getRefreshPeriod() { - return refreshPeriod; - } - - public void setRefreshPeriod(long refreshPeriod) { - this.refreshPeriod = refreshPeriod; - } -} +/** + * 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.classic.turbo; + +import java.io.File; +import java.net.URL; +import java.net.URLDecoder; + +import org.slf4j.Marker; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.spi.FilterReply; + +/** + * Reconfigure a LoggerContext when the configuration file changes. + * + * @author Ceki Gulcu + * + */ +public class ReconfigureOnChangeFilter extends TurboFilter { + + final static long INIT = System.currentTimeMillis(); + final static long SENTINEL = Long.MAX_VALUE; + + /** + * Scan for changes in configuration file once every minute. + */ + // 1 minute - value mentioned in documentation + public final static long DEFAULT_REFRESH_PERIOD = 60 * 1000; + + long refreshPeriod = DEFAULT_REFRESH_PERIOD; + File fileToScan; + protected long nextCheck; + long lastModified; + + @Override + public void start() { + URL url = (URL) context + .getObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN); + if (url != null) { + fileToScan = convertToFile(url); + if (fileToScan != null) { + synchronized (context.getConfigurationLock()) { + long inSeconds = refreshPeriod / 1000; + addInfo("Will scan for changes in file [" + fileToScan + "] every " + + inSeconds + " seconds. "); + lastModified = fileToScan.lastModified(); + updateNextCheck(System.currentTimeMillis()); + } + super.start(); + } + } else { + addError("Could not find URL of file to scan."); + } + } + + @SuppressWarnings("deprecation") + File convertToFile(URL url) { + String protocol = url.getProtocol(); + if ("file".equals(protocol)) { + File file = new File(URLDecoder.decode(url.getFile())); + return file; + } else { + addError("URL [" + url + "] is not of type file"); + return null; + } + } + + // The next fields counts the number of time the decide method is called + // + // IMPORTANT: This field can be updated by multiple threads. It follows that + // 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; + + @Override + public FilterReply decide(Marker marker, Logger logger, Level level, + String format, Object[] params, Throwable t) { + if (!isStarted()) { + return FilterReply.NEUTRAL; + } + + // for performance reasons, check for changes every 16 invocations + if (((invocationCounter++) & 0xF) != 0xF) { + return FilterReply.NEUTRAL; + } + + synchronized (context.getConfigurationLock()) { + boolean changed = changeDetected(); + if (changed) { + addInfo("Detected change in [" + fileToScan + "]"); + addInfo("Resetting and reconfiguring context [" + context.getName() + + "]"); + reconfigure(); + } + } + return FilterReply.NEUTRAL; + } + + void updateNextCheck(long now) { + nextCheck = now + refreshPeriod; + } + +// String stem() { +// return currentThreadName() + ", context " + context.getName() +// + ", nextCheck=" + (nextCheck - INIT); +// } + + // This method is synchronized to prevent near-simultaneous re-configurations + protected boolean changeDetected() { + long now = System.currentTimeMillis(); + if (now >= nextCheck) { + updateNextCheck(now); + return (lastModified != fileToScan.lastModified() && lastModified != SENTINEL); + } + return false; + } + + String currentThreadName() { + return Thread.currentThread().getName(); + } + + void disableSubsequentRecofiguration() { + lastModified = SENTINEL; + } + + protected void reconfigure() { + // Even though this method resets the loggerContext, which clears the list + // of turbo filters including this instance, it is still possible for this + // instance to be subsequently invoked by another thread if it was already + // executing when the context was reset. + // We prevent multiple reconfigurations (for the same file change event) by + // setting an appropriate sentinel value for lastMofidied field. + disableSubsequentRecofiguration(); + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(context); + LoggerContext lc = (LoggerContext) context; + lc.reset(); + try { + jc.doConfigure(fileToScan); + } catch (JoranException e) { + addError("Failure during reconfiguration", e); + } + } + + public long getRefreshPeriod() { + return refreshPeriod; + } + + public void setRefreshPeriod(long refreshPeriod) { + this.refreshPeriod = refreshPeriod; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/TurboFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/TurboFilter.java index 471e43c8ca7337c481bf8f122cc318d7e4ee26d8..4e6757cc043639aadaa1155b14d86080dc0180aa 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/TurboFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/TurboFilter.java @@ -1,76 +1,76 @@ -/** - * 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.classic.turbo; - -import org.slf4j.Marker; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.spi.FilterReply; -import ch.qos.logback.core.spi.LifeCycle; - -/** - * TurboFilter is a specialized filter with a decide method that takes a bunch - * of parameters instead of a single event object. The latter is cleaner but - * the latter is much more performant. - *

- * For more information about turbo filters, please refer to the online manual at - * http://logback.qos.ch/manual/filters.html#TurboFilter - * - * @author Ceki Gulcu - */ -public abstract class TurboFilter extends ContextAwareBase implements LifeCycle { - - private String name; - boolean start = false; - - - /** - * Make a decision based on the multiple parameters passed as arguments. - * The returned value should be one of {@link FilterReply#DENY}, - * {@link FilterReply#NEUTRAL}, or {@link FilterReply#ACCEPT}. - - * @param marker - * @param logger - * @param level - * @param format - * @param params - * @param t - * @return - */ - public abstract FilterReply decide(Marker marker, Logger logger, - Level level, String format, Object[] params, Throwable t); - - public void start() { - this.start = true; - } - - public boolean isStarted() { - return this.start; - } - - public void stop() { - this.start = false; - } - - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} +/** + * 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.classic.turbo; + +import org.slf4j.Marker; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.spi.LifeCycle; + +/** + * TurboFilter is a specialized filter with a decide method that takes a bunch + * of parameters instead of a single event object. The latter is cleaner but + * the latter is much more performant. + *

+ * For more information about turbo filters, please refer to the online manual at + * http://logback.qos.ch/manual/filters.html#TurboFilter + * + * @author Ceki Gulcu + */ +public abstract class TurboFilter extends ContextAwareBase implements LifeCycle { + + private String name; + boolean start = false; + + + /** + * Make a decision based on the multiple parameters passed as arguments. + * The returned value should be one of {@link FilterReply#DENY}, + * {@link FilterReply#NEUTRAL}, or {@link FilterReply#ACCEPT}. + + * @param marker + * @param logger + * @param level + * @param format + * @param params + * @param t + * @return + */ + public abstract FilterReply decide(Marker marker, Logger logger, + Level level, String format, Object[] params, Throwable t); + + public void start() { + this.start = true; + } + + public boolean isStarted() { + return this.start; + } + + public void stop() { + this.start = false; + } + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java b/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java index 521144305afb081715b6a61ded44322706c014f4..527bac38319c9352d5d936642c59196fd777e425 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java @@ -1,158 +1,158 @@ -/** - * 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.classic.util; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.List; - -import ch.qos.logback.classic.BasicConfigurator; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.status.ErrorStatus; -import ch.qos.logback.core.status.InfoStatus; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.status.WarnStatus; -import ch.qos.logback.core.util.Loader; -import ch.qos.logback.core.util.OptionHelper; - -// contributors -// Ted Graham, Matt Fowles, see also http://jira.qos.ch/browse/LBCORE-32 -/** - * This class contains logback's logic for automatic configuration - * - * @author Ceki Gulcu - */ -public class ContextInitializer { - - final public static String AUTOCONFIG_FILE = "logback.xml"; - final public static String TEST_AUTOCONFIG_FILE = "logback-test.xml"; - final public static String CONFIG_FILE_PROPERTY = "logback.configurationFile"; - final public static String STATUS_LISTENER_CLASS = "logback.statusListenerClass"; - final public static String SYSOUT = "SYSOUT"; - - final LoggerContext loggerContext; - - public ContextInitializer(LoggerContext loggerContext) { - this.loggerContext = loggerContext; - } - - public void configureByResource(URL url) throws JoranException { - if (url == null) { - throw new IllegalArgumentException("URL argument cannot be null"); - } - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(loggerContext); - configurator.doConfigure(url); - } - - private URL findConfigFileURLFromSystemProperties(ClassLoader classLoader, boolean updateStatus) { - String logbackConfigFile = OptionHelper.getSystemProperty(CONFIG_FILE_PROPERTY); - - if (logbackConfigFile != null) { - URL result = null; - try { - result = new URL(logbackConfigFile); - return result; - } catch (MalformedURLException e) { - // so, resource is not a URL: - // attempt to get the resource from the class path - result = Loader.getResource(logbackConfigFile, classLoader); - if (result != null) { - return result; - } - File f = new File(logbackConfigFile); - if (f.exists() && f.isFile()) { - try { - result = f.toURI().toURL(); - return result; - } catch (MalformedURLException e1) { - } - } - } finally { - if (updateStatus) { - statusOnResourceSearch(logbackConfigFile, classLoader, result); - } - } - } - return null; - } - - public URL findURLOfDefaultConfigurationFile(boolean updateStatus) { - ClassLoader myClassLoader = Loader.getClassLoaderOfObject(this); - URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus); - if (url != null) { - return url; - } - - url = Loader.getResource(TEST_AUTOCONFIG_FILE, myClassLoader); - if (updateStatus) { - statusOnResourceSearch(TEST_AUTOCONFIG_FILE, myClassLoader, url); - } - if (url != null) { - return url; - } - - url = Loader.getResource(AUTOCONFIG_FILE, myClassLoader); - if (updateStatus) { - statusOnResourceSearch(AUTOCONFIG_FILE, myClassLoader, url); - } - return url; - } - - public void autoConfig() throws JoranException { - StatusListenerConfigHelper.installIfAsked(loggerContext); - URL url = findURLOfDefaultConfigurationFile(true); - if (url != null) { - configureByResource(url); - } else { - BasicConfigurator.configure(loggerContext); - } - } - - private void multiplicityWarning(String resourceName, ClassLoader classLoader ) { - List urlList = null; - StatusManager sm = loggerContext.getStatusManager(); - try { - urlList = Loader.getResourceOccurenceCount(resourceName, classLoader); - } catch (IOException e) { - sm.add(new ErrorStatus("Failed to get url list for resource [" + resourceName + "]", - loggerContext, e)); - } - if(urlList != null && urlList.size() > 1) { - sm.add(new WarnStatus("Resource [" + resourceName + "] occurs multiple times on the classpath.", - loggerContext)); - for(URL url: urlList) { - sm.add(new WarnStatus("Resource ["+resourceName+"] occurs at ["+url.toString()+"]", - loggerContext)); - } - } - } - - private void statusOnResourceSearch(String resourceName, ClassLoader classLoader, URL url) { - StatusManager sm = loggerContext.getStatusManager(); - if (url == null) { - sm.add(new InfoStatus("Could NOT find resource [" + resourceName + "]", - loggerContext)); - } else { - sm.add(new InfoStatus("Found resource [" + resourceName + "] at ["+url.toString()+"]", - loggerContext)); - multiplicityWarning(resourceName, classLoader); - } - } - -} +/** + * 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.classic.util; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +import ch.qos.logback.classic.BasicConfigurator; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.WarnStatus; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; + +// contributors +// Ted Graham, Matt Fowles, see also http://jira.qos.ch/browse/LBCORE-32 +/** + * This class contains logback's logic for automatic configuration + * + * @author Ceki Gulcu + */ +public class ContextInitializer { + + final public static String AUTOCONFIG_FILE = "logback.xml"; + final public static String TEST_AUTOCONFIG_FILE = "logback-test.xml"; + final public static String CONFIG_FILE_PROPERTY = "logback.configurationFile"; + final public static String STATUS_LISTENER_CLASS = "logback.statusListenerClass"; + final public static String SYSOUT = "SYSOUT"; + + final LoggerContext loggerContext; + + public ContextInitializer(LoggerContext loggerContext) { + this.loggerContext = loggerContext; + } + + public void configureByResource(URL url) throws JoranException { + if (url == null) { + throw new IllegalArgumentException("URL argument cannot be null"); + } + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(loggerContext); + configurator.doConfigure(url); + } + + private URL findConfigFileURLFromSystemProperties(ClassLoader classLoader, boolean updateStatus) { + String logbackConfigFile = OptionHelper.getSystemProperty(CONFIG_FILE_PROPERTY); + + if (logbackConfigFile != null) { + URL result = null; + try { + result = new URL(logbackConfigFile); + return result; + } catch (MalformedURLException e) { + // so, resource is not a URL: + // attempt to get the resource from the class path + result = Loader.getResource(logbackConfigFile, classLoader); + if (result != null) { + return result; + } + File f = new File(logbackConfigFile); + if (f.exists() && f.isFile()) { + try { + result = f.toURI().toURL(); + return result; + } catch (MalformedURLException e1) { + } + } + } finally { + if (updateStatus) { + statusOnResourceSearch(logbackConfigFile, classLoader, result); + } + } + } + return null; + } + + public URL findURLOfDefaultConfigurationFile(boolean updateStatus) { + ClassLoader myClassLoader = Loader.getClassLoaderOfObject(this); + URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus); + if (url != null) { + return url; + } + + url = Loader.getResource(TEST_AUTOCONFIG_FILE, myClassLoader); + if (updateStatus) { + statusOnResourceSearch(TEST_AUTOCONFIG_FILE, myClassLoader, url); + } + if (url != null) { + return url; + } + + url = Loader.getResource(AUTOCONFIG_FILE, myClassLoader); + if (updateStatus) { + statusOnResourceSearch(AUTOCONFIG_FILE, myClassLoader, url); + } + return url; + } + + public void autoConfig() throws JoranException { + StatusListenerConfigHelper.installIfAsked(loggerContext); + URL url = findURLOfDefaultConfigurationFile(true); + if (url != null) { + configureByResource(url); + } else { + BasicConfigurator.configure(loggerContext); + } + } + + private void multiplicityWarning(String resourceName, ClassLoader classLoader ) { + List urlList = null; + StatusManager sm = loggerContext.getStatusManager(); + try { + urlList = Loader.getResourceOccurenceCount(resourceName, classLoader); + } catch (IOException e) { + sm.add(new ErrorStatus("Failed to get url list for resource [" + resourceName + "]", + loggerContext, e)); + } + if(urlList != null && urlList.size() > 1) { + sm.add(new WarnStatus("Resource [" + resourceName + "] occurs multiple times on the classpath.", + loggerContext)); + for(URL url: urlList) { + sm.add(new WarnStatus("Resource ["+resourceName+"] occurs at ["+url.toString()+"]", + loggerContext)); + } + } + } + + private void statusOnResourceSearch(String resourceName, ClassLoader classLoader, URL url) { + StatusManager sm = loggerContext.getStatusManager(); + if (url == null) { + sm.add(new InfoStatus("Could NOT find resource [" + resourceName + "]", + loggerContext)); + } else { + sm.add(new InfoStatus("Found resource [" + resourceName + "] at ["+url.toString()+"]", + loggerContext)); + multiplicityWarning(resourceName, classLoader); + } + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/util/DefaultNestedComponentRules.java b/logback-classic/src/main/java/ch/qos/logback/classic/util/DefaultNestedComponentRules.java index d950318056ec37350ec62e299c3a73688f31ce72..72588d71313b62c6f52f2cd3381f42d13ea48da3 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/util/DefaultNestedComponentRules.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/util/DefaultNestedComponentRules.java @@ -1,41 +1,41 @@ -/** - * 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.classic.util; - -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.boolex.JaninoEventEvaluator; -import ch.qos.logback.core.AppenderBase; -import ch.qos.logback.core.UnsynchronizedAppenderBase; -import ch.qos.logback.core.filter.EvaluatorFilter; -import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; - -/** - * Contains mappings for the default type of nested components in - * logback-classic. - * - * @author Ceki Gulcu - * - */ -public class DefaultNestedComponentRules { - - static public void addDefaultNestedComponentRegistryRules( - DefaultNestedComponentRegistry registry) { - registry.add(AppenderBase.class, "layout", PatternLayout.class); - registry.add(UnsynchronizedAppenderBase.class, "layout", PatternLayout.class); - registry - .add(EvaluatorFilter.class, "evaluator", JaninoEventEvaluator.class); - - } - -} +/** + * 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.classic.util; + +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.boolex.JaninoEventEvaluator; +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.UnsynchronizedAppenderBase; +import ch.qos.logback.core.filter.EvaluatorFilter; +import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; + +/** + * Contains mappings for the default type of nested components in + * logback-classic. + * + * @author Ceki Gulcu + * + */ +public class DefaultNestedComponentRules { + + static public void addDefaultNestedComponentRegistryRules( + DefaultNestedComponentRegistry registry) { + registry.add(AppenderBase.class, "layout", PatternLayout.class); + registry.add(UnsynchronizedAppenderBase.class, "layout", PatternLayout.class); + registry + .add(EvaluatorFilter.class, "evaluator", JaninoEventEvaluator.class); + + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/util/JNDIUtil.java b/logback-classic/src/main/java/ch/qos/logback/classic/util/JNDIUtil.java index 290980c646a6b68ac73f8d064d2c4a5bb362bbfd..76303cefd1413b3443765e25e1252ee6aca5653b 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/util/JNDIUtil.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/util/JNDIUtil.java @@ -1,43 +1,43 @@ -/** - * 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.classic.util; - -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NamingException; - -/** - * A simple utility class to create and use a JNDI Context. - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ - -public class JNDIUtil { - - public static Context getInitialContext() throws NamingException { - return new InitialContext(); - } - - public static String lookup(Context ctx, String name) { - if (ctx == null) { - return null; - } - try { - return (String) ctx.lookup(name); - } catch (NamingException e) { - return null; - } - } +/** + * 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.classic.util; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +/** + * A simple utility class to create and use a JNDI Context. + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ + +public class JNDIUtil { + + public static Context getInitialContext() throws NamingException { + return new InitialContext(); + } + + public static String lookup(Context ctx, String name) { + if (ctx == null) { + return null; + } + try { + return (String) ctx.lookup(name); + } catch (NamingException e) { + return null; + } + } } \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/util/LevelToSyslogSeverity.java b/logback-classic/src/main/java/ch/qos/logback/classic/util/LevelToSyslogSeverity.java index 9c221c06ab013419eafd192adbe83839113391fc..fd0df894d0926cba796a56ab0e8fd32c8ae15117 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/util/LevelToSyslogSeverity.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/util/LevelToSyslogSeverity.java @@ -1,47 +1,47 @@ -/** - * 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.classic.util; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.net.SyslogConstants; - -public class LevelToSyslogSeverity { - - /* - * Convert a level to equivalent syslog severity. Only levels for printing - * methods i.e TRACE, DEBUG, WARN, INFO and ERROR are converted. - * - */ - static public int convert(ILoggingEvent event) { - - Level level = event.getLevel(); - - switch (level.levelInt) { - case Level.ERROR_INT: - return SyslogConstants.ERROR_SEVERITY; - case Level.WARN_INT: - return SyslogConstants.WARNING_SEVERITY; - case Level.INFO_INT: - return SyslogConstants.INFO_SEVERITY; - case Level.DEBUG_INT: - return SyslogConstants.DEBUG_SEVERITY; - case Level.TRACE_INT: - return SyslogConstants.DEBUG_SEVERITY; - default: - throw new IllegalArgumentException("Level " + level - + " is not a valid level for a printing method"); - } - } -} +/** + * 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.classic.util; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.net.SyslogConstants; + +public class LevelToSyslogSeverity { + + /* + * Convert a level to equivalent syslog severity. Only levels for printing + * methods i.e TRACE, DEBUG, WARN, INFO and ERROR are converted. + * + */ + static public int convert(ILoggingEvent event) { + + Level level = event.getLevel(); + + switch (level.levelInt) { + case Level.ERROR_INT: + return SyslogConstants.ERROR_SEVERITY; + case Level.WARN_INT: + return SyslogConstants.WARNING_SEVERITY; + case Level.INFO_INT: + return SyslogConstants.INFO_SEVERITY; + case Level.DEBUG_INT: + return SyslogConstants.DEBUG_SEVERITY; + case Level.TRACE_INT: + return SyslogConstants.DEBUG_SEVERITY; + default: + throw new IllegalArgumentException("Level " + level + + " is not a valid level for a printing method"); + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/util/LoggerStatusPrinter.java b/logback-classic/src/main/java/ch/qos/logback/classic/util/LoggerStatusPrinter.java index 834a66111a5485349289fd759eb8e39f9b6a068f..56004be8b1248c8c422628ee4d2fc6e5cae7592a 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/util/LoggerStatusPrinter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/util/LoggerStatusPrinter.java @@ -1,28 +1,28 @@ -/** - * 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.classic.util; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.util.StatusPrinter; - -public class LoggerStatusPrinter { - - public static void printStatusInDefaultContext() { - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - StatusPrinter.print(lc); - } - -} +/** + * 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.classic.util; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.util.StatusPrinter; + +public class LoggerStatusPrinter { + + public static void printStatusInDefaultContext() { + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + StatusPrinter.print(lc); + } + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/util/StatusListenerConfigHelper.java b/logback-classic/src/main/java/ch/qos/logback/classic/util/StatusListenerConfigHelper.java index ef1f21798e9ff2890f451d4a381701118201d917..0705d720fe8dd27491fb5428c2a3e86f220f4467 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/util/StatusListenerConfigHelper.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/util/StatusListenerConfigHelper.java @@ -1,49 +1,49 @@ -/** - * 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.classic.util; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.status.OnConsoleStatusListener; -import ch.qos.logback.core.status.StatusListener; -import ch.qos.logback.core.util.OptionHelper; - -public class StatusListenerConfigHelper { - - static void installIfAsked(LoggerContext loggerContext) { - String slClass = OptionHelper.getSystemProperty( - ContextInitializer.STATUS_LISTENER_CLASS); - if (!OptionHelper.isEmpty(slClass)) { - addStatusListener(loggerContext, slClass); - } - } - - static void addStatusListener(LoggerContext loggerContext, - String listenerClass) { - StatusListener listener = null; - if (ContextInitializer.SYSOUT.equalsIgnoreCase(listenerClass)) { - listener = new OnConsoleStatusListener(); - } else { - try { - listener = (StatusListener) OptionHelper.instantiateByClassName( - listenerClass, StatusListener.class, loggerContext); - } catch (Exception e) { - // printing on the console is the best we can do - e.printStackTrace(); - } - } - if (listener != null) { - loggerContext.getStatusManager().add(listener); - } - } -} +/** + * 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.classic.util; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.status.OnConsoleStatusListener; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.util.OptionHelper; + +public class StatusListenerConfigHelper { + + static void installIfAsked(LoggerContext loggerContext) { + String slClass = OptionHelper.getSystemProperty( + ContextInitializer.STATUS_LISTENER_CLASS); + if (!OptionHelper.isEmpty(slClass)) { + addStatusListener(loggerContext, slClass); + } + } + + static void addStatusListener(LoggerContext loggerContext, + String listenerClass) { + StatusListener listener = null; + if (ContextInitializer.SYSOUT.equalsIgnoreCase(listenerClass)) { + listener = new OnConsoleStatusListener(); + } else { + try { + listener = (StatusListener) OptionHelper.instantiateByClassName( + listenerClass, StatusListener.class, loggerContext); + } catch (Exception e) { + // printing on the console is the best we can do + e.printStackTrace(); + } + } + if (listener != null) { + loggerContext.getStatusManager().add(listener); + } + } +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/util/package.html b/logback-classic/src/main/java/ch/qos/logback/classic/util/package.html index 259b7f9ccf9138ff2251edca76c6bb7bfe332d36..ac31665981634e8aaf3b6ef9f5becf4bf5520c8a 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/util/package.html +++ b/logback-classic/src/main/java/ch/qos/logback/classic/util/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains utility classes.

- - + + + + + + + + + +

Contains utility classes.

+ + \ No newline at end of file diff --git a/logback-classic/src/main/java/org/slf4j/impl/CopyOnInheritThreadLocal.java b/logback-classic/src/main/java/org/slf4j/impl/CopyOnInheritThreadLocal.java index 68e4b692d2565bd0ed343840eefdcc17ed64a9c1..5b2a5194100deddb5250775fbd3dea749d406440 100644 --- a/logback-classic/src/main/java/org/slf4j/impl/CopyOnInheritThreadLocal.java +++ b/logback-classic/src/main/java/org/slf4j/impl/CopyOnInheritThreadLocal.java @@ -1,41 +1,41 @@ -/** - * 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 org.slf4j.impl; - -import java.util.HashMap; - -/** - * This class extends InheritableThreadLocal so that children threads get a copy - * of the parent's hashmap. - * - * @author Ceki Gülcü - */ -public class CopyOnInheritThreadLocal extends - InheritableThreadLocal> { - - /** - * Child threads should get a copy of the parent's hashmap. - */ - @Override - protected HashMap childValue( - HashMap parentValue) { - if (parentValue == null) { - return null; - } else { - HashMap hm = new HashMap(parentValue); - return hm; - } - } - -} +/** + * 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 org.slf4j.impl; + +import java.util.HashMap; + +/** + * This class extends InheritableThreadLocal so that children threads get a copy + * of the parent's hashmap. + * + * @author Ceki Gülcü + */ +public class CopyOnInheritThreadLocal extends + InheritableThreadLocal> { + + /** + * Child threads should get a copy of the parent's hashmap. + */ + @Override + protected HashMap childValue( + HashMap parentValue) { + if (parentValue == null) { + return null; + } else { + HashMap hm = new HashMap(parentValue); + return hm; + } + } + +} diff --git a/logback-classic/src/main/java/org/slf4j/impl/LogbackMDCAdapter.java b/logback-classic/src/main/java/org/slf4j/impl/LogbackMDCAdapter.java index dc10b1c51dd11bf0819426c754df1b07fb76f2c8..93b4c1e515d1a639282867e698f4f216a71213c8 100644 --- a/logback-classic/src/main/java/org/slf4j/impl/LogbackMDCAdapter.java +++ b/logback-classic/src/main/java/org/slf4j/impl/LogbackMDCAdapter.java @@ -1,175 +1,175 @@ -/** - * 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 org.slf4j.impl; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import org.slf4j.spi.MDCAdapter; - -/** - * A Mapped Diagnostic Context, or MDC in short, is an instrument - * for distinguishing interleaved log output from different sources. Log output - * is typically interleaved when a server handles multiple clients - * near-simultaneously.

The MDC is managed on a per thread basis. - * A child thread automatically inherits a copy of the mapped - * diagnostic context of its parent.

- * - * For more information about MDC, please refer to the online manual at - * http://logback.qos.ch/manual/mdc.html - * - * @author Ceki Gülcü - */ -public class LogbackMDCAdapter implements MDCAdapter { - - // final CopyOnInheritThreadLocal copyOnInheritThreadLocal = new - // CopyOnInheritThreadLocal(); - - final CopyOnInheritThreadLocal copyOnInheritThreadLocal = new CopyOnInheritThreadLocal(); - - LogbackMDCAdapter() { - } - - /** - * Put a context value (the val parameter) as identified with - * the key parameter into the current thread's context map. - * Note that contrary to log4j, the val parameter can be null. - * - *

If the current thread does not have a context map it is created as a - * side effect of this call. - * - *

Each time a value is added, a new instance of the map is created. This - * is to be certain that the serialization process will operate on the updated - * map and not send a reference to the old map, thus not allowing the remote - * logback component to see the latest changes. - * - * @throws IllegalArgumentException - * in case the "key" parameter is null - */ - public void put(String key, String val) throws IllegalArgumentException { - if (key == null) { - throw new IllegalArgumentException("key cannot be null"); - } - - HashMap oldMap = copyOnInheritThreadLocal.get(); - - HashMap newMap = new HashMap(); - if (oldMap != null) { - newMap.putAll(oldMap); - } - // the newMap replaces the old one for serialisation's sake - copyOnInheritThreadLocal.set(newMap); - newMap.put(key, val); - } - - /** - * Get the context identified by the key parameter. - * - *

This method has no side effects. - */ - public String get(String key) { - HashMap hashMap = copyOnInheritThreadLocal.get(); - - if ((hashMap != null) && (key != null)) { - return hashMap.get(key); - } else { - return null; - } - } - - /** - * Remove the the context identified by the key parameter. - * - *

Each time a value is removed, a new instance of the map is created. - * This is to be certain that the serialization process will operate on the - * updated map and not send a reference to the old map, thus not allowing the - * remote logback component to see the latest changes. - */ - public void remove(String key) { - HashMap oldMap = copyOnInheritThreadLocal.get(); - - HashMap newMap = new HashMap(); - if (oldMap != null) { - newMap.putAll(oldMap); - } - // the newMap replaces the old one for serialisation's sake - copyOnInheritThreadLocal.set(newMap); - newMap.remove(key); - } - - /** - * Clear all entries in the MDC. - */ - public void clear() { - HashMap hashMap = copyOnInheritThreadLocal.get(); - - if (hashMap != null) { - hashMap.clear(); - copyOnInheritThreadLocal.remove(); - } - } - - /** - * Get the current thread's MDC as a map. This method is intended to be used - * internally. - */ - public Map getPropertyMap() { - return copyOnInheritThreadLocal.get(); - } - - /** - * Return a copy of the current thread's context map. Returned value may be - * null. - */ - public Map getCopyOfContextMap() { - HashMap hashMap = copyOnInheritThreadLocal.get(); - if (hashMap == null) { - return null; - } else { - return new HashMap(hashMap); - } - } - - /** - * Returns the keys in the MDC as a {@link Set}. The returned value can be - * null. - */ - public Set getKeys() { - HashMap hashMap = copyOnInheritThreadLocal.get(); - - if (hashMap != null) { - return hashMap.keySet(); - } else { - return null; - } - } - - @SuppressWarnings("unchecked") - public void setContextMap(Map contextMap) { - HashMap oldMap = copyOnInheritThreadLocal.get(); - - HashMap newMap = new HashMap(); - newMap.putAll(contextMap); - - // the newMap replaces the old one for serialisation's sake - copyOnInheritThreadLocal.set(newMap); - - // hints for the garbage collector - if (oldMap != null) { - oldMap.clear(); - oldMap = null; - } - } -} +/** + * 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 org.slf4j.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.slf4j.spi.MDCAdapter; + +/** + * A Mapped Diagnostic Context, or MDC in short, is an instrument + * for distinguishing interleaved log output from different sources. Log output + * is typically interleaved when a server handles multiple clients + * near-simultaneously.

The MDC is managed on a per thread basis. + * A child thread automatically inherits a copy of the mapped + * diagnostic context of its parent.

+ * + * For more information about MDC, please refer to the online manual at + * http://logback.qos.ch/manual/mdc.html + * + * @author Ceki Gülcü + */ +public class LogbackMDCAdapter implements MDCAdapter { + + // final CopyOnInheritThreadLocal copyOnInheritThreadLocal = new + // CopyOnInheritThreadLocal(); + + final CopyOnInheritThreadLocal copyOnInheritThreadLocal = new CopyOnInheritThreadLocal(); + + LogbackMDCAdapter() { + } + + /** + * Put a context value (the val parameter) as identified with + * the key parameter into the current thread's context map. + * Note that contrary to log4j, the val parameter can be null. + * + *

If the current thread does not have a context map it is created as a + * side effect of this call. + * + *

Each time a value is added, a new instance of the map is created. This + * is to be certain that the serialization process will operate on the updated + * map and not send a reference to the old map, thus not allowing the remote + * logback component to see the latest changes. + * + * @throws IllegalArgumentException + * in case the "key" parameter is null + */ + public void put(String key, String val) throws IllegalArgumentException { + if (key == null) { + throw new IllegalArgumentException("key cannot be null"); + } + + HashMap oldMap = copyOnInheritThreadLocal.get(); + + HashMap newMap = new HashMap(); + if (oldMap != null) { + newMap.putAll(oldMap); + } + // the newMap replaces the old one for serialisation's sake + copyOnInheritThreadLocal.set(newMap); + newMap.put(key, val); + } + + /** + * Get the context identified by the key parameter. + * + *

This method has no side effects. + */ + public String get(String key) { + HashMap hashMap = copyOnInheritThreadLocal.get(); + + if ((hashMap != null) && (key != null)) { + return hashMap.get(key); + } else { + return null; + } + } + + /** + * Remove the the context identified by the key parameter. + * + *

Each time a value is removed, a new instance of the map is created. + * This is to be certain that the serialization process will operate on the + * updated map and not send a reference to the old map, thus not allowing the + * remote logback component to see the latest changes. + */ + public void remove(String key) { + HashMap oldMap = copyOnInheritThreadLocal.get(); + + HashMap newMap = new HashMap(); + if (oldMap != null) { + newMap.putAll(oldMap); + } + // the newMap replaces the old one for serialisation's sake + copyOnInheritThreadLocal.set(newMap); + newMap.remove(key); + } + + /** + * Clear all entries in the MDC. + */ + public void clear() { + HashMap hashMap = copyOnInheritThreadLocal.get(); + + if (hashMap != null) { + hashMap.clear(); + copyOnInheritThreadLocal.remove(); + } + } + + /** + * Get the current thread's MDC as a map. This method is intended to be used + * internally. + */ + public Map getPropertyMap() { + return copyOnInheritThreadLocal.get(); + } + + /** + * Return a copy of the current thread's context map. Returned value may be + * null. + */ + public Map getCopyOfContextMap() { + HashMap hashMap = copyOnInheritThreadLocal.get(); + if (hashMap == null) { + return null; + } else { + return new HashMap(hashMap); + } + } + + /** + * Returns the keys in the MDC as a {@link Set}. The returned value can be + * null. + */ + public Set getKeys() { + HashMap hashMap = copyOnInheritThreadLocal.get(); + + if (hashMap != null) { + return hashMap.keySet(); + } else { + return null; + } + } + + @SuppressWarnings("unchecked") + public void setContextMap(Map contextMap) { + HashMap oldMap = copyOnInheritThreadLocal.get(); + + HashMap newMap = new HashMap(); + newMap.putAll(contextMap); + + // the newMap replaces the old one for serialisation's sake + copyOnInheritThreadLocal.set(newMap); + + // hints for the garbage collector + if (oldMap != null) { + oldMap.clear(); + oldMap = null; + } + } +} diff --git a/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index 1b1ff81b1e296cc42d241da6e478303bf4f3aa77..f8c2ea80284931928934e75ed6e63073d801e8a0 100644 --- a/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -1,167 +1,167 @@ -/** - * 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 org.slf4j.impl; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; - -import org.slf4j.ILoggerFactory; -import org.slf4j.LoggerFactory; -import org.slf4j.helpers.Util; -import org.slf4j.spi.LoggerFactoryBinder; - -import ch.qos.logback.classic.ClassicConstants; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.selector.ContextJNDISelector; -import ch.qos.logback.classic.selector.ContextSelector; -import ch.qos.logback.classic.selector.DefaultContextSelector; -import ch.qos.logback.classic.util.ContextInitializer; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.util.Loader; -import ch.qos.logback.core.util.OptionHelper; -import ch.qos.logback.core.util.StatusPrinter; - -/** - * - * The binding of {@link LoggerFactory} class with an actual instance of - * {@link ILoggerFactory} is performed using information returned by this class. - * - * @author Ceki Gülcü - */ -public class StaticLoggerBinder implements LoggerFactoryBinder { - - /** - * Declare the version of the SLF4J API this implementation is compiled - * against. The value of this field is usually modified with each release. - */ - // to avoid constant folding by the compiler, this field must *not* be final - public static String REQUESTED_API_VERSION = "1.5.8"; // !final - - final static String NULL_CS_URL = CoreConstants.CODES_URL + "#null_CS"; - - /** - * The unique instance of this class. - */ - private static StaticLoggerBinder SINGLETON = new StaticLoggerBinder(); - - static { - SINGLETON.init(); - } - - private boolean initialized = false; - private LoggerContext defaultLoggerContext = new LoggerContext(); - private ContextSelector contextSelector; - - private StaticLoggerBinder() { - defaultLoggerContext.setName(CoreConstants.DEFAULT_CONTEXT_NAME); - } - - public static StaticLoggerBinder getSingleton() { - return SINGLETON; - } - - /** - * Package access for testing purposes. - */ - static void reset() { - SINGLETON = new StaticLoggerBinder(); - SINGLETON.init(); - } - - /** - * Package access for testing purposes. - */ - void init() { - try { - try { - new ContextInitializer(defaultLoggerContext).autoConfig(); - } catch (JoranException je) { - Util.reportFailure("Failed to auto configure default logger context", - je); - } - StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext); - - // See if a special context selector is needed - String contextSelectorStr = OptionHelper - .getSystemProperty(ClassicConstants.LOGBACK_CONTEXT_SELECTOR); - if (contextSelectorStr == null) { - contextSelector = new DefaultContextSelector(defaultLoggerContext); - } else if (contextSelectorStr.equals("JNDI")) { - // if jndi is specified, let's use the appropriate class - contextSelector = new ContextJNDISelector(defaultLoggerContext); - } else { - contextSelector = dynamicalContextSelector(defaultLoggerContext, - contextSelectorStr); - } - initialized = true; - } catch (Throwable t) { - // we should never get here - Util.reportFailure("Failed to instantiate [" - + LoggerContext.class.getName() + "]", t); - } - } - - /** - * Intantiate the context selector class designated by the user. The selector - * must have a constructor taking a LoggerContext instance as an argument. - * - * @param defaultLoggerContext - * @param contextSelectorStr - * @return an instance of the designated context selector class - * @throws ClassNotFoundException - * @throws SecurityException - * @throws NoSuchMethodException - * @throws IllegalArgumentException - * @throws InstantiationException - * @throws IllegalAccessException - * @throws InvocationTargetException - */ - static ContextSelector dynamicalContextSelector( - 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 }); - return (ContextSelector) cons.newInstance(defaultLoggerContext); - } - - public ILoggerFactory getLoggerFactory() { - if (!initialized) { - return defaultLoggerContext; - } - - if (contextSelector == null) { - throw new IllegalStateException( - "contextSelector cannot be null. See also " + NULL_CS_URL); - } - return contextSelector.getLoggerContext(); - } - - public String getLoggerFactoryClassStr() { - return contextSelector.getClass().getName(); - } - - /** - * Return the {@link ContextSelector} instance in use. - * - * @return the ContextSelector instance in use - */ - public ContextSelector getContextSelector() { - return contextSelector; - } - -} +/** + * 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 org.slf4j.impl; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import org.slf4j.ILoggerFactory; +import org.slf4j.LoggerFactory; +import org.slf4j.helpers.Util; +import org.slf4j.spi.LoggerFactoryBinder; + +import ch.qos.logback.classic.ClassicConstants; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.selector.ContextJNDISelector; +import ch.qos.logback.classic.selector.ContextSelector; +import ch.qos.logback.classic.selector.DefaultContextSelector; +import ch.qos.logback.classic.util.ContextInitializer; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; +import ch.qos.logback.core.util.StatusPrinter; + +/** + * + * The binding of {@link LoggerFactory} class with an actual instance of + * {@link ILoggerFactory} is performed using information returned by this class. + * + * @author Ceki Gülcü + */ +public class StaticLoggerBinder implements LoggerFactoryBinder { + + /** + * Declare the version of the SLF4J API this implementation is compiled + * against. The value of this field is usually modified with each release. + */ + // to avoid constant folding by the compiler, this field must *not* be final + public static String REQUESTED_API_VERSION = "1.5.8"; // !final + + final static String NULL_CS_URL = CoreConstants.CODES_URL + "#null_CS"; + + /** + * The unique instance of this class. + */ + private static StaticLoggerBinder SINGLETON = new StaticLoggerBinder(); + + static { + SINGLETON.init(); + } + + private boolean initialized = false; + private LoggerContext defaultLoggerContext = new LoggerContext(); + private ContextSelector contextSelector; + + private StaticLoggerBinder() { + defaultLoggerContext.setName(CoreConstants.DEFAULT_CONTEXT_NAME); + } + + public static StaticLoggerBinder getSingleton() { + return SINGLETON; + } + + /** + * Package access for testing purposes. + */ + static void reset() { + SINGLETON = new StaticLoggerBinder(); + SINGLETON.init(); + } + + /** + * Package access for testing purposes. + */ + void init() { + try { + try { + new ContextInitializer(defaultLoggerContext).autoConfig(); + } catch (JoranException je) { + Util.reportFailure("Failed to auto configure default logger context", + je); + } + StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext); + + // See if a special context selector is needed + String contextSelectorStr = OptionHelper + .getSystemProperty(ClassicConstants.LOGBACK_CONTEXT_SELECTOR); + if (contextSelectorStr == null) { + contextSelector = new DefaultContextSelector(defaultLoggerContext); + } else if (contextSelectorStr.equals("JNDI")) { + // if jndi is specified, let's use the appropriate class + contextSelector = new ContextJNDISelector(defaultLoggerContext); + } else { + contextSelector = dynamicalContextSelector(defaultLoggerContext, + contextSelectorStr); + } + initialized = true; + } catch (Throwable t) { + // we should never get here + Util.reportFailure("Failed to instantiate [" + + LoggerContext.class.getName() + "]", t); + } + } + + /** + * Intantiate the context selector class designated by the user. The selector + * must have a constructor taking a LoggerContext instance as an argument. + * + * @param defaultLoggerContext + * @param contextSelectorStr + * @return an instance of the designated context selector class + * @throws ClassNotFoundException + * @throws SecurityException + * @throws NoSuchMethodException + * @throws IllegalArgumentException + * @throws InstantiationException + * @throws IllegalAccessException + * @throws InvocationTargetException + */ + static ContextSelector dynamicalContextSelector( + 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 }); + return (ContextSelector) cons.newInstance(defaultLoggerContext); + } + + public ILoggerFactory getLoggerFactory() { + if (!initialized) { + return defaultLoggerContext; + } + + if (contextSelector == null) { + throw new IllegalStateException( + "contextSelector cannot be null. See also " + NULL_CS_URL); + } + return contextSelector.getLoggerContext(); + } + + public String getLoggerFactoryClassStr() { + return contextSelector.getClass().getName(); + } + + /** + * Return the {@link ContextSelector} instance in use. + * + * @return the ContextSelector instance in use + */ + public ContextSelector getContextSelector() { + return contextSelector; + } + +} diff --git a/logback-classic/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/logback-classic/src/main/java/org/slf4j/impl/StaticMDCBinder.java index 3255eabb310d57a4e7cf4fcffa0d360c47400f97..c24fca85de4aee59f9568d9b03307002a0933382 100644 --- a/logback-classic/src/main/java/org/slf4j/impl/StaticMDCBinder.java +++ b/logback-classic/src/main/java/org/slf4j/impl/StaticMDCBinder.java @@ -1,46 +1,46 @@ -/** - * 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 org.slf4j.impl; - -import org.slf4j.spi.MDCAdapter; - - -/** - * This implementation is bound to {@link LogbackMDCAdapter}. - * - * @author Ceki Gülcü - */ -public class StaticMDCBinder { - - - /** - * The unique instance of this class. - */ - public static final StaticMDCBinder SINGLETON = new StaticMDCBinder(); - - private StaticMDCBinder() { - } - - /** - * Currently this method always returns an instance of - * {@link StaticMDCBinder}. - */ - public MDCAdapter getMDCA() { - return new LogbackMDCAdapter(); - } - - public String getMDCAdapterClassStr() { - return LogbackMDCAdapter.class.getName(); - } -} +/** + * 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 org.slf4j.impl; + +import org.slf4j.spi.MDCAdapter; + + +/** + * This implementation is bound to {@link LogbackMDCAdapter}. + * + * @author Ceki Gülcü + */ +public class StaticMDCBinder { + + + /** + * The unique instance of this class. + */ + public static final StaticMDCBinder SINGLETON = new StaticMDCBinder(); + + private StaticMDCBinder() { + } + + /** + * Currently this method always returns an instance of + * {@link StaticMDCBinder}. + */ + public MDCAdapter getMDCA() { + return new LogbackMDCAdapter(); + } + + public String getMDCAdapterClassStr() { + return LogbackMDCAdapter.class.getName(); + } +} diff --git a/logback-classic/src/main/java/org/slf4j/impl/StaticMarkerBinder.java b/logback-classic/src/main/java/org/slf4j/impl/StaticMarkerBinder.java index f20320be2d3bcd192cf88aa07acd143586172211..8be32ee55f07788168700d31dbe94001cfecee7d 100644 --- a/logback-classic/src/main/java/org/slf4j/impl/StaticMarkerBinder.java +++ b/logback-classic/src/main/java/org/slf4j/impl/StaticMarkerBinder.java @@ -1,57 +1,57 @@ -/** - * 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 org.slf4j.impl; - -import org.slf4j.IMarkerFactory; -import org.slf4j.MarkerFactory; -import org.slf4j.helpers.BasicMarkerFactory; -import org.slf4j.spi.MarkerFactoryBinder; - -/** - * - * The binding of {@link MarkerFactory} class with an actual instance of - * {@link IMarkerFactory} is performed using information returned by this class. - * - * @author Ceki Gülcü - */ -public class StaticMarkerBinder implements MarkerFactoryBinder { - - /** - * The unique instance of this class. - */ - public static final StaticMarkerBinder SINGLETON = new StaticMarkerBinder(); - - final IMarkerFactory markerFactory = new BasicMarkerFactory(); - - private StaticMarkerBinder() { - } - - /** - * Currently this method always returns an instance of - * {@link BasicMarkerFactory}. - */ - public IMarkerFactory getMarkerFactory() { - return markerFactory; - } - - /** - * Currently, this method returns the class name of - * {@link BasicMarkerFactory}. - */ - public String getMarkerFactoryClassStr() { - return BasicMarkerFactory.class.getName(); - } - - -} +/** + * 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 org.slf4j.impl; + +import org.slf4j.IMarkerFactory; +import org.slf4j.MarkerFactory; +import org.slf4j.helpers.BasicMarkerFactory; +import org.slf4j.spi.MarkerFactoryBinder; + +/** + * + * The binding of {@link MarkerFactory} class with an actual instance of + * {@link IMarkerFactory} is performed using information returned by this class. + * + * @author Ceki Gülcü + */ +public class StaticMarkerBinder implements MarkerFactoryBinder { + + /** + * The unique instance of this class. + */ + public static final StaticMarkerBinder SINGLETON = new StaticMarkerBinder(); + + final IMarkerFactory markerFactory = new BasicMarkerFactory(); + + private StaticMarkerBinder() { + } + + /** + * Currently this method always returns an instance of + * {@link BasicMarkerFactory}. + */ + public IMarkerFactory getMarkerFactory() { + return markerFactory; + } + + /** + * Currently, this method returns the class name of + * {@link BasicMarkerFactory}. + */ + public String getMarkerFactoryClassStr() { + return BasicMarkerFactory.class.getName(); + } + + +} diff --git a/logback-classic/src/main/java/org/slf4j/package.html b/logback-classic/src/main/java/org/slf4j/package.html index 434391f7d3c7412c93eaa38261877f76aed2e4e7..86c86246826354b4220cfdc192e3282c39607c65 100644 --- a/logback-classic/src/main/java/org/slf4j/package.html +++ b/logback-classic/src/main/java/org/slf4j/package.html @@ -1,14 +1,14 @@ - - - - - - - - - -

Contains SLF4J implementations binding logback classes to the SLF4J framework. The - complete javadoc for SLF4J can be found on the SLF4J website.

- - + + + + + + + + + +

Contains SLF4J implementations binding logback classes to the SLF4J framework. The + complete javadoc for SLF4J can be found on the SLF4J website.

+ + \ No newline at end of file diff --git a/logback-classic/src/test/input/autoConfig.xml b/logback-classic/src/test/input/autoConfig.xml index cbaf6effbca916291cf510e1f9f9d2b263ab8c89..6abcad9eee17cdb466b933da6cb7acd14da2f7eb 100644 --- a/logback-classic/src/test/input/autoConfig.xml +++ b/logback-classic/src/test/input/autoConfig.xml @@ -1,15 +1,15 @@ - - - - - - - %msg%n" - - - - - - - - + + + + + + + %msg%n" + + + + + + + + diff --git a/logback-classic/src/test/input/integration/db/mysql-with-driver.xml b/logback-classic/src/test/input/integration/db/mysql-with-driver.xml index 9952d5a8718a9275fe94486f53755dd6c1f2deac..1f42baca0c8268a00736bcf493fe7c4e75673c7d 100644 --- a/logback-classic/src/test/input/integration/db/mysql-with-driver.xml +++ b/logback-classic/src/test/input/integration/db/mysql-with-driver.xml @@ -1,18 +1,18 @@ - - - - - - - com.mysql.jdbc.Driver - jdbc:mysql://localhost:3306/logback - root - - - - - - - - - + + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/logback + root + + + + + + + + + diff --git a/logback-classic/src/test/input/integration/db/oracle10g-with-driver.xml b/logback-classic/src/test/input/integration/db/oracle10g-with-driver.xml index d5b742b3576f40b9a88f4bd248b84046b60ae620..0f601fd82b6a57238add54f5bddaa611fc4450dd 100644 --- a/logback-classic/src/test/input/integration/db/oracle10g-with-driver.xml +++ b/logback-classic/src/test/input/integration/db/oracle10g-with-driver.xml @@ -1,18 +1,18 @@ - - - - - - - oracle.jdbc.OracleDriver - jdbc:oracle:thin:@localhost:1522:xe - hr - hr - - - - - - - - + + + + + + + oracle.jdbc.OracleDriver + jdbc:oracle:thin:@localhost:1522:xe + hr + hr + + + + + + + + diff --git a/logback-classic/src/test/input/integration/db/oracle11g-with-driver.xml b/logback-classic/src/test/input/integration/db/oracle11g-with-driver.xml index 47e90714baca8a56d798a7b8e13a3e34ae46f6ac..a0fdbc26e2c927cfdb1a960b8b6aa5a54f1d39af 100644 --- a/logback-classic/src/test/input/integration/db/oracle11g-with-driver.xml +++ b/logback-classic/src/test/input/integration/db/oracle11g-with-driver.xml @@ -1,18 +1,18 @@ - - - - - - - oracle.jdbc.OracleDriver - jdbc:oracle:thin:@localhost:1521:orcl - SCOTT - SCOTT - - - - - - - - + + + + + + + oracle.jdbc.OracleDriver + jdbc:oracle:thin:@localhost:1521:orcl + SCOTT + SCOTT + + + + + + + + diff --git a/logback-classic/src/test/input/integration/db/postgresql-with-driver.xml b/logback-classic/src/test/input/integration/db/postgresql-with-driver.xml index cb0a3ab8ad74e29f53a6d9a6436f4a94c717ad2e..ce5a3cf8bd467660072169bb516410a5431275ab 100644 --- a/logback-classic/src/test/input/integration/db/postgresql-with-driver.xml +++ b/logback-classic/src/test/input/integration/db/postgresql-with-driver.xml @@ -1,18 +1,18 @@ - - - - - - - org.postgresql.Driver - jdbc:postgresql://192.168.1.5:5432/test - logback - logback - - - - - - - - + + + + + + + org.postgresql.Driver + jdbc:postgresql://192.168.1.5:5432/test + logback + logback + + + + + + + + diff --git a/logback-classic/src/test/input/integration/db/sqlserver-with-driver.xml b/logback-classic/src/test/input/integration/db/sqlserver-with-driver.xml index 7f8d2266fda600db1c50e61e97528803c5bfc3f4..e6a1fd977d3c0bdd9686cc81502031170a29536d 100644 --- a/logback-classic/src/test/input/integration/db/sqlserver-with-driver.xml +++ b/logback-classic/src/test/input/integration/db/sqlserver-with-driver.xml @@ -1,18 +1,18 @@ - - - - - - - com.microsoft.sqlserver.jdbc.SQLServerDriver - jdbc:sqlserver://localhost:1987;databaseName=logback; - logback - logback - - - - - - - - + + + + + + + com.microsoft.sqlserver.jdbc.SQLServerDriver + jdbc:sqlserver://localhost:1987;databaseName=logback; + logback + logback + + + + + + + + diff --git a/logback-classic/src/test/input/issue/lbcore26.xml b/logback-classic/src/test/input/issue/lbcore26.xml index ac56c831d77ffd8ff64a4145a5a48cb0bf88d59b..aaf73b32f25c264e820fee7bae282bf32823e468 100644 --- a/logback-classic/src/test/input/issue/lbcore26.xml +++ b/logback-classic/src/test/input/issue/lbcore26.xml @@ -1,18 +1,18 @@ - - - target/test-output/lbcore26.log - - - target/test-output/lbcore26.%d{yyyy-MM-dd}.log - 30 - - - - %date [%thread] %-5level %logger - %msg%n - - - - - - + + + target/test-output/lbcore26.log + + + target/test-output/lbcore26.%d{yyyy-MM-dd}.log + 30 + + + + %date [%thread] %-5level %logger - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/issue/lbcore63.xml b/logback-classic/src/test/input/issue/lbcore63.xml index cc06a4acd978492f5fa4ce056bc33af550cd9593..c01dca2db720ca3b0b6705628dbecdfc60e65b48 100644 --- a/logback-classic/src/test/input/issue/lbcore63.xml +++ b/logback-classic/src/test/input/issue/lbcore63.xml @@ -1,34 +1,34 @@ - - - - - - - %d{HH:mm:ss.SSS} - %msg%n - - - - - logs/main.log - - logs/main-%i.log - 1 - 3 - - - 500MB - - - %-25(%7r [%thread]) - %msg%n - - - - - - - - + + + + + + + %d{HH:mm:ss.SSS} - %msg%n + + + + + logs/main.log + + logs/main-%i.log + 1 + 3 + + + 500MB + + + %-25(%7r [%thread]) - %msg%n + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/callerData.xml b/logback-classic/src/test/input/joran/callerData.xml index f61286a15acd085f0c8dd099fdcdc91d8cc23610..4d66239e59415aa777f524837f5581ea28f4f0ec 100644 --- a/logback-classic/src/test/input/joran/callerData.xml +++ b/logback-classic/src/test/input/joran/callerData.xml @@ -1,31 +1,31 @@ - - - - - - - m.matches(message) - - m - ^hello.* - false - - - - - - - %caller{4, helloEval}%d %level - %m%n - - - - - - - - - - - + + + + + + + m.matches(message) + + m + ^hello.* + false + + + + + + + %caller{4, helloEval}%d %level - %m%n + + + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/contextRename.xml b/logback-classic/src/test/input/joran/contextRename.xml index 07151b8f2713f5ebe53c8ca149c70ecff971cf47..be0d445a56e7783c9b04636a181561f7d8968de3 100644 --- a/logback-classic/src/test/input/joran/contextRename.xml +++ b/logback-classic/src/test/input/joran/contextRename.xml @@ -1,3 +1,3 @@ - - wombat + + wombat \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/conversionRule/htmlLayout0.xml b/logback-classic/src/test/input/joran/conversionRule/htmlLayout0.xml index 866998e2a05976f1a47da4e4ceb570c27831d753..302af87cf01e9089540163ffe29bf444df0659c8 100644 --- a/logback-classic/src/test/input/joran/conversionRule/htmlLayout0.xml +++ b/logback-classic/src/test/input/joran/conversionRule/htmlLayout0.xml @@ -1,15 +1,15 @@ - - - - - - - %sample%msg - - - - - - + + + + + + + %sample%msg + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/conversionRule/patternLayout0.xml b/logback-classic/src/test/input/joran/conversionRule/patternLayout0.xml index 682c5879621ff81503fe54391907a24015f73b36..1468bbb22ca1ef500c75e302b9053dc2927adf4c 100644 --- a/logback-classic/src/test/input/joran/conversionRule/patternLayout0.xml +++ b/logback-classic/src/test/input/joran/conversionRule/patternLayout0.xml @@ -1,15 +1,15 @@ - - - - - - - %sample - %msg - - - - - - + + + + + + + %sample - %msg + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/evaluatorFilter.xml b/logback-classic/src/test/input/joran/evaluatorFilter.xml index a3369da2fa2485c21cb4ebb4b0b04eda02f03c22..e0823f73ec649f0be7bbc005cf41205a0fc5a941 100644 --- a/logback-classic/src/test/input/joran/evaluatorFilter.xml +++ b/logback-classic/src/test/input/joran/evaluatorFilter.xml @@ -1,19 +1,19 @@ - - - - - - myFilter - DENY - - mdcEvaluator - "to be ignored".equals(message) - - - - - - - + + + + + + myFilter + DENY + + mdcEvaluator + "to be ignored".equals(message) + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/ignore.xml b/logback-classic/src/test/input/joran/ignore.xml index 55374b6b23061233b9c3c31b076e542b1fa7f4e6..1bd2cd78919837a64d61b4e6712234f32d5abad7 100644 --- a/logback-classic/src/test/input/joran/ignore.xml +++ b/logback-classic/src/test/input/joran/ignore.xml @@ -1,20 +1,20 @@ - - - - - - (marker.contains("IGNORE")) - - - - - %date %level - %m%n%ex{full, IGNORE_EVAL} - - - - - - - - + + + + + + (marker.contains("IGNORE")) + + + + + %date %level - %m%n%ex{full, IGNORE_EVAL} + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/levelFilter.xml b/logback-classic/src/test/input/joran/levelFilter.xml index aa8cd306d0730ec3fc07cf9c23813a430e75b5bd..96796abdf7208bcddb1bf69db675256b0a64b009 100644 --- a/logback-classic/src/test/input/joran/levelFilter.xml +++ b/logback-classic/src/test/input/joran/levelFilter.xml @@ -1,14 +1,14 @@ - - - - - - DENY - ERROR - - - - - - + + + + + + DENY + ERROR + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/loggerLevelByProperty.xml b/logback-classic/src/test/input/joran/loggerLevelByProperty.xml index c5379e17536af151772b2fdb733744f229f0ddb2..10aa93995ccbf99af9bd590a859dc68db35a2009 100644 --- a/logback-classic/src/test/input/joran/loggerLevelByProperty.xml +++ b/logback-classic/src/test/input/joran/loggerLevelByProperty.xml @@ -1,14 +1,14 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/rolling/basic.xml b/logback-classic/src/test/input/joran/rolling/basic.xml index 4314248e09fc31fd01dec89dfe33ab7ca4eebb72..75ade9e9e763f35fefb63b697fa364c3723ec2b8 100644 --- a/logback-classic/src/test/input/joran/rolling/basic.xml +++ b/logback-classic/src/test/input/joran/rolling/basic.xml @@ -1,22 +1,22 @@ - - - - ${randomOutputDir}z${testId} - - - ${randomOutputDir}${testId}-%d{yyyy-MM-dd_HH_mm_ss} - - - - %msg%n - - - - - - - - - + + + + ${randomOutputDir}z${testId} + + + ${randomOutputDir}${testId}-%d{yyyy-MM-dd_HH_mm_ss} + + + + %msg%n + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/rolling/timeAndSize.xml b/logback-classic/src/test/input/joran/rolling/timeAndSize.xml index 15a5d2e13ad7c74804053b31e1bfa89830c2b5d9..8e727090b60af0f505fdd91f7059ba50323ec989 100644 --- a/logback-classic/src/test/input/joran/rolling/timeAndSize.xml +++ b/logback-classic/src/test/input/joran/rolling/timeAndSize.xml @@ -1,26 +1,26 @@ - - - - ${randomOutputDir}z${testId} - - - ${randomOutputDir}${testId}-%d{yyyy-MM-dd_HH_mm_ss}.%i - - - ${sizeThreshold} - - - - %msg%n - - - - - - - - - + + + + ${randomOutputDir}z${testId} + + + ${randomOutputDir}${testId}-%d{yyyy-MM-dd_HH_mm_ss}.%i + + + ${sizeThreshold} + + + + %msg%n + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/rootLevelByProperty.xml b/logback-classic/src/test/input/joran/rootLevelByProperty.xml index 21301d0ed68b61809cf88df0c2632b09ef22375e..cde6a04e9c229aa5ce488530112c8a4f25bfe722 100644 --- a/logback-classic/src/test/input/joran/rootLevelByProperty.xml +++ b/logback-classic/src/test/input/joran/rootLevelByProperty.xml @@ -1,13 +1,13 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/scan1.xml b/logback-classic/src/test/input/joran/scan1.xml index 35249d2b8cdbdcf862b500bab4000016c06301a7..ea436320d5f17a36ca1ff2a49c7e1450a0d7888e 100644 --- a/logback-classic/src/test/input/joran/scan1.xml +++ b/logback-classic/src/test/input/joran/scan1.xml @@ -1,17 +1,17 @@ - - - - - - - - yx %d - %m%n" - - - - - - - - + + + + + + + + yx %d - %m%n" + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/sift/completeCycle.xml b/logback-classic/src/test/input/joran/sift/completeCycle.xml index 4192a5bf1a538f09fc59745672047763f13fd3ca..622582f42b4471a9551bc8ac5d0e32fc07bfed8c 100644 --- a/logback-classic/src/test/input/joran/sift/completeCycle.xml +++ b/logback-classic/src/test/input/joran/sift/completeCycle.xml @@ -1,22 +1,22 @@ - - - - - - - - - cycle - cycleDefault - - - - - - - - - - - + + + + + + + + + cycle + cycleDefault + + + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/sift/defaultLayoutRule.xml b/logback-classic/src/test/input/joran/sift/defaultLayoutRule.xml index 0e2419918f5889044eb41a6206c11f062e2e433f..7e4213d1c80a3f945dd71a0ca8830f75f356143d 100644 --- a/logback-classic/src/test/input/joran/sift/defaultLayoutRule.xml +++ b/logback-classic/src/test/input/joran/sift/defaultLayoutRule.xml @@ -1,23 +1,23 @@ - - - - - - userid - default - - - - - %level %msg - - - - - - - - - - + + + + + + userid + default + + + + + %level %msg + + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/sift/hoard0.xml b/logback-classic/src/test/input/joran/sift/hoard0.xml index a0a084f3b05aa4aea81d67c610838e1aa639f35e..930f5502cd73758780c1d88f241cb4d40f4ace07 100644 --- a/logback-classic/src/test/input/joran/sift/hoard0.xml +++ b/logback-classic/src/test/input/joran/sift/hoard0.xml @@ -1,26 +1,26 @@ - - - - - - - - userid - asdad - - - ${userid}.log - true - - %d [%thread] %level %logger{35} - %msg%n - - - - - - - - - - + + + + + + + + userid + asdad + + + ${userid}.log + true + + %d [%thread] %level %logger{35} - %msg%n + + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/sift/smoke.xml b/logback-classic/src/test/input/joran/sift/smoke.xml index d93a07593444dcfd7dc578cf6a48d1df46c3b101..91e3f565a600fc9dea70ec94b30c2e1fa601fbf5 100644 --- a/logback-classic/src/test/input/joran/sift/smoke.xml +++ b/logback-classic/src/test/input/joran/sift/smoke.xml @@ -1,22 +1,22 @@ - - - - - - - - - userid - smoke - - - - - - - - - - - + + + + + + + + + userid + smoke + + + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/sift/unsetDefaultValueProperty.xml b/logback-classic/src/test/input/joran/sift/unsetDefaultValueProperty.xml index 301dd7186dcad65ee26ba962bfcfb33fb27fb76f..7afa57b9fafde7c26c9cb27e35d72273d66afd8d 100644 --- a/logback-classic/src/test/input/joran/sift/unsetDefaultValueProperty.xml +++ b/logback-classic/src/test/input/joran/sift/unsetDefaultValueProperty.xml @@ -1,21 +1,21 @@ - - - - - - - - - userid - - - - - - - - - - - + + + + + + + + + userid + + + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/simple2.xml b/logback-classic/src/test/input/joran/simple2.xml index 6916f4d23e9706117f23303741a2c36969647ab7..9659faafa3a2d0fc41692a55edd87700405c378a 100644 --- a/logback-classic/src/test/input/joran/simple2.xml +++ b/logback-classic/src/test/input/joran/simple2.xml @@ -1,17 +1,17 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/simpleEvaluator.xml b/logback-classic/src/test/input/joran/simpleEvaluator.xml index bdd19b3d96c815c4cc00968d415ee2553523417a..65011419fab948c0bded0010ecaee3ffb1dccc12 100644 --- a/logback-classic/src/test/input/joran/simpleEvaluator.xml +++ b/logback-classic/src/test/input/joran/simpleEvaluator.xml @@ -1,10 +1,10 @@ - - - m.matches(message) - - m - ^hello.* - false - - - + + + m.matches(message) + + m + ^hello.* + false + + + diff --git a/logback-classic/src/test/input/joran/simpleLevel.xml b/logback-classic/src/test/input/joran/simpleLevel.xml index 64a9ab547d61d86688c29b6bc93cf51420b1cf1a..d783617f741c83ff05c53ac36c704bb17ab6de13 100644 --- a/logback-classic/src/test/input/joran/simpleLevel.xml +++ b/logback-classic/src/test/input/joran/simpleLevel.xml @@ -1,14 +1,14 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/simpleList.xml b/logback-classic/src/test/input/joran/simpleList.xml index a4d9ac01250a73cf3275d514fd0d584df2b31d47..97239950f06316c3a4c8e2a28a838bdf741b9c5c 100644 --- a/logback-classic/src/test/input/joran/simpleList.xml +++ b/logback-classic/src/test/input/joran/simpleList.xml @@ -1,14 +1,14 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/smtp/customEvaluator.xml b/logback-classic/src/test/input/joran/smtp/customEvaluator.xml index 89319985b526f8b450a0679318ed64bfefe4979f..32d83a443e89c0370f79ae38a7c89d95b13819ea 100644 --- a/logback-classic/src/test/input/joran/smtp/customEvaluator.xml +++ b/logback-classic/src/test/input/joran/smtp/customEvaluator.xml @@ -1,20 +1,20 @@ - - - - localhost - ${port} - nospam@qos.ch - user@host.dom - %logger - %m - - 2 - - - %message - - - - - - - + + + + localhost + ${port} + nospam@qos.ch + user@host.dom + %logger - %m + + 2 + + + %message + + + + + + + diff --git a/logback-classic/src/test/input/joran/statusListener.xml b/logback-classic/src/test/input/joran/statusListener.xml index e91f5f6c2d9b1de89458311ce6fe3ea324bf9187..bc9c7202ae7854ca2d5d021ea88c1d425da09630 100644 --- a/logback-classic/src/test/input/joran/statusListener.xml +++ b/logback-classic/src/test/input/joran/statusListener.xml @@ -1,20 +1,20 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/syslog_LBCLASSIC_50.xml b/logback-classic/src/test/input/joran/syslog_LBCLASSIC_50.xml index d06e4e00ebeabac910e55469a49469d69211edb9..de886285fa7153fb33345097d3223e0e1c01e4b7 100644 --- a/logback-classic/src/test/input/joran/syslog_LBCLASSIC_50.xml +++ b/logback-classic/src/test/input/joran/syslog_LBCLASSIC_50.xml @@ -1,14 +1,14 @@ - - - - 127.0.0.1 - LOCAL7 - - %d %p [%t] %c::%m%n - - - - - - + + + + 127.0.0.1 + LOCAL7 + + %d %p [%t] %c::%m%n + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/timestamp.xml b/logback-classic/src/test/input/joran/timestamp.xml index 65be6ec84ed107b257729ea7bb9410734b1f9728..e36da68144f51a50f90349d614b44f7f3814c4a2 100644 --- a/logback-classic/src/test/input/joran/timestamp.xml +++ b/logback-classic/src/test/input/joran/timestamp.xml @@ -1,4 +1,4 @@ - - - + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/turbo.xml b/logback-classic/src/test/input/joran/turbo.xml index 8d81b0535a8b9cf3c83569e11c2e538f8251528a..2e3cdc53992b6ab060ee5542fa0ec8bb175a6fad 100644 --- a/logback-classic/src/test/input/joran/turbo.xml +++ b/logback-classic/src/test/input/joran/turbo.xml @@ -1,18 +1,18 @@ - - - - - - - - - %caller{4} %d %level - %m%n - - - - - - - - + + + + + + + + + %caller{4} %d %level - %m%n + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/turbo2.xml b/logback-classic/src/test/input/joran/turbo2.xml index f8374c15918240961033841c40494e558eda7ff3..8f452e60ed1e26748c86b2987e0fc4522e43763e 100644 --- a/logback-classic/src/test/input/joran/turbo2.xml +++ b/logback-classic/src/test/input/joran/turbo2.xml @@ -1,21 +1,21 @@ - - - - - - seb - ceki - - - - - %d %level - %m%n - - - - - - - - + + + + + + seb + ceki + + + + + %d %level - %m%n + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/turboDynamicThreshold.xml b/logback-classic/src/test/input/joran/turboDynamicThreshold.xml index 2215ca62287ccc5cce7e4e2374162f1a4b6cf960..bbba7b5333dd60009189e1d1c0a5b53e02211709 100644 --- a/logback-classic/src/test/input/joran/turboDynamicThreshold.xml +++ b/logback-classic/src/test/input/joran/turboDynamicThreshold.xml @@ -1,29 +1,29 @@ - - - - - - - userId - ERROR - - user1 - INFO - - - user2 - TRACE - - - - - - - - - - - - - + + + + + + + userId + ERROR + + user1 + INFO + + + user2 + TRACE + + + + + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/turboDynamicThreshold2.xml b/logback-classic/src/test/input/joran/turboDynamicThreshold2.xml index 758a0cb03201dba2b02160ac496bb93acf78dd2b..40b36932614bae59280a45c3e898349991f4232a 100644 --- a/logback-classic/src/test/input/joran/turboDynamicThreshold2.xml +++ b/logback-classic/src/test/input/joran/turboDynamicThreshold2.xml @@ -1,32 +1,32 @@ - - - - - - - userId - ERROR - ACCEPT - DENY - - user1 - DEBUG - - - user2 - TRACE - - - - - - - - - - - - - + + + + + + + userId + ERROR + ACCEPT + DENY + + user1 + DEBUG + + + user2 + TRACE + + + + + + + + + + + + + diff --git a/logback-classic/src/test/input/joran/unique.xml b/logback-classic/src/test/input/joran/unique.xml index e236b8cdf4b99cc32b4189f54c7690cf939e8d95..73b4ea3c660edfac6436b5c387772858b59d0ebf 100644 --- a/logback-classic/src/test/input/joran/unique.xml +++ b/logback-classic/src/test/input/joran/unique.xml @@ -1,15 +1,15 @@ - - - - - target/test-output/TS_${dayTimestamp}log.txt - false - - %-4relative [%thread] %-5level %logger{35} - %msg%n - - - - - - - + + + + + target/test-output/TS_${dayTimestamp}log.txt + false + + %-4relative [%thread] %-5level %logger{35} - %msg%n + + + + + + + diff --git a/logback-classic/src/test/input/socket/clientConfig.xml b/logback-classic/src/test/input/socket/clientConfig.xml index 2ba3ba8e010121c82767fe341826b68b6a44109b..4411efa2d246d9b3f3bbce90165db5ebe9b0480e 100644 --- a/logback-classic/src/test/input/socket/clientConfig.xml +++ b/logback-classic/src/test/input/socket/clientConfig.xml @@ -1,24 +1,24 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/logback-classic/src/test/input/socket/serverConfig.xml b/logback-classic/src/test/input/socket/serverConfig.xml index 564f360a6a840058e25a37011408cd489fbb27a6..7823131843b235be14df58e743a235a0c7547ab9 100644 --- a/logback-classic/src/test/input/socket/serverConfig.xml +++ b/logback-classic/src/test/input/socket/serverConfig.xml @@ -1,17 +1,17 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/input/turbo/scan 1.xml b/logback-classic/src/test/input/turbo/scan 1.xml index d9df3a0295e26585c9486ae1c2210215f0d11efd..dc3d0fe0d3c205887a9a23f874e72d62a3f54a21 100644 --- a/logback-classic/src/test/input/turbo/scan 1.xml +++ b/logback-classic/src/test/input/turbo/scan 1.xml @@ -1,7 +1,7 @@ - - - - - - + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java index 38d0d843f76e31e83179c78a93534f93bffa68c4..91b29f6ee1cc74b1f8eeb3375db185c129869d25 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java @@ -1,40 +1,40 @@ -/** - * 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.classic; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({org.slf4j.impl.PackageTest.class, - ch.qos.logback.classic.PackageTest.class, - ch.qos.logback.classic.util.PackageTest.class, - ch.qos.logback.classic.control.PackageTest.class, - ch.qos.logback.classic.joran.PackageTest.class, - ch.qos.logback.classic.rolling.PackageTest.class, - ch.qos.logback.classic.jmx.PackageTest.class, - ch.qos.logback.classic.boolex.PackageTest.class, - ch.qos.logback.classic.selector.PackageTest.class, - ch.qos.logback.classic.html.PackageTest.class, - ch.qos.logback.classic.net.PackageTest.class, - ch.qos.logback.classic.pattern.PackageTest.class, - ch.qos.logback.classic.db.PackageTest.class, - ch.qos.logback.classic.spi.PackageTest.class, - ch.qos.logback.classic.turbo.PackageTest.class, - ch.qos.logback.classic.sift.PackageTest.class, - ch.qos.logback.classic.issue.PackageTest.class}) -public class AllClassicTest { - -} +/** + * 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.classic; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({org.slf4j.impl.PackageTest.class, + ch.qos.logback.classic.PackageTest.class, + ch.qos.logback.classic.util.PackageTest.class, + ch.qos.logback.classic.control.PackageTest.class, + ch.qos.logback.classic.joran.PackageTest.class, + ch.qos.logback.classic.rolling.PackageTest.class, + ch.qos.logback.classic.jmx.PackageTest.class, + ch.qos.logback.classic.boolex.PackageTest.class, + ch.qos.logback.classic.selector.PackageTest.class, + ch.qos.logback.classic.html.PackageTest.class, + ch.qos.logback.classic.net.PackageTest.class, + ch.qos.logback.classic.pattern.PackageTest.class, + ch.qos.logback.classic.db.PackageTest.class, + ch.qos.logback.classic.spi.PackageTest.class, + ch.qos.logback.classic.turbo.PackageTest.class, + ch.qos.logback.classic.sift.PackageTest.class, + ch.qos.logback.classic.issue.PackageTest.class}) +public class AllClassicTest { + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java b/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java index 8bf96f07c844be031b03ccaaa37cf3357122a003..c9471fd76549a0ff4009ab2174909475f335c3a3 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java @@ -1,23 +1,23 @@ -/** - * 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.classic; - -public class ClassicTestConstants { - - final static public String ISO_REGEX = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2},\\d{3}"; - final static public String NAKED_MAIN_REGEX = "[mM]ain(\\sThread)?"; - final static public String MAIN_REGEX = "\\["+NAKED_MAIN_REGEX+"\\]"; - final static public String INPUT_PREFIX = "src/test/input/"; - final static public String JORAN_INPUT_PREFIX = INPUT_PREFIX+"joran/"; -} +/** + * 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.classic; + +public class ClassicTestConstants { + + final static public String ISO_REGEX = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2},\\d{3}"; + final static public String NAKED_MAIN_REGEX = "[mM]ain(\\sThread)?"; + final static public String MAIN_REGEX = "\\["+NAKED_MAIN_REGEX+"\\]"; + final static public String INPUT_PREFIX = "src/test/input/"; + final static public String JORAN_INPUT_PREFIX = INPUT_PREFIX+"joran/"; +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/Foo.java b/logback-classic/src/test/java/ch/qos/logback/classic/Foo.java index f87c13c8fe1c56aa598bf0d1f497948eb11c4aa9..7053982def4124666379745f05dc05956f9b2760 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/Foo.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/Foo.java @@ -1,30 +1,30 @@ -/** - * 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.classic; - -import java.io.Serializable; - -class Foo implements Serializable { - private static final long serialVersionUID = 1L; - final Logger logger; - - Foo(Logger logger) { - this.logger = logger; - } - - void doFoo() { - logger.debug("hello"); - } -} - +/** + * 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.classic; + +import java.io.Serializable; + +class Foo implements Serializable { + private static final long serialVersionUID = 1L; + final Logger logger; + + Foo(Logger logger) { + this.logger = logger; + } + + void doFoo() { + logger.debug("hello"); + } +} + diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/HLogger.java b/logback-classic/src/test/java/ch/qos/logback/classic/HLogger.java index 81ea93e2b6751b528db5b4befcae90a7854b44f3..33d8b677b3d5d3e3cd923aff15c62aaf1c3e0bb8 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/HLogger.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/HLogger.java @@ -1,408 +1,408 @@ -/** - * 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.classic; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import org.slf4j.helpers.MarkerIgnoringBase; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.CoreConstants; - - -public class HLogger extends MarkerIgnoringBase { - - private static final long serialVersionUID = 1L; - - static int instanceCount = 0; - - /** - * The name of this logger - */ - private String name; - - // The assigned levelInt of this logger. Can be null. - private Level level; - - // The effective levelInt is the assigned levelInt and if null, a levelInt is - // inherited form a parent. - private Level effectiveLevel; - - /** - * The parent of this category. All categories have at least one ancestor - * which is the root category. - */ - HLogger parent; - - /** - * The children of this logger. A logger may have zero or more children. - */ - Map childrenMap; - - /** - * Array of appenders. - */ - private ArrayList> appenderList; - - /** - * Additivity is set to true by default, that is children inherit the - * appenders of their ancestors by default. If this variable is set to - * false then the appenders located in the ancestors of this - * logger will not be used. However, the children of this logger will inherit - * its appenders, unless the children have their additivity flag set to - * false too. See the user manual for more details. - */ - protected boolean additive = true; - - HLogger(String name, HLogger parent) { - this.name = name; - this.parent = parent; - instanceCount++; - } - - Level getEffectiveLevel() { - return effectiveLevel; - } - - Level getLevel() { - return level; - } - - public String getName() { - return name; - } - - private final boolean isRootLogger() { - // only the root logger has a null parent - return parent == null; - } - - /** - * Get a child by its suffix. - * - *

- * IMPORTANT: Calls to this method must be within a syncronized block on this - * logger! - * - * @param suffix - * @return - */ - HLogger getChildBySuffix(final String suffix) { - if (childrenMap == null) { - return null; - } else { - return (HLogger) childrenMap.get(suffix); - } - } - - public synchronized void setLevel(Level newLevel) { - if (level == newLevel) { - // nothing to do; - return; - } - - level = newLevel; - effectiveLevel = newLevel; - if (childrenMap != null) { - for (Iterator i = childrenMap.values().iterator(); i.hasNext();) { - HLogger child = (HLogger) i.next(); - - // tell child to handle parent levelInt change - child.handleParentLevelChange(effectiveLevel); - } - } - } - - /** - * This method is invoked by parent logger to let this logger know that the - * prent's levelInt changed. - * - * @param newParentLevel - */ - private synchronized void handleParentLevelChange(Level newParentLevel) { - // changes in the parent levelInt affect children only if their levelInt is - // null - if (level == null) { - effectiveLevel = newParentLevel; - - // propagate the parent levelInt change to this logger's children - if (childrenMap != null) { - for (Iterator i = childrenMap.values().iterator(); i.hasNext();) { - HLogger child = (HLogger) i.next(); - // tell child to handle parent levelInt change - child.handleParentLevelChange(effectiveLevel); - } - } - } - } - - /** - * Remove all previously added appenders from this logger instance.

This - * is useful when re-reading configuration information. - */ - public synchronized void removeAllAppenders() { - if (appenderList != null) { - int len = appenderList.size(); - for (int i = 0; i < len; i++) { - Appender a = appenderList.get(i); - a.stop(); - } - appenderList.clear(); - appenderList = null; - } - } - - /** - * Invoke all the appenders of this logger. - * - * @param event - * The event to log - */ - public void callAppenders(ILoggingEvent event) { - int writes = 0; - - for (HLogger l = this; l != null; l = l.parent) { - // Protected against simultaneous call to addAppender, removeAppender,... - synchronized (l) { - if (l.appenderList != null) { - writes += l.appendLoopOnAppenders(event); - } - if (!l.additive) { - break; - } - } - } - - // No appenders in hierarchy, warn user only once. - // if(!hierarchy.emittedNoAppenderWarning && writes == 0) { - // LogLog.error("No appenders could be found for category (" + - // this.getName() + ")."); - // LogLog.error("Please initialize the log4j system properly."); - // hierarchy.emittedNoAppenderWarning = true; - // } - } - - private int appendLoopOnAppenders(ILoggingEvent event) { - int size = 0; - Appender appender; - - if (appenderList != null) { - size = appenderList.size(); - for (int i = 0; i < size; i++) { - appender = appenderList.get(i); - appender.doAppend(event); - } - } - return size; - } - - /** - * Remove the appender passed as parameter form the list of appenders. - */ - public synchronized void removeAppender(Appender appender) { - if ((appender == null) || (appenderList == null)) { - } - appenderList.remove(appender); - } - - /** - * Create a child of this logger by suffix, that is, the part of the name - * extending this logger. For example, if this logger is named "x.y" and the - * lastPart is "z", then the created child logger will be named "x.y.z". - * - *

- * IMPORTANT: Calls to this method must be within a syncronized block on this - * logger. - * - * @param lastPart - * the suffix (i.e. last part) of the child logger name. This - * parameter may not include dots, i.e. the logger separator - * character. - * @return - */ - HLogger createChildByLastNamePart(final String lastPart) { - int i_index = lastPart.indexOf(CoreConstants.DOT); - if (i_index != -1) { - throw new IllegalArgumentException("Child name [" + lastPart - + " passed as parameter, may not include [" + CoreConstants.DOT - + "]"); - } - - if (childrenMap == null) { - childrenMap = new HashMap(2); - } - HLogger childHLogger; - if (this.isRootLogger()) { - childHLogger = new HLogger(lastPart, this); - } else { - childHLogger = new HLogger(name + CoreConstants.DOT + lastPart, - this); - } - childrenMap.put(lastPart, childHLogger); - childHLogger.effectiveLevel = this.effectiveLevel; - return childHLogger; - } - - public final void trace(String msg) { - if (effectiveLevel.levelInt <= Level.TRACE_INT) { - throw new UnsupportedOperationException("not yet implemented"); - } - } - - public void trace(String msg, Throwable t) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void trace(Object parameterizedMsg, Object param1) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void trace(String parameterizedMsg, Object param1, Object param2) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - - - public final void debug(String msg) { - if (effectiveLevel.levelInt <= Level.DEBUG_INT) { - throw new UnsupportedOperationException("not yet implemented"); - } - } - - public void debug(String msg, Throwable t) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void debug(Object parameterizedMsg, Object param1) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void debug(String parameterizedMsg, Object param1, Object param2) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void error(String msg) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void error(String msg, Throwable t) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void error(String parameterizedMsg, Object param1) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void error(String parameterizedMsg, Object param1, Object param2) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void info(String msg) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void info(String msg, Throwable t) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void info(String parameterizedMsg, Object param1) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void info(String parameterizedMsg, Object param1, Object param2) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public boolean isTraceEnabled() { - return false; - } - - public boolean isDebugEnabled() { - return false; - } - - public boolean isErrorEnabled() { - return false; // To change body of implemented methods use File | Settings | - // File Templates. - } - - public boolean isInfoEnabled() { - return false; // To change body of implemented methods use File | Settings | - // File Templates. - } - - public boolean isWarnEnabled() { - return false; // To change body of implemented methods use File | Settings | - // File Templates. - } - - public void warn(String msg) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void warn(String msg, Throwable t) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void warn(String parameterizedMsg, Object param1) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void warn(String parameterizedMsg, Object param1, Object param2) { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public void trace(String format, Object arg) { - } - - public void trace(String format, Object[] argArray) { - } - - public void debug(String format, Object arg) { - } - - public void debug(String format, Object[] argArray) { - } - - public void info(String format, Object[] argArray) { - } - - public void warn(String format, Object[] argArray) { - } - - public void error(String format, Object[] argArray) { - } -} +/** + * 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.classic; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.slf4j.helpers.MarkerIgnoringBase; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.CoreConstants; + + +public class HLogger extends MarkerIgnoringBase { + + private static final long serialVersionUID = 1L; + + static int instanceCount = 0; + + /** + * The name of this logger + */ + private String name; + + // The assigned levelInt of this logger. Can be null. + private Level level; + + // The effective levelInt is the assigned levelInt and if null, a levelInt is + // inherited form a parent. + private Level effectiveLevel; + + /** + * The parent of this category. All categories have at least one ancestor + * which is the root category. + */ + HLogger parent; + + /** + * The children of this logger. A logger may have zero or more children. + */ + Map childrenMap; + + /** + * Array of appenders. + */ + private ArrayList> appenderList; + + /** + * Additivity is set to true by default, that is children inherit the + * appenders of their ancestors by default. If this variable is set to + * false then the appenders located in the ancestors of this + * logger will not be used. However, the children of this logger will inherit + * its appenders, unless the children have their additivity flag set to + * false too. See the user manual for more details. + */ + protected boolean additive = true; + + HLogger(String name, HLogger parent) { + this.name = name; + this.parent = parent; + instanceCount++; + } + + Level getEffectiveLevel() { + return effectiveLevel; + } + + Level getLevel() { + return level; + } + + public String getName() { + return name; + } + + private final boolean isRootLogger() { + // only the root logger has a null parent + return parent == null; + } + + /** + * Get a child by its suffix. + * + *

+ * IMPORTANT: Calls to this method must be within a syncronized block on this + * logger! + * + * @param suffix + * @return + */ + HLogger getChildBySuffix(final String suffix) { + if (childrenMap == null) { + return null; + } else { + return (HLogger) childrenMap.get(suffix); + } + } + + public synchronized void setLevel(Level newLevel) { + if (level == newLevel) { + // nothing to do; + return; + } + + level = newLevel; + effectiveLevel = newLevel; + if (childrenMap != null) { + for (Iterator i = childrenMap.values().iterator(); i.hasNext();) { + HLogger child = (HLogger) i.next(); + + // tell child to handle parent levelInt change + child.handleParentLevelChange(effectiveLevel); + } + } + } + + /** + * This method is invoked by parent logger to let this logger know that the + * prent's levelInt changed. + * + * @param newParentLevel + */ + private synchronized void handleParentLevelChange(Level newParentLevel) { + // changes in the parent levelInt affect children only if their levelInt is + // null + if (level == null) { + effectiveLevel = newParentLevel; + + // propagate the parent levelInt change to this logger's children + if (childrenMap != null) { + for (Iterator i = childrenMap.values().iterator(); i.hasNext();) { + HLogger child = (HLogger) i.next(); + // tell child to handle parent levelInt change + child.handleParentLevelChange(effectiveLevel); + } + } + } + } + + /** + * Remove all previously added appenders from this logger instance.

This + * is useful when re-reading configuration information. + */ + public synchronized void removeAllAppenders() { + if (appenderList != null) { + int len = appenderList.size(); + for (int i = 0; i < len; i++) { + Appender a = appenderList.get(i); + a.stop(); + } + appenderList.clear(); + appenderList = null; + } + } + + /** + * Invoke all the appenders of this logger. + * + * @param event + * The event to log + */ + public void callAppenders(ILoggingEvent event) { + int writes = 0; + + for (HLogger l = this; l != null; l = l.parent) { + // Protected against simultaneous call to addAppender, removeAppender,... + synchronized (l) { + if (l.appenderList != null) { + writes += l.appendLoopOnAppenders(event); + } + if (!l.additive) { + break; + } + } + } + + // No appenders in hierarchy, warn user only once. + // if(!hierarchy.emittedNoAppenderWarning && writes == 0) { + // LogLog.error("No appenders could be found for category (" + + // this.getName() + ")."); + // LogLog.error("Please initialize the log4j system properly."); + // hierarchy.emittedNoAppenderWarning = true; + // } + } + + private int appendLoopOnAppenders(ILoggingEvent event) { + int size = 0; + Appender appender; + + if (appenderList != null) { + size = appenderList.size(); + for (int i = 0; i < size; i++) { + appender = appenderList.get(i); + appender.doAppend(event); + } + } + return size; + } + + /** + * Remove the appender passed as parameter form the list of appenders. + */ + public synchronized void removeAppender(Appender appender) { + if ((appender == null) || (appenderList == null)) { + } + appenderList.remove(appender); + } + + /** + * Create a child of this logger by suffix, that is, the part of the name + * extending this logger. For example, if this logger is named "x.y" and the + * lastPart is "z", then the created child logger will be named "x.y.z". + * + *

+ * IMPORTANT: Calls to this method must be within a syncronized block on this + * logger. + * + * @param lastPart + * the suffix (i.e. last part) of the child logger name. This + * parameter may not include dots, i.e. the logger separator + * character. + * @return + */ + HLogger createChildByLastNamePart(final String lastPart) { + int i_index = lastPart.indexOf(CoreConstants.DOT); + if (i_index != -1) { + throw new IllegalArgumentException("Child name [" + lastPart + + " passed as parameter, may not include [" + CoreConstants.DOT + + "]"); + } + + if (childrenMap == null) { + childrenMap = new HashMap(2); + } + HLogger childHLogger; + if (this.isRootLogger()) { + childHLogger = new HLogger(lastPart, this); + } else { + childHLogger = new HLogger(name + CoreConstants.DOT + lastPart, + this); + } + childrenMap.put(lastPart, childHLogger); + childHLogger.effectiveLevel = this.effectiveLevel; + return childHLogger; + } + + public final void trace(String msg) { + if (effectiveLevel.levelInt <= Level.TRACE_INT) { + throw new UnsupportedOperationException("not yet implemented"); + } + } + + public void trace(String msg, Throwable t) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void trace(Object parameterizedMsg, Object param1) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void trace(String parameterizedMsg, Object param1, Object param2) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + + + public final void debug(String msg) { + if (effectiveLevel.levelInt <= Level.DEBUG_INT) { + throw new UnsupportedOperationException("not yet implemented"); + } + } + + public void debug(String msg, Throwable t) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void debug(Object parameterizedMsg, Object param1) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void debug(String parameterizedMsg, Object param1, Object param2) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void error(String msg) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void error(String msg, Throwable t) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void error(String parameterizedMsg, Object param1) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void error(String parameterizedMsg, Object param1, Object param2) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void info(String msg) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void info(String msg, Throwable t) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void info(String parameterizedMsg, Object param1) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void info(String parameterizedMsg, Object param1, Object param2) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public boolean isTraceEnabled() { + return false; + } + + public boolean isDebugEnabled() { + return false; + } + + public boolean isErrorEnabled() { + return false; // To change body of implemented methods use File | Settings | + // File Templates. + } + + public boolean isInfoEnabled() { + return false; // To change body of implemented methods use File | Settings | + // File Templates. + } + + public boolean isWarnEnabled() { + return false; // To change body of implemented methods use File | Settings | + // File Templates. + } + + public void warn(String msg) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void warn(String msg, Throwable t) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void warn(String parameterizedMsg, Object param1) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void warn(String parameterizedMsg, Object param1, Object param2) { + // To change body of implemented methods use File | Settings | File + // Templates. + } + + public void trace(String format, Object arg) { + } + + public void trace(String format, Object[] argArray) { + } + + public void debug(String format, Object arg) { + } + + public void debug(String format, Object[] argArray) { + } + + public void info(String format, Object[] argArray) { + } + + public void warn(String format, Object[] argArray) { + } + + public void error(String format, Object[] argArray) { + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/HLoggerContext.java b/logback-classic/src/test/java/ch/qos/logback/classic/HLoggerContext.java index 30c1d766e23b7338b32bca8d4676a699b80438ee..9354b0de31ac3e0587ae4b1649a63cf30e7b6450 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/HLoggerContext.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/HLoggerContext.java @@ -1,118 +1,118 @@ -/** - * 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.classic; - -import ch.qos.logback.classic.Level; - - - -/** - * @author ceki - */ -public class HLoggerContext { - - private HLogger root; - private int size; - - public HLoggerContext() { - this.root = new HLogger("root", null); - this.root.setLevel(Level.DEBUG); - size = 1; - } - - /** - * Return this contexts root logger - * - * @return - */ - public HLogger getRootLogger() { - return root; - } - - public HLogger getLogger(final String name) { - - int i = 0; - HLogger HLogger = root; - HLogger childHLogger = null; - String childName; - - while (true) { - int h = name.indexOf('.', i); - if (h == -1) { - childName = name.substring(i); - } else { - childName = name.substring(i, h); - } - // move i left of the last point - i = h + 1; - - synchronized (HLogger) { - childHLogger = HLogger.getChildBySuffix(childName); - if (childHLogger == null) { - childHLogger = HLogger.createChildByLastNamePart(childName); - incSize(); - } - } - HLogger = childHLogger; - if (h == -1) { - return childHLogger; - } - } - } - - private synchronized void incSize() { - size++; - } - - int size() { - return size; - } - /** - * Check if the named logger exists in the hierarchy. If so return - * its reference, otherwise returns null. - * - * @param name the name of the logger to search for. - */ - HLogger exists(String name) { - int i = 0; - HLogger HLogger = root; - HLogger childHLogger = null; - String childName; - while (true) { - int h = name.indexOf('.', i); - if (h == -1) { - childName = name.substring(i); - } else { - childName = name.substring(i, h); - } - // move i left of the last point - i = h + 1; - - synchronized (HLogger) { - childHLogger = HLogger.getChildBySuffix(childName); - if (childHLogger == null) { - return null; - } - } - HLogger = childHLogger; - if (h == -1) { - if (childHLogger.getName().equals(name)) { - return childHLogger; - } else { - return null; - } - } - } - } -} +/** + * 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.classic; + +import ch.qos.logback.classic.Level; + + + +/** + * @author ceki + */ +public class HLoggerContext { + + private HLogger root; + private int size; + + public HLoggerContext() { + this.root = new HLogger("root", null); + this.root.setLevel(Level.DEBUG); + size = 1; + } + + /** + * Return this contexts root logger + * + * @return + */ + public HLogger getRootLogger() { + return root; + } + + public HLogger getLogger(final String name) { + + int i = 0; + HLogger HLogger = root; + HLogger childHLogger = null; + String childName; + + while (true) { + int h = name.indexOf('.', i); + if (h == -1) { + childName = name.substring(i); + } else { + childName = name.substring(i, h); + } + // move i left of the last point + i = h + 1; + + synchronized (HLogger) { + childHLogger = HLogger.getChildBySuffix(childName); + if (childHLogger == null) { + childHLogger = HLogger.createChildByLastNamePart(childName); + incSize(); + } + } + HLogger = childHLogger; + if (h == -1) { + return childHLogger; + } + } + } + + private synchronized void incSize() { + size++; + } + + int size() { + return size; + } + /** + * Check if the named logger exists in the hierarchy. If so return + * its reference, otherwise returns null. + * + * @param name the name of the logger to search for. + */ + HLogger exists(String name) { + int i = 0; + HLogger HLogger = root; + HLogger childHLogger = null; + String childName; + while (true) { + int h = name.indexOf('.', i); + if (h == -1) { + childName = name.substring(i); + } else { + childName = name.substring(i, h); + } + // move i left of the last point + i = h + 1; + + synchronized (HLogger) { + childHLogger = HLogger.getChildBySuffix(childName); + if (childHLogger == null) { + return null; + } + } + HLogger = childHLogger; + if (h == -1) { + if (childHLogger.getName().equals(name)) { + return childHLogger; + } else { + return null; + } + } + } + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextDeadlockTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextDeadlockTest.java index ca1ed1db26b86290f85b846f7e859f0cf7f8110e..954cf038da17b3e158020b70bbe138ac374f3a96 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextDeadlockTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextDeadlockTest.java @@ -1,72 +1,72 @@ -/** - * 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.classic; - -import java.io.ByteArrayInputStream; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; - -public class LoggerContextDeadlockTest { - - LoggerContext loggerContext = new LoggerContext(); - JoranConfigurator jc = new JoranConfigurator(); - GetLoggerThread getLoggerThread = new GetLoggerThread(loggerContext); - - @Before - public void setUp() throws Exception { - jc.setContext(loggerContext); - } - - @After - public void tearDown() throws Exception { - } - - @Test(timeout=20000) - public void testLBCLASSIC_81() throws JoranException { - - - getLoggerThread.start(); - for (int i = 0; i < 500; i++) { - ByteArrayInputStream baos = new ByteArrayInputStream(new String( - "").getBytes()); - jc.doConfigure(baos); - } - } - - class GetLoggerThread extends Thread { - - final LoggerContext loggerContext; - GetLoggerThread(LoggerContext loggerContext) { - this.loggerContext = loggerContext; - } - @Override - public void run() { - for (int i = 0; i < 10000; i++) { - if(i % 100 == 0) { - try { - Thread.sleep(1); - } catch (InterruptedException e) { - } - } - loggerContext.getLogger("a" + i); - } - } - } - -} +/** + * 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.classic; + +import java.io.ByteArrayInputStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; + +public class LoggerContextDeadlockTest { + + LoggerContext loggerContext = new LoggerContext(); + JoranConfigurator jc = new JoranConfigurator(); + GetLoggerThread getLoggerThread = new GetLoggerThread(loggerContext); + + @Before + public void setUp() throws Exception { + jc.setContext(loggerContext); + } + + @After + public void tearDown() throws Exception { + } + + @Test(timeout=20000) + public void testLBCLASSIC_81() throws JoranException { + + + getLoggerThread.start(); + for (int i = 0; i < 500; i++) { + ByteArrayInputStream baos = new ByteArrayInputStream(new String( + "").getBytes()); + jc.doConfigure(baos); + } + } + + class GetLoggerThread extends Thread { + + final LoggerContext loggerContext; + GetLoggerThread(LoggerContext loggerContext) { + this.loggerContext = loggerContext; + } + @Override + public void run() { + for (int i = 0; i < 10000; i++) { + if(i % 100 == 0) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + } + } + loggerContext.getLogger("a" + i); + } + } + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextTest.java index f8f8ccdbd7dc1c54a828b36cfda1c90ec2f77a0e..46f694ef43687330cf0732056e1df7b604c8555c 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextTest.java @@ -1,218 +1,218 @@ -/** - * 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.classic; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.turbo.NOPTurboFilter; -import ch.qos.logback.core.status.StatusManager; - -public class LoggerContextTest { - LoggerContext lc; - - @Before - public void setUp() throws Exception { - Logger.instanceCount = 0; - lc = new LoggerContext(); - lc.setName("x"); - } - - @Test - public void testRootGetLogger() { - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - assertEquals(Level.DEBUG, root.getLevel()); - assertEquals(Level.DEBUG, root.getEffectiveLevel()); - } - - @Test - public void testLoggerX() { - Logger x = lc.getLogger("x"); - assertNotNull(x); - assertEquals("x", x.getName()); - assertNull(x.getLevel()); - assertEquals(Level.DEBUG, x.getEffectiveLevel()); - } - - @Test - public void testNull() { - try { - lc.getLogger((String) null); - fail("null should cause an exception"); - } catch (IllegalArgumentException e) { - } - } - - @Test - public void testEmpty() { - Logger empty = lc.getLogger(""); - LoggerTestHelper.assertNameEquals(empty, ""); - LoggerTestHelper.assertLevels(null, empty, Level.DEBUG); - - Logger dot = lc.getLogger("."); - LoggerTestHelper.assertNameEquals(dot, "."); - // LoggerTestHelper.assertNameEquals(dot.parent, ""); - // LoggerTestHelper.assertNameEquals(dot.parent.parent, "root"); - - // assertNull(dot.parent.parent.parent); - LoggerTestHelper.assertLevels(null, dot, Level.DEBUG); - - assertEquals(3, Logger.instanceCount); - } - - @Test - public void testDotDot() { - Logger dotdot = lc.getLogger(".."); - assertEquals(4, Logger.instanceCount); - LoggerTestHelper.assertNameEquals(dotdot, ".."); - // LoggerTestHelper.assertNameEquals(dotdot.parent, "."); - // LoggerTestHelper.assertNameEquals(dotdot.parent.parent, ""); - // LoggerTestHelper.assertNameEquals(dotdot.parent.parent.parent, "root"); - } - - @Test - public void testLoggerXY() { - assertEquals(1, Logger.instanceCount); - - Logger xy = lc.getLogger("x.y"); - assertEquals(3, Logger.instanceCount); - LoggerTestHelper.assertNameEquals(xy, "x.y"); - LoggerTestHelper.assertLevels(null, xy, Level.DEBUG); - - Logger x = lc.getLogger("x"); - assertEquals(3, Logger.instanceCount); - - Logger xy2 = lc.getLogger("x.y"); - assertEquals(xy, xy2); - - Logger x2 = lc.getLogger("x"); - assertEquals(x, x2); - assertEquals(3, Logger.instanceCount); - } - - @Test - public void testLoggerMultipleChildren() { - assertEquals(1, Logger.instanceCount); - Logger xy0 = lc.getLogger("x.y0"); - LoggerTestHelper.assertNameEquals(xy0, "x.y0"); - - Logger xy1 = lc.getLogger("x.y1"); - LoggerTestHelper.assertNameEquals(xy1, "x.y1"); - - LoggerTestHelper.assertLevels(null, xy0, Level.DEBUG); - LoggerTestHelper.assertLevels(null, xy1, Level.DEBUG); - assertEquals(4, Logger.instanceCount); - - for (int i = 0; i < 100; i++) { - Logger xy_i = lc.getLogger("x.y" + i); - LoggerTestHelper.assertNameEquals(xy_i, "x.y" + i); - LoggerTestHelper.assertLevels(null, xy_i, Level.DEBUG); - } - assertEquals(102, Logger.instanceCount); - } - - @Test - public void testMultiLevel() { - Logger wxyz = lc.getLogger("w.x.y.z"); - LoggerTestHelper.assertNameEquals(wxyz, "w.x.y.z"); - LoggerTestHelper.assertLevels(null, wxyz, Level.DEBUG); - - Logger wx = lc.getLogger("w.x"); - wx.setLevel(Level.INFO); - LoggerTestHelper.assertNameEquals(wx, "w.x"); - LoggerTestHelper.assertLevels(Level.INFO, wx, Level.INFO); - LoggerTestHelper.assertLevels(null, lc.getLogger("w.x.y"), Level.INFO); - LoggerTestHelper.assertLevels(null, wxyz, Level.INFO); - } - - @Test - public void testStatusWithUnconfiguredContext() { - Logger logger = lc.getLogger(LoggerContextTest.class); - - for (int i = 0; i < 3; i++) { - logger.debug("test"); - } - - logger = lc.getLogger("x.y.z"); - - for (int i = 0; i < 3; i++) { - logger.debug("test"); - } - - StatusManager sm = lc.getStatusManager(); - assertTrue("StatusManager has recieved too many messages", - sm.getCount() == 1); - } - - - @Test - public void resetTest() { - - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - Logger a = lc.getLogger("a"); - Logger ab = lc.getLogger("a.b"); - - ab.setLevel(Level.WARN); - root.setLevel(Level.INFO); - lc.reset(); - assertEquals(Level.DEBUG, root.getEffectiveLevel()); - assertTrue(root.isDebugEnabled()); - assertEquals(Level.DEBUG, a.getEffectiveLevel()); - assertEquals(Level.DEBUG, ab.getEffectiveLevel()); - - assertEquals(Level.DEBUG, root.getLevel()); - assertNull(a.getLevel()); - assertNull(ab.getLevel()); - } - - // http://jira.qos.ch/browse/LBCLASSIC-89 - @Test - public void turboFilterStopOnReset() { - NOPTurboFilter nopTF = new NOPTurboFilter(); - nopTF.start(); - lc.addTurboFilter(nopTF); - assertTrue(nopTF.isStarted()); - lc.reset(); - assertFalse(nopTF.isStarted()); - } - - @Test - public void resetTest_LBCORE_104() { - lc.putProperty("keyA", "valA"); - lc.putObject("keyA", "valA"); - assertEquals("valA", lc.getProperty("keyA")); - assertEquals("valA", lc.getObject("keyA")); - lc.reset(); - assertNull(lc.getProperty("keyA")); - assertNull(lc.getObject("keyA")); - } - - @Test - public void levelResetTest() { - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - root.setLevel(Level.TRACE); - assertTrue(root.isTraceEnabled()); - lc.reset(); - assertFalse(root.isTraceEnabled()); - assertTrue(root.isDebugEnabled()); - } - +/** + * 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.classic; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.turbo.NOPTurboFilter; +import ch.qos.logback.core.status.StatusManager; + +public class LoggerContextTest { + LoggerContext lc; + + @Before + public void setUp() throws Exception { + Logger.instanceCount = 0; + lc = new LoggerContext(); + lc.setName("x"); + } + + @Test + public void testRootGetLogger() { + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + assertEquals(Level.DEBUG, root.getLevel()); + assertEquals(Level.DEBUG, root.getEffectiveLevel()); + } + + @Test + public void testLoggerX() { + Logger x = lc.getLogger("x"); + assertNotNull(x); + assertEquals("x", x.getName()); + assertNull(x.getLevel()); + assertEquals(Level.DEBUG, x.getEffectiveLevel()); + } + + @Test + public void testNull() { + try { + lc.getLogger((String) null); + fail("null should cause an exception"); + } catch (IllegalArgumentException e) { + } + } + + @Test + public void testEmpty() { + Logger empty = lc.getLogger(""); + LoggerTestHelper.assertNameEquals(empty, ""); + LoggerTestHelper.assertLevels(null, empty, Level.DEBUG); + + Logger dot = lc.getLogger("."); + LoggerTestHelper.assertNameEquals(dot, "."); + // LoggerTestHelper.assertNameEquals(dot.parent, ""); + // LoggerTestHelper.assertNameEquals(dot.parent.parent, "root"); + + // assertNull(dot.parent.parent.parent); + LoggerTestHelper.assertLevels(null, dot, Level.DEBUG); + + assertEquals(3, Logger.instanceCount); + } + + @Test + public void testDotDot() { + Logger dotdot = lc.getLogger(".."); + assertEquals(4, Logger.instanceCount); + LoggerTestHelper.assertNameEquals(dotdot, ".."); + // LoggerTestHelper.assertNameEquals(dotdot.parent, "."); + // LoggerTestHelper.assertNameEquals(dotdot.parent.parent, ""); + // LoggerTestHelper.assertNameEquals(dotdot.parent.parent.parent, "root"); + } + + @Test + public void testLoggerXY() { + assertEquals(1, Logger.instanceCount); + + Logger xy = lc.getLogger("x.y"); + assertEquals(3, Logger.instanceCount); + LoggerTestHelper.assertNameEquals(xy, "x.y"); + LoggerTestHelper.assertLevels(null, xy, Level.DEBUG); + + Logger x = lc.getLogger("x"); + assertEquals(3, Logger.instanceCount); + + Logger xy2 = lc.getLogger("x.y"); + assertEquals(xy, xy2); + + Logger x2 = lc.getLogger("x"); + assertEquals(x, x2); + assertEquals(3, Logger.instanceCount); + } + + @Test + public void testLoggerMultipleChildren() { + assertEquals(1, Logger.instanceCount); + Logger xy0 = lc.getLogger("x.y0"); + LoggerTestHelper.assertNameEquals(xy0, "x.y0"); + + Logger xy1 = lc.getLogger("x.y1"); + LoggerTestHelper.assertNameEquals(xy1, "x.y1"); + + LoggerTestHelper.assertLevels(null, xy0, Level.DEBUG); + LoggerTestHelper.assertLevels(null, xy1, Level.DEBUG); + assertEquals(4, Logger.instanceCount); + + for (int i = 0; i < 100; i++) { + Logger xy_i = lc.getLogger("x.y" + i); + LoggerTestHelper.assertNameEquals(xy_i, "x.y" + i); + LoggerTestHelper.assertLevels(null, xy_i, Level.DEBUG); + } + assertEquals(102, Logger.instanceCount); + } + + @Test + public void testMultiLevel() { + Logger wxyz = lc.getLogger("w.x.y.z"); + LoggerTestHelper.assertNameEquals(wxyz, "w.x.y.z"); + LoggerTestHelper.assertLevels(null, wxyz, Level.DEBUG); + + Logger wx = lc.getLogger("w.x"); + wx.setLevel(Level.INFO); + LoggerTestHelper.assertNameEquals(wx, "w.x"); + LoggerTestHelper.assertLevels(Level.INFO, wx, Level.INFO); + LoggerTestHelper.assertLevels(null, lc.getLogger("w.x.y"), Level.INFO); + LoggerTestHelper.assertLevels(null, wxyz, Level.INFO); + } + + @Test + public void testStatusWithUnconfiguredContext() { + Logger logger = lc.getLogger(LoggerContextTest.class); + + for (int i = 0; i < 3; i++) { + logger.debug("test"); + } + + logger = lc.getLogger("x.y.z"); + + for (int i = 0; i < 3; i++) { + logger.debug("test"); + } + + StatusManager sm = lc.getStatusManager(); + assertTrue("StatusManager has recieved too many messages", + sm.getCount() == 1); + } + + + @Test + public void resetTest() { + + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + Logger a = lc.getLogger("a"); + Logger ab = lc.getLogger("a.b"); + + ab.setLevel(Level.WARN); + root.setLevel(Level.INFO); + lc.reset(); + assertEquals(Level.DEBUG, root.getEffectiveLevel()); + assertTrue(root.isDebugEnabled()); + assertEquals(Level.DEBUG, a.getEffectiveLevel()); + assertEquals(Level.DEBUG, ab.getEffectiveLevel()); + + assertEquals(Level.DEBUG, root.getLevel()); + assertNull(a.getLevel()); + assertNull(ab.getLevel()); + } + + // http://jira.qos.ch/browse/LBCLASSIC-89 + @Test + public void turboFilterStopOnReset() { + NOPTurboFilter nopTF = new NOPTurboFilter(); + nopTF.start(); + lc.addTurboFilter(nopTF); + assertTrue(nopTF.isStarted()); + lc.reset(); + assertFalse(nopTF.isStarted()); + } + + @Test + public void resetTest_LBCORE_104() { + lc.putProperty("keyA", "valA"); + lc.putObject("keyA", "valA"); + assertEquals("valA", lc.getProperty("keyA")); + assertEquals("valA", lc.getObject("keyA")); + lc.reset(); + assertNull(lc.getProperty("keyA")); + assertNull(lc.getObject("keyA")); + } + + @Test + public void levelResetTest() { + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + root.setLevel(Level.TRACE); + assertTrue(root.isTraceEnabled()); + lc.reset(); + assertFalse(root.isTraceEnabled()); + assertTrue(root.isDebugEnabled()); + } + } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java index 948d65234e63442a06c3f5916b8ed4f227064f64..89608a35528b5ecdb7dcb9469087f822e6d3c1d2 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java @@ -1,251 +1,251 @@ -/** - * 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.classic; - -import static org.junit.Assert.assertTrue; - -import org.junit.Before; -import org.junit.Test; -import org.slf4j.helpers.BogoPerf; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.turbo.NOPTurboFilter; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.UnsynchronizedAppenderBase; -import ch.qos.logback.core.appender.NOPAppender; -import ch.qos.logback.core.testUtil.Env; - -public class LoggerPerfTest { - - static final long NANOS_IN_ONE_SEC = 1000 * 1000 * 1000L; - static long NORMAL_RUN_LENGTH = 1 * 1000 * 1000; - static long SHORTENED_RUN_LENGTH = 500 * 1000; - - LoggerContext lc = new LoggerContext(); - Logger lbLogger = lc.getLogger(this.getClass()); - org.slf4j.Logger logger = lbLogger; - - @Before - public void setUp() throws Exception { - } - - // =========================================================================== - @Test - public void durationOfDisabledLogsWith_1_NOPFilter() { - double avg = computeDurationOfDisabledLogsWith_1_NOPFilter(1, - NORMAL_RUN_LENGTH); - System.out.println("durationOfDisabledLogsWith_1_NOPFilter=" + avg); - long referencePerf = 60; - - BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); - } - - double computeDurationOfDisabledLogsWith_1_NOPFilter(int numOfFilters, - long len) { - for (int i = 0; i < numOfFilters; i++) { - lc.addTurboFilter(new NOPTurboFilter()); - } - lbLogger.setLevel(Level.OFF); - for (long i = 0; i < len; i++) - logger.debug("Toto"); - - long start = System.nanoTime(); - for (long i = 0; i < len; i++) - logger.debug("Toto"); - - return (System.nanoTime() - start) / len; - } - - // =========================================================================== - @Test - public void durationOfIsDebugEnabled() { - double avg = computedurationOfIsDebugEnabled(10 * NORMAL_RUN_LENGTH); - System.out.println("durationOfIsDebugEnabled=" + avg); - - long referencePerf = 15; - BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); - } - - double computedurationOfIsDebugEnabled(final long len) { - lbLogger.setLevel(Level.OFF); - for (long i = 0; i < len; i++) - logger.isDebugEnabled(); - - long start = System.nanoTime(); - for (long i = 0; i < len; i++) - logger.isDebugEnabled(); - return (System.nanoTime() - start) / len; - } - - // =========================================================================== - @Test - public void durationOfDisabledLog_NoParameters() { - double avg = computeDurationOfDisabledLog_NoParameters(10 * NORMAL_RUN_LENGTH); - System.out.println("durationOfDisabledLog_NoParameters=" + avg); - - long referencePerf = 18; - BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); - } - - double computeDurationOfDisabledLog_NoParameters(final long len) { - lbLogger.setLevel(Level.OFF); - for (long i = 0; i < len; i++) - logger.debug("Toto"); - - long start = System.nanoTime(); - for (long i = 0; i < len; i++) - logger.debug("Toto"); - return (System.nanoTime() - start) / len; - } - - // =========================================================================== - - @Test - public void durationOfDisabledLog_1_Parameter() { - double avgDuration = computeDurationOfDisabledLog_1_Parameter(NORMAL_RUN_LENGTH); - System.out.println("durationOfDisabledLog_1_Parameter=" + avgDuration); - - long referencePerf = 30; - BogoPerf.assertDuration(avgDuration, referencePerf, - CoreConstants.REFERENCE_BIPS); - } - - double computeDurationOfDisabledLog_1_Parameter(long len) { - lbLogger.setLevel(Level.OFF); - final Object o = new Object(); - for (long i = 0; i < len; i++) - logger.debug("Toto {}", o); - - long start = System.nanoTime(); - for (long i = 0; i < len; i++) - logger.debug("Toto {}", o); - - long end = System.nanoTime(); - return (end - start) / len; - } - - // =========================================================================== - - @Test - public void durationOfEnabledLog() { - if (Env.isLinux()) { - // the JIT on Linux behaves very differently - return; - } - double avgDuration = computeDurationOfEnabledLog(SHORTENED_RUN_LENGTH); - System.out.println("durationOfEnabledLog=" + avgDuration); - - long referencePerf = 800; - BogoPerf.assertDuration(avgDuration, referencePerf, - CoreConstants.REFERENCE_BIPS); - } - - double computeDurationOfEnabledLog(long len) { - lbLogger.setLevel(Level.ALL); - - NOPAppender nopAppender = new NOPAppender(); - nopAppender.start(); - ((ch.qos.logback.classic.Logger) logger).addAppender(nopAppender); - for (long i = 0; i < len; i++) { - logger.debug("Toto"); - } - long start = System.nanoTime(); - for (long i = 0; i < len; i++) { - logger.debug("Toto"); - } - long end = System.nanoTime(); - return (end - start) / len; - } - - // =========================================================================== - - @Test - public void testThreadedLogging() throws InterruptedException { - SleepAppender appender = new SleepAppender(); - - int MILLIS_PER_CALL = 250; - int NANOS_PER_CALL = 250 * 1000 * 1000; - - appender.setDuration(MILLIS_PER_CALL); - appender.start(); - - lbLogger.addAppender(appender); - lbLogger.setLevel(Level.DEBUG); - long start; - long end; - int threadCount = 10; - int iterCount = 5; - TestRunner[] threads = new TestRunner[threadCount]; - for (int i = 0; i < threads.length; ++i) { - threads[i] = new TestRunner(logger, iterCount); - } - start = System.nanoTime(); - for (Thread thread : threads) { - thread.start(); - } - for (TestRunner thread : threads) { - thread.join(); - } - end = System.nanoTime(); - double tolerance = threadCount * .125; // Very little thread contention - // should occur in this test. - double max = ((((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) * iterCount) - * tolerance; - double serialized = (((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) - * iterCount * threadCount; - double actual = ((double) (end - start)) / NANOS_IN_ONE_SEC; - System.out - .printf( - "Sleep duration: %,.4f seconds. Max expected: %,.4f seconds, Serialized: %,.4f\n", - actual, max, serialized); - assertTrue("Exceeded maximum expected time.", actual < max); - } - - // ============================================================ - private static class TestRunner extends Thread { - private org.slf4j.Logger logger; - private long len; - - public TestRunner(org.slf4j.Logger logger, long len) { - this.logger = logger; - this.len = len; - } - - public void run() { - Thread.yield(); - for (long i = 0; i < len; i++) { - logger.debug("Toto"); - } - } - } - - // ============================================================ - public static class SleepAppender extends UnsynchronizedAppenderBase { - private static long duration = 500; - - public void setDuration(long millis) { - duration = millis; - } - - @Override - protected void append(E eventObject) { - try { - Thread.sleep(duration); - } catch (InterruptedException ie) { - // Ignore - } - } - } - // ============================================================ -} +/** + * 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.classic; + +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; +import org.slf4j.helpers.BogoPerf; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.turbo.NOPTurboFilter; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.UnsynchronizedAppenderBase; +import ch.qos.logback.core.appender.NOPAppender; +import ch.qos.logback.core.testUtil.Env; + +public class LoggerPerfTest { + + static final long NANOS_IN_ONE_SEC = 1000 * 1000 * 1000L; + static long NORMAL_RUN_LENGTH = 1 * 1000 * 1000; + static long SHORTENED_RUN_LENGTH = 500 * 1000; + + LoggerContext lc = new LoggerContext(); + Logger lbLogger = lc.getLogger(this.getClass()); + org.slf4j.Logger logger = lbLogger; + + @Before + public void setUp() throws Exception { + } + + // =========================================================================== + @Test + public void durationOfDisabledLogsWith_1_NOPFilter() { + double avg = computeDurationOfDisabledLogsWith_1_NOPFilter(1, + NORMAL_RUN_LENGTH); + System.out.println("durationOfDisabledLogsWith_1_NOPFilter=" + avg); + long referencePerf = 60; + + BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); + } + + double computeDurationOfDisabledLogsWith_1_NOPFilter(int numOfFilters, + long len) { + for (int i = 0; i < numOfFilters; i++) { + lc.addTurboFilter(new NOPTurboFilter()); + } + lbLogger.setLevel(Level.OFF); + for (long i = 0; i < len; i++) + logger.debug("Toto"); + + long start = System.nanoTime(); + for (long i = 0; i < len; i++) + logger.debug("Toto"); + + return (System.nanoTime() - start) / len; + } + + // =========================================================================== + @Test + public void durationOfIsDebugEnabled() { + double avg = computedurationOfIsDebugEnabled(10 * NORMAL_RUN_LENGTH); + System.out.println("durationOfIsDebugEnabled=" + avg); + + long referencePerf = 15; + BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); + } + + double computedurationOfIsDebugEnabled(final long len) { + lbLogger.setLevel(Level.OFF); + for (long i = 0; i < len; i++) + logger.isDebugEnabled(); + + long start = System.nanoTime(); + for (long i = 0; i < len; i++) + logger.isDebugEnabled(); + return (System.nanoTime() - start) / len; + } + + // =========================================================================== + @Test + public void durationOfDisabledLog_NoParameters() { + double avg = computeDurationOfDisabledLog_NoParameters(10 * NORMAL_RUN_LENGTH); + System.out.println("durationOfDisabledLog_NoParameters=" + avg); + + long referencePerf = 18; + BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); + } + + double computeDurationOfDisabledLog_NoParameters(final long len) { + lbLogger.setLevel(Level.OFF); + for (long i = 0; i < len; i++) + logger.debug("Toto"); + + long start = System.nanoTime(); + for (long i = 0; i < len; i++) + logger.debug("Toto"); + return (System.nanoTime() - start) / len; + } + + // =========================================================================== + + @Test + public void durationOfDisabledLog_1_Parameter() { + double avgDuration = computeDurationOfDisabledLog_1_Parameter(NORMAL_RUN_LENGTH); + System.out.println("durationOfDisabledLog_1_Parameter=" + avgDuration); + + long referencePerf = 30; + BogoPerf.assertDuration(avgDuration, referencePerf, + CoreConstants.REFERENCE_BIPS); + } + + double computeDurationOfDisabledLog_1_Parameter(long len) { + lbLogger.setLevel(Level.OFF); + final Object o = new Object(); + for (long i = 0; i < len; i++) + logger.debug("Toto {}", o); + + long start = System.nanoTime(); + for (long i = 0; i < len; i++) + logger.debug("Toto {}", o); + + long end = System.nanoTime(); + return (end - start) / len; + } + + // =========================================================================== + + @Test + public void durationOfEnabledLog() { + if (Env.isLinux()) { + // the JIT on Linux behaves very differently + return; + } + double avgDuration = computeDurationOfEnabledLog(SHORTENED_RUN_LENGTH); + System.out.println("durationOfEnabledLog=" + avgDuration); + + long referencePerf = 800; + BogoPerf.assertDuration(avgDuration, referencePerf, + CoreConstants.REFERENCE_BIPS); + } + + double computeDurationOfEnabledLog(long len) { + lbLogger.setLevel(Level.ALL); + + NOPAppender nopAppender = new NOPAppender(); + nopAppender.start(); + ((ch.qos.logback.classic.Logger) logger).addAppender(nopAppender); + for (long i = 0; i < len; i++) { + logger.debug("Toto"); + } + long start = System.nanoTime(); + for (long i = 0; i < len; i++) { + logger.debug("Toto"); + } + long end = System.nanoTime(); + return (end - start) / len; + } + + // =========================================================================== + + @Test + public void testThreadedLogging() throws InterruptedException { + SleepAppender appender = new SleepAppender(); + + int MILLIS_PER_CALL = 250; + int NANOS_PER_CALL = 250 * 1000 * 1000; + + appender.setDuration(MILLIS_PER_CALL); + appender.start(); + + lbLogger.addAppender(appender); + lbLogger.setLevel(Level.DEBUG); + long start; + long end; + int threadCount = 10; + int iterCount = 5; + TestRunner[] threads = new TestRunner[threadCount]; + for (int i = 0; i < threads.length; ++i) { + threads[i] = new TestRunner(logger, iterCount); + } + start = System.nanoTime(); + for (Thread thread : threads) { + thread.start(); + } + for (TestRunner thread : threads) { + thread.join(); + } + end = System.nanoTime(); + double tolerance = threadCount * .125; // Very little thread contention + // should occur in this test. + double max = ((((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) * iterCount) + * tolerance; + double serialized = (((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) + * iterCount * threadCount; + double actual = ((double) (end - start)) / NANOS_IN_ONE_SEC; + System.out + .printf( + "Sleep duration: %,.4f seconds. Max expected: %,.4f seconds, Serialized: %,.4f\n", + actual, max, serialized); + assertTrue("Exceeded maximum expected time.", actual < max); + } + + // ============================================================ + private static class TestRunner extends Thread { + private org.slf4j.Logger logger; + private long len; + + public TestRunner(org.slf4j.Logger logger, long len) { + this.logger = logger; + this.len = len; + } + + public void run() { + Thread.yield(); + for (long i = 0; i < len; i++) { + logger.debug("Toto"); + } + } + } + + // ============================================================ + public static class SleepAppender extends UnsynchronizedAppenderBase { + private static long duration = 500; + + public void setDuration(long millis) { + duration = millis; + } + + @Override + protected void append(E eventObject) { + try { + Thread.sleep(duration); + } catch (InterruptedException ie) { + // Ignore + } + } + } + // ============================================================ +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java index 2a3f7fe7cedb0d1c6d09c64d6e2f604864b86e28..f4a6d32246af34a0b761db1454f0bfa95d2b743d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java @@ -1,71 +1,71 @@ -/** - * 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.classic; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class LoggerSerializationTest { - - LoggerContext lc; - Logger logger; - - ByteArrayOutputStream bos; - ObjectOutputStream oos; - ObjectInputStream inputStream; - - @Before - public void setUp() throws Exception { - lc = new LoggerContext(); - lc.setName("testContext"); - logger = lc.getLogger(LoggerSerializationTest.class); - // create the byte output stream - bos = new ByteArrayOutputStream(); - oos = new ObjectOutputStream(bos); - } - - @After - public void tearDown() throws Exception { - lc = null; - logger = null; - } - - @Test - public void serialization() throws IOException, ClassNotFoundException { - Foo foo = new Foo(logger); - foo.doFoo(); - Foo fooBack = writeAndRead(foo); - fooBack.doFoo(); - } - - private Foo writeAndRead(Foo foo) throws IOException, - ClassNotFoundException { - oos.writeObject(foo); - oos.flush(); - oos.close(); - ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); - inputStream = new ObjectInputStream(bis); - - Foo fooBack = (Foo) inputStream.readObject(); - inputStream.close(); - return fooBack; - } -} +/** + * 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.classic; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class LoggerSerializationTest { + + LoggerContext lc; + Logger logger; + + ByteArrayOutputStream bos; + ObjectOutputStream oos; + ObjectInputStream inputStream; + + @Before + public void setUp() throws Exception { + lc = new LoggerContext(); + lc.setName("testContext"); + logger = lc.getLogger(LoggerSerializationTest.class); + // create the byte output stream + bos = new ByteArrayOutputStream(); + oos = new ObjectOutputStream(bos); + } + + @After + public void tearDown() throws Exception { + lc = null; + logger = null; + } + + @Test + public void serialization() throws IOException, ClassNotFoundException { + Foo foo = new Foo(logger); + foo.doFoo(); + Foo fooBack = writeAndRead(foo); + fooBack.doFoo(); + } + + private Foo writeAndRead(Foo foo) throws IOException, + ClassNotFoundException { + oos.writeObject(foo); + oos.flush(); + oos.close(); + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + inputStream = new ObjectInputStream(bis); + + Foo fooBack = (Foo) inputStream.readObject(); + inputStream.close(); + return fooBack; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTest.java index f6350f988b1a7ad827ca8dd8de245bb76b13b99e..6004a9bdd60cb2f9326b673f45edfc157ddbbffd 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTest.java @@ -1,227 +1,227 @@ -/** - * 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.classic; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.List; - -import org.junit.Test; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.read.ListAppender; -import ch.qos.logback.core.status.Status; - -public class LoggerTest { - - LoggerContext lc = new LoggerContext(); - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - Logger loggerTest = lc.getLogger(LoggerTest.class); - - ListAppender listAppender = new ListAppender(); - - @Test - public void smoke() { - ListAppender listAppender = new ListAppender(); - listAppender.start(); - root.addAppender(listAppender); - Logger logger = lc.getLogger(LoggerTest.class); - assertEquals(0, listAppender.list.size()); - logger.debug("hello"); - assertEquals(1, listAppender.list.size()); - } - - @Test - public void testNoStart() { - // listAppender.start(); - listAppender.setContext(lc); - root.addAppender(listAppender); - Logger logger = lc.getLogger(LoggerTest.class); - logger.debug("hello"); - - List statusList = lc.getStatusManager().getCopyOfStatusList(); - Status s0 = statusList.get(0); - assertEquals(Status.WARN, s0.getLevel()); - assertTrue(s0.getMessage().startsWith("Attempted to append to non started")); - } - - @Test - public void testAdditive() { - listAppender.start(); - root.addAppender(listAppender); - loggerTest.addAppender(listAppender); - loggerTest.setAdditive(false); - loggerTest.debug("hello"); - // 1 instead of two, since logger is not additive - assertEquals(1, listAppender.list.size()); - } - - @Test - public void testRootLogger() { - Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); - LoggerContext lc = logger.getLoggerContext(); - - assertNotNull("Returned logger is null", logger); - assertEquals("Return logger isn't named root", logger.getName(), - Logger.ROOT_LOGGER_NAME); - assertTrue("logger instances should be indentical", logger == lc.root); - } - - @Test - public void testBasicFiltering() throws Exception { - listAppender.start(); - root.addAppender(listAppender); - root.setLevel(Level.INFO); - loggerTest.debug("x"); - assertEquals(0, listAppender.list.size()); - loggerTest.info("x"); - loggerTest.warn("x"); - loggerTest.error("x"); - assertEquals(3, listAppender.list.size()); - } - - void checkLevelThreshold(Logger logger, Level threshold) { - - if (Level.ERROR_INT >= threshold.levelInt) { - assertTrue(logger.isErrorEnabled()); - assertTrue(logger.isEnabledFor(Level.ERROR)); - } else { - assertFalse(logger.isErrorEnabled()); - assertFalse(logger.isEnabledFor(Level.ERROR)); - } - - if (Level.WARN_INT >= threshold.levelInt) { - assertTrue(logger.isWarnEnabled()); - assertTrue(logger.isEnabledFor(Level.WARN)); - } else { - assertFalse(logger.isWarnEnabled()); - assertFalse(logger.isEnabledFor(Level.WARN)); - } - if (Level.INFO_INT >= threshold.levelInt) { - assertTrue(logger.isInfoEnabled()); - assertTrue(logger.isEnabledFor(Level.INFO)); - } else { - assertFalse(logger.isInfoEnabled()); - assertFalse(logger.isEnabledFor(Level.INFO)); - } - if (Level.DEBUG_INT >= threshold.levelInt) { - assertTrue(logger.isDebugEnabled()); - assertTrue(logger.isEnabledFor(Level.DEBUG)); - } else { - assertFalse(logger.isDebugEnabled()); - assertFalse(logger.isEnabledFor(Level.DEBUG)); - } - if (Level.TRACE_INT >= threshold.levelInt) { - assertTrue(logger.isTraceEnabled()); - assertTrue(logger.isEnabledFor(Level.TRACE)); - } else { - assertFalse(logger.isTraceEnabled()); - assertFalse(logger.isEnabledFor(Level.TRACE)); - } - } - - @Test - public void innerClass_I() { - root.setLevel(Level.DEBUG); - Logger a = lc.getLogger("a"); - a.setLevel(Level.INFO); - Logger a_b = lc.getLogger("a$b"); - assertEquals(Level.INFO, a_b.getEffectiveLevel()); - } - - @Test - public void innerClass_II() { - root.setLevel(Level.DEBUG); - Logger a = lc.getLogger(this.getClass()); - a.setLevel(Level.INFO); - Logger a_b = lc.getLogger(new Inner().getClass()); - assertEquals(Level.INFO, a_b.getEffectiveLevel()); - } - - - class Inner { - } - - @Test - public void testEnabled_All() throws Exception { - root.setLevel(Level.ALL); - checkLevelThreshold(loggerTest, Level.ALL); - } - - @Test - public void testEnabled_Debug() throws Exception { - root.setLevel(Level.DEBUG); - checkLevelThreshold(loggerTest, Level.DEBUG); - } - - @Test - public void testEnabled_Info() throws Exception { - root.setLevel(Level.INFO); - checkLevelThreshold(loggerTest, Level.INFO); - } - - @Test - public void testEnabledX_Warn() throws Exception { - root.setLevel(Level.WARN); - checkLevelThreshold(loggerTest, Level.WARN); - } - - public void testEnabledX_Errror() throws Exception { - root.setLevel(Level.ERROR); - checkLevelThreshold(loggerTest, Level.ERROR); - } - - @Test - public void testEnabledX_Off() throws Exception { - root.setLevel(Level.OFF); - checkLevelThreshold(loggerTest, Level.OFF); - } - - @Test - public void setRootLevelToNull() { - try { - root.setLevel(null); - fail("The level of the root logger should not be settable to null"); - } catch (IllegalArgumentException e) { - } - } - - @Test - public void setLevelToNull_A() { - loggerTest.setLevel(null); - assertEquals(root.getEffectiveLevel(), loggerTest.getEffectiveLevel()); - } - - @Test - public void setLevelToNull_B() { - loggerTest.setLevel(Level.DEBUG); - loggerTest.setLevel(null); - assertEquals(root.getEffectiveLevel(), loggerTest.getEffectiveLevel()); - } - - @Test - public void setLevelToNull_LBCLASSIC_91() { - loggerTest.setLevel(Level.DEBUG); - ch.qos.logback.classic.Logger child = lc.getLogger(loggerTest.getName() + ".child"); - loggerTest.setLevel(null); - assertEquals(root.getEffectiveLevel(), loggerTest.getEffectiveLevel()); - assertEquals(root.getEffectiveLevel(), child.getEffectiveLevel()); - } - -} +/** + * 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.classic; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.List; + +import org.junit.Test; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import ch.qos.logback.core.status.Status; + +public class LoggerTest { + + LoggerContext lc = new LoggerContext(); + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + Logger loggerTest = lc.getLogger(LoggerTest.class); + + ListAppender listAppender = new ListAppender(); + + @Test + public void smoke() { + ListAppender listAppender = new ListAppender(); + listAppender.start(); + root.addAppender(listAppender); + Logger logger = lc.getLogger(LoggerTest.class); + assertEquals(0, listAppender.list.size()); + logger.debug("hello"); + assertEquals(1, listAppender.list.size()); + } + + @Test + public void testNoStart() { + // listAppender.start(); + listAppender.setContext(lc); + root.addAppender(listAppender); + Logger logger = lc.getLogger(LoggerTest.class); + logger.debug("hello"); + + List statusList = lc.getStatusManager().getCopyOfStatusList(); + Status s0 = statusList.get(0); + assertEquals(Status.WARN, s0.getLevel()); + assertTrue(s0.getMessage().startsWith("Attempted to append to non started")); + } + + @Test + public void testAdditive() { + listAppender.start(); + root.addAppender(listAppender); + loggerTest.addAppender(listAppender); + loggerTest.setAdditive(false); + loggerTest.debug("hello"); + // 1 instead of two, since logger is not additive + assertEquals(1, listAppender.list.size()); + } + + @Test + public void testRootLogger() { + Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); + LoggerContext lc = logger.getLoggerContext(); + + assertNotNull("Returned logger is null", logger); + assertEquals("Return logger isn't named root", logger.getName(), + Logger.ROOT_LOGGER_NAME); + assertTrue("logger instances should be indentical", logger == lc.root); + } + + @Test + public void testBasicFiltering() throws Exception { + listAppender.start(); + root.addAppender(listAppender); + root.setLevel(Level.INFO); + loggerTest.debug("x"); + assertEquals(0, listAppender.list.size()); + loggerTest.info("x"); + loggerTest.warn("x"); + loggerTest.error("x"); + assertEquals(3, listAppender.list.size()); + } + + void checkLevelThreshold(Logger logger, Level threshold) { + + if (Level.ERROR_INT >= threshold.levelInt) { + assertTrue(logger.isErrorEnabled()); + assertTrue(logger.isEnabledFor(Level.ERROR)); + } else { + assertFalse(logger.isErrorEnabled()); + assertFalse(logger.isEnabledFor(Level.ERROR)); + } + + if (Level.WARN_INT >= threshold.levelInt) { + assertTrue(logger.isWarnEnabled()); + assertTrue(logger.isEnabledFor(Level.WARN)); + } else { + assertFalse(logger.isWarnEnabled()); + assertFalse(logger.isEnabledFor(Level.WARN)); + } + if (Level.INFO_INT >= threshold.levelInt) { + assertTrue(logger.isInfoEnabled()); + assertTrue(logger.isEnabledFor(Level.INFO)); + } else { + assertFalse(logger.isInfoEnabled()); + assertFalse(logger.isEnabledFor(Level.INFO)); + } + if (Level.DEBUG_INT >= threshold.levelInt) { + assertTrue(logger.isDebugEnabled()); + assertTrue(logger.isEnabledFor(Level.DEBUG)); + } else { + assertFalse(logger.isDebugEnabled()); + assertFalse(logger.isEnabledFor(Level.DEBUG)); + } + if (Level.TRACE_INT >= threshold.levelInt) { + assertTrue(logger.isTraceEnabled()); + assertTrue(logger.isEnabledFor(Level.TRACE)); + } else { + assertFalse(logger.isTraceEnabled()); + assertFalse(logger.isEnabledFor(Level.TRACE)); + } + } + + @Test + public void innerClass_I() { + root.setLevel(Level.DEBUG); + Logger a = lc.getLogger("a"); + a.setLevel(Level.INFO); + Logger a_b = lc.getLogger("a$b"); + assertEquals(Level.INFO, a_b.getEffectiveLevel()); + } + + @Test + public void innerClass_II() { + root.setLevel(Level.DEBUG); + Logger a = lc.getLogger(this.getClass()); + a.setLevel(Level.INFO); + Logger a_b = lc.getLogger(new Inner().getClass()); + assertEquals(Level.INFO, a_b.getEffectiveLevel()); + } + + + class Inner { + } + + @Test + public void testEnabled_All() throws Exception { + root.setLevel(Level.ALL); + checkLevelThreshold(loggerTest, Level.ALL); + } + + @Test + public void testEnabled_Debug() throws Exception { + root.setLevel(Level.DEBUG); + checkLevelThreshold(loggerTest, Level.DEBUG); + } + + @Test + public void testEnabled_Info() throws Exception { + root.setLevel(Level.INFO); + checkLevelThreshold(loggerTest, Level.INFO); + } + + @Test + public void testEnabledX_Warn() throws Exception { + root.setLevel(Level.WARN); + checkLevelThreshold(loggerTest, Level.WARN); + } + + public void testEnabledX_Errror() throws Exception { + root.setLevel(Level.ERROR); + checkLevelThreshold(loggerTest, Level.ERROR); + } + + @Test + public void testEnabledX_Off() throws Exception { + root.setLevel(Level.OFF); + checkLevelThreshold(loggerTest, Level.OFF); + } + + @Test + public void setRootLevelToNull() { + try { + root.setLevel(null); + fail("The level of the root logger should not be settable to null"); + } catch (IllegalArgumentException e) { + } + } + + @Test + public void setLevelToNull_A() { + loggerTest.setLevel(null); + assertEquals(root.getEffectiveLevel(), loggerTest.getEffectiveLevel()); + } + + @Test + public void setLevelToNull_B() { + loggerTest.setLevel(Level.DEBUG); + loggerTest.setLevel(null); + assertEquals(root.getEffectiveLevel(), loggerTest.getEffectiveLevel()); + } + + @Test + public void setLevelToNull_LBCLASSIC_91() { + loggerTest.setLevel(Level.DEBUG); + ch.qos.logback.classic.Logger child = lc.getLogger(loggerTest.getName() + ".child"); + loggerTest.setLevel(null); + assertEquals(root.getEffectiveLevel(), loggerTest.getEffectiveLevel()); + assertEquals(root.getEffectiveLevel(), child.getEffectiveLevel()); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java index 7ba0cfdee976a6122a4dfab95b1338a04970465a..a062b32236c54319fbf315e082c743a7cc7ae545 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java @@ -1,35 +1,35 @@ -/** - * 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.classic; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import junit.framework.*; - -public class LoggerTestHelper extends TestCase { - - - static void assertNameEquals(Logger logger, String name) { - assertNotNull(logger); - assertEquals(name, logger.getName()); - } - static void assertLevels(Level level, Logger logger, Level effectiveLevel) { - if(level == null) { - assertNull(logger.getLevel()); - } else { - assertEquals(level, logger.getLevel()); - } - assertEquals(effectiveLevel, logger.getEffectiveLevel()); - } +/** + * 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.classic; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import junit.framework.*; + +public class LoggerTestHelper extends TestCase { + + + static void assertNameEquals(Logger logger, String name) { + assertNotNull(logger); + assertEquals(name, logger.getName()); + } + static void assertLevels(Level level, Logger logger, Level effectiveLevel) { + if(level == null) { + assertNull(logger.getLevel()); + } else { + assertEquals(level, logger.getLevel()); + } + assertEquals(effectiveLevel, logger.getEffectiveLevel()); + } } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/MDCTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/MDCTest.java index 4a48191ed850499622750204a316a57452f5024d..91b2a0670fbc46df5459123c5d5fbea47f3bead6 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/MDCTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/MDCTest.java @@ -1,52 +1,52 @@ -/** - * 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.classic; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import java.util.HashMap; - -import org.junit.Test; -import org.slf4j.MDC; - -public class MDCTest { - - @Test - public void test() throws InterruptedException { - MDCTestThread threadA = new MDCTestThread("a"); - threadA.start(); - - MDCTestThread threadB = new MDCTestThread("b"); - threadB.start(); - - threadA.join(); - threadB.join(); - - assertNull(threadA.x0); - assertEquals("a", threadA.x1); - assertNull(threadA.x2); - - assertNull(threadB.x0); - assertEquals("b", threadB.x1); - assertNull(threadB.x2); - - } - - @Test - public void testLBCLASSIC_98() { - MDC.setContextMap(new HashMap()); - } - -} +/** + * 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.classic; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.HashMap; + +import org.junit.Test; +import org.slf4j.MDC; + +public class MDCTest { + + @Test + public void test() throws InterruptedException { + MDCTestThread threadA = new MDCTestThread("a"); + threadA.start(); + + MDCTestThread threadB = new MDCTestThread("b"); + threadB.start(); + + threadA.join(); + threadB.join(); + + assertNull(threadA.x0); + assertEquals("a", threadA.x1); + assertNull(threadA.x2); + + assertNull(threadB.x0); + assertEquals("b", threadB.x1); + assertNull(threadB.x2); + + } + + @Test + public void testLBCLASSIC_98() { + MDC.setContextMap(new HashMap()); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/MDCTestThread.java b/logback-classic/src/test/java/ch/qos/logback/classic/MDCTestThread.java index 524aa6e3cfaa6fadd4fe072c6c94071273bd2b41..51cef97c8c1c83150312f86cc5bbea60585f3ea6 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/MDCTestThread.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/MDCTestThread.java @@ -1,39 +1,39 @@ -/** - * 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.classic; - -import org.slf4j.MDC; - -public class MDCTestThread extends Thread { - - String val; - - public MDCTestThread(String val) { - super(); - this.val = val; - } - - String x0; - String x1; - String x2; - - public void run() { - x0 = MDC.get("x"); - MDC.put("x", val); - x1 = MDC.get("x"); - MDC.clear(); - x2 = MDC.get("x"); - //System.out.println("Exiting "+val); - } +/** + * 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.classic; + +import org.slf4j.MDC; + +public class MDCTestThread extends Thread { + + String val; + + public MDCTestThread(String val) { + super(); + this.val = val; + } + + String x0; + String x1; + String x2; + + public void run() { + x0 = MDC.get("x"); + MDC.put("x", val); + x1 = MDC.get("x"); + MDC.clear(); + x2 = MDC.get("x"); + //System.out.println("Exiting "+val); + } } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/MessageFormattingTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/MessageFormattingTest.java index 3c610b42afbf7842be9b1c6c4919aa3a8c27e9d4..3d2230b7525b41c035d913027b5e99a96afae376 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/MessageFormattingTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/MessageFormattingTest.java @@ -1,84 +1,84 @@ -/** - * 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.classic; - -import static org.junit.Assert.assertEquals; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.read.ListAppender; - -public class MessageFormattingTest { - - LoggerContext lc; - ListAppender listAppender; - - @Before - public void setUp() { - lc = new LoggerContext(); - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - listAppender = new ListAppender(); - listAppender.setContext(lc); - listAppender.start(); - logger.addAppender(listAppender); - } - - @Test - public void testFormattingOneArg() { - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - logger.debug("{}", new Integer(12)); - ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); - assertEquals("12", event.getFormattedMessage()); - } - - @Test - public void testFormattingTwoArg() { - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - logger.debug("{}-{}", new Integer(12), new Integer(13)); - ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); - assertEquals("12-13", event.getFormattedMessage()); - } - - @Test - public void testNoFormatting() { - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - logger.debug("test", new Integer(12), new Integer(13)); - ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); - assertEquals("test", event.getFormattedMessage()); - } - - @Test - public void testNoFormatting2() { - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - logger.debug("test"); - ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); - assertEquals("test", event.getFormattedMessage()); - } - - @Test - public void testMessageConverter() { - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - logger.debug("{}", 12); - ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); - PatternLayout layout = new PatternLayout(); - layout.setContext(lc); - layout.setPattern("%m"); - layout.start(); - String formattedMessage = layout.doLayout(event); - assertEquals("12", formattedMessage); - } - -} +/** + * 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.classic; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; + +public class MessageFormattingTest { + + LoggerContext lc; + ListAppender listAppender; + + @Before + public void setUp() { + lc = new LoggerContext(); + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + listAppender = new ListAppender(); + listAppender.setContext(lc); + listAppender.start(); + logger.addAppender(listAppender); + } + + @Test + public void testFormattingOneArg() { + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + logger.debug("{}", new Integer(12)); + ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); + assertEquals("12", event.getFormattedMessage()); + } + + @Test + public void testFormattingTwoArg() { + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + logger.debug("{}-{}", new Integer(12), new Integer(13)); + ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); + assertEquals("12-13", event.getFormattedMessage()); + } + + @Test + public void testNoFormatting() { + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + logger.debug("test", new Integer(12), new Integer(13)); + ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); + assertEquals("test", event.getFormattedMessage()); + } + + @Test + public void testNoFormatting2() { + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + logger.debug("test"); + ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); + assertEquals("test", event.getFormattedMessage()); + } + + @Test + public void testMessageConverter() { + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + logger.debug("{}", 12); + ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); + PatternLayout layout = new PatternLayout(); + layout.setContext(lc); + layout.setPattern("%m"); + layout.start(); + String formattedMessage = layout.doLayout(event); + assertEquals("12", formattedMessage); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java index 98969ecb96f0378a9cf5c2d14be4f6eda3a335b8..9a3040952c4adce83199a1e48fe44b84d2b0d087 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java @@ -1,29 +1,29 @@ -/** - * 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.classic; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses( { LoggerContextTest.class, LoggerPerfTest.class, - ScenarioBasedLoggerContextTest.class, PatternLayoutTest.class, - LoggerTest.class, LoggerSerializationTest.class, - MessageFormattingTest.class, MDCTest.class, - TurboFilteringInLoggerTest.class }) - - -public class PackageTest { +/** + * 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.classic; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses( { LoggerContextTest.class, LoggerPerfTest.class, + ScenarioBasedLoggerContextTest.class, PatternLayoutTest.class, + LoggerTest.class, LoggerSerializationTest.class, + MessageFormattingTest.class, MDCTest.class, + TurboFilteringInLoggerTest.class }) + + +public class PackageTest { } \ No newline at end of file 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 211bcba4b651e2a33ee74f850922283fec5a070d..9f4cf279455154d6d6a6e7707b336c21df667947 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 @@ -1,179 +1,179 @@ -/** - * 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.classic; - -import static ch.qos.logback.classic.ClassicTestConstants.ISO_REGEX; -import static ch.qos.logback.classic.ClassicTestConstants.MAIN_REGEX; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.pattern.ConverterTest; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.classic.testUtil.SampleConverter; -import ch.qos.logback.classic.util.TeztConstants; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.pattern.PatternLayoutBase; -import ch.qos.logback.core.pattern.parser.AbstractPatternLayoutBaseTest; -import ch.qos.logback.core.testUtil.StringListAppender; - -public class PatternLayoutTest extends AbstractPatternLayoutBaseTest { - - private PatternLayout pl = new PatternLayout(); - private LoggerContext lc = new LoggerContext(); - Logger logger = lc.getLogger(ConverterTest.class); - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - - ILoggingEvent le; - List optionList = new ArrayList(); - - public PatternLayoutTest() { - super(); - Exception ex = new Exception("Bogus exception"); - le = makeLoggingEvent(ex); - } - - @Before - public void setUp() { - pl.setContext(lc); - } - - ILoggingEvent makeLoggingEvent(Exception ex) { - return new LoggingEvent( - ch.qos.logback.core.pattern.FormattingConverter.class.getName(), - logger, Level.INFO, "Some message", ex, null); - } - - @Override - public ILoggingEvent getEventObject() { - return makeLoggingEvent(null); - } - - public PatternLayoutBase getPatternLayoutBase() { - return new PatternLayout(); - } - - @Test - public void testOK() { - pl.setPattern("%d %le [%t] %lo{30} - %m%n"); - pl.start(); - String val = pl.doLayout(getEventObject()); - // 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*"; - - assertTrue(val.matches(regex)); - } - - @Test - public void testNoExeptionHandler() { - pl.setPattern("%m%n"); - pl.start(); - String val = pl.doLayout(le); - assertTrue(val.contains("java.lang.Exception: Bogus exception")); - } - - @Test - public void testCompositePattern() { - pl.setPattern("%-56(%d %lo{20}) - %m%n"); - pl.start(); - 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*"; - assertTrue(val.matches(regex)); - } - - @Test - public void contextProperty() { - 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"); - pl.start(); - String val = pl.doLayout(le); - assertTrue(!val.contains("java.lang.Exception: Bogus exception")); - } - - @Test - public void testWithParenthesis() { - pl.setPattern("\\(%msg:%msg\\) %msg"); - pl.start(); - le = makeLoggingEvent(null); - String val = pl.doLayout(le); - // System.out.println("VAL == " + val); - assertEquals("(Some message:Some message) Some message", val); - } - - @Test - public void testWithLettersComingFromLog4j() { - // Letters: p = level and c = logger - pl.setPattern("%d %p [%t] %c{30} - %m%n"); - pl.start(); - String val = pl.doLayout(getEventObject()); - // 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*"; - assertTrue(val.matches(regex)); - } - - @Test - public void contextNameTest() { - pl.setPattern("%contextName"); - lc.setName("aValue"); - pl.start(); - String val = pl.doLayout(getEventObject()); - assertEquals("aValue", val); - } - - @Override - public Context getContext() { - return lc; - } - - void configure(String file) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(lc); - jc.doConfigure(file); - } - - @Test - public void testConversionRuleSupportInPatternLayout() throws JoranException { - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/conversionRule/patternLayout0.xml"); - root.getAppender("LIST"); - String msg = "Simon says"; - logger.debug(msg); - StringListAppender sla = (StringListAppender) root.getAppender("LIST"); - assertNotNull(sla); - assertEquals(1, sla.strList.size()); - assertEquals(SampleConverter.SAMPLE_STR+" - "+msg, sla.strList.get(0)); - } -} +/** + * 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.classic; + +import static ch.qos.logback.classic.ClassicTestConstants.ISO_REGEX; +import static ch.qos.logback.classic.ClassicTestConstants.MAIN_REGEX; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.pattern.ConverterTest; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.classic.testUtil.SampleConverter; +import ch.qos.logback.classic.util.TeztConstants; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.pattern.PatternLayoutBase; +import ch.qos.logback.core.pattern.parser.AbstractPatternLayoutBaseTest; +import ch.qos.logback.core.testUtil.StringListAppender; + +public class PatternLayoutTest extends AbstractPatternLayoutBaseTest { + + private PatternLayout pl = new PatternLayout(); + private LoggerContext lc = new LoggerContext(); + Logger logger = lc.getLogger(ConverterTest.class); + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + + ILoggingEvent le; + List optionList = new ArrayList(); + + public PatternLayoutTest() { + super(); + Exception ex = new Exception("Bogus exception"); + le = makeLoggingEvent(ex); + } + + @Before + public void setUp() { + pl.setContext(lc); + } + + ILoggingEvent makeLoggingEvent(Exception ex) { + return new LoggingEvent( + ch.qos.logback.core.pattern.FormattingConverter.class.getName(), + logger, Level.INFO, "Some message", ex, null); + } + + @Override + public ILoggingEvent getEventObject() { + return makeLoggingEvent(null); + } + + public PatternLayoutBase getPatternLayoutBase() { + return new PatternLayout(); + } + + @Test + public void testOK() { + pl.setPattern("%d %le [%t] %lo{30} - %m%n"); + pl.start(); + String val = pl.doLayout(getEventObject()); + // 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*"; + + assertTrue(val.matches(regex)); + } + + @Test + public void testNoExeptionHandler() { + pl.setPattern("%m%n"); + pl.start(); + String val = pl.doLayout(le); + assertTrue(val.contains("java.lang.Exception: Bogus exception")); + } + + @Test + public void testCompositePattern() { + pl.setPattern("%-56(%d %lo{20}) - %m%n"); + pl.start(); + 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*"; + assertTrue(val.matches(regex)); + } + + @Test + public void contextProperty() { + 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"); + pl.start(); + String val = pl.doLayout(le); + assertTrue(!val.contains("java.lang.Exception: Bogus exception")); + } + + @Test + public void testWithParenthesis() { + pl.setPattern("\\(%msg:%msg\\) %msg"); + pl.start(); + le = makeLoggingEvent(null); + String val = pl.doLayout(le); + // System.out.println("VAL == " + val); + assertEquals("(Some message:Some message) Some message", val); + } + + @Test + public void testWithLettersComingFromLog4j() { + // Letters: p = level and c = logger + pl.setPattern("%d %p [%t] %c{30} - %m%n"); + pl.start(); + String val = pl.doLayout(getEventObject()); + // 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*"; + assertTrue(val.matches(regex)); + } + + @Test + public void contextNameTest() { + pl.setPattern("%contextName"); + lc.setName("aValue"); + pl.start(); + String val = pl.doLayout(getEventObject()); + assertEquals("aValue", val); + } + + @Override + public Context getContext() { + return lc; + } + + void configure(String file) throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(lc); + jc.doConfigure(file); + } + + @Test + public void testConversionRuleSupportInPatternLayout() throws JoranException { + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/conversionRule/patternLayout0.xml"); + root.getAppender("LIST"); + String msg = "Simon says"; + logger.debug(msg); + StringListAppender sla = (StringListAppender) root.getAppender("LIST"); + assertNotNull(sla); + assertEquals(1, sla.strList.size()); + assertEquals(SampleConverter.SAMPLE_STR+" - "+msg, sla.strList.get(0)); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/ScenarioBasedLoggerContextTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/ScenarioBasedLoggerContextTest.java index 4e8642c97449ad7c010474ea1848d1fd34bdaf8a..8248a5c101aca89c29d996a7b0fb91555193a953 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/ScenarioBasedLoggerContextTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/ScenarioBasedLoggerContextTest.java @@ -1,115 +1,115 @@ -/** - * 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.classic; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import java.util.List; -import java.util.Map; - -import org.junit.Ignore; -import org.junit.Test; - -import ch.qos.logback.classic.control.ControlLogger; -import ch.qos.logback.classic.control.ControlLoggerContext; -import ch.qos.logback.classic.control.CreateLogger; -import ch.qos.logback.classic.control.ScenarioAction; -import ch.qos.logback.classic.control.ScenarioMaker; -import ch.qos.logback.classic.control.SetLevel; -import ch.qos.logback.classic.control.Scenario; - - -public class ScenarioBasedLoggerContextTest { - LoggerContext lc; - - - @Test - public void testLen3() { - doScenarioedTest(3); - } - - @Test - public void testLength_30() { - doScenarioedTest(30); - } - - @Test - public void testLength_20000() { - doScenarioedTest(20*1000); - } - - @Test - @Ignore - public void testLengthLong() { - doScenarioedTest(100*1000); - } - - private void doScenarioedTest(int len) { - LoggerContext lc = new LoggerContext(); - ControlLoggerContext controlContext = new ControlLoggerContext(); - Scenario s = ScenarioMaker.makeRealisticCreationScenario(len); - List actionList = s.getActionList(); - int size = actionList.size(); - for (int i = 0; i < size; i++) { - ScenarioAction action = (ScenarioAction) actionList.get(i); - if (action instanceof CreateLogger) { - CreateLogger cl = (CreateLogger) action; - lc.getLogger(cl.getLoggerName()); - controlContext.getLogger(cl.getLoggerName()); - } else if (action instanceof SetLevel) { - SetLevel sl = (SetLevel) action; - Logger l = lc.getLogger(sl.getLoggerName()); - ControlLogger controlLogger = controlContext.getLogger(sl.getLoggerName()); - l.setLevel(sl.getLevel()); - controlLogger.setLevel(sl.getLevel()); - } - } - - compareLoggerContexts(controlContext, lc); - } - - void compareLoggerContexts(ControlLoggerContext controlLC, LoggerContext lc) { - Map controlLoggerMap = controlLC.getLoggerMap(); - - assertEquals(controlLoggerMap.size()+1, lc.size()); - - for (String loggerName: controlLoggerMap.keySet()) { - - Logger logger = lc.exists(loggerName); - ControlLogger controlLogger = (ControlLogger) controlLoggerMap.get(loggerName); - if (logger == null) { - throw new IllegalStateException("logger" + loggerName + " should exist"); - } - assertEquals(loggerName, logger.getName()); - assertEquals(loggerName, controlLogger.getName()); - - compareLoggers(controlLogger, logger); - } - } - - void compareLoggers(ControlLogger controlLogger, Logger logger) { - assertEquals(controlLogger.getName(), logger.getName()); - assertEquals(controlLogger.getEffectiveLevel(), logger.getEffectiveLevel()); - - Level controlLevel = controlLogger.getLevel(); - Level level = logger.getLevel(); - - if (controlLevel == null) { - assertNull(level); - } else { - assertEquals(controlLevel, level); - } - } +/** + * 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.classic; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.List; +import java.util.Map; + +import org.junit.Ignore; +import org.junit.Test; + +import ch.qos.logback.classic.control.ControlLogger; +import ch.qos.logback.classic.control.ControlLoggerContext; +import ch.qos.logback.classic.control.CreateLogger; +import ch.qos.logback.classic.control.ScenarioAction; +import ch.qos.logback.classic.control.ScenarioMaker; +import ch.qos.logback.classic.control.SetLevel; +import ch.qos.logback.classic.control.Scenario; + + +public class ScenarioBasedLoggerContextTest { + LoggerContext lc; + + + @Test + public void testLen3() { + doScenarioedTest(3); + } + + @Test + public void testLength_30() { + doScenarioedTest(30); + } + + @Test + public void testLength_20000() { + doScenarioedTest(20*1000); + } + + @Test + @Ignore + public void testLengthLong() { + doScenarioedTest(100*1000); + } + + private void doScenarioedTest(int len) { + LoggerContext lc = new LoggerContext(); + ControlLoggerContext controlContext = new ControlLoggerContext(); + Scenario s = ScenarioMaker.makeRealisticCreationScenario(len); + List actionList = s.getActionList(); + int size = actionList.size(); + for (int i = 0; i < size; i++) { + ScenarioAction action = (ScenarioAction) actionList.get(i); + if (action instanceof CreateLogger) { + CreateLogger cl = (CreateLogger) action; + lc.getLogger(cl.getLoggerName()); + controlContext.getLogger(cl.getLoggerName()); + } else if (action instanceof SetLevel) { + SetLevel sl = (SetLevel) action; + Logger l = lc.getLogger(sl.getLoggerName()); + ControlLogger controlLogger = controlContext.getLogger(sl.getLoggerName()); + l.setLevel(sl.getLevel()); + controlLogger.setLevel(sl.getLevel()); + } + } + + compareLoggerContexts(controlContext, lc); + } + + void compareLoggerContexts(ControlLoggerContext controlLC, LoggerContext lc) { + Map controlLoggerMap = controlLC.getLoggerMap(); + + assertEquals(controlLoggerMap.size()+1, lc.size()); + + for (String loggerName: controlLoggerMap.keySet()) { + + Logger logger = lc.exists(loggerName); + ControlLogger controlLogger = (ControlLogger) controlLoggerMap.get(loggerName); + if (logger == null) { + throw new IllegalStateException("logger" + loggerName + " should exist"); + } + assertEquals(loggerName, logger.getName()); + assertEquals(loggerName, controlLogger.getName()); + + compareLoggers(controlLogger, logger); + } + } + + void compareLoggers(ControlLogger controlLogger, Logger logger) { + assertEquals(controlLogger.getName(), logger.getName()); + assertEquals(controlLogger.getEffectiveLevel(), logger.getEffectiveLevel()); + + Level controlLevel = controlLogger.getLevel(); + Level level = logger.getLevel(); + + if (controlLevel == null) { + assertNull(level); + } else { + assertEquals(controlLevel, level); + } + } } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/TurboFilteringInLoggerTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/TurboFilteringInLoggerTest.java index 7aaa9673cf5203fcacd702ebdad03270ffdf1154..1bb51d633cff0d2e802a0f9d6ae4a757aa4d82db 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/TurboFilteringInLoggerTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/TurboFilteringInLoggerTest.java @@ -1,183 +1,183 @@ -/** - * 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.classic; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Marker; -import org.slf4j.MarkerFactory; - -import ch.qos.logback.classic.turbo.MarkerFilter; -import ch.qos.logback.classic.turbo.TurboFilter; -import ch.qos.logback.core.spi.FilterReply; - - -public class TurboFilteringInLoggerTest { - - static final String BLUE = "BLUE"; - LoggerContext context; - Logger logger; - Marker blueMarker = MarkerFactory.getMarker(BLUE); - - @Before - public void setUp() throws Exception { - context = new LoggerContext(); - context.setName("test"); - context.start(); - logger = context.getLogger(TurboFilteringInLoggerTest.class); - } - - - private void addYesFilter() { - YesFilter filter = new YesFilter(); - filter.start(); - context.addTurboFilter(filter); - } - - private void addNoFilter() { - NoFilter filter = new NoFilter(); - filter.start(); - context.addTurboFilter(filter); - } - - private void addAcceptBLUEFilter() { - MarkerFilter filter = new MarkerFilter(); - filter.setMarker(BLUE); - filter.setOnMatch("ACCEPT"); - filter.start(); - context.addTurboFilter(filter); - } - - private void addDenyBLUEFilter() { - MarkerFilter filter = new MarkerFilter(); - filter.setMarker(BLUE); - filter.setOnMatch("DENY"); - filter.start(); - context.addTurboFilter(filter); - } - - @Test - public void testIsDebugEnabledWithYesFilter() { - addYesFilter(); - logger.setLevel(Level.INFO); - assertTrue(logger.isDebugEnabled()); - } - - @Test - public void testIsInfoEnabledWithYesFilter() { - addYesFilter(); - logger.setLevel(Level.WARN); - assertTrue(logger.isInfoEnabled()); - } - - @Test - public void testIsWarnEnabledWithYesFilter() { - addYesFilter(); - logger.setLevel(Level.ERROR); - assertTrue(logger.isWarnEnabled()); - } - - @Test - public void testIsErrorEnabledWithYesFilter() { - addYesFilter(); - logger.setLevel(Level.OFF); - assertTrue(logger.isErrorEnabled()); - } - - @Test - public void testIsEnabledForWithYesFilter() { - addYesFilter(); - logger.setLevel(Level.ERROR); - assertTrue(logger.isEnabledFor(Level.INFO)); - } - - @Test - public void testIsEnabledForWithNoFilter() { - addNoFilter(); - logger.setLevel(Level.DEBUG); - assertFalse(logger.isEnabledFor(Level.INFO)); - } - - @Test - public void testIsDebugEnabledWithNoFilter() { - addNoFilter(); - logger.setLevel(Level.DEBUG); - assertFalse(logger.isDebugEnabled()); - } - - @Test - public void testIsInfoEnabledWithNoFilter() { - addNoFilter(); - logger.setLevel(Level.DEBUG); - assertFalse(logger.isInfoEnabled()); - } - - @Test - public void testIsWarnEnabledWithNoFilter() { - addNoFilter(); - logger.setLevel(Level.DEBUG); - assertFalse(logger.isWarnEnabled()); - } - - @Test - public void testIsErrorEnabledWithNoFilter() { - addNoFilter(); - logger.setLevel(Level.DEBUG); - assertFalse(logger.isErrorEnabled()); - } - - @Test - public void testIsErrorEnabledWithAcceptBlueFilter() { - addAcceptBLUEFilter(); - logger.setLevel(Level.ERROR); - assertTrue(logger.isDebugEnabled(blueMarker)); - } - - @Test - public void testIsErrorEnabledWithDenyBlueFilter() { - addDenyBLUEFilter(); - logger.setLevel(Level.ALL); - assertFalse(logger.isDebugEnabled(blueMarker)); - } - - @Test - public void testLoggingContextReset() { - addYesFilter(); - assertNotNull(context.getTurboFilterList().get(0)); - context.reset(); - assertEquals(0, context.getTurboFilterList().size()); - } - -} - -class YesFilter extends TurboFilter { - @Override - public FilterReply decide(Marker marker, Logger logger, Level level, - String format, Object[] params, Throwable t) { - return FilterReply.ACCEPT; - } -} - -class NoFilter extends TurboFilter { - @Override - public FilterReply decide(Marker marker, Logger logger, Level level, - String format, Object[] params, Throwable t) { - return FilterReply.DENY; - } +/** + * 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.classic; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +import ch.qos.logback.classic.turbo.MarkerFilter; +import ch.qos.logback.classic.turbo.TurboFilter; +import ch.qos.logback.core.spi.FilterReply; + + +public class TurboFilteringInLoggerTest { + + static final String BLUE = "BLUE"; + LoggerContext context; + Logger logger; + Marker blueMarker = MarkerFactory.getMarker(BLUE); + + @Before + public void setUp() throws Exception { + context = new LoggerContext(); + context.setName("test"); + context.start(); + logger = context.getLogger(TurboFilteringInLoggerTest.class); + } + + + private void addYesFilter() { + YesFilter filter = new YesFilter(); + filter.start(); + context.addTurboFilter(filter); + } + + private void addNoFilter() { + NoFilter filter = new NoFilter(); + filter.start(); + context.addTurboFilter(filter); + } + + private void addAcceptBLUEFilter() { + MarkerFilter filter = new MarkerFilter(); + filter.setMarker(BLUE); + filter.setOnMatch("ACCEPT"); + filter.start(); + context.addTurboFilter(filter); + } + + private void addDenyBLUEFilter() { + MarkerFilter filter = new MarkerFilter(); + filter.setMarker(BLUE); + filter.setOnMatch("DENY"); + filter.start(); + context.addTurboFilter(filter); + } + + @Test + public void testIsDebugEnabledWithYesFilter() { + addYesFilter(); + logger.setLevel(Level.INFO); + assertTrue(logger.isDebugEnabled()); + } + + @Test + public void testIsInfoEnabledWithYesFilter() { + addYesFilter(); + logger.setLevel(Level.WARN); + assertTrue(logger.isInfoEnabled()); + } + + @Test + public void testIsWarnEnabledWithYesFilter() { + addYesFilter(); + logger.setLevel(Level.ERROR); + assertTrue(logger.isWarnEnabled()); + } + + @Test + public void testIsErrorEnabledWithYesFilter() { + addYesFilter(); + logger.setLevel(Level.OFF); + assertTrue(logger.isErrorEnabled()); + } + + @Test + public void testIsEnabledForWithYesFilter() { + addYesFilter(); + logger.setLevel(Level.ERROR); + assertTrue(logger.isEnabledFor(Level.INFO)); + } + + @Test + public void testIsEnabledForWithNoFilter() { + addNoFilter(); + logger.setLevel(Level.DEBUG); + assertFalse(logger.isEnabledFor(Level.INFO)); + } + + @Test + public void testIsDebugEnabledWithNoFilter() { + addNoFilter(); + logger.setLevel(Level.DEBUG); + assertFalse(logger.isDebugEnabled()); + } + + @Test + public void testIsInfoEnabledWithNoFilter() { + addNoFilter(); + logger.setLevel(Level.DEBUG); + assertFalse(logger.isInfoEnabled()); + } + + @Test + public void testIsWarnEnabledWithNoFilter() { + addNoFilter(); + logger.setLevel(Level.DEBUG); + assertFalse(logger.isWarnEnabled()); + } + + @Test + public void testIsErrorEnabledWithNoFilter() { + addNoFilter(); + logger.setLevel(Level.DEBUG); + assertFalse(logger.isErrorEnabled()); + } + + @Test + public void testIsErrorEnabledWithAcceptBlueFilter() { + addAcceptBLUEFilter(); + logger.setLevel(Level.ERROR); + assertTrue(logger.isDebugEnabled(blueMarker)); + } + + @Test + public void testIsErrorEnabledWithDenyBlueFilter() { + addDenyBLUEFilter(); + logger.setLevel(Level.ALL); + assertFalse(logger.isDebugEnabled(blueMarker)); + } + + @Test + public void testLoggingContextReset() { + addYesFilter(); + assertNotNull(context.getTurboFilterList().get(0)); + context.reset(); + assertEquals(0, context.getTurboFilterList().size()); + } + +} + +class YesFilter extends TurboFilter { + @Override + public FilterReply decide(Marker marker, Logger logger, Level level, + String format, Object[] params, Throwable t) { + return FilterReply.ACCEPT; + } +} + +class NoFilter extends TurboFilter { + @Override + public FilterReply decide(Marker marker, Logger logger, Level level, + String format, Object[] params, Throwable t) { + return FilterReply.DENY; + } } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/boolex/JaninoEventEvaluatorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/boolex/JaninoEventEvaluatorTest.java index d4069f1b68c9104360470d8ef9d46f64745b0dbc..9763d5dacbc0e333045738563fe27f3ee248b38a 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/boolex/JaninoEventEvaluatorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/boolex/JaninoEventEvaluatorTest.java @@ -1,244 +1,244 @@ -/** - * 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.classic.boolex; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.IOException; - -import org.junit.Test; -import org.slf4j.MarkerFactory; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.pattern.ConverterTest; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.core.boolex.EvaluationException; -import ch.qos.logback.core.boolex.JaninoEventEvaluatorBase; -import ch.qos.logback.core.boolex.Matcher; -import ch.qos.logback.core.filter.EvaluatorFilter; -import ch.qos.logback.core.spi.FilterReply; - -public class JaninoEventEvaluatorTest { - - LoggerContext loggerContext = new LoggerContext(); - Logger logger = loggerContext.getLogger(ConverterTest.class); - - Matcher matcherX = new Matcher(); - - JaninoEventEvaluator jee = new JaninoEventEvaluator(); - - public JaninoEventEvaluatorTest() { - jee.setContext(loggerContext); - - matcherX.setName("x"); - matcherX.setRegex("^Some\\s.*"); - matcherX.start(); - - } - - LoggingEvent makeLoggingEvent(Exception ex) { - LoggingEvent e = new LoggingEvent( - ch.qos.logback.core.pattern.FormattingConverter.class.getName(), - logger, Level.INFO, "Some message", ex, null); - return e; - } - - @Test - public void testBasic() throws Exception { - jee.setExpression("message.equals(\"Some message\")"); - jee.start(); - - ILoggingEvent event = makeLoggingEvent(null); - // System.out.println(event); - assertTrue(jee.evaluate(event)); - } - - @Test - public void testLevel() throws Exception { - jee.setExpression("level > DEBUG"); - jee.start(); - - ILoggingEvent event = makeLoggingEvent(null); - // System.out.println(event); - assertTrue(jee.evaluate(event)); - } - - @Test - public void testtimeStamp() throws Exception { - jee.setExpression("timeStamp > 10"); - jee.start(); - - ILoggingEvent event = makeLoggingEvent(null); - assertTrue(jee.evaluate(event)); - } - - @Test - public void testWithMatcher() throws Exception { - jee.setExpression("x.matches(message)"); - jee.addMatcher(matcherX); - jee.start(); - - ILoggingEvent event = makeLoggingEvent(null); - assertTrue(jee.evaluate(event)); - } - - @Test - public void marker() throws Exception { - jee.setExpression("marker.contains(\"BLUE\")"); - jee.start(); - - LoggingEvent event = makeLoggingEvent(null); - event.setMarker(MarkerFactory.getMarker("BLUE")); - assertTrue(jee.evaluate(event)); - } - - @Test - public void withNullMarker_LBCORE_118() throws Exception { - jee.setExpression("marker.contains(\"BLUE\")"); - jee.start(); - - ILoggingEvent event = makeLoggingEvent(null); - try { - jee.evaluate(event); - fail("We should not reach this point"); - } catch (EvaluationException ee) { - // received an exception as expected - } - } - - @Test - public void evaluatorFilterWithNullMarker_LBCORE_118() throws Exception { - EvaluatorFilter ef = new EvaluatorFilter(); - ef.setContext(loggerContext); - - ef.setOnMatch(FilterReply.ACCEPT); - ef.setOnMismatch(FilterReply.DENY); - - jee.setExpression("marker.contains(\"BLUE\")"); - jee.start(); - - ef.setEvaluator(jee); - ef.start(); - ILoggingEvent event = makeLoggingEvent(null); - assertEquals(FilterReply.NEUTRAL, ef.decide(event)); - - } - - @Test - public void testComplex() throws Exception { - jee - .setExpression("level >= INFO && x.matches(message) && marker.contains(\"BLUE\")"); - jee.addMatcher(matcherX); - jee.start(); - - LoggingEvent event = makeLoggingEvent(null); - event.setMarker(MarkerFactory.getMarker("BLUE")); - assertTrue(jee.evaluate(event)); - } - - /** - * check that evaluator with bogus exp does not start - * - * @throws Exception - */ - @Test - public void testBogusExp1() { - jee.setExpression("mzzzz.get(\"key\").equals(null)"); - jee.setName("bogus"); - jee.start(); - - assertFalse(jee.isStarted()); - } - - // check that eval stops after errors - @Test - public void testBogusExp2() { - jee.setExpression("mdc.get(\"keyXN89\").equals(null)"); - jee.setName("bogus"); - jee.start(); - - assertTrue(jee.isStarted()); - - ILoggingEvent event = makeLoggingEvent(null); - - for (int i = 0; i < JaninoEventEvaluatorBase.ERROR_THRESHOLD; i++) { - try { - jee.evaluate(event); - fail("should throw an exception"); - } catch (EvaluationException e) { - } - } - // after a few attempts the evaluator should stop - assertFalse(jee.isStarted()); - - } - - static final long LEN = 10 * 1000; - - // with 6 parameters 400 nanos - // with 7 parameters 460 nanos (all levels + selected fields from - // LoggingEvent) - // with 10 parameters 510 nanos (all levels + fields) - void loop(JaninoEventEvaluator jee, String msg) throws Exception { - ILoggingEvent event = makeLoggingEvent(null); - // final long start = System.nanoTime(); - for (int i = 0; i < LEN; i++) { - jee.evaluate(event); - } - // final long end = System.nanoTime(); - // System.out.println(msg + (end - start) / LEN + " nanos"); - } - - @Test - public void testLoop1() throws Exception { - jee.setExpression("timeStamp > 10"); - jee.start(); - - loop(jee, "timestamp > 10]: "); - } - - @Test - public void testLoop2() throws Exception { - jee.setExpression("x.matches(message)"); - jee.addMatcher(matcherX); - jee.start(); - - loop(jee, "x.matches(message): "); - } - - @Test - public void throwable_LBCLASSIC_155_I() throws EvaluationException { - jee.setExpression("throwable instanceof java.io.IOException"); - jee.start(); - - LoggingEvent event = makeLoggingEvent(new IOException("")); - assertTrue(jee.evaluate(event)); - } - - @Test - public void throwable_LBCLASSIC_155_II() throws EvaluationException { - jee.setExpression("throwableProxy.getClassName().contains(\"IO\")"); - jee.start(); - - LoggingEvent event = makeLoggingEvent(new IOException("")); - assertTrue(jee.evaluate(event)); - } - -} +/** + * 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.classic.boolex; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; + +import org.junit.Test; +import org.slf4j.MarkerFactory; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.pattern.ConverterTest; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.JaninoEventEvaluatorBase; +import ch.qos.logback.core.boolex.Matcher; +import ch.qos.logback.core.filter.EvaluatorFilter; +import ch.qos.logback.core.spi.FilterReply; + +public class JaninoEventEvaluatorTest { + + LoggerContext loggerContext = new LoggerContext(); + Logger logger = loggerContext.getLogger(ConverterTest.class); + + Matcher matcherX = new Matcher(); + + JaninoEventEvaluator jee = new JaninoEventEvaluator(); + + public JaninoEventEvaluatorTest() { + jee.setContext(loggerContext); + + matcherX.setName("x"); + matcherX.setRegex("^Some\\s.*"); + matcherX.start(); + + } + + LoggingEvent makeLoggingEvent(Exception ex) { + LoggingEvent e = new LoggingEvent( + ch.qos.logback.core.pattern.FormattingConverter.class.getName(), + logger, Level.INFO, "Some message", ex, null); + return e; + } + + @Test + public void testBasic() throws Exception { + jee.setExpression("message.equals(\"Some message\")"); + jee.start(); + + ILoggingEvent event = makeLoggingEvent(null); + // System.out.println(event); + assertTrue(jee.evaluate(event)); + } + + @Test + public void testLevel() throws Exception { + jee.setExpression("level > DEBUG"); + jee.start(); + + ILoggingEvent event = makeLoggingEvent(null); + // System.out.println(event); + assertTrue(jee.evaluate(event)); + } + + @Test + public void testtimeStamp() throws Exception { + jee.setExpression("timeStamp > 10"); + jee.start(); + + ILoggingEvent event = makeLoggingEvent(null); + assertTrue(jee.evaluate(event)); + } + + @Test + public void testWithMatcher() throws Exception { + jee.setExpression("x.matches(message)"); + jee.addMatcher(matcherX); + jee.start(); + + ILoggingEvent event = makeLoggingEvent(null); + assertTrue(jee.evaluate(event)); + } + + @Test + public void marker() throws Exception { + jee.setExpression("marker.contains(\"BLUE\")"); + jee.start(); + + LoggingEvent event = makeLoggingEvent(null); + event.setMarker(MarkerFactory.getMarker("BLUE")); + assertTrue(jee.evaluate(event)); + } + + @Test + public void withNullMarker_LBCORE_118() throws Exception { + jee.setExpression("marker.contains(\"BLUE\")"); + jee.start(); + + ILoggingEvent event = makeLoggingEvent(null); + try { + jee.evaluate(event); + fail("We should not reach this point"); + } catch (EvaluationException ee) { + // received an exception as expected + } + } + + @Test + public void evaluatorFilterWithNullMarker_LBCORE_118() throws Exception { + EvaluatorFilter ef = new EvaluatorFilter(); + ef.setContext(loggerContext); + + ef.setOnMatch(FilterReply.ACCEPT); + ef.setOnMismatch(FilterReply.DENY); + + jee.setExpression("marker.contains(\"BLUE\")"); + jee.start(); + + ef.setEvaluator(jee); + ef.start(); + ILoggingEvent event = makeLoggingEvent(null); + assertEquals(FilterReply.NEUTRAL, ef.decide(event)); + + } + + @Test + public void testComplex() throws Exception { + jee + .setExpression("level >= INFO && x.matches(message) && marker.contains(\"BLUE\")"); + jee.addMatcher(matcherX); + jee.start(); + + LoggingEvent event = makeLoggingEvent(null); + event.setMarker(MarkerFactory.getMarker("BLUE")); + assertTrue(jee.evaluate(event)); + } + + /** + * check that evaluator with bogus exp does not start + * + * @throws Exception + */ + @Test + public void testBogusExp1() { + jee.setExpression("mzzzz.get(\"key\").equals(null)"); + jee.setName("bogus"); + jee.start(); + + assertFalse(jee.isStarted()); + } + + // check that eval stops after errors + @Test + public void testBogusExp2() { + jee.setExpression("mdc.get(\"keyXN89\").equals(null)"); + jee.setName("bogus"); + jee.start(); + + assertTrue(jee.isStarted()); + + ILoggingEvent event = makeLoggingEvent(null); + + for (int i = 0; i < JaninoEventEvaluatorBase.ERROR_THRESHOLD; i++) { + try { + jee.evaluate(event); + fail("should throw an exception"); + } catch (EvaluationException e) { + } + } + // after a few attempts the evaluator should stop + assertFalse(jee.isStarted()); + + } + + static final long LEN = 10 * 1000; + + // with 6 parameters 400 nanos + // with 7 parameters 460 nanos (all levels + selected fields from + // LoggingEvent) + // with 10 parameters 510 nanos (all levels + fields) + void loop(JaninoEventEvaluator jee, String msg) throws Exception { + ILoggingEvent event = makeLoggingEvent(null); + // final long start = System.nanoTime(); + for (int i = 0; i < LEN; i++) { + jee.evaluate(event); + } + // final long end = System.nanoTime(); + // System.out.println(msg + (end - start) / LEN + " nanos"); + } + + @Test + public void testLoop1() throws Exception { + jee.setExpression("timeStamp > 10"); + jee.start(); + + loop(jee, "timestamp > 10]: "); + } + + @Test + public void testLoop2() throws Exception { + jee.setExpression("x.matches(message)"); + jee.addMatcher(matcherX); + jee.start(); + + loop(jee, "x.matches(message): "); + } + + @Test + public void throwable_LBCLASSIC_155_I() throws EvaluationException { + jee.setExpression("throwable instanceof java.io.IOException"); + jee.start(); + + LoggingEvent event = makeLoggingEvent(new IOException("")); + assertTrue(jee.evaluate(event)); + } + + @Test + public void throwable_LBCLASSIC_155_II() throws EvaluationException { + jee.setExpression("throwableProxy.getClassName().contains(\"IO\")"); + jee.start(); + + LoggingEvent event = makeLoggingEvent(new IOException("")); + assertTrue(jee.evaluate(event)); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/boolex/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/boolex/PackageTest.java index 28b41d6538b739b892616ca49d2609cf61cfc0e8..5ee17d665b244d3ac48f5f3bc0353d2d25073374 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/boolex/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/boolex/PackageTest.java @@ -1,25 +1,25 @@ -/** - * 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.classic.boolex; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -import ch.qos.logback.classic.jmx.JMXConfiguratorTest; - -@RunWith(Suite.class) -@SuiteClasses(JMXConfiguratorTest.class) -public class PackageTest { +/** + * 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.classic.boolex; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import ch.qos.logback.classic.jmx.JMXConfiguratorTest; + +@RunWith(Suite.class) +@SuiteClasses(JMXConfiguratorTest.class) +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/control/CLCTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/control/CLCTest.java index e75b4e20c5a39eec19b0c7b847b8fcce6719cb32..199ffa1b6355ce3df2be11b43d1caa439209a0c8 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/control/CLCTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/control/CLCTest.java @@ -1,56 +1,56 @@ -/** - * 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.classic.control; - -import junit.framework.TestCase; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.control.ControlLogger; -import ch.qos.logback.classic.control.ControlLoggerContext; - - -/** - * This class is for testing ControlLoggerContext which is a control class for testing HLoggerContext. - */ -public class CLCTest extends TestCase { - ControlLoggerContext clc; - - - protected void setUp() throws Exception { - clc = new ControlLoggerContext(); - } - - public void test1() { - ControlLogger x = clc.getLogger("x"); - assertEquals("x", x.getName()); - assertEquals(clc.getRootLogger(), x.parent); - - ControlLogger abc = clc.getLogger("a.b.c"); - assertEquals("a.b.c", abc.getName()); - assertEquals(Level.DEBUG, abc.getEffectiveLevel()); - } - - public void testCreation() { - ControlLogger xyz = clc.getLogger("x.y.z"); - assertEquals("x.y.z", xyz.getName()); - assertEquals("x.y", xyz.parent.getName()); - assertEquals("x", xyz.parent.parent.getName()); - assertEquals("root", xyz.parent.parent.parent.getName()); - - ControlLogger xyz_ = clc.exists("x.y.z"); - assertEquals("x.y.z", xyz_.getName()); - - - } +/** + * 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.classic.control; + +import junit.framework.TestCase; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.control.ControlLogger; +import ch.qos.logback.classic.control.ControlLoggerContext; + + +/** + * This class is for testing ControlLoggerContext which is a control class for testing HLoggerContext. + */ +public class CLCTest extends TestCase { + ControlLoggerContext clc; + + + protected void setUp() throws Exception { + clc = new ControlLoggerContext(); + } + + public void test1() { + ControlLogger x = clc.getLogger("x"); + assertEquals("x", x.getName()); + assertEquals(clc.getRootLogger(), x.parent); + + ControlLogger abc = clc.getLogger("a.b.c"); + assertEquals("a.b.c", abc.getName()); + assertEquals(Level.DEBUG, abc.getEffectiveLevel()); + } + + public void testCreation() { + ControlLogger xyz = clc.getLogger("x.y.z"); + assertEquals("x.y.z", xyz.getName()); + assertEquals("x.y", xyz.parent.getName()); + assertEquals("x", xyz.parent.parent.getName()); + assertEquals("root", xyz.parent.parent.parent.getName()); + + ControlLogger xyz_ = clc.exists("x.y.z"); + assertEquals("x.y.z", xyz_.getName()); + + + } } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/control/ControlLogger.java b/logback-classic/src/test/java/ch/qos/logback/classic/control/ControlLogger.java index af3ccba7a23ae8bc7d3608c054d393f239e019da..d9b0b7e138cf9f24621867726aea658e8a6de1bc 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/control/ControlLogger.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/control/ControlLogger.java @@ -1,185 +1,185 @@ -/** - * 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.classic.control; - -import org.slf4j.helpers.MarkerIgnoringBase; - -import ch.qos.logback.classic.Level; - -/** - * See javadoc for ControlLoggerContext. - */ -public class ControlLogger extends MarkerIgnoringBase { - - private static final long serialVersionUID = 1L; - final ControlLogger parent; - final String name; - Level level; - - - public ControlLogger(String name, ControlLogger parent) { - if(name == null){ - throw new IllegalArgumentException("name cannot be null"); - } - this.name = name; - this.parent = parent; - } - public String getName() { - return name; - } - - public Level getLevel() { - return level; - } - - public void setLevel(Level level) { - this.level = level; - } - - public final Level getEffectiveLevel() { - for(ControlLogger cl = this; cl != null; cl=cl.parent) { - if(cl.level != null) - return cl.level; - } - return null; // If reached will cause an NullPointerException. - } - - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ControlLogger)) return false; - - final ControlLogger controlLogger = (ControlLogger) o; - return name.equals(controlLogger.name); - } - - public int hashCode() { - return name.hashCode(); - } - - public final void trace(String o) { - if(getEffectiveLevel().levelInt <= Level.TRACE_INT ) { - throw new UnsupportedOperationException("not yet implemented"); - } - } - - public void trace(String msg, Throwable t) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void trace(String parameterizedMsg, Object param1) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void trace(String parameterizedMsg, Object param1, Object param2) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public final void debug(String o) { - if(getEffectiveLevel().levelInt <= Level.DEBUG_INT ) { - throw new UnsupportedOperationException("not yet implemented"); - } - } - - public void debug(String msg, Throwable t) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void debug(String parameterizedMsg, Object param1) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void debug(String parameterizedMsg, Object param1, Object param2) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void error(String msg) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void error(String msg, Throwable t) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void error(String parameterizedMsg, Object param1) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void error(String parameterizedMsg, Object param1, Object param2) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void info(String msg) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void info(String msg, Throwable t) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void info(String parameterizedMsg, Object param1) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void info(String parameterizedMsg, Object param1, Object param2) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isTraceEnabled() { - return false; - } - - public boolean isDebugEnabled() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isErrorEnabled() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isInfoEnabled() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isWarnEnabled() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public void warn(String msg) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void warn(String msg, Throwable t) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void warn(String parameterizedMsg, Object param1) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void warn(String parameterizedMsg, Object param1, Object param2) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void trace(String format, Object[] argArray) { - } - public void debug(String format, Object[] argArray) { - } - public void info(String format, Object[] argArray) { - } - public void warn(String format, Object[] argArray) { - } - public void error(String format, Object[] argArray) { - } - -} +/** + * 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.classic.control; + +import org.slf4j.helpers.MarkerIgnoringBase; + +import ch.qos.logback.classic.Level; + +/** + * See javadoc for ControlLoggerContext. + */ +public class ControlLogger extends MarkerIgnoringBase { + + private static final long serialVersionUID = 1L; + final ControlLogger parent; + final String name; + Level level; + + + public ControlLogger(String name, ControlLogger parent) { + if(name == null){ + throw new IllegalArgumentException("name cannot be null"); + } + this.name = name; + this.parent = parent; + } + public String getName() { + return name; + } + + public Level getLevel() { + return level; + } + + public void setLevel(Level level) { + this.level = level; + } + + public final Level getEffectiveLevel() { + for(ControlLogger cl = this; cl != null; cl=cl.parent) { + if(cl.level != null) + return cl.level; + } + return null; // If reached will cause an NullPointerException. + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ControlLogger)) return false; + + final ControlLogger controlLogger = (ControlLogger) o; + return name.equals(controlLogger.name); + } + + public int hashCode() { + return name.hashCode(); + } + + public final void trace(String o) { + if(getEffectiveLevel().levelInt <= Level.TRACE_INT ) { + throw new UnsupportedOperationException("not yet implemented"); + } + } + + public void trace(String msg, Throwable t) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void trace(String parameterizedMsg, Object param1) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void trace(String parameterizedMsg, Object param1, Object param2) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public final void debug(String o) { + if(getEffectiveLevel().levelInt <= Level.DEBUG_INT ) { + throw new UnsupportedOperationException("not yet implemented"); + } + } + + public void debug(String msg, Throwable t) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void debug(String parameterizedMsg, Object param1) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void debug(String parameterizedMsg, Object param1, Object param2) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void error(String msg) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void error(String msg, Throwable t) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void error(String parameterizedMsg, Object param1) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void error(String parameterizedMsg, Object param1, Object param2) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void info(String msg) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void info(String msg, Throwable t) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void info(String parameterizedMsg, Object param1) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void info(String parameterizedMsg, Object param1, Object param2) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isTraceEnabled() { + return false; + } + + public boolean isDebugEnabled() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isErrorEnabled() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isInfoEnabled() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isWarnEnabled() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public void warn(String msg) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void warn(String msg, Throwable t) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void warn(String parameterizedMsg, Object param1) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void warn(String parameterizedMsg, Object param1, Object param2) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void trace(String format, Object[] argArray) { + } + public void debug(String format, Object[] argArray) { + } + public void info(String format, Object[] argArray) { + } + public void warn(String format, Object[] argArray) { + } + public void error(String format, Object[] argArray) { + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/control/ControlLoggerContext.java b/logback-classic/src/test/java/ch/qos/logback/classic/control/ControlLoggerContext.java index 9f86dc5169e9ab1ad3c192198ee3d271d03bb93a..65f3ca5367984b1118556a9a08c7551df015bebe 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/control/ControlLoggerContext.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/control/ControlLoggerContext.java @@ -1,110 +1,110 @@ -/** - * 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.classic.control; - -import java.util.HashMap; -import java.util.Map; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.core.CoreConstants; - -/** - * This logger context quite optimized for logger retrieval. - * - *

It uses a single loggerMap where the key is the logger name and the value - * is the logger. - * - *

This approach acts a lower limit for what is achievable for low memory - * usage as well as low creation/retrieval times. However, this simplicity also - * results in slow effective level evaluation, the most frequently exercised - * part of the API. - * - *

This class is expected to contain correct results, and serve to verify - * the correctness of a more sophisticated implementation. - * - * @author ceki - */ -public class ControlLoggerContext { - - private ControlLogger root; - // - // Hashtable loggerMap = new Hashtable(); - Map loggerMap = new HashMap(); - - public ControlLoggerContext() { - this.root = new ControlLogger("root", null); - this.root.setLevel(Level.DEBUG); - } - - /** - * Return this contexts root logger - * - * @return - */ - public ControlLogger getRootLogger() { - return root; - } - - public ControlLogger exists(String name) { - if (name == null) { - throw new IllegalArgumentException("name parameter cannot be null"); - } - - synchronized (loggerMap) { - return (ControlLogger) loggerMap.get(name); - } - } - - public final ControlLogger getLogger(String name) { - if (name == null) { - throw new IllegalArgumentException("name parameter cannot be null"); - } - - synchronized (loggerMap) { - ControlLogger cl = (ControlLogger) loggerMap.get(name); - if (cl != null) { - return cl; - } - ControlLogger parent = this.root; - - int i = 0; - while (true) { - i = name.indexOf(CoreConstants.DOT, i); - if (i == -1) { - // System.out.println("FINAL-Creating logger named [" + name + "] with - // parent " + parent.getName()); - cl = new ControlLogger(name, parent); - loggerMap.put(name, cl); - return cl; - } else { - String parentName = name.substring(0, i); - ControlLogger p = (ControlLogger) loggerMap.get(parentName); - if (p == null) { - // System.out.println("INTERMEDIARY-Creating logger [" + parentName - // + "] with parent " + parent.getName()); - p = new ControlLogger(parentName, parent); - loggerMap.put(parentName, p); - } - parent = p; - } - // make i move past the last found dot. - i++; - } - } - } - - public Map getLoggerMap() { - return loggerMap; - } -} +/** + * 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.classic.control; + +import java.util.HashMap; +import java.util.Map; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.core.CoreConstants; + +/** + * This logger context quite optimized for logger retrieval. + * + *

It uses a single loggerMap where the key is the logger name and the value + * is the logger. + * + *

This approach acts a lower limit for what is achievable for low memory + * usage as well as low creation/retrieval times. However, this simplicity also + * results in slow effective level evaluation, the most frequently exercised + * part of the API. + * + *

This class is expected to contain correct results, and serve to verify + * the correctness of a more sophisticated implementation. + * + * @author ceki + */ +public class ControlLoggerContext { + + private ControlLogger root; + // + // Hashtable loggerMap = new Hashtable(); + Map loggerMap = new HashMap(); + + public ControlLoggerContext() { + this.root = new ControlLogger("root", null); + this.root.setLevel(Level.DEBUG); + } + + /** + * Return this contexts root logger + * + * @return + */ + public ControlLogger getRootLogger() { + return root; + } + + public ControlLogger exists(String name) { + if (name == null) { + throw new IllegalArgumentException("name parameter cannot be null"); + } + + synchronized (loggerMap) { + return (ControlLogger) loggerMap.get(name); + } + } + + public final ControlLogger getLogger(String name) { + if (name == null) { + throw new IllegalArgumentException("name parameter cannot be null"); + } + + synchronized (loggerMap) { + ControlLogger cl = (ControlLogger) loggerMap.get(name); + if (cl != null) { + return cl; + } + ControlLogger parent = this.root; + + int i = 0; + while (true) { + i = name.indexOf(CoreConstants.DOT, i); + if (i == -1) { + // System.out.println("FINAL-Creating logger named [" + name + "] with + // parent " + parent.getName()); + cl = new ControlLogger(name, parent); + loggerMap.put(name, cl); + return cl; + } else { + String parentName = name.substring(0, i); + ControlLogger p = (ControlLogger) loggerMap.get(parentName); + if (p == null) { + // System.out.println("INTERMEDIARY-Creating logger [" + parentName + // + "] with parent " + parent.getName()); + p = new ControlLogger(parentName, parent); + loggerMap.put(parentName, p); + } + parent = p; + } + // make i move past the last found dot. + i++; + } + } + } + + public Map getLoggerMap() { + return loggerMap; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/control/CreateLogger.java b/logback-classic/src/test/java/ch/qos/logback/classic/control/CreateLogger.java index 6c1c05cd8812ab925db0450a57de3aa448652e9a..d5d88d0517891430b80fef66a7ebd06768320798 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/control/CreateLogger.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/control/CreateLogger.java @@ -1,32 +1,32 @@ -/** - * 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.classic.control; - - -public class CreateLogger extends ScenarioAction { - - final String loggerName; - - public CreateLogger(String loggerName) { - this.loggerName = loggerName; - } - - public String getLoggerName() { - return loggerName; - } - - public String toString() { - return "CreateLogger("+loggerName+")"; - } -} +/** + * 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.classic.control; + + +public class CreateLogger extends ScenarioAction { + + final String loggerName; + + public CreateLogger(String loggerName) { + this.loggerName = loggerName; + } + + public String getLoggerName() { + return loggerName; + } + + public String toString() { + return "CreateLogger("+loggerName+")"; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/control/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/control/PackageTest.java index 00034bbb7677eae411a3b12d1198dcece2b30184..211abb4b2ee0bddf361318729b38b0d267086bd6 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/control/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/control/PackageTest.java @@ -1,24 +1,24 @@ -/** - * 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.classic.control; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - - -@RunWith(Suite.class) -@SuiteClasses({}) -public class PackageTest { +/** + * 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.classic.control; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + + +@RunWith(Suite.class) +@SuiteClasses({}) +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/control/Scenario.java b/logback-classic/src/test/java/ch/qos/logback/classic/control/Scenario.java index 207b713a0260ae0c3e204dde8bff64fb344929be..e06e06a1d358de305c76fd79fde42bbbd772455b 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/control/Scenario.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/control/Scenario.java @@ -1,39 +1,39 @@ -/** - * 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.classic.control; - -import java.util.ArrayList; -import java.util.List; -import java.util.Vector; - -public class Scenario { - - private List actionList = new Vector(); - - public void add(ScenarioAction action) { - actionList.add(action); - } - - public List getActionList() { - return new ArrayList(actionList); - } - - public int size() { - return actionList.size(); - } - - public ScenarioAction get(int i) { - return (ScenarioAction) actionList.get(i); - } -} +/** + * 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.classic.control; + +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; + +public class Scenario { + + private List actionList = new Vector(); + + public void add(ScenarioAction action) { + actionList.add(action); + } + + public List getActionList() { + return new ArrayList(actionList); + } + + public int size() { + return actionList.size(); + } + + public ScenarioAction get(int i) { + return (ScenarioAction) actionList.get(i); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioAction.java b/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioAction.java index 1a60ae57efcac7e44f4206f509d2f8366662780b..ac55428973de44055150aba5143cf752be331686 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioAction.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioAction.java @@ -1,18 +1,18 @@ -/** - * 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.classic.control; - -public class ScenarioAction { - -} +/** + * 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.classic.control; + +public class ScenarioAction { + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioMaker.java b/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioMaker.java index c5cc0e70253ebd86755cfe7ed5d7934c5e0f9405..f346fe99d29a275e4bcad7df798312023c9a62a2 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioMaker.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioMaker.java @@ -1,103 +1,103 @@ -/** - * 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.classic.control; - -import java.util.LinkedList; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.core.CoreConstants; - -public class ScenarioMaker { - - private final static int AVERAGE_LOGGER_DEPTH = 4; - private final static int LOGGER_DEPT_DEV = 2; - // the frequency of a set levelInt event for every create logger event - private final static int CREATE_LOGGER_TO_SET_LEVEL_FREQUENCY = 5; - private final static int SECOND_SET_LEVEL_FREQUENCY = 3; - - private static long count = 0; - - /** - * Makes a scenario with len logger creations. Logger names are generated - * independently such that the overwhelming majority of logger names will be - * unrelated to each other. Each logger creation may be followed with a - * randomly generated set levelInt action on that logger. - * - * @param len - * @return - */ - static public Scenario makeTypeAScenario(int len) { - Scenario scenario = new Scenario(); - ; - for (int i = 0; i < len; i++) { - String loggerName = ScenarioRandomUtil.randomLoggerName( - AVERAGE_LOGGER_DEPTH, LOGGER_DEPT_DEV); - scenario.add(new CreateLogger(loggerName)); - } - return scenario; - } - - static public Scenario makeRealisticCreationScenario(int len) { - Scenario scenario = new Scenario(); - LinkedList queue = new LinkedList(); - int loggerCreationCount = 0; - - // add an empty string to get going - queue.add(""); - - while (loggerCreationCount < len) { - if ((count % 100) == 0) { - System.out.println("count=" + count); - } - - String loggerName = (String) queue.removeFirst(); - int randomChildrenCount = ScenarioRandomUtil - .randomChildrenCount(loggerName); - - if (randomChildrenCount == 0) { - scenario.add(new CreateLogger(loggerName)); - addSetLevelSubScenario(scenario, loggerName); - loggerCreationCount++; - } else { - for (int i = 0; i < randomChildrenCount; i++) { - String childName; - if (loggerName.equals("")) { - childName = ScenarioRandomUtil.randomId(); - count += childName.length(); - } else { - childName = loggerName + CoreConstants.DOT - + ScenarioRandomUtil.randomId(); - count += childName.length(); - } - queue.add(childName); - addSetLevelSubScenario(scenario, loggerName); - loggerCreationCount++; - } - } - } - return scenario; - } - - static void addSetLevelSubScenario(Scenario scenario, String loggerName) { - if (ScenarioRandomUtil.oneInFreq(CREATE_LOGGER_TO_SET_LEVEL_FREQUENCY)) { - Level l = ScenarioRandomUtil.randomLevel(); - scenario.add(new SetLevel(l, loggerName)); - if (ScenarioRandomUtil.oneInFreq(SECOND_SET_LEVEL_FREQUENCY)) { - l = ScenarioRandomUtil.randomLevel(); - scenario.add(new SetLevel(l, loggerName)); - } - } - } - +/** + * 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.classic.control; + +import java.util.LinkedList; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.core.CoreConstants; + +public class ScenarioMaker { + + private final static int AVERAGE_LOGGER_DEPTH = 4; + private final static int LOGGER_DEPT_DEV = 2; + // the frequency of a set levelInt event for every create logger event + private final static int CREATE_LOGGER_TO_SET_LEVEL_FREQUENCY = 5; + private final static int SECOND_SET_LEVEL_FREQUENCY = 3; + + private static long count = 0; + + /** + * Makes a scenario with len logger creations. Logger names are generated + * independently such that the overwhelming majority of logger names will be + * unrelated to each other. Each logger creation may be followed with a + * randomly generated set levelInt action on that logger. + * + * @param len + * @return + */ + static public Scenario makeTypeAScenario(int len) { + Scenario scenario = new Scenario(); + ; + for (int i = 0; i < len; i++) { + String loggerName = ScenarioRandomUtil.randomLoggerName( + AVERAGE_LOGGER_DEPTH, LOGGER_DEPT_DEV); + scenario.add(new CreateLogger(loggerName)); + } + return scenario; + } + + static public Scenario makeRealisticCreationScenario(int len) { + Scenario scenario = new Scenario(); + LinkedList queue = new LinkedList(); + int loggerCreationCount = 0; + + // add an empty string to get going + queue.add(""); + + while (loggerCreationCount < len) { + if ((count % 100) == 0) { + System.out.println("count=" + count); + } + + String loggerName = (String) queue.removeFirst(); + int randomChildrenCount = ScenarioRandomUtil + .randomChildrenCount(loggerName); + + if (randomChildrenCount == 0) { + scenario.add(new CreateLogger(loggerName)); + addSetLevelSubScenario(scenario, loggerName); + loggerCreationCount++; + } else { + for (int i = 0; i < randomChildrenCount; i++) { + String childName; + if (loggerName.equals("")) { + childName = ScenarioRandomUtil.randomId(); + count += childName.length(); + } else { + childName = loggerName + CoreConstants.DOT + + ScenarioRandomUtil.randomId(); + count += childName.length(); + } + queue.add(childName); + addSetLevelSubScenario(scenario, loggerName); + loggerCreationCount++; + } + } + } + return scenario; + } + + static void addSetLevelSubScenario(Scenario scenario, String loggerName) { + if (ScenarioRandomUtil.oneInFreq(CREATE_LOGGER_TO_SET_LEVEL_FREQUENCY)) { + Level l = ScenarioRandomUtil.randomLevel(); + scenario.add(new SetLevel(l, loggerName)); + if (ScenarioRandomUtil.oneInFreq(SECOND_SET_LEVEL_FREQUENCY)) { + l = ScenarioRandomUtil.randomLevel(); + scenario.add(new SetLevel(l, loggerName)); + } + } + } + } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioRandomUtil.java b/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioRandomUtil.java index 6ef2820e8fd73a57145fe101646ebcce1cef70f5..98393746ad42971193e8893d26ae2768a02d5dc0 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioRandomUtil.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/control/ScenarioRandomUtil.java @@ -1,135 +1,135 @@ -/** - * 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.classic.control; - -import java.util.Random; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.corpus.RandomUtil; - -public class ScenarioRandomUtil { - private final static long SEED = 74130; - - private final static Random random = new Random(SEED); - private final static int AVERAGE_ID_LEN = 32; - private final static int AVERAGE_ID_DEV = 16; - - private final static int AVERAGE_CHILDREN_COUNT = 30; - private final static int CHILDREN_COUNT_VAR = 10; - - public static boolean oneInFreq(int freq) { - return (random.nextInt(freq) % freq) == 0; - } - - public static Level randomLevel() { - int rl = random.nextInt(6); - switch (rl) { - case 0: - return null; - case 1: - return Level.TRACE; - case 2: - return Level.DEBUG; - case 3: - return Level.INFO; - case 4: - return Level.WARN; - case 5: - return Level.ERROR; - default: - throw new IllegalStateException( - "rl should have been a value between 0 to 5, but it is " + rl); - } - } - - public static String randomLoggerName(int average, int stdDeviation) { - int depth = RandomUtil.gaussianAsPositiveInt(random, average, stdDeviation); - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < depth; i++) { - if (i != 0) { - buf.append('.'); - } - buf.append(randomId()); - } - return buf.toString(); - } - - public static String randomId() { - - int len = RandomUtil.gaussianAsPositiveInt(random, AVERAGE_ID_LEN, AVERAGE_ID_DEV); - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < len; i++) { - int offset = random.nextInt(26); - char c = (char) ('a' + offset); - buf.append(c); - } - return buf.toString(); - } - - - /** - * Returns 3 for root, 3 for children of root, 9 for offspring of generation 2 - * and 3, and for generations 4 and later, return 0 with probability 0.5 and a - * gaussian (average=AVERAGE_CHILDREN_COUNT) with probability 0.5. - * - * @param name - * @return - */ - public static int randomChildrenCount(String name) { - int dots = dotCount(name); - if (dots <= 1) { - return 3; - } else if (dots == 2 || dots == 3) { - return 9; - } else { - if (shouldHaveChildrenWithProbabilitz(0.5)) { - return RandomUtil.gaussianAsPositiveInt(random, AVERAGE_CHILDREN_COUNT, CHILDREN_COUNT_VAR); - } else { - return 0; - } - } - - } - - /** - * Returns true with probability p. - * - * @param p - * @return - */ - static boolean shouldHaveChildrenWithProbabilitz(double p) { - if (p < 0 || p > 1.0) { - throw new IllegalArgumentException( - "p must be a value between 0 and 1.0, it was " + p + " instead."); - } - double r = random.nextDouble(); - if (r < p) { - return true; - } else { - return false; - } - } - - static int dotCount(String s) { - int count = 0; - int len = s.length(); - for (int i = 0; i < len; i++) { - char c = s.charAt(i); - if (c == '.') { - count++; - } - } - return count; - } -} +/** + * 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.classic.control; + +import java.util.Random; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.corpus.RandomUtil; + +public class ScenarioRandomUtil { + private final static long SEED = 74130; + + private final static Random random = new Random(SEED); + private final static int AVERAGE_ID_LEN = 32; + private final static int AVERAGE_ID_DEV = 16; + + private final static int AVERAGE_CHILDREN_COUNT = 30; + private final static int CHILDREN_COUNT_VAR = 10; + + public static boolean oneInFreq(int freq) { + return (random.nextInt(freq) % freq) == 0; + } + + public static Level randomLevel() { + int rl = random.nextInt(6); + switch (rl) { + case 0: + return null; + case 1: + return Level.TRACE; + case 2: + return Level.DEBUG; + case 3: + return Level.INFO; + case 4: + return Level.WARN; + case 5: + return Level.ERROR; + default: + throw new IllegalStateException( + "rl should have been a value between 0 to 5, but it is " + rl); + } + } + + public static String randomLoggerName(int average, int stdDeviation) { + int depth = RandomUtil.gaussianAsPositiveInt(random, average, stdDeviation); + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < depth; i++) { + if (i != 0) { + buf.append('.'); + } + buf.append(randomId()); + } + return buf.toString(); + } + + public static String randomId() { + + int len = RandomUtil.gaussianAsPositiveInt(random, AVERAGE_ID_LEN, AVERAGE_ID_DEV); + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < len; i++) { + int offset = random.nextInt(26); + char c = (char) ('a' + offset); + buf.append(c); + } + return buf.toString(); + } + + + /** + * Returns 3 for root, 3 for children of root, 9 for offspring of generation 2 + * and 3, and for generations 4 and later, return 0 with probability 0.5 and a + * gaussian (average=AVERAGE_CHILDREN_COUNT) with probability 0.5. + * + * @param name + * @return + */ + public static int randomChildrenCount(String name) { + int dots = dotCount(name); + if (dots <= 1) { + return 3; + } else if (dots == 2 || dots == 3) { + return 9; + } else { + if (shouldHaveChildrenWithProbabilitz(0.5)) { + return RandomUtil.gaussianAsPositiveInt(random, AVERAGE_CHILDREN_COUNT, CHILDREN_COUNT_VAR); + } else { + return 0; + } + } + + } + + /** + * Returns true with probability p. + * + * @param p + * @return + */ + static boolean shouldHaveChildrenWithProbabilitz(double p) { + if (p < 0 || p > 1.0) { + throw new IllegalArgumentException( + "p must be a value between 0 and 1.0, it was " + p + " instead."); + } + double r = random.nextDouble(); + if (r < p) { + return true; + } else { + return false; + } + } + + static int dotCount(String s) { + int count = 0; + int len = s.length(); + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + if (c == '.') { + count++; + } + } + return count; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/control/SetLevel.java b/logback-classic/src/test/java/ch/qos/logback/classic/control/SetLevel.java index 2605da209bb7c88e925b16985324dc352fa9ba23..c2b53d189d121d24eac503af65a8d39410978769 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/control/SetLevel.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/control/SetLevel.java @@ -1,37 +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.classic.control; - -import ch.qos.logback.classic.Level; - -public class SetLevel extends ScenarioAction { - final String loggerName; - final Level level; - - public SetLevel(Level level, String loggerName) { - this.level = level; - this.loggerName = loggerName; - } - - public Level getLevel() { - return level; - } - - public String getLoggerName() { - return loggerName; - } - public String toString() { - return "SetLevel("+level+", "+loggerName+")"; - } -} +/** + * 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.classic.control; + +import ch.qos.logback.classic.Level; + +public class SetLevel extends ScenarioAction { + final String loggerName; + final Level level; + + public SetLevel(Level level, String loggerName) { + this.level = level; + this.loggerName = loggerName; + } + + public Level getLevel() { + return level; + } + + public String getLoggerName() { + return loggerName; + } + public String toString() { + return "SetLevel("+level+", "+loggerName+")"; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/Corpus.java b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/Corpus.java index 254522df47cd02dc5ed7349cb77edd235fe28d8b..ee911c820c02cd6e849cb507f610ef08a809d251 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/Corpus.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/Corpus.java @@ -1,118 +1,118 @@ -/** - * 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.classic.corpus; - -import java.io.FileWriter; -import java.io.IOException; -import java.net.URL; -import java.util.List; - -import ch.qos.logback.classic.ClassicConstants; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.IThrowableProxy; -import ch.qos.logback.classic.spi.LoggerContextVO; -import ch.qos.logback.classic.spi.PubLoggingEventVO; -import ch.qos.logback.classic.spi.ThrowableProxyUtil; -import ch.qos.logback.core.CoreConstants; - -/** - * - *

Usage: - * - *

ILoggingEvent[] eventArray = Corpus.makeStandardCorpus(); - * - *

if you wish to dump the events into a file, say "/corpus.log" : - * - *

Corpus.dump(eventArray, "/corpus.log"); - * - *

For the model behind the corpus, refer to {@link CorpusModel}. - * - * @author Ceki Gülcü - * - */ -public class Corpus { - - static public final int STANDARD_CORPUS_SIZE = 50 * 1000; - private static final int STANDARD_SEED = 34780; - - static public List getStandatdCorpusWordList() throws IOException { - ClassLoader classLoader = Corpus.class.getClassLoader(); - URL originOfSpeciesURL = classLoader - .getResource("corpus/origin_of_species.txt"); - return TextFileUtil.toWords(originOfSpeciesURL); - } - - /** - * Make a standard corpus. The standard corpus has - * {@link #STANDARD_CORPUS_SIZE} elements. - * - * @return event array representing the standard corpus - * @throws IOException - */ - static public ILoggingEvent[] makeStandardCorpus() throws IOException { - List worldList = getStandatdCorpusWordList(); - CorpusModel corpusMaker = new CorpusModel(STANDARD_SEED, worldList); - return make(corpusMaker, STANDARD_CORPUS_SIZE, true); - } - - static public ILoggingEvent[] make(CorpusModel corpusModel, int n, - boolean withCallerData) { - LoggerContextVO lcVO = corpusModel.getRandomlyNamedLoggerContextVO(); - PubLoggingEventVO[] plevoArray = new PubLoggingEventVO[n]; - for (int i = 0; i < n; i++) { - PubLoggingEventVO e = new PubLoggingEventVO(); - plevoArray[i] = e; - e.loggerContextVO = lcVO; - e.timeStamp = corpusModel.getRandomTimeStamp(); - - LogStatement logStatement = corpusModel.getRandomLogStatementFromPool(); - e.loggerName = logStatement.loggerName; - e.level = logStatement.level; - e.message = logStatement.mat.message; - e.argumentArray = corpusModel - .getRandomArgumentArray(logStatement.mat.numberOfArguments); - - if (withCallerData) { - e.callerDataArray = corpusModel.getRandomCallerData( - ClassicConstants.DEFAULT_MAX_CALLEDER_DATA_DEPTH, e.loggerName); - } - e.throwableProxy = logStatement.throwableProxy; - e.threadName = corpusModel.getRandomThreadNameFromPool(); - } - return plevoArray; - } - - /** - * Dump the events passed as argument into the file named targetFile. - * - * @param eventArray - * @param targetFile - * @throws IOException - */ - public static void dump(ILoggingEvent[] eventArray, String targetFile) - throws IOException { - FileWriter fw = new FileWriter(targetFile); - for (ILoggingEvent e : eventArray) { - fw.write(e.toString()); - fw.append(CoreConstants.LINE_SEPARATOR); - if (e.getThrowableProxy() != null) { - IThrowableProxy tp = e.getThrowableProxy(); - fw.write(ThrowableProxyUtil.asString(tp)); - } - } - fw.flush(); - fw.close(); - } - -} +/** + * 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.classic.corpus; + +import java.io.FileWriter; +import java.io.IOException; +import java.net.URL; +import java.util.List; + +import ch.qos.logback.classic.ClassicConstants; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.LoggerContextVO; +import ch.qos.logback.classic.spi.PubLoggingEventVO; +import ch.qos.logback.classic.spi.ThrowableProxyUtil; +import ch.qos.logback.core.CoreConstants; + +/** + * + *

Usage: + * + *

ILoggingEvent[] eventArray = Corpus.makeStandardCorpus(); + * + *

if you wish to dump the events into a file, say "/corpus.log" : + * + *

Corpus.dump(eventArray, "/corpus.log"); + * + *

For the model behind the corpus, refer to {@link CorpusModel}. + * + * @author Ceki Gülcü + * + */ +public class Corpus { + + static public final int STANDARD_CORPUS_SIZE = 50 * 1000; + private static final int STANDARD_SEED = 34780; + + static public List getStandatdCorpusWordList() throws IOException { + ClassLoader classLoader = Corpus.class.getClassLoader(); + URL originOfSpeciesURL = classLoader + .getResource("corpus/origin_of_species.txt"); + return TextFileUtil.toWords(originOfSpeciesURL); + } + + /** + * Make a standard corpus. The standard corpus has + * {@link #STANDARD_CORPUS_SIZE} elements. + * + * @return event array representing the standard corpus + * @throws IOException + */ + static public ILoggingEvent[] makeStandardCorpus() throws IOException { + List worldList = getStandatdCorpusWordList(); + CorpusModel corpusMaker = new CorpusModel(STANDARD_SEED, worldList); + return make(corpusMaker, STANDARD_CORPUS_SIZE, true); + } + + static public ILoggingEvent[] make(CorpusModel corpusModel, int n, + boolean withCallerData) { + LoggerContextVO lcVO = corpusModel.getRandomlyNamedLoggerContextVO(); + PubLoggingEventVO[] plevoArray = new PubLoggingEventVO[n]; + for (int i = 0; i < n; i++) { + PubLoggingEventVO e = new PubLoggingEventVO(); + plevoArray[i] = e; + e.loggerContextVO = lcVO; + e.timeStamp = corpusModel.getRandomTimeStamp(); + + LogStatement logStatement = corpusModel.getRandomLogStatementFromPool(); + e.loggerName = logStatement.loggerName; + e.level = logStatement.level; + e.message = logStatement.mat.message; + e.argumentArray = corpusModel + .getRandomArgumentArray(logStatement.mat.numberOfArguments); + + if (withCallerData) { + e.callerDataArray = corpusModel.getRandomCallerData( + ClassicConstants.DEFAULT_MAX_CALLEDER_DATA_DEPTH, e.loggerName); + } + e.throwableProxy = logStatement.throwableProxy; + e.threadName = corpusModel.getRandomThreadNameFromPool(); + } + return plevoArray; + } + + /** + * Dump the events passed as argument into the file named targetFile. + * + * @param eventArray + * @param targetFile + * @throws IOException + */ + public static void dump(ILoggingEvent[] eventArray, String targetFile) + throws IOException { + FileWriter fw = new FileWriter(targetFile); + for (ILoggingEvent e : eventArray) { + fw.write(e.toString()); + fw.append(CoreConstants.LINE_SEPARATOR); + if (e.getThrowableProxy() != null) { + IThrowableProxy tp = e.getThrowableProxy(); + fw.write(ThrowableProxyUtil.asString(tp)); + } + } + fw.flush(); + fw.close(); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/CorpusModel.java b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/CorpusModel.java index e7749bbbc0a1ad3259807e873a05984c74087388..649855df5a49fcfa115568a7421b18c9e5047c2c 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/CorpusModel.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/CorpusModel.java @@ -1,324 +1,324 @@ -/** - * 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.classic.corpus; - -import java.util.List; -import java.util.Random; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.ClassPackagingData; -import ch.qos.logback.classic.spi.LoggerContextVO; -import ch.qos.logback.classic.spi.StackTraceElementProxy; -import ch.qos.logback.classic.spi.ThrowableProxy; -import ch.qos.logback.classic.spi.ThrowableProxyVO; - -/** - * Models the corpus. - * - *

This contains the probability distributions of levels, logger names, - * messages, message arguments. - * - * @author Ceki Gülcü - * - */ -public class CorpusModel { - - // N(u,s) denotes a random variable normally distributed with mean u and - // variance sqrt(s), where sqrt() is the square root function. For an - // explanation of normal distribution please see - // http://en.wikipedia.org/wiki/Normal_distribution - - // It is assumed that the number of parts in a logger name is a random - // variable normally distributed with mean AVERAGE_LOGGER_NAME_PARTS and - // standard deviation STD_DEV_FOR_LOGGER_NAME_PARTS - static final int AVERAGE_LOGGER_NAME_PARTS = 6; - static final int STD_DEV_FOR_LOGGER_NAME_PARTS = 3; - - // It is assumed that there are LOGGER_POOL_SIZE logger names - // in our model corpus. - static final int LOGGER_POOL_SIZE = 1000; - - // It is assumed that there are LOG_STATEMENT_POOL_SIZE log statements - // in our model corpus. - static final int LOG_STATEMENT_POOL_SIZE = LOGGER_POOL_SIZE * 8; - - // level distribution is determined by the following table - // It corresponds to TRACE 3%, DEBUG 30%, INFO 30%, WARN 5%, - // ERROR 5%. See also getRandomLevel() method. - static final double[] LEVEL_DISTRIBUTION = new double[] { .3, .3, .9, .95 }; - - // It is assumed that the number of words in the message (contained in a log - // statement) is a random variable normally distributed with mean - // AVERAGE_MESSAGE_WORDS and standard deviation STD_DEV_FOR_MESSAGE_WORDS - static final int AVERAGE_MESSAGE_WORDS = 8; - static final int STD_DEV_FOR_MESSAGE_WORDS = 4; - - // messages will have no arguments 80% of the time, one argument in 8%, two - // arguments in 7% and three arguments in 5% of cases - static final double[] ARGUMENT_DISTRIBUTION = new double[] { .80, .88, 0.95 }; - - static final double THROWABLE_PROPABILITY_FOR_WARNING = .1; - static final double THROWABLE_PROPABILITY_FOR_ERRORS = .3; - // .5 of throwables are nested once - static final double NESTING_PROBABILITY = .5; - - // For each logging event the timer is incremented by a certain value. it is - // assumed that this value is a random variable normally distributed with mean - // AVERAGE_MILLIS_INCREMENT and standard deviation - // STD_DEV_FOR_MILLIS_INCREMENT - static final int AVERAGE_MILLIS_INCREMENT = 10; - static final int STD_DEV_FOR_MILLIS_INCREMENT = 5; - - // assume that there are THREAD_POOL_SIZE threads in the corpus - static final int THREAD_POOL_SIZE = 10; - - final Random random; - final List worldList; - String[] threadNamePool; - LogStatement[] logStatementPool; - String[] loggerNamePool; - - // 2009-03-06 13:08 GMT - long lastTimeStamp = 1236344888578L; - - public CorpusModel(long seed, List worldList) { - random = new Random(seed); - this.worldList = worldList; - buildThreadNamePool(); - buildLoggerNamePool(); - buildLogStatementPool(); - } - - private void buildThreadNamePool() { - threadNamePool = new String[THREAD_POOL_SIZE]; - for (int i = 0; i < THREAD_POOL_SIZE; i++) { - threadNamePool[i] = "CorpusMakerThread-" + i; - } - } - - private void buildLoggerNamePool() { - loggerNamePool = new String[LOGGER_POOL_SIZE]; - for (int i = 0; i < LOGGER_POOL_SIZE; i++) { - loggerNamePool[i] = makeRandomLoggerName(); - } - } - - private void buildLogStatementPool() { - logStatementPool = new LogStatement[LOG_STATEMENT_POOL_SIZE]; - for (int i = 0; i < LOG_STATEMENT_POOL_SIZE; i++) { - logStatementPool[i] = makeRandomLogStatement(loggerNamePool); - } - } - - private int[] getRandomAnchorPositions(int wordCount, int numAnchors) { - // note that the same position may appear multiple times in - // positionsIndex, but without serious consequences - int[] positionsIndex = new int[numAnchors]; - for (int i = 0; i < numAnchors; i++) { - positionsIndex[i] = random.nextInt(wordCount); - } - return positionsIndex; - } - - private String[] getRandomWords(int n) { - String[] wordArray = new String[n]; - for (int i = 0; i < n; i++) { - wordArray[i] = getRandomWord(); - } - return wordArray; - } - - public long getRandomLong() { - return random.nextLong(); - } - - public String getRandomThreadNameFromPool() { - int index = random.nextInt(THREAD_POOL_SIZE); - return threadNamePool[index]; - } - - public LogStatement getRandomLogStatementFromPool() { - int index = random.nextInt(logStatementPool.length); - return logStatementPool[index]; - } - - private String getRandomLoggerNameFromPool(String[] loggerNamePool) { - int index = random.nextInt(loggerNamePool.length); - return loggerNamePool[index]; - } - - public long getRandomTimeStamp() { - // subtract 1 so that 0 is allowed - lastTimeStamp += RandomUtil.gaussianAsPositiveInt(random, - AVERAGE_MILLIS_INCREMENT, STD_DEV_FOR_MILLIS_INCREMENT) - 1; - return lastTimeStamp; - } - - LoggerContextVO getRandomlyNamedLoggerContextVO() { - LoggerContext lc = new LoggerContext(); - lc.setName(getRandomJavaIdentifier()); - return new LoggerContextVO(lc); - } - - String getRandomWord() { - int size = worldList.size(); - int randomIndex = random.nextInt(size); - return worldList.get(randomIndex); - } - - String extractLastPart(String loggerName) { - int i = loggerName.lastIndexOf('.'); - if (i == -1) { - return loggerName; - } else { - return loggerName.substring(i + 1); - } - } - - public StackTraceElement[] getRandomCallerData(int depth, String loggerName) { - StackTraceElement[] cda = new StackTraceElement[depth]; - StackTraceElement cd = new StackTraceElement(loggerName, - getRandomJavaIdentifier(), extractLastPart(loggerName), 0); - cda[0] = cd; - for (int i = 1; i < depth; i++) { - String ln = getRandomLoggerNameFromPool(loggerNamePool); - cda[i] = new StackTraceElement(ln, getRandomJavaIdentifier(), - extractLastPart(ln), i * 10); - } - return cda; - } - - public Object[] getRandomArgumentArray(int numOfArguments) { - if (numOfArguments == 0) { - return null; - } - Object[] argumentArray = new Object[numOfArguments]; - for (int i = 0; i < numOfArguments; i++) { - argumentArray[i] = new Long(random.nextLong()); - } - return argumentArray; - } - - private MessageArgumentTuple makeRandomMessageArgumentTuple() { - int numOfArguments = getNumberOfMessageArguments(); - - int wordCount = RandomUtil.gaussianAsPositiveInt(random, - AVERAGE_MESSAGE_WORDS, STD_DEV_FOR_MESSAGE_WORDS); - String[] wordArray = getRandomWords(wordCount); - - int[] anchorPositions = getRandomAnchorPositions(wordCount, numOfArguments); - - for (int anchorIndex : anchorPositions) { - wordArray[anchorIndex] = "{}"; - } - - StringBuilder sb = new StringBuilder(); - for (int i = 1; i < wordCount; i++) { - sb.append(wordArray[i]).append(' '); - } - sb.append(getRandomWord()); - return new MessageArgumentTuple(sb.toString(), numOfArguments); - } - - private LogStatement makeRandomLogStatement(String[] loggerNamePool) { - MessageArgumentTuple mat = makeRandomMessageArgumentTuple(); - String loggerName = getRandomLoggerNameFromPool(loggerNamePool); - Level randomLevel = getRandomLevel(); - Throwable t = getRandomThrowable(randomLevel); - ThrowableProxyVO throwableProxy = null; - if (t != null) { - throwableProxy = ThrowableProxyVO.build(new ThrowableProxy(t)); - pupulateWithPackagingData(throwableProxy.getStackTraceElementProxyArray()); - } - LogStatement logStatement = new LogStatement(loggerName, randomLevel, mat, - throwableProxy); - return logStatement; - } - - private Throwable getRandomThrowable(Level level) { - double rn = random.nextDouble(); - if ((level == Level.WARN && rn < THROWABLE_PROPABILITY_FOR_WARNING) - || (level == Level.ERROR && rn < THROWABLE_PROPABILITY_FOR_ERRORS)) { - return ExceptionBuilder.build(random, NESTING_PROBABILITY); - } else { - return null; - } - } - - private void pupulateWithPackagingData(StackTraceElementProxy[] stepArray) { - int i = 0; - for (StackTraceElementProxy step : stepArray) { - String identifier = "na"; - String version = "na"; - if (i++ % 2 == 0) { - identifier = getRandomJavaIdentifier(); - version = getRandomJavaIdentifier(); - } - ClassPackagingData cpd = new ClassPackagingData(identifier, version); - step.setClassPackagingData(cpd); - } - } - - private int getNumberOfMessageArguments() { - double rn = random.nextDouble(); - if (rn < ARGUMENT_DISTRIBUTION[0]) { - return 0; - } - if (rn < ARGUMENT_DISTRIBUTION[1]) { - return 1; - } - if (rn < ARGUMENT_DISTRIBUTION[2]) { - return 2; - } - return 3; - } - - String getRandomJavaIdentifier() { - String w = getRandomWord(); - w = w.replaceAll("\\p{Punct}", ""); - return w; - } - - private String makeRandomLoggerName() { - int parts = RandomUtil.gaussianAsPositiveInt(random, - AVERAGE_LOGGER_NAME_PARTS, STD_DEV_FOR_LOGGER_NAME_PARTS); - StringBuilder sb = new StringBuilder(); - for (int i = 1; i < parts; i++) { - sb.append(getRandomJavaIdentifier()).append('.'); - } - sb.append(getRandomJavaIdentifier()); - return sb.toString(); - } - - private Level getRandomLevel() { - double rn = random.nextDouble(); - if (rn < LEVEL_DISTRIBUTION[0]) { - return Level.TRACE; - } - if (rn < LEVEL_DISTRIBUTION[1]) { - return Level.DEBUG; - } - - if (rn < LEVEL_DISTRIBUTION[2]) { - return Level.INFO; - } - - if (rn < LEVEL_DISTRIBUTION[3]) { - return Level.WARN; - } - - return Level.ERROR; - } -} +/** + * 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.classic.corpus; + +import java.util.List; +import java.util.Random; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ClassPackagingData; +import ch.qos.logback.classic.spi.LoggerContextVO; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.classic.spi.ThrowableProxy; +import ch.qos.logback.classic.spi.ThrowableProxyVO; + +/** + * Models the corpus. + * + *

This contains the probability distributions of levels, logger names, + * messages, message arguments. + * + * @author Ceki Gülcü + * + */ +public class CorpusModel { + + // N(u,s) denotes a random variable normally distributed with mean u and + // variance sqrt(s), where sqrt() is the square root function. For an + // explanation of normal distribution please see + // http://en.wikipedia.org/wiki/Normal_distribution + + // It is assumed that the number of parts in a logger name is a random + // variable normally distributed with mean AVERAGE_LOGGER_NAME_PARTS and + // standard deviation STD_DEV_FOR_LOGGER_NAME_PARTS + static final int AVERAGE_LOGGER_NAME_PARTS = 6; + static final int STD_DEV_FOR_LOGGER_NAME_PARTS = 3; + + // It is assumed that there are LOGGER_POOL_SIZE logger names + // in our model corpus. + static final int LOGGER_POOL_SIZE = 1000; + + // It is assumed that there are LOG_STATEMENT_POOL_SIZE log statements + // in our model corpus. + static final int LOG_STATEMENT_POOL_SIZE = LOGGER_POOL_SIZE * 8; + + // level distribution is determined by the following table + // It corresponds to TRACE 3%, DEBUG 30%, INFO 30%, WARN 5%, + // ERROR 5%. See also getRandomLevel() method. + static final double[] LEVEL_DISTRIBUTION = new double[] { .3, .3, .9, .95 }; + + // It is assumed that the number of words in the message (contained in a log + // statement) is a random variable normally distributed with mean + // AVERAGE_MESSAGE_WORDS and standard deviation STD_DEV_FOR_MESSAGE_WORDS + static final int AVERAGE_MESSAGE_WORDS = 8; + static final int STD_DEV_FOR_MESSAGE_WORDS = 4; + + // messages will have no arguments 80% of the time, one argument in 8%, two + // arguments in 7% and three arguments in 5% of cases + static final double[] ARGUMENT_DISTRIBUTION = new double[] { .80, .88, 0.95 }; + + static final double THROWABLE_PROPABILITY_FOR_WARNING = .1; + static final double THROWABLE_PROPABILITY_FOR_ERRORS = .3; + // .5 of throwables are nested once + static final double NESTING_PROBABILITY = .5; + + // For each logging event the timer is incremented by a certain value. it is + // assumed that this value is a random variable normally distributed with mean + // AVERAGE_MILLIS_INCREMENT and standard deviation + // STD_DEV_FOR_MILLIS_INCREMENT + static final int AVERAGE_MILLIS_INCREMENT = 10; + static final int STD_DEV_FOR_MILLIS_INCREMENT = 5; + + // assume that there are THREAD_POOL_SIZE threads in the corpus + static final int THREAD_POOL_SIZE = 10; + + final Random random; + final List worldList; + String[] threadNamePool; + LogStatement[] logStatementPool; + String[] loggerNamePool; + + // 2009-03-06 13:08 GMT + long lastTimeStamp = 1236344888578L; + + public CorpusModel(long seed, List worldList) { + random = new Random(seed); + this.worldList = worldList; + buildThreadNamePool(); + buildLoggerNamePool(); + buildLogStatementPool(); + } + + private void buildThreadNamePool() { + threadNamePool = new String[THREAD_POOL_SIZE]; + for (int i = 0; i < THREAD_POOL_SIZE; i++) { + threadNamePool[i] = "CorpusMakerThread-" + i; + } + } + + private void buildLoggerNamePool() { + loggerNamePool = new String[LOGGER_POOL_SIZE]; + for (int i = 0; i < LOGGER_POOL_SIZE; i++) { + loggerNamePool[i] = makeRandomLoggerName(); + } + } + + private void buildLogStatementPool() { + logStatementPool = new LogStatement[LOG_STATEMENT_POOL_SIZE]; + for (int i = 0; i < LOG_STATEMENT_POOL_SIZE; i++) { + logStatementPool[i] = makeRandomLogStatement(loggerNamePool); + } + } + + private int[] getRandomAnchorPositions(int wordCount, int numAnchors) { + // note that the same position may appear multiple times in + // positionsIndex, but without serious consequences + int[] positionsIndex = new int[numAnchors]; + for (int i = 0; i < numAnchors; i++) { + positionsIndex[i] = random.nextInt(wordCount); + } + return positionsIndex; + } + + private String[] getRandomWords(int n) { + String[] wordArray = new String[n]; + for (int i = 0; i < n; i++) { + wordArray[i] = getRandomWord(); + } + return wordArray; + } + + public long getRandomLong() { + return random.nextLong(); + } + + public String getRandomThreadNameFromPool() { + int index = random.nextInt(THREAD_POOL_SIZE); + return threadNamePool[index]; + } + + public LogStatement getRandomLogStatementFromPool() { + int index = random.nextInt(logStatementPool.length); + return logStatementPool[index]; + } + + private String getRandomLoggerNameFromPool(String[] loggerNamePool) { + int index = random.nextInt(loggerNamePool.length); + return loggerNamePool[index]; + } + + public long getRandomTimeStamp() { + // subtract 1 so that 0 is allowed + lastTimeStamp += RandomUtil.gaussianAsPositiveInt(random, + AVERAGE_MILLIS_INCREMENT, STD_DEV_FOR_MILLIS_INCREMENT) - 1; + return lastTimeStamp; + } + + LoggerContextVO getRandomlyNamedLoggerContextVO() { + LoggerContext lc = new LoggerContext(); + lc.setName(getRandomJavaIdentifier()); + return new LoggerContextVO(lc); + } + + String getRandomWord() { + int size = worldList.size(); + int randomIndex = random.nextInt(size); + return worldList.get(randomIndex); + } + + String extractLastPart(String loggerName) { + int i = loggerName.lastIndexOf('.'); + if (i == -1) { + return loggerName; + } else { + return loggerName.substring(i + 1); + } + } + + public StackTraceElement[] getRandomCallerData(int depth, String loggerName) { + StackTraceElement[] cda = new StackTraceElement[depth]; + StackTraceElement cd = new StackTraceElement(loggerName, + getRandomJavaIdentifier(), extractLastPart(loggerName), 0); + cda[0] = cd; + for (int i = 1; i < depth; i++) { + String ln = getRandomLoggerNameFromPool(loggerNamePool); + cda[i] = new StackTraceElement(ln, getRandomJavaIdentifier(), + extractLastPart(ln), i * 10); + } + return cda; + } + + public Object[] getRandomArgumentArray(int numOfArguments) { + if (numOfArguments == 0) { + return null; + } + Object[] argumentArray = new Object[numOfArguments]; + for (int i = 0; i < numOfArguments; i++) { + argumentArray[i] = new Long(random.nextLong()); + } + return argumentArray; + } + + private MessageArgumentTuple makeRandomMessageArgumentTuple() { + int numOfArguments = getNumberOfMessageArguments(); + + int wordCount = RandomUtil.gaussianAsPositiveInt(random, + AVERAGE_MESSAGE_WORDS, STD_DEV_FOR_MESSAGE_WORDS); + String[] wordArray = getRandomWords(wordCount); + + int[] anchorPositions = getRandomAnchorPositions(wordCount, numOfArguments); + + for (int anchorIndex : anchorPositions) { + wordArray[anchorIndex] = "{}"; + } + + StringBuilder sb = new StringBuilder(); + for (int i = 1; i < wordCount; i++) { + sb.append(wordArray[i]).append(' '); + } + sb.append(getRandomWord()); + return new MessageArgumentTuple(sb.toString(), numOfArguments); + } + + private LogStatement makeRandomLogStatement(String[] loggerNamePool) { + MessageArgumentTuple mat = makeRandomMessageArgumentTuple(); + String loggerName = getRandomLoggerNameFromPool(loggerNamePool); + Level randomLevel = getRandomLevel(); + Throwable t = getRandomThrowable(randomLevel); + ThrowableProxyVO throwableProxy = null; + if (t != null) { + throwableProxy = ThrowableProxyVO.build(new ThrowableProxy(t)); + pupulateWithPackagingData(throwableProxy.getStackTraceElementProxyArray()); + } + LogStatement logStatement = new LogStatement(loggerName, randomLevel, mat, + throwableProxy); + return logStatement; + } + + private Throwable getRandomThrowable(Level level) { + double rn = random.nextDouble(); + if ((level == Level.WARN && rn < THROWABLE_PROPABILITY_FOR_WARNING) + || (level == Level.ERROR && rn < THROWABLE_PROPABILITY_FOR_ERRORS)) { + return ExceptionBuilder.build(random, NESTING_PROBABILITY); + } else { + return null; + } + } + + private void pupulateWithPackagingData(StackTraceElementProxy[] stepArray) { + int i = 0; + for (StackTraceElementProxy step : stepArray) { + String identifier = "na"; + String version = "na"; + if (i++ % 2 == 0) { + identifier = getRandomJavaIdentifier(); + version = getRandomJavaIdentifier(); + } + ClassPackagingData cpd = new ClassPackagingData(identifier, version); + step.setClassPackagingData(cpd); + } + } + + private int getNumberOfMessageArguments() { + double rn = random.nextDouble(); + if (rn < ARGUMENT_DISTRIBUTION[0]) { + return 0; + } + if (rn < ARGUMENT_DISTRIBUTION[1]) { + return 1; + } + if (rn < ARGUMENT_DISTRIBUTION[2]) { + return 2; + } + return 3; + } + + String getRandomJavaIdentifier() { + String w = getRandomWord(); + w = w.replaceAll("\\p{Punct}", ""); + return w; + } + + private String makeRandomLoggerName() { + int parts = RandomUtil.gaussianAsPositiveInt(random, + AVERAGE_LOGGER_NAME_PARTS, STD_DEV_FOR_LOGGER_NAME_PARTS); + StringBuilder sb = new StringBuilder(); + for (int i = 1; i < parts; i++) { + sb.append(getRandomJavaIdentifier()).append('.'); + } + sb.append(getRandomJavaIdentifier()); + return sb.toString(); + } + + private Level getRandomLevel() { + double rn = random.nextDouble(); + if (rn < LEVEL_DISTRIBUTION[0]) { + return Level.TRACE; + } + if (rn < LEVEL_DISTRIBUTION[1]) { + return Level.DEBUG; + } + + if (rn < LEVEL_DISTRIBUTION[2]) { + return Level.INFO; + } + + if (rn < LEVEL_DISTRIBUTION[3]) { + return Level.WARN; + } + + return Level.ERROR; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/ExceptionBuilder.java b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/ExceptionBuilder.java index 92d517abd3c31206fb492bb247c59bb8475e2f46..ff91fb4fb3d49a393e767e0b69533eb5735f526c 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/ExceptionBuilder.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/ExceptionBuilder.java @@ -1,47 +1,47 @@ -/** - * 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.classic.corpus; - -import java.util.Random; - -import javax.management.remote.JMXProviderException; - -public class ExceptionBuilder { - - static Throwable build(Random r, double nestingProbability) { - double rn = r.nextDouble(); - boolean nested = false; - if (rn < nestingProbability) { - nested = true; - } - - Throwable cause = null; - if(nested) { - cause = makeThrowable(r, null); - } - return makeThrowable(r, cause); - } - - private static Throwable makeThrowable(Random r, Throwable cause) { - int exType = r.nextInt(4); - switch(exType) { - case 0: return new IllegalArgumentException("an illegal argument was passed", cause); - case 1: return new Exception("this is a test", cause); - case 2: return new JMXProviderException("jmx provider exception error occured", cause); - case 3: return new OutOfMemoryError("ran out of memory"); - } - return null; - } - -} +/** + * 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.classic.corpus; + +import java.util.Random; + +import javax.management.remote.JMXProviderException; + +public class ExceptionBuilder { + + static Throwable build(Random r, double nestingProbability) { + double rn = r.nextDouble(); + boolean nested = false; + if (rn < nestingProbability) { + nested = true; + } + + Throwable cause = null; + if(nested) { + cause = makeThrowable(r, null); + } + return makeThrowable(r, cause); + } + + private static Throwable makeThrowable(Random r, Throwable cause) { + int exType = r.nextInt(4); + switch(exType) { + case 0: return new IllegalArgumentException("an illegal argument was passed", cause); + case 1: return new Exception("this is a test", cause); + case 2: return new JMXProviderException("jmx provider exception error occured", cause); + case 3: return new OutOfMemoryError("ran out of memory"); + } + return null; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/LogStatement.java b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/LogStatement.java index 2665c688f123484db3e56e883849fc39ec012a07..802a227091d32097096c2700d5acea2abff682d2 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/LogStatement.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/LogStatement.java @@ -1,42 +1,42 @@ -/** - * 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.classic.corpus; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.IThrowableProxy; - -/** - * Captures the data contained within a log statement, that is the data that the - * developer puts in the source code when he writes: - * - *

logger.debug("hello world"); - * - * @author Ceki Gülcü - */ -public class LogStatement { - - final String loggerName; - final MessageArgumentTuple mat; - final Level level; - final IThrowableProxy throwableProxy; - - public LogStatement(String loggerName, Level level, MessageArgumentTuple mat, - IThrowableProxy tp) { - this.loggerName = loggerName; - this.level = level; - this.mat = mat; - this.throwableProxy = tp; - } - -} +/** + * 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.classic.corpus; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.IThrowableProxy; + +/** + * Captures the data contained within a log statement, that is the data that the + * developer puts in the source code when he writes: + * + *

logger.debug("hello world"); + * + * @author Ceki Gülcü + */ +public class LogStatement { + + final String loggerName; + final MessageArgumentTuple mat; + final Level level; + final IThrowableProxy throwableProxy; + + public LogStatement(String loggerName, Level level, MessageArgumentTuple mat, + IThrowableProxy tp) { + this.loggerName = loggerName; + this.level = level; + this.mat = mat; + this.throwableProxy = tp; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/MessageArgumentTuple.java b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/MessageArgumentTuple.java index 4fe8086cebe693719679d970af9eeb0e436780aa..25ee8b7f425db086312430aa87b62798a70c6222 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/MessageArgumentTuple.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/MessageArgumentTuple.java @@ -1,30 +1,30 @@ -/** - * 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.classic.corpus; - -public class MessageArgumentTuple { - - final String message; - final int numberOfArguments; - - MessageArgumentTuple(String message) { - this(message, 0); - } - - public MessageArgumentTuple(String message, int numberOfArguments) { - this.message = message; - this.numberOfArguments = numberOfArguments; - } - -} +/** + * 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.classic.corpus; + +public class MessageArgumentTuple { + + final String message; + final int numberOfArguments; + + MessageArgumentTuple(String message) { + this(message, 0); + } + + public MessageArgumentTuple(String message, int numberOfArguments) { + this.message = message; + this.numberOfArguments = numberOfArguments; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/RandomUtil.java b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/RandomUtil.java index 1b1b0f67d397da07bdff636d21e8353af1d7d3d6..cd835a9effbb1210353ca48f4011156e8190017d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/RandomUtil.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/RandomUtil.java @@ -1,46 +1,46 @@ -/** - * 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.classic.corpus; - -import java.util.Random; - -public class RandomUtil { - - - /** - * Approximate a gaussian distrib with only positive integer values - * - * @param average - * @param stdDeviation - * @return - */ - static public int gaussianAsPositiveInt(Random random, int average, int stdDeviation) { - if (average < 1) { - throw new IllegalArgumentException( - "The average must not be smaller than 1."); - } - - if (stdDeviation < 1) { - throw new IllegalArgumentException( - "The stdDeviation must not be smaller than 1."); - } - - double d = random.nextGaussian() * stdDeviation + average; - int result = 1; - if (d > 1.0) { - result = (int) Math.round(d); - } - return result; - } -} +/** + * 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.classic.corpus; + +import java.util.Random; + +public class RandomUtil { + + + /** + * Approximate a gaussian distrib with only positive integer values + * + * @param average + * @param stdDeviation + * @return + */ + static public int gaussianAsPositiveInt(Random random, int average, int stdDeviation) { + if (average < 1) { + throw new IllegalArgumentException( + "The average must not be smaller than 1."); + } + + if (stdDeviation < 1) { + throw new IllegalArgumentException( + "The stdDeviation must not be smaller than 1."); + } + + double d = random.nextGaussian() * stdDeviation + average; + int result = 1; + if (d > 1.0) { + result = (int) Math.round(d); + } + return result; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/TextFileUtil.java b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/TextFileUtil.java index d6412f753469ead82e9ef24f2fdde03597795f00..7e4ac5c4be7f94591c9dfa22d5a5085449a254ba 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/corpus/TextFileUtil.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/corpus/TextFileUtil.java @@ -1,61 +1,61 @@ -/** - * 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.classic.corpus; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -public class TextFileUtil { - - - public static List toWords(URL url) throws IOException { - InputStream is = url.openStream(); - InputStreamReader reader = new InputStreamReader(is); - BufferedReader br = new BufferedReader(reader); - return toWords(br); - } - - public static List toWords(String filename) throws IOException { - FileReader fr = new FileReader(filename); - BufferedReader br = new BufferedReader(fr); - return toWords(br); - } - - public static List toWords(BufferedReader br) throws IOException { - - // (\\d+)$ - //String regExp = "^(\\d+) "+ msg + " ([\\dabcdef-]+)$"; - //Pattern p = Pattern.compile(regExp); - String line; - - List wordList = new ArrayList(); - - while ((line = br.readLine()) != null) { - //line = line.replaceAll("\\p{Punct}+", " "); - String[] words = line.split("\\s"); - for(String word: words) { - wordList.add(word); - } - } - br.close(); - - return wordList; - } -} +/** + * 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.classic.corpus; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +public class TextFileUtil { + + + public static List toWords(URL url) throws IOException { + InputStream is = url.openStream(); + InputStreamReader reader = new InputStreamReader(is); + BufferedReader br = new BufferedReader(reader); + return toWords(br); + } + + public static List toWords(String filename) throws IOException { + FileReader fr = new FileReader(filename); + BufferedReader br = new BufferedReader(fr); + return toWords(br); + } + + public static List toWords(BufferedReader br) throws IOException { + + // (\\d+)$ + //String regExp = "^(\\d+) "+ msg + " ([\\dabcdef-]+)$"; + //Pattern p = Pattern.compile(regExp); + String line; + + List wordList = new ArrayList(); + + while ((line = br.readLine()) != null) { + //line = line.replaceAll("\\p{Punct}+", " "); + String[] words = line.split("\\s"); + for(String word: words) { + wordList.add(word); + } + } + br.close(); + + return wordList; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/corpusTest/RandomUtilTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/corpusTest/RandomUtilTest.java index 0da71f9daa2e2afa21ff4a888df4a8d5f4c7b975..9159d6e8dfc2041145e73cc4bd093db4d32f243d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/corpusTest/RandomUtilTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/corpusTest/RandomUtilTest.java @@ -1,61 +1,61 @@ -/** - * 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.classic.corpusTest; - -import static org.junit.Assert.assertEquals; - -import java.util.Random; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.corpus.RandomUtil; - - -public class RandomUtilTest { - long now = System.currentTimeMillis(); - - @Before - public void setup() { - System.out.println(RandomUtilTest.class.getName()+" now="+now); - } - - @Test - public void smoke() { - - int EXPECTED_AVERAGE = 6; - int EXPECTED_STD_DEVIATION = 3; - - - System.out.println(); - Random r = new Random(now); - int len = 3000; - int[] valArray = new int[len]; - for(int i = 0; i < len; i++) { - valArray[i] = RandomUtil.gaussianAsPositiveInt(r, EXPECTED_AVERAGE, EXPECTED_STD_DEVIATION); - } - double avg = average(valArray); - - assertEquals(EXPECTED_AVERAGE, avg, 0.3); - } - - public double average(int[] va) { - double avg = 0; - for(int i = 0; i < va.length; i++) { - avg = (avg*i+va[i])/(i+1); - } - return avg; - } - -} +/** + * 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.classic.corpusTest; + +import static org.junit.Assert.assertEquals; + +import java.util.Random; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.corpus.RandomUtil; + + +public class RandomUtilTest { + long now = System.currentTimeMillis(); + + @Before + public void setup() { + System.out.println(RandomUtilTest.class.getName()+" now="+now); + } + + @Test + public void smoke() { + + int EXPECTED_AVERAGE = 6; + int EXPECTED_STD_DEVIATION = 3; + + + System.out.println(); + Random r = new Random(now); + int len = 3000; + int[] valArray = new int[len]; + for(int i = 0; i < len; i++) { + valArray[i] = RandomUtil.gaussianAsPositiveInt(r, EXPECTED_AVERAGE, EXPECTED_STD_DEVIATION); + } + double avg = average(valArray); + + assertEquals(EXPECTED_AVERAGE, avg, 0.3); + } + + public double average(int[] va) { + double avg = 0; + for(int i = 0; i < va.length; i++) { + avg = (avg*i+va[i])/(i+1); + } + return avg; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/corpusTest/TextFileUtilTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/corpusTest/TextFileUtilTest.java index 8e8dfacb95074bca2be504eaf1e9db5d131329b7..372062362a17a111314bd13e3f07ad9cdd742ad9 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/corpusTest/TextFileUtilTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/corpusTest/TextFileUtilTest.java @@ -1,45 +1,45 @@ -/** - * 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.classic.corpusTest; - -import static org.junit.Assert.*; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; -import java.util.List; - -import org.junit.Test; - -import ch.qos.logback.classic.corpus.TextFileUtil; - -public class TextFileUtilTest { - - @Test - public void smoke() throws IOException { - String s = "When on board H.M.S. 'Beagle,' as naturalist, I was much struck with\r\n" - + "certain facts in the distribution of the inhabitants of South America,\r\n" - + "and in the geological relations of the present to the past inhabitants\r\n" - + "of that continent."; - - StringReader sr = new StringReader(s); - BufferedReader br = new BufferedReader(sr); - List wordList = TextFileUtil.toWords(br); - assertEquals(38, wordList.size()); - assertEquals("When", wordList.get(0)); - assertEquals("'Beagle,'", wordList.get(4)); - assertEquals("of", wordList.get(17)); - - } -} +/** + * 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.classic.corpusTest; + +import static org.junit.Assert.*; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.List; + +import org.junit.Test; + +import ch.qos.logback.classic.corpus.TextFileUtil; + +public class TextFileUtilTest { + + @Test + public void smoke() throws IOException { + String s = "When on board H.M.S. 'Beagle,' as naturalist, I was much struck with\r\n" + + "certain facts in the distribution of the inhabitants of South America,\r\n" + + "and in the geological relations of the present to the past inhabitants\r\n" + + "of that continent."; + + StringReader sr = new StringReader(s); + BufferedReader br = new BufferedReader(sr); + List wordList = TextFileUtil.toWords(br); + assertEquals(38, wordList.size()); + assertEquals("When", wordList.get(0)); + assertEquals("'Beagle,'", wordList.get(4)); + assertEquals("of", wordList.get(17)); + + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderIntegrationTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderIntegrationTest.java index 8a8d382ac34a382b6ca2dcdcf51c79d92caba343..f60397278177793f8e8602f849cdc94ccd9172c5 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderIntegrationTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderIntegrationTest.java @@ -1,145 +1,145 @@ -/** - * 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.classic.db; - -import static org.junit.Assert.assertEquals; - -import java.net.InetAddress; -import java.util.Random; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.MDC; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.testUtil.Env; -import ch.qos.logback.core.util.StatusPrinter; - -public class DBAppenderIntegrationTest { - - static String LOCAL_HOST_NAME; - static String[] CONFORMING_HOST_LIST = new String[] { "Orion" }; - - int diff = new Random(System.nanoTime()).nextInt(10000); - LoggerContext lc = new LoggerContext(); - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - InetAddress localhostIA = InetAddress.getLocalHost(); - LOCAL_HOST_NAME = localhostIA.getHostName(); - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - } - - @Before - public void setUp() throws Exception { - lc.setName("lc"+diff); - } - - @After - public void tearDown() throws Exception { - // lc will never be used again - lc.stop(); - } - - public void doTest(String configFile) throws JoranException { - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - configurator.doConfigure(configFile); - - Logger logger = lc.getLogger(DBAppenderIntegrationTest.class); - - MDC.put("userid", "user" + diff); - int runLength = 5; - for (int i = 1; i <= runLength; i++) { - logger.debug("This is a debug message. Message number: " + i); - } - logger.error("At last an error.", new Exception("Just testing")); - - // check that there were no errors - StatusPrinter.print(lc); - assertEquals(Status.INFO, lc.getStatusManager().getLevel()); - - } - - static boolean isConformingHostAndJDK16OrHigher() { - if(!Env.isJDK6OrHigher()) { - return false; - } - for (String conformingHost : CONFORMING_HOST_LIST) { - if (conformingHost.equalsIgnoreCase(LOCAL_HOST_NAME)) { - return true; - } - } - return false; - } - - @Test - public void sqlserver() throws Exception { - // perform test only on conforming hosts - if (!isConformingHostAndJDK16OrHigher()) { - return; - } - doTest("src/test/input/integration/db/sqlserver-with-driver.xml"); - } - - @Test - @Ignore - public void oracle10g() throws Exception { - // perform test only on conforming hosts - if (!isConformingHostAndJDK16OrHigher()) { - return; - } - doTest("src/test/input/integration/db/oracle10g-with-driver.xml"); - } - - @Test - @Ignore - public void oracle11g() throws Exception { - // perform test only on conforming hosts - if (!isConformingHostAndJDK16OrHigher()) { - return; - } - doTest("src/test/input/integration/db/oracle11g-with-driver.xml"); - } - - @Test - public void mysql() throws Exception { - // perform test only on conforming hosts - if (!isConformingHostAndJDK16OrHigher()) { - return; - } - doTest("src/test/input/integration/db/mysql-with-driver.xml"); - } - - @Test - public void postgres() throws Exception { - // perform test only on conforming hosts - if (!isConformingHostAndJDK16OrHigher()) { - return; - } - doTest("src/test/input/integration/db/postgresql-with-driver.xml"); - } - -} +/** + * 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.classic.db; + +import static org.junit.Assert.assertEquals; + +import java.net.InetAddress; +import java.util.Random; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.MDC; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.testUtil.Env; +import ch.qos.logback.core.util.StatusPrinter; + +public class DBAppenderIntegrationTest { + + static String LOCAL_HOST_NAME; + static String[] CONFORMING_HOST_LIST = new String[] { "Orion" }; + + int diff = new Random(System.nanoTime()).nextInt(10000); + LoggerContext lc = new LoggerContext(); + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + InetAddress localhostIA = InetAddress.getLocalHost(); + LOCAL_HOST_NAME = localhostIA.getHostName(); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + lc.setName("lc"+diff); + } + + @After + public void tearDown() throws Exception { + // lc will never be used again + lc.stop(); + } + + public void doTest(String configFile) throws JoranException { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + configurator.doConfigure(configFile); + + Logger logger = lc.getLogger(DBAppenderIntegrationTest.class); + + MDC.put("userid", "user" + diff); + int runLength = 5; + for (int i = 1; i <= runLength; i++) { + logger.debug("This is a debug message. Message number: " + i); + } + logger.error("At last an error.", new Exception("Just testing")); + + // check that there were no errors + StatusPrinter.print(lc); + assertEquals(Status.INFO, lc.getStatusManager().getLevel()); + + } + + static boolean isConformingHostAndJDK16OrHigher() { + if(!Env.isJDK6OrHigher()) { + return false; + } + for (String conformingHost : CONFORMING_HOST_LIST) { + if (conformingHost.equalsIgnoreCase(LOCAL_HOST_NAME)) { + return true; + } + } + return false; + } + + @Test + public void sqlserver() throws Exception { + // perform test only on conforming hosts + if (!isConformingHostAndJDK16OrHigher()) { + return; + } + doTest("src/test/input/integration/db/sqlserver-with-driver.xml"); + } + + @Test + @Ignore + public void oracle10g() throws Exception { + // perform test only on conforming hosts + if (!isConformingHostAndJDK16OrHigher()) { + return; + } + doTest("src/test/input/integration/db/oracle10g-with-driver.xml"); + } + + @Test + @Ignore + public void oracle11g() throws Exception { + // perform test only on conforming hosts + if (!isConformingHostAndJDK16OrHigher()) { + return; + } + doTest("src/test/input/integration/db/oracle11g-with-driver.xml"); + } + + @Test + public void mysql() throws Exception { + // perform test only on conforming hosts + if (!isConformingHostAndJDK16OrHigher()) { + return; + } + doTest("src/test/input/integration/db/mysql-with-driver.xml"); + } + + @Test + public void postgres() throws Exception { + // perform test only on conforming hosts + if (!isConformingHostAndJDK16OrHigher()) { + return; + } + doTest("src/test/input/integration/db/postgresql-with-driver.xml"); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderTest.java index c56ee583a9744164021a81c9e444d8b70075e0b2..ef86c44928aff5f2a6645ce1ff76750abb2fd92f 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderTest.java @@ -1,170 +1,170 @@ -/** - * 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.classic.db; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Map; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.core.db.DriverManagerConnectionSource; - -public class DBAppenderTest { - - LoggerContext lc; - Logger logger; - DBAppender appender; - DriverManagerConnectionSource connectionSource; - - DBAppenderTestFixture dbAppenderTestFixture; - - @Before - public void setUp() throws SQLException { - dbAppenderTestFixture = new DBAppenderTestFixture(); - dbAppenderTestFixture.setUp(); - - lc = new LoggerContext(); - lc.setName("default"); - logger = lc.getLogger("root"); - appender = new DBAppender(); - appender.setName("DB"); - appender.setContext(lc); - connectionSource = new DriverManagerConnectionSource(); - connectionSource.setContext(lc); - connectionSource.setDriverClass(DBAppenderTestFixture.HSQLDB_DRIVER_CLASS); - connectionSource.setUrl(dbAppenderTestFixture.url); - connectionSource.setUser(dbAppenderTestFixture.user); - connectionSource.setPassword(dbAppenderTestFixture.password); - connectionSource.start(); - appender.setConnectionSource(connectionSource); - appender.start(); - } - - @After - public void tearDown() throws SQLException { - logger = null; - lc = null; - appender = null; - connectionSource = null; - dbAppenderTestFixture.tearDown(); - } - - @Test - public void testAppendLoggingEvent() throws SQLException { - ILoggingEvent event = createLoggingEvent(); - - appender.append(event); - //StatusPrinter.print(lc.getStatusManager()); - - Statement stmt = connectionSource.getConnection().createStatement(); - ResultSet rs = null; - rs = stmt.executeQuery("SELECT * FROM logging_event"); - if (rs.next()) { - assertEquals(event.getTimeStamp(), rs.getLong(1)); - assertEquals(event.getFormattedMessage(), rs.getString(2)); - assertEquals(event.getLoggerName(), rs.getString(3)); - assertEquals(event.getLevel().toString(), rs.getString(4)); - assertEquals(event.getThreadName(), rs.getString(5)); - assertEquals(DBHelper.computeReferenceMask(event), rs.getShort(6)); - StackTraceElement callerData = event.getCallerData()[0]; - assertEquals(callerData.getFileName(), rs.getString(7)); - assertEquals(callerData.getClassName(), rs.getString(8)); - assertEquals(callerData.getMethodName(), rs.getString(9)); - } else { - fail("No row was inserted in the database"); - } - - rs.close(); - stmt.close(); - } - - @Test - public void testAppendThrowable() throws SQLException { - ILoggingEvent event = createLoggingEvent(); - - appender.append(event); - - Statement stmt = connectionSource.getConnection().createStatement(); - ResultSet rs = null; - rs = stmt.executeQuery("SELECT * FROM logging_event_exception where event_id = 0"); - int i = 0; - while (rs.next()) { - assertEquals(event.getThrowableProxy().getStackTraceElementProxyArray()[i].toString(), rs.getString(3)); - i++; - } - - rs.close(); - stmt.close(); - } - - @Test - public void testContextInfo() throws SQLException { - ILoggingEvent event = createLoggingEvent(); - lc.putProperty("testKey1", "testValue1"); - - appender.append(event); - - Statement stmt = connectionSource.getConnection().createStatement(); - ResultSet rs = null; - rs = stmt.executeQuery("SELECT * FROM logging_event_property where event_id = 0"); - Map map = appender.mergePropertyMaps(event); - while (rs.next()) { - String key = rs.getString(2); - assertEquals(map.get(key), rs.getString(3)); - //System.out.println("value: " + map.get(key)); - } - - rs.close(); - stmt.close(); - } - - @Test - public void testAppendMultipleEvents() throws SQLException { - for (int i = 0; i < 10; i++) { - ILoggingEvent event = createLoggingEvent(); - appender.append(event); - } - - Statement stmt = connectionSource.getConnection().createStatement(); - ResultSet rs = null; - rs = stmt.executeQuery("SELECT * FROM logging_event"); - int count = 0; - while (rs.next()) { - count++; - } - assertEquals(10, count); - - rs.close(); - stmt.close(); - } - - - private ILoggingEvent createLoggingEvent() { - ILoggingEvent le = new LoggingEvent(this.getClass().getName(), logger, - Level.DEBUG, "test message", new Exception("test Ex"), null); - return le; - } -} +/** + * 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.classic.db; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Map; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.db.DriverManagerConnectionSource; + +public class DBAppenderTest { + + LoggerContext lc; + Logger logger; + DBAppender appender; + DriverManagerConnectionSource connectionSource; + + DBAppenderTestFixture dbAppenderTestFixture; + + @Before + public void setUp() throws SQLException { + dbAppenderTestFixture = new DBAppenderTestFixture(); + dbAppenderTestFixture.setUp(); + + lc = new LoggerContext(); + lc.setName("default"); + logger = lc.getLogger("root"); + appender = new DBAppender(); + appender.setName("DB"); + appender.setContext(lc); + connectionSource = new DriverManagerConnectionSource(); + connectionSource.setContext(lc); + connectionSource.setDriverClass(DBAppenderTestFixture.HSQLDB_DRIVER_CLASS); + connectionSource.setUrl(dbAppenderTestFixture.url); + connectionSource.setUser(dbAppenderTestFixture.user); + connectionSource.setPassword(dbAppenderTestFixture.password); + connectionSource.start(); + appender.setConnectionSource(connectionSource); + appender.start(); + } + + @After + public void tearDown() throws SQLException { + logger = null; + lc = null; + appender = null; + connectionSource = null; + dbAppenderTestFixture.tearDown(); + } + + @Test + public void testAppendLoggingEvent() throws SQLException { + ILoggingEvent event = createLoggingEvent(); + + appender.append(event); + //StatusPrinter.print(lc.getStatusManager()); + + Statement stmt = connectionSource.getConnection().createStatement(); + ResultSet rs = null; + rs = stmt.executeQuery("SELECT * FROM logging_event"); + if (rs.next()) { + assertEquals(event.getTimeStamp(), rs.getLong(1)); + assertEquals(event.getFormattedMessage(), rs.getString(2)); + assertEquals(event.getLoggerName(), rs.getString(3)); + assertEquals(event.getLevel().toString(), rs.getString(4)); + assertEquals(event.getThreadName(), rs.getString(5)); + assertEquals(DBHelper.computeReferenceMask(event), rs.getShort(6)); + StackTraceElement callerData = event.getCallerData()[0]; + assertEquals(callerData.getFileName(), rs.getString(7)); + assertEquals(callerData.getClassName(), rs.getString(8)); + assertEquals(callerData.getMethodName(), rs.getString(9)); + } else { + fail("No row was inserted in the database"); + } + + rs.close(); + stmt.close(); + } + + @Test + public void testAppendThrowable() throws SQLException { + ILoggingEvent event = createLoggingEvent(); + + appender.append(event); + + Statement stmt = connectionSource.getConnection().createStatement(); + ResultSet rs = null; + rs = stmt.executeQuery("SELECT * FROM logging_event_exception where event_id = 0"); + int i = 0; + while (rs.next()) { + assertEquals(event.getThrowableProxy().getStackTraceElementProxyArray()[i].toString(), rs.getString(3)); + i++; + } + + rs.close(); + stmt.close(); + } + + @Test + public void testContextInfo() throws SQLException { + ILoggingEvent event = createLoggingEvent(); + lc.putProperty("testKey1", "testValue1"); + + appender.append(event); + + Statement stmt = connectionSource.getConnection().createStatement(); + ResultSet rs = null; + rs = stmt.executeQuery("SELECT * FROM logging_event_property where event_id = 0"); + Map map = appender.mergePropertyMaps(event); + while (rs.next()) { + String key = rs.getString(2); + assertEquals(map.get(key), rs.getString(3)); + //System.out.println("value: " + map.get(key)); + } + + rs.close(); + stmt.close(); + } + + @Test + public void testAppendMultipleEvents() throws SQLException { + for (int i = 0; i < 10; i++) { + ILoggingEvent event = createLoggingEvent(); + appender.append(event); + } + + Statement stmt = connectionSource.getConnection().createStatement(); + ResultSet rs = null; + rs = stmt.executeQuery("SELECT * FROM logging_event"); + int count = 0; + while (rs.next()) { + count++; + } + assertEquals(10, count); + + rs.close(); + stmt.close(); + } + + + private ILoggingEvent createLoggingEvent() { + ILoggingEvent le = new LoggingEvent(this.getClass().getName(), logger, + Level.DEBUG, "test message", new Exception("test Ex"), null); + return le; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderTestFixture.java b/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderTestFixture.java index 455f067606ac8afc3f845a72fe8f74d36179f7f5..46cfd2b94d72d4e557cbe4e347c4e677f1283d42 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderTestFixture.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderTestFixture.java @@ -1,173 +1,173 @@ -/** - * 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.classic.db; - -import static org.junit.Assert.assertNotNull; - -import java.io.PrintWriter; -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Properties; - -import org.hsqldb.Server; -import org.hsqldb.ServerConstants; -import org.hsqldb.jdbcDriver; - -public class DBAppenderTestFixture { - - public static final String HSQLDB_DRIVER_CLASS = "org.hsqldb.jdbcDriver"; - // String serverProps; - String url = null; - String user = "sa"; - String password = ""; - Server server; - - // boolean isNetwork = true; - HsqlMode mode = HsqlMode.MEM; - - public DBAppenderTestFixture() { - } - - public void setUp() throws SQLException { - - switch (mode) { - case NET: - url = "jdbc:hsqldb:hsql://localhost:4808/test"; - break; - case MEM: - url = "jdbc:hsqldb:mem:test;sql.enforce_strict_size=true"; - server = new Server(); - server.setDatabaseName(0, "test"); - server.setDatabasePath(0, url); - server.setLogWriter(new PrintWriter(System.out)); - server.setErrWriter(new PrintWriter(System.out)); - server.setTrace(false); - server.setSilent(false); - server.start(); - - break; - case FILE: - url = "jdbc:hsqldb:file:test;sql.enforce_strict_size=true"; - break; - - } - - // try { - // Class.forName(DRIVER_CLASS); - // } catch (Exception e) { - // e.printStackTrace(); - // System.out.println(this + ".setUp() error: " + e.getMessage()); - // } - // Thread.yield(); - System.out.println(server.getState()); - - int waitCount = 0; - while (server.getState() != ServerConstants.SERVER_STATE_ONLINE - && waitCount < 5) { - try { - waitCount++; - Thread.sleep(1); - } catch (InterruptedException e) { - } - } - createTables(); - } - - public void tearDown() throws SQLException { - dropTables(); - - if (mode == HsqlMode.MEM) { - server.stop(); - server = null; - } - } - - Connection newConnection() throws SQLException { - jdbcDriver driver = new jdbcDriver(); - Properties props = new Properties(); - props.setProperty("user", user); - props.setProperty("password", password); - return driver.connect(url, props); - - // return DriverManager.getConnection(url, user, password); - } - - private void createTables() throws SQLException { - Connection conn = newConnection(); - assertNotNull(conn); - StringBuffer buf = new StringBuffer(); - buf.append("CREATE TABLE logging_event ("); - buf.append("timestmp BIGINT NOT NULL,"); - buf.append("formatted_message LONGVARCHAR NOT NULL,"); - buf.append("logger_name VARCHAR(256) NOT NULL,"); - buf.append("level_string VARCHAR(256) NOT NULL,"); - buf.append("thread_name VARCHAR(256),"); - buf.append("reference_flag SMALLINT,"); - buf.append("caller_filename VARCHAR(256), "); - buf.append("caller_class VARCHAR(256), "); - buf.append("caller_method VARCHAR(256), "); - buf.append("caller_line CHAR(4), "); - buf.append("event_id INT NOT NULL IDENTITY);"); - query(conn, buf.toString()); - - buf = new StringBuffer(); - buf.append("CREATE TABLE logging_event_property ("); - buf.append("event_id INT NOT NULL,"); - buf.append("mapped_key VARCHAR(254) NOT NULL,"); - buf.append("mapped_value LONGVARCHAR,"); - buf.append("PRIMARY KEY(event_id, mapped_key),"); - buf.append("FOREIGN KEY (event_id) REFERENCES logging_event(event_id));"); - query(conn, buf.toString()); - - buf = new StringBuffer(); - buf.append("CREATE TABLE logging_event_exception ("); - buf.append("event_id INT NOT NULL,"); - buf.append("i SMALLINT NOT NULL,"); - buf.append("trace_line VARCHAR(256) NOT NULL,"); - buf.append("PRIMARY KEY(event_id, i),"); - buf.append("FOREIGN KEY (event_id) REFERENCES logging_event(event_id));"); - query(conn, buf.toString()); - } - - private void dropTables() throws SQLException { - Connection conn = newConnection(); - StringBuffer buf = new StringBuffer(); - buf.append("DROP TABLE logging_event_exception IF EXISTS;"); - query(conn, buf.toString()); - - buf = new StringBuffer(); - buf.append("DROP TABLE logging_event_property IF EXISTS;"); - query(conn, buf.toString()); - - buf = new StringBuffer(); - buf.append("DROP TABLE logging_event IF EXISTS;"); - query(conn, buf.toString()); - } - - private void query(Connection conn, String expression) throws SQLException { - - Statement st = null; - st = conn.createStatement(); - int i = st.executeUpdate(expression); - if (i == -1) { - System.out.println("db error : " + expression); - } - st.close(); - } - - public enum HsqlMode { - MEM, FILE, NET; - } -} +/** + * 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.classic.db; + +import static org.junit.Assert.assertNotNull; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +import org.hsqldb.Server; +import org.hsqldb.ServerConstants; +import org.hsqldb.jdbcDriver; + +public class DBAppenderTestFixture { + + public static final String HSQLDB_DRIVER_CLASS = "org.hsqldb.jdbcDriver"; + // String serverProps; + String url = null; + String user = "sa"; + String password = ""; + Server server; + + // boolean isNetwork = true; + HsqlMode mode = HsqlMode.MEM; + + public DBAppenderTestFixture() { + } + + public void setUp() throws SQLException { + + switch (mode) { + case NET: + url = "jdbc:hsqldb:hsql://localhost:4808/test"; + break; + case MEM: + url = "jdbc:hsqldb:mem:test;sql.enforce_strict_size=true"; + server = new Server(); + server.setDatabaseName(0, "test"); + server.setDatabasePath(0, url); + server.setLogWriter(new PrintWriter(System.out)); + server.setErrWriter(new PrintWriter(System.out)); + server.setTrace(false); + server.setSilent(false); + server.start(); + + break; + case FILE: + url = "jdbc:hsqldb:file:test;sql.enforce_strict_size=true"; + break; + + } + + // try { + // Class.forName(DRIVER_CLASS); + // } catch (Exception e) { + // e.printStackTrace(); + // System.out.println(this + ".setUp() error: " + e.getMessage()); + // } + // Thread.yield(); + System.out.println(server.getState()); + + int waitCount = 0; + while (server.getState() != ServerConstants.SERVER_STATE_ONLINE + && waitCount < 5) { + try { + waitCount++; + Thread.sleep(1); + } catch (InterruptedException e) { + } + } + createTables(); + } + + public void tearDown() throws SQLException { + dropTables(); + + if (mode == HsqlMode.MEM) { + server.stop(); + server = null; + } + } + + Connection newConnection() throws SQLException { + jdbcDriver driver = new jdbcDriver(); + Properties props = new Properties(); + props.setProperty("user", user); + props.setProperty("password", password); + return driver.connect(url, props); + + // return DriverManager.getConnection(url, user, password); + } + + private void createTables() throws SQLException { + Connection conn = newConnection(); + assertNotNull(conn); + StringBuffer buf = new StringBuffer(); + buf.append("CREATE TABLE logging_event ("); + buf.append("timestmp BIGINT NOT NULL,"); + buf.append("formatted_message LONGVARCHAR NOT NULL,"); + buf.append("logger_name VARCHAR(256) NOT NULL,"); + buf.append("level_string VARCHAR(256) NOT NULL,"); + buf.append("thread_name VARCHAR(256),"); + buf.append("reference_flag SMALLINT,"); + buf.append("caller_filename VARCHAR(256), "); + buf.append("caller_class VARCHAR(256), "); + buf.append("caller_method VARCHAR(256), "); + buf.append("caller_line CHAR(4), "); + buf.append("event_id INT NOT NULL IDENTITY);"); + query(conn, buf.toString()); + + buf = new StringBuffer(); + buf.append("CREATE TABLE logging_event_property ("); + buf.append("event_id INT NOT NULL,"); + buf.append("mapped_key VARCHAR(254) NOT NULL,"); + buf.append("mapped_value LONGVARCHAR,"); + buf.append("PRIMARY KEY(event_id, mapped_key),"); + buf.append("FOREIGN KEY (event_id) REFERENCES logging_event(event_id));"); + query(conn, buf.toString()); + + buf = new StringBuffer(); + buf.append("CREATE TABLE logging_event_exception ("); + buf.append("event_id INT NOT NULL,"); + buf.append("i SMALLINT NOT NULL,"); + buf.append("trace_line VARCHAR(256) NOT NULL,"); + buf.append("PRIMARY KEY(event_id, i),"); + buf.append("FOREIGN KEY (event_id) REFERENCES logging_event(event_id));"); + query(conn, buf.toString()); + } + + private void dropTables() throws SQLException { + Connection conn = newConnection(); + StringBuffer buf = new StringBuffer(); + buf.append("DROP TABLE logging_event_exception IF EXISTS;"); + query(conn, buf.toString()); + + buf = new StringBuffer(); + buf.append("DROP TABLE logging_event_property IF EXISTS;"); + query(conn, buf.toString()); + + buf = new StringBuffer(); + buf.append("DROP TABLE logging_event IF EXISTS;"); + query(conn, buf.toString()); + } + + private void query(Connection conn, String expression) throws SQLException { + + Statement st = null; + st = conn.createStatement(); + int i = st.executeUpdate(expression); + if (i == -1) { + System.out.println("db error : " + expression); + } + st.close(); + } + + public enum HsqlMode { + MEM, FILE, NET; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/db/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/db/PackageTest.java index 7180d6b7f122c9f11c77bd3481f1d19778426cbc..6fdc4d3ae97c5e46c64353bfcbef67e3c6d97924 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/db/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/db/PackageTest.java @@ -1,23 +1,23 @@ -/** - * 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.classic.db; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses( {DBAppenderTest.class}) -public class PackageTest { +/** + * 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.classic.db; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses( {DBAppenderTest.class}) +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java index e75797e311a99014305b3a4f161f9ff3b18adaaa..e7b9f6af9f356994e7b27c0d74e736f5e284000d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java @@ -1,256 +1,256 @@ -/** - * 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.classic.html; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.util.List; - -import org.dom4j.Document; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.xml.sax.EntityResolver; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.ClassicTestConstants; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.spi.DummyThrowableProxy; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.classic.spi.StackTraceElementProxy; -import ch.qos.logback.classic.spi.ThrowableProxy; -import ch.qos.logback.classic.util.TeztConstants; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.read.ListAppender; -import ch.qos.logback.core.testUtil.StringListAppender; -import ch.qos.logback.core.util.StatusPrinter; - -public class HTMLLayoutTest { - - LoggerContext lc; - Logger root; - HTMLLayout layout; - - @Before - public void setUp() throws Exception { - lc = new LoggerContext(); - lc.setName("default"); - - ListAppender appender = new ListAppender(); - appender.setContext(lc); - layout = new HTMLLayout(); - layout.setThrowableRenderer(new DefaultThrowableRenderer()); - layout.setContext(lc); - layout.setPattern("%level%thread%msg"); - layout.start(); - appender.setLayout(layout); - root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - root.addAppender(appender); - appender.start(); - } - - @After - public void tearDown() throws Exception { - lc = null; - layout = null; - } - - @Test - public void testHeader() throws Exception { - String header = layout.getFileHeader(); - // System.out.println(header); - - Document doc = parseOutput(header + ""); - Element rootElement = doc.getRootElement(); - assertNotNull(rootElement.element("body")); - } - - @SuppressWarnings("unchecked") - @Test - public void testPresentationHeader() throws Exception { - String header = layout.getFileHeader(); - String presentationHeader = layout.getPresentationHeader(); - header = header + presentationHeader; - // System.out.println(header); - - Document doc = parseOutput(header + ""); - Element rootElement = doc.getRootElement(); - Element bodyElement = rootElement.element("body"); - Element tableElement = bodyElement.element("table"); - Element trElement = tableElement.element("tr"); - List elementList = trElement.elements(); - assertEquals("Level", elementList.get(0).getText()); - assertEquals("Thread", elementList.get(1).getText()); - assertEquals("Message", elementList.get(2).getText()); - } - - @Test - public void testAppendThrowable() throws Exception { - StringBuilder buf = new StringBuilder(); - DummyThrowableProxy tp = new DummyThrowableProxy(); - tp.setClassName("test1"); - tp.setMessage("msg1"); - - StackTraceElement ste1 = new StackTraceElement("c1", "m1", "f1", 1); - StackTraceElement ste2 = new StackTraceElement("c2", "m2", "f2", 2); - - StackTraceElementProxy[] stepArray = { new StackTraceElementProxy(ste1), - new StackTraceElementProxy(ste2) }; - tp.setStackTraceElementProxyArray(stepArray); - DefaultThrowableRenderer renderer = (DefaultThrowableRenderer) layout - .getThrowableRenderer(); - - renderer.render(buf, tp); - System.out.println(buf.toString()); - String[] result = buf.toString().split(CoreConstants.LINE_SEPARATOR); - System.out.println(result[0]); - assertEquals("test1: msg1", result[0]); - assertEquals(DefaultThrowableRenderer.TRACE_PREFIX + "at c1.m1(f1:1)", result[1]); - } - - @Test - public void testDoLayout() throws Exception { - ILoggingEvent le = createLoggingEvent(); - - String result = layout.getFileHeader(); - result += layout.getPresentationHeader(); - result += layout.doLayout(le); - result += layout.getPresentationFooter(); - result += layout.getFileFooter(); - - Document doc = parseOutput(result); - Element rootElement = doc.getRootElement(); - rootElement.toString(); - - // the rest of this test is very dependent of the output generated - // by HTMLLayout. Given that the XML parser already verifies - // that the result conforms to xhtml-strict, we may want to - // skip the assertions below. However, the assertions below are another - // *independent* way to check the output format. - - // head, body - assertEquals(2, rootElement.elements().size()); - Element bodyElement = (Element) rootElement.elements().get(1); - Element tableElement = (Element) bodyElement.elements().get(3); - assertEquals("table", tableElement.getName()); - Element trElement = (Element) tableElement.elements().get(1); - { - Element tdElement = (Element) trElement.elements().get(0); - assertEquals("DEBUG", tdElement.getText()); - } - { - Element tdElement = (Element) trElement.elements().get(1); - String regex = ClassicTestConstants.NAKED_MAIN_REGEX; - assertTrue(tdElement.getText().toString().matches(regex)); - } - { - Element tdElement = (Element) trElement.elements().get(2); - assertEquals("test message", tdElement.getText()); - } - } - - @SuppressWarnings("unchecked") - @Test - public void layoutWithException() throws Exception { - layout.setPattern("%level %thread %msg %ex"); - LoggingEvent le = createLoggingEvent(); - le.setThrowableProxy(new ThrowableProxy(new Exception("test Exception"))); - String result = layout.doLayout(le); - - String stringToParse = layout.getFileHeader(); - stringToParse = stringToParse + layout.getPresentationHeader(); - stringToParse += result; - stringToParse += ""; - - // System.out.println(stringToParse); - - Document doc = parseOutput(stringToParse); - Element rootElement = doc.getRootElement(); - Element bodyElement = rootElement.element("body"); - Element tableElement = bodyElement.element("table"); - List trElementList = tableElement.elements(); - Element exceptionRowElement = trElementList.get(2); - Element exceptionElement = exceptionRowElement.element("td"); - - assertEquals(3, tableElement.elements().size()); - assertTrue(exceptionElement.getText().contains( - "java.lang.Exception: test Exception")); - } - - @Test - @Ignore - public void rawLimit() throws Exception { - StringBuilder sb = new StringBuilder(); - String header = layout.getFileHeader(); - assertTrue(header - .startsWith("")); - sb.append(header); - sb.append(layout.getPresentationHeader()); - for (int i = 0; i < CoreConstants.TABLE_ROW_LIMIT * 3; i++) { - sb.append(layout.doLayout(new LoggingEvent(this.getClass().getName(), - root, Level.DEBUG, "test message" + i, null, null))); - } - sb.append(layout.getPresentationFooter()); - sb.append(layout.getFileFooter()); - // check that the output adheres to xhtml-strict.dtd - parseOutput(sb.toString()); - } - - private LoggingEvent createLoggingEvent() { - LoggingEvent le = new LoggingEvent(this.getClass().getName(), root, - Level.DEBUG, "test message", null, null); - return le; - } - - Document parseOutput(String output) throws Exception { - EntityResolver resolver = new XHTMLEntityResolver(); - SAXReader reader = new SAXReader(); - reader.setValidation(true); - reader.setEntityResolver(resolver); - return reader.read(new ByteArrayInputStream(output.getBytes())); - } - - void configure(String file) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(lc); - jc.doConfigure(file); - } - - @Test - public void testConversionRuleSupportInHtmlLayout() throws JoranException { - configure(TeztConstants.TEST_DIR_PREFIX - + "input/joran/conversionRule/htmlLayout0.xml"); - - root.getAppender("LIST"); - String msg = "Simon says"; - root.debug(msg); - StringListAppender sla = (StringListAppender) root - .getAppender("LIST"); - assertNotNull(sla); - StatusPrinter.print(lc); - assertEquals(1, sla.strList.size()); - assertFalse(sla.strList.get(0).contains("PARSER_ERROR")); - } -} +/** + * 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.classic.html; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.util.List; + +import org.dom4j.Document; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.xml.sax.EntityResolver; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.ClassicTestConstants; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.spi.DummyThrowableProxy; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.classic.spi.ThrowableProxy; +import ch.qos.logback.classic.util.TeztConstants; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.read.ListAppender; +import ch.qos.logback.core.testUtil.StringListAppender; +import ch.qos.logback.core.util.StatusPrinter; + +public class HTMLLayoutTest { + + LoggerContext lc; + Logger root; + HTMLLayout layout; + + @Before + public void setUp() throws Exception { + lc = new LoggerContext(); + lc.setName("default"); + + ListAppender appender = new ListAppender(); + appender.setContext(lc); + layout = new HTMLLayout(); + layout.setThrowableRenderer(new DefaultThrowableRenderer()); + layout.setContext(lc); + layout.setPattern("%level%thread%msg"); + layout.start(); + appender.setLayout(layout); + root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + root.addAppender(appender); + appender.start(); + } + + @After + public void tearDown() throws Exception { + lc = null; + layout = null; + } + + @Test + public void testHeader() throws Exception { + String header = layout.getFileHeader(); + // System.out.println(header); + + Document doc = parseOutput(header + ""); + Element rootElement = doc.getRootElement(); + assertNotNull(rootElement.element("body")); + } + + @SuppressWarnings("unchecked") + @Test + public void testPresentationHeader() throws Exception { + String header = layout.getFileHeader(); + String presentationHeader = layout.getPresentationHeader(); + header = header + presentationHeader; + // System.out.println(header); + + Document doc = parseOutput(header + ""); + Element rootElement = doc.getRootElement(); + Element bodyElement = rootElement.element("body"); + Element tableElement = bodyElement.element("table"); + Element trElement = tableElement.element("tr"); + List elementList = trElement.elements(); + assertEquals("Level", elementList.get(0).getText()); + assertEquals("Thread", elementList.get(1).getText()); + assertEquals("Message", elementList.get(2).getText()); + } + + @Test + public void testAppendThrowable() throws Exception { + StringBuilder buf = new StringBuilder(); + DummyThrowableProxy tp = new DummyThrowableProxy(); + tp.setClassName("test1"); + tp.setMessage("msg1"); + + StackTraceElement ste1 = new StackTraceElement("c1", "m1", "f1", 1); + StackTraceElement ste2 = new StackTraceElement("c2", "m2", "f2", 2); + + StackTraceElementProxy[] stepArray = { new StackTraceElementProxy(ste1), + new StackTraceElementProxy(ste2) }; + tp.setStackTraceElementProxyArray(stepArray); + DefaultThrowableRenderer renderer = (DefaultThrowableRenderer) layout + .getThrowableRenderer(); + + renderer.render(buf, tp); + System.out.println(buf.toString()); + String[] result = buf.toString().split(CoreConstants.LINE_SEPARATOR); + System.out.println(result[0]); + assertEquals("test1: msg1", result[0]); + assertEquals(DefaultThrowableRenderer.TRACE_PREFIX + "at c1.m1(f1:1)", result[1]); + } + + @Test + public void testDoLayout() throws Exception { + ILoggingEvent le = createLoggingEvent(); + + String result = layout.getFileHeader(); + result += layout.getPresentationHeader(); + result += layout.doLayout(le); + result += layout.getPresentationFooter(); + result += layout.getFileFooter(); + + Document doc = parseOutput(result); + Element rootElement = doc.getRootElement(); + rootElement.toString(); + + // the rest of this test is very dependent of the output generated + // by HTMLLayout. Given that the XML parser already verifies + // that the result conforms to xhtml-strict, we may want to + // skip the assertions below. However, the assertions below are another + // *independent* way to check the output format. + + // head, body + assertEquals(2, rootElement.elements().size()); + Element bodyElement = (Element) rootElement.elements().get(1); + Element tableElement = (Element) bodyElement.elements().get(3); + assertEquals("table", tableElement.getName()); + Element trElement = (Element) tableElement.elements().get(1); + { + Element tdElement = (Element) trElement.elements().get(0); + assertEquals("DEBUG", tdElement.getText()); + } + { + Element tdElement = (Element) trElement.elements().get(1); + String regex = ClassicTestConstants.NAKED_MAIN_REGEX; + assertTrue(tdElement.getText().toString().matches(regex)); + } + { + Element tdElement = (Element) trElement.elements().get(2); + assertEquals("test message", tdElement.getText()); + } + } + + @SuppressWarnings("unchecked") + @Test + public void layoutWithException() throws Exception { + layout.setPattern("%level %thread %msg %ex"); + LoggingEvent le = createLoggingEvent(); + le.setThrowableProxy(new ThrowableProxy(new Exception("test Exception"))); + String result = layout.doLayout(le); + + String stringToParse = layout.getFileHeader(); + stringToParse = stringToParse + layout.getPresentationHeader(); + stringToParse += result; + stringToParse += ""; + + // System.out.println(stringToParse); + + Document doc = parseOutput(stringToParse); + Element rootElement = doc.getRootElement(); + Element bodyElement = rootElement.element("body"); + Element tableElement = bodyElement.element("table"); + List trElementList = tableElement.elements(); + Element exceptionRowElement = trElementList.get(2); + Element exceptionElement = exceptionRowElement.element("td"); + + assertEquals(3, tableElement.elements().size()); + assertTrue(exceptionElement.getText().contains( + "java.lang.Exception: test Exception")); + } + + @Test + @Ignore + public void rawLimit() throws Exception { + StringBuilder sb = new StringBuilder(); + String header = layout.getFileHeader(); + assertTrue(header + .startsWith("")); + sb.append(header); + sb.append(layout.getPresentationHeader()); + for (int i = 0; i < CoreConstants.TABLE_ROW_LIMIT * 3; i++) { + sb.append(layout.doLayout(new LoggingEvent(this.getClass().getName(), + root, Level.DEBUG, "test message" + i, null, null))); + } + sb.append(layout.getPresentationFooter()); + sb.append(layout.getFileFooter()); + // check that the output adheres to xhtml-strict.dtd + parseOutput(sb.toString()); + } + + private LoggingEvent createLoggingEvent() { + LoggingEvent le = new LoggingEvent(this.getClass().getName(), root, + Level.DEBUG, "test message", null, null); + return le; + } + + Document parseOutput(String output) throws Exception { + EntityResolver resolver = new XHTMLEntityResolver(); + SAXReader reader = new SAXReader(); + reader.setValidation(true); + reader.setEntityResolver(resolver); + return reader.read(new ByteArrayInputStream(output.getBytes())); + } + + void configure(String file) throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(lc); + jc.doConfigure(file); + } + + @Test + public void testConversionRuleSupportInHtmlLayout() throws JoranException { + configure(TeztConstants.TEST_DIR_PREFIX + + "input/joran/conversionRule/htmlLayout0.xml"); + + root.getAppender("LIST"); + String msg = "Simon says"; + root.debug(msg); + StringListAppender sla = (StringListAppender) root + .getAppender("LIST"); + assertNotNull(sla); + StatusPrinter.print(lc); + assertEquals(1, sla.strList.size()); + assertFalse(sla.strList.get(0).contains("PARSER_ERROR")); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/html/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/html/PackageTest.java index 3378527a06dcd89b485caaac0fdb1b097d72cb27..153e8190a279f0472c2e414bcc93fd06df5d561d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/html/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/html/PackageTest.java @@ -1,23 +1,23 @@ -/** - * 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.classic.html; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses(HTMLLayoutTest.class) -public class PackageTest { +/** + * 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.classic.html; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses(HTMLLayoutTest.class) +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/html/XHTMLEntityResolver.java b/logback-classic/src/test/java/ch/qos/logback/classic/html/XHTMLEntityResolver.java index 3f9c7dc0ca787e8f16fc33d39ce28a326fc40eab..55d6a7655232e1fd0fa8cbfcc2956f706789f5f8 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/html/XHTMLEntityResolver.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/html/XHTMLEntityResolver.java @@ -1,56 +1,56 @@ -/** - * 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.classic.html; - -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -import org.xml.sax.EntityResolver; -import org.xml.sax.InputSource; - -public class XHTMLEntityResolver implements EntityResolver { - - // key: public id, value: relative path to DTD file - static Map entityMap = new HashMap(); - - static { - entityMap.put("-//W3C//DTD XHTML 1.0 Strict//EN", - "/dtd/xhtml1-strict.dtd"); - entityMap.put("-//W3C//ENTITIES Latin 1 for XHTML//EN", - "/dtd/xhtml-lat1.ent"); - entityMap.put("-//W3C//ENTITIES Symbols for XHTML//EN", - "/dtd/xhtml-symbol.ent"); - entityMap.put("-//W3C//ENTITIES Special for XHTML//EN", - "/dtd/xhtml-special.ent"); - } - - public InputSource resolveEntity(String publicId, String systemId) { - //System.out.println(publicId); - final String relativePath = (String)entityMap.get(publicId); - - if (relativePath != null) { - Class clazz = getClass(); - InputStream in = - clazz.getResourceAsStream(relativePath); - if (in == null) { - return null; - } else { - return new InputSource(in); - } - } else { - return null; - } - } -} +/** + * 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.classic.html; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; + +public class XHTMLEntityResolver implements EntityResolver { + + // key: public id, value: relative path to DTD file + static Map entityMap = new HashMap(); + + static { + entityMap.put("-//W3C//DTD XHTML 1.0 Strict//EN", + "/dtd/xhtml1-strict.dtd"); + entityMap.put("-//W3C//ENTITIES Latin 1 for XHTML//EN", + "/dtd/xhtml-lat1.ent"); + entityMap.put("-//W3C//ENTITIES Symbols for XHTML//EN", + "/dtd/xhtml-symbol.ent"); + entityMap.put("-//W3C//ENTITIES Special for XHTML//EN", + "/dtd/xhtml-special.ent"); + } + + public InputSource resolveEntity(String publicId, String systemId) { + //System.out.println(publicId); + final String relativePath = (String)entityMap.get(publicId); + + if (relativePath != null) { + Class clazz = getClass(); + InputStream in = + clazz.getResourceAsStream(relativePath); + if (in == null) { + return null; + } else { + return new InputSource(in); + } + } else { + return null; + } + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/LBCORE63.java b/logback-classic/src/test/java/ch/qos/logback/classic/issue/LBCORE63.java index 23073deeeb7ec668743623b20c0fe2c9ca3f75d5..d4bdc6a66498a7a3d894ea64bc6a874c7622577a 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/LBCORE63.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/issue/LBCORE63.java @@ -1,100 +1,100 @@ -/** - * 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.classic.issue; - -import java.util.Date; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.util.StatusPrinter; - -public class LBCORE63 extends Thread { - private final static String LOGGER_CONFIGURATION_FILE = "./src/test/input/issue/lbcore63.xml"; - private final Logger logger = LoggerFactory.getLogger(LBCORE63.class); - - private final long start; - - public LBCORE63() throws JoranException { - start = new Date().getTime(); - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - JoranConfigurator configurator = new JoranConfigurator(); - lc.reset(); - configurator.setContext(lc); - configurator.doConfigure(LOGGER_CONFIGURATION_FILE); - StatusPrinter.printInCaseOfErrorsOrWarnings(lc); - } - - public void start() { - ScheduledThreadPoolExecutor ex1 = new ScheduledThreadPoolExecutor(1); - ScheduledThreadPoolExecutor ex2 = new ScheduledThreadPoolExecutor(1); - ScheduledThreadPoolExecutor ex3 = new ScheduledThreadPoolExecutor(1); - ScheduledThreadPoolExecutor ex4 = new ScheduledThreadPoolExecutor(1); - ScheduledThreadPoolExecutor ex5 = new ScheduledThreadPoolExecutor(1); - ex1.scheduleAtFixedRate(new Task("EX1"), 10, 10, TimeUnit.MICROSECONDS); - ex2.scheduleAtFixedRate(new Task("EX2"), 10, 10, TimeUnit.MICROSECONDS); - ex3.scheduleAtFixedRate(new Task("EX3"), 10, 10, TimeUnit.MICROSECONDS); - ex4.scheduleAtFixedRate(new Task("EX4"), 10, 10, TimeUnit.MICROSECONDS); - ex5.scheduleAtFixedRate(new Task("EX5"), 10, 10, TimeUnit.MICROSECONDS); - - super.start(); - } - - public void run() { - try { - while (true) { - logger.debug("[MAIN] {}", new Date().getTime() - start); - Thread.sleep(10); - } - } catch (InterruptedException e) { - logger.info("[MAIN]: Interrupted: {}", e.getMessage()); - } - } - - public static void main(String[] args) { - try { - LBCORE63 main = new LBCORE63(); - main.start(); - } catch (JoranException e) { - System.out.println("Failed to load application: " + e.getMessage()); - } - } - - class Task implements Runnable { - private final Logger logger = LoggerFactory.getLogger(Task.class); - //private final Logger logger_main = LoggerFactory.getLogger(LBCORE63.class); - final String name; - private final long start; - - int counter = 0; - public long diff; - - public Task(final String name) { - this.name = name; - start = new Date().getTime(); - } - - public void run() { - counter++; - diff = new Date().getTime() - start; - logger.debug("counter={}", counter); - //logger_main.debug("[MAIN] - [{}] {}", name, new Date().getTime() - start); - } - } -} +/** + * 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.classic.issue; + +import java.util.Date; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.StatusPrinter; + +public class LBCORE63 extends Thread { + private final static String LOGGER_CONFIGURATION_FILE = "./src/test/input/issue/lbcore63.xml"; + private final Logger logger = LoggerFactory.getLogger(LBCORE63.class); + + private final long start; + + public LBCORE63() throws JoranException { + start = new Date().getTime(); + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + JoranConfigurator configurator = new JoranConfigurator(); + lc.reset(); + configurator.setContext(lc); + configurator.doConfigure(LOGGER_CONFIGURATION_FILE); + StatusPrinter.printInCaseOfErrorsOrWarnings(lc); + } + + public void start() { + ScheduledThreadPoolExecutor ex1 = new ScheduledThreadPoolExecutor(1); + ScheduledThreadPoolExecutor ex2 = new ScheduledThreadPoolExecutor(1); + ScheduledThreadPoolExecutor ex3 = new ScheduledThreadPoolExecutor(1); + ScheduledThreadPoolExecutor ex4 = new ScheduledThreadPoolExecutor(1); + ScheduledThreadPoolExecutor ex5 = new ScheduledThreadPoolExecutor(1); + ex1.scheduleAtFixedRate(new Task("EX1"), 10, 10, TimeUnit.MICROSECONDS); + ex2.scheduleAtFixedRate(new Task("EX2"), 10, 10, TimeUnit.MICROSECONDS); + ex3.scheduleAtFixedRate(new Task("EX3"), 10, 10, TimeUnit.MICROSECONDS); + ex4.scheduleAtFixedRate(new Task("EX4"), 10, 10, TimeUnit.MICROSECONDS); + ex5.scheduleAtFixedRate(new Task("EX5"), 10, 10, TimeUnit.MICROSECONDS); + + super.start(); + } + + public void run() { + try { + while (true) { + logger.debug("[MAIN] {}", new Date().getTime() - start); + Thread.sleep(10); + } + } catch (InterruptedException e) { + logger.info("[MAIN]: Interrupted: {}", e.getMessage()); + } + } + + public static void main(String[] args) { + try { + LBCORE63 main = new LBCORE63(); + main.start(); + } catch (JoranException e) { + System.out.println("Failed to load application: " + e.getMessage()); + } + } + + class Task implements Runnable { + private final Logger logger = LoggerFactory.getLogger(Task.class); + //private final Logger logger_main = LoggerFactory.getLogger(LBCORE63.class); + final String name; + private final long start; + + int counter = 0; + public long diff; + + public Task(final String name) { + this.name = name; + start = new Date().getTime(); + } + + public void run() { + counter++; + diff = new Date().getTime() - start; + logger.debug("counter={}", counter); + //logger_main.debug("[MAIN] - [{}] {}", name, new Date().getTime() - start); + } + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/issue/PackageTest.java index 6f412369fd918d4ef757f02b17f34604b9df2776..f23dae92353832c7b6f46af9d4d26742c57aed88 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/issue/PackageTest.java @@ -1,25 +1,25 @@ -/** - * 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.classic.issue; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -import ch.qos.logback.classic.issue.lbclassic135.lbclassic139.LB139_DeadlockTest; - -@RunWith(Suite.class) -@SuiteClasses(LB139_DeadlockTest.class) -public class PackageTest { +/** + * 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.classic.issue; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import ch.qos.logback.classic.issue.lbclassic135.lbclassic139.LB139_DeadlockTest; + +@RunWith(Suite.class) +@SuiteClasses(LB139_DeadlockTest.class) +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingRunnable.java b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingRunnable.java index 6817ea76f32eaf7fa4ed80a57b1e5d346aaeb490..91c907b5fc7289b98d638d24dd0bec84a9a84ac6 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingRunnable.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingRunnable.java @@ -1,38 +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.classic.issue.lbclassic135; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; - -public class LoggingRunnable extends RunnableWithCounterAndDone { - - Logger logger; - - public LoggingRunnable(Logger logger) { - this.logger = logger; - } - - public void run() { - while (!isDone()) { - logger.info("hello world ABCDEFGHI"); - counter++; - // don't hog the CPU forever - if (counter % 100 == 0) { - Thread.yield(); - } - } - } - -} +/** + * 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.classic.issue.lbclassic135; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.contention.RunnableWithCounterAndDone; + +public class LoggingRunnable extends RunnableWithCounterAndDone { + + Logger logger; + + public LoggingRunnable(Logger logger) { + this.logger = logger; + } + + public void run() { + while (!isDone()) { + logger.info("hello world ABCDEFGHI"); + counter++; + // don't hog the CPU forever + if (counter % 100 == 0) { + Thread.yield(); + } + } + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingToFileThrouhput.java b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingToFileThrouhput.java index 3d206e7bcccb42844869e9b7c17e0439d457b301..4590a0d6ed7d154e700c4e776426988d4fc72fd3 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingToFileThrouhput.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingToFileThrouhput.java @@ -1,116 +1,116 @@ -/** - * 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.classic.issue.lbclassic135; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.FileAppender; -import ch.qos.logback.core.contention.ThreadedThroughputCalculator; - -/** - * Short sample code testing the throughput of a fair lock. - * - * @author Ceki Gulcu - */ -public class LoggingToFileThrouhput { - - static int THREAD_COUNT = 1; - static long OVERALL_DURATION_IN_MILLIS = 5000; - - public static void main(String args[]) throws InterruptedException { - - ThreadedThroughputCalculator tp = new ThreadedThroughputCalculator( - OVERALL_DURATION_IN_MILLIS); - tp.printEnvironmentInfo("lbclassic135 LoggingToFileThrouhput"); - - LoggerContext lc = new LoggerContext(); - Logger logger = buildLoggerContext(lc); - - for (int i = 0; i < 2; i++) { - tp.execute(buildArray(logger)); - } - - tp.execute(buildArray(logger)); - tp.printThroughput("File: "); - lc.stop(); - } - - static Logger buildLoggerContext(LoggerContext lc) { - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - - PatternLayout patternLayout = new PatternLayout(); - patternLayout.setContext(lc); - patternLayout.setPattern("%d %l [%t] - %msg%n"); - patternLayout.start(); - FileAppender fileAppender = new FileAppender(); - fileAppender.setContext(lc); - fileAppender.setFile("target/lbclassic135.log"); - fileAppender.setLayout(patternLayout); - fileAppender.setAppend(false); - fileAppender.start(); - root.addAppender(fileAppender); - return lc.getLogger(LoggingToFileThrouhput.class); - } - - static LoggingRunnable[] buildArray(Logger logger) { - - LoggingRunnable[] array = new LoggingRunnable[THREAD_COUNT]; - for (int i = 0; i < THREAD_COUNT; i++) { - array[i] = new LoggingRunnable(logger); - } - return array; - } -} - -//=== lbclassic135 LoggingToFileThrouhput === -// ******** 10 Threads ***** -// synchronized doAppend() method -// -// java.runtime.version = 1.6.0_05-b13 -// java.vendor = Sun Microsystems Inc. -// os.name = Windows XP -// -// Threads 1: total of 485077 operations, or 97 operations per millisecond -// Threads 10: total of 309402 operations, or 61 operations per millisecond - -//* After revision 2310 -//* Threads 1: total of 462465 operations, or 92 operations per millisecond -//* Threads 10: total of 243362 operations, or 48 operations per millisecond - -// ==================== Linux ======================== - -// java.runtime.version = 1.6.0_11-b03 -// java.vendor = Sun Microsystems Inc. -// os.name = Linux -// os.version = 2.6.25-gentoo-r6 -// Threads 1: total of 356355 operations, or 71 operations per millisecond -// Threads 10: total of 287943 operations, or 57 operations per millisecond - -//* After revision 2310 -//* Threads 1: total of 331494 operations, or 66 operations per millisecond -//* Threads 10: total of 311104 operations, or 58 operations per millisecond - -// java.runtime.version = jvmxa6460-20081105_25433 -// java.vendor = IBM Corporation -// java.version = 1.6.0 -// os.name = Linux -// os.version = 2.6.25-gentoo-r6 -// Threads 1: total of 280381 operations, or 56 operations per millisecond -// Threads 10 total of 142989 operations, or 28 operations per millisecond - -//* After revision 2310 -//* Threads 1: total of 305638 operations, or 61 operations per millisecond +/** + * 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.classic.issue.lbclassic135; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.contention.ThreadedThroughputCalculator; + +/** + * Short sample code testing the throughput of a fair lock. + * + * @author Ceki Gulcu + */ +public class LoggingToFileThrouhput { + + static int THREAD_COUNT = 1; + static long OVERALL_DURATION_IN_MILLIS = 5000; + + public static void main(String args[]) throws InterruptedException { + + ThreadedThroughputCalculator tp = new ThreadedThroughputCalculator( + OVERALL_DURATION_IN_MILLIS); + tp.printEnvironmentInfo("lbclassic135 LoggingToFileThrouhput"); + + LoggerContext lc = new LoggerContext(); + Logger logger = buildLoggerContext(lc); + + for (int i = 0; i < 2; i++) { + tp.execute(buildArray(logger)); + } + + tp.execute(buildArray(logger)); + tp.printThroughput("File: "); + lc.stop(); + } + + static Logger buildLoggerContext(LoggerContext lc) { + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + + PatternLayout patternLayout = new PatternLayout(); + patternLayout.setContext(lc); + patternLayout.setPattern("%d %l [%t] - %msg%n"); + patternLayout.start(); + FileAppender fileAppender = new FileAppender(); + fileAppender.setContext(lc); + fileAppender.setFile("target/lbclassic135.log"); + fileAppender.setLayout(patternLayout); + fileAppender.setAppend(false); + fileAppender.start(); + root.addAppender(fileAppender); + return lc.getLogger(LoggingToFileThrouhput.class); + } + + static LoggingRunnable[] buildArray(Logger logger) { + + LoggingRunnable[] array = new LoggingRunnable[THREAD_COUNT]; + for (int i = 0; i < THREAD_COUNT; i++) { + array[i] = new LoggingRunnable(logger); + } + return array; + } +} + +//=== lbclassic135 LoggingToFileThrouhput === +// ******** 10 Threads ***** +// synchronized doAppend() method +// +// java.runtime.version = 1.6.0_05-b13 +// java.vendor = Sun Microsystems Inc. +// os.name = Windows XP +// +// Threads 1: total of 485077 operations, or 97 operations per millisecond +// Threads 10: total of 309402 operations, or 61 operations per millisecond + +//* After revision 2310 +//* Threads 1: total of 462465 operations, or 92 operations per millisecond +//* Threads 10: total of 243362 operations, or 48 operations per millisecond + +// ==================== Linux ======================== + +// java.runtime.version = 1.6.0_11-b03 +// java.vendor = Sun Microsystems Inc. +// os.name = Linux +// os.version = 2.6.25-gentoo-r6 +// Threads 1: total of 356355 operations, or 71 operations per millisecond +// Threads 10: total of 287943 operations, or 57 operations per millisecond + +//* After revision 2310 +//* Threads 1: total of 331494 operations, or 66 operations per millisecond +//* Threads 10: total of 311104 operations, or 58 operations per millisecond + +// java.runtime.version = jvmxa6460-20081105_25433 +// java.vendor = IBM Corporation +// java.version = 1.6.0 +// os.name = Linux +// os.version = 2.6.25-gentoo-r6 +// Threads 1: total of 280381 operations, or 56 operations per millisecond +// Threads 10 total of 142989 operations, or 28 operations per millisecond + +//* After revision 2310 +//* Threads 1: total of 305638 operations, or 61 operations per millisecond //* Threads 10: total of 147660 operations, or 29 operations per millisecond \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/DateFormattingThreadedThroughputCalculator.java b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/DateFormattingThreadedThroughputCalculator.java index 9c07530bb917c5123fd705bdf63d97af02cdd375..94d549ba1785b7cb71043c8aea37bc2e7a0b3aa2 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/DateFormattingThreadedThroughputCalculator.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/DateFormattingThreadedThroughputCalculator.java @@ -1,58 +1,58 @@ -/** - * 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.classic.issue.lbclassic36; - -import ch.qos.logback.classic.issue.lbclassic36.SelectiveDateFormattingRunnable.FormattingModel; -import ch.qos.logback.core.contention.ThreadedThroughputCalculator; - -/** - * Measure the threaded throughtput of date formatting operations - * - * @author Joern Huxhorn - * @author Ceki Gulcu - */ -public class DateFormattingThreadedThroughputCalculator { - - static int THREAD_COUNT = 16; - static long OVERALL_DURATION_IN_MILLIS = 3000; - - public static void main(String args[]) throws InterruptedException { - - ThreadedThroughputCalculator tp = new ThreadedThroughputCalculator( - OVERALL_DURATION_IN_MILLIS); - tp.printEnvironmentInfo("DateFormatting"); - - for (int i = 0; i < 2; i++) { - tp.execute(buildArray(FormattingModel.SDF)); - tp.execute(buildArray(FormattingModel.JODA)); - } - - tp.execute(buildArray(FormattingModel.JODA)); - tp.printThroughput("JODA: "); - - tp.execute(buildArray(FormattingModel.SDF)); - tp.printThroughput("SDF: "); - - - } - - static SelectiveDateFormattingRunnable[] buildArray(FormattingModel model) { - SelectiveDateFormattingRunnable[] array = new SelectiveDateFormattingRunnable[THREAD_COUNT]; - for (int i = 0; i < THREAD_COUNT; i++) { - array[i] = new SelectiveDateFormattingRunnable(model); - } - return array; - } - -} +/** + * 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.classic.issue.lbclassic36; + +import ch.qos.logback.classic.issue.lbclassic36.SelectiveDateFormattingRunnable.FormattingModel; +import ch.qos.logback.core.contention.ThreadedThroughputCalculator; + +/** + * Measure the threaded throughtput of date formatting operations + * + * @author Joern Huxhorn + * @author Ceki Gulcu + */ +public class DateFormattingThreadedThroughputCalculator { + + static int THREAD_COUNT = 16; + static long OVERALL_DURATION_IN_MILLIS = 3000; + + public static void main(String args[]) throws InterruptedException { + + ThreadedThroughputCalculator tp = new ThreadedThroughputCalculator( + OVERALL_DURATION_IN_MILLIS); + tp.printEnvironmentInfo("DateFormatting"); + + for (int i = 0; i < 2; i++) { + tp.execute(buildArray(FormattingModel.SDF)); + tp.execute(buildArray(FormattingModel.JODA)); + } + + tp.execute(buildArray(FormattingModel.JODA)); + tp.printThroughput("JODA: "); + + tp.execute(buildArray(FormattingModel.SDF)); + tp.printThroughput("SDF: "); + + + } + + static SelectiveDateFormattingRunnable[] buildArray(FormattingModel model) { + SelectiveDateFormattingRunnable[] array = new SelectiveDateFormattingRunnable[THREAD_COUNT]; + for (int i = 0; i < THREAD_COUNT; i++) { + array[i] = new SelectiveDateFormattingRunnable(model); + } + return array; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/SelectiveDateFormattingRunnable.java b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/SelectiveDateFormattingRunnable.java index 1fa2326695fa4d42734fc1c742e886859b818245..aa26781340ea1ccb6f91edc689d86884a68fa2aa 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/SelectiveDateFormattingRunnable.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/SelectiveDateFormattingRunnable.java @@ -1,99 +1,99 @@ -/** - * 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.classic.issue.lbclassic36; - -import java.text.SimpleDateFormat; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; - -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; - -/** - * A runnable which behaves differently depending on the desired locking model. - * - * @author Raplh Goers - * @author Ceki Gulcu - */ -public class SelectiveDateFormattingRunnable extends - RunnableWithCounterAndDone { - - public static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS"; - - enum FormattingModel { - SDF, JODA; - } - - FormattingModel model; - static long CACHE = 0; - - static SimpleDateFormat SDF = new SimpleDateFormat(ISO8601_PATTERN); - static final DateTimeFormatter JODA = DateTimeFormat - .forPattern(ISO8601_PATTERN); - - SelectiveDateFormattingRunnable(FormattingModel model) { - this.model = model; - } - - public void run() { - switch (model) { - case SDF: - sdfRun(); - break; - case JODA: - jodaRun(); - break; - } - } - - void sdfRun() { - - for (;;) { - synchronized (SDF) { - long now = System.currentTimeMillis(); - if (CACHE != now) { - CACHE = now; - SDF.format(now); - } - } - counter++; - if (done) { - return; - } - } - } - - void jodaRun() { - for (;;) { - long now = System.currentTimeMillis(); - if (isCacheStale(now)) { - JODA.print(now); - } - counter++; - if (done) { - return; - } - } - } - - private static boolean isCacheStale(long now) { - synchronized (JODA) { - if (CACHE != now) { - CACHE = now; - return true; - } - } - return false; - } - -} +/** + * 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.classic.issue.lbclassic36; + +import java.text.SimpleDateFormat; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +import ch.qos.logback.core.contention.RunnableWithCounterAndDone; + +/** + * A runnable which behaves differently depending on the desired locking model. + * + * @author Raplh Goers + * @author Ceki Gulcu + */ +public class SelectiveDateFormattingRunnable extends + RunnableWithCounterAndDone { + + public static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS"; + + enum FormattingModel { + SDF, JODA; + } + + FormattingModel model; + static long CACHE = 0; + + static SimpleDateFormat SDF = new SimpleDateFormat(ISO8601_PATTERN); + static final DateTimeFormatter JODA = DateTimeFormat + .forPattern(ISO8601_PATTERN); + + SelectiveDateFormattingRunnable(FormattingModel model) { + this.model = model; + } + + public void run() { + switch (model) { + case SDF: + sdfRun(); + break; + case JODA: + jodaRun(); + break; + } + } + + void sdfRun() { + + for (;;) { + synchronized (SDF) { + long now = System.currentTimeMillis(); + if (CACHE != now) { + CACHE = now; + SDF.format(now); + } + } + counter++; + if (done) { + return; + } + } + } + + void jodaRun() { + for (;;) { + long now = System.currentTimeMillis(); + if (isCacheStale(now)) { + JODA.print(now); + } + counter++; + if (done) { + return; + } + } + } + + private static boolean isCacheStale(long now) { + synchronized (JODA) { + if (CACHE != now) { + CACHE = now; + return true; + } + } + return false; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbcore26/Main.java b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbcore26/Main.java index d4e746babb633412915fbe5a189425f16a33aa84..2a033e1ec3880ecad032e612d5c946271c2023db 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbcore26/Main.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbcore26/Main.java @@ -1,32 +1,32 @@ -package ch.qos.logback.classic.issue.lbcore26; - -import java.util.Date; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.ClassicTestConstants; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.util.StatusPrinter; - -public class Main { - - public static void main(String[] args) throws JoranException { - - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - configurator.doConfigure(ClassicTestConstants.INPUT_PREFIX - + "issue/lbcore26.xml"); - - StatusPrinter.printInCaseOfErrorsOrWarnings(lc); - Logger logger = LoggerFactory.getLogger(Main.class); - for (int i = 0; i < 16; i++) { - logger.info("hello " + new Date()); - } - - } - -} +package ch.qos.logback.classic.issue.lbcore26; + +import java.util.Date; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.ClassicTestConstants; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.StatusPrinter; + +public class Main { + + public static void main(String[] args) throws JoranException { + + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + configurator.doConfigure(ClassicTestConstants.INPUT_PREFIX + + "issue/lbcore26.xml"); + + StatusPrinter.printInCaseOfErrorsOrWarnings(lc); + Logger logger = LoggerFactory.getLogger(Main.class); + for (int i = 0; i < 16; i++) { + logger.info("hello " + new Date()); + } + + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/jmx/JMXConfiguratorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/jmx/JMXConfiguratorTest.java index 5abb87e1bfef2355d558223b24c59d91f9013d00..e34a1d417eb328d68acdd098e5fc892ae7e8cd92 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/jmx/JMXConfiguratorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/jmx/JMXConfiguratorTest.java @@ -1,158 +1,158 @@ -/** - * 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.classic.jmx; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.lang.management.ManagementFactory; -import java.util.List; - -import javax.management.MBeanServer; -import javax.management.ObjectName; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.LoggerContextListener; -import ch.qos.logback.core.testUtil.RandomUtil; - -public class JMXConfiguratorTest { - - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - LoggerContext lc = new LoggerContext(); - Logger testLogger = lc.getLogger(this.getClass()); - - List listenerList; - int diff = RandomUtil.getPositiveInt(); - - - @Before - public void setUp() throws Exception { - lc.setName("context-" + diff); - assertNotNull(mbs); - } - - @After - public void tearDown() throws Exception { - lc.stop(); - } - - @Override - public String toString() { - return this.getClass().getName() + "(" + lc.getName() + ")"; - } - - @Test - public void contextReset() throws Exception { - String randomizedObjectNameAsStr = "ch.qos.logback."+diff + ":Name=" + lc.getName() - + ",Type=" + this.getClass().getName(); - - ObjectName objectName = MBeanUtil.string2ObjectName(lc, this, randomizedObjectNameAsStr); - JMXConfigurator jmxConfigurator = new JMXConfigurator(lc, mbs, objectName); - mbs.registerMBean(jmxConfigurator, objectName); - - listenerList = lc.getCopyOfListenerList(); - assertEquals(1, listenerList.size()); - - lc.reset(); - - // check that after lc.reset, jmxConfigurator should still be - // registered as a listener in the loggerContext and also as an - // MBean in mbs - listenerList = lc.getCopyOfListenerList(); - assertEquals(1, listenerList.size()); - assertTrue(listenerList.contains(jmxConfigurator)); - - assertTrue(mbs.isRegistered(objectName)); - } - - @Test - public void contextStop() throws Exception { - String randomizedObjectNameAsStr = "ch.qos.logback."+diff + ":Name=" + lc.getName() - + ",Type=" + this.getClass().getName(); - - ObjectName objectName = MBeanUtil.string2ObjectName(lc, this, randomizedObjectNameAsStr); - JMXConfigurator jmxConfigurator = new JMXConfigurator(lc, mbs, objectName); - mbs.registerMBean(jmxConfigurator, objectName); - - listenerList = lc.getCopyOfListenerList(); - assertEquals(1, listenerList.size()); - - lc.stop(); - - // check that after lc.stop, jmxConfigurator is no longer - // registered as a listener in the loggerContext nor as an - // MBean in mbs - listenerList = lc.getCopyOfListenerList(); - assertEquals(0, listenerList.size()); - - assertFalse(mbs.isRegistered(objectName)); - } - - @Test - public void testNonRemovalOfPreviousIntanceFromTheContextListenerList() { - String objectNameAsStr = "ch.qos.logback.toto" + ":Name=" + lc.getName() - + ",Type=" + this.getClass().getName(); - ObjectName objectName = MBeanUtil.string2ObjectName(lc, this, objectNameAsStr); - JMXConfigurator jmxConfigurator0 = new JMXConfigurator(lc, mbs, objectName); - - listenerList = lc.getCopyOfListenerList(); - assertTrue(listenerList.contains(jmxConfigurator0)); - - JMXConfigurator jmxConfigurator1 = new JMXConfigurator(lc, mbs, objectName); - listenerList = lc.getCopyOfListenerList(); - assertEquals(1, listenerList.size()); - assertTrue("old configurator should be present", listenerList - .contains(jmxConfigurator0)); - assertFalse("new configurator should be absent", listenerList - .contains(jmxConfigurator1)); - } - - @Test - public void getLoggerLevel_LBCLASSIC_78() { - String objectNameAsStr = "ch.qos"+diff + ":Name=" + lc.getName() - + ",Type=" + this.getClass().getName(); - - ObjectName on = MBeanUtil.string2ObjectName(lc, this, objectNameAsStr); - JMXConfigurator configurator = new JMXConfigurator(lc, mbs, on); - assertEquals("", configurator.getLoggerLevel(testLogger.getName())); - MBeanUtil.unregister(lc, mbs, on, this); - } - - - @Test - public void setLoggerLevel_LBCLASSIC_79() { - String objectNameAsStr = "ch.qos"+diff + ":Name=" + lc.getName() - + ",Type=" + this.getClass().getName(); - - ObjectName on = MBeanUtil.string2ObjectName(lc, this, objectNameAsStr); - JMXConfigurator configurator = new JMXConfigurator(lc, mbs, on); - configurator.setLoggerLevel(testLogger.getName(), "DEBUG"); - assertEquals(Level.DEBUG, testLogger.getLevel()); - - configurator.setLoggerLevel(testLogger.getName(), "null"); - assertNull(testLogger.getLevel()); - - MBeanUtil.unregister(lc, mbs, on, this); - } - -} +/** + * 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.classic.jmx; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.lang.management.ManagementFactory; +import java.util.List; + +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.LoggerContextListener; +import ch.qos.logback.core.testUtil.RandomUtil; + +public class JMXConfiguratorTest { + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + LoggerContext lc = new LoggerContext(); + Logger testLogger = lc.getLogger(this.getClass()); + + List listenerList; + int diff = RandomUtil.getPositiveInt(); + + + @Before + public void setUp() throws Exception { + lc.setName("context-" + diff); + assertNotNull(mbs); + } + + @After + public void tearDown() throws Exception { + lc.stop(); + } + + @Override + public String toString() { + return this.getClass().getName() + "(" + lc.getName() + ")"; + } + + @Test + public void contextReset() throws Exception { + String randomizedObjectNameAsStr = "ch.qos.logback."+diff + ":Name=" + lc.getName() + + ",Type=" + this.getClass().getName(); + + ObjectName objectName = MBeanUtil.string2ObjectName(lc, this, randomizedObjectNameAsStr); + JMXConfigurator jmxConfigurator = new JMXConfigurator(lc, mbs, objectName); + mbs.registerMBean(jmxConfigurator, objectName); + + listenerList = lc.getCopyOfListenerList(); + assertEquals(1, listenerList.size()); + + lc.reset(); + + // check that after lc.reset, jmxConfigurator should still be + // registered as a listener in the loggerContext and also as an + // MBean in mbs + listenerList = lc.getCopyOfListenerList(); + assertEquals(1, listenerList.size()); + assertTrue(listenerList.contains(jmxConfigurator)); + + assertTrue(mbs.isRegistered(objectName)); + } + + @Test + public void contextStop() throws Exception { + String randomizedObjectNameAsStr = "ch.qos.logback."+diff + ":Name=" + lc.getName() + + ",Type=" + this.getClass().getName(); + + ObjectName objectName = MBeanUtil.string2ObjectName(lc, this, randomizedObjectNameAsStr); + JMXConfigurator jmxConfigurator = new JMXConfigurator(lc, mbs, objectName); + mbs.registerMBean(jmxConfigurator, objectName); + + listenerList = lc.getCopyOfListenerList(); + assertEquals(1, listenerList.size()); + + lc.stop(); + + // check that after lc.stop, jmxConfigurator is no longer + // registered as a listener in the loggerContext nor as an + // MBean in mbs + listenerList = lc.getCopyOfListenerList(); + assertEquals(0, listenerList.size()); + + assertFalse(mbs.isRegistered(objectName)); + } + + @Test + public void testNonRemovalOfPreviousIntanceFromTheContextListenerList() { + String objectNameAsStr = "ch.qos.logback.toto" + ":Name=" + lc.getName() + + ",Type=" + this.getClass().getName(); + ObjectName objectName = MBeanUtil.string2ObjectName(lc, this, objectNameAsStr); + JMXConfigurator jmxConfigurator0 = new JMXConfigurator(lc, mbs, objectName); + + listenerList = lc.getCopyOfListenerList(); + assertTrue(listenerList.contains(jmxConfigurator0)); + + JMXConfigurator jmxConfigurator1 = new JMXConfigurator(lc, mbs, objectName); + listenerList = lc.getCopyOfListenerList(); + assertEquals(1, listenerList.size()); + assertTrue("old configurator should be present", listenerList + .contains(jmxConfigurator0)); + assertFalse("new configurator should be absent", listenerList + .contains(jmxConfigurator1)); + } + + @Test + public void getLoggerLevel_LBCLASSIC_78() { + String objectNameAsStr = "ch.qos"+diff + ":Name=" + lc.getName() + + ",Type=" + this.getClass().getName(); + + ObjectName on = MBeanUtil.string2ObjectName(lc, this, objectNameAsStr); + JMXConfigurator configurator = new JMXConfigurator(lc, mbs, on); + assertEquals("", configurator.getLoggerLevel(testLogger.getName())); + MBeanUtil.unregister(lc, mbs, on, this); + } + + + @Test + public void setLoggerLevel_LBCLASSIC_79() { + String objectNameAsStr = "ch.qos"+diff + ":Name=" + lc.getName() + + ",Type=" + this.getClass().getName(); + + ObjectName on = MBeanUtil.string2ObjectName(lc, this, objectNameAsStr); + JMXConfigurator configurator = new JMXConfigurator(lc, mbs, on); + configurator.setLoggerLevel(testLogger.getName(), "DEBUG"); + assertEquals(Level.DEBUG, testLogger.getLevel()); + + configurator.setLoggerLevel(testLogger.getName(), "null"); + assertNull(testLogger.getLevel()); + + MBeanUtil.unregister(lc, mbs, on, this); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/jmx/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/jmx/PackageTest.java index 0e1e9f04e2e891b43a4df33c968d4b62803ada87..a3510141a7a11568f23c31f89b254e504e022ebc 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/jmx/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/jmx/PackageTest.java @@ -1,25 +1,25 @@ -/** - * 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.classic.jmx; - - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses(JMXConfiguratorTest.class) -public class PackageTest { - +/** + * 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.classic.jmx; + + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses(JMXConfiguratorTest.class) +public class PackageTest { + } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/EvaluatorJoranTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/joran/EvaluatorJoranTest.java index 4baca0b90de6ed9fa89ab23f92c61aa7b9360d1c..1fe7fa5f93706c3c94d6833b5209a343b0b8453a 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/EvaluatorJoranTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/joran/EvaluatorJoranTest.java @@ -1,106 +1,106 @@ -/** - * 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.classic.joran; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.Map; - -import org.junit.Test; -import org.slf4j.Marker; -import org.slf4j.MarkerFactory; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.boolex.JaninoEventEvaluator; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.classic.util.TeztConstants; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.boolex.EvaluationException; -import ch.qos.logback.core.joran.spi.JoranException; - - -public class EvaluatorJoranTest { - - @Test - public void testSimpleEvaluator() throws NullPointerException, EvaluationException, JoranException { - JoranConfigurator jc = new JoranConfigurator(); - LoggerContext loggerContext = new LoggerContext(); - jc.setContext(loggerContext); - jc.doConfigure(TeztConstants.TEST_DIR_PREFIX + "input/joran/simpleEvaluator.xml"); - - - Map evalMap = (Map) loggerContext.getObject(CoreConstants.EVALUATOR_MAP); - assertNotNull(evalMap); - JaninoEventEvaluator evaluator = (JaninoEventEvaluator) evalMap.get("msgEval"); - assertNotNull(evaluator); - - Logger logger = loggerContext.getLogger("xx"); - ILoggingEvent event0 = new LoggingEvent("foo", logger, Level.DEBUG, "Hello world", null, null); - assertTrue(evaluator.evaluate(event0)); - - ILoggingEvent event1 = new LoggingEvent("foo", logger, Level.DEBUG, "random blurb", null, null); - assertFalse(evaluator.evaluate(event1)); - } - - @Test - public void testIgnoreMarker() throws NullPointerException, EvaluationException, JoranException { - JoranConfigurator jc = new JoranConfigurator(); - LoggerContext loggerContext = new LoggerContext(); - jc.setContext(loggerContext); - jc.doConfigure(TeztConstants.TEST_DIR_PREFIX + "input/joran/ignore.xml"); - - Map evalMap = (Map) loggerContext.getObject(CoreConstants.EVALUATOR_MAP); - assertNotNull(evalMap); - - Logger logger = loggerContext.getLogger("xx"); - - JaninoEventEvaluator evaluator = (JaninoEventEvaluator) evalMap.get("IGNORE_EVAL"); - LoggingEvent event = new LoggingEvent("foo", logger, Level.DEBUG, "Hello world",null, null); - - Marker ignoreMarker = MarkerFactory.getMarker("IGNORE"); - event.setMarker(ignoreMarker); - assertTrue(evaluator.evaluate(event)); - - logger.debug("hello", new Exception("test")); - logger.debug(ignoreMarker, "hello ignore", new Exception("test")); - - //logger.debug("hello", new Exception("test")); - - //StatusPrinter.print(loggerContext.getStatusManager()); - } - - @Test - public void testMultipleConditionsInExpression() throws NullPointerException, EvaluationException { - LoggerContext loggerContext = new LoggerContext(); - Logger logger = loggerContext.getLogger("xx"); - JaninoEventEvaluator ee = new JaninoEventEvaluator(); - ee.setName("testEval"); - ee.setContext(loggerContext); - //&& - //&& - ee.setExpression("message.contains(\"stacktrace\") && message.contains(\"logging\")"); - ee.start(); - //StatusPrinter.print(loggerContext); - - String message = "stacktrace bla bla logging"; - ILoggingEvent event = new LoggingEvent(this.getClass().getName(), logger, Level.DEBUG, message, null, null); - - assertTrue(ee.evaluate(event)); - } -} +/** + * 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.classic.joran; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.Test; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.boolex.JaninoEventEvaluator; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.classic.util.TeztConstants; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.joran.spi.JoranException; + + +public class EvaluatorJoranTest { + + @Test + public void testSimpleEvaluator() throws NullPointerException, EvaluationException, JoranException { + JoranConfigurator jc = new JoranConfigurator(); + LoggerContext loggerContext = new LoggerContext(); + jc.setContext(loggerContext); + jc.doConfigure(TeztConstants.TEST_DIR_PREFIX + "input/joran/simpleEvaluator.xml"); + + + Map evalMap = (Map) loggerContext.getObject(CoreConstants.EVALUATOR_MAP); + assertNotNull(evalMap); + JaninoEventEvaluator evaluator = (JaninoEventEvaluator) evalMap.get("msgEval"); + assertNotNull(evaluator); + + Logger logger = loggerContext.getLogger("xx"); + ILoggingEvent event0 = new LoggingEvent("foo", logger, Level.DEBUG, "Hello world", null, null); + assertTrue(evaluator.evaluate(event0)); + + ILoggingEvent event1 = new LoggingEvent("foo", logger, Level.DEBUG, "random blurb", null, null); + assertFalse(evaluator.evaluate(event1)); + } + + @Test + public void testIgnoreMarker() throws NullPointerException, EvaluationException, JoranException { + JoranConfigurator jc = new JoranConfigurator(); + LoggerContext loggerContext = new LoggerContext(); + jc.setContext(loggerContext); + jc.doConfigure(TeztConstants.TEST_DIR_PREFIX + "input/joran/ignore.xml"); + + Map evalMap = (Map) loggerContext.getObject(CoreConstants.EVALUATOR_MAP); + assertNotNull(evalMap); + + Logger logger = loggerContext.getLogger("xx"); + + JaninoEventEvaluator evaluator = (JaninoEventEvaluator) evalMap.get("IGNORE_EVAL"); + LoggingEvent event = new LoggingEvent("foo", logger, Level.DEBUG, "Hello world",null, null); + + Marker ignoreMarker = MarkerFactory.getMarker("IGNORE"); + event.setMarker(ignoreMarker); + assertTrue(evaluator.evaluate(event)); + + logger.debug("hello", new Exception("test")); + logger.debug(ignoreMarker, "hello ignore", new Exception("test")); + + //logger.debug("hello", new Exception("test")); + + //StatusPrinter.print(loggerContext.getStatusManager()); + } + + @Test + public void testMultipleConditionsInExpression() throws NullPointerException, EvaluationException { + LoggerContext loggerContext = new LoggerContext(); + Logger logger = loggerContext.getLogger("xx"); + JaninoEventEvaluator ee = new JaninoEventEvaluator(); + ee.setName("testEval"); + ee.setContext(loggerContext); + //&& + //&& + ee.setExpression("message.contains(\"stacktrace\") && message.contains(\"logging\")"); + ee.start(); + //StatusPrinter.print(loggerContext); + + String message = "stacktrace bla bla logging"; + ILoggingEvent event = new LoggingEvent(this.getClass().getName(), logger, Level.DEBUG, message, null, null); + + assertTrue(ee.evaluate(event)); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java index 93f831738daf08d982f8f05e212d63ac37c374df..58b385543d623bb569e555c2964163314e90c90a 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java @@ -1,293 +1,293 @@ -/** - * 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.classic.joran; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.junit.Test; -import org.slf4j.MDC; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.turbo.DebugUsersTurboFilter; -import ch.qos.logback.classic.turbo.NOPTurboFilter; -import ch.qos.logback.classic.turbo.TurboFilter; -import ch.qos.logback.classic.util.TeztConstants; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.read.ListAppender; -import ch.qos.logback.core.status.StatusChecker; -import ch.qos.logback.core.testUtil.StringListAppender; - -public class JoranConfiguratorTest { - - LoggerContext loggerContext = new LoggerContext(); - Logger logger = loggerContext.getLogger(this.getClass().getName()); - Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME); - - void configure(String file) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(loggerContext); - jc.doConfigure(file); - } - - @Test - public void simpleList() throws JoranException { - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/simpleList.xml"); - - Logger logger = loggerContext.getLogger(this.getClass().getName()); - Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME); - ListAppender listAppender = (ListAppender) root.getAppender("LIST"); - assertEquals(0, listAppender.list.size()); - String msg = "hello world"; - logger.debug(msg); - assertEquals(1, listAppender.list.size()); - ILoggingEvent le = (ILoggingEvent) listAppender.list.get(0); - assertEquals(msg, le.getMessage()); - } - - @Test - public void level() throws JoranException { - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/simpleLevel.xml"); - ListAppender listAppender = (ListAppender) root.getAppender("LIST"); - assertEquals(0, listAppender.list.size()); - String msg = "hello world"; - logger.debug(msg); - assertEquals(0, listAppender.list.size()); - } - - @Test - public void rootLoggerLevelSettingBySystemProperty() - throws JoranException { - String propertyName = "logback.level"; - - System.setProperty(propertyName, "INFO"); - configure(TeztConstants.TEST_DIR_PREFIX - + "input/joran/rootLevelByProperty.xml"); - // StatusPrinter.print(loggerContext); - ListAppender listAppender = (ListAppender) root.getAppender("LIST"); - assertEquals(0, listAppender.list.size()); - String msg = "hello world"; - logger.debug(msg); - assertEquals(0, listAppender.list.size()); - System.clearProperty(propertyName); - } - - @Test - public void loggerLevelSettingBySystemProperty() throws JoranException { - String propertyName = "logback.level"; - - System.setProperty(propertyName, "DEBUG"); - configure(TeztConstants.TEST_DIR_PREFIX - + "input/joran/loggerLevelByProperty.xml"); - // StatusPrinter.print(loggerContext); - ListAppender listAppender = (ListAppender) root.getAppender("LIST"); - assertEquals(0, listAppender.list.size()); - String msg = "hello world"; - logger.debug(msg); - assertEquals(1, listAppender.list.size()); - System.clearProperty(propertyName); - } - - @Test - public void statusListener() throws JoranException { - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/statusListener.xml"); - // StatusPrinter.print(loggerContext); - } - - @Test - public void contextRename() throws JoranException { - loggerContext.setName(CoreConstants.DEFAULT_CONTEXT_NAME); - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/contextRename.xml"); - assertEquals("wombat", loggerContext.getName()); - } - - @Test - public void eval() throws JoranException { - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/callerData.xml"); - - String msg = "hello world"; - logger.debug("toto"); - logger.debug(msg); - - StringListAppender slAppender = (StringListAppender) loggerContext - .getLogger("root").getAppender("STR_LIST"); - assertNotNull(slAppender); - assertEquals(2, slAppender.strList.size()); - assertTrue(slAppender.strList.get(0).contains(" DEBUG - toto")); - - String str1 = slAppender.strList.get(1); - assertTrue(str1.contains("Caller+0")); - assertTrue(str1.contains(" DEBUG - hello world")); - } - - @Test - public void turboFilter() throws JoranException { - // Although this test uses turbo filters, it only checks - // that Joran can see the xml element and create - // and place the relevant object correctly. - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/turbo.xml"); - - TurboFilter filter = loggerContext.getTurboFilterList().get(0); - assertTrue(filter instanceof NOPTurboFilter); - } - - @Test - public void testTurboFilterWithStringList() throws JoranException { - // Although this test uses turbo filters, it only checks - // that Joran can see elements, and behave correctly - // that is call the addUser method and pass the correct values - // to that method. - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/turbo2.xml"); - - // StatusPrinter.print(loggerContext.getStatusManager()); - - TurboFilter filter = loggerContext.getTurboFilterList().get(0); - assertTrue(filter instanceof DebugUsersTurboFilter); - DebugUsersTurboFilter dutf = (DebugUsersTurboFilter) filter; - assertEquals(2, dutf.getUsers().size()); - } - - @Test - public void testLevelFilter() throws JoranException { - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/levelFilter.xml"); - - // StatusPrinter.print(loggerContext); - - logger.warn("hello"); - logger.error("to be ignored"); - - @SuppressWarnings("unchecked") - ListAppender listAppender = (ListAppender) root - .getAppender("LIST"); - - assertNotNull(listAppender); - assertEquals(1, listAppender.list.size()); - ILoggingEvent back = listAppender.list.get(0); - assertEquals(Level.WARN, back.getLevel()); - assertEquals("hello", back.getMessage()); - } - - @Test - public void testEvaluatorFilter() throws JoranException { - configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/evaluatorFilter.xml"); - - // StatusPrinter.print(loggerContext); - - logger.warn("hello"); - logger.error("to be ignored"); - - @SuppressWarnings("unchecked") - ListAppender listAppender = (ListAppender) root - .getAppender("LIST"); - - assertNotNull(listAppender); - assertEquals(1, listAppender.list.size()); - ILoggingEvent back = listAppender.list.get(0); - assertEquals(Level.WARN, back.getLevel()); - assertEquals("hello", back.getMessage()); - } - - @Test - public void testTurboDynamicThreshold() throws JoranException { - configure(TeztConstants.TEST_DIR_PREFIX - + "input/joran/turboDynamicThreshold.xml"); - - ListAppender listAppender = (ListAppender) root.getAppender("LIST"); - assertEquals(0, listAppender.list.size()); - - // this one should be denied - MDC.put("userId", "user1"); - logger.debug("hello user1"); - // this one should log - MDC.put("userId", "user2"); - logger.debug("hello user2"); - - assertEquals(1, listAppender.list.size()); - ILoggingEvent le = (ILoggingEvent) listAppender.list.get(0); - assertEquals("hello user2", le.getMessage()); - } - - @Test - public void testTurboDynamicThreshold2() throws JoranException { - configure(TeztConstants.TEST_DIR_PREFIX - + "input/joran/turboDynamicThreshold2.xml"); - - ListAppender listAppender = (ListAppender) root.getAppender("LIST"); - assertEquals(0, listAppender.list.size()); - - // this one should log - MDC.put("userId", "user1"); - logger.debug("hello user1"); - // this one should log - MDC.put("userId", "user2"); - logger.debug("hello user2"); - // this one should fail - MDC.put("userId", "user3"); - logger.debug("hello user3"); - - assertEquals(2, listAppender.list.size()); - ILoggingEvent le = (ILoggingEvent) listAppender.list.get(0); - assertEquals("hello user1", le.getMessage()); - le = (ILoggingEvent) listAppender.list.get(1); - assertEquals("hello user2", le.getMessage()); - } - - // Tests whether ConfigurationAction is installing ReconfigureOnChangeFilter - @Test - public void scan1() throws JoranException, IOException, InterruptedException { - - String configFileAsStr = TeztConstants.TEST_DIR_PREFIX - + "input/joran/scan1.xml"; - configure(configFileAsStr); - - File file = new File(configFileAsStr); - file.setLastModified(System.currentTimeMillis()); - - Thread.sleep(100); - // scanning requires 16 logs - for (int i = 0; i < 16; i++) { - logger.debug("after " + i); - } - - // StatusPrinter.print(loggerContext); - StatusChecker checker = new StatusChecker(loggerContext); - assertTrue(checker.isErrorFree()); - assertTrue(checker.containsMatch("Resetting and reconfiguring context")); - } - - @Test - public void timestamp() throws JoranException, IOException, InterruptedException { - - String configFileAsStr = TeztConstants.TEST_DIR_PREFIX - + "input/joran/timestamp.xml"; - configure(configFileAsStr); - - String r = loggerContext.getProperty("testTimestamp"); - assertNotNull(r); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM"); - String expected = sdf.format(new Date()); - assertEquals("expected \""+expected+"\" but got "+r, expected, r); - } - -} +/** + * 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.classic.joran; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.junit.Test; +import org.slf4j.MDC; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.turbo.DebugUsersTurboFilter; +import ch.qos.logback.classic.turbo.NOPTurboFilter; +import ch.qos.logback.classic.turbo.TurboFilter; +import ch.qos.logback.classic.util.TeztConstants; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.read.ListAppender; +import ch.qos.logback.core.status.StatusChecker; +import ch.qos.logback.core.testUtil.StringListAppender; + +public class JoranConfiguratorTest { + + LoggerContext loggerContext = new LoggerContext(); + Logger logger = loggerContext.getLogger(this.getClass().getName()); + Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME); + + void configure(String file) throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(loggerContext); + jc.doConfigure(file); + } + + @Test + public void simpleList() throws JoranException { + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/simpleList.xml"); + + Logger logger = loggerContext.getLogger(this.getClass().getName()); + Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME); + ListAppender listAppender = (ListAppender) root.getAppender("LIST"); + assertEquals(0, listAppender.list.size()); + String msg = "hello world"; + logger.debug(msg); + assertEquals(1, listAppender.list.size()); + ILoggingEvent le = (ILoggingEvent) listAppender.list.get(0); + assertEquals(msg, le.getMessage()); + } + + @Test + public void level() throws JoranException { + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/simpleLevel.xml"); + ListAppender listAppender = (ListAppender) root.getAppender("LIST"); + assertEquals(0, listAppender.list.size()); + String msg = "hello world"; + logger.debug(msg); + assertEquals(0, listAppender.list.size()); + } + + @Test + public void rootLoggerLevelSettingBySystemProperty() + throws JoranException { + String propertyName = "logback.level"; + + System.setProperty(propertyName, "INFO"); + configure(TeztConstants.TEST_DIR_PREFIX + + "input/joran/rootLevelByProperty.xml"); + // StatusPrinter.print(loggerContext); + ListAppender listAppender = (ListAppender) root.getAppender("LIST"); + assertEquals(0, listAppender.list.size()); + String msg = "hello world"; + logger.debug(msg); + assertEquals(0, listAppender.list.size()); + System.clearProperty(propertyName); + } + + @Test + public void loggerLevelSettingBySystemProperty() throws JoranException { + String propertyName = "logback.level"; + + System.setProperty(propertyName, "DEBUG"); + configure(TeztConstants.TEST_DIR_PREFIX + + "input/joran/loggerLevelByProperty.xml"); + // StatusPrinter.print(loggerContext); + ListAppender listAppender = (ListAppender) root.getAppender("LIST"); + assertEquals(0, listAppender.list.size()); + String msg = "hello world"; + logger.debug(msg); + assertEquals(1, listAppender.list.size()); + System.clearProperty(propertyName); + } + + @Test + public void statusListener() throws JoranException { + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/statusListener.xml"); + // StatusPrinter.print(loggerContext); + } + + @Test + public void contextRename() throws JoranException { + loggerContext.setName(CoreConstants.DEFAULT_CONTEXT_NAME); + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/contextRename.xml"); + assertEquals("wombat", loggerContext.getName()); + } + + @Test + public void eval() throws JoranException { + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/callerData.xml"); + + String msg = "hello world"; + logger.debug("toto"); + logger.debug(msg); + + StringListAppender slAppender = (StringListAppender) loggerContext + .getLogger("root").getAppender("STR_LIST"); + assertNotNull(slAppender); + assertEquals(2, slAppender.strList.size()); + assertTrue(slAppender.strList.get(0).contains(" DEBUG - toto")); + + String str1 = slAppender.strList.get(1); + assertTrue(str1.contains("Caller+0")); + assertTrue(str1.contains(" DEBUG - hello world")); + } + + @Test + public void turboFilter() throws JoranException { + // Although this test uses turbo filters, it only checks + // that Joran can see the xml element and create + // and place the relevant object correctly. + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/turbo.xml"); + + TurboFilter filter = loggerContext.getTurboFilterList().get(0); + assertTrue(filter instanceof NOPTurboFilter); + } + + @Test + public void testTurboFilterWithStringList() throws JoranException { + // Although this test uses turbo filters, it only checks + // that Joran can see elements, and behave correctly + // that is call the addUser method and pass the correct values + // to that method. + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/turbo2.xml"); + + // StatusPrinter.print(loggerContext.getStatusManager()); + + TurboFilter filter = loggerContext.getTurboFilterList().get(0); + assertTrue(filter instanceof DebugUsersTurboFilter); + DebugUsersTurboFilter dutf = (DebugUsersTurboFilter) filter; + assertEquals(2, dutf.getUsers().size()); + } + + @Test + public void testLevelFilter() throws JoranException { + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/levelFilter.xml"); + + // StatusPrinter.print(loggerContext); + + logger.warn("hello"); + logger.error("to be ignored"); + + @SuppressWarnings("unchecked") + ListAppender listAppender = (ListAppender) root + .getAppender("LIST"); + + assertNotNull(listAppender); + assertEquals(1, listAppender.list.size()); + ILoggingEvent back = listAppender.list.get(0); + assertEquals(Level.WARN, back.getLevel()); + assertEquals("hello", back.getMessage()); + } + + @Test + public void testEvaluatorFilter() throws JoranException { + configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/evaluatorFilter.xml"); + + // StatusPrinter.print(loggerContext); + + logger.warn("hello"); + logger.error("to be ignored"); + + @SuppressWarnings("unchecked") + ListAppender listAppender = (ListAppender) root + .getAppender("LIST"); + + assertNotNull(listAppender); + assertEquals(1, listAppender.list.size()); + ILoggingEvent back = listAppender.list.get(0); + assertEquals(Level.WARN, back.getLevel()); + assertEquals("hello", back.getMessage()); + } + + @Test + public void testTurboDynamicThreshold() throws JoranException { + configure(TeztConstants.TEST_DIR_PREFIX + + "input/joran/turboDynamicThreshold.xml"); + + ListAppender listAppender = (ListAppender) root.getAppender("LIST"); + assertEquals(0, listAppender.list.size()); + + // this one should be denied + MDC.put("userId", "user1"); + logger.debug("hello user1"); + // this one should log + MDC.put("userId", "user2"); + logger.debug("hello user2"); + + assertEquals(1, listAppender.list.size()); + ILoggingEvent le = (ILoggingEvent) listAppender.list.get(0); + assertEquals("hello user2", le.getMessage()); + } + + @Test + public void testTurboDynamicThreshold2() throws JoranException { + configure(TeztConstants.TEST_DIR_PREFIX + + "input/joran/turboDynamicThreshold2.xml"); + + ListAppender listAppender = (ListAppender) root.getAppender("LIST"); + assertEquals(0, listAppender.list.size()); + + // this one should log + MDC.put("userId", "user1"); + logger.debug("hello user1"); + // this one should log + MDC.put("userId", "user2"); + logger.debug("hello user2"); + // this one should fail + MDC.put("userId", "user3"); + logger.debug("hello user3"); + + assertEquals(2, listAppender.list.size()); + ILoggingEvent le = (ILoggingEvent) listAppender.list.get(0); + assertEquals("hello user1", le.getMessage()); + le = (ILoggingEvent) listAppender.list.get(1); + assertEquals("hello user2", le.getMessage()); + } + + // Tests whether ConfigurationAction is installing ReconfigureOnChangeFilter + @Test + public void scan1() throws JoranException, IOException, InterruptedException { + + String configFileAsStr = TeztConstants.TEST_DIR_PREFIX + + "input/joran/scan1.xml"; + configure(configFileAsStr); + + File file = new File(configFileAsStr); + file.setLastModified(System.currentTimeMillis()); + + Thread.sleep(100); + // scanning requires 16 logs + for (int i = 0; i < 16; i++) { + logger.debug("after " + i); + } + + // StatusPrinter.print(loggerContext); + StatusChecker checker = new StatusChecker(loggerContext); + assertTrue(checker.isErrorFree()); + assertTrue(checker.containsMatch("Resetting and reconfiguring context")); + } + + @Test + public void timestamp() throws JoranException, IOException, InterruptedException { + + String configFileAsStr = TeztConstants.TEST_DIR_PREFIX + + "input/joran/timestamp.xml"; + configure(configFileAsStr); + + String r = loggerContext.getProperty("testTimestamp"); + assertNotNull(r); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM"); + String expected = sdf.format(new Date()); + assertEquals("expected \""+expected+"\" but got "+r, expected, r); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/joran/PackageTest.java index cb838cc4ce5ec7cee7429d85ff88e9aacee838fa..5ece1510faaab036fba2e759fa348720e4b9ecb2 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/joran/PackageTest.java @@ -1,24 +1,24 @@ -/** - * 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.classic.joran; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - - -@RunWith(Suite.class) -@SuiteClasses( { JoranConfiguratorTest.class, EvaluatorJoranTest.class}) -public class PackageTest { +/** + * 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.classic.joran; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + + +@RunWith(Suite.class) +@SuiteClasses( { JoranConfiguratorTest.class, EvaluatorJoranTest.class}) +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/Checker.java b/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/Checker.java index 95a2a8f8fa83280cca6e9947dbc05bf30a28441d..ed69d5a747330f9b9b2801a5c9501c48ce5e497e 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/Checker.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/Checker.java @@ -1,92 +1,92 @@ -/** - * 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.classic.multiJVM; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class Checker { - - static long LEN; - static String FILENAME; - - static void usage(String msg) { - System.err.println(msg); - System.err - .println("Usage: java " - + Checker.class.getName() - + " runLength filename stamp0 stamp1 ..\n" - + " runLength (integer) the number of logs to generate perthread\n" - + " filename (string) the filename where to write\n" - + " stamp0 JVM instance stamp0\n" - + " stamp1 JVM instance stamp1\n"); - System.exit(1); - } - - public static void main(String[] argv) throws Exception { - if (argv.length < 3) { - usage("Wrong number of arguments."); - } - - LEN = Integer.parseInt(argv[0]); - FILENAME = argv[1]; - - for (int i = 2; i < argv.length; i++) { - check(argv[i], FILENAME, true); - } - } - - static void check(String stamp, String filename, boolean safetyMode) - throws Exception { - - FileReader fr = new FileReader(FILENAME); - BufferedReader br = new BufferedReader(fr); - - String regExp = "^" + stamp + " DEBUG - " + LoggingThread.msgLong - + " (\\d+)$"; - // System.out.println(regExp); - Pattern p = Pattern.compile(regExp); - - String line; - int expected = 0; - while ((line = br.readLine()) != null) { - // System.out.println(line); - Matcher m = p.matcher(line); - if (m.matches()) { - String g = m.group(1); - int num = Integer.parseInt(g); - if (num != expected) { - System.err.println("ERROR: out of sequence line: "); - System.err.println(line); - return; - } - expected++; - } - } - - if (expected != LEN) { - System.err.println("ERROR: For JVM stamp " + stamp + " found " + expected - + " was expecting " + LEN); - } else { - System.out.println("For JVM stamp " + stamp + " found " + LEN - + " lines in correct sequence"); - } - fr.close(); - br.close(); - - } - -} +/** + * 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.classic.multiJVM; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Checker { + + static long LEN; + static String FILENAME; + + static void usage(String msg) { + System.err.println(msg); + System.err + .println("Usage: java " + + Checker.class.getName() + + " runLength filename stamp0 stamp1 ..\n" + + " runLength (integer) the number of logs to generate perthread\n" + + " filename (string) the filename where to write\n" + + " stamp0 JVM instance stamp0\n" + + " stamp1 JVM instance stamp1\n"); + System.exit(1); + } + + public static void main(String[] argv) throws Exception { + if (argv.length < 3) { + usage("Wrong number of arguments."); + } + + LEN = Integer.parseInt(argv[0]); + FILENAME = argv[1]; + + for (int i = 2; i < argv.length; i++) { + check(argv[i], FILENAME, true); + } + } + + static void check(String stamp, String filename, boolean safetyMode) + throws Exception { + + FileReader fr = new FileReader(FILENAME); + BufferedReader br = new BufferedReader(fr); + + String regExp = "^" + stamp + " DEBUG - " + LoggingThread.msgLong + + " (\\d+)$"; + // System.out.println(regExp); + Pattern p = Pattern.compile(regExp); + + String line; + int expected = 0; + while ((line = br.readLine()) != null) { + // System.out.println(line); + Matcher m = p.matcher(line); + if (m.matches()) { + String g = m.group(1); + int num = Integer.parseInt(g); + if (num != expected) { + System.err.println("ERROR: out of sequence line: "); + System.err.println(line); + return; + } + expected++; + } + } + + if (expected != LEN) { + System.err.println("ERROR: For JVM stamp " + stamp + " found " + expected + + " was expecting " + LEN); + } else { + System.out.println("For JVM stamp " + stamp + " found " + LEN + + " lines in correct sequence"); + } + fr.close(); + br.close(); + + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/FileAppenderPerf.java b/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/FileAppenderPerf.java index 8d30475f383e0db2c2b1a38aa1db3feb7f6899ef..c499534382a0733cd90075cffe52364a8b0c6d39 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/FileAppenderPerf.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/FileAppenderPerf.java @@ -1,99 +1,99 @@ -/** - * 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.classic.multiJVM; - -import org.slf4j.Logger; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.FileAppender; -import ch.qos.logback.core.testUtil.RandomUtil; - -public class FileAppenderPerf { - static String msgLong = "ABCDEGHIJKLMNOPQRSTUVWXYZabcdeghijklmnopqrstuvwxyz1234567890"; - - static long LEN = 100 * 1000; - static int DIFF = RandomUtil.getPositiveInt() % 1000; - static String FILENAME; - - static LoggerContext buildLoggerContext(String filename, boolean safetyMode) { - LoggerContext loggerContext = new LoggerContext(); - - FileAppender fa = new FileAppender(); - - PatternLayout patternLayout = new PatternLayout(); - patternLayout.setPattern("%5p %c - %m%n"); - patternLayout.setContext(loggerContext); - patternLayout.start(); - - fa.setLayout(patternLayout); - fa.setFile(filename); - fa.setAppend(false); - fa.setImmediateFlush(true); - fa.setBufferedIO(false); - fa.setPrudent(safetyMode); - fa.setContext(loggerContext); - fa.start(); - - ch.qos.logback.classic.Logger root = loggerContext - .getLogger(Logger.ROOT_LOGGER_NAME); - root.addAppender(fa); - - return loggerContext; - } - - static void usage(String msg) { - System.err.println(msg); - System.err.println("Usage: java " + FileAppenderPerf.class.getName() - + " filename"); - - System.exit(1); - } - - public static void main(String[] argv) throws Exception { - if (argv.length > 1) { - usage("Wrong number of arguments."); - } - - if (argv.length == 0) { - FILENAME = DIFF+""; - } else { - FILENAME = argv[0]; - } - - perfCase(false); - perfCase(true); - } - - static void perfCase(boolean safetyMode) throws Exception { - LoggerContext lc = buildLoggerContext(FILENAME + "-" + safetyMode + ".log", - safetyMode); - Logger logger = lc.getLogger(FileAppenderPerf.class); - - long start = System.nanoTime(); - for (int i = 0; i < LEN; i++) { - logger.debug(msgLong + " " + i); - } - // in microseconds - double durationPerLog = (System.nanoTime() - start) / (LEN * 1000.0); - - lc.stop(); - - System.out.println("Average duration of " + (durationPerLog) - + " microseconds per log. Prudent mode=" + safetyMode); - System.out.println("------------------------------------------------"); - } - -} +/** + * 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.classic.multiJVM; + +import org.slf4j.Logger; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.testUtil.RandomUtil; + +public class FileAppenderPerf { + static String msgLong = "ABCDEGHIJKLMNOPQRSTUVWXYZabcdeghijklmnopqrstuvwxyz1234567890"; + + static long LEN = 100 * 1000; + static int DIFF = RandomUtil.getPositiveInt() % 1000; + static String FILENAME; + + static LoggerContext buildLoggerContext(String filename, boolean safetyMode) { + LoggerContext loggerContext = new LoggerContext(); + + FileAppender fa = new FileAppender(); + + PatternLayout patternLayout = new PatternLayout(); + patternLayout.setPattern("%5p %c - %m%n"); + patternLayout.setContext(loggerContext); + patternLayout.start(); + + fa.setLayout(patternLayout); + fa.setFile(filename); + fa.setAppend(false); + fa.setImmediateFlush(true); + fa.setBufferedIO(false); + fa.setPrudent(safetyMode); + fa.setContext(loggerContext); + fa.start(); + + ch.qos.logback.classic.Logger root = loggerContext + .getLogger(Logger.ROOT_LOGGER_NAME); + root.addAppender(fa); + + return loggerContext; + } + + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + FileAppenderPerf.class.getName() + + " filename"); + + System.exit(1); + } + + public static void main(String[] argv) throws Exception { + if (argv.length > 1) { + usage("Wrong number of arguments."); + } + + if (argv.length == 0) { + FILENAME = DIFF+""; + } else { + FILENAME = argv[0]; + } + + perfCase(false); + perfCase(true); + } + + static void perfCase(boolean safetyMode) throws Exception { + LoggerContext lc = buildLoggerContext(FILENAME + "-" + safetyMode + ".log", + safetyMode); + Logger logger = lc.getLogger(FileAppenderPerf.class); + + long start = System.nanoTime(); + for (int i = 0; i < LEN; i++) { + logger.debug(msgLong + " " + i); + } + // in microseconds + double durationPerLog = (System.nanoTime() - start) / (LEN * 1000.0); + + lc.stop(); + + System.out.println("Average duration of " + (durationPerLog) + + " microseconds per log. Prudent mode=" + safetyMode); + System.out.println("------------------------------------------------"); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/LoggingThread.java b/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/LoggingThread.java index 4eca19c3c08d6379d09d6e09f3be2003b7575b34..bbb4318424979172e60b6a4c251591e6e0b56d66 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/LoggingThread.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/LoggingThread.java @@ -1,48 +1,48 @@ -/** - * 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.classic.multiJVM; - -import org.slf4j.Logger; - -public class LoggingThread extends Thread { - static String msgLong = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - - final long len; - final Logger logger; - private double durationPerLog; - - public LoggingThread(Logger logger, long len) { - this.logger = logger; - this.len = len; - } - - public void run() { - long before = System.nanoTime(); - for (int i = 0; i < len; i++) { - logger.debug(msgLong + " " + i); -// try { -// Thread.sleep(100); -// } catch (InterruptedException e) { -// } - } - // in microseconds - durationPerLog = (System.nanoTime() - before) / (len * 1000.0); - } - - public double getDurationPerLogInMicroseconds() { - return durationPerLog; - } - - -} +/** + * 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.classic.multiJVM; + +import org.slf4j.Logger; + +public class LoggingThread extends Thread { + static String msgLong = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + + final long len; + final Logger logger; + private double durationPerLog; + + public LoggingThread(Logger logger, long len) { + this.logger = logger; + this.len = len; + } + + public void run() { + long before = System.nanoTime(); + for (int i = 0; i < len; i++) { + logger.debug(msgLong + " " + i); +// try { +// Thread.sleep(100); +// } catch (InterruptedException e) { +// } + } + // in microseconds + durationPerLog = (System.nanoTime() - before) / (len * 1000.0); + } + + public double getDurationPerLogInMicroseconds() { + return durationPerLog; + } + + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/SafeModeFileAppender.java b/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/SafeModeFileAppender.java index dfea6b7886da6a32576d8dd93fffe26938624836..9a029c15f1e133875ebc40e71235b4afbf1f6158 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/SafeModeFileAppender.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/SafeModeFileAppender.java @@ -1,98 +1,98 @@ -/** - * 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.classic.multiJVM; - -import org.slf4j.Logger; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.FileAppender; - -/** - * An application to write to a file using a FileAppender in safe mode. - * - * @author Ceki Gulcu - * - */ -public class SafeModeFileAppender { - - static long LEN; - static String FILENAME; - static String STAMP; - - static public void main(String[] argv) throws Exception { - if (argv.length != 3) { - usage("Wrong number of arguments."); - } - - STAMP = argv[0]; - LEN = Integer.parseInt(argv[1]); - FILENAME = argv[2]; - writeContinously(STAMP, FILENAME, true); - } - - static void usage(String msg) { - System.err.println(msg); - System.err.println("Usage: java " + SafeModeFileAppender.class.getName() - + " stamp runLength filename\n" + " stamp JVM instance stamp\n" - + " runLength (integer) the number of logs to generate perthread" - + " filename (string) the filename where to write\n"); - System.exit(1); - } - - static LoggerContext buildLoggerContext(String stamp, String filename, - boolean safetyMode) { - LoggerContext loggerContext = new LoggerContext(); - - FileAppender fa = new FileAppender(); - - PatternLayout patternLayout = new PatternLayout(); - patternLayout.setPattern(stamp + " %5p - %m%n"); - patternLayout.setContext(loggerContext); - patternLayout.start(); - - fa.setLayout(patternLayout); - fa.setFile(filename); - fa.setAppend(true); - fa.setImmediateFlush(true); - fa.setBufferedIO(false); - fa.setPrudent(safetyMode); - fa.setContext(loggerContext); - fa.start(); - - ch.qos.logback.classic.Logger root = loggerContext - .getLogger(Logger.ROOT_LOGGER_NAME); - root.addAppender(fa); - - return loggerContext; - } - - static void writeContinously(String stamp, String filename, boolean safetyMode) - throws Exception { - LoggerContext lc = buildLoggerContext(stamp, filename, safetyMode); - Logger logger = lc.getLogger(SafeModeFileAppender.class); - - long before = System.nanoTime(); - for (int i = 0; i < LEN; i++) { - logger.debug(LoggingThread.msgLong + " " + i); - } - lc.stop(); - double durationPerLog = (System.nanoTime() - before) / (LEN * 1000.0); - - System.out.println("Average duration of " + (durationPerLog) - + " microseconds per log. Safety mode " + safetyMode); - System.out.println("------------------------------------------------"); - } -} +/** + * 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.classic.multiJVM; + +import org.slf4j.Logger; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.FileAppender; + +/** + * An application to write to a file using a FileAppender in safe mode. + * + * @author Ceki Gulcu + * + */ +public class SafeModeFileAppender { + + static long LEN; + static String FILENAME; + static String STAMP; + + static public void main(String[] argv) throws Exception { + if (argv.length != 3) { + usage("Wrong number of arguments."); + } + + STAMP = argv[0]; + LEN = Integer.parseInt(argv[1]); + FILENAME = argv[2]; + writeContinously(STAMP, FILENAME, true); + } + + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + SafeModeFileAppender.class.getName() + + " stamp runLength filename\n" + " stamp JVM instance stamp\n" + + " runLength (integer) the number of logs to generate perthread" + + " filename (string) the filename where to write\n"); + System.exit(1); + } + + static LoggerContext buildLoggerContext(String stamp, String filename, + boolean safetyMode) { + LoggerContext loggerContext = new LoggerContext(); + + FileAppender fa = new FileAppender(); + + PatternLayout patternLayout = new PatternLayout(); + patternLayout.setPattern(stamp + " %5p - %m%n"); + patternLayout.setContext(loggerContext); + patternLayout.start(); + + fa.setLayout(patternLayout); + fa.setFile(filename); + fa.setAppend(true); + fa.setImmediateFlush(true); + fa.setBufferedIO(false); + fa.setPrudent(safetyMode); + fa.setContext(loggerContext); + fa.start(); + + ch.qos.logback.classic.Logger root = loggerContext + .getLogger(Logger.ROOT_LOGGER_NAME); + root.addAppender(fa); + + return loggerContext; + } + + static void writeContinously(String stamp, String filename, boolean safetyMode) + throws Exception { + LoggerContext lc = buildLoggerContext(stamp, filename, safetyMode); + Logger logger = lc.getLogger(SafeModeFileAppender.class); + + long before = System.nanoTime(); + for (int i = 0; i < LEN; i++) { + logger.debug(LoggingThread.msgLong + " " + i); + } + lc.stop(); + double durationPerLog = (System.nanoTime() - before) / (LEN * 1000.0); + + System.out.println("Average duration of " + (durationPerLog) + + " microseconds per log. Safety mode " + safetyMode); + System.out.println("------------------------------------------------"); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/SafeModeRollingFileAppender.java b/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/SafeModeRollingFileAppender.java index ef260dea3e918853ed5d7e28dd97de73010d78c4..0878bbf4a6f2038a0e5903f6542795ea611ac48f 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/SafeModeRollingFileAppender.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/multiJVM/SafeModeRollingFileAppender.java @@ -1,113 +1,113 @@ -/** - * 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.classic.multiJVM; - -import org.slf4j.Logger; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.rolling.RollingFileAppender; -import ch.qos.logback.core.rolling.TimeBasedRollingPolicy; -import ch.qos.logback.core.util.StatusPrinter; - -/** - * An application to write to a file using a RollingFileAppender in safe mode. - * - * @author Ceki Gulcu - * - */ -public class SafeModeRollingFileAppender { - - static long LEN; - static String FILENAME; - static String STAMP; - - static final String DATE_PATTERN = "yyyy-MM-dd_HH_mm_ss"; - - static public void main(String[] argv) throws Exception { - if (argv.length != 3) { - usage("Wrong number of arguments."); - } - - STAMP = argv[0]; - LEN = Integer.parseInt(argv[1]); - FILENAME = argv[2]; - writeContinously(STAMP, FILENAME, true); - } - - static void usage(String msg) { - System.err.println(msg); - System.err.println("Usage: java " + SafeModeRollingFileAppender.class.getName() - + " stamp runLength filename\n" + " stamp JVM instance stamp\n" - + " runLength (integer) the number of logs to generate perthread" - + " filename (string) the filename where to write\n"); - System.exit(1); - } - - static LoggerContext buildLoggerContext(String stamp, String filename, - boolean safetyMode) { - LoggerContext loggerContext = new LoggerContext(); - - RollingFileAppender rfa = new RollingFileAppender(); - PatternLayout patternLayout = new PatternLayout(); - patternLayout.setPattern(stamp + " %5p - %-50m%n"); - patternLayout.setContext(loggerContext); - patternLayout.start(); - - rfa.setLayout(patternLayout); - - rfa.setAppend(true); - rfa.setImmediateFlush(true); - rfa.setBufferedIO(false); - rfa.setPrudent(safetyMode); - rfa.setContext(loggerContext); - - TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy(); - - tbrp.setContext(loggerContext); - tbrp.setFileNamePattern(filename+"-%d{"+DATE_PATTERN+"}.log"); - tbrp.setParent(rfa); - tbrp.start(); - - rfa.setRollingPolicy(tbrp); - - - rfa.start(); - - ch.qos.logback.classic.Logger root = loggerContext - .getLogger(Logger.ROOT_LOGGER_NAME); - root.addAppender(rfa); - - return loggerContext; - } - - static void writeContinously(String stamp, String filename, boolean safetyMode) - throws Exception { - LoggerContext lc = buildLoggerContext(stamp, filename, safetyMode); - Logger logger = lc.getLogger(SafeModeRollingFileAppender.class); - - long before = System.nanoTime(); - for (int i = 0; i < LEN; i++) { - logger.debug(LoggingThread.msgLong + " " + i); - } - lc.stop(); - StatusPrinter.print(lc); - double durationPerLog = (System.nanoTime() - before) / (LEN * 1000.0); - - System.out.println("Average duration of " + (durationPerLog) - + " microseconds per log. Safety mode " + safetyMode); - System.out.println("------------------------------------------------"); - } -} +/** + * 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.classic.multiJVM; + +import org.slf4j.Logger; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.rolling.RollingFileAppender; +import ch.qos.logback.core.rolling.TimeBasedRollingPolicy; +import ch.qos.logback.core.util.StatusPrinter; + +/** + * An application to write to a file using a RollingFileAppender in safe mode. + * + * @author Ceki Gulcu + * + */ +public class SafeModeRollingFileAppender { + + static long LEN; + static String FILENAME; + static String STAMP; + + static final String DATE_PATTERN = "yyyy-MM-dd_HH_mm_ss"; + + static public void main(String[] argv) throws Exception { + if (argv.length != 3) { + usage("Wrong number of arguments."); + } + + STAMP = argv[0]; + LEN = Integer.parseInt(argv[1]); + FILENAME = argv[2]; + writeContinously(STAMP, FILENAME, true); + } + + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + SafeModeRollingFileAppender.class.getName() + + " stamp runLength filename\n" + " stamp JVM instance stamp\n" + + " runLength (integer) the number of logs to generate perthread" + + " filename (string) the filename where to write\n"); + System.exit(1); + } + + static LoggerContext buildLoggerContext(String stamp, String filename, + boolean safetyMode) { + LoggerContext loggerContext = new LoggerContext(); + + RollingFileAppender rfa = new RollingFileAppender(); + PatternLayout patternLayout = new PatternLayout(); + patternLayout.setPattern(stamp + " %5p - %-50m%n"); + patternLayout.setContext(loggerContext); + patternLayout.start(); + + rfa.setLayout(patternLayout); + + rfa.setAppend(true); + rfa.setImmediateFlush(true); + rfa.setBufferedIO(false); + rfa.setPrudent(safetyMode); + rfa.setContext(loggerContext); + + TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy(); + + tbrp.setContext(loggerContext); + tbrp.setFileNamePattern(filename+"-%d{"+DATE_PATTERN+"}.log"); + tbrp.setParent(rfa); + tbrp.start(); + + rfa.setRollingPolicy(tbrp); + + + rfa.start(); + + ch.qos.logback.classic.Logger root = loggerContext + .getLogger(Logger.ROOT_LOGGER_NAME); + root.addAppender(rfa); + + return loggerContext; + } + + static void writeContinously(String stamp, String filename, boolean safetyMode) + throws Exception { + LoggerContext lc = buildLoggerContext(stamp, filename, safetyMode); + Logger logger = lc.getLogger(SafeModeRollingFileAppender.class); + + long before = System.nanoTime(); + for (int i = 0; i < LEN; i++) { + logger.debug(LoggingThread.msgLong + " " + i); + } + lc.stop(); + StatusPrinter.print(lc); + double durationPerLog = (System.nanoTime() - before) / (LEN * 1000.0); + + System.out.println("Average duration of " + (durationPerLog) + + " microseconds per log. Safety mode " + safetyMode); + System.out.println("------------------------------------------------"); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/CounterBasedEvaluator.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/CounterBasedEvaluator.java index 6b1617e5f94416a2f8192f6d1644158bcd268be9..52a7b93daad582fd96b089cbd2a39511aeb33da8 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/CounterBasedEvaluator.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/CounterBasedEvaluator.java @@ -1,75 +1,75 @@ -/** - * 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.classic.net; - -import ch.qos.logback.core.boolex.EvaluationException; -import ch.qos.logback.core.boolex.EventEvaluator; -import ch.qos.logback.core.spi.ContextAwareBase; - -/** - * A simple EventEvaluator implementation that triggers email transmission after - * a given number of events occur, regardless of event level. - * - *

By default, the limit is 1024. - */ -public class CounterBasedEvaluator extends ContextAwareBase implements EventEvaluator { - - static int DEFAULT_LIMIT = 1024; - int limit = DEFAULT_LIMIT; - int counter = 0; - String name; - boolean started; - - public boolean evaluate(Object event) throws NullPointerException, - EvaluationException { - counter++; - - if (counter == limit) { - counter = 0; - return true; - } else { - return false; - } - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public boolean isStarted() { - return started; - } - - public void start() { - started = true; - } - - public void stop() { - started = false; - } - - public int getLimit() { - return limit; - } - - public void setLimit(int limit) { - this.limit = limit; - } - - -} +/** + * 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.classic.net; + +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.spi.ContextAwareBase; + +/** + * A simple EventEvaluator implementation that triggers email transmission after + * a given number of events occur, regardless of event level. + * + *

By default, the limit is 1024. + */ +public class CounterBasedEvaluator extends ContextAwareBase implements EventEvaluator { + + static int DEFAULT_LIMIT = 1024; + int limit = DEFAULT_LIMIT; + int counter = 0; + String name; + boolean started; + + public boolean evaluate(Object event) throws NullPointerException, + EvaluationException { + counter++; + + if (counter == limit) { + counter = 0; + return true; + } else { + return false; + } + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isStarted() { + return started; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + + public int getLimit() { + return limit; + } + + public void setLimit(int limit) { + this.limit = limit; + } + + +} 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 701577665ef1e418a4ab82814ef6b0ba9b6fb575..3e605fc923e0374b08f90aa8f0febcf56f6b0605 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 @@ -1,129 +1,129 @@ -/** - * 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.classic.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import javax.mail.Address; -import javax.mail.MessagingException; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.core.Layout; - -public class DilutedSMTPAppenderTest { - - SMTPAppender appender; - - @Before - public void setUp() throws Exception { - LoggerContext lc = new LoggerContext(); - appender = new SMTPAppender(); - appender.setContext(lc); - appender.setName("smtp"); - appender.setFrom("user@host.dom"); - appender.setLayout(buildLayout(lc)); - appender.setSMTPHost("mail2.qos.ch"); - appender.setSubject("logging report"); - appender.addTo("sebastien.nospam@qos.ch"); - appender.start(); - } - - private static Layout buildLayout(LoggerContext lc) { - PatternLayout layout = new PatternLayout(); - layout.setContext(lc); - layout.setFileHeader("Some header\n"); - layout.setPattern("%-4relative [%thread] %-5level %class - %msg%n"); - layout.setFileFooter("Some footer"); - layout.start(); - return layout; - } - - @After - public void tearDown() throws Exception { - appender = null; - } - - @Test - public void testStart() { - try { - Address[] addressArray = appender.getMessage().getFrom(); - Address address = addressArray[0]; - assertEquals("user@host.dom", address.toString()); - - addressArray = null; - address = null; - - addressArray = appender.getMessage().getAllRecipients(); - address = addressArray[0]; - assertEquals("sebastien.nospam@qos.ch", address.toString()); - - assertEquals("logging report", appender.getSubject()); - - assertTrue(appender.isStarted()); - - } catch (MessagingException ex) { - fail("Unexpected exception."); - } - } - - @Test - public void testAppendNonTriggeringEvent() { - LoggingEvent event = new LoggingEvent(); - event.setThreadName("thead name"); - event.setLevel(Level.DEBUG); - appender.subAppend(event); - assertEquals(1, appender.cb.length()); - } - - @Test - public void testEntryConditionsCheck() { - appender.checkEntryConditions(); - assertEquals(0, appender.getContext().getStatusManager().getCount()); - } - - @Test - public void testEntryConditionsCheckNoMessage() { - appender.setMessage(null); - appender.checkEntryConditions(); - assertEquals(1, appender.getContext().getStatusManager().getCount()); - } - - @Test - public void testTriggeringPolicy() { - appender.setEvaluator(null); - appender.checkEntryConditions(); - assertEquals(1, appender.getContext().getStatusManager().getCount()); - } - - @Test - public void testEntryConditionsCheckNoLayout() { - appender.setLayout(null); - appender.checkEntryConditions(); - assertEquals(1, appender.getContext().getStatusManager().getCount()); - } - - - - -} +/** + * 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.classic.net; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import javax.mail.Address; +import javax.mail.MessagingException; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.Layout; + +public class DilutedSMTPAppenderTest { + + SMTPAppender appender; + + @Before + public void setUp() throws Exception { + LoggerContext lc = new LoggerContext(); + appender = new SMTPAppender(); + appender.setContext(lc); + appender.setName("smtp"); + appender.setFrom("user@host.dom"); + appender.setLayout(buildLayout(lc)); + appender.setSMTPHost("mail2.qos.ch"); + appender.setSubject("logging report"); + appender.addTo("sebastien.nospam@qos.ch"); + appender.start(); + } + + private static Layout buildLayout(LoggerContext lc) { + PatternLayout layout = new PatternLayout(); + layout.setContext(lc); + layout.setFileHeader("Some header\n"); + layout.setPattern("%-4relative [%thread] %-5level %class - %msg%n"); + layout.setFileFooter("Some footer"); + layout.start(); + return layout; + } + + @After + public void tearDown() throws Exception { + appender = null; + } + + @Test + public void testStart() { + try { + Address[] addressArray = appender.getMessage().getFrom(); + Address address = addressArray[0]; + assertEquals("user@host.dom", address.toString()); + + addressArray = null; + address = null; + + addressArray = appender.getMessage().getAllRecipients(); + address = addressArray[0]; + assertEquals("sebastien.nospam@qos.ch", address.toString()); + + assertEquals("logging report", appender.getSubject()); + + assertTrue(appender.isStarted()); + + } catch (MessagingException ex) { + fail("Unexpected exception."); + } + } + + @Test + public void testAppendNonTriggeringEvent() { + LoggingEvent event = new LoggingEvent(); + event.setThreadName("thead name"); + event.setLevel(Level.DEBUG); + appender.subAppend(event); + assertEquals(1, appender.cb.length()); + } + + @Test + public void testEntryConditionsCheck() { + appender.checkEntryConditions(); + assertEquals(0, appender.getContext().getStatusManager().getCount()); + } + + @Test + public void testEntryConditionsCheckNoMessage() { + appender.setMessage(null); + appender.checkEntryConditions(); + assertEquals(1, appender.getContext().getStatusManager().getCount()); + } + + @Test + public void testTriggeringPolicy() { + appender.setEvaluator(null); + appender.checkEntryConditions(); + assertEquals(1, appender.getContext().getStatusManager().getCount()); + } + + @Test + public void testEntryConditionsCheckNoLayout() { + appender.setLayout(null); + appender.checkEntryConditions(); + assertEquals(1, appender.getContext().getStatusManager().getCount()); + } + + + + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/ExternalMockSocketServer.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/ExternalMockSocketServer.java index ae8a6ee6a7eec00b7444dafcf8ac622c0aded970..fb287c5b191b923b14ce9da749e12e925ddc1a04 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/ExternalMockSocketServer.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/ExternalMockSocketServer.java @@ -1,93 +1,93 @@ -/** - * 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.classic.net; - -import java.io.InputStream; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.ArrayList; -import java.util.List; - -public class ExternalMockSocketServer { - - static final String LOGGINGEVENT = "LoggingEvent"; - static final String LOGGINGEVENT2 = "LoggingEvent2"; - static final String MINIMALEXT = "MinimalExt"; - static final String MINIMALSER = "MinimalSer"; - - static final int PORT = 4560; - - //static int loopLen; - static int clientNumber; - - static List msgList = new ArrayList(); - static boolean finished = false; - - String className = LOGGINGEVENT; - - public static void main(String[] args) { - if (args.length == 1) { - clientNumber = Integer.parseInt(args[0]); - //loopLen = Integer.parseInt((args[1])); - runServer(); - } else { - usage("Wrong number of arguments."); - } - } - - static void usage(String msg) { - System.err.println(msg); - System.err - .println("Usage: java " + ExternalMockSocketServer.class.getName() - + " loopNumber"); - System.exit(1); - } - - static void runServer() { - - try { - System.out.println("Starting Server..."); - ServerSocket serverSocket = new ServerSocket(PORT); - System.out.println("Listening on port " + PORT); - for (int j = 0; j < clientNumber; j++) { - Socket socket = serverSocket.accept(); - System.out.println("New client accepted."); - System.out.println("Connected to client at " + socket.getInetAddress()); - - InputStream is = socket.getInputStream(); - long sum = 0; - - while (true) { - // this call is blocking - int val = is.read(); - if(val == -1) { - break; - } - // if a byte is available, we skip it. - // this allows to pass all available bytes in a quick manner. - int a = is.available(); - sum += a + 1; - is.skip(a); - } - System.out.println(sum/1000 + " KB"); - } - serverSocket.close(); - } catch (Exception se) { - se.printStackTrace(); - } - System.out.println("Server finished."); - finished = true; - } - -} +/** + * 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.classic.net; + +import java.io.InputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; + +public class ExternalMockSocketServer { + + static final String LOGGINGEVENT = "LoggingEvent"; + static final String LOGGINGEVENT2 = "LoggingEvent2"; + static final String MINIMALEXT = "MinimalExt"; + static final String MINIMALSER = "MinimalSer"; + + static final int PORT = 4560; + + //static int loopLen; + static int clientNumber; + + static List msgList = new ArrayList(); + static boolean finished = false; + + String className = LOGGINGEVENT; + + public static void main(String[] args) { + if (args.length == 1) { + clientNumber = Integer.parseInt(args[0]); + //loopLen = Integer.parseInt((args[1])); + runServer(); + } else { + usage("Wrong number of arguments."); + } + } + + static void usage(String msg) { + System.err.println(msg); + System.err + .println("Usage: java " + ExternalMockSocketServer.class.getName() + + " loopNumber"); + System.exit(1); + } + + static void runServer() { + + try { + System.out.println("Starting Server..."); + ServerSocket serverSocket = new ServerSocket(PORT); + System.out.println("Listening on port " + PORT); + for (int j = 0; j < clientNumber; j++) { + Socket socket = serverSocket.accept(); + System.out.println("New client accepted."); + System.out.println("Connected to client at " + socket.getInetAddress()); + + InputStream is = socket.getInputStream(); + long sum = 0; + + while (true) { + // this call is blocking + int val = is.read(); + if(val == -1) { + break; + } + // if a byte is available, we skip it. + // this allows to pass all available bytes in a quick manner. + int a = is.available(); + sum += a + 1; + is.skip(a); + } + System.out.println(sum/1000 + " KB"); + } + serverSocket.close(); + } catch (Exception se) { + se.printStackTrace(); + } + System.out.println("Server finished."); + finished = true; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSQueueAppenderTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSQueueAppenderTest.java index 64f6db9e7711fe593dc28f85f1b694c0ebab92b9..9910bfe997d0bf8ba5b7aa63219b165e733c8437 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSQueueAppenderTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSQueueAppenderTest.java @@ -1,143 +1,143 @@ -/** - * 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.classic.net; - -import java.io.Serializable; - -import javax.jms.ObjectMessage; - -import junit.framework.TestCase; -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.net.mock.MockQueue; -import ch.qos.logback.classic.net.mock.MockQueueConnectionFactory; -import ch.qos.logback.classic.net.mock.MockQueueSender; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.classic.util.MockInitialContext; -import ch.qos.logback.classic.util.MockInitialContextFactory; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.spi.PreSerializationTransformer; - -public class JMSQueueAppenderTest extends TestCase { - - ch.qos.logback.core.Context context; - JMSQueueAppender appender; - PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); - - @Override - protected void setUp() throws Exception { - context = new ContextBase(); - appender = new JMSQueueAppender(); - appender.setContext(context); - appender.setName("jmsQueue"); - appender.qcfBindingName = "queueCnxFactory"; - appender.queueBindingName = "testQueue"; - appender.setProviderURL("url"); - appender.setInitialContextFactoryName(MockInitialContextFactory.class.getName()); - - MockInitialContext mic = MockInitialContextFactory.getContext(); - mic.map.put(appender.qcfBindingName, new MockQueueConnectionFactory()); - mic.map.put(appender.queueBindingName, new MockQueue(appender.queueBindingName)); - - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - appender = null; - context = null; - super.tearDown(); - } - - public void testAppendOk() { - appender.start(); - - ILoggingEvent le = createLoggingEvent(); - appender.append(le); - - MockQueueSender qs = (MockQueueSender)appender.queueSender; - assertEquals(1, qs.getMessageList().size()); - ObjectMessage message = (ObjectMessage) qs.getMessageList().get(0); - try { - Serializable witness = pst.transform(le); - assertEquals(witness, message.getObject()); - } catch (Exception e) { - fail(); - } - } - - public void testAppendFailure() { - appender.start(); - - //make sure the append method does not work - appender.queueSender = null; - - ILoggingEvent le = createLoggingEvent(); - for (int i = 1; i <= 3; i++) { - appender.append(le); - assertEquals(i, context.getStatusManager().getCount()); - assertTrue(appender.isStarted()); - } - appender.append(le); - assertEquals(4, context.getStatusManager().getCount()); - assertFalse(appender.isStarted()); - } - - public void testStartMinimalInfo() { - //let's leave only what's in the setup() - //method, minus the providerURL - appender.setProviderURL(null); - appender.start(); - - assertTrue(appender.isStarted()); - - try { - assertEquals(appender.queueBindingName, appender.queueSender.getQueue().getQueueName()); - } catch (Exception e) { - fail(); - } - } - - public void testStartUserPass() { - appender.setUserName("test"); - appender.setPassword("test"); - - appender.start(); - - assertTrue(appender.isStarted()); - - try { - assertEquals(appender.queueBindingName, appender.queueSender.getQueue().getQueueName()); - } catch (Exception e) { - fail(); - } - } - - public void testStartFails() { - appender.queueBindingName = null; - - appender.start(); - - assertFalse(appender.isStarted()); - } - - private ILoggingEvent createLoggingEvent() { - LoggingEvent le = new LoggingEvent(); - le.setLevel(Level.DEBUG); - le.setMessage("test message"); - le.setTimeStamp(System.currentTimeMillis()); - le.setThreadName(Thread.currentThread().getName()); - return le; - } -} +/** + * 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.classic.net; + +import java.io.Serializable; + +import javax.jms.ObjectMessage; + +import junit.framework.TestCase; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.net.mock.MockQueue; +import ch.qos.logback.classic.net.mock.MockQueueConnectionFactory; +import ch.qos.logback.classic.net.mock.MockQueueSender; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.classic.util.MockInitialContext; +import ch.qos.logback.classic.util.MockInitialContextFactory; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.spi.PreSerializationTransformer; + +public class JMSQueueAppenderTest extends TestCase { + + ch.qos.logback.core.Context context; + JMSQueueAppender appender; + PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); + + @Override + protected void setUp() throws Exception { + context = new ContextBase(); + appender = new JMSQueueAppender(); + appender.setContext(context); + appender.setName("jmsQueue"); + appender.qcfBindingName = "queueCnxFactory"; + appender.queueBindingName = "testQueue"; + appender.setProviderURL("url"); + appender.setInitialContextFactoryName(MockInitialContextFactory.class.getName()); + + MockInitialContext mic = MockInitialContextFactory.getContext(); + mic.map.put(appender.qcfBindingName, new MockQueueConnectionFactory()); + mic.map.put(appender.queueBindingName, new MockQueue(appender.queueBindingName)); + + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + appender = null; + context = null; + super.tearDown(); + } + + public void testAppendOk() { + appender.start(); + + ILoggingEvent le = createLoggingEvent(); + appender.append(le); + + MockQueueSender qs = (MockQueueSender)appender.queueSender; + assertEquals(1, qs.getMessageList().size()); + ObjectMessage message = (ObjectMessage) qs.getMessageList().get(0); + try { + Serializable witness = pst.transform(le); + assertEquals(witness, message.getObject()); + } catch (Exception e) { + fail(); + } + } + + public void testAppendFailure() { + appender.start(); + + //make sure the append method does not work + appender.queueSender = null; + + ILoggingEvent le = createLoggingEvent(); + for (int i = 1; i <= 3; i++) { + appender.append(le); + assertEquals(i, context.getStatusManager().getCount()); + assertTrue(appender.isStarted()); + } + appender.append(le); + assertEquals(4, context.getStatusManager().getCount()); + assertFalse(appender.isStarted()); + } + + public void testStartMinimalInfo() { + //let's leave only what's in the setup() + //method, minus the providerURL + appender.setProviderURL(null); + appender.start(); + + assertTrue(appender.isStarted()); + + try { + assertEquals(appender.queueBindingName, appender.queueSender.getQueue().getQueueName()); + } catch (Exception e) { + fail(); + } + } + + public void testStartUserPass() { + appender.setUserName("test"); + appender.setPassword("test"); + + appender.start(); + + assertTrue(appender.isStarted()); + + try { + assertEquals(appender.queueBindingName, appender.queueSender.getQueue().getQueueName()); + } catch (Exception e) { + fail(); + } + } + + public void testStartFails() { + appender.queueBindingName = null; + + appender.start(); + + assertFalse(appender.isStarted()); + } + + private ILoggingEvent createLoggingEvent() { + LoggingEvent le = new LoggingEvent(); + le.setLevel(Level.DEBUG); + le.setMessage("test message"); + le.setTimeStamp(System.currentTimeMillis()); + le.setThreadName(Thread.currentThread().getName()); + return le; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSQueueAppenderTestApp.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSQueueAppenderTestApp.java index 80d07691fa1250286e0a76cdd67804b4e874f5df..88563b8b244bb83fe2ade6eae46ae87110106c5a 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSQueueAppenderTestApp.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSQueueAppenderTestApp.java @@ -1,61 +1,61 @@ -/** - * 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.classic.net; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.util.StatusPrinter; - -public class JMSQueueAppenderTestApp { - - public static void main(String[] args) { - Logger logger = (Logger)LoggerFactory.getLogger(JMSTopicAppenderTestApp.class); - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - lc.reset(); - - JMSQueueAppender appender = new JMSQueueAppender(); - appender.setContext(lc); - appender.setName("jmsQueue"); - appender.setInitialContextFactoryName("org.apache.activemq.jndi.ActiveMQInitialContextFactory"); - //appender.setPassword(""); - appender.setProviderURL("tcp://localhost:61616"); - //appender.setSecurityCredentials(""); - //appender.setSecurityPrincipalName(""); - appender.setQueueBindingName("MyQueue"); - appender.setQueueConnectionFactoryBindingName("ConnectionFactory"); - //appender.setURLPkgPrefixes(""); - //appender.setUserName(""); - - appender.start(); - logger.addAppender(appender); - - //JIT - for (int i = 0; i < 10000; i++) { - logger.debug("** Hello world. n=" + i); - } - - long before = System.nanoTime(); - for (int i = 0; i < 10000; i++) { - logger.debug("** Hello world. n=" + i); - } - long after = System.nanoTime(); - - System.out.println("Time per logs for 10'000 logs: " + (after-before)/10000); - - StatusPrinter.print(lc.getStatusManager()); - } - +/** + * 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.classic.net; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.util.StatusPrinter; + +public class JMSQueueAppenderTestApp { + + public static void main(String[] args) { + Logger logger = (Logger)LoggerFactory.getLogger(JMSTopicAppenderTestApp.class); + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + lc.reset(); + + JMSQueueAppender appender = new JMSQueueAppender(); + appender.setContext(lc); + appender.setName("jmsQueue"); + appender.setInitialContextFactoryName("org.apache.activemq.jndi.ActiveMQInitialContextFactory"); + //appender.setPassword(""); + appender.setProviderURL("tcp://localhost:61616"); + //appender.setSecurityCredentials(""); + //appender.setSecurityPrincipalName(""); + appender.setQueueBindingName("MyQueue"); + appender.setQueueConnectionFactoryBindingName("ConnectionFactory"); + //appender.setURLPkgPrefixes(""); + //appender.setUserName(""); + + appender.start(); + logger.addAppender(appender); + + //JIT + for (int i = 0; i < 10000; i++) { + logger.debug("** Hello world. n=" + i); + } + + long before = System.nanoTime(); + for (int i = 0; i < 10000; i++) { + logger.debug("** Hello world. n=" + i); + } + long after = System.nanoTime(); + + System.out.println("Time per logs for 10'000 logs: " + (after-before)/10000); + + StatusPrinter.print(lc.getStatusManager()); + } + } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSTopicAppenderTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSTopicAppenderTest.java index efe2595de052c8b176f4dc8614b9f824bd280ff0..4a7346dd56ee9e8861deea43bfc85a5041437d89 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSTopicAppenderTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSTopicAppenderTest.java @@ -1,248 +1,248 @@ -/** - * 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.classic.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.Serializable; -import java.util.Properties; - -import javax.jms.ObjectMessage; -import javax.naming.Context; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.net.mock.MockTopic; -import ch.qos.logback.classic.net.mock.MockTopicConnectionFactory; -import ch.qos.logback.classic.net.mock.MockTopicPublisher; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.classic.util.MockInitialContext; -import ch.qos.logback.classic.util.MockInitialContextFactory; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.spi.PreSerializationTransformer; - -public class JMSTopicAppenderTest { - - ch.qos.logback.core.Context context; - JMSTopicAppender appender; - PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); - - - @Before - public void setUp() throws Exception { - context = new ContextBase(); - appender = new JMSTopicAppender(); - appender.setContext(context); - appender.setName("jmsTopic"); - appender.tcfBindingName = "topicCnxFactory"; - appender.topicBindingName = "testTopic"; - appender.setProviderURL("url"); - appender.setInitialContextFactoryName(MockInitialContextFactory.class.getName()); - - MockInitialContext mic = MockInitialContextFactory.getContext(); - mic.map.put(appender.tcfBindingName, new MockTopicConnectionFactory()); - mic.map.put(appender.topicBindingName, new MockTopic(appender.topicBindingName)); - - } - - - @After - public void tearDown() throws Exception { - appender = null; - context = null; - } - - @Test - public void testAppendOk() { - appender.start(); - - ILoggingEvent le = createLoggingEvent(); - appender.append(le); - - MockTopicPublisher tp = (MockTopicPublisher)appender.topicPublisher; - assertEquals(1, tp.getMessageList().size()); - ObjectMessage message = (ObjectMessage) tp.getMessageList().get(0); - try { - Serializable witness = pst.transform(le); - assertEquals(witness, message.getObject()); - } catch (Exception e) { - fail(); - } - } - - @Test - public void testAppendFailure() { - appender.start(); - - //make sure the append method does not work - appender.topicPublisher = null; - - ILoggingEvent le = createLoggingEvent(); - for (int i = 1; i <= 3; i++) { - appender.append(le); - assertEquals(i, context.getStatusManager().getCount()); - assertTrue(appender.isStarted()); - } - appender.append(le); - assertEquals(4, context.getStatusManager().getCount()); - assertFalse(appender.isStarted()); - } - - @Test - public void testBuildEnvProperties() { - appender.setInitialContextFactoryName("icfn"); - appender.setProviderURL("url"); - appender.setURLPkgPrefixes("pkgPref"); - appender.setSecurityPrincipalName("user"); - appender.setSecurityCredentials("cred"); - - Properties props = appender.buildEnvProperties(); - assertEquals(5, props.size()); - assertEquals(appender.getInitialContextFactoryName(), props - .getProperty(Context.INITIAL_CONTEXT_FACTORY)); - assertEquals(appender.getProviderURL(), props.getProperty(Context.PROVIDER_URL)); - assertEquals(appender.getURLPkgPrefixes(), props - .getProperty(Context.URL_PKG_PREFIXES)); - assertEquals(appender.getSecurityPrincipalName(), props - .getProperty(Context.SECURITY_PRINCIPAL)); - assertEquals(appender.getSecurityCredentials(), props - .getProperty(Context.SECURITY_CREDENTIALS)); - } - - @Test - public void testBuildEnvPropertiesWithNullProviderURL() { - appender.setInitialContextFactoryName("icfn"); - appender.setProviderURL(null); - appender.setURLPkgPrefixes("pkgPref"); - appender.setSecurityPrincipalName("user"); - appender.setSecurityCredentials("cred"); - - Properties props = appender.buildEnvProperties(); - assertEquals(4, props.size()); - assertEquals(appender.getInitialContextFactoryName(), props - .getProperty(Context.INITIAL_CONTEXT_FACTORY)); - assertEquals(null, props.getProperty(Context.PROVIDER_URL)); - assertEquals(appender.getURLPkgPrefixes(), props - .getProperty(Context.URL_PKG_PREFIXES)); - assertEquals(appender.getSecurityPrincipalName(), props - .getProperty(Context.SECURITY_PRINCIPAL)); - assertEquals(appender.getSecurityCredentials(), props - .getProperty(Context.SECURITY_CREDENTIALS)); - - assertEquals(1, context.getStatusManager().getCount()); - } - - @Test - public void testBuildEnvPropertiesWithNullCredentials() { - appender.setInitialContextFactoryName("icfn"); - appender.setProviderURL("url"); - appender.setURLPkgPrefixes("pkgPref"); - appender.setSecurityPrincipalName("user"); - appender.setSecurityCredentials(null); - - Properties props = appender.buildEnvProperties(); - assertEquals(4, props.size()); - assertEquals(appender.getInitialContextFactoryName(), props - .getProperty(Context.INITIAL_CONTEXT_FACTORY)); - assertEquals(appender.getProviderURL(), props.getProperty(Context.PROVIDER_URL)); - assertEquals(appender.getURLPkgPrefixes(), props - .getProperty(Context.URL_PKG_PREFIXES)); - assertEquals(appender.getSecurityPrincipalName(), props - .getProperty(Context.SECURITY_PRINCIPAL)); - assertEquals(null, props - .getProperty(Context.SECURITY_CREDENTIALS)); - - assertEquals(1, context.getStatusManager().getCount()); - } - - @Test - public void testBuildEnvPropertiesWithPkgNull() { - appender.setInitialContextFactoryName("icfn"); - appender.setProviderURL("url"); - appender.setURLPkgPrefixes(null); - appender.setSecurityPrincipalName("user"); - appender.setSecurityCredentials("cred"); - - Properties props = appender.buildEnvProperties(); - assertEquals(4, props.size()); - assertEquals(appender.getInitialContextFactoryName(), props - .getProperty(Context.INITIAL_CONTEXT_FACTORY)); - assertEquals(appender.getProviderURL(), props.getProperty(Context.PROVIDER_URL)); - assertEquals(null, props - .getProperty(Context.URL_PKG_PREFIXES)); - assertEquals(appender.getSecurityPrincipalName(), props - .getProperty(Context.SECURITY_PRINCIPAL)); - assertEquals(appender.getSecurityCredentials(), props - .getProperty(Context.SECURITY_CREDENTIALS)); - - assertEquals(0, context.getStatusManager().getCount()); - } - - @Test - public void testStartMinimalInfo() { - //let's leave only what's in the setup() - //method, minus the providerURL - appender.setProviderURL(null); - appender.start(); - - assertTrue(appender.isStarted()); - - try { - assertEquals(appender.topicBindingName, appender.topicPublisher.getTopic().getTopicName()); - } catch (Exception e) { - fail(); - } - } - - @Test - public void testStartUserPass() { - appender.setUserName("test"); - appender.setPassword("test"); - - appender.start(); - - assertTrue(appender.isStarted()); - - try { - assertEquals(appender.topicBindingName, appender.topicPublisher.getTopic().getTopicName()); - } catch (Exception e) { - fail(); - } - } - - @Test - public void testStartFails() { - appender.topicBindingName = null; - - appender.start(); - - assertFalse(appender.isStarted()); - } - - private ILoggingEvent createLoggingEvent() { - LoggingEvent le = new LoggingEvent(); - le.setLevel(Level.DEBUG); - le.setMessage("test message"); - le.setTimeStamp(System.currentTimeMillis()); - le.setThreadName(Thread.currentThread().getName()); - return le; - } -} +/** + * 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.classic.net; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.Serializable; +import java.util.Properties; + +import javax.jms.ObjectMessage; +import javax.naming.Context; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.net.mock.MockTopic; +import ch.qos.logback.classic.net.mock.MockTopicConnectionFactory; +import ch.qos.logback.classic.net.mock.MockTopicPublisher; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.classic.util.MockInitialContext; +import ch.qos.logback.classic.util.MockInitialContextFactory; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.spi.PreSerializationTransformer; + +public class JMSTopicAppenderTest { + + ch.qos.logback.core.Context context; + JMSTopicAppender appender; + PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); + + + @Before + public void setUp() throws Exception { + context = new ContextBase(); + appender = new JMSTopicAppender(); + appender.setContext(context); + appender.setName("jmsTopic"); + appender.tcfBindingName = "topicCnxFactory"; + appender.topicBindingName = "testTopic"; + appender.setProviderURL("url"); + appender.setInitialContextFactoryName(MockInitialContextFactory.class.getName()); + + MockInitialContext mic = MockInitialContextFactory.getContext(); + mic.map.put(appender.tcfBindingName, new MockTopicConnectionFactory()); + mic.map.put(appender.topicBindingName, new MockTopic(appender.topicBindingName)); + + } + + + @After + public void tearDown() throws Exception { + appender = null; + context = null; + } + + @Test + public void testAppendOk() { + appender.start(); + + ILoggingEvent le = createLoggingEvent(); + appender.append(le); + + MockTopicPublisher tp = (MockTopicPublisher)appender.topicPublisher; + assertEquals(1, tp.getMessageList().size()); + ObjectMessage message = (ObjectMessage) tp.getMessageList().get(0); + try { + Serializable witness = pst.transform(le); + assertEquals(witness, message.getObject()); + } catch (Exception e) { + fail(); + } + } + + @Test + public void testAppendFailure() { + appender.start(); + + //make sure the append method does not work + appender.topicPublisher = null; + + ILoggingEvent le = createLoggingEvent(); + for (int i = 1; i <= 3; i++) { + appender.append(le); + assertEquals(i, context.getStatusManager().getCount()); + assertTrue(appender.isStarted()); + } + appender.append(le); + assertEquals(4, context.getStatusManager().getCount()); + assertFalse(appender.isStarted()); + } + + @Test + public void testBuildEnvProperties() { + appender.setInitialContextFactoryName("icfn"); + appender.setProviderURL("url"); + appender.setURLPkgPrefixes("pkgPref"); + appender.setSecurityPrincipalName("user"); + appender.setSecurityCredentials("cred"); + + Properties props = appender.buildEnvProperties(); + assertEquals(5, props.size()); + assertEquals(appender.getInitialContextFactoryName(), props + .getProperty(Context.INITIAL_CONTEXT_FACTORY)); + assertEquals(appender.getProviderURL(), props.getProperty(Context.PROVIDER_URL)); + assertEquals(appender.getURLPkgPrefixes(), props + .getProperty(Context.URL_PKG_PREFIXES)); + assertEquals(appender.getSecurityPrincipalName(), props + .getProperty(Context.SECURITY_PRINCIPAL)); + assertEquals(appender.getSecurityCredentials(), props + .getProperty(Context.SECURITY_CREDENTIALS)); + } + + @Test + public void testBuildEnvPropertiesWithNullProviderURL() { + appender.setInitialContextFactoryName("icfn"); + appender.setProviderURL(null); + appender.setURLPkgPrefixes("pkgPref"); + appender.setSecurityPrincipalName("user"); + appender.setSecurityCredentials("cred"); + + Properties props = appender.buildEnvProperties(); + assertEquals(4, props.size()); + assertEquals(appender.getInitialContextFactoryName(), props + .getProperty(Context.INITIAL_CONTEXT_FACTORY)); + assertEquals(null, props.getProperty(Context.PROVIDER_URL)); + assertEquals(appender.getURLPkgPrefixes(), props + .getProperty(Context.URL_PKG_PREFIXES)); + assertEquals(appender.getSecurityPrincipalName(), props + .getProperty(Context.SECURITY_PRINCIPAL)); + assertEquals(appender.getSecurityCredentials(), props + .getProperty(Context.SECURITY_CREDENTIALS)); + + assertEquals(1, context.getStatusManager().getCount()); + } + + @Test + public void testBuildEnvPropertiesWithNullCredentials() { + appender.setInitialContextFactoryName("icfn"); + appender.setProviderURL("url"); + appender.setURLPkgPrefixes("pkgPref"); + appender.setSecurityPrincipalName("user"); + appender.setSecurityCredentials(null); + + Properties props = appender.buildEnvProperties(); + assertEquals(4, props.size()); + assertEquals(appender.getInitialContextFactoryName(), props + .getProperty(Context.INITIAL_CONTEXT_FACTORY)); + assertEquals(appender.getProviderURL(), props.getProperty(Context.PROVIDER_URL)); + assertEquals(appender.getURLPkgPrefixes(), props + .getProperty(Context.URL_PKG_PREFIXES)); + assertEquals(appender.getSecurityPrincipalName(), props + .getProperty(Context.SECURITY_PRINCIPAL)); + assertEquals(null, props + .getProperty(Context.SECURITY_CREDENTIALS)); + + assertEquals(1, context.getStatusManager().getCount()); + } + + @Test + public void testBuildEnvPropertiesWithPkgNull() { + appender.setInitialContextFactoryName("icfn"); + appender.setProviderURL("url"); + appender.setURLPkgPrefixes(null); + appender.setSecurityPrincipalName("user"); + appender.setSecurityCredentials("cred"); + + Properties props = appender.buildEnvProperties(); + assertEquals(4, props.size()); + assertEquals(appender.getInitialContextFactoryName(), props + .getProperty(Context.INITIAL_CONTEXT_FACTORY)); + assertEquals(appender.getProviderURL(), props.getProperty(Context.PROVIDER_URL)); + assertEquals(null, props + .getProperty(Context.URL_PKG_PREFIXES)); + assertEquals(appender.getSecurityPrincipalName(), props + .getProperty(Context.SECURITY_PRINCIPAL)); + assertEquals(appender.getSecurityCredentials(), props + .getProperty(Context.SECURITY_CREDENTIALS)); + + assertEquals(0, context.getStatusManager().getCount()); + } + + @Test + public void testStartMinimalInfo() { + //let's leave only what's in the setup() + //method, minus the providerURL + appender.setProviderURL(null); + appender.start(); + + assertTrue(appender.isStarted()); + + try { + assertEquals(appender.topicBindingName, appender.topicPublisher.getTopic().getTopicName()); + } catch (Exception e) { + fail(); + } + } + + @Test + public void testStartUserPass() { + appender.setUserName("test"); + appender.setPassword("test"); + + appender.start(); + + assertTrue(appender.isStarted()); + + try { + assertEquals(appender.topicBindingName, appender.topicPublisher.getTopic().getTopicName()); + } catch (Exception e) { + fail(); + } + } + + @Test + public void testStartFails() { + appender.topicBindingName = null; + + appender.start(); + + assertFalse(appender.isStarted()); + } + + private ILoggingEvent createLoggingEvent() { + LoggingEvent le = new LoggingEvent(); + le.setLevel(Level.DEBUG); + le.setMessage("test message"); + le.setTimeStamp(System.currentTimeMillis()); + le.setThreadName(Thread.currentThread().getName()); + return le; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSTopicAppenderTestApp.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSTopicAppenderTestApp.java index 4a90462d02ce37e3f3d19208090bcb108d16a7b2..7f684bba506f6624a904e59148f81dd318d6fc02 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSTopicAppenderTestApp.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/JMSTopicAppenderTestApp.java @@ -1,62 +1,62 @@ -/** - * 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.classic.net; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.util.StatusPrinter; - -public class JMSTopicAppenderTestApp { - - public static void main(String[] args) { - Logger logger = (Logger)LoggerFactory.getLogger(JMSTopicAppenderTestApp.class); - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - lc.reset(); - - JMSTopicAppender appender = new JMSTopicAppender(); - appender.setContext(lc); - appender.setName("jmsTopic"); - appender.setInitialContextFactoryName("org.apache.activemq.jndi.ActiveMQInitialContextFactory"); - //appender.setPassword(""); - appender.setProviderURL("tcp://localhost:61616"); - //appender.setSecurityCredentials(""); - //appender.setSecurityPrincipalName(""); - appender.setTopicBindingName("MyTopic"); - appender.setTopicConnectionFactoryBindingName("ConnectionFactory"); - //appender.setURLPkgPrefixes(""); - //appender.setUserName(""); - - appender.start(); - logger.addAppender(appender); - - - //JIT - for (int i = 0; i < 10000; i++) { - logger.debug("** Hello world. n=" + i); - } - - long before = System.nanoTime(); - for (int i = 0; i < 10000; i++) { - logger.debug("** Hello world. n=" + i); - } - long after = System.nanoTime(); - - System.out.println("Time per logs for 10'000 logs: " + (after-before)/10000); - - StatusPrinter.print(lc.getStatusManager()); - } - +/** + * 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.classic.net; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.util.StatusPrinter; + +public class JMSTopicAppenderTestApp { + + public static void main(String[] args) { + Logger logger = (Logger)LoggerFactory.getLogger(JMSTopicAppenderTestApp.class); + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + lc.reset(); + + JMSTopicAppender appender = new JMSTopicAppender(); + appender.setContext(lc); + appender.setName("jmsTopic"); + appender.setInitialContextFactoryName("org.apache.activemq.jndi.ActiveMQInitialContextFactory"); + //appender.setPassword(""); + appender.setProviderURL("tcp://localhost:61616"); + //appender.setSecurityCredentials(""); + //appender.setSecurityPrincipalName(""); + appender.setTopicBindingName("MyTopic"); + appender.setTopicConnectionFactoryBindingName("ConnectionFactory"); + //appender.setURLPkgPrefixes(""); + //appender.setUserName(""); + + appender.start(); + logger.addAppender(appender); + + + //JIT + for (int i = 0; i < 10000; i++) { + logger.debug("** Hello world. n=" + i); + } + + long before = System.nanoTime(); + for (int i = 0; i < 10000; i++) { + logger.debug("** Hello world. n=" + i); + } + long after = System.nanoTime(); + + System.out.println("Time per logs for 10'000 logs: " + (after-before)/10000); + + StatusPrinter.print(lc.getStatusManager()); + } + } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/NOPOutputStream.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/NOPOutputStream.java index c8232f508cbe3af0c019073ba8719c2986a34d88..71c8f3ab4f29e300ed2486ee6d45c639fbafbfdb 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/NOPOutputStream.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/NOPOutputStream.java @@ -1,42 +1,42 @@ -/** - * 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.classic.net; - -import java.io.IOException; -import java.io.OutputStream; - -public class NOPOutputStream extends OutputStream { - - long count; - - @Override - public void write(int b) throws IOException { - count++; - // do nothing - } - - public long getCount() { - return count; - } - - public long size() { - return count; - } - - - public void reset() { - count = 0; - } - -} +/** + * 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.classic.net; + +import java.io.IOException; +import java.io.OutputStream; + +public class NOPOutputStream extends OutputStream { + + long count; + + @Override + public void write(int b) throws IOException { + count++; + // do nothing + } + + public long getCount() { + return count; + } + + public long size() { + return count; + } + + + public void reset() { + count = 0; + } + +} 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 232582a37e25128f1c49d61ae8e62caf5a55d52e..076d7cac9c552e4410eb929edc5203e0a37bccb4 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 @@ -1,24 +1,24 @@ -/** - * 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.classic.net; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses( { SyslogAppenderTest.class, DilutedSMTPAppenderTest.class, - SocketAppenderTest.class, JMSQueueAppenderTest.class, JMSTopicAppenderTest.class }) -public class PackageTest { +/** + * 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.classic.net; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses( { SyslogAppenderTest.class, DilutedSMTPAppenderTest.class, + SocketAppenderTest.class, JMSQueueAppenderTest.class, JMSTopicAppenderTest.class }) +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/SMTPAppender_GreenTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/SMTPAppender_GreenTest.java index 092f73b062643e4ef7e29b3251733440f2db982a..e368a4dd8be114fbe4441e92964932b515a655d3 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/SMTPAppender_GreenTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/SMTPAppender_GreenTest.java @@ -1,224 +1,224 @@ -/** - * 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.classic.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; - -import javax.mail.MessagingException; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; - -import org.dom4j.io.SAXReader; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.MDC; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.html.HTMLLayout; -import ch.qos.logback.classic.html.XHTMLEntityResolver; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.util.TeztConstants; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.Layout; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.testUtil.RandomUtil; -import ch.qos.logback.core.util.StatusPrinter; - -import com.icegreen.greenmail.util.GreenMail; -import com.icegreen.greenmail.util.GreenMailUtil; -import com.icegreen.greenmail.util.ServerSetup; - -public class SMTPAppender_GreenTest { - - int port = RandomUtil.getRandomServerPort(); - GreenMail greenMail; - SMTPAppender smtpAppender; - LoggerContext lc = new LoggerContext(); - Logger logger = lc.getLogger(this.getClass()); - - static final String TEST_SUBJECT = "test subject"; - static final String HEADER = "HEADER\n"; - static final String FOOTER = "FOOTER\n"; - - @Before - public void setUp() throws Exception { - MDC.clear(); - ServerSetup serverSetup = new ServerSetup(port, "localhost", - ServerSetup.PROTOCOL_SMTP); - greenMail = new GreenMail(serverSetup); - greenMail.start(); - // let the grean mail server get a head start - Thread.sleep(100); - } - - @After - public void tearDown() throws Exception { - greenMail.stop(); - } - - - void buildSMTPAppender() throws Exception { - smtpAppender = new SMTPAppender(); - smtpAppender.setContext(lc); - smtpAppender.setName("smtp"); - smtpAppender.setFrom("user@host.dom"); - smtpAppender.setSMTPHost("localhost"); - smtpAppender.setSMTPPort(port); - smtpAppender.setSubject(TEST_SUBJECT); - smtpAppender.addTo("nospam@qos.ch"); - // smtpAppender.start(); - } - - private Layout buildPatternLayout(LoggerContext lc) { - PatternLayout layout = new PatternLayout(); - layout.setContext(lc); - layout.setFileHeader(HEADER); - layout.setPattern("%-4relative %mdc [%thread] %-5level %class - %msg%n"); - layout.setFileFooter(FOOTER); - layout.start(); - return layout; - } - - private Layout buildHTMLLayout(LoggerContext lc) { - HTMLLayout layout = new HTMLLayout(); - layout.setContext(lc); - // layout.setFileHeader(HEADER); - layout.setPattern("%level%class%msg"); - // layout.setFileFooter(FOOTER); - layout.start(); - return layout; - } - - - - private MimeMultipart verify(String subject) throws MessagingException, IOException { - MimeMessage[] mma = greenMail.getReceivedMessages(); - assertNotNull(mma); - assertEquals(1, mma.length); - MimeMessage mm = mma[0]; - // http://jira.qos.ch/browse/LBCLASSIC-67 - assertEquals(subject, mm.getSubject()); - return (MimeMultipart) mm.getContent(); - } - - @Test - public void smoke() throws Exception { - buildSMTPAppender(); - smtpAppender.setLayout(buildPatternLayout(lc)); - smtpAppender.start(); - logger.addAppender(smtpAppender); - logger.debug("hello"); - logger.error("en error", new Exception("an exception")); - - StatusPrinter.print(lc); - MimeMultipart mp = verify(TEST_SUBJECT); - String body = GreenMailUtil.getBody(mp.getBodyPart(0)); - assertTrue(body.startsWith(HEADER.trim())); - assertTrue(body.endsWith(FOOTER.trim())); - } - - @Test - public void LBCLASSIC_104() throws Exception { - buildSMTPAppender(); - smtpAppender.setLayout(buildPatternLayout(lc)); - smtpAppender.start(); - logger.addAppender(smtpAppender); - MDC.put("key", "val"); - logger.debug("hello"); - MDC.clear(); - logger.error("en error", new Exception("an exception")); - - MimeMultipart mp = verify(TEST_SUBJECT); - String body = GreenMailUtil.getBody(mp.getBodyPart(0)); - assertTrue(body.startsWith(HEADER.trim())); - assertTrue(body.contains("key=val")); - assertTrue(body.endsWith(FOOTER.trim())); - } - - - @Test - public void html() throws Exception { - buildSMTPAppender(); - smtpAppender.setLayout(buildHTMLLayout(lc)); - smtpAppender.start(); - logger.addAppender(smtpAppender); - logger.debug("hello"); - logger.error("en error", new Exception("an exception")); - MimeMultipart mp = verify(TEST_SUBJECT); - - // verify strict adherence to xhtml1-strict.dtd - SAXReader reader = new SAXReader(); - reader.setValidation(true); - reader.setEntityResolver(new XHTMLEntityResolver()); - reader.read(mp.getBodyPart(0).getInputStream()); - - } - - @Test - /** - * Checks that even when many events are processed, the output is still - * conforms to xhtml-strict.dtd. - * - * Note that SMTPAppender only keeps only 500 or so (=buffer size) events. So - * the generated output will be rather short. - */ - public void htmlLong() throws Exception { - buildSMTPAppender(); - smtpAppender.setLayout(buildHTMLLayout(lc)); - smtpAppender.start(); - logger.addAppender(smtpAppender); - for (int i = 0; i < CoreConstants.TABLE_ROW_LIMIT * 3; i++) { - logger.debug("hello " + i); - } - logger.error("en error", new Exception("an exception")); - - MimeMultipart mp = verify(TEST_SUBJECT); - - // verify strict adherence to xhtml1-strict.dtd - SAXReader reader = new SAXReader(); - reader.setValidation(true); - reader.setEntityResolver(new XHTMLEntityResolver()); - reader.read(mp.getBodyPart(0).getInputStream()); - } - - private void configure(String file) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(lc); - System.out.println("port="+port); - lc.putProperty("port", "" + port); - jc.doConfigure(file); - } - - @Test - public void testCustomEvaluator() throws Exception { - configure(TeztConstants.TEST_DIR_PREFIX - + "input/joran/smtp/customEvaluator.xml"); - - logger.debug("hello"); - String msg2 = "world"; - logger.debug(msg2); - logger.debug("invisible"); - MimeMultipart mp = verify(this.getClass().getName()+ " - "+msg2); - String body = GreenMailUtil.getBody(mp.getBodyPart(0)); - assertEquals("helloworld", body); - } -} +/** + * 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.classic.net; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; + +import org.dom4j.io.SAXReader; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.MDC; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.html.HTMLLayout; +import ch.qos.logback.classic.html.XHTMLEntityResolver; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.util.TeztConstants; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.testUtil.RandomUtil; +import ch.qos.logback.core.util.StatusPrinter; + +import com.icegreen.greenmail.util.GreenMail; +import com.icegreen.greenmail.util.GreenMailUtil; +import com.icegreen.greenmail.util.ServerSetup; + +public class SMTPAppender_GreenTest { + + int port = RandomUtil.getRandomServerPort(); + GreenMail greenMail; + SMTPAppender smtpAppender; + LoggerContext lc = new LoggerContext(); + Logger logger = lc.getLogger(this.getClass()); + + static final String TEST_SUBJECT = "test subject"; + static final String HEADER = "HEADER\n"; + static final String FOOTER = "FOOTER\n"; + + @Before + public void setUp() throws Exception { + MDC.clear(); + ServerSetup serverSetup = new ServerSetup(port, "localhost", + ServerSetup.PROTOCOL_SMTP); + greenMail = new GreenMail(serverSetup); + greenMail.start(); + // let the grean mail server get a head start + Thread.sleep(100); + } + + @After + public void tearDown() throws Exception { + greenMail.stop(); + } + + + void buildSMTPAppender() throws Exception { + smtpAppender = new SMTPAppender(); + smtpAppender.setContext(lc); + smtpAppender.setName("smtp"); + smtpAppender.setFrom("user@host.dom"); + smtpAppender.setSMTPHost("localhost"); + smtpAppender.setSMTPPort(port); + smtpAppender.setSubject(TEST_SUBJECT); + smtpAppender.addTo("nospam@qos.ch"); + // smtpAppender.start(); + } + + private Layout buildPatternLayout(LoggerContext lc) { + PatternLayout layout = new PatternLayout(); + layout.setContext(lc); + layout.setFileHeader(HEADER); + layout.setPattern("%-4relative %mdc [%thread] %-5level %class - %msg%n"); + layout.setFileFooter(FOOTER); + layout.start(); + return layout; + } + + private Layout buildHTMLLayout(LoggerContext lc) { + HTMLLayout layout = new HTMLLayout(); + layout.setContext(lc); + // layout.setFileHeader(HEADER); + layout.setPattern("%level%class%msg"); + // layout.setFileFooter(FOOTER); + layout.start(); + return layout; + } + + + + private MimeMultipart verify(String subject) throws MessagingException, IOException { + MimeMessage[] mma = greenMail.getReceivedMessages(); + assertNotNull(mma); + assertEquals(1, mma.length); + MimeMessage mm = mma[0]; + // http://jira.qos.ch/browse/LBCLASSIC-67 + assertEquals(subject, mm.getSubject()); + return (MimeMultipart) mm.getContent(); + } + + @Test + public void smoke() throws Exception { + buildSMTPAppender(); + smtpAppender.setLayout(buildPatternLayout(lc)); + smtpAppender.start(); + logger.addAppender(smtpAppender); + logger.debug("hello"); + logger.error("en error", new Exception("an exception")); + + StatusPrinter.print(lc); + MimeMultipart mp = verify(TEST_SUBJECT); + String body = GreenMailUtil.getBody(mp.getBodyPart(0)); + assertTrue(body.startsWith(HEADER.trim())); + assertTrue(body.endsWith(FOOTER.trim())); + } + + @Test + public void LBCLASSIC_104() throws Exception { + buildSMTPAppender(); + smtpAppender.setLayout(buildPatternLayout(lc)); + smtpAppender.start(); + logger.addAppender(smtpAppender); + MDC.put("key", "val"); + logger.debug("hello"); + MDC.clear(); + logger.error("en error", new Exception("an exception")); + + MimeMultipart mp = verify(TEST_SUBJECT); + String body = GreenMailUtil.getBody(mp.getBodyPart(0)); + assertTrue(body.startsWith(HEADER.trim())); + assertTrue(body.contains("key=val")); + assertTrue(body.endsWith(FOOTER.trim())); + } + + + @Test + public void html() throws Exception { + buildSMTPAppender(); + smtpAppender.setLayout(buildHTMLLayout(lc)); + smtpAppender.start(); + logger.addAppender(smtpAppender); + logger.debug("hello"); + logger.error("en error", new Exception("an exception")); + MimeMultipart mp = verify(TEST_SUBJECT); + + // verify strict adherence to xhtml1-strict.dtd + SAXReader reader = new SAXReader(); + reader.setValidation(true); + reader.setEntityResolver(new XHTMLEntityResolver()); + reader.read(mp.getBodyPart(0).getInputStream()); + + } + + @Test + /** + * Checks that even when many events are processed, the output is still + * conforms to xhtml-strict.dtd. + * + * Note that SMTPAppender only keeps only 500 or so (=buffer size) events. So + * the generated output will be rather short. + */ + public void htmlLong() throws Exception { + buildSMTPAppender(); + smtpAppender.setLayout(buildHTMLLayout(lc)); + smtpAppender.start(); + logger.addAppender(smtpAppender); + for (int i = 0; i < CoreConstants.TABLE_ROW_LIMIT * 3; i++) { + logger.debug("hello " + i); + } + logger.error("en error", new Exception("an exception")); + + MimeMultipart mp = verify(TEST_SUBJECT); + + // verify strict adherence to xhtml1-strict.dtd + SAXReader reader = new SAXReader(); + reader.setValidation(true); + reader.setEntityResolver(new XHTMLEntityResolver()); + reader.read(mp.getBodyPart(0).getInputStream()); + } + + private void configure(String file) throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(lc); + System.out.println("port="+port); + lc.putProperty("port", "" + port); + jc.doConfigure(file); + } + + @Test + public void testCustomEvaluator() throws Exception { + configure(TeztConstants.TEST_DIR_PREFIX + + "input/joran/smtp/customEvaluator.xml"); + + logger.debug("hello"); + String msg2 = "world"; + logger.debug(msg2); + logger.debug("invisible"); + MimeMultipart mp = verify(this.getClass().getName()+ " - "+msg2); + String body = GreenMailUtil.getBody(mp.getBodyPart(0)); + assertEquals("helloworld", body); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/SMTPAppender_SubethaSMTPTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/SMTPAppender_SubethaSMTPTest.java index 71a633a3f6fef15cf3e7786a468a25497cec8bd2..b1ffc6cfd9cdfd55f722b030ec7098498fc29db8 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/SMTPAppender_SubethaSMTPTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/SMTPAppender_SubethaSMTPTest.java @@ -1,328 +1,328 @@ -/** - * 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.classic.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayOutputStream; -import java.util.List; -import java.util.Random; - -import javax.mail.Part; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; - -import org.dom4j.io.SAXReader; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.subethamail.smtp.AuthenticationHandler; -import org.subethamail.smtp.AuthenticationHandlerFactory; -import org.subethamail.smtp.auth.LoginAuthenticationHandler; -import org.subethamail.smtp.auth.LoginFailedException; -import org.subethamail.smtp.auth.PlainAuthenticationHandler; -import org.subethamail.smtp.auth.PluginAuthenticationHandler; -import org.subethamail.smtp.auth.UsernamePasswordValidator; -import org.subethamail.smtp.server.MessageListenerAdapter; -import org.subethamail.wiser.Wiser; -import org.subethamail.wiser.WiserMessage; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.html.HTMLLayout; -import ch.qos.logback.classic.html.XHTMLEntityResolver; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.Layout; -import ch.qos.logback.core.util.StatusPrinter; - -public class SMTPAppender_SubethaSMTPTest { - - int diff = 1024 + new Random().nextInt(10000); - Wiser wiser; - - SMTPAppender smtpAppender; - LoggerContext lc = new LoggerContext(); - - static final String TEST_SUBJECT = "test subject"; - static final String HEADER = "HEADER\n"; - static final String FOOTER = "FOOTER\n"; - - @Before - public void setUp() throws Exception { - wiser = new Wiser(); - wiser.setPort(diff); - wiser.getServer(); - wiser.start(); - //StartTLSCommand s; - buildSMTPAppender(); - } - - void buildSMTPAppender() throws Exception { - smtpAppender = new SMTPAppender(); - smtpAppender.setContext(lc); - smtpAppender.setName("smtp"); - smtpAppender.setFrom("user@host.dom"); - smtpAppender.setSMTPHost("localhost"); - smtpAppender.setSMTPPort(diff); - smtpAppender.setSubject(TEST_SUBJECT); - smtpAppender.addTo("noreply@qos.ch"); - } - - private Layout buildPatternLayout(LoggerContext lc) { - PatternLayout layout = new PatternLayout(); - layout.setContext(lc); - layout.setFileHeader(HEADER); - layout.setPattern("%-4relative [%thread] %-5level %logger %class - %msg%n"); - layout.setFileFooter(FOOTER); - layout.start(); - return layout; - } - - private Layout buildHTMLLayout(LoggerContext lc) { - HTMLLayout layout = new HTMLLayout(); - layout.setContext(lc); - // layout.setFileHeader(HEADER); - layout.setPattern("%level%class%msg"); - // layout.setFileFooter(FOOTER); - layout.start(); - return layout; - } - - @After - public void tearDown() throws Exception { - wiser.stop(); - } - - private static String getWholeMessage(Part msg) { - try { - ByteArrayOutputStream bodyOut = new ByteArrayOutputStream(); - msg.writeTo(bodyOut); - return bodyOut.toString("US-ASCII").trim(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private static String getBody(Part msg) { - String all = getWholeMessage(msg); - int i = all.indexOf("\r\n\r\n"); - return all.substring(i + 4, all.length()); -} - - @Test - public void smoke() throws Exception { - smtpAppender.setLayout(buildPatternLayout(lc)); - smtpAppender.start(); - Logger logger = lc.getLogger("test"); - logger.addAppender(smtpAppender); - logger.debug("hello"); - logger.error("en error", new Exception("an exception")); - List wiserMsgList = wiser.getMessages(); - - assertNotNull(wiserMsgList); - assertEquals(1, wiserMsgList.size()); - WiserMessage wm = wiserMsgList.get(0); - // http://jira.qos.ch/browse/LBCLASSIC-67 - MimeMessage mm = wm.getMimeMessage(); - assertEquals(TEST_SUBJECT, mm.getSubject()); - - MimeMultipart mp = (MimeMultipart) mm.getContent(); - String body = getBody(mp.getBodyPart(0)); - System.out.println("["+body); - assertTrue(body.startsWith(HEADER.trim())); - assertTrue(body.endsWith(FOOTER.trim())); - } - - @Test - public void html() throws Exception { - smtpAppender.setLayout(buildHTMLLayout(lc)); - smtpAppender.start(); - Logger logger = lc.getLogger("test"); - logger.addAppender(smtpAppender); - logger.debug("hello"); - logger.error("en error", new Exception("an exception")); - - List wiserMsgList = wiser.getMessages(); - - assertNotNull(wiserMsgList); - assertEquals(1, wiserMsgList.size()); - WiserMessage wm = wiserMsgList.get(0); - MimeMessage mm = wm.getMimeMessage(); - assertEquals(TEST_SUBJECT, mm.getSubject()); - - MimeMultipart mp = (MimeMultipart) mm.getContent(); - - // verify strict adherence to xhtml1-strict.dtd - SAXReader reader = new SAXReader(); - reader.setValidation(true); - reader.setEntityResolver(new XHTMLEntityResolver()); - reader.read(mp.getBodyPart(0).getInputStream()); - // System.out.println(GreenMailUtil.getBody(mp.getBodyPart(0))); - } - - @Test - /** - * Checks that even when many events are processed, the output is still - * conforms to xhtml-strict.dtd. - * - * Note that SMTPAppender only keeps only 500 or so (=buffer size) events. So - * the generated output will be rather short. - */ - public void htmlLong() throws Exception { - smtpAppender.setLayout(buildHTMLLayout(lc)); - smtpAppender.start(); - Logger logger = lc.getLogger("test"); - logger.addAppender(smtpAppender); - for (int i = 0; i < CoreConstants.TABLE_ROW_LIMIT * 3; i++) { - logger.debug("hello " + i); - } - logger.error("en error", new Exception("an exception")); - List wiserMsgList = wiser.getMessages(); - - assertNotNull(wiserMsgList); - assertEquals(1, wiserMsgList.size()); - WiserMessage wm = wiserMsgList.get(0); - MimeMessage mm = wm.getMimeMessage(); - assertEquals(TEST_SUBJECT, mm.getSubject()); - - MimeMultipart mp = (MimeMultipart) mm.getContent(); - - // verify strict adherence to xhtml1-strict.dtd - SAXReader reader = new SAXReader(); - reader.setValidation(true); - reader.setEntityResolver(new XHTMLEntityResolver()); - reader.read(mp.getBodyPart(0).getInputStream()); - } - - @Test - public void authenticated() throws Exception { - MessageListenerAdapter mla = (MessageListenerAdapter)wiser.getServer().getMessageHandlerFactory(); - mla.setAuthenticationHandlerFactory(new TrivialAuthHandlerFactory()); - - smtpAppender.setUsername("x"); - smtpAppender.setPassword("x"); - - smtpAppender.setLayout(buildPatternLayout(lc)); - smtpAppender.start(); - Logger logger = lc.getLogger("test"); - logger.addAppender(smtpAppender); - logger.debug("hello"); - logger.error("en error", new Exception("an exception")); - - List wiserMsgList = wiser.getMessages(); - - assertNotNull(wiserMsgList); - assertEquals(1, wiserMsgList.size()); - WiserMessage wm = wiserMsgList.get(0); - // http://jira.qos.ch/browse/LBCLASSIC-67 - MimeMessage mm = wm.getMimeMessage(); - assertEquals(TEST_SUBJECT, mm.getSubject()); - - MimeMultipart mp = (MimeMultipart) mm.getContent(); - String body = getBody(mp.getBodyPart(0)); - assertTrue(body.startsWith(HEADER.trim())); - assertTrue(body.endsWith(FOOTER.trim())); - } - - @Test - @Ignore - // Unfortunately, there seems to be a problem with SubethaSMTP's implementation - // of startTLS. The same SMTPAppender code works fine when tested with gmail. - public void authenticatedSSL() throws Exception { - MessageListenerAdapter mla = (MessageListenerAdapter)wiser.getServer().getMessageHandlerFactory(); - mla.setAuthenticationHandlerFactory(new TrivialAuthHandlerFactory()); - - smtpAppender.setSTARTTLS(true); - smtpAppender.setUsername("xx"); - smtpAppender.setPassword("xx"); - - smtpAppender.setLayout(buildPatternLayout(lc)); - smtpAppender.start(); - Logger logger = lc.getLogger("test"); - logger.addAppender(smtpAppender); - logger.debug("hello"); - logger.error("en error", new Exception("an exception")); - - StatusPrinter.print(lc); - List wiserMsgList = wiser.getMessages(); - - assertNotNull(wiserMsgList); - assertEquals(1, wiserMsgList.size()); - } - - @Test - @Ignore - public void authenticatedGmailStartTLS() throws Exception { - smtpAppender.setSMTPHost("smtp.gmail.com"); - smtpAppender.setSMTPPort(587); - - smtpAppender.addTo("XXX@gmail.com"); - smtpAppender.setSTARTTLS(true); - smtpAppender.setUsername("XXX@gmail.com"); - smtpAppender.setPassword("XXX"); - - smtpAppender.setLayout(buildPatternLayout(lc)); - smtpAppender.start(); - Logger logger = lc.getLogger("authenticatedGmailSTARTTLS"); - logger.addAppender(smtpAppender); - logger.debug("hello"); - logger.error("en error", new Exception("an exception")); - - StatusPrinter.print(lc); - } - - @Test - @Ignore - public void authenticatedGmail_SSL() throws Exception { - smtpAppender.setSMTPHost("smtp.gmail.com"); - smtpAppender.setSMTPPort(465); - - smtpAppender.addTo("XXX@gmail.com"); - smtpAppender.setSSL(true); - smtpAppender.setUsername("XXX@gmail.com"); - smtpAppender.setPassword("XXX"); - - smtpAppender.setLayout(buildPatternLayout(lc)); - smtpAppender.start(); - Logger logger = lc.getLogger("authenticatedGmail_SSL"); - logger.addAppender(smtpAppender); - logger.debug("hello"); - logger.error("en error", new Exception("an exception")); - - StatusPrinter.print(lc); - } - - public class TrivialAuthHandlerFactory implements AuthenticationHandlerFactory { - public AuthenticationHandler create() { - PluginAuthenticationHandler ret = new PluginAuthenticationHandler(); - UsernamePasswordValidator validator = new UsernamePasswordValidator() { - public void login(String username, String password) - throws LoginFailedException { - if(!username.equals(password)) { - throw new LoginFailedException("username="+username+", password="+password); - } - } - }; - ret.addPlugin(new PlainAuthenticationHandler(validator)); - ret.addPlugin(new LoginAuthenticationHandler(validator)); - return ret; - } - } - -} +/** + * 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.classic.net; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.util.List; +import java.util.Random; + +import javax.mail.Part; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; + +import org.dom4j.io.SAXReader; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.subethamail.smtp.AuthenticationHandler; +import org.subethamail.smtp.AuthenticationHandlerFactory; +import org.subethamail.smtp.auth.LoginAuthenticationHandler; +import org.subethamail.smtp.auth.LoginFailedException; +import org.subethamail.smtp.auth.PlainAuthenticationHandler; +import org.subethamail.smtp.auth.PluginAuthenticationHandler; +import org.subethamail.smtp.auth.UsernamePasswordValidator; +import org.subethamail.smtp.server.MessageListenerAdapter; +import org.subethamail.wiser.Wiser; +import org.subethamail.wiser.WiserMessage; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.html.HTMLLayout; +import ch.qos.logback.classic.html.XHTMLEntityResolver; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.util.StatusPrinter; + +public class SMTPAppender_SubethaSMTPTest { + + int diff = 1024 + new Random().nextInt(10000); + Wiser wiser; + + SMTPAppender smtpAppender; + LoggerContext lc = new LoggerContext(); + + static final String TEST_SUBJECT = "test subject"; + static final String HEADER = "HEADER\n"; + static final String FOOTER = "FOOTER\n"; + + @Before + public void setUp() throws Exception { + wiser = new Wiser(); + wiser.setPort(diff); + wiser.getServer(); + wiser.start(); + //StartTLSCommand s; + buildSMTPAppender(); + } + + void buildSMTPAppender() throws Exception { + smtpAppender = new SMTPAppender(); + smtpAppender.setContext(lc); + smtpAppender.setName("smtp"); + smtpAppender.setFrom("user@host.dom"); + smtpAppender.setSMTPHost("localhost"); + smtpAppender.setSMTPPort(diff); + smtpAppender.setSubject(TEST_SUBJECT); + smtpAppender.addTo("noreply@qos.ch"); + } + + private Layout buildPatternLayout(LoggerContext lc) { + PatternLayout layout = new PatternLayout(); + layout.setContext(lc); + layout.setFileHeader(HEADER); + layout.setPattern("%-4relative [%thread] %-5level %logger %class - %msg%n"); + layout.setFileFooter(FOOTER); + layout.start(); + return layout; + } + + private Layout buildHTMLLayout(LoggerContext lc) { + HTMLLayout layout = new HTMLLayout(); + layout.setContext(lc); + // layout.setFileHeader(HEADER); + layout.setPattern("%level%class%msg"); + // layout.setFileFooter(FOOTER); + layout.start(); + return layout; + } + + @After + public void tearDown() throws Exception { + wiser.stop(); + } + + private static String getWholeMessage(Part msg) { + try { + ByteArrayOutputStream bodyOut = new ByteArrayOutputStream(); + msg.writeTo(bodyOut); + return bodyOut.toString("US-ASCII").trim(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static String getBody(Part msg) { + String all = getWholeMessage(msg); + int i = all.indexOf("\r\n\r\n"); + return all.substring(i + 4, all.length()); +} + + @Test + public void smoke() throws Exception { + smtpAppender.setLayout(buildPatternLayout(lc)); + smtpAppender.start(); + Logger logger = lc.getLogger("test"); + logger.addAppender(smtpAppender); + logger.debug("hello"); + logger.error("en error", new Exception("an exception")); + List wiserMsgList = wiser.getMessages(); + + assertNotNull(wiserMsgList); + assertEquals(1, wiserMsgList.size()); + WiserMessage wm = wiserMsgList.get(0); + // http://jira.qos.ch/browse/LBCLASSIC-67 + MimeMessage mm = wm.getMimeMessage(); + assertEquals(TEST_SUBJECT, mm.getSubject()); + + MimeMultipart mp = (MimeMultipart) mm.getContent(); + String body = getBody(mp.getBodyPart(0)); + System.out.println("["+body); + assertTrue(body.startsWith(HEADER.trim())); + assertTrue(body.endsWith(FOOTER.trim())); + } + + @Test + public void html() throws Exception { + smtpAppender.setLayout(buildHTMLLayout(lc)); + smtpAppender.start(); + Logger logger = lc.getLogger("test"); + logger.addAppender(smtpAppender); + logger.debug("hello"); + logger.error("en error", new Exception("an exception")); + + List wiserMsgList = wiser.getMessages(); + + assertNotNull(wiserMsgList); + assertEquals(1, wiserMsgList.size()); + WiserMessage wm = wiserMsgList.get(0); + MimeMessage mm = wm.getMimeMessage(); + assertEquals(TEST_SUBJECT, mm.getSubject()); + + MimeMultipart mp = (MimeMultipart) mm.getContent(); + + // verify strict adherence to xhtml1-strict.dtd + SAXReader reader = new SAXReader(); + reader.setValidation(true); + reader.setEntityResolver(new XHTMLEntityResolver()); + reader.read(mp.getBodyPart(0).getInputStream()); + // System.out.println(GreenMailUtil.getBody(mp.getBodyPart(0))); + } + + @Test + /** + * Checks that even when many events are processed, the output is still + * conforms to xhtml-strict.dtd. + * + * Note that SMTPAppender only keeps only 500 or so (=buffer size) events. So + * the generated output will be rather short. + */ + public void htmlLong() throws Exception { + smtpAppender.setLayout(buildHTMLLayout(lc)); + smtpAppender.start(); + Logger logger = lc.getLogger("test"); + logger.addAppender(smtpAppender); + for (int i = 0; i < CoreConstants.TABLE_ROW_LIMIT * 3; i++) { + logger.debug("hello " + i); + } + logger.error("en error", new Exception("an exception")); + List wiserMsgList = wiser.getMessages(); + + assertNotNull(wiserMsgList); + assertEquals(1, wiserMsgList.size()); + WiserMessage wm = wiserMsgList.get(0); + MimeMessage mm = wm.getMimeMessage(); + assertEquals(TEST_SUBJECT, mm.getSubject()); + + MimeMultipart mp = (MimeMultipart) mm.getContent(); + + // verify strict adherence to xhtml1-strict.dtd + SAXReader reader = new SAXReader(); + reader.setValidation(true); + reader.setEntityResolver(new XHTMLEntityResolver()); + reader.read(mp.getBodyPart(0).getInputStream()); + } + + @Test + public void authenticated() throws Exception { + MessageListenerAdapter mla = (MessageListenerAdapter)wiser.getServer().getMessageHandlerFactory(); + mla.setAuthenticationHandlerFactory(new TrivialAuthHandlerFactory()); + + smtpAppender.setUsername("x"); + smtpAppender.setPassword("x"); + + smtpAppender.setLayout(buildPatternLayout(lc)); + smtpAppender.start(); + Logger logger = lc.getLogger("test"); + logger.addAppender(smtpAppender); + logger.debug("hello"); + logger.error("en error", new Exception("an exception")); + + List wiserMsgList = wiser.getMessages(); + + assertNotNull(wiserMsgList); + assertEquals(1, wiserMsgList.size()); + WiserMessage wm = wiserMsgList.get(0); + // http://jira.qos.ch/browse/LBCLASSIC-67 + MimeMessage mm = wm.getMimeMessage(); + assertEquals(TEST_SUBJECT, mm.getSubject()); + + MimeMultipart mp = (MimeMultipart) mm.getContent(); + String body = getBody(mp.getBodyPart(0)); + assertTrue(body.startsWith(HEADER.trim())); + assertTrue(body.endsWith(FOOTER.trim())); + } + + @Test + @Ignore + // Unfortunately, there seems to be a problem with SubethaSMTP's implementation + // of startTLS. The same SMTPAppender code works fine when tested with gmail. + public void authenticatedSSL() throws Exception { + MessageListenerAdapter mla = (MessageListenerAdapter)wiser.getServer().getMessageHandlerFactory(); + mla.setAuthenticationHandlerFactory(new TrivialAuthHandlerFactory()); + + smtpAppender.setSTARTTLS(true); + smtpAppender.setUsername("xx"); + smtpAppender.setPassword("xx"); + + smtpAppender.setLayout(buildPatternLayout(lc)); + smtpAppender.start(); + Logger logger = lc.getLogger("test"); + logger.addAppender(smtpAppender); + logger.debug("hello"); + logger.error("en error", new Exception("an exception")); + + StatusPrinter.print(lc); + List wiserMsgList = wiser.getMessages(); + + assertNotNull(wiserMsgList); + assertEquals(1, wiserMsgList.size()); + } + + @Test + @Ignore + public void authenticatedGmailStartTLS() throws Exception { + smtpAppender.setSMTPHost("smtp.gmail.com"); + smtpAppender.setSMTPPort(587); + + smtpAppender.addTo("XXX@gmail.com"); + smtpAppender.setSTARTTLS(true); + smtpAppender.setUsername("XXX@gmail.com"); + smtpAppender.setPassword("XXX"); + + smtpAppender.setLayout(buildPatternLayout(lc)); + smtpAppender.start(); + Logger logger = lc.getLogger("authenticatedGmailSTARTTLS"); + logger.addAppender(smtpAppender); + logger.debug("hello"); + logger.error("en error", new Exception("an exception")); + + StatusPrinter.print(lc); + } + + @Test + @Ignore + public void authenticatedGmail_SSL() throws Exception { + smtpAppender.setSMTPHost("smtp.gmail.com"); + smtpAppender.setSMTPPort(465); + + smtpAppender.addTo("XXX@gmail.com"); + smtpAppender.setSSL(true); + smtpAppender.setUsername("XXX@gmail.com"); + smtpAppender.setPassword("XXX"); + + smtpAppender.setLayout(buildPatternLayout(lc)); + smtpAppender.start(); + Logger logger = lc.getLogger("authenticatedGmail_SSL"); + logger.addAppender(smtpAppender); + logger.debug("hello"); + logger.error("en error", new Exception("an exception")); + + StatusPrinter.print(lc); + } + + public class TrivialAuthHandlerFactory implements AuthenticationHandlerFactory { + public AuthenticationHandler create() { + PluginAuthenticationHandler ret = new PluginAuthenticationHandler(); + UsernamePasswordValidator validator = new UsernamePasswordValidator() { + public void login(String username, String password) + throws LoginFailedException { + if(!username.equals(password)) { + throw new LoginFailedException("username="+username+", password="+password); + } + } + }; + ret.addPlugin(new PlainAuthenticationHandler(validator)); + ret.addPlugin(new LoginAuthenticationHandler(validator)); + return ret; + } + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/SerializationPerfsTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/SerializationPerfsTest.java index 7bc624f969471c169f3d7a5bc19d76fc5f624a54..09d010283c08878786ceaf92190f8f041568413d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/SerializationPerfsTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/SerializationPerfsTest.java @@ -1,200 +1,200 @@ -/** - * 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.classic.net; - -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.net.Socket; - -import junit.framework.TestCase; -import ch.qos.logback.classic.net.testObjectBuilders.Builder; -import ch.qos.logback.classic.net.testObjectBuilders.TrivialLoggingEventBuilder; -import ch.qos.logback.classic.net.testObjectBuilders.MinimalSerBuilder; - -public class SerializationPerfsTest extends TestCase { - - ObjectOutputStream oos; - - int loopNumber = 10000; - int resetFrequency = 100; - int pauseFrequency = 10; - long pauseLengthInMillis = 20; - - /** - *

- * Run the test with a MockSocketServer or with a NOPOutputStream - * - *

- * Run with external mock can be done using the ExternalMockSocketServer. It - * needs to be launched from a separate JVM. The ExternalMockSocketServer does - * not consume the events but passes through the available bytes that it is - * receiving. - * - *

- * For example, with 4 test methods, you can launch the - * ExternalMockSocketServer this way: - *

- *

- * java ch.qos.logback.classic.net.ExternalMockSocketServer 4 - *

- */ - boolean runWithExternalMockServer = true; - - /** - * Last results: - * Data sent mesured in kilobytes. - * Avg time mesured in microsecs. - * - * NOPOutputStream: - * | | Runs | Avg time | Data sent | - * | MinimalObj Ext | 10000 | | | - * | MinimalObj Ser | 10000 | | | - * | LoggEvent Ext | 10000 | | | - * | LoggEvent Ser | 10000 | | | - * - * External MockServer with 45 letters-long message: on localhost - * (always the same message) - * | | Runs | Avg time | Data sent | - * | MinimalObj Ext | 10000 | - | - | - * | MinimalObj Ser | 10000 | 74 | 248 | - * | LoggEvent Ext | 10000 | - | - | - * | LoggEvent Ser | 10000 | 156 | 835 | - * pauseFrequency = 10 and pauseLengthInMillis = 20 - * - * External MockServer with 45 letters-long message: on localhost - * (different message each time) - * | | Runs | Avg time | Data sent | - * | MinimalObj Ext | 10000 | | | - * | MinimalObj Ser | 10000 | 73 | 1139 | - * | LoggEvent Ext | 10000 | | | - * | LoggEvent Ser | 10000 | 162 | 1752 | - * pauseFrequency = 10 and pauseLengthInMillis = 20 - * - * External MockServer with 45 letters-long message: on PIXIE - * (always the same message) - * | | Runs | Avg time | Data sent | - * | MinimalObj Ext | 10000 | - | - | - * | MinimalObj Ser | 10000 | 29 | 248 | - * | LoggEvent Ext | 10000 | - | - | - * | LoggEvent Ser | 10000 | 42 | 835 | - * pauseFrequency = 10 and pauseLengthInMillis = 20 - * - * External MockServer with 45 letters-long message: on PIXIE - * (different message each time) - * | | Runs | Avg time | Data sent | - * | MinimalObj Ext | 10000 | | | - * | MinimalObj Ser | 10000 | 27 | 1139 | - * | LoggEvent Ext | 10000 | | | - * | LoggEvent Ser | 10000 | 44 | 1752 | - * pauseFrequency = 10 and pauseLengthInMillis = 20 - * - */ - - public void setUp() throws Exception { - super.setUp(); - if (runWithExternalMockServer) { - oos = new ObjectOutputStream(new Socket("pixie", - ExternalMockSocketServer.PORT).getOutputStream()); - } else { - oos = new ObjectOutputStream(new NOPOutputStream()); - } - } - - public void tearDown() throws Exception { - super.tearDown(); - oos.close(); - oos = null; - } - - public void runPerfTest(Builder builder, String label) throws Exception { - // long time1 = System.nanoTime(); - - // Object builtObject = builder.build(1); - - // first run for just in time compiler - int resetCounter = 0; - int pauseCounter = 0; - for (int i = 0; i < loopNumber; i++) { - try { - oos.writeObject(builder.build(i)); - oos.flush(); - if (++resetCounter >= resetFrequency) { - oos.reset(); - resetCounter = 0; - } - if (++pauseCounter >= pauseFrequency) { - Thread.sleep(pauseLengthInMillis); - pauseCounter = 0; - } - - } catch (IOException ex) { - fail(ex.getMessage()); - } - } - - // second run - Long t1; - Long t2; - Long total = 0L; - resetCounter = 0; - pauseCounter = 0; - // System.out.println("Beginning mesured run"); - for (int i = 0; i < loopNumber; i++) { - try { - t1 = System.nanoTime(); - oos.writeObject(builder.build(i)); - oos.flush(); - t2 = System.nanoTime(); - total += (t2 - t1); - if (++resetCounter >= resetFrequency) { - oos.reset(); - resetCounter = 0; - } - if (++pauseCounter >= pauseFrequency) { - Thread.sleep(pauseLengthInMillis); - pauseCounter = 0; - } - } catch (IOException ex) { - fail(ex.getMessage()); - } - } - total /= 1000; - System.out.println(label + " : average time = " + total / loopNumber - + " microsecs after " + loopNumber + " writes."); - - // long time2 = System.nanoTime(); - // System.out.println("********* -> Time needed to run the test method: " + - // Long.toString(time2-time1)); - } - - // public void testWithMinimalExternalization() throws Exception { - // Builder builder = new MinimalExtBuilder(); - // runPerfTest(builder, "Minimal object externalization"); - // } - - public void testWithMinimalSerialization() throws Exception { - Builder builder = new MinimalSerBuilder(); - runPerfTest(builder, "Minimal object serialization"); - } - - // public void testWithExternalization() throws Exception { - // Builder builder = new LoggingEventExtBuilder(); - // runPerfTest(builder, "LoggingEvent object externalization"); - // } - - public void testWithSerialization() throws Exception { - Builder builder = new TrivialLoggingEventBuilder(); - runPerfTest(builder, "LoggingEvent object serialization"); - } -} +/** + * 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.classic.net; + +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.net.Socket; + +import junit.framework.TestCase; +import ch.qos.logback.classic.net.testObjectBuilders.Builder; +import ch.qos.logback.classic.net.testObjectBuilders.TrivialLoggingEventBuilder; +import ch.qos.logback.classic.net.testObjectBuilders.MinimalSerBuilder; + +public class SerializationPerfsTest extends TestCase { + + ObjectOutputStream oos; + + int loopNumber = 10000; + int resetFrequency = 100; + int pauseFrequency = 10; + long pauseLengthInMillis = 20; + + /** + *

+ * Run the test with a MockSocketServer or with a NOPOutputStream + * + *

+ * Run with external mock can be done using the ExternalMockSocketServer. It + * needs to be launched from a separate JVM. The ExternalMockSocketServer does + * not consume the events but passes through the available bytes that it is + * receiving. + * + *

+ * For example, with 4 test methods, you can launch the + * ExternalMockSocketServer this way: + *

+ *

+ * java ch.qos.logback.classic.net.ExternalMockSocketServer 4 + *

+ */ + boolean runWithExternalMockServer = true; + + /** + * Last results: + * Data sent mesured in kilobytes. + * Avg time mesured in microsecs. + * + * NOPOutputStream: + * | | Runs | Avg time | Data sent | + * | MinimalObj Ext | 10000 | | | + * | MinimalObj Ser | 10000 | | | + * | LoggEvent Ext | 10000 | | | + * | LoggEvent Ser | 10000 | | | + * + * External MockServer with 45 letters-long message: on localhost + * (always the same message) + * | | Runs | Avg time | Data sent | + * | MinimalObj Ext | 10000 | - | - | + * | MinimalObj Ser | 10000 | 74 | 248 | + * | LoggEvent Ext | 10000 | - | - | + * | LoggEvent Ser | 10000 | 156 | 835 | + * pauseFrequency = 10 and pauseLengthInMillis = 20 + * + * External MockServer with 45 letters-long message: on localhost + * (different message each time) + * | | Runs | Avg time | Data sent | + * | MinimalObj Ext | 10000 | | | + * | MinimalObj Ser | 10000 | 73 | 1139 | + * | LoggEvent Ext | 10000 | | | + * | LoggEvent Ser | 10000 | 162 | 1752 | + * pauseFrequency = 10 and pauseLengthInMillis = 20 + * + * External MockServer with 45 letters-long message: on PIXIE + * (always the same message) + * | | Runs | Avg time | Data sent | + * | MinimalObj Ext | 10000 | - | - | + * | MinimalObj Ser | 10000 | 29 | 248 | + * | LoggEvent Ext | 10000 | - | - | + * | LoggEvent Ser | 10000 | 42 | 835 | + * pauseFrequency = 10 and pauseLengthInMillis = 20 + * + * External MockServer with 45 letters-long message: on PIXIE + * (different message each time) + * | | Runs | Avg time | Data sent | + * | MinimalObj Ext | 10000 | | | + * | MinimalObj Ser | 10000 | 27 | 1139 | + * | LoggEvent Ext | 10000 | | | + * | LoggEvent Ser | 10000 | 44 | 1752 | + * pauseFrequency = 10 and pauseLengthInMillis = 20 + * + */ + + public void setUp() throws Exception { + super.setUp(); + if (runWithExternalMockServer) { + oos = new ObjectOutputStream(new Socket("pixie", + ExternalMockSocketServer.PORT).getOutputStream()); + } else { + oos = new ObjectOutputStream(new NOPOutputStream()); + } + } + + public void tearDown() throws Exception { + super.tearDown(); + oos.close(); + oos = null; + } + + public void runPerfTest(Builder builder, String label) throws Exception { + // long time1 = System.nanoTime(); + + // Object builtObject = builder.build(1); + + // first run for just in time compiler + int resetCounter = 0; + int pauseCounter = 0; + for (int i = 0; i < loopNumber; i++) { + try { + oos.writeObject(builder.build(i)); + oos.flush(); + if (++resetCounter >= resetFrequency) { + oos.reset(); + resetCounter = 0; + } + if (++pauseCounter >= pauseFrequency) { + Thread.sleep(pauseLengthInMillis); + pauseCounter = 0; + } + + } catch (IOException ex) { + fail(ex.getMessage()); + } + } + + // second run + Long t1; + Long t2; + Long total = 0L; + resetCounter = 0; + pauseCounter = 0; + // System.out.println("Beginning mesured run"); + for (int i = 0; i < loopNumber; i++) { + try { + t1 = System.nanoTime(); + oos.writeObject(builder.build(i)); + oos.flush(); + t2 = System.nanoTime(); + total += (t2 - t1); + if (++resetCounter >= resetFrequency) { + oos.reset(); + resetCounter = 0; + } + if (++pauseCounter >= pauseFrequency) { + Thread.sleep(pauseLengthInMillis); + pauseCounter = 0; + } + } catch (IOException ex) { + fail(ex.getMessage()); + } + } + total /= 1000; + System.out.println(label + " : average time = " + total / loopNumber + + " microsecs after " + loopNumber + " writes."); + + // long time2 = System.nanoTime(); + // System.out.println("********* -> Time needed to run the test method: " + + // Long.toString(time2-time1)); + } + + // public void testWithMinimalExternalization() throws Exception { + // Builder builder = new MinimalExtBuilder(); + // runPerfTest(builder, "Minimal object externalization"); + // } + + public void testWithMinimalSerialization() throws Exception { + Builder builder = new MinimalSerBuilder(); + runPerfTest(builder, "Minimal object serialization"); + } + + // public void testWithExternalization() throws Exception { + // Builder builder = new LoggingEventExtBuilder(); + // runPerfTest(builder, "LoggingEvent object externalization"); + // } + + public void testWithSerialization() throws Exception { + Builder builder = new TrivialLoggingEventBuilder(); + runPerfTest(builder, "LoggingEvent object serialization"); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java index df183b15505410134510ebf8a89e45d580bac521..45cf3b9b3922c6a960822fb635ef1072b15e0fe9 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java @@ -1,271 +1,271 @@ -/** - * 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.classic.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.util.Map; - -import org.junit.Test; -import org.slf4j.MDC; -import org.slf4j.Marker; -import org.slf4j.MarkerFactory; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggerContextVO; -import ch.qos.logback.core.read.ListAppender; -import ch.qos.logback.core.util.StatusPrinter; - -public class SocketAppenderTest { - - static final String LIST_APPENDER_NAME = "la"; - static final int JOIN_OR_WAIT_TIMEOUT = 200; - static final int SLEEP_AFTER_LOG = 100; - - int port = 4561; - LoggerContext lc = new LoggerContext(); - LoggerContext serverLC = new LoggerContext(); - ListAppender la = new ListAppender(); - SocketAppender socketAppender = new SocketAppender(); - private boolean includeCallerData = false; - private SimpleSocketServer simpleSocketServer; - - @Test - public void startFailNoRemoteHost() { - SocketAppender appender = new SocketAppender(); - appender.setContext(lc); - appender.setPort(123); - appender.start(); - assertEquals(1, lc.getStatusManager().getCount()); - } - - @Test - public void recieveMessage() throws InterruptedException { - fireServer(); - waitForServerToStart(); - configureClient(); - - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - logger.debug("test msg"); - - Thread.sleep(SLEEP_AFTER_LOG); - - simpleSocketServer.close(); - simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); - assertTrue(simpleSocketServer.isClosed()); - assertEquals(1, la.list.size()); - - ILoggingEvent remoteEvent = la.list.get(0); - assertNull(remoteEvent.getCallerData()); - assertEquals("test msg", remoteEvent.getMessage()); - assertEquals(Level.DEBUG, remoteEvent.getLevel()); - } - - @Test - public void recieveWithContext() throws InterruptedException { - fireServer(); - waitForServerToStart(); - configureClient(); - - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - logger.debug("test msg"); - Thread.sleep(SLEEP_AFTER_LOG); - - simpleSocketServer.close(); - simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); - assertTrue(simpleSocketServer.isClosed()); - assertEquals(1, la.list.size()); - - ILoggingEvent remoteEvent = la.list.get(0); - - String loggerName = remoteEvent.getLoggerName(); - assertNotNull(loggerName); - assertEquals(Logger.ROOT_LOGGER_NAME, loggerName); - - LoggerContextVO loggerContextRemoteView = remoteEvent - .getLoggerContextVO(); - assertNull(remoteEvent.getCallerData()); - assertNotNull(loggerContextRemoteView); - assertEquals("test", loggerContextRemoteView.getName()); - Map props = loggerContextRemoteView.getPropertyMap(); - assertEquals("testValue", props.get("testKey")); - } - - @Test - public void messageWithMDC() throws InterruptedException { - fireServer(); - waitForServerToStart(); - configureClient(); - - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - - MDC.put("key", "testValue"); - logger.debug("test msg"); - - Thread.sleep(SLEEP_AFTER_LOG); - simpleSocketServer.close(); - simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); - assertTrue(simpleSocketServer.isClosed()); - ListAppender la = getListAppender(); - assertEquals(1, la.list.size()); - - ILoggingEvent remoteEvent = la.list.get(0); - Map MDCPropertyMap = remoteEvent.getMDCPropertyMap(); - assertEquals("testValue", MDCPropertyMap.get("key")); - assertNull(remoteEvent.getCallerData()); - } - - // test http://jira.qos.ch/browse/LBCLASSIC-145 - @Test - public void withCallerData() throws InterruptedException { - includeCallerData = true; - fireServer(); - waitForServerToStart(); - configureClient(); - - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - logger.debug("test msg"); - - Thread.sleep(SLEEP_AFTER_LOG); - simpleSocketServer.close(); - simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); - assertTrue(simpleSocketServer.isClosed()); - ListAppender la = getListAppender(); - assertEquals(1, la.list.size()); - - ILoggingEvent remoteEvent = la.list.get(0); - assertNotNull(remoteEvent.getCallerData()); - } - - @Test - public void messageWithMarker() throws InterruptedException { - fireServer(); - waitForServerToStart(); - - // Thread.sleep(SLEEP_AFTER_SERVER_START); - configureClient(); - - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - - Marker marker = MarkerFactory.getMarker("testMarker"); - logger.debug(marker, "test msg"); - Thread.sleep(SLEEP_AFTER_LOG); - - simpleSocketServer.close(); - simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); - assertTrue(simpleSocketServer.isClosed()); - assertEquals(1, la.list.size()); - - ILoggingEvent remoteEvent = la.list.get(0); - assertEquals("testMarker", remoteEvent.getMarker().getName()); - } - - @Test - public void messageWithUpdatedMDC() throws InterruptedException { - fireServer(); - waitForServerToStart(); - - configureClient(); - - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - - MDC.put("key", "testValue"); - logger.debug("test msg"); - - MDC.put("key", "updatedTestValue"); - logger.debug("test msg 2"); - Thread.sleep(SLEEP_AFTER_LOG); - - simpleSocketServer.close(); - simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); - assertTrue(simpleSocketServer.isClosed()); - ListAppender la = getListAppender(); - - assertEquals(2, la.list.size()); - - // We observe the second logging event. It should provide us with - // the updated MDC property. - ILoggingEvent remoteEvent = la.list.get(1); - Map MDCPropertyMap = remoteEvent.getMDCPropertyMap(); - assertEquals("updatedTestValue", MDCPropertyMap.get("key")); - } - - @Test - public void lateServerLaunch() throws InterruptedException { - socketAppender.setReconnectionDelay(20); - configureClient(); - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - logger.debug("test msg"); - - fireServer(); - waitForServerToStart(); - Thread.sleep(SLEEP_AFTER_LOG); // allow time for client and server to - // connect - logger.debug("test msg 2"); - Thread.sleep(SLEEP_AFTER_LOG); - - simpleSocketServer.close(); - Thread.sleep(SLEEP_AFTER_LOG); - simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); - StatusPrinter.print(lc); - assertTrue(simpleSocketServer.isClosed()); - assertEquals(1, la.list.size()); - - ILoggingEvent remoteEvent = la.list.get(0); - assertEquals("test msg 2", remoteEvent.getMessage()); - assertEquals(Level.DEBUG, remoteEvent.getLevel()); - } - - private void waitForServerToStart() throws InterruptedException { - synchronized (simpleSocketServer) { - simpleSocketServer.wait(JOIN_OR_WAIT_TIMEOUT); - } - } - - private void fireServer() throws InterruptedException { - Logger root = serverLC.getLogger("root"); - la.setName(LIST_APPENDER_NAME); - la.setContext(serverLC); - la.start(); - root.addAppender(la); - simpleSocketServer = new SimpleSocketServer(serverLC, port); - simpleSocketServer.start(); - Thread.yield(); - } - - ListAppender getListAppender() { - Logger root = serverLC.getLogger("root"); - return (ListAppender) root.getAppender(LIST_APPENDER_NAME); - } - - private void configureClient() { - lc = new LoggerContext(); - lc.setName("test"); - lc.putProperty("testKey", "testValue"); - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - socketAppender.setContext(lc); - socketAppender.setName("socket"); - socketAppender.setPort(port); - socketAppender.setRemoteHost("localhost"); - socketAppender.setIncludeCallerData(includeCallerData); - root.addAppender(socketAppender); - socketAppender.start(); - } -} +/** + * 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.classic.net; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.Test; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggerContextVO; +import ch.qos.logback.core.read.ListAppender; +import ch.qos.logback.core.util.StatusPrinter; + +public class SocketAppenderTest { + + static final String LIST_APPENDER_NAME = "la"; + static final int JOIN_OR_WAIT_TIMEOUT = 200; + static final int SLEEP_AFTER_LOG = 100; + + int port = 4561; + LoggerContext lc = new LoggerContext(); + LoggerContext serverLC = new LoggerContext(); + ListAppender la = new ListAppender(); + SocketAppender socketAppender = new SocketAppender(); + private boolean includeCallerData = false; + private SimpleSocketServer simpleSocketServer; + + @Test + public void startFailNoRemoteHost() { + SocketAppender appender = new SocketAppender(); + appender.setContext(lc); + appender.setPort(123); + appender.start(); + assertEquals(1, lc.getStatusManager().getCount()); + } + + @Test + public void recieveMessage() throws InterruptedException { + fireServer(); + waitForServerToStart(); + configureClient(); + + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + logger.debug("test msg"); + + Thread.sleep(SLEEP_AFTER_LOG); + + simpleSocketServer.close(); + simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); + assertTrue(simpleSocketServer.isClosed()); + assertEquals(1, la.list.size()); + + ILoggingEvent remoteEvent = la.list.get(0); + assertNull(remoteEvent.getCallerData()); + assertEquals("test msg", remoteEvent.getMessage()); + assertEquals(Level.DEBUG, remoteEvent.getLevel()); + } + + @Test + public void recieveWithContext() throws InterruptedException { + fireServer(); + waitForServerToStart(); + configureClient(); + + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + logger.debug("test msg"); + Thread.sleep(SLEEP_AFTER_LOG); + + simpleSocketServer.close(); + simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); + assertTrue(simpleSocketServer.isClosed()); + assertEquals(1, la.list.size()); + + ILoggingEvent remoteEvent = la.list.get(0); + + String loggerName = remoteEvent.getLoggerName(); + assertNotNull(loggerName); + assertEquals(Logger.ROOT_LOGGER_NAME, loggerName); + + LoggerContextVO loggerContextRemoteView = remoteEvent + .getLoggerContextVO(); + assertNull(remoteEvent.getCallerData()); + assertNotNull(loggerContextRemoteView); + assertEquals("test", loggerContextRemoteView.getName()); + Map props = loggerContextRemoteView.getPropertyMap(); + assertEquals("testValue", props.get("testKey")); + } + + @Test + public void messageWithMDC() throws InterruptedException { + fireServer(); + waitForServerToStart(); + configureClient(); + + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + + MDC.put("key", "testValue"); + logger.debug("test msg"); + + Thread.sleep(SLEEP_AFTER_LOG); + simpleSocketServer.close(); + simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); + assertTrue(simpleSocketServer.isClosed()); + ListAppender la = getListAppender(); + assertEquals(1, la.list.size()); + + ILoggingEvent remoteEvent = la.list.get(0); + Map MDCPropertyMap = remoteEvent.getMDCPropertyMap(); + assertEquals("testValue", MDCPropertyMap.get("key")); + assertNull(remoteEvent.getCallerData()); + } + + // test http://jira.qos.ch/browse/LBCLASSIC-145 + @Test + public void withCallerData() throws InterruptedException { + includeCallerData = true; + fireServer(); + waitForServerToStart(); + configureClient(); + + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + logger.debug("test msg"); + + Thread.sleep(SLEEP_AFTER_LOG); + simpleSocketServer.close(); + simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); + assertTrue(simpleSocketServer.isClosed()); + ListAppender la = getListAppender(); + assertEquals(1, la.list.size()); + + ILoggingEvent remoteEvent = la.list.get(0); + assertNotNull(remoteEvent.getCallerData()); + } + + @Test + public void messageWithMarker() throws InterruptedException { + fireServer(); + waitForServerToStart(); + + // Thread.sleep(SLEEP_AFTER_SERVER_START); + configureClient(); + + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + + Marker marker = MarkerFactory.getMarker("testMarker"); + logger.debug(marker, "test msg"); + Thread.sleep(SLEEP_AFTER_LOG); + + simpleSocketServer.close(); + simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); + assertTrue(simpleSocketServer.isClosed()); + assertEquals(1, la.list.size()); + + ILoggingEvent remoteEvent = la.list.get(0); + assertEquals("testMarker", remoteEvent.getMarker().getName()); + } + + @Test + public void messageWithUpdatedMDC() throws InterruptedException { + fireServer(); + waitForServerToStart(); + + configureClient(); + + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + + MDC.put("key", "testValue"); + logger.debug("test msg"); + + MDC.put("key", "updatedTestValue"); + logger.debug("test msg 2"); + Thread.sleep(SLEEP_AFTER_LOG); + + simpleSocketServer.close(); + simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); + assertTrue(simpleSocketServer.isClosed()); + ListAppender la = getListAppender(); + + assertEquals(2, la.list.size()); + + // We observe the second logging event. It should provide us with + // the updated MDC property. + ILoggingEvent remoteEvent = la.list.get(1); + Map MDCPropertyMap = remoteEvent.getMDCPropertyMap(); + assertEquals("updatedTestValue", MDCPropertyMap.get("key")); + } + + @Test + public void lateServerLaunch() throws InterruptedException { + socketAppender.setReconnectionDelay(20); + configureClient(); + Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + logger.debug("test msg"); + + fireServer(); + waitForServerToStart(); + Thread.sleep(SLEEP_AFTER_LOG); // allow time for client and server to + // connect + logger.debug("test msg 2"); + Thread.sleep(SLEEP_AFTER_LOG); + + simpleSocketServer.close(); + Thread.sleep(SLEEP_AFTER_LOG); + simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT); + StatusPrinter.print(lc); + assertTrue(simpleSocketServer.isClosed()); + assertEquals(1, la.list.size()); + + ILoggingEvent remoteEvent = la.list.get(0); + assertEquals("test msg 2", remoteEvent.getMessage()); + assertEquals(Level.DEBUG, remoteEvent.getLevel()); + } + + private void waitForServerToStart() throws InterruptedException { + synchronized (simpleSocketServer) { + simpleSocketServer.wait(JOIN_OR_WAIT_TIMEOUT); + } + } + + private void fireServer() throws InterruptedException { + Logger root = serverLC.getLogger("root"); + la.setName(LIST_APPENDER_NAME); + la.setContext(serverLC); + la.start(); + root.addAppender(la); + simpleSocketServer = new SimpleSocketServer(serverLC, port); + simpleSocketServer.start(); + Thread.yield(); + } + + ListAppender getListAppender() { + Logger root = serverLC.getLogger("root"); + return (ListAppender) root.getAppender(LIST_APPENDER_NAME); + } + + private void configureClient() { + lc = new LoggerContext(); + lc.setName("test"); + lc.putProperty("testKey", "testValue"); + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + socketAppender.setContext(lc); + socketAppender.setName("socket"); + socketAppender.setPort(port); + socketAppender.setRemoteHost("localhost"); + socketAppender.setIncludeCallerData(includeCallerData); + root.addAppender(socketAppender); + socketAppender.start(); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/SyslogAppenderTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/SyslogAppenderTest.java index fe464defcfd416852e22a4bcf2dc72ed9f0e7341..d2a0567f507f93b23dd3aeeefbb826189b4635bf 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/SyslogAppenderTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/SyslogAppenderTest.java @@ -1,159 +1,159 @@ -/** - * 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.classic.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.ClassicTestConstants; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.net.mock.MockSyslogServer; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.net.SyslogConstants; -import ch.qos.logback.core.testUtil.RandomUtil; - -public class SyslogAppenderTest { - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void basic() throws InterruptedException { - int port = RandomUtil.getRandomServerPort(); - - MockSyslogServer mockServer = new MockSyslogServer(1, port); - mockServer.start(); - // give MockSyslogServer head start - Thread.sleep(100); - - LoggerContext lc = new LoggerContext(); - lc.setName("test"); - SyslogAppender sa = new SyslogAppender(); - sa.setContext(lc); - sa.setSyslogHost("localhost"); - sa.setFacility("MAIL"); - sa.setPort(port); - sa.setSuffixPattern("[%thread] %logger %msg"); - sa.start(); - assertTrue(sa.isStarted()); - - String loggerName = this.getClass().getName(); - Logger logger = lc.getLogger(loggerName); - logger.addAppender(sa); - String logMsg = "hello"; - logger.debug(logMsg); - - // wait max 2 seconds for mock server to finish. However, it should - // much sooner than that. - mockServer.join(8000); - assertTrue(mockServer.isFinished()); - assertEquals(1, mockServer.getMessageList().size()); - String msg = mockServer.getMessageList().get(0); - - String threadName = Thread.currentThread().getName(); - - String expected = "<" - + (SyslogConstants.LOG_MAIL + SyslogConstants.DEBUG_SEVERITY) + ">"; - assertTrue(msg.startsWith(expected)); - - String first = "<\\d{2}>\\w{3} \\d{2} \\d{2}(:\\d{2}){2} [\\w.-]* "; - checkRegexMatch(msg, first + "\\[" + threadName + "\\] " + loggerName - + " " + logMsg); - - } - - @Test - public void tException() throws InterruptedException { - int port = RandomUtil.getRandomServerPort(); - - MockSyslogServer mockServer = new MockSyslogServer(21, port); - mockServer.start(); - // give MockSyslogServer head start - Thread.sleep(100); - - LoggerContext lc = new LoggerContext(); - lc.setName("test"); - SyslogAppender sa = new SyslogAppender(); - sa.setContext(lc); - sa.setSyslogHost("localhost"); - sa.setFacility("MAIL"); - sa.setPort(port); - sa.setSuffixPattern("[%thread] %logger %msg"); - sa.start(); - assertTrue(sa.isStarted()); - - String loggerName = this.getClass().getName(); - Logger logger = lc.getLogger(loggerName); - logger.addAppender(sa); - String logMsg = "hello"; - String exMsg = "just testing"; - Exception ex = new Exception(exMsg); - logger.debug(logMsg, ex); - // StatusPrinter.print(lc.getStatusManager()); - - // wait max 2 seconds for mock server to finish. However, it should - // much sooner than that. - mockServer.join(8000); - assertTrue(mockServer.isFinished()); - - // message + 20 lines of stacktrace - assertEquals(21, mockServer.getMessageList().size()); - // int i = 0; - // for (String line: mockServer.msgList) { - // System.out.println(i++ + ": " + line); - // } - - String msg = mockServer.getMessageList().get(0); - String expected = "<" - + (SyslogConstants.LOG_MAIL + SyslogConstants.DEBUG_SEVERITY) + ">"; - assertTrue(msg.startsWith(expected)); - - String expectedPrefix = "<\\d{2}>\\w{3} \\d{2} \\d{2}(:\\d{2}){2} [\\w.-]* "; - String threadName = Thread.currentThread().getName(); - String regex = expectedPrefix + "\\[" + threadName + "\\] " - + loggerName + " " + logMsg; - checkRegexMatch(msg, regex); - } - - private void checkRegexMatch(String s, String regex) { - assertTrue("The string ["+s+"] did not match regex ["+regex+"]", s.matches(regex)); - } - - @Test - public void LBCLASSIC_50() throws JoranException { - - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - lc.reset(); - configurator.doConfigure(ClassicTestConstants.JORAN_INPUT_PREFIX - + "syslog_LBCLASSIC_50.xml"); - - org.slf4j.Logger logger = LoggerFactory.getLogger(this.getClass()); - logger.info("hello"); - } -} +/** + * 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.classic.net; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.ClassicTestConstants; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.net.mock.MockSyslogServer; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.net.SyslogConstants; +import ch.qos.logback.core.testUtil.RandomUtil; + +public class SyslogAppenderTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void basic() throws InterruptedException { + int port = RandomUtil.getRandomServerPort(); + + MockSyslogServer mockServer = new MockSyslogServer(1, port); + mockServer.start(); + // give MockSyslogServer head start + Thread.sleep(100); + + LoggerContext lc = new LoggerContext(); + lc.setName("test"); + SyslogAppender sa = new SyslogAppender(); + sa.setContext(lc); + sa.setSyslogHost("localhost"); + sa.setFacility("MAIL"); + sa.setPort(port); + sa.setSuffixPattern("[%thread] %logger %msg"); + sa.start(); + assertTrue(sa.isStarted()); + + String loggerName = this.getClass().getName(); + Logger logger = lc.getLogger(loggerName); + logger.addAppender(sa); + String logMsg = "hello"; + logger.debug(logMsg); + + // wait max 2 seconds for mock server to finish. However, it should + // much sooner than that. + mockServer.join(8000); + assertTrue(mockServer.isFinished()); + assertEquals(1, mockServer.getMessageList().size()); + String msg = mockServer.getMessageList().get(0); + + String threadName = Thread.currentThread().getName(); + + String expected = "<" + + (SyslogConstants.LOG_MAIL + SyslogConstants.DEBUG_SEVERITY) + ">"; + assertTrue(msg.startsWith(expected)); + + String first = "<\\d{2}>\\w{3} \\d{2} \\d{2}(:\\d{2}){2} [\\w.-]* "; + checkRegexMatch(msg, first + "\\[" + threadName + "\\] " + loggerName + + " " + logMsg); + + } + + @Test + public void tException() throws InterruptedException { + int port = RandomUtil.getRandomServerPort(); + + MockSyslogServer mockServer = new MockSyslogServer(21, port); + mockServer.start(); + // give MockSyslogServer head start + Thread.sleep(100); + + LoggerContext lc = new LoggerContext(); + lc.setName("test"); + SyslogAppender sa = new SyslogAppender(); + sa.setContext(lc); + sa.setSyslogHost("localhost"); + sa.setFacility("MAIL"); + sa.setPort(port); + sa.setSuffixPattern("[%thread] %logger %msg"); + sa.start(); + assertTrue(sa.isStarted()); + + String loggerName = this.getClass().getName(); + Logger logger = lc.getLogger(loggerName); + logger.addAppender(sa); + String logMsg = "hello"; + String exMsg = "just testing"; + Exception ex = new Exception(exMsg); + logger.debug(logMsg, ex); + // StatusPrinter.print(lc.getStatusManager()); + + // wait max 2 seconds for mock server to finish. However, it should + // much sooner than that. + mockServer.join(8000); + assertTrue(mockServer.isFinished()); + + // message + 20 lines of stacktrace + assertEquals(21, mockServer.getMessageList().size()); + // int i = 0; + // for (String line: mockServer.msgList) { + // System.out.println(i++ + ": " + line); + // } + + String msg = mockServer.getMessageList().get(0); + String expected = "<" + + (SyslogConstants.LOG_MAIL + SyslogConstants.DEBUG_SEVERITY) + ">"; + assertTrue(msg.startsWith(expected)); + + String expectedPrefix = "<\\d{2}>\\w{3} \\d{2} \\d{2}(:\\d{2}){2} [\\w.-]* "; + String threadName = Thread.currentThread().getName(); + String regex = expectedPrefix + "\\[" + threadName + "\\] " + + loggerName + " " + logMsg; + checkRegexMatch(msg, regex); + } + + private void checkRegexMatch(String s, String regex) { + assertTrue("The string ["+s+"] did not match regex ["+regex+"]", s.matches(regex)); + } + + @Test + public void LBCLASSIC_50() throws JoranException { + + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + lc.reset(); + configurator.doConfigure(ClassicTestConstants.JORAN_INPUT_PREFIX + + "syslog_LBCLASSIC_50.xml"); + + org.slf4j.Logger logger = LoggerFactory.getLogger(this.getClass()); + logger.info("hello"); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockObjectMessage.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockObjectMessage.java index 6612b14805ea917ed8214390ad80074fcf269713..a6f53e263a5d9c05a8c242a95933d42eae20f548 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockObjectMessage.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockObjectMessage.java @@ -1,260 +1,260 @@ -/** - * 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.classic.net.mock; - -import java.io.Serializable; -import java.util.Enumeration; - -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.ObjectMessage; - -public class MockObjectMessage implements ObjectMessage { - - Serializable object; - - public Serializable getObject() throws JMSException { - return object; - } - - public void setObject(Serializable object) throws JMSException { - this.object = object; - } - - public void acknowledge() throws JMSException { - - - } - - public void clearBody() throws JMSException { - - - } - - public void clearProperties() throws JMSException { - - - } - - public boolean getBooleanProperty(String arg0) throws JMSException { - - return false; - } - - public byte getByteProperty(String arg0) throws JMSException { - - return 0; - } - - public double getDoubleProperty(String arg0) throws JMSException { - - return 0; - } - - public float getFloatProperty(String arg0) throws JMSException { - - return 0; - } - - public int getIntProperty(String arg0) throws JMSException { - - return 0; - } - - public String getJMSCorrelationID() throws JMSException { - - return null; - } - - public byte[] getJMSCorrelationIDAsBytes() throws JMSException { - - return null; - } - - public int getJMSDeliveryMode() throws JMSException { - - return 0; - } - - public Destination getJMSDestination() throws JMSException { - - return null; - } - - public long getJMSExpiration() throws JMSException { - - return 0; - } - - public String getJMSMessageID() throws JMSException { - - return null; - } - - public int getJMSPriority() throws JMSException { - - return 0; - } - - public boolean getJMSRedelivered() throws JMSException { - - return false; - } - - public Destination getJMSReplyTo() throws JMSException { - - return null; - } - - public long getJMSTimestamp() throws JMSException { - - return 0; - } - - public String getJMSType() throws JMSException { - - return null; - } - - public long getLongProperty(String arg0) throws JMSException { - - return 0; - } - - public Object getObjectProperty(String arg0) throws JMSException { - - return null; - } - - public Enumeration getPropertyNames() throws JMSException { - - return null; - } - - public short getShortProperty(String arg0) throws JMSException { - - return 0; - } - - public String getStringProperty(String arg0) throws JMSException { - - return null; - } - - public boolean propertyExists(String arg0) throws JMSException { - - return false; - } - - public void setBooleanProperty(String arg0, boolean arg1) throws JMSException { - - - } - - public void setByteProperty(String arg0, byte arg1) throws JMSException { - - - } - - public void setDoubleProperty(String arg0, double arg1) throws JMSException { - - - } - - public void setFloatProperty(String arg0, float arg1) throws JMSException { - - - } - - public void setIntProperty(String arg0, int arg1) throws JMSException { - - - } - - public void setJMSCorrelationID(String arg0) throws JMSException { - - - } - - public void setJMSCorrelationIDAsBytes(byte[] arg0) throws JMSException { - - - } - - public void setJMSDeliveryMode(int arg0) throws JMSException { - - - } - - public void setJMSDestination(Destination arg0) throws JMSException { - - - } - - public void setJMSExpiration(long arg0) throws JMSException { - - - } - - public void setJMSMessageID(String arg0) throws JMSException { - - - } - - public void setJMSPriority(int arg0) throws JMSException { - - - } - - public void setJMSRedelivered(boolean arg0) throws JMSException { - - - } - - public void setJMSReplyTo(Destination arg0) throws JMSException { - - - } - - public void setJMSTimestamp(long arg0) throws JMSException { - - - } - - public void setJMSType(String arg0) throws JMSException { - - - } - - public void setLongProperty(String arg0, long arg1) throws JMSException { - - - } - - public void setObjectProperty(String arg0, Object arg1) throws JMSException { - - - } - - public void setShortProperty(String arg0, short arg1) throws JMSException { - - - } - - public void setStringProperty(String arg0, String arg1) throws JMSException { - - - } - -} +/** + * 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.classic.net.mock; + +import java.io.Serializable; +import java.util.Enumeration; + +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.ObjectMessage; + +public class MockObjectMessage implements ObjectMessage { + + Serializable object; + + public Serializable getObject() throws JMSException { + return object; + } + + public void setObject(Serializable object) throws JMSException { + this.object = object; + } + + public void acknowledge() throws JMSException { + + + } + + public void clearBody() throws JMSException { + + + } + + public void clearProperties() throws JMSException { + + + } + + public boolean getBooleanProperty(String arg0) throws JMSException { + + return false; + } + + public byte getByteProperty(String arg0) throws JMSException { + + return 0; + } + + public double getDoubleProperty(String arg0) throws JMSException { + + return 0; + } + + public float getFloatProperty(String arg0) throws JMSException { + + return 0; + } + + public int getIntProperty(String arg0) throws JMSException { + + return 0; + } + + public String getJMSCorrelationID() throws JMSException { + + return null; + } + + public byte[] getJMSCorrelationIDAsBytes() throws JMSException { + + return null; + } + + public int getJMSDeliveryMode() throws JMSException { + + return 0; + } + + public Destination getJMSDestination() throws JMSException { + + return null; + } + + public long getJMSExpiration() throws JMSException { + + return 0; + } + + public String getJMSMessageID() throws JMSException { + + return null; + } + + public int getJMSPriority() throws JMSException { + + return 0; + } + + public boolean getJMSRedelivered() throws JMSException { + + return false; + } + + public Destination getJMSReplyTo() throws JMSException { + + return null; + } + + public long getJMSTimestamp() throws JMSException { + + return 0; + } + + public String getJMSType() throws JMSException { + + return null; + } + + public long getLongProperty(String arg0) throws JMSException { + + return 0; + } + + public Object getObjectProperty(String arg0) throws JMSException { + + return null; + } + + public Enumeration getPropertyNames() throws JMSException { + + return null; + } + + public short getShortProperty(String arg0) throws JMSException { + + return 0; + } + + public String getStringProperty(String arg0) throws JMSException { + + return null; + } + + public boolean propertyExists(String arg0) throws JMSException { + + return false; + } + + public void setBooleanProperty(String arg0, boolean arg1) throws JMSException { + + + } + + public void setByteProperty(String arg0, byte arg1) throws JMSException { + + + } + + public void setDoubleProperty(String arg0, double arg1) throws JMSException { + + + } + + public void setFloatProperty(String arg0, float arg1) throws JMSException { + + + } + + public void setIntProperty(String arg0, int arg1) throws JMSException { + + + } + + public void setJMSCorrelationID(String arg0) throws JMSException { + + + } + + public void setJMSCorrelationIDAsBytes(byte[] arg0) throws JMSException { + + + } + + public void setJMSDeliveryMode(int arg0) throws JMSException { + + + } + + public void setJMSDestination(Destination arg0) throws JMSException { + + + } + + public void setJMSExpiration(long arg0) throws JMSException { + + + } + + public void setJMSMessageID(String arg0) throws JMSException { + + + } + + public void setJMSPriority(int arg0) throws JMSException { + + + } + + public void setJMSRedelivered(boolean arg0) throws JMSException { + + + } + + public void setJMSReplyTo(Destination arg0) throws JMSException { + + + } + + public void setJMSTimestamp(long arg0) throws JMSException { + + + } + + public void setJMSType(String arg0) throws JMSException { + + + } + + public void setLongProperty(String arg0, long arg1) throws JMSException { + + + } + + public void setObjectProperty(String arg0, Object arg1) throws JMSException { + + + } + + public void setShortProperty(String arg0, short arg1) throws JMSException { + + + } + + public void setStringProperty(String arg0, String arg1) throws JMSException { + + + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueue.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueue.java index 0e0bc4eefb245c1454c90a09a93d5283437b0af8..1d48abb8783fa19ad07b02d177ca01e3f7b36ea4 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueue.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueue.java @@ -1,31 +1,31 @@ -/** - * 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.classic.net.mock; - -import javax.jms.JMSException; -import javax.jms.Queue; - -public class MockQueue implements Queue { - - String name; - - public MockQueue(String name) { - this.name = name; - } - - public String getQueueName() throws JMSException { - return name; - } - -} +/** + * 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.classic.net.mock; + +import javax.jms.JMSException; +import javax.jms.Queue; + +public class MockQueue implements Queue { + + String name; + + public MockQueue(String name) { + this.name = name; + } + + public String getQueueName() throws JMSException { + return name; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueConnection.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueConnection.java index 7cc1359cb19995ae8154c1f5a6f83ab757415d5a..7fd48327e87fae6671aadbf594ac8df06f4ed228 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueConnection.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueConnection.java @@ -1,96 +1,96 @@ -/** - * 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.classic.net.mock; - -import javax.jms.ConnectionConsumer; -import javax.jms.ConnectionMetaData; -import javax.jms.Destination; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.jms.Queue; -import javax.jms.QueueConnection; -import javax.jms.QueueSession; -import javax.jms.ServerSessionPool; -import javax.jms.Session; -import javax.jms.Topic; - -public class MockQueueConnection implements QueueConnection { - - MockQueueSession session = new MockQueueSession(); - - public QueueSession createQueueSession(boolean arg0, int arg1) throws JMSException { - return session; - } - - public ConnectionConsumer createConnectionConsumer(Queue arg0, String arg1, ServerSessionPool arg2, int arg3) throws JMSException { - - return null; - } - - public void close() throws JMSException { - - - } - - public ConnectionConsumer createConnectionConsumer(Destination arg0, String arg1, ServerSessionPool arg2, int arg3) throws JMSException { - - return null; - } - - public ConnectionConsumer createDurableConnectionConsumer(Topic arg0, String arg1, String arg2, ServerSessionPool arg3, int arg4) throws JMSException { - - return null; - } - - public Session createSession(boolean arg0, int arg1) throws JMSException { - - return null; - } - - public String getClientID() throws JMSException { - - return null; - } - - public ExceptionListener getExceptionListener() throws JMSException { - - return null; - } - - public ConnectionMetaData getMetaData() throws JMSException { - - return null; - } - - public void setClientID(String arg0) throws JMSException { - - - } - - public void setExceptionListener(ExceptionListener arg0) throws JMSException { - - - } - - public void start() throws JMSException { - - - } - - public void stop() throws JMSException { - - - } - -} +/** + * 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.classic.net.mock; + +import javax.jms.ConnectionConsumer; +import javax.jms.ConnectionMetaData; +import javax.jms.Destination; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.jms.Queue; +import javax.jms.QueueConnection; +import javax.jms.QueueSession; +import javax.jms.ServerSessionPool; +import javax.jms.Session; +import javax.jms.Topic; + +public class MockQueueConnection implements QueueConnection { + + MockQueueSession session = new MockQueueSession(); + + public QueueSession createQueueSession(boolean arg0, int arg1) throws JMSException { + return session; + } + + public ConnectionConsumer createConnectionConsumer(Queue arg0, String arg1, ServerSessionPool arg2, int arg3) throws JMSException { + + return null; + } + + public void close() throws JMSException { + + + } + + public ConnectionConsumer createConnectionConsumer(Destination arg0, String arg1, ServerSessionPool arg2, int arg3) throws JMSException { + + return null; + } + + public ConnectionConsumer createDurableConnectionConsumer(Topic arg0, String arg1, String arg2, ServerSessionPool arg3, int arg4) throws JMSException { + + return null; + } + + public Session createSession(boolean arg0, int arg1) throws JMSException { + + return null; + } + + public String getClientID() throws JMSException { + + return null; + } + + public ExceptionListener getExceptionListener() throws JMSException { + + return null; + } + + public ConnectionMetaData getMetaData() throws JMSException { + + return null; + } + + public void setClientID(String arg0) throws JMSException { + + + } + + public void setExceptionListener(ExceptionListener arg0) throws JMSException { + + + } + + public void start() throws JMSException { + + + } + + public void stop() throws JMSException { + + + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueConnectionFactory.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueConnectionFactory.java index 5c802ca6e077c5588eccc20d1d2d05711bf2a147..6cab91224f8986114cd32f2eff6048ed90d54223 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueConnectionFactory.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueConnectionFactory.java @@ -1,42 +1,42 @@ -/** - * 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.classic.net.mock; - -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.QueueConnection; -import javax.jms.QueueConnectionFactory; - -public class MockQueueConnectionFactory implements QueueConnectionFactory { - - MockQueueConnection cnx = new MockQueueConnection(); - - public QueueConnection createQueueConnection() throws JMSException { - return cnx; - } - - public QueueConnection createQueueConnection(String user, String pass) throws JMSException { - - return cnx; - } - - public Connection createConnection() throws JMSException { - return null; - } - - public Connection createConnection(String arg0, String arg1) throws JMSException { - return null; - } - -} +/** + * 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.classic.net.mock; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; + +public class MockQueueConnectionFactory implements QueueConnectionFactory { + + MockQueueConnection cnx = new MockQueueConnection(); + + public QueueConnection createQueueConnection() throws JMSException { + return cnx; + } + + public QueueConnection createQueueConnection(String user, String pass) throws JMSException { + + return cnx; + } + + public Connection createConnection() throws JMSException { + return null; + } + + public Connection createConnection(String arg0, String arg1) throws JMSException { + return null; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueSender.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueSender.java index 84e852fdeb2300e9a45b322edcd8059ed987e891..07bc9ae0fa1f445241aac63f6007b8e843a0517a 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueSender.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueSender.java @@ -1,134 +1,134 @@ -/** - * 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.classic.net.mock; - -import java.util.ArrayList; -import java.util.List; - -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Queue; -import javax.jms.QueueSender; - -public class MockQueueSender implements QueueSender { - - List messageList = new ArrayList(); - Queue queue; - - public MockQueueSender(Queue queue) { - this.queue = queue; - } - - public List getMessageList() { - return messageList; - } - - public Queue getQueue() throws JMSException { - return queue; - } - - public void send(Message message) throws JMSException { - messageList.add(message); - - } - - public void send(Queue arg0, Message arg1) throws JMSException { - - - } - - public void send(Message arg0, int arg1, int arg2, long arg3) throws JMSException { - - - } - - public void send(Queue arg0, Message arg1, int arg2, int arg3, long arg4) throws JMSException { - - - } - - public void close() throws JMSException { - - - } - - public int getDeliveryMode() throws JMSException { - - return 0; - } - - public Destination getDestination() throws JMSException { - - return null; - } - - public boolean getDisableMessageID() throws JMSException { - - return false; - } - - public boolean getDisableMessageTimestamp() throws JMSException { - - return false; - } - - public int getPriority() throws JMSException { - - return 0; - } - - public long getTimeToLive() throws JMSException { - - return 0; - } - - public void send(Destination arg0, Message arg1) throws JMSException { - - - } - - public void send(Destination arg0, Message arg1, int arg2, int arg3, long arg4) throws JMSException { - - - } - - public void setDeliveryMode(int arg0) throws JMSException { - - - } - - public void setDisableMessageID(boolean arg0) throws JMSException { - - - } - - public void setDisableMessageTimestamp(boolean arg0) throws JMSException { - - - } - - public void setPriority(int arg0) throws JMSException { - - - } - - public void setTimeToLive(long arg0) throws JMSException { - - - } - - - -} +/** + * 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.classic.net.mock; + +import java.util.ArrayList; +import java.util.List; + +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.Queue; +import javax.jms.QueueSender; + +public class MockQueueSender implements QueueSender { + + List messageList = new ArrayList(); + Queue queue; + + public MockQueueSender(Queue queue) { + this.queue = queue; + } + + public List getMessageList() { + return messageList; + } + + public Queue getQueue() throws JMSException { + return queue; + } + + public void send(Message message) throws JMSException { + messageList.add(message); + + } + + public void send(Queue arg0, Message arg1) throws JMSException { + + + } + + public void send(Message arg0, int arg1, int arg2, long arg3) throws JMSException { + + + } + + public void send(Queue arg0, Message arg1, int arg2, int arg3, long arg4) throws JMSException { + + + } + + public void close() throws JMSException { + + + } + + public int getDeliveryMode() throws JMSException { + + return 0; + } + + public Destination getDestination() throws JMSException { + + return null; + } + + public boolean getDisableMessageID() throws JMSException { + + return false; + } + + public boolean getDisableMessageTimestamp() throws JMSException { + + return false; + } + + public int getPriority() throws JMSException { + + return 0; + } + + public long getTimeToLive() throws JMSException { + + return 0; + } + + public void send(Destination arg0, Message arg1) throws JMSException { + + + } + + public void send(Destination arg0, Message arg1, int arg2, int arg3, long arg4) throws JMSException { + + + } + + public void setDeliveryMode(int arg0) throws JMSException { + + + } + + public void setDisableMessageID(boolean arg0) throws JMSException { + + + } + + public void setDisableMessageTimestamp(boolean arg0) throws JMSException { + + + } + + public void setPriority(int arg0) throws JMSException { + + + } + + public void setTimeToLive(long arg0) throws JMSException { + + + } + + + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueSession.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueSession.java index a33b09cdf33af782f05ee22d2def5699571458ea..09e3308c9435f45c47035cbcf29e2ab37650d408 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueSession.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockQueueSession.java @@ -1,208 +1,208 @@ -/** - * 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.classic.net.mock; - -import java.io.Serializable; - -import javax.jms.BytesMessage; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.MapMessage; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.ObjectMessage; -import javax.jms.Queue; -import javax.jms.QueueBrowser; -import javax.jms.QueueReceiver; -import javax.jms.QueueSender; -import javax.jms.QueueSession; -import javax.jms.StreamMessage; -import javax.jms.TemporaryQueue; -import javax.jms.TemporaryTopic; -import javax.jms.TextMessage; -import javax.jms.Topic; -import javax.jms.TopicSubscriber; - -public class MockQueueSession implements QueueSession { - - public ObjectMessage createObjectMessage() throws JMSException { - return new MockObjectMessage(); - } - - public QueueSender createSender(Queue queue) throws JMSException { - if (queue == null) { - return null; - } - return new MockQueueSender(queue); - } - - public QueueBrowser createBrowser(Queue arg0) throws JMSException { - - return null; - } - - public QueueBrowser createBrowser(Queue arg0, String arg1) throws JMSException { - - return null; - } - - public Queue createQueue(String arg0) throws JMSException { - - return null; - } - - public QueueReceiver createReceiver(Queue arg0) throws JMSException { - - return null; - } - - public QueueReceiver createReceiver(Queue arg0, String arg1) throws JMSException { - - return null; - } - - public TemporaryQueue createTemporaryQueue() throws JMSException { - - return null; - } - - public void close() throws JMSException { - - - } - - public void commit() throws JMSException { - - - } - - public BytesMessage createBytesMessage() throws JMSException { - - return null; - } - - public MessageConsumer createConsumer(Destination arg0) throws JMSException { - - return null; - } - - public MessageConsumer createConsumer(Destination arg0, String arg1) throws JMSException { - - return null; - } - - public MessageConsumer createConsumer(Destination arg0, String arg1, boolean arg2) throws JMSException { - - return null; - } - - public TopicSubscriber createDurableSubscriber(Topic arg0, String arg1) throws JMSException { - - return null; - } - - public TopicSubscriber createDurableSubscriber(Topic arg0, String arg1, String arg2, boolean arg3) throws JMSException { - - return null; - } - - public MapMessage createMapMessage() throws JMSException { - - return null; - } - - public Message createMessage() throws JMSException { - - return null; - } - - public ObjectMessage createObjectMessage(Serializable arg0) throws JMSException { - - return null; - } - - public MessageProducer createProducer(Destination arg0) throws JMSException { - - return null; - } - - public StreamMessage createStreamMessage() throws JMSException { - - return null; - } - - public TemporaryTopic createTemporaryTopic() throws JMSException { - - return null; - } - - public TextMessage createTextMessage() throws JMSException { - - return null; - } - - public TextMessage createTextMessage(String arg0) throws JMSException { - - return null; - } - - public Topic createTopic(String arg0) throws JMSException { - - return null; - } - - public int getAcknowledgeMode() throws JMSException { - - return 0; - } - - public MessageListener getMessageListener() throws JMSException { - - return null; - } - - public boolean getTransacted() throws JMSException { - - return false; - } - - public void recover() throws JMSException { - - - } - - public void rollback() throws JMSException { - - - } - - public void run() { - - - } - - public void setMessageListener(MessageListener arg0) throws JMSException { - - - } - - public void unsubscribe(String arg0) throws JMSException { - - - } - - -} +/** + * 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.classic.net.mock; + +import java.io.Serializable; + +import javax.jms.BytesMessage; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.MapMessage; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.QueueBrowser; +import javax.jms.QueueReceiver; +import javax.jms.QueueSender; +import javax.jms.QueueSession; +import javax.jms.StreamMessage; +import javax.jms.TemporaryQueue; +import javax.jms.TemporaryTopic; +import javax.jms.TextMessage; +import javax.jms.Topic; +import javax.jms.TopicSubscriber; + +public class MockQueueSession implements QueueSession { + + public ObjectMessage createObjectMessage() throws JMSException { + return new MockObjectMessage(); + } + + public QueueSender createSender(Queue queue) throws JMSException { + if (queue == null) { + return null; + } + return new MockQueueSender(queue); + } + + public QueueBrowser createBrowser(Queue arg0) throws JMSException { + + return null; + } + + public QueueBrowser createBrowser(Queue arg0, String arg1) throws JMSException { + + return null; + } + + public Queue createQueue(String arg0) throws JMSException { + + return null; + } + + public QueueReceiver createReceiver(Queue arg0) throws JMSException { + + return null; + } + + public QueueReceiver createReceiver(Queue arg0, String arg1) throws JMSException { + + return null; + } + + public TemporaryQueue createTemporaryQueue() throws JMSException { + + return null; + } + + public void close() throws JMSException { + + + } + + public void commit() throws JMSException { + + + } + + public BytesMessage createBytesMessage() throws JMSException { + + return null; + } + + public MessageConsumer createConsumer(Destination arg0) throws JMSException { + + return null; + } + + public MessageConsumer createConsumer(Destination arg0, String arg1) throws JMSException { + + return null; + } + + public MessageConsumer createConsumer(Destination arg0, String arg1, boolean arg2) throws JMSException { + + return null; + } + + public TopicSubscriber createDurableSubscriber(Topic arg0, String arg1) throws JMSException { + + return null; + } + + public TopicSubscriber createDurableSubscriber(Topic arg0, String arg1, String arg2, boolean arg3) throws JMSException { + + return null; + } + + public MapMessage createMapMessage() throws JMSException { + + return null; + } + + public Message createMessage() throws JMSException { + + return null; + } + + public ObjectMessage createObjectMessage(Serializable arg0) throws JMSException { + + return null; + } + + public MessageProducer createProducer(Destination arg0) throws JMSException { + + return null; + } + + public StreamMessage createStreamMessage() throws JMSException { + + return null; + } + + public TemporaryTopic createTemporaryTopic() throws JMSException { + + return null; + } + + public TextMessage createTextMessage() throws JMSException { + + return null; + } + + public TextMessage createTextMessage(String arg0) throws JMSException { + + return null; + } + + public Topic createTopic(String arg0) throws JMSException { + + return null; + } + + public int getAcknowledgeMode() throws JMSException { + + return 0; + } + + public MessageListener getMessageListener() throws JMSException { + + return null; + } + + public boolean getTransacted() throws JMSException { + + return false; + } + + public void recover() throws JMSException { + + + } + + public void rollback() throws JMSException { + + + } + + public void run() { + + + } + + public void setMessageListener(MessageListener arg0) throws JMSException { + + + } + + public void unsubscribe(String arg0) throws JMSException { + + + } + + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockSyslogServer.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockSyslogServer.java index 8e0fe328a3b5842697d7e37cd5dd427728691633..9bea188c974d703ab6480d184eaec93a290b86a7 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockSyslogServer.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockSyslogServer.java @@ -1,72 +1,72 @@ -/** - * 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.classic.net.mock; - -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Ceki Gülcü - */ -public class MockSyslogServer extends Thread { - - final int loopLen; - final int port; - - List msgList = new ArrayList(); - boolean finished = false; - - public MockSyslogServer(int loopLen, int port) { - super(); - this.loopLen = loopLen; - this.port = port; - } - - @Override - public void run() { - //System.out.println("MockSyslogServer listening on port "+port); - DatagramSocket socket = null; - try { - socket = new DatagramSocket(port); - - for (int i = 0; i < loopLen; i++) { - byte[] buf = new byte[2048]; - DatagramPacket packet = new DatagramPacket(buf, buf.length); - //System.out.println("Waiting for message"); - socket.receive(packet); - //System.out.println("Got message"); - String msg = new String(buf, 0, packet.getLength()); - msgList.add(msg); - } - } catch (Exception se) { - se.printStackTrace(); - } finally { - if(socket != null) { - try {socket.close();} catch(Exception e) {} - } - } - finished = true; - } - - public boolean isFinished() { - return finished; - } - - public List getMessageList() { - return msgList; - } -} +/** + * 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.classic.net.mock; + +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Ceki Gülcü + */ +public class MockSyslogServer extends Thread { + + final int loopLen; + final int port; + + List msgList = new ArrayList(); + boolean finished = false; + + public MockSyslogServer(int loopLen, int port) { + super(); + this.loopLen = loopLen; + this.port = port; + } + + @Override + public void run() { + //System.out.println("MockSyslogServer listening on port "+port); + DatagramSocket socket = null; + try { + socket = new DatagramSocket(port); + + for (int i = 0; i < loopLen; i++) { + byte[] buf = new byte[2048]; + DatagramPacket packet = new DatagramPacket(buf, buf.length); + //System.out.println("Waiting for message"); + socket.receive(packet); + //System.out.println("Got message"); + String msg = new String(buf, 0, packet.getLength()); + msgList.add(msg); + } + } catch (Exception se) { + se.printStackTrace(); + } finally { + if(socket != null) { + try {socket.close();} catch(Exception e) {} + } + } + finished = true; + } + + public boolean isFinished() { + return finished; + } + + public List getMessageList() { + return msgList; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopic.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopic.java index e573e6f6aa63e168ee88543752f64ab1f74a9487..054fa6ff0fda950d823ab3ff1a15b7c9d7538d30 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopic.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopic.java @@ -1,31 +1,31 @@ -/** - * 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.classic.net.mock; - -import javax.jms.JMSException; -import javax.jms.Topic; - -public class MockTopic implements Topic { - - String name; - - public MockTopic(String name) { - this.name = name; - } - - public String getTopicName() throws JMSException { - return name; - } - -} +/** + * 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.classic.net.mock; + +import javax.jms.JMSException; +import javax.jms.Topic; + +public class MockTopic implements Topic { + + String name; + + public MockTopic(String name) { + this.name = name; + } + + public String getTopicName() throws JMSException { + return name; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicConnection.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicConnection.java index ac5845ee6299d061b389e8b9d120728cd79682cf..c89ae352cbfae1cf7c0814599ae1d3af3f434bda 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicConnection.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicConnection.java @@ -1,95 +1,95 @@ -/** - * 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.classic.net.mock; - -import javax.jms.ConnectionConsumer; -import javax.jms.ConnectionMetaData; -import javax.jms.Destination; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.jms.ServerSessionPool; -import javax.jms.Session; -import javax.jms.Topic; -import javax.jms.TopicConnection; -import javax.jms.TopicSession; - -public class MockTopicConnection implements TopicConnection { - - MockTopicSession session = new MockTopicSession(); - - public TopicSession createTopicSession(boolean arg0, int arg1) throws JMSException { - return session; - } - - public ConnectionConsumer createConnectionConsumer(Topic arg0, String arg1, ServerSessionPool arg2, int arg3) throws JMSException { - - return null; - } - - public ConnectionConsumer createDurableConnectionConsumer(Topic arg0, String arg1, String arg2, ServerSessionPool arg3, int arg4) throws JMSException { - - return null; - } - - public void close() throws JMSException { - - - } - - public ConnectionConsumer createConnectionConsumer(Destination arg0, String arg1, ServerSessionPool arg2, int arg3) throws JMSException { - - return null; - } - - public Session createSession(boolean arg0, int arg1) throws JMSException { - - return null; - } - - public String getClientID() throws JMSException { - - return null; - } - - public ExceptionListener getExceptionListener() throws JMSException { - - return null; - } - - public ConnectionMetaData getMetaData() throws JMSException { - - return null; - } - - public void setClientID(String arg0) throws JMSException { - - - } - - public void setExceptionListener(ExceptionListener arg0) throws JMSException { - - - } - - public void start() throws JMSException { - - - } - - public void stop() throws JMSException { - - - } - -} +/** + * 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.classic.net.mock; + +import javax.jms.ConnectionConsumer; +import javax.jms.ConnectionMetaData; +import javax.jms.Destination; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.jms.ServerSessionPool; +import javax.jms.Session; +import javax.jms.Topic; +import javax.jms.TopicConnection; +import javax.jms.TopicSession; + +public class MockTopicConnection implements TopicConnection { + + MockTopicSession session = new MockTopicSession(); + + public TopicSession createTopicSession(boolean arg0, int arg1) throws JMSException { + return session; + } + + public ConnectionConsumer createConnectionConsumer(Topic arg0, String arg1, ServerSessionPool arg2, int arg3) throws JMSException { + + return null; + } + + public ConnectionConsumer createDurableConnectionConsumer(Topic arg0, String arg1, String arg2, ServerSessionPool arg3, int arg4) throws JMSException { + + return null; + } + + public void close() throws JMSException { + + + } + + public ConnectionConsumer createConnectionConsumer(Destination arg0, String arg1, ServerSessionPool arg2, int arg3) throws JMSException { + + return null; + } + + public Session createSession(boolean arg0, int arg1) throws JMSException { + + return null; + } + + public String getClientID() throws JMSException { + + return null; + } + + public ExceptionListener getExceptionListener() throws JMSException { + + return null; + } + + public ConnectionMetaData getMetaData() throws JMSException { + + return null; + } + + public void setClientID(String arg0) throws JMSException { + + + } + + public void setExceptionListener(ExceptionListener arg0) throws JMSException { + + + } + + public void start() throws JMSException { + + + } + + public void stop() throws JMSException { + + + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicConnectionFactory.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicConnectionFactory.java index 369de36fe22cde6cf6e186fba254343af625aa5f..0909fbbbc2471cc7452b8feb23889af4b3f2be40 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicConnectionFactory.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicConnectionFactory.java @@ -1,42 +1,42 @@ -/** - * 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.classic.net.mock; - -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.TopicConnection; -import javax.jms.TopicConnectionFactory; - -public class MockTopicConnectionFactory implements TopicConnectionFactory { - - MockTopicConnection cnx = new MockTopicConnection(); - - public TopicConnection createTopicConnection() throws JMSException { - return cnx; - } - - public TopicConnection createTopicConnection(String user, String pass) throws JMSException { - - return cnx; - } - - public Connection createConnection() throws JMSException { - return null; - } - - public Connection createConnection(String arg0, String arg1) throws JMSException { - return null; - } - -} +/** + * 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.classic.net.mock; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.TopicConnection; +import javax.jms.TopicConnectionFactory; + +public class MockTopicConnectionFactory implements TopicConnectionFactory { + + MockTopicConnection cnx = new MockTopicConnection(); + + public TopicConnection createTopicConnection() throws JMSException { + return cnx; + } + + public TopicConnection createTopicConnection(String user, String pass) throws JMSException { + + return cnx; + } + + public Connection createConnection() throws JMSException { + return null; + } + + public Connection createConnection(String arg0, String arg1) throws JMSException { + return null; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicPublisher.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicPublisher.java index d2316a456eaeb209829990f1a5f3d685ef3af015..0aacade69de1e44f0fb6b23f3b6b8d5cdf155e4a 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicPublisher.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicPublisher.java @@ -1,140 +1,140 @@ -/** - * 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.classic.net.mock; - -import java.util.ArrayList; -import java.util.List; - -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Topic; -import javax.jms.TopicPublisher; - -public class MockTopicPublisher implements TopicPublisher { - - List messageList = new ArrayList(); - Topic topic; - - public MockTopicPublisher(Topic topic) { - this.topic = topic; - } - - public void publish(Message message) throws JMSException { - messageList.add(message); - } - - public List getMessageList() { - return messageList; - } - - public Topic getTopic() throws JMSException { - return topic; - } - - public void publish(Message arg0, int arg1, int arg2, long arg3) throws JMSException { - - } - - public void publish(Topic arg0, Message arg1, int arg2, int arg3, long arg4) throws JMSException { - - - } - - public void publish(Topic arg0, Message arg1) throws JMSException { - - - } - - public void close() throws JMSException { - - - } - - public int getDeliveryMode() throws JMSException { - - return 0; - } - - public Destination getDestination() throws JMSException { - - return null; - } - - public boolean getDisableMessageID() throws JMSException { - - return false; - } - - public boolean getDisableMessageTimestamp() throws JMSException { - - return false; - } - - public int getPriority() throws JMSException { - - return 0; - } - - public long getTimeToLive() throws JMSException { - - return 0; - } - - public void send(Destination arg0, Message arg1, int arg2, int arg3, long arg4) throws JMSException { - - - } - - public void send(Destination arg0, Message arg1) throws JMSException { - - - } - - public void send(Message arg0, int arg1, int arg2, long arg3) throws JMSException { - - - } - - public void send(Message arg0) throws JMSException { - - - } - - public void setDeliveryMode(int arg0) throws JMSException { - - - } - - public void setDisableMessageID(boolean arg0) throws JMSException { - - - } - - public void setDisableMessageTimestamp(boolean arg0) throws JMSException { - - - } - - public void setPriority(int arg0) throws JMSException { - - - } - - public void setTimeToLive(long arg0) throws JMSException { - - - } - -} +/** + * 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.classic.net.mock; + +import java.util.ArrayList; +import java.util.List; + +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.Topic; +import javax.jms.TopicPublisher; + +public class MockTopicPublisher implements TopicPublisher { + + List messageList = new ArrayList(); + Topic topic; + + public MockTopicPublisher(Topic topic) { + this.topic = topic; + } + + public void publish(Message message) throws JMSException { + messageList.add(message); + } + + public List getMessageList() { + return messageList; + } + + public Topic getTopic() throws JMSException { + return topic; + } + + public void publish(Message arg0, int arg1, int arg2, long arg3) throws JMSException { + + } + + public void publish(Topic arg0, Message arg1, int arg2, int arg3, long arg4) throws JMSException { + + + } + + public void publish(Topic arg0, Message arg1) throws JMSException { + + + } + + public void close() throws JMSException { + + + } + + public int getDeliveryMode() throws JMSException { + + return 0; + } + + public Destination getDestination() throws JMSException { + + return null; + } + + public boolean getDisableMessageID() throws JMSException { + + return false; + } + + public boolean getDisableMessageTimestamp() throws JMSException { + + return false; + } + + public int getPriority() throws JMSException { + + return 0; + } + + public long getTimeToLive() throws JMSException { + + return 0; + } + + public void send(Destination arg0, Message arg1, int arg2, int arg3, long arg4) throws JMSException { + + + } + + public void send(Destination arg0, Message arg1) throws JMSException { + + + } + + public void send(Message arg0, int arg1, int arg2, long arg3) throws JMSException { + + + } + + public void send(Message arg0) throws JMSException { + + + } + + public void setDeliveryMode(int arg0) throws JMSException { + + + } + + public void setDisableMessageID(boolean arg0) throws JMSException { + + + } + + public void setDisableMessageTimestamp(boolean arg0) throws JMSException { + + + } + + public void setPriority(int arg0) throws JMSException { + + + } + + public void setTimeToLive(long arg0) throws JMSException { + + + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicSession.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicSession.java index d2149ef7d8c5ff744f509743c9cfd279884ad863..a198cca361b7ce7f363f4349e6d0804fc262120f 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicSession.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/mock/MockTopicSession.java @@ -1,198 +1,198 @@ -/** - * 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.classic.net.mock; - -import java.io.Serializable; - -import javax.jms.BytesMessage; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.MapMessage; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.ObjectMessage; -import javax.jms.Queue; -import javax.jms.QueueBrowser; -import javax.jms.StreamMessage; -import javax.jms.TemporaryQueue; -import javax.jms.TemporaryTopic; -import javax.jms.TextMessage; -import javax.jms.Topic; -import javax.jms.TopicPublisher; -import javax.jms.TopicSession; -import javax.jms.TopicSubscriber; - -public class MockTopicSession implements TopicSession { - - public ObjectMessage createObjectMessage() throws JMSException { - return new MockObjectMessage(); - } - - public TopicPublisher createPublisher(Topic topic) throws JMSException { - if (topic == null) { - return null; - } - return new MockTopicPublisher(topic); - } - - - public TopicSubscriber createDurableSubscriber(Topic arg0, String arg1) throws JMSException { - return null; - } - - public TopicSubscriber createDurableSubscriber(Topic arg0, String arg1, String arg2, boolean arg3) throws JMSException { - return null; - } - - public TopicSubscriber createSubscriber(Topic arg0) throws JMSException { - return null; - } - - public TopicSubscriber createSubscriber(Topic arg0, String arg1, boolean arg2) throws JMSException { - return null; - } - - public TemporaryTopic createTemporaryTopic() throws JMSException { - return null; - } - - public Topic createTopic(String arg0) throws JMSException { - return null; - } - - public void unsubscribe(String arg0) throws JMSException { - - } - - public void close() throws JMSException { - - } - - public void commit() throws JMSException { - - } - - public QueueBrowser createBrowser(Queue arg0) throws JMSException { - - return null; - } - - public QueueBrowser createBrowser(Queue arg0, String arg1) throws JMSException { - - return null; - } - - public BytesMessage createBytesMessage() throws JMSException { - - return null; - } - - public MessageConsumer createConsumer(Destination arg0) throws JMSException { - - return null; - } - - public MessageConsumer createConsumer(Destination arg0, String arg1) throws JMSException { - - return null; - } - - public MessageConsumer createConsumer(Destination arg0, String arg1, boolean arg2) throws JMSException { - - return null; - } - - public MapMessage createMapMessage() throws JMSException { - - return null; - } - - public Message createMessage() throws JMSException { - - return null; - } - - public ObjectMessage createObjectMessage(Serializable arg0) throws JMSException { - - return null; - } - - public MessageProducer createProducer(Destination arg0) throws JMSException { - - return null; - } - - public Queue createQueue(String arg0) throws JMSException { - - return null; - } - - public StreamMessage createStreamMessage() throws JMSException { - - return null; - } - - public TemporaryQueue createTemporaryQueue() throws JMSException { - - return null; - } - - public TextMessage createTextMessage() throws JMSException { - - return null; - } - - public TextMessage createTextMessage(String arg0) throws JMSException { - - return null; - } - - public int getAcknowledgeMode() throws JMSException { - - return 0; - } - - public MessageListener getMessageListener() throws JMSException { - - return null; - } - - public boolean getTransacted() throws JMSException { - - return false; - } - - public void recover() throws JMSException { - - - } - - public void rollback() throws JMSException { - - - } - - public void run() { - - - } - - public void setMessageListener(MessageListener arg0) throws JMSException { - - - } - -} +/** + * 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.classic.net.mock; + +import java.io.Serializable; + +import javax.jms.BytesMessage; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.MapMessage; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.QueueBrowser; +import javax.jms.StreamMessage; +import javax.jms.TemporaryQueue; +import javax.jms.TemporaryTopic; +import javax.jms.TextMessage; +import javax.jms.Topic; +import javax.jms.TopicPublisher; +import javax.jms.TopicSession; +import javax.jms.TopicSubscriber; + +public class MockTopicSession implements TopicSession { + + public ObjectMessage createObjectMessage() throws JMSException { + return new MockObjectMessage(); + } + + public TopicPublisher createPublisher(Topic topic) throws JMSException { + if (topic == null) { + return null; + } + return new MockTopicPublisher(topic); + } + + + public TopicSubscriber createDurableSubscriber(Topic arg0, String arg1) throws JMSException { + return null; + } + + public TopicSubscriber createDurableSubscriber(Topic arg0, String arg1, String arg2, boolean arg3) throws JMSException { + return null; + } + + public TopicSubscriber createSubscriber(Topic arg0) throws JMSException { + return null; + } + + public TopicSubscriber createSubscriber(Topic arg0, String arg1, boolean arg2) throws JMSException { + return null; + } + + public TemporaryTopic createTemporaryTopic() throws JMSException { + return null; + } + + public Topic createTopic(String arg0) throws JMSException { + return null; + } + + public void unsubscribe(String arg0) throws JMSException { + + } + + public void close() throws JMSException { + + } + + public void commit() throws JMSException { + + } + + public QueueBrowser createBrowser(Queue arg0) throws JMSException { + + return null; + } + + public QueueBrowser createBrowser(Queue arg0, String arg1) throws JMSException { + + return null; + } + + public BytesMessage createBytesMessage() throws JMSException { + + return null; + } + + public MessageConsumer createConsumer(Destination arg0) throws JMSException { + + return null; + } + + public MessageConsumer createConsumer(Destination arg0, String arg1) throws JMSException { + + return null; + } + + public MessageConsumer createConsumer(Destination arg0, String arg1, boolean arg2) throws JMSException { + + return null; + } + + public MapMessage createMapMessage() throws JMSException { + + return null; + } + + public Message createMessage() throws JMSException { + + return null; + } + + public ObjectMessage createObjectMessage(Serializable arg0) throws JMSException { + + return null; + } + + public MessageProducer createProducer(Destination arg0) throws JMSException { + + return null; + } + + public Queue createQueue(String arg0) throws JMSException { + + return null; + } + + public StreamMessage createStreamMessage() throws JMSException { + + return null; + } + + public TemporaryQueue createTemporaryQueue() throws JMSException { + + return null; + } + + public TextMessage createTextMessage() throws JMSException { + + return null; + } + + public TextMessage createTextMessage(String arg0) throws JMSException { + + return null; + } + + public int getAcknowledgeMode() throws JMSException { + + return 0; + } + + public MessageListener getMessageListener() throws JMSException { + + return null; + } + + public boolean getTransacted() throws JMSException { + + return false; + } + + public void recover() throws JMSException { + + + } + + public void rollback() throws JMSException { + + + } + + public void run() { + + + } + + public void setMessageListener(MessageListener arg0) throws JMSException { + + + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/Builder.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/Builder.java index 5ce412a74ceaae062b814dce110fb53cd98a0fb3..2365fca9aa7c20b83b40af58d41a9c1970376798 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/Builder.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/Builder.java @@ -1,24 +1,24 @@ -/** - * 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.classic.net.testObjectBuilders; - -public interface Builder { - - // 45 characters message - final String MSG_PREFIX = "aaaaabbbbbcccccdddddaaaaabbbbbcccccdddddaaaa"; - - // final String MSG_PREFIX = "a"; - - Object build(int i); -} +/** + * 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.classic.net.testObjectBuilders; + +public interface Builder { + + // 45 characters message + final String MSG_PREFIX = "aaaaabbbbbcccccdddddaaaaabbbbbcccccdddddaaaa"; + + // final String MSG_PREFIX = "a"; + + Object build(int i); +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/LoggingEventWithParametersBuilder.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/LoggingEventWithParametersBuilder.java index 95bbe28daff9f77ff2756f706823eb8412509a9c..655e50c8dfe8832740eaaa7802e3bc1af2c243ae 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/LoggingEventWithParametersBuilder.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/LoggingEventWithParametersBuilder.java @@ -1,50 +1,50 @@ -/** - * 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.classic.net.testObjectBuilders; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.LoggingEvent; - -public class LoggingEventWithParametersBuilder implements Builder { - - final String MSG = "aaaaabbbbbcccc {} cdddddaaaaabbbbbcccccdddddaaaa {}"; - - private Logger logger = new LoggerContext() - .getLogger(Logger.ROOT_LOGGER_NAME); - - public Object build(int i) { - - LoggingEvent le = new LoggingEvent(); - le.setTimeStamp(System.currentTimeMillis()); - - Object[] aa = new Object[] { i, "HELLO WORLD [========== ]" + i }; - - le.setArgumentArray(aa); - String msg = MSG + i; - le.setMessage(msg); - - // compute formatted message - // this forces le.formmatedMessage to be set (this is the whole point of the - // exercise) - le.getFormattedMessage(); - le.setLevel(Level.DEBUG); - le.setLoggerName(logger.getName()); - le.setLoggerContextRemoteView(logger.getLoggerRemoteView().getLoggerContextView()); - le.setThreadName("threadName"); - - return le; - } -} +/** + * 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.classic.net.testObjectBuilders; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.LoggingEvent; + +public class LoggingEventWithParametersBuilder implements Builder { + + final String MSG = "aaaaabbbbbcccc {} cdddddaaaaabbbbbcccccdddddaaaa {}"; + + private Logger logger = new LoggerContext() + .getLogger(Logger.ROOT_LOGGER_NAME); + + public Object build(int i) { + + LoggingEvent le = new LoggingEvent(); + le.setTimeStamp(System.currentTimeMillis()); + + Object[] aa = new Object[] { i, "HELLO WORLD [========== ]" + i }; + + le.setArgumentArray(aa); + String msg = MSG + i; + le.setMessage(msg); + + // compute formatted message + // this forces le.formmatedMessage to be set (this is the whole point of the + // exercise) + le.getFormattedMessage(); + le.setLevel(Level.DEBUG); + le.setLoggerName(logger.getName()); + le.setLoggerContextRemoteView(logger.getLoggerRemoteView().getLoggerContextView()); + le.setThreadName("threadName"); + + return le; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/MinimalSerBuilder.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/MinimalSerBuilder.java index 835d00c688aa4e7ced2a3db5f011d6fe754ec4a5..845f3b354d81a75edf14b4d03981c2009c34ea7b 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/MinimalSerBuilder.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/MinimalSerBuilder.java @@ -1,36 +1,36 @@ -/** - * 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.classic.net.testObjectBuilders; - -import java.io.Serializable; - - -public class MinimalSerBuilder implements Builder{ - - public Object build(int i) { - return new MinimalSer(i); - } - -} - -class MinimalSer implements Serializable { - - private static final long serialVersionUID = 2807646397580899815L; - - String message; - - public MinimalSer(int i) { - message = Builder.MSG_PREFIX; - } +/** + * 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.classic.net.testObjectBuilders; + +import java.io.Serializable; + + +public class MinimalSerBuilder implements Builder{ + + public Object build(int i) { + return new MinimalSer(i); + } + +} + +class MinimalSer implements Serializable { + + private static final long serialVersionUID = 2807646397580899815L; + + String message; + + public MinimalSer(int i) { + message = Builder.MSG_PREFIX; + } } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/TrivialLoggingEventBuilder.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/TrivialLoggingEventBuilder.java index 7011f197b2f89c7edb30318392f3cd20eff3ba18..072cf62a8c0f8c30cf6d04bd557d4564517c15a4 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/TrivialLoggingEventBuilder.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/TrivialLoggingEventBuilder.java @@ -1,36 +1,36 @@ -/** - * 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.classic.net.testObjectBuilders; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.LoggingEvent; - -public class TrivialLoggingEventBuilder implements Builder { - - private Logger logger = new LoggerContext() - .getLogger(Logger.ROOT_LOGGER_NAME); - - public Object build(int i) { - LoggingEvent le = new LoggingEvent(); - le.setTimeStamp(System.currentTimeMillis()); - le.setLevel(Level.DEBUG); - le.setLoggerName(logger.getName()); - le.setLoggerContextRemoteView(logger.getLoggerRemoteView().getLoggerContextView()); - le.setMessage(MSG_PREFIX); - le.setThreadName("threadName"); - return le; - } -} +/** + * 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.classic.net.testObjectBuilders; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.LoggingEvent; + +public class TrivialLoggingEventBuilder implements Builder { + + private Logger logger = new LoggerContext() + .getLogger(Logger.ROOT_LOGGER_NAME); + + public Object build(int i) { + LoggingEvent le = new LoggingEvent(); + le.setTimeStamp(System.currentTimeMillis()); + le.setLevel(Level.DEBUG); + le.setLoggerName(logger.getName()); + le.setLoggerContextRemoteView(logger.getLoggerRemoteView().getLoggerContextView()); + le.setMessage(MSG_PREFIX); + le.setThreadName("threadName"); + return le; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java index c4c5b3bae06d8b3441e6f474928b97c06d629be1..56117866fffeda93314310edd669a17d8800d8e2 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java @@ -1,386 +1,386 @@ -/** - * 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.classic.pattern; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.slf4j.MDC; -import org.slf4j.MarkerFactory; - -import ch.qos.logback.classic.ClassicConstants; -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.ClassicTestConstants; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.net.SyslogConstants; -import ch.qos.logback.core.pattern.DynamicConverter; -import ch.qos.logback.core.pattern.FormatInfo; - -public class ConverterTest { - - LoggerContext lc = new LoggerContext(); - Logger logger = lc.getLogger(ConverterTest.class); - LoggingEvent le; - List optionList = new ArrayList(); - - // The LoggingEvent is massaged with an FCQN of FormattingConverter. This - // forces the returned caller information to match the caller stack for this - // this particular test. - LoggingEvent makeLoggingEvent(Exception ex) { - return new LoggingEvent( - ch.qos.logback.core.pattern.FormattingConverter.class.getName(), - logger, Level.INFO, "Some message", ex, null); - } - - Exception getException(String msg, Exception cause) { - return new Exception(msg, cause); - } - - @Before - public void setUp() throws Exception { - Exception rootEx = getException("Innermost", null); - Exception nestedEx = getException("Nested", rootEx); - - Exception ex = new Exception("Bogus exception", nestedEx); - - le = makeLoggingEvent(ex); - } - - @Test - public void testLineOfCaller() { - { - DynamicConverter converter = new LineOfCallerConverter(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - // the number below should be the line number of the previous line - assertEquals("75", buf.toString()); - } - } - - @Test - public void testLevel() { - { - DynamicConverter converter = new LevelConverter(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - assertEquals("INFO", buf.toString()); - } - { - DynamicConverter converter = new LevelConverter(); - converter.setFormattingInfo(new FormatInfo(1, 1, true, false)); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - assertEquals("I", buf.toString()); - } - } - - @Test - public void testThread() { - DynamicConverter converter = new ThreadConverter(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - String regex = ClassicTestConstants.NAKED_MAIN_REGEX; - assertTrue(buf.toString().matches(regex)); - } - - @Test - public void testMessage() { - DynamicConverter converter = new MessageConverter(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - assertEquals("Some message", buf.toString()); - } - - @Test - public void testLineSeparator() { - DynamicConverter converter = new LineSeparatorConverter(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - assertEquals(CoreConstants.LINE_SEPARATOR, buf.toString()); - } - - @Test - public void testException() { - { - DynamicConverter converter = new ThrowableProxyConverter(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - } - - { - DynamicConverter converter = new ThrowableProxyConverter(); - this.optionList.add("3"); - converter.setOptionList(this.optionList); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - } - } - - @Test - public void testLogger() { - { - ClassicConverter converter = new LoggerConverter(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - assertEquals(this.getClass().getName(), buf.toString()); - } - - { - ClassicConverter converter = new LoggerConverter(); - this.optionList.add("20"); - converter.setOptionList(this.optionList); - converter.start(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - assertEquals("c.q.l.c.p.ConverterTest", buf.toString()); - } - - { - DynamicConverter converter = new LoggerConverter(); - this.optionList.clear(); - this.optionList.add("0"); - converter.setOptionList(this.optionList); - converter.start(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - assertEquals("ConverterTest", buf.toString()); - } - } - - @Test - public void testVeryLongLoggerName() { - ClassicConverter converter = new LoggerConverter(); - this.optionList.add("5"); - converter.setOptionList(this.optionList); - converter.start(); - StringBuffer buf = new StringBuffer(); - - char c = 'a'; - int extraParts = 3; - int totalParts = ClassicConstants.MAX_DOTS + extraParts; - StringBuilder loggerNameBuf = new StringBuilder(); - StringBuilder witness = new StringBuilder(); - - for(int i = 0; i < totalParts ; i++) { - loggerNameBuf.append(c).append(c).append(c); - if(i < ClassicConstants.MAX_DOTS) { - witness.append(c); - } else { - witness.append(c).append(c).append(c); - } - loggerNameBuf.append('.'); - witness.append('.'); - } - loggerNameBuf.append("zzzzzz"); - witness.append("zzzzzz"); - - le.setLoggerName(loggerNameBuf.toString()); - converter.write(buf, le); - assertEquals(witness.toString(), buf.toString()); - } - - @Test - public void testClass() { - DynamicConverter converter = new ClassOfCallerConverter(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - assertEquals(this.getClass().getName(), buf.toString()); - } - - @Test - public void testMethodOfCaller() { - DynamicConverter converter = new MethodOfCallerConverter(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - assertEquals("testMethodOfCaller", buf.toString()); - } - - @Test - public void testFileOfCaller() { - DynamicConverter converter = new FileOfCallerConverter(); - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - assertEquals("ConverterTest.java", buf.toString()); - } - - @Test - public void testCallerData() { - { - DynamicConverter converter = new CallerDataConverter(); - converter.start(); - - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - if (buf.length() < 10) { - fail("buf is too short"); - } - } - - { - DynamicConverter converter = new CallerDataConverter(); - this.optionList.add("2"); - this.optionList.add("XXX"); - converter.setOptionList(this.optionList); - converter.start(); - - StringBuffer buf = new StringBuffer(); - LoggingEvent event = makeLoggingEvent(null); - event.setMarker(MarkerFactory.getMarker("XXX")); - converter.write(buf, event); - if (buf.length() < 10) { - fail("buf is too short"); - } - } - - { - DynamicConverter converter = new CallerDataConverter(); - this.optionList.clear(); - this.optionList.add("2"); - this.optionList.add("XXX"); - this.optionList.add("*"); - converter.setOptionList(this.optionList); - converter.start(); - - StringBuffer buf = new StringBuffer(); - LoggingEvent event = makeLoggingEvent(null); - event.setMarker(MarkerFactory.getMarker("YYY")); - converter.write(buf, event); - if (buf.length() < 10) { - fail("buf is too short"); - } - } - { - DynamicConverter converter = new CallerDataConverter(); - this.optionList.clear(); - this.optionList.add("2"); - this.optionList.add("XXX"); - this.optionList.add("+"); - converter.setOptionList(this.optionList); - converter.start(); - - StringBuffer buf = new StringBuffer(); - LoggingEvent event = makeLoggingEvent(null); - event.setMarker(MarkerFactory.getMarker("YYY")); - converter.write(buf, event); - if (buf.length() < 10) { - fail("buf is too short"); - } - } - - { - DynamicConverter converter = new CallerDataConverter(); - this.optionList.clear(); - this.optionList.add("2"); - this.optionList.add("XXX"); - this.optionList.add("*"); - converter.setOptionList(this.optionList); - converter.start(); - - StringBuffer buf = new StringBuffer(); - converter.write(buf, le); - if (buf.length() < 10) { - fail("buf is too short"); - } - // System.out.println(buf); - } - - } - - @Test - public void testRelativeTime() throws Exception { - DynamicConverter converter = new RelativeTimeConverter(); - StringBuffer buf0 = new StringBuffer(); - StringBuffer buf1 = new StringBuffer(); - ILoggingEvent e0 = makeLoggingEvent(null); - ILoggingEvent e1 = makeLoggingEvent(null); - converter.write(buf0, e0); - converter.write(buf1, e1); - assertEquals(buf0.toString(), buf1.toString()); - } - - @Test - public void testSyslogStart() throws Exception { - DynamicConverter converter = new SyslogStartConverter(); - this.optionList.clear(); - this.optionList.add("MAIL"); - converter.setOptionList(this.optionList); - converter.start(); - - ILoggingEvent event = makeLoggingEvent(null); - - StringBuffer buf = new StringBuffer(); - converter.write(buf, event); - - String expected = "<" - + (SyslogConstants.LOG_MAIL + SyslogConstants.INFO_SEVERITY) + ">"; - assertTrue(buf.toString().startsWith(expected)); - } - - @Test - public void testMDCConverter() throws Exception { - MDC.clear(); - MDC.put("someKey", "someValue"); - MDCConverter converter = new MDCConverter(); - this.optionList.clear(); - this.optionList.add("someKey"); - converter.setOptionList(optionList); - converter.start(); - - ILoggingEvent event = makeLoggingEvent(null); - - String result = converter.convert(event); - assertEquals("someValue", result); - } - - @Test - public void contextNameConverter() { - ClassicConverter converter = new ContextNameConverter(); - // see http://jira.qos.ch/browse/LBCLASSIC-149 - LoggerContext lcOther = new LoggerContext(); - lcOther.setName("another"); - converter.setContext(lcOther); - - lc.setName("aValue"); - ILoggingEvent event = makeLoggingEvent(null); - - String result = converter.convert(event); - assertEquals("aValue", result); - } - - @Test - public void contextProperty() { - PropertyConverter converter = new PropertyConverter(); - converter.setContext(lc); - List ol = new ArrayList(); - ol.add("k"); - converter.setOptionList(ol); - converter.start(); - lc.setName("aValue"); - lc.putProperty("k", "v"); - ILoggingEvent event = makeLoggingEvent(null); - - String result = converter.convert(event); - assertEquals("v", result); - } -} +/** + * 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.classic.pattern; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.slf4j.MDC; +import org.slf4j.MarkerFactory; + +import ch.qos.logback.classic.ClassicConstants; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.ClassicTestConstants; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.net.SyslogConstants; +import ch.qos.logback.core.pattern.DynamicConverter; +import ch.qos.logback.core.pattern.FormatInfo; + +public class ConverterTest { + + LoggerContext lc = new LoggerContext(); + Logger logger = lc.getLogger(ConverterTest.class); + LoggingEvent le; + List optionList = new ArrayList(); + + // The LoggingEvent is massaged with an FCQN of FormattingConverter. This + // forces the returned caller information to match the caller stack for this + // this particular test. + LoggingEvent makeLoggingEvent(Exception ex) { + return new LoggingEvent( + ch.qos.logback.core.pattern.FormattingConverter.class.getName(), + logger, Level.INFO, "Some message", ex, null); + } + + Exception getException(String msg, Exception cause) { + return new Exception(msg, cause); + } + + @Before + public void setUp() throws Exception { + Exception rootEx = getException("Innermost", null); + Exception nestedEx = getException("Nested", rootEx); + + Exception ex = new Exception("Bogus exception", nestedEx); + + le = makeLoggingEvent(ex); + } + + @Test + public void testLineOfCaller() { + { + DynamicConverter converter = new LineOfCallerConverter(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + // the number below should be the line number of the previous line + assertEquals("75", buf.toString()); + } + } + + @Test + public void testLevel() { + { + DynamicConverter converter = new LevelConverter(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + assertEquals("INFO", buf.toString()); + } + { + DynamicConverter converter = new LevelConverter(); + converter.setFormattingInfo(new FormatInfo(1, 1, true, false)); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + assertEquals("I", buf.toString()); + } + } + + @Test + public void testThread() { + DynamicConverter converter = new ThreadConverter(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + String regex = ClassicTestConstants.NAKED_MAIN_REGEX; + assertTrue(buf.toString().matches(regex)); + } + + @Test + public void testMessage() { + DynamicConverter converter = new MessageConverter(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + assertEquals("Some message", buf.toString()); + } + + @Test + public void testLineSeparator() { + DynamicConverter converter = new LineSeparatorConverter(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + assertEquals(CoreConstants.LINE_SEPARATOR, buf.toString()); + } + + @Test + public void testException() { + { + DynamicConverter converter = new ThrowableProxyConverter(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + } + + { + DynamicConverter converter = new ThrowableProxyConverter(); + this.optionList.add("3"); + converter.setOptionList(this.optionList); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + } + } + + @Test + public void testLogger() { + { + ClassicConverter converter = new LoggerConverter(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + assertEquals(this.getClass().getName(), buf.toString()); + } + + { + ClassicConverter converter = new LoggerConverter(); + this.optionList.add("20"); + converter.setOptionList(this.optionList); + converter.start(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + assertEquals("c.q.l.c.p.ConverterTest", buf.toString()); + } + + { + DynamicConverter converter = new LoggerConverter(); + this.optionList.clear(); + this.optionList.add("0"); + converter.setOptionList(this.optionList); + converter.start(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + assertEquals("ConverterTest", buf.toString()); + } + } + + @Test + public void testVeryLongLoggerName() { + ClassicConverter converter = new LoggerConverter(); + this.optionList.add("5"); + converter.setOptionList(this.optionList); + converter.start(); + StringBuffer buf = new StringBuffer(); + + char c = 'a'; + int extraParts = 3; + int totalParts = ClassicConstants.MAX_DOTS + extraParts; + StringBuilder loggerNameBuf = new StringBuilder(); + StringBuilder witness = new StringBuilder(); + + for(int i = 0; i < totalParts ; i++) { + loggerNameBuf.append(c).append(c).append(c); + if(i < ClassicConstants.MAX_DOTS) { + witness.append(c); + } else { + witness.append(c).append(c).append(c); + } + loggerNameBuf.append('.'); + witness.append('.'); + } + loggerNameBuf.append("zzzzzz"); + witness.append("zzzzzz"); + + le.setLoggerName(loggerNameBuf.toString()); + converter.write(buf, le); + assertEquals(witness.toString(), buf.toString()); + } + + @Test + public void testClass() { + DynamicConverter converter = new ClassOfCallerConverter(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + assertEquals(this.getClass().getName(), buf.toString()); + } + + @Test + public void testMethodOfCaller() { + DynamicConverter converter = new MethodOfCallerConverter(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + assertEquals("testMethodOfCaller", buf.toString()); + } + + @Test + public void testFileOfCaller() { + DynamicConverter converter = new FileOfCallerConverter(); + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + assertEquals("ConverterTest.java", buf.toString()); + } + + @Test + public void testCallerData() { + { + DynamicConverter converter = new CallerDataConverter(); + converter.start(); + + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + if (buf.length() < 10) { + fail("buf is too short"); + } + } + + { + DynamicConverter converter = new CallerDataConverter(); + this.optionList.add("2"); + this.optionList.add("XXX"); + converter.setOptionList(this.optionList); + converter.start(); + + StringBuffer buf = new StringBuffer(); + LoggingEvent event = makeLoggingEvent(null); + event.setMarker(MarkerFactory.getMarker("XXX")); + converter.write(buf, event); + if (buf.length() < 10) { + fail("buf is too short"); + } + } + + { + DynamicConverter converter = new CallerDataConverter(); + this.optionList.clear(); + this.optionList.add("2"); + this.optionList.add("XXX"); + this.optionList.add("*"); + converter.setOptionList(this.optionList); + converter.start(); + + StringBuffer buf = new StringBuffer(); + LoggingEvent event = makeLoggingEvent(null); + event.setMarker(MarkerFactory.getMarker("YYY")); + converter.write(buf, event); + if (buf.length() < 10) { + fail("buf is too short"); + } + } + { + DynamicConverter converter = new CallerDataConverter(); + this.optionList.clear(); + this.optionList.add("2"); + this.optionList.add("XXX"); + this.optionList.add("+"); + converter.setOptionList(this.optionList); + converter.start(); + + StringBuffer buf = new StringBuffer(); + LoggingEvent event = makeLoggingEvent(null); + event.setMarker(MarkerFactory.getMarker("YYY")); + converter.write(buf, event); + if (buf.length() < 10) { + fail("buf is too short"); + } + } + + { + DynamicConverter converter = new CallerDataConverter(); + this.optionList.clear(); + this.optionList.add("2"); + this.optionList.add("XXX"); + this.optionList.add("*"); + converter.setOptionList(this.optionList); + converter.start(); + + StringBuffer buf = new StringBuffer(); + converter.write(buf, le); + if (buf.length() < 10) { + fail("buf is too short"); + } + // System.out.println(buf); + } + + } + + @Test + public void testRelativeTime() throws Exception { + DynamicConverter converter = new RelativeTimeConverter(); + StringBuffer buf0 = new StringBuffer(); + StringBuffer buf1 = new StringBuffer(); + ILoggingEvent e0 = makeLoggingEvent(null); + ILoggingEvent e1 = makeLoggingEvent(null); + converter.write(buf0, e0); + converter.write(buf1, e1); + assertEquals(buf0.toString(), buf1.toString()); + } + + @Test + public void testSyslogStart() throws Exception { + DynamicConverter converter = new SyslogStartConverter(); + this.optionList.clear(); + this.optionList.add("MAIL"); + converter.setOptionList(this.optionList); + converter.start(); + + ILoggingEvent event = makeLoggingEvent(null); + + StringBuffer buf = new StringBuffer(); + converter.write(buf, event); + + String expected = "<" + + (SyslogConstants.LOG_MAIL + SyslogConstants.INFO_SEVERITY) + ">"; + assertTrue(buf.toString().startsWith(expected)); + } + + @Test + public void testMDCConverter() throws Exception { + MDC.clear(); + MDC.put("someKey", "someValue"); + MDCConverter converter = new MDCConverter(); + this.optionList.clear(); + this.optionList.add("someKey"); + converter.setOptionList(optionList); + converter.start(); + + ILoggingEvent event = makeLoggingEvent(null); + + String result = converter.convert(event); + assertEquals("someValue", result); + } + + @Test + public void contextNameConverter() { + ClassicConverter converter = new ContextNameConverter(); + // see http://jira.qos.ch/browse/LBCLASSIC-149 + LoggerContext lcOther = new LoggerContext(); + lcOther.setName("another"); + converter.setContext(lcOther); + + lc.setName("aValue"); + ILoggingEvent event = makeLoggingEvent(null); + + String result = converter.convert(event); + assertEquals("aValue", result); + } + + @Test + public void contextProperty() { + PropertyConverter converter = new PropertyConverter(); + converter.setContext(lc); + List ol = new ArrayList(); + ol.add("k"); + converter.setOptionList(ol); + converter.start(); + lc.setName("aValue"); + lc.putProperty("k", "v"); + ILoggingEvent event = makeLoggingEvent(null); + + String result = converter.convert(event); + assertEquals("v", result); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverterTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverterTest.java index a6af091487bfc655d4f914baa9d590e501121a3a..8a2e364bec14b010719d4414a511101ff69a94c0 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverterTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverterTest.java @@ -1,107 +1,107 @@ -/** - * 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.classic.pattern; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; - -public class ExtendedThrowableProxyConverterTest { - - LoggerContext lc = new LoggerContext(); - ExtendedThrowableProxyConverter etpc = new ExtendedThrowableProxyConverter(); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - - @Before - public void setUp() throws Exception { - etpc.setContext(lc); - etpc.start(); - } - - @After - public void tearDown() throws Exception { - } - - private ILoggingEvent createLoggingEvent(Throwable t) { - ILoggingEvent le = new LoggingEvent(this.getClass().getName(), lc - .getLogger(Logger.ROOT_LOGGER_NAME), Level.DEBUG, "test message", t, - null); - return le; - } - - @Test - public void integration() { - PatternLayout pl = new PatternLayout(); - pl.setContext(lc); - pl.setPattern("%m%n"); - pl.start(); - ILoggingEvent e = createLoggingEvent(new Exception("x")); - String res = pl.doLayout(e); - - // make sure that at least some package data was output - Pattern p = Pattern.compile(" \\[junit.*\\]"); - Matcher m = p.matcher(res); - int i = 0; - while(m.find()) { - i++; - } - assertTrue(i+ " should be larger than 5", i > 5); - } - - @Test - public void smoke() { - Exception t = new Exception("smoke"); - verify(t); - } - - @Test - public void nested() { - Throwable t = makeNestedException(1); - verify(t); - } - - void verify(Throwable t) { - t.printStackTrace(pw); - - ILoggingEvent le = createLoggingEvent(t); - String result = etpc.convert(le); - result = result.replace("common frames omitted", "more"); - result = result.replaceAll(" \\[.*\\]", ""); - assertEquals(sw.toString(), result); - } - - Throwable makeNestedException(int level) { - if (level == 0) { - return new Exception("nesting level=" + level); - } - Throwable cause = makeNestedException(level - 1); - return new Exception("nesting level =" + level, cause); - } -} +/** + * 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.classic.pattern; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; + +public class ExtendedThrowableProxyConverterTest { + + LoggerContext lc = new LoggerContext(); + ExtendedThrowableProxyConverter etpc = new ExtendedThrowableProxyConverter(); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + + @Before + public void setUp() throws Exception { + etpc.setContext(lc); + etpc.start(); + } + + @After + public void tearDown() throws Exception { + } + + private ILoggingEvent createLoggingEvent(Throwable t) { + ILoggingEvent le = new LoggingEvent(this.getClass().getName(), lc + .getLogger(Logger.ROOT_LOGGER_NAME), Level.DEBUG, "test message", t, + null); + return le; + } + + @Test + public void integration() { + PatternLayout pl = new PatternLayout(); + pl.setContext(lc); + pl.setPattern("%m%n"); + pl.start(); + ILoggingEvent e = createLoggingEvent(new Exception("x")); + String res = pl.doLayout(e); + + // make sure that at least some package data was output + Pattern p = Pattern.compile(" \\[junit.*\\]"); + Matcher m = p.matcher(res); + int i = 0; + while(m.find()) { + i++; + } + assertTrue(i+ " should be larger than 5", i > 5); + } + + @Test + public void smoke() { + Exception t = new Exception("smoke"); + verify(t); + } + + @Test + public void nested() { + Throwable t = makeNestedException(1); + verify(t); + } + + void verify(Throwable t) { + t.printStackTrace(pw); + + ILoggingEvent le = createLoggingEvent(t); + String result = etpc.convert(le); + result = result.replace("common frames omitted", "more"); + result = result.replaceAll(" \\[.*\\]", ""); + assertEquals(sw.toString(), result); + } + + Throwable makeNestedException(int level) { + if (level == 0) { + return new Exception("nesting level=" + level); + } + Throwable cause = makeNestedException(level - 1); + return new Exception("nesting level =" + level, cause); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/LRUCacheTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/LRUCacheTest.java index a9be0406c822ddebbb4ae9dcc8f4e312eef1604e..c9628b6368cc7e52f6fc88a9be1a7c290864af5d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/LRUCacheTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/LRUCacheTest.java @@ -1,125 +1,125 @@ -/** - * 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.classic.pattern; - -import static org.junit.Assert.assertEquals; - -import java.util.LinkedList; -import java.util.List; - -import org.junit.Ignore; -import org.junit.Test; - -import ch.qos.logback.classic.pattern.lru.Event; -import ch.qos.logback.classic.pattern.lru.T_LRUCache; - -@Ignore -public class LRUCacheTest { - - @Test - public void smoke() { - - LRUCache cache = new LRUCache(2); - cache.put("a", "a"); - cache.put("b", "b"); - cache.put("c", "c"); - List witness = new LinkedList(); - witness.add("b"); - witness.add("c"); - assertEquals(witness, cache.keyList()); - } - - @Test - public void typicalScenarioTest() { - int simulationLen = 1000 * 10; - int cacheSize = 100; - int worldSize = 1000; - doScenario(simulationLen, cacheSize, worldSize); - } - - @Test - public void scenarioCoverageTest() { - int simulationLen = 1000 * 10; - - int[] cacheSizes = new int[] { 1, 10, 100}; - // tests with large worldSizes are slow because with a large - // world size the probability of a cache miss is high. - int[] worldSizes = new int[] { 1, 10, 100 }; - - for (int i = 0; i < cacheSizes.length; i++) { - for (int j = 0; j < worldSizes.length; j++) { - doScenario(simulationLen, cacheSizes[i], worldSizes[j]); - } - } - } - - void doScenario(int simulationLen, int cacheSize, int worldSize) { - int get2PutRatio = 10; - Simulator simulator = new Simulator(worldSize, get2PutRatio, false); - List scenario = simulator.generateScenario(simulationLen); - LRUCache lruCache = new LRUCache(cacheSize); - T_LRUCache tlruCache = new T_LRUCache(cacheSize); - long start = System.nanoTime(); - simulator.simulate(scenario, lruCache, tlruCache); - //assertEquals(tlruCache.keyList(), lruCache.keyList()); - long end = System.nanoTime(); - System.out.println("cacheSize=" + cacheSize + ", worldSize=" + worldSize - + ", elapsed time=" + ((end - start) / (1000 * 1000)) + " in millis"); - } - - - - @Test - @Ignore // slow test that is known to pass - public void multiThreadedScenario() throws InterruptedException { - int cacheSize = 100; - int worldSize = cacheSize*2; - LRUCache lruCache = new LRUCache(cacheSize); - T_LRUCache tlruCache = new T_LRUCache(cacheSize); - SimulatorRunnable[] simulatorArray = new SimulatorRunnable[5]; - for(int i = 0; i < simulatorArray.length; i++) { - simulatorArray[i] = new SimulatorRunnable(lruCache, tlruCache, worldSize); - } - for(int i = 0; i < simulatorArray.length; i++) { - simulatorArray[i].start(); - } - for(int i = 0; i < simulatorArray.length; i++) { - simulatorArray[i].join(); - } - assertEquals(tlruCache.keyList(), lruCache.keyList()); - } - - private class SimulatorRunnable extends Thread { - - LRUCache lruCache; - T_LRUCache tlruCache; - int worldSize; - - SimulatorRunnable(LRUCache lruCache, T_LRUCache tlruCache, int worldSize) { - this.lruCache = lruCache; - this.tlruCache = tlruCache; - this.worldSize = worldSize; - } - - public void run() { - int get2PutRatio = 10; - int simulationLen = 1000*50; - Simulator simulator = new Simulator(worldSize, get2PutRatio, true); - List scenario = simulator.generateScenario(simulationLen); - simulator.simulate(scenario, lruCache, tlruCache); - System.out.println("done"); - } - } - -} +/** + * 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.classic.pattern; + +import static org.junit.Assert.assertEquals; + +import java.util.LinkedList; +import java.util.List; + +import org.junit.Ignore; +import org.junit.Test; + +import ch.qos.logback.classic.pattern.lru.Event; +import ch.qos.logback.classic.pattern.lru.T_LRUCache; + +@Ignore +public class LRUCacheTest { + + @Test + public void smoke() { + + LRUCache cache = new LRUCache(2); + cache.put("a", "a"); + cache.put("b", "b"); + cache.put("c", "c"); + List witness = new LinkedList(); + witness.add("b"); + witness.add("c"); + assertEquals(witness, cache.keyList()); + } + + @Test + public void typicalScenarioTest() { + int simulationLen = 1000 * 10; + int cacheSize = 100; + int worldSize = 1000; + doScenario(simulationLen, cacheSize, worldSize); + } + + @Test + public void scenarioCoverageTest() { + int simulationLen = 1000 * 10; + + int[] cacheSizes = new int[] { 1, 10, 100}; + // tests with large worldSizes are slow because with a large + // world size the probability of a cache miss is high. + int[] worldSizes = new int[] { 1, 10, 100 }; + + for (int i = 0; i < cacheSizes.length; i++) { + for (int j = 0; j < worldSizes.length; j++) { + doScenario(simulationLen, cacheSizes[i], worldSizes[j]); + } + } + } + + void doScenario(int simulationLen, int cacheSize, int worldSize) { + int get2PutRatio = 10; + Simulator simulator = new Simulator(worldSize, get2PutRatio, false); + List scenario = simulator.generateScenario(simulationLen); + LRUCache lruCache = new LRUCache(cacheSize); + T_LRUCache tlruCache = new T_LRUCache(cacheSize); + long start = System.nanoTime(); + simulator.simulate(scenario, lruCache, tlruCache); + //assertEquals(tlruCache.keyList(), lruCache.keyList()); + long end = System.nanoTime(); + System.out.println("cacheSize=" + cacheSize + ", worldSize=" + worldSize + + ", elapsed time=" + ((end - start) / (1000 * 1000)) + " in millis"); + } + + + + @Test + @Ignore // slow test that is known to pass + public void multiThreadedScenario() throws InterruptedException { + int cacheSize = 100; + int worldSize = cacheSize*2; + LRUCache lruCache = new LRUCache(cacheSize); + T_LRUCache tlruCache = new T_LRUCache(cacheSize); + SimulatorRunnable[] simulatorArray = new SimulatorRunnable[5]; + for(int i = 0; i < simulatorArray.length; i++) { + simulatorArray[i] = new SimulatorRunnable(lruCache, tlruCache, worldSize); + } + for(int i = 0; i < simulatorArray.length; i++) { + simulatorArray[i].start(); + } + for(int i = 0; i < simulatorArray.length; i++) { + simulatorArray[i].join(); + } + assertEquals(tlruCache.keyList(), lruCache.keyList()); + } + + private class SimulatorRunnable extends Thread { + + LRUCache lruCache; + T_LRUCache tlruCache; + int worldSize; + + SimulatorRunnable(LRUCache lruCache, T_LRUCache tlruCache, int worldSize) { + this.lruCache = lruCache; + this.tlruCache = tlruCache; + this.worldSize = worldSize; + } + + public void run() { + int get2PutRatio = 10; + int simulationLen = 1000*50; + Simulator simulator = new Simulator(worldSize, get2PutRatio, true); + List scenario = simulator.generateScenario(simulationLen); + simulator.simulate(scenario, lruCache, tlruCache); + System.out.println("done"); + } + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/MDCConverterTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/MDCConverterTest.java index 1aaa4c56d6ff2dd000a291c449261617def750ef..4dcf0893dc288ec0bf549e148e30af0b46e6e97e 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/MDCConverterTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/MDCConverterTest.java @@ -1,78 +1,78 @@ -/** - * 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.classic.pattern; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.MDC; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.core.util.SystemInfo; - -public class MDCConverterTest { - - LoggerContext lc; - MDCConverter converter; - - @Before - public void setUp() throws Exception { - lc = new LoggerContext(); - converter = new MDCConverter(); - converter.start(); - } - - @After - public void tearDown() throws Exception { - lc = null; - converter.stop(); - converter = null; - } - - @Test - public void testConverWithOneEntry() { - MDC.clear(); - MDC.put("testKey", "testValue"); - ILoggingEvent le = createLoggingEvent(); - String result = converter.convert(le); - assertEquals("testKey=testValue", result); - } - - @Test - public void testConverWithMultipleEntries() { - MDC.clear(); - MDC.put("testKey", "testValue"); - MDC.put("testKey2", "testValue2"); - ILoggingEvent le = createLoggingEvent(); - String result = converter.convert(le); - if (SystemInfo.getJavaVendor().contains("IBM")) { - assertEquals("testKey2=testValue2, testKey=testValue", result); - } else { - assertEquals("testKey=testValue, testKey2=testValue2", result); - } - } - - private ILoggingEvent createLoggingEvent() { - ILoggingEvent le = new LoggingEvent(this.getClass().getName(), lc - .getLogger(Logger.ROOT_LOGGER_NAME), Level.DEBUG, "test message", null, - null); - return le; - } -} +/** + * 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.classic.pattern; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.MDC; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.util.SystemInfo; + +public class MDCConverterTest { + + LoggerContext lc; + MDCConverter converter; + + @Before + public void setUp() throws Exception { + lc = new LoggerContext(); + converter = new MDCConverter(); + converter.start(); + } + + @After + public void tearDown() throws Exception { + lc = null; + converter.stop(); + converter = null; + } + + @Test + public void testConverWithOneEntry() { + MDC.clear(); + MDC.put("testKey", "testValue"); + ILoggingEvent le = createLoggingEvent(); + String result = converter.convert(le); + assertEquals("testKey=testValue", result); + } + + @Test + public void testConverWithMultipleEntries() { + MDC.clear(); + MDC.put("testKey", "testValue"); + MDC.put("testKey2", "testValue2"); + ILoggingEvent le = createLoggingEvent(); + String result = converter.convert(le); + if (SystemInfo.getJavaVendor().contains("IBM")) { + assertEquals("testKey2=testValue2, testKey=testValue", result); + } else { + assertEquals("testKey=testValue, testKey2=testValue2", result); + } + } + + private ILoggingEvent createLoggingEvent() { + ILoggingEvent le = new LoggingEvent(this.getClass().getName(), lc + .getLogger(Logger.ROOT_LOGGER_NAME), Level.DEBUG, "test message", null, + null); + return le; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/MarkerConverterTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/MarkerConverterTest.java index 8bc071f7ef5d47619e2f6795f94a67a6c6b7a7cc..8d7f64a2a87dc9b311dfa29290547cfaff50fd8b 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/MarkerConverterTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/MarkerConverterTest.java @@ -1,94 +1,94 @@ -/** - * 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.classic.pattern; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.IMarkerFactory; -import org.slf4j.Marker; -import org.slf4j.helpers.BasicMarkerFactory; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; - -public class MarkerConverterTest { - - LoggerContext lc; - MarkerConverter converter; - // use a different facotry for each test so that they are independent - IMarkerFactory markerFactory = new BasicMarkerFactory(); - - @Before - public void setUp() throws Exception { - lc = new LoggerContext(); - converter = new MarkerConverter(); - converter.start(); - } - - @After - public void tearDown() throws Exception { - lc = null; - converter.stop(); - converter = null; - } - - @Test - public void testWithNullMarker() { - String result = converter.convert(createLoggingEvent(null)); - assertEquals("", result); - } - - @Test - public void testWithMarker() { - String name = "test"; - Marker marker = markerFactory.getMarker(name); - String result = converter.convert(createLoggingEvent(marker)); - assertEquals(name, result); - } - - @Test - public void testWithOneChildMarker() { - Marker marker = markerFactory.getMarker("test"); - marker.add(markerFactory.getMarker("child")); - - String result = converter.convert(createLoggingEvent(marker)); - - assertEquals("test [ child ]", result); - } - - @Test - public void testWithSeveralChildMarker() { - Marker marker = markerFactory.getMarker("testParent"); - marker.add(markerFactory.getMarker("child1")); - marker.add(markerFactory.getMarker("child2")); - marker.add(markerFactory.getMarker("child3")); - - String result = converter.convert(createLoggingEvent(marker)); - - assertEquals("testParent [ child1, child2, child3 ]", result); - } - - private ILoggingEvent createLoggingEvent(Marker marker) { - LoggingEvent le = new LoggingEvent(this.getClass().getName(), lc.getLogger(Logger.ROOT_LOGGER_NAME), - Level.DEBUG, "test message", null, null); - le.setMarker(marker); - return le; - } -} +/** + * 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.classic.pattern; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.IMarkerFactory; +import org.slf4j.Marker; +import org.slf4j.helpers.BasicMarkerFactory; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; + +public class MarkerConverterTest { + + LoggerContext lc; + MarkerConverter converter; + // use a different facotry for each test so that they are independent + IMarkerFactory markerFactory = new BasicMarkerFactory(); + + @Before + public void setUp() throws Exception { + lc = new LoggerContext(); + converter = new MarkerConverter(); + converter.start(); + } + + @After + public void tearDown() throws Exception { + lc = null; + converter.stop(); + converter = null; + } + + @Test + public void testWithNullMarker() { + String result = converter.convert(createLoggingEvent(null)); + assertEquals("", result); + } + + @Test + public void testWithMarker() { + String name = "test"; + Marker marker = markerFactory.getMarker(name); + String result = converter.convert(createLoggingEvent(marker)); + assertEquals(name, result); + } + + @Test + public void testWithOneChildMarker() { + Marker marker = markerFactory.getMarker("test"); + marker.add(markerFactory.getMarker("child")); + + String result = converter.convert(createLoggingEvent(marker)); + + assertEquals("test [ child ]", result); + } + + @Test + public void testWithSeveralChildMarker() { + Marker marker = markerFactory.getMarker("testParent"); + marker.add(markerFactory.getMarker("child1")); + marker.add(markerFactory.getMarker("child2")); + marker.add(markerFactory.getMarker("child3")); + + String result = converter.convert(createLoggingEvent(marker)); + + assertEquals("testParent [ child1, child2, child3 ]", result); + } + + private ILoggingEvent createLoggingEvent(Marker marker) { + LoggingEvent le = new LoggingEvent(this.getClass().getName(), lc.getLogger(Logger.ROOT_LOGGER_NAME), + Level.DEBUG, "test message", null, null); + le.setMarker(marker); + return le; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/PackageTest.java index 2f2e0950abb5cfaaa42690b47f4a713352a2e43d..36ff650a5990dc1d560c622d3dbef03d91d0561e 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/PackageTest.java @@ -1,27 +1,27 @@ -/** - * 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.classic.pattern; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses( { ConverterTest.class, - TargetLengthBasedClassNameAbbreviatorTest.class, MDCConverterTest.class, - MarkerConverterTest.class, ExtendedThrowableProxyConverterTest.class, - ThrowableProxyConverterTest.class }) -public class PackageTest { - +/** + * 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.classic.pattern; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses( { ConverterTest.class, + TargetLengthBasedClassNameAbbreviatorTest.class, MDCConverterTest.class, + MarkerConverterTest.class, ExtendedThrowableProxyConverterTest.class, + ThrowableProxyConverterTest.class }) +public class PackageTest { + } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/Simulator.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/Simulator.java index 430c05c72e92c82b353f2f2f778fa61261244b6c..d07fdc48eac3bcaefc52423a1df09aba17db0424 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/Simulator.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/Simulator.java @@ -1,92 +1,92 @@ -/** - * 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.classic.pattern; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import ch.qos.logback.classic.pattern.lru.Event; -import ch.qos.logback.classic.pattern.lru.T_LRUCache; - -public class Simulator { - - Random random; - - int worldSize; - int get2PutRatio; - boolean multiThreaded; - - public Simulator(int worldSize, int get2PutRatio, boolean multiThreaded) { - this.worldSize = worldSize; - this.get2PutRatio = get2PutRatio; - long seed = System.nanoTime(); - // System.out.println("seed is "+seed); - random = new Random(seed); - this.multiThreaded = multiThreaded; - } - - public List generateScenario(int len) { - List scenario = new ArrayList(); - - for (int i = 0; i < len; i++) { - - int r = random.nextInt(get2PutRatio); - boolean put = false; - if (r == 0) { - put = true; - } - r = random.nextInt(worldSize); - Event e = new Event(put, String.valueOf(r)); - scenario.add(e); - } - return scenario; - } - - public void simulate(List scenario, LRUCache lruCache, - T_LRUCache tlruCache) { - for (Event e : scenario) { - if (e.put) { - lruCache.put(e.k, e.k); - tlruCache.put(e.k); - } else { - String r0 = lruCache.get(e.k); - String r1 = tlruCache.get(e.k); - if (!multiThreaded) { - // if the simulation is used in a multi-threaded - // context, then the state of lruCache may be different than - // that of tlruCache. In single threaded mode, they should - // return the same values all the time - if (r0 != null) { - assertEquals(r0, e.k); - } - assertEquals(r0, r1); - } - } - } - } - - // void compareAndDumpIfDifferent(LRUCache lruCache, - // T_LRUCache tlruCache) { - // lruCache.dump(); - // tlruCache.dump(); - // if(!lruCache.keyList().equals(tlruCache.ketList())) { - // lruCache.dump(); - // tlruCache.dump(); - // throw new AssertionFailedError("s"); - // } - // } -} +/** + * 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.classic.pattern; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import ch.qos.logback.classic.pattern.lru.Event; +import ch.qos.logback.classic.pattern.lru.T_LRUCache; + +public class Simulator { + + Random random; + + int worldSize; + int get2PutRatio; + boolean multiThreaded; + + public Simulator(int worldSize, int get2PutRatio, boolean multiThreaded) { + this.worldSize = worldSize; + this.get2PutRatio = get2PutRatio; + long seed = System.nanoTime(); + // System.out.println("seed is "+seed); + random = new Random(seed); + this.multiThreaded = multiThreaded; + } + + public List generateScenario(int len) { + List scenario = new ArrayList(); + + for (int i = 0; i < len; i++) { + + int r = random.nextInt(get2PutRatio); + boolean put = false; + if (r == 0) { + put = true; + } + r = random.nextInt(worldSize); + Event e = new Event(put, String.valueOf(r)); + scenario.add(e); + } + return scenario; + } + + public void simulate(List scenario, LRUCache lruCache, + T_LRUCache tlruCache) { + for (Event e : scenario) { + if (e.put) { + lruCache.put(e.k, e.k); + tlruCache.put(e.k); + } else { + String r0 = lruCache.get(e.k); + String r1 = tlruCache.get(e.k); + if (!multiThreaded) { + // if the simulation is used in a multi-threaded + // context, then the state of lruCache may be different than + // that of tlruCache. In single threaded mode, they should + // return the same values all the time + if (r0 != null) { + assertEquals(r0, e.k); + } + assertEquals(r0, r1); + } + } + } + } + + // void compareAndDumpIfDifferent(LRUCache lruCache, + // T_LRUCache tlruCache) { + // lruCache.dump(); + // tlruCache.dump(); + // if(!lruCache.keyList().equals(tlruCache.ketList())) { + // lruCache.dump(); + // tlruCache.dump(); + // throw new AssertionFailedError("s"); + // } + // } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviatorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviatorTest.java index 656a77f0fe433a13e4e88df6cba01111e083bd59..0de74daca8a9f15d40f95ad622b60cc6b1c87f7f 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviatorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviatorTest.java @@ -1,149 +1,149 @@ -/** - * 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.classic.pattern; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import ch.qos.logback.classic.pattern.TargetLengthBasedClassNameAbbreviator; - -public class TargetLengthBasedClassNameAbbreviatorTest { - - - @Test - public void testShortName() { - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(100); - String name = "hello"; - assertEquals(name, abbreviator.abbreviate(name)); - } - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(100); - String name = "hello.world"; - assertEquals(name, abbreviator.abbreviate(name)); - } - } - - @Test - public void testNoDot() { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); - String name = "hello"; - assertEquals(name, abbreviator.abbreviate(name)); - } - - @Test - public void testOneDot() { - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); - String name = "hello.world"; - assertEquals("h.world", abbreviator.abbreviate(name)); - } - - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); - String name = "h.world"; - assertEquals("h.world", abbreviator.abbreviate(name)); - } - - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); - String name = ".world"; - assertEquals(".world", abbreviator.abbreviate(name)); - } - } - - @Test - public void testTwoDot() { - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); - String name = "com.logback.Foobar"; - assertEquals("c.l.Foobar", abbreviator.abbreviate(name)); - } - - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); - String name = "c.logback.Foobar"; - assertEquals("c.l.Foobar", abbreviator.abbreviate(name)); - } - - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); - String name = "c..Foobar"; - assertEquals("c..Foobar", abbreviator.abbreviate(name)); - } - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); - String name = "..Foobar"; - assertEquals("..Foobar", abbreviator.abbreviate(name)); - } - } - - @Test - public void test3Dot() { - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); - String name = "com.logback.xyz.Foobar"; - assertEquals("c.l.x.Foobar", abbreviator.abbreviate(name)); - } - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(13); - String name = "com.logback.xyz.Foobar"; - assertEquals("c.l.x.Foobar", abbreviator.abbreviate(name)); - } - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(14); - String name = "com.logback.xyz.Foobar"; - assertEquals("c.l.xyz.Foobar", abbreviator.abbreviate(name)); - } - - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(15); - String name = "com.logback.alligator.Foobar"; - assertEquals("c.l.a.Foobar", abbreviator.abbreviate(name)); - } - } - @Test - public void testXDot() { - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(21); - String name = "com.logback.wombat.alligator.Foobar"; - assertEquals("c.l.w.a.Foobar", abbreviator.abbreviate(name)); - } - - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(22); - String name = "com.logback.wombat.alligator.Foobar"; - assertEquals("c.l.w.alligator.Foobar", abbreviator.abbreviate(name)); - } - - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); - String name = "com.logback.wombat.alligator.tomato.Foobar"; - assertEquals("c.l.w.a.t.Foobar", abbreviator.abbreviate(name)); - } - - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(21); - String name = "com.logback.wombat.alligator.tomato.Foobar"; - assertEquals("c.l.w.a.tomato.Foobar", abbreviator.abbreviate(name)); - } - - { - TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(29); - String name = "com.logback.wombat.alligator.tomato.Foobar"; - assertEquals("c.l.w.alligator.tomato.Foobar", abbreviator.abbreviate(name)); - } - } -} +/** + * 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.classic.pattern; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ch.qos.logback.classic.pattern.TargetLengthBasedClassNameAbbreviator; + +public class TargetLengthBasedClassNameAbbreviatorTest { + + + @Test + public void testShortName() { + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(100); + String name = "hello"; + assertEquals(name, abbreviator.abbreviate(name)); + } + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(100); + String name = "hello.world"; + assertEquals(name, abbreviator.abbreviate(name)); + } + } + + @Test + public void testNoDot() { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); + String name = "hello"; + assertEquals(name, abbreviator.abbreviate(name)); + } + + @Test + public void testOneDot() { + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); + String name = "hello.world"; + assertEquals("h.world", abbreviator.abbreviate(name)); + } + + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); + String name = "h.world"; + assertEquals("h.world", abbreviator.abbreviate(name)); + } + + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); + String name = ".world"; + assertEquals(".world", abbreviator.abbreviate(name)); + } + } + + @Test + public void testTwoDot() { + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); + String name = "com.logback.Foobar"; + assertEquals("c.l.Foobar", abbreviator.abbreviate(name)); + } + + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); + String name = "c.logback.Foobar"; + assertEquals("c.l.Foobar", abbreviator.abbreviate(name)); + } + + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); + String name = "c..Foobar"; + assertEquals("c..Foobar", abbreviator.abbreviate(name)); + } + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); + String name = "..Foobar"; + assertEquals("..Foobar", abbreviator.abbreviate(name)); + } + } + + @Test + public void test3Dot() { + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); + String name = "com.logback.xyz.Foobar"; + assertEquals("c.l.x.Foobar", abbreviator.abbreviate(name)); + } + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(13); + String name = "com.logback.xyz.Foobar"; + assertEquals("c.l.x.Foobar", abbreviator.abbreviate(name)); + } + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(14); + String name = "com.logback.xyz.Foobar"; + assertEquals("c.l.xyz.Foobar", abbreviator.abbreviate(name)); + } + + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(15); + String name = "com.logback.alligator.Foobar"; + assertEquals("c.l.a.Foobar", abbreviator.abbreviate(name)); + } + } + @Test + public void testXDot() { + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(21); + String name = "com.logback.wombat.alligator.Foobar"; + assertEquals("c.l.w.a.Foobar", abbreviator.abbreviate(name)); + } + + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(22); + String name = "com.logback.wombat.alligator.Foobar"; + assertEquals("c.l.w.alligator.Foobar", abbreviator.abbreviate(name)); + } + + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(1); + String name = "com.logback.wombat.alligator.tomato.Foobar"; + assertEquals("c.l.w.a.t.Foobar", abbreviator.abbreviate(name)); + } + + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(21); + String name = "com.logback.wombat.alligator.tomato.Foobar"; + assertEquals("c.l.w.a.tomato.Foobar", abbreviator.abbreviate(name)); + } + + { + TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(29); + String name = "com.logback.wombat.alligator.tomato.Foobar"; + assertEquals("c.l.w.alligator.tomato.Foobar", abbreviator.abbreviate(name)); + } + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ThrowableProxyConverterTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ThrowableProxyConverterTest.java index 1a463f6e7383ee2783427700f2afecef31431cae..0da62ca9c96d6accd64f1206f730b4453ba54207 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ThrowableProxyConverterTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ThrowableProxyConverterTest.java @@ -1,79 +1,79 @@ -/** - * 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.classic.pattern; - -import static org.junit.Assert.assertEquals; - -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.classic.util.TeztHelper; - -public class ThrowableProxyConverterTest { - - LoggerContext lc = new LoggerContext(); - ThrowableProxyConverter tpc = new ThrowableProxyConverter(); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - - @Before - public void setUp() throws Exception { - tpc.setContext(lc); - tpc.start(); - } - - @After - public void tearDown() throws Exception { - } - - private ILoggingEvent createLoggingEvent(Throwable t) { - ILoggingEvent le = new LoggingEvent(this.getClass().getName(), lc - .getLogger(Logger.ROOT_LOGGER_NAME), Level.DEBUG, "test message", t, - null); - return le; - } - - @Test - public void smoke() { - Exception t = new Exception("smoke"); - verify(t); - } - - @Test - public void nested() { - Throwable t = TeztHelper.makeNestedException(1); - verify(t); - } - - void verify(Throwable t) { - t.printStackTrace(pw); - - ILoggingEvent le = createLoggingEvent(t); - String result = tpc.convert(le); - System.out.println(result); - result = result.replace("common frames omitted", "more"); - assertEquals(sw.toString(), result); - } - - -} +/** + * 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.classic.pattern; + +import static org.junit.Assert.assertEquals; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.classic.util.TeztHelper; + +public class ThrowableProxyConverterTest { + + LoggerContext lc = new LoggerContext(); + ThrowableProxyConverter tpc = new ThrowableProxyConverter(); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + + @Before + public void setUp() throws Exception { + tpc.setContext(lc); + tpc.start(); + } + + @After + public void tearDown() throws Exception { + } + + private ILoggingEvent createLoggingEvent(Throwable t) { + ILoggingEvent le = new LoggingEvent(this.getClass().getName(), lc + .getLogger(Logger.ROOT_LOGGER_NAME), Level.DEBUG, "test message", t, + null); + return le; + } + + @Test + public void smoke() { + Exception t = new Exception("smoke"); + verify(t); + } + + @Test + public void nested() { + Throwable t = TeztHelper.makeNestedException(1); + verify(t); + } + + void verify(Throwable t) { + t.printStackTrace(pw); + + ILoggingEvent le = createLoggingEvent(t); + String result = tpc.convert(le); + System.out.println(result); + result = result.replace("common frames omitted", "more"); + assertEquals(sw.toString(), result); + } + + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/Event.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/Event.java index 4631076f9ceeef91a4fda79effe67ed3a63e9929..6219c35e0ef287a0ecc0cdc375b5aea3eb28bb90 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/Event.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/Event.java @@ -1,33 +1,33 @@ -/** - * 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.classic.pattern.lru; - -public class Event { - - final public boolean put; - final public K k; - - public Event(boolean put, K k) { - this.put = put; - this.k = k; - } - - public String toString() { - if(put) { - return "Event: put, "+k; - } else { - return "Event: get, "+k; - } - } -} +/** + * 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.classic.pattern.lru; + +public class Event { + + final public boolean put; + final public K k; + + public Event(boolean put, K k) { + this.put = put; + this.k = k; + } + + public String toString() { + if(put) { + return "Event: put, "+k; + } else { + return "Event: get, "+k; + } + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/T_Entry.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/T_Entry.java index fa80bcb582963adb7a61349b10d586d279fac706..59cff0afebcda2d5eb09f9855c1c726f1ec3e477 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/T_Entry.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/T_Entry.java @@ -1,45 +1,45 @@ -/** - * 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.classic.pattern.lru; - -public class T_Entry implements Comparable { - - K k; - long sequenceNumber; - - T_Entry(K k, long sn) { - this.k = k; - this.sequenceNumber = sn; - } - - public int compareTo(Object o) { - if(!(o instanceof T_Entry)) { - throw new IllegalArgumentException("arguments must be of type "+T_Entry.class); - } - - T_Entry other = (T_Entry) o; - if(sequenceNumber > other.sequenceNumber) { - return 1; - } - if(sequenceNumber == other.sequenceNumber) { - return 0; - } - return -1; - } - @Override - public String toString() { - return "("+k+","+sequenceNumber+")"; - //return "("+k+")"; - } -} +/** + * 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.classic.pattern.lru; + +public class T_Entry implements Comparable { + + K k; + long sequenceNumber; + + T_Entry(K k, long sn) { + this.k = k; + this.sequenceNumber = sn; + } + + public int compareTo(Object o) { + if(!(o instanceof T_Entry)) { + throw new IllegalArgumentException("arguments must be of type "+T_Entry.class); + } + + T_Entry other = (T_Entry) o; + if(sequenceNumber > other.sequenceNumber) { + return 1; + } + if(sequenceNumber == other.sequenceNumber) { + return 0; + } + return -1; + } + @Override + public String toString() { + return "("+k+","+sequenceNumber+")"; + //return "("+k+")"; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/T_LRUCache.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/T_LRUCache.java index d56a0419902209f6290be171b7534bde70b6efd4..d132ee18f44b59fcc6a523063977d6835bf7d93b 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/T_LRUCache.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/lru/T_LRUCache.java @@ -1,93 +1,93 @@ -/** - * 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.classic.pattern.lru; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -/** - * This is an alternative (slower) implementation of LRUCache for testing - * purposes. - * - * @author Ceki Gulcu - */ -public class T_LRUCache { - - int sequenceNumber; - final int cacheSize; - List> cacheList = new LinkedList>(); - - public T_LRUCache(int size) { - this.cacheSize = size; - } - - @SuppressWarnings("unchecked") - synchronized public void put(K k) { - sequenceNumber++; - T_Entry te = getEntry(k); - if (te != null) { - te.sequenceNumber = sequenceNumber; - } else { - te = new T_Entry(k, sequenceNumber); - cacheList.add(te); - } - Collections.sort(cacheList); - while(cacheList.size() > cacheSize) { - cacheList.remove(0); - } - } - - @SuppressWarnings("unchecked") - synchronized public K get(K k) { - T_Entry te = getEntry(k); - if (te == null) { - return null; - } else { - te.sequenceNumber = ++sequenceNumber; - Collections.sort(cacheList); - return te.k; - } - } - - synchronized public List keyList() { - List keyList = new ArrayList(); - for (T_Entry e : cacheList) { - keyList.add(e.k); - } - return keyList; - } - - private T_Entry getEntry(K k) { - for (int i = 0; i < cacheList.size(); i++) { - T_Entry te = cacheList.get(i); - if (te.k.equals(k)) { - return te; - } - } - return null; - } - - public void dump() { - System.out.print("T:"); - for (T_Entry te : cacheList) { - //System.out.print(te.toString()+"->"); - System.out.print(te.k+", "); - } - System.out.println(); - } - -} - +/** + * 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.classic.pattern.lru; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * This is an alternative (slower) implementation of LRUCache for testing + * purposes. + * + * @author Ceki Gulcu + */ +public class T_LRUCache { + + int sequenceNumber; + final int cacheSize; + List> cacheList = new LinkedList>(); + + public T_LRUCache(int size) { + this.cacheSize = size; + } + + @SuppressWarnings("unchecked") + synchronized public void put(K k) { + sequenceNumber++; + T_Entry te = getEntry(k); + if (te != null) { + te.sequenceNumber = sequenceNumber; + } else { + te = new T_Entry(k, sequenceNumber); + cacheList.add(te); + } + Collections.sort(cacheList); + while(cacheList.size() > cacheSize) { + cacheList.remove(0); + } + } + + @SuppressWarnings("unchecked") + synchronized public K get(K k) { + T_Entry te = getEntry(k); + if (te == null) { + return null; + } else { + te.sequenceNumber = ++sequenceNumber; + Collections.sort(cacheList); + return te.k; + } + } + + synchronized public List keyList() { + List keyList = new ArrayList(); + for (T_Entry e : cacheList) { + keyList.add(e.k); + } + return keyList; + } + + private T_Entry getEntry(K k) { + for (int i = 0; i < cacheList.size(); i++) { + T_Entry te = cacheList.get(i); + if (te.k.equals(k)) { + return te; + } + } + return null; + } + + public void dump() { + System.out.print("T:"); + for (T_Entry te : cacheList) { + //System.out.print(te.toString()+"->"); + System.out.print(te.k+", "); + } + System.out.println(); + } + +} + diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/rolling/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/rolling/PackageTest.java index 487b2c134876a86433e8e5cfa04a557151002309..5996ff5a028948f7bec2fba60ed0b5a02bbbd07d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/rolling/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/rolling/PackageTest.java @@ -1,23 +1,23 @@ -/** - * 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.classic.rolling; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses( { UniqueFileTest.class, TimeBasedRollingWithConfigFileTest.class }) -public class PackageTest { +/** + * 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.classic.rolling; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses( { UniqueFileTest.class, TimeBasedRollingWithConfigFileTest.class }) +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/rolling/TimeBasedRollingWithConfigFileTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/rolling/TimeBasedRollingWithConfigFileTest.java index 096dda2d1798723f0349db207f3eab89ca92f333..f25d9818cc954839584e9e2952e3bda894737235 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/rolling/TimeBasedRollingWithConfigFileTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/rolling/TimeBasedRollingWithConfigFileTest.java @@ -1,191 +1,191 @@ -/** - * 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.classic.rolling; - -import static org.junit.Assert.assertTrue; - -import java.util.Date; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.ClassicTestConstants; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.rolling.RollingFileAppender; -import ch.qos.logback.core.rolling.ScaffoldingForRollingTests; -import ch.qos.logback.core.rolling.TimeBasedFileNamingAndTriggeringPolicy; -import ch.qos.logback.core.rolling.TimeBasedRollingPolicy; -import ch.qos.logback.core.status.StatusChecker; - -public class TimeBasedRollingWithConfigFileTest extends - ScaffoldingForRollingTests { - - LoggerContext lc = new LoggerContext(); - Logger logger = lc.getLogger(this.getClass()); - int fileSize = 0; - int fileIndexCounter = -1; - int sizeThreshold; - - @Before - @Override - public void setUp() { - lc.setName("test"); - super.setUp(); - lc.putProperty("randomOutputDir", randomOutputDir); - } - - @After - public void tearDown() throws Exception { - } - - void loadConfig(String confifFile) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(lc); - jc.doConfigure(confifFile); - currentTime = System.currentTimeMillis(); - recomputeRolloverThreshold(currentTime); - } - - @Test - public void basic() throws Exception { - String testId = "basic"; - lc.putProperty("testId", testId); - loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId - + ".xml"); - StatusChecker sc = new StatusChecker(lc); - assertTrue(sc.isErrorFree()); - - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - - expectedFilenameList.add(randomOutputDir + "z" + testId); - - RollingFileAppender rfa = (RollingFileAppender) root - .getAppender("ROLLING"); - - TimeBasedRollingPolicy tprp = (TimeBasedRollingPolicy) rfa - .getTriggeringPolicy(); - TimeBasedFileNamingAndTriggeringPolicy tbnatp = tprp - .getTimeBasedFileNamingAndTriggeringPolicy(); - - String prefix = "Hello---"; - int runLength = 4; - for (int i = 0; i < runLength; i++) { - logger.debug(prefix + i); - addExpectedFileNamedIfItsTime_ByDate(testId, false); - incCurrentTime(500); - tbnatp.setCurrentTime(currentTime); - } - - existenceCheck(expectedFilenameList); - sortedContentCheck(randomOutputDir, runLength, prefix); - } - - @Test - public void timeAndSize() throws Exception { - String testId = "timeAndSize"; - lc.putProperty("testId", testId); - String prefix = "Hello-----"; - - // the number of times the log file will be written to before time based - // roll-over occurs - int approxWritesPerPeriod = 64; - sizeThreshold = prefix.length() * approxWritesPerPeriod; - lc.putProperty("sizeThreshold", "" + sizeThreshold); - loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId - + ".xml"); - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - - expectedFilenameList.add(randomOutputDir + "z" + testId); - - RollingFileAppender rfa = (RollingFileAppender) root - .getAppender("ROLLING"); - - StatusChecker sc = new StatusChecker(lc); - assertTrue(sc.isErrorFree()); - - TimeBasedRollingPolicy tprp = (TimeBasedRollingPolicy) rfa - .getTriggeringPolicy(); - TimeBasedFileNamingAndTriggeringPolicy tbnatp = tprp - .getTimeBasedFileNamingAndTriggeringPolicy(); - - int timeIncrement = 1000 / approxWritesPerPeriod; - int runLength = approxWritesPerPeriod * 3; - for (int i = 0; i < runLength; i++) { - String msg = prefix + i; - logger.debug(msg); - addExpectedFileNamedIfItsTime(testId, msg, false); - incCurrentTime(timeIncrement); - tbnatp.setCurrentTime(currentTime); - } - - sortedContentCheck(randomOutputDir, runLength, prefix); - int eCount = existenceCount(expectedFilenameList); - // for various reasons, it is extremely difficult to have the files - // match exactly the expected archive files. Thus, we aim for - // an approximate match - assertTrue("exitenceCount=" + eCount + ", expectedFilenameList.size=" - + expectedFilenameList.size(), eCount >= 4 - && eCount > expectedFilenameList.size() / 2); - } - - void addExpectedFileNamedIfItsTime(String testId, String msg, - boolean gzExtension) { - fileSize += msg.getBytes().length; - - if (passThresholdTime(nextRolloverThreshold)) { - fileIndexCounter = 0; - fileSize = 0; - addExpectedFileName(testId, getDateOfPreviousPeriodsStart(), - fileIndexCounter, gzExtension); - recomputeRolloverThreshold(currentTime); - return; - } - - // windows can delay file size changes, so we only allow for - // fileIndexCounter 0 and 1 - if ((fileIndexCounter < 1) && fileSize > sizeThreshold) { - addExpectedFileName(testId, getDateOfPreviousPeriodsStart(), - ++fileIndexCounter, gzExtension); - fileSize = -1; - return; - } - } - - void addExpectedFileName(String testId, Date date, int fileIndexCounter, - boolean gzExtension) { - - String fn = randomOutputDir + testId + "-" + SDF.format(date) + "." - + fileIndexCounter; - System.out.println("Adding " + fn); - if (gzExtension) { - fn += ".gz"; - } - expectedFilenameList.add(fn); - } - - @Override - protected void addExpectedFileNamedIfItsTime_ByDate(String testId, - boolean gzExtension) { - if (passThresholdTime(nextRolloverThreshold)) { - addExpectedFileName_ByDate(testId, getDateOfPreviousPeriodsStart(), - gzExtension); - recomputeRolloverThreshold(currentTime); - } - } -} +/** + * 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.classic.rolling; + +import static org.junit.Assert.assertTrue; + +import java.util.Date; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.ClassicTestConstants; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.rolling.RollingFileAppender; +import ch.qos.logback.core.rolling.ScaffoldingForRollingTests; +import ch.qos.logback.core.rolling.TimeBasedFileNamingAndTriggeringPolicy; +import ch.qos.logback.core.rolling.TimeBasedRollingPolicy; +import ch.qos.logback.core.status.StatusChecker; + +public class TimeBasedRollingWithConfigFileTest extends + ScaffoldingForRollingTests { + + LoggerContext lc = new LoggerContext(); + Logger logger = lc.getLogger(this.getClass()); + int fileSize = 0; + int fileIndexCounter = -1; + int sizeThreshold; + + @Before + @Override + public void setUp() { + lc.setName("test"); + super.setUp(); + lc.putProperty("randomOutputDir", randomOutputDir); + } + + @After + public void tearDown() throws Exception { + } + + void loadConfig(String confifFile) throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(lc); + jc.doConfigure(confifFile); + currentTime = System.currentTimeMillis(); + recomputeRolloverThreshold(currentTime); + } + + @Test + public void basic() throws Exception { + String testId = "basic"; + lc.putProperty("testId", testId); + loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + + ".xml"); + StatusChecker sc = new StatusChecker(lc); + assertTrue(sc.isErrorFree()); + + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + + expectedFilenameList.add(randomOutputDir + "z" + testId); + + RollingFileAppender rfa = (RollingFileAppender) root + .getAppender("ROLLING"); + + TimeBasedRollingPolicy tprp = (TimeBasedRollingPolicy) rfa + .getTriggeringPolicy(); + TimeBasedFileNamingAndTriggeringPolicy tbnatp = tprp + .getTimeBasedFileNamingAndTriggeringPolicy(); + + String prefix = "Hello---"; + int runLength = 4; + for (int i = 0; i < runLength; i++) { + logger.debug(prefix + i); + addExpectedFileNamedIfItsTime_ByDate(testId, false); + incCurrentTime(500); + tbnatp.setCurrentTime(currentTime); + } + + existenceCheck(expectedFilenameList); + sortedContentCheck(randomOutputDir, runLength, prefix); + } + + @Test + public void timeAndSize() throws Exception { + String testId = "timeAndSize"; + lc.putProperty("testId", testId); + String prefix = "Hello-----"; + + // the number of times the log file will be written to before time based + // roll-over occurs + int approxWritesPerPeriod = 64; + sizeThreshold = prefix.length() * approxWritesPerPeriod; + lc.putProperty("sizeThreshold", "" + sizeThreshold); + loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + + ".xml"); + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + + expectedFilenameList.add(randomOutputDir + "z" + testId); + + RollingFileAppender rfa = (RollingFileAppender) root + .getAppender("ROLLING"); + + StatusChecker sc = new StatusChecker(lc); + assertTrue(sc.isErrorFree()); + + TimeBasedRollingPolicy tprp = (TimeBasedRollingPolicy) rfa + .getTriggeringPolicy(); + TimeBasedFileNamingAndTriggeringPolicy tbnatp = tprp + .getTimeBasedFileNamingAndTriggeringPolicy(); + + int timeIncrement = 1000 / approxWritesPerPeriod; + int runLength = approxWritesPerPeriod * 3; + for (int i = 0; i < runLength; i++) { + String msg = prefix + i; + logger.debug(msg); + addExpectedFileNamedIfItsTime(testId, msg, false); + incCurrentTime(timeIncrement); + tbnatp.setCurrentTime(currentTime); + } + + sortedContentCheck(randomOutputDir, runLength, prefix); + int eCount = existenceCount(expectedFilenameList); + // for various reasons, it is extremely difficult to have the files + // match exactly the expected archive files. Thus, we aim for + // an approximate match + assertTrue("exitenceCount=" + eCount + ", expectedFilenameList.size=" + + expectedFilenameList.size(), eCount >= 4 + && eCount > expectedFilenameList.size() / 2); + } + + void addExpectedFileNamedIfItsTime(String testId, String msg, + boolean gzExtension) { + fileSize += msg.getBytes().length; + + if (passThresholdTime(nextRolloverThreshold)) { + fileIndexCounter = 0; + fileSize = 0; + addExpectedFileName(testId, getDateOfPreviousPeriodsStart(), + fileIndexCounter, gzExtension); + recomputeRolloverThreshold(currentTime); + return; + } + + // windows can delay file size changes, so we only allow for + // fileIndexCounter 0 and 1 + if ((fileIndexCounter < 1) && fileSize > sizeThreshold) { + addExpectedFileName(testId, getDateOfPreviousPeriodsStart(), + ++fileIndexCounter, gzExtension); + fileSize = -1; + return; + } + } + + void addExpectedFileName(String testId, Date date, int fileIndexCounter, + boolean gzExtension) { + + String fn = randomOutputDir + testId + "-" + SDF.format(date) + "." + + fileIndexCounter; + System.out.println("Adding " + fn); + if (gzExtension) { + fn += ".gz"; + } + expectedFilenameList.add(fn); + } + + @Override + protected void addExpectedFileNamedIfItsTime_ByDate(String testId, + boolean gzExtension) { + if (passThresholdTime(nextRolloverThreshold)) { + addExpectedFileName_ByDate(testId, getDateOfPreviousPeriodsStart(), + gzExtension); + recomputeRolloverThreshold(currentTime); + } + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/rolling/UniqueFileTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/rolling/UniqueFileTest.java index 38bec983a75d5e9894e7f3399ff72127fcccea07..18907b612532116383ea6173cbea922bff03108f 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/rolling/UniqueFileTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/rolling/UniqueFileTest.java @@ -1,65 +1,65 @@ -/** - * 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.classic.rolling; - -import static org.junit.Assert.assertTrue; - -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.junit.Test; - -import ch.qos.logback.classic.ClassicTestConstants; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.rolling.ScaffoldingForRollingTests; -import ch.qos.logback.core.status.StatusChecker; -import ch.qos.logback.core.util.CoreTestConstants; - -/** - * Test that we can create time-stamped log files with the help of - * the <timestamp> element in configuration files. - * - * @author Ceki Gülcü - * - */ -public class UniqueFileTest { - - LoggerContext lc = new LoggerContext(); - Logger logger = lc.getLogger(this.getClass()); - - - void loadConfig(String confifFile) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(lc); - jc.doConfigure(confifFile); - } - - @Test - public void basic() throws Exception { - loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "unique.xml"); - SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); - String timestamp = sdf.format(new Date()); - - StatusChecker sc = new StatusChecker(lc); - assertTrue(sc.isErrorFree()); - - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - root.info("hello"); - - ScaffoldingForRollingTests.existenceCheck(CoreTestConstants.OUTPUT_DIR_PREFIX+"TS_"+timestamp+"log.txt"); - } -} +/** + * 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.classic.rolling; + +import static org.junit.Assert.assertTrue; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.junit.Test; + +import ch.qos.logback.classic.ClassicTestConstants; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.rolling.ScaffoldingForRollingTests; +import ch.qos.logback.core.status.StatusChecker; +import ch.qos.logback.core.util.CoreTestConstants; + +/** + * Test that we can create time-stamped log files with the help of + * the <timestamp> element in configuration files. + * + * @author Ceki Gülcü + * + */ +public class UniqueFileTest { + + LoggerContext lc = new LoggerContext(); + Logger logger = lc.getLogger(this.getClass()); + + + void loadConfig(String confifFile) throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(lc); + jc.doConfigure(confifFile); + } + + @Test + public void basic() throws Exception { + loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "unique.xml"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + String timestamp = sdf.format(new Date()); + + StatusChecker sc = new StatusChecker(lc); + assertTrue(sc.isErrorFree()); + + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + root.info("hello"); + + ScaffoldingForRollingTests.existenceCheck(CoreTestConstants.OUTPUT_DIR_PREFIX+"TS_"+timestamp+"log.txt"); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/selector/ContextDetachingSCLTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/selector/ContextDetachingSCLTest.java index 88d6021b61968fa6949d88566f1dac80a48decd6..260082c379fdac759a6acec2ff0bbe480a2ab9f0 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/selector/ContextDetachingSCLTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/selector/ContextDetachingSCLTest.java @@ -1,81 +1,81 @@ -/** - * 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.classic.selector; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.LoggerFactory; -import org.slf4j.impl.StaticLoggerBinder; - -import ch.qos.logback.classic.ClassicConstants; -import ch.qos.logback.classic.selector.servlet.ContextDetachingSCL; -import ch.qos.logback.classic.util.MockInitialContext; -import ch.qos.logback.classic.util.MockInitialContextFactory; - -public class ContextDetachingSCLTest { - - static String INITIAL_CONTEXT_KEY = "java.naming.factory.initial"; - - ContextDetachingSCL listener; - - @Before - public void setUp() throws Exception { - System.setProperty(ClassicConstants.LOGBACK_CONTEXT_SELECTOR, "JNDI"); - //LoggerFactory.setup(); - - listener = new ContextDetachingSCL(); - - MockInitialContextFactory.initialize(); - MockInitialContext mic = MockInitialContextFactory.getContext(); - mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, "toto"); - - //The property must be set after we setup the Mock - System.setProperty(INITIAL_CONTEXT_KEY, MockInitialContextFactory.class.getName()); - - //this call will create the context "toto" - LoggerFactory.getLogger(ContextDetachingSCLTest.class); - - } - - @After - public void tearDown() throws Exception { - System.clearProperty(INITIAL_CONTEXT_KEY); - } - - @Test - public void testDetach() { - ContextJNDISelector selector = (ContextJNDISelector) StaticLoggerBinder.getSingleton().getContextSelector(); - listener.contextDestroyed(null); - assertEquals(0, selector.getCount()); - } - - - @Test - public void testDetachWithMissingContext() { - MockInitialContext mic = MockInitialContextFactory.getContext(); - mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, "tata"); - ContextJNDISelector selector = (ContextJNDISelector) StaticLoggerBinder.getSingleton().getContextSelector(); - assertEquals("tata", selector.getLoggerContext().getName()); - - mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, "titi"); - assertEquals("titi", selector.getLoggerContext().getName()); - listener.contextDestroyed(null); - - assertEquals(2, selector.getCount()); - } - -} +/** + * 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.classic.selector; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.LoggerFactory; +import org.slf4j.impl.StaticLoggerBinder; + +import ch.qos.logback.classic.ClassicConstants; +import ch.qos.logback.classic.selector.servlet.ContextDetachingSCL; +import ch.qos.logback.classic.util.MockInitialContext; +import ch.qos.logback.classic.util.MockInitialContextFactory; + +public class ContextDetachingSCLTest { + + static String INITIAL_CONTEXT_KEY = "java.naming.factory.initial"; + + ContextDetachingSCL listener; + + @Before + public void setUp() throws Exception { + System.setProperty(ClassicConstants.LOGBACK_CONTEXT_SELECTOR, "JNDI"); + //LoggerFactory.setup(); + + listener = new ContextDetachingSCL(); + + MockInitialContextFactory.initialize(); + MockInitialContext mic = MockInitialContextFactory.getContext(); + mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, "toto"); + + //The property must be set after we setup the Mock + System.setProperty(INITIAL_CONTEXT_KEY, MockInitialContextFactory.class.getName()); + + //this call will create the context "toto" + LoggerFactory.getLogger(ContextDetachingSCLTest.class); + + } + + @After + public void tearDown() throws Exception { + System.clearProperty(INITIAL_CONTEXT_KEY); + } + + @Test + public void testDetach() { + ContextJNDISelector selector = (ContextJNDISelector) StaticLoggerBinder.getSingleton().getContextSelector(); + listener.contextDestroyed(null); + assertEquals(0, selector.getCount()); + } + + + @Test + public void testDetachWithMissingContext() { + MockInitialContext mic = MockInitialContextFactory.getContext(); + mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, "tata"); + ContextJNDISelector selector = (ContextJNDISelector) StaticLoggerBinder.getSingleton().getContextSelector(); + assertEquals("tata", selector.getLoggerContext().getName()); + + mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, "titi"); + assertEquals("titi", selector.getLoggerContext().getName()); + listener.contextDestroyed(null); + + assertEquals(2, selector.getCount()); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/selector/ContextJNDISelectorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/selector/ContextJNDISelectorTest.java index 273bdff540ce8a97bdc92b53c18230b0540895bb..8e41eb1cd5b7befcb1b5b90b093385d454b145d9 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/selector/ContextJNDISelectorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/selector/ContextJNDISelectorTest.java @@ -1,88 +1,88 @@ -/** - * 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.classic.selector; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.LoggerFactory; -import org.slf4j.impl.StaticLoggerBinder; -import org.slf4j.impl.StaticLoggerBinderFriend; - -import ch.qos.logback.classic.ClassicConstants; -import ch.qos.logback.classic.util.MockInitialContext; -import ch.qos.logback.classic.util.MockInitialContextFactory; -import ch.qos.logback.core.Context; - -public class ContextJNDISelectorTest { - - static String INITIAL_CONTEXT_KEY = "java.naming.factory.initial"; - - @Before - public void setUp() throws Exception { - - System.setProperty(ClassicConstants.LOGBACK_CONTEXT_SELECTOR, "JNDI"); - StaticLoggerBinderFriend.reset(); - - MockInitialContextFactory.initialize(); - MockInitialContext mic = MockInitialContextFactory.getContext(); - mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, "toto"); - - //The property must be set after we setup the Mock - System.setProperty(INITIAL_CONTEXT_KEY, MockInitialContextFactory.class.getName()); - - //this call will create the context "toto" - LoggerFactory.getLogger(ContextDetachingSCLTest.class); - } - - @After - public void tearDown() throws Exception { - System.clearProperty(INITIAL_CONTEXT_KEY); - } - - @Test - public void testGetExistingContext() { - ContextSelector selector = StaticLoggerBinder.getSingleton().getContextSelector(); - Context context = selector.getLoggerContext(); - assertEquals("toto", context.getName()); - } - - @Test - public void testCreateContext() { - MockInitialContext mic = MockInitialContextFactory.getContext(); - mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, "tata"); - - LoggerFactory.getLogger(ContextDetachingSCLTest.class); - - ContextJNDISelector selector = (ContextJNDISelector)StaticLoggerBinder.getSingleton().getContextSelector(); - Context context = selector.getLoggerContext(); - assertEquals("tata", context.getName()); - System.out.println(selector.getContextNames()); - assertEquals(2, selector.getCount()); - } - - @Test - public void defaultContext() { - MockInitialContext mic = MockInitialContextFactory.getContext(); - mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, null); - - ContextJNDISelector selector = (ContextJNDISelector)StaticLoggerBinder.getSingleton().getContextSelector(); - Context context = selector.getLoggerContext(); - - assertEquals("default", context.getName()); - } - -} +/** + * 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.classic.selector; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.LoggerFactory; +import org.slf4j.impl.StaticLoggerBinder; +import org.slf4j.impl.StaticLoggerBinderFriend; + +import ch.qos.logback.classic.ClassicConstants; +import ch.qos.logback.classic.util.MockInitialContext; +import ch.qos.logback.classic.util.MockInitialContextFactory; +import ch.qos.logback.core.Context; + +public class ContextJNDISelectorTest { + + static String INITIAL_CONTEXT_KEY = "java.naming.factory.initial"; + + @Before + public void setUp() throws Exception { + + System.setProperty(ClassicConstants.LOGBACK_CONTEXT_SELECTOR, "JNDI"); + StaticLoggerBinderFriend.reset(); + + MockInitialContextFactory.initialize(); + MockInitialContext mic = MockInitialContextFactory.getContext(); + mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, "toto"); + + //The property must be set after we setup the Mock + System.setProperty(INITIAL_CONTEXT_KEY, MockInitialContextFactory.class.getName()); + + //this call will create the context "toto" + LoggerFactory.getLogger(ContextDetachingSCLTest.class); + } + + @After + public void tearDown() throws Exception { + System.clearProperty(INITIAL_CONTEXT_KEY); + } + + @Test + public void testGetExistingContext() { + ContextSelector selector = StaticLoggerBinder.getSingleton().getContextSelector(); + Context context = selector.getLoggerContext(); + assertEquals("toto", context.getName()); + } + + @Test + public void testCreateContext() { + MockInitialContext mic = MockInitialContextFactory.getContext(); + mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, "tata"); + + LoggerFactory.getLogger(ContextDetachingSCLTest.class); + + ContextJNDISelector selector = (ContextJNDISelector)StaticLoggerBinder.getSingleton().getContextSelector(); + Context context = selector.getLoggerContext(); + assertEquals("tata", context.getName()); + System.out.println(selector.getContextNames()); + assertEquals(2, selector.getCount()); + } + + @Test + public void defaultContext() { + MockInitialContext mic = MockInitialContextFactory.getContext(); + mic.map.put(ClassicConstants.JNDI_CONTEXT_NAME, null); + + ContextJNDISelector selector = (ContextJNDISelector)StaticLoggerBinder.getSingleton().getContextSelector(); + Context context = selector.getLoggerContext(); + + assertEquals("default", context.getName()); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/selector/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/selector/PackageTest.java index 285505fcfa1e9c640ea8a0ae7d7581209313a262..d2de4f1b49d656548c334ed91c54b83ea4c09847 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/selector/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/selector/PackageTest.java @@ -1,23 +1,23 @@ -/** - * 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.classic.selector; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({ContextJNDISelectorTest.class, ContextDetachingSCLTest.class}) -public class PackageTest { +/** + * 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.classic.selector; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ContextJNDISelectorTest.class, ContextDetachingSCLTest.class}) +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/sift/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/sift/PackageTest.java index 4c837e4e59c3b32e92be22302635d6cdf72564d7..3637912dccfdb0e1e5f37b74317a579115c81bc2 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/sift/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/sift/PackageTest.java @@ -1,23 +1,23 @@ -/** - * 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.classic.sift; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({SiftingAppenderTest.class}) -public class PackageTest { +/** + * 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.classic.sift; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({SiftingAppenderTest.class}) +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java index a5bf0776f1c366856c5112e10fdaebf778073d74..80333cd6a213562326c4e524e070d68957ef0ada 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java @@ -1,118 +1,118 @@ -/** - * 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.classic.sift; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; - -import java.util.List; - -import org.junit.Test; -import org.slf4j.MDC; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.classic.util.TeztConstants; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.read.ListAppender; -import ch.qos.logback.core.sift.AppenderTracker; -import ch.qos.logback.core.testUtil.StringListAppender; -import ch.qos.logback.core.util.StatusPrinter; - -public class SiftingAppenderTest { - - static String PREFIX = TeztConstants.TEST_DIR_PREFIX + "input/joran/sift/"; - - LoggerContext loggerContext = new LoggerContext(); - Logger logger = loggerContext.getLogger(this.getClass().getName()); - Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME); - - void configure(String file) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(loggerContext); - jc.doConfigure(file); - } - - @Test - public void unsetDefaultValueProperty() throws JoranException { - configure(PREFIX + "unsetDefaultValueProperty.xml"); - logger.debug("hello"); - SiftingAppender sa = (SiftingAppender) root.getAppender("SIFT"); - assertFalse(sa.isStarted()); - } - - @Test - public void smoke() throws JoranException { - configure(PREFIX + "smoke.xml"); - logger.debug("smoke"); - long timestamp = 0; - SiftingAppender ha = (SiftingAppender) root.getAppender("SIFT"); - ListAppender listAppender = (ListAppender) ha - .getAppenderTracker().get("smoke", timestamp); - - StatusPrinter.print(loggerContext); - assertNotNull(listAppender); - List eventList = listAppender.list; - assertEquals(1, listAppender.list.size()); - assertEquals("smoke", eventList.get(0).getMessage()); - } - - @Test - public void defaultLayoutRule() throws JoranException { - configure(PREFIX + "defaultLayoutRule.xml"); - logger.debug("hello"); - long timestamp = 0; - SiftingAppender ha = (SiftingAppender) root.getAppender("SIFT"); - StringListAppender listAppender = (StringListAppender) ha - .getAppenderTracker().get("default", timestamp); - - StatusPrinter.print(loggerContext); - assertNotNull(listAppender); - List strList = listAppender.strList; - assertEquals(1, strList.size()); - assertEquals("DEBUG hello", strList.get(0)); - } - - @Test - public void testWholeCycle() throws JoranException { - String mdcKey = "cycle"; - configure(PREFIX + "completeCycle.xml"); - MDC.put(mdcKey, "a"); - logger.debug("smoke"); - long timestamp = System.currentTimeMillis(); - SiftingAppender ha = (SiftingAppender) root.getAppender("SIFT"); - ListAppender listAppender = (ListAppender) ha - .getAppenderTracker().get("a", timestamp); - StatusPrinter.print(loggerContext); - - assertNotNull(listAppender); - List eventList = listAppender.list; - assertEquals(1, listAppender.list.size()); - assertEquals("smoke", eventList.get(0).getMessage()); - - MDC.remove(mdcKey); - LoggingEvent le = new LoggingEvent("x", logger, Level.INFO, "hello", null, - null); - le.setTimeStamp(timestamp + AppenderTracker.THRESHOLD * 2); - ha.doAppend(le); - assertFalse(listAppender.isStarted()); - assertEquals(1, ha.getAppenderTracker().keyList().size()); - assertEquals("cycleDefault", ha.getAppenderTracker().keyList().get(0)); - } -} +/** + * 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.classic.sift; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +import java.util.List; + +import org.junit.Test; +import org.slf4j.MDC; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.classic.util.TeztConstants; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.read.ListAppender; +import ch.qos.logback.core.sift.AppenderTracker; +import ch.qos.logback.core.testUtil.StringListAppender; +import ch.qos.logback.core.util.StatusPrinter; + +public class SiftingAppenderTest { + + static String PREFIX = TeztConstants.TEST_DIR_PREFIX + "input/joran/sift/"; + + LoggerContext loggerContext = new LoggerContext(); + Logger logger = loggerContext.getLogger(this.getClass().getName()); + Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME); + + void configure(String file) throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(loggerContext); + jc.doConfigure(file); + } + + @Test + public void unsetDefaultValueProperty() throws JoranException { + configure(PREFIX + "unsetDefaultValueProperty.xml"); + logger.debug("hello"); + SiftingAppender sa = (SiftingAppender) root.getAppender("SIFT"); + assertFalse(sa.isStarted()); + } + + @Test + public void smoke() throws JoranException { + configure(PREFIX + "smoke.xml"); + logger.debug("smoke"); + long timestamp = 0; + SiftingAppender ha = (SiftingAppender) root.getAppender("SIFT"); + ListAppender listAppender = (ListAppender) ha + .getAppenderTracker().get("smoke", timestamp); + + StatusPrinter.print(loggerContext); + assertNotNull(listAppender); + List eventList = listAppender.list; + assertEquals(1, listAppender.list.size()); + assertEquals("smoke", eventList.get(0).getMessage()); + } + + @Test + public void defaultLayoutRule() throws JoranException { + configure(PREFIX + "defaultLayoutRule.xml"); + logger.debug("hello"); + long timestamp = 0; + SiftingAppender ha = (SiftingAppender) root.getAppender("SIFT"); + StringListAppender listAppender = (StringListAppender) ha + .getAppenderTracker().get("default", timestamp); + + StatusPrinter.print(loggerContext); + assertNotNull(listAppender); + List strList = listAppender.strList; + assertEquals(1, strList.size()); + assertEquals("DEBUG hello", strList.get(0)); + } + + @Test + public void testWholeCycle() throws JoranException { + String mdcKey = "cycle"; + configure(PREFIX + "completeCycle.xml"); + MDC.put(mdcKey, "a"); + logger.debug("smoke"); + long timestamp = System.currentTimeMillis(); + SiftingAppender ha = (SiftingAppender) root.getAppender("SIFT"); + ListAppender listAppender = (ListAppender) ha + .getAppenderTracker().get("a", timestamp); + StatusPrinter.print(loggerContext); + + assertNotNull(listAppender); + List eventList = listAppender.list; + assertEquals(1, listAppender.list.size()); + assertEquals("smoke", eventList.get(0).getMessage()); + + MDC.remove(mdcKey); + LoggingEvent le = new LoggingEvent("x", logger, Level.INFO, "hello", null, + null); + le.setTimeStamp(timestamp + AppenderTracker.THRESHOLD * 2); + ha.doAppend(le); + assertFalse(listAppender.isStarted()); + assertEquals(1, ha.getAppenderTracker().keyList().size()); + assertEquals("cycleDefault", ha.getAppenderTracker().keyList().get(0)); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/BasicContextListener.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/BasicContextListener.java index 8b03d8123bdfdb89a00fb24d915f0d7ded719e7e..4e32c1edfdf8677ce91ac6fbe21918729a67a50d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/BasicContextListener.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/BasicContextListener.java @@ -1,49 +1,49 @@ -/** - * 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.classic.spi; - -import ch.qos.logback.classic.LoggerContext; - -public class BasicContextListener implements LoggerContextListener { - - enum UpdateType { NONE, START, RESET, STOP}; - - UpdateType updateType = UpdateType.NONE; - LoggerContext context; - - boolean resetResistant; - - public void setResetResistant(boolean resetResistant) { - this.resetResistant = resetResistant; - } - - public void onReset(LoggerContext context) { - updateType = UpdateType.RESET; - this.context = context; - - } - public void onStart(LoggerContext context) { - updateType = UpdateType.START;; - this.context = context; - } - - public void onStop(LoggerContext context) { - updateType = UpdateType.STOP;; - this.context = context; - } - - public boolean isResetResistant() { - return resetResistant; - } -} +/** + * 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.classic.spi; + +import ch.qos.logback.classic.LoggerContext; + +public class BasicContextListener implements LoggerContextListener { + + enum UpdateType { NONE, START, RESET, STOP}; + + UpdateType updateType = UpdateType.NONE; + LoggerContext context; + + boolean resetResistant; + + public void setResetResistant(boolean resetResistant) { + this.resetResistant = resetResistant; + } + + public void onReset(LoggerContext context) { + updateType = UpdateType.RESET; + this.context = context; + + } + public void onStart(LoggerContext context) { + updateType = UpdateType.START;; + this.context = context; + } + + public void onStop(LoggerContext context) { + updateType = UpdateType.STOP;; + this.context = context; + } + + public boolean isResetResistant() { + return resetResistant; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/BogusClassLoader.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/BogusClassLoader.java index e85560167afa9cd5db70df4598d91dbfa900c255..361a80b11a71ac206642cc5993f42422b9e8b3ad 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/BogusClassLoader.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/BogusClassLoader.java @@ -1,52 +1,52 @@ -/** - * 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.classic.spi; - -import java.net.URL; -import java.net.URLClassLoader; - -/** - * A trivial class loader which throws a NoClassDefFoundError if the requested - * class name contains the string "Bogus". - * - * @author Ceki Gülcü - */ -public class BogusClassLoader extends URLClassLoader { - - public BogusClassLoader(URL[] urls) { - super(urls); - } - - public BogusClassLoader(URL[] urls, ClassLoader parent) { - super(urls, parent); - } - - public Class loadClass(String name) throws ClassNotFoundException { - return loadClass(name, false); - } - - /** - * Throw NoClassDefFoundError if the requested class contains the string - * "Bogus". Otherwise, delegate to super-class. - */ - protected Class loadClass(String name, boolean resolve) - throws ClassNotFoundException { - - if (name.contains("Bogus")) { - throw new NoClassDefFoundError(); - } - - return super.loadClass(name, resolve); - } -} +/** + * 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.classic.spi; + +import java.net.URL; +import java.net.URLClassLoader; + +/** + * A trivial class loader which throws a NoClassDefFoundError if the requested + * class name contains the string "Bogus". + * + * @author Ceki Gülcü + */ +public class BogusClassLoader extends URLClassLoader { + + public BogusClassLoader(URL[] urls) { + super(urls); + } + + public BogusClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + } + + public Class loadClass(String name) throws ClassNotFoundException { + return loadClass(name, false); + } + + /** + * Throw NoClassDefFoundError if the requested class contains the string + * "Bogus". Otherwise, delegate to super-class. + */ + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + + if (name.contains("Bogus")) { + throw new NoClassDefFoundError(); + } + + return super.loadClass(name, resolve); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/CPDCSpecial.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/CPDCSpecial.java index f0200f0f0a9deebdeed277a8200ee9990623afd0..a3402d40a105a3da241ee99470a7c57ddc185c13 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/CPDCSpecial.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/CPDCSpecial.java @@ -1,24 +1,24 @@ -/** - * 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.classic.spi; - -public interface CPDCSpecial { - - public abstract void doTest(); - - public abstract Throwable getThrowable(); - - public abstract IThrowableProxy getThrowableProxy(); - +/** + * 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.classic.spi; + +public interface CPDCSpecial { + + public abstract void doTest(); + + public abstract Throwable getThrowable(); + + public abstract IThrowableProxy getThrowableProxy(); + } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/CallerDataTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/CallerDataTest.java index 96299c2d66ec67ddcbf2933e1982cfbf26e9452a..14fa5ecbb276870a14cc795d857001f5feb7982a 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/CallerDataTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/CallerDataTest.java @@ -1,48 +1,48 @@ -/** - * 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.classic.spi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class CallerDataTest { - - - @Test - public void testBasic() { - Throwable t = new Throwable(); - StackTraceElement[] steArray = t.getStackTrace(); - - StackTraceElement[] cda = CallerData.extract(t, CallerDataTest.class.getName(), 50); - assertNotNull(cda); - assertTrue(cda.length > 0); - assertEquals(steArray.length - 1, cda.length); - } - - /** - * This test verifies that in case caller data cannot be - * extracted, CallerData.extract does not throw an exception - * - */ - @Test - public void testDeferredProcessing() { - StackTraceElement[] cda = CallerData.extract(new Throwable(), "com.inexistent.foo", 10); - assertNotNull(cda); - assertEquals(0, cda.length); - } - -} +/** + * 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.classic.spi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class CallerDataTest { + + + @Test + public void testBasic() { + Throwable t = new Throwable(); + StackTraceElement[] steArray = t.getStackTrace(); + + StackTraceElement[] cda = CallerData.extract(t, CallerDataTest.class.getName(), 50); + assertNotNull(cda); + assertTrue(cda.length > 0); + assertEquals(steArray.length - 1, cda.length); + } + + /** + * This test verifies that in case caller data cannot be + * extracted, CallerData.extract does not throw an exception + * + */ + @Test + public void testDeferredProcessing() { + StackTraceElement[] cda = CallerData.extract(new Throwable(), "com.inexistent.foo", 10); + assertNotNull(cda); + assertEquals(0, cda.length); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/ContextListenerTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/ContextListenerTest.java index c985487052af4089b3b0723cd1868ac7890cfa9b..95c31865d5e8d86972cb4ae2cc009911ee774e15 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/ContextListenerTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/ContextListenerTest.java @@ -1,64 +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.classic.spi; - -import static org.junit.Assert.assertEquals; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.BasicContextListener.UpdateType; - -public class ContextListenerTest { - - LoggerContext context; - BasicContextListener listener; - - @Before - public void setUp() throws Exception { - context = new LoggerContext(); - listener = new BasicContextListener(); - context.addListener(listener); - } - - @Test - public void testNotifyOnReset() { - context.reset(); - assertEquals(UpdateType.RESET, listener.updateType); - assertEquals(listener.context, context); - } - - @Test - public void testNotifyOnStopResistant() { - listener.setResetResistant(true); - context.stop(); - assertEquals(UpdateType.STOP, listener.updateType); - assertEquals(listener.context, context); - } - - @Test - public void testNotifyOnStopNotResistant() { - context.stop(); - assertEquals(UpdateType.RESET, listener.updateType); - assertEquals(listener.context, context); - } - - @Test - public void testNotifyOnStart() { - context.start(); - assertEquals(UpdateType.START, listener.updateType); - assertEquals(listener.context, context); - } -} +/** + * 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.classic.spi; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.BasicContextListener.UpdateType; + +public class ContextListenerTest { + + LoggerContext context; + BasicContextListener listener; + + @Before + public void setUp() throws Exception { + context = new LoggerContext(); + listener = new BasicContextListener(); + context.addListener(listener); + } + + @Test + public void testNotifyOnReset() { + context.reset(); + assertEquals(UpdateType.RESET, listener.updateType); + assertEquals(listener.context, context); + } + + @Test + public void testNotifyOnStopResistant() { + listener.setResetResistant(true); + context.stop(); + assertEquals(UpdateType.STOP, listener.updateType); + assertEquals(listener.context, context); + } + + @Test + public void testNotifyOnStopNotResistant() { + context.stop(); + assertEquals(UpdateType.RESET, listener.updateType); + assertEquals(listener.context, context); + } + + @Test + public void testNotifyOnStart() { + context.start(); + assertEquals(UpdateType.START, listener.updateType); + assertEquals(listener.context, context); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/DummyThrowableProxy.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/DummyThrowableProxy.java index 4a0a90ccf2f1a9427741de35ce6723268743bebf..a59b9898523aea0d439546bc4b341eaf42a0598c 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/DummyThrowableProxy.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/DummyThrowableProxy.java @@ -1,61 +1,61 @@ -/** - * 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.classic.spi; - -public class DummyThrowableProxy implements IThrowableProxy { - - private String className; - private String message; - private int commonFramesCount; - private StackTraceElementProxy[] stackTraceElementProxyArray; - private IThrowableProxy cause; - - - public String getClassName() { - return className; - } - public void setClassName(String className) { - this.className = className; - } - public String getMessage() { - return message; - } - public void setMessage(String message) { - this.message = message; - } - public int getCommonFrames() { - return commonFramesCount; - } - public void setCommonFramesCount(int commonFramesCount) { - this.commonFramesCount = commonFramesCount; - } - - public StackTraceElementProxy[] getStackTraceElementProxyArray() { - return stackTraceElementProxyArray; - } - public void setStackTraceElementProxyArray( - StackTraceElementProxy[] stackTraceElementProxyArray) { - this.stackTraceElementProxyArray = stackTraceElementProxyArray; - } - public IThrowableProxy getCause() { - return cause; - } - public void setCause(IThrowableProxy cause) { - this.cause = cause; - } - - - - -} +/** + * 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.classic.spi; + +public class DummyThrowableProxy implements IThrowableProxy { + + private String className; + private String message; + private int commonFramesCount; + private StackTraceElementProxy[] stackTraceElementProxyArray; + private IThrowableProxy cause; + + + public String getClassName() { + return className; + } + public void setClassName(String className) { + this.className = className; + } + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + public int getCommonFrames() { + return commonFramesCount; + } + public void setCommonFramesCount(int commonFramesCount) { + this.commonFramesCount = commonFramesCount; + } + + public StackTraceElementProxy[] getStackTraceElementProxyArray() { + return stackTraceElementProxyArray; + } + public void setStackTraceElementProxyArray( + StackTraceElementProxy[] stackTraceElementProxyArray) { + this.stackTraceElementProxyArray = stackTraceElementProxyArray; + } + public IThrowableProxy getCause() { + return cause; + } + public void setCause(IThrowableProxy cause) { + this.cause = cause; + } + + + + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LocalFirstClassLoader.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LocalFirstClassLoader.java index 5704ed6794c5df6547790f3e3d5de7f0837be17f..9a06d42085633e4c2a1aa50e36d4c3c82250e236 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LocalFirstClassLoader.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LocalFirstClassLoader.java @@ -1,79 +1,79 @@ -/** - * 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.classic.spi; - -import java.net.URL; -import java.net.URLClassLoader; - -/** - * An almost trivial no fuss implementation of a class loader following the - * child-first delegation model. - * - * @author Ceki Gülcü - */ -public class LocalFirstClassLoader extends URLClassLoader { - - public LocalFirstClassLoader(URL[] urls) { - super(urls); - } - - public LocalFirstClassLoader(URL[] urls, ClassLoader parent) { - super(urls, parent); - } - - public void addURL(URL url) { - super.addURL(url); - } - - public Class loadClass(String name) throws ClassNotFoundException { - return loadClass(name, false); - } - - /** - * We override the parent-first behavior established by java.lang.Classloader. - * - * The implementation is surprisingly straightforward. - */ - protected Class loadClass(String name, boolean resolve) - throws ClassNotFoundException { - - // First, check if the class has already been loaded - Class c = findLoadedClass(name); - - // if not loaded, search the local (child) resources - if (c == null) { - try { - c = findClass(name); - } catch (ClassNotFoundException cnfe) { - // ignore - } - } - - // if we could not find it, delegate to parent - // Note that we don't attempt to catch any ClassNotFoundException - if (c == null) { - if (getParent() != null) { - c = getParent().loadClass(name); - } else { - c = getSystemClassLoader().loadClass(name); - } - } - - if (resolve) { - resolveClass(c); - } - - return c; - } -} +/** + * 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.classic.spi; + +import java.net.URL; +import java.net.URLClassLoader; + +/** + * An almost trivial no fuss implementation of a class loader following the + * child-first delegation model. + * + * @author Ceki Gülcü + */ +public class LocalFirstClassLoader extends URLClassLoader { + + public LocalFirstClassLoader(URL[] urls) { + super(urls); + } + + public LocalFirstClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + } + + public void addURL(URL url) { + super.addURL(url); + } + + public Class loadClass(String name) throws ClassNotFoundException { + return loadClass(name, false); + } + + /** + * We override the parent-first behavior established by java.lang.Classloader. + * + * The implementation is surprisingly straightforward. + */ + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + + // First, check if the class has already been loaded + Class c = findLoadedClass(name); + + // if not loaded, search the local (child) resources + if (c == null) { + try { + c = findClass(name); + } catch (ClassNotFoundException cnfe) { + // ignore + } + } + + // if we could not find it, delegate to parent + // Note that we don't attempt to catch any ClassNotFoundException + if (c == null) { + if (getParent() != null) { + c = getParent().loadClass(name); + } else { + c = getSystemClassLoader().loadClass(name); + } + } + + if (resolve) { + resolveClass(c); + } + + return c; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggerComparatorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggerComparatorTest.java index e978f31e4211c3e85f091ecf5953473c287930bb..ce0e31328fe66f6e80b461ef4d987ebb5c452f4c 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggerComparatorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggerComparatorTest.java @@ -1,51 +1,51 @@ -/** - * 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.classic.spi; - -import org.junit.Before; -import org.junit.Test; -import static org.junit.Assert.*; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; - - -public class LoggerComparatorTest { - - LoggerComparator comparator = new LoggerComparator(); - LoggerContext lc = new LoggerContext(); - - Logger root = lc.getLogger("root"); - - Logger a = lc.getLogger("a"); - Logger b = lc.getLogger("b"); - - @Before - public void setUp() throws Exception { - - } - - - - @Test - public void testSmoke() { - assertEquals(0, comparator.compare(a, a)); - assertEquals(-1, comparator.compare(a, b)); - assertEquals(1, comparator.compare(b, a)); - assertEquals(-1, comparator.compare(root, a)); - // following two tests failed before bug #127 was fixed - assertEquals(1, comparator.compare(a, root)); - assertEquals(0, comparator.compare(root, root)); - } -} +/** + * 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.classic.spi; + +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; + + +public class LoggerComparatorTest { + + LoggerComparator comparator = new LoggerComparator(); + LoggerContext lc = new LoggerContext(); + + Logger root = lc.getLogger("root"); + + Logger a = lc.getLogger("a"); + Logger b = lc.getLogger("b"); + + @Before + public void setUp() throws Exception { + + } + + + + @Test + public void testSmoke() { + assertEquals(0, comparator.compare(a, a)); + assertEquals(-1, comparator.compare(a, b)); + assertEquals(1, comparator.compare(b, a)); + assertEquals(-1, comparator.compare(root, a)); + // following two tests failed before bug #127 was fixed + assertEquals(1, comparator.compare(a, root)); + assertEquals(0, comparator.compare(root, root)); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationPerfTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationPerfTest.java index fe25a2fde9ed7ba81bb690ad6fb58792fa24554b..465dec6a9808a69565dac8c5c16e8aa7e21bda46 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationPerfTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationPerfTest.java @@ -1,139 +1,139 @@ -/** - * 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.classic.spi; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.IOException; -import java.io.ObjectOutputStream; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.helpers.BogoPerf; - -import ch.qos.logback.classic.net.NOPOutputStream; -import ch.qos.logback.classic.net.testObjectBuilders.Builder; -import ch.qos.logback.classic.net.testObjectBuilders.LoggingEventWithParametersBuilder; -import ch.qos.logback.classic.net.testObjectBuilders.TrivialLoggingEventBuilder; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.testUtil.Env; - -// As of logback 0.9.15, -// average time per logging event: 3979 nanoseconds -// size 545'648 bytes -// -// Using LoggingEventDO -// -// average time per logging event: 4052 nanoseconds -// average size=45, with params, average size=136 -// -// Using LoggerEventVO, with loggerName, and loggerContextRemoteView -// average time per logging event: 4034 -// average size 57, with params, average size=148 - -public class LoggingEventSerializationPerfTest { - - static int LOOP_LEN = 10 * 1000; - - NOPOutputStream noos = new NOPOutputStream(); - ObjectOutputStream oos; - - @Before - public void setUp() throws Exception { - oos = new ObjectOutputStream(noos); - } - - @After - public void tearDown() throws Exception { - } - - double doLoop(Builder builder, int loopLen) { - long start = System.nanoTime(); - int resetCounter = 0; - for (int i = 0; i < loopLen; i++) { - try { - ILoggingEvent le = (ILoggingEvent) builder.build(i); - oos.writeObject(LoggingEventVO.build(le)); - - oos.flush(); - if (++resetCounter >= CoreConstants.OOS_RESET_FREQUENCY) { - oos.reset(); - resetCounter = 0; - } - - } catch (IOException ex) { - fail(ex.getMessage()); - } - } - long end = System.nanoTime(); - return (end - start) / (1.0d * loopLen); - } - - @Test - public void testPerformance() { - if (Env.isLinux()) { - return; - } - TrivialLoggingEventBuilder builder = new TrivialLoggingEventBuilder(); - - for (int i = 0; i < 3; i++) { - doLoop(builder, LOOP_LEN); - noos.reset(); - } - double rt = doLoop(builder, LOOP_LEN); - System.out - .println("avetage time per logging event " + rt + " nanoseconds"); - - long averageSize = (long) (noos.size() / (LOOP_LEN)); - System.out.println("noos size " + noos.size() + " average size=" - + averageSize); - double averageSizeLimit = 60; - - assertTrue("average size " + averageSize + " should be less than " - + averageSizeLimit, averageSizeLimit > averageSize); - - // the reference was computed on Orion (Ceki's computer) - long referencePerf = 5000; - BogoPerf.assertDuration(rt, referencePerf, CoreConstants.REFERENCE_BIPS); - } - - @Test - public void testPerformanceWithParameters() { - if (Env.isLinux()) { - return; - } - LoggingEventWithParametersBuilder builder = new LoggingEventWithParametersBuilder(); - - // warm up - for (int i = 0; i < 3; i++) { - doLoop(builder, LOOP_LEN); - noos.reset(); - } - double rt = doLoop(builder, LOOP_LEN); - long averageSize = (long) (noos.size() / (LOOP_LEN)); - - System.out.println("noos size " + noos.size() + " average size=" - + averageSize); - - double averageSizeLimit = 160; - assertTrue("averageSize " + averageSize + " should be less than " - + averageSizeLimit, averageSizeLimit > averageSize); - - // the reference was computed on Orion (Ceki's computer) - long referencePerf = 7000; - BogoPerf.assertDuration(rt, referencePerf, CoreConstants.REFERENCE_BIPS); - } -} +/** + * 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.classic.spi; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.io.ObjectOutputStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.helpers.BogoPerf; + +import ch.qos.logback.classic.net.NOPOutputStream; +import ch.qos.logback.classic.net.testObjectBuilders.Builder; +import ch.qos.logback.classic.net.testObjectBuilders.LoggingEventWithParametersBuilder; +import ch.qos.logback.classic.net.testObjectBuilders.TrivialLoggingEventBuilder; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.testUtil.Env; + +// As of logback 0.9.15, +// average time per logging event: 3979 nanoseconds +// size 545'648 bytes +// +// Using LoggingEventDO +// +// average time per logging event: 4052 nanoseconds +// average size=45, with params, average size=136 +// +// Using LoggerEventVO, with loggerName, and loggerContextRemoteView +// average time per logging event: 4034 +// average size 57, with params, average size=148 + +public class LoggingEventSerializationPerfTest { + + static int LOOP_LEN = 10 * 1000; + + NOPOutputStream noos = new NOPOutputStream(); + ObjectOutputStream oos; + + @Before + public void setUp() throws Exception { + oos = new ObjectOutputStream(noos); + } + + @After + public void tearDown() throws Exception { + } + + double doLoop(Builder builder, int loopLen) { + long start = System.nanoTime(); + int resetCounter = 0; + for (int i = 0; i < loopLen; i++) { + try { + ILoggingEvent le = (ILoggingEvent) builder.build(i); + oos.writeObject(LoggingEventVO.build(le)); + + oos.flush(); + if (++resetCounter >= CoreConstants.OOS_RESET_FREQUENCY) { + oos.reset(); + resetCounter = 0; + } + + } catch (IOException ex) { + fail(ex.getMessage()); + } + } + long end = System.nanoTime(); + return (end - start) / (1.0d * loopLen); + } + + @Test + public void testPerformance() { + if (Env.isLinux()) { + return; + } + TrivialLoggingEventBuilder builder = new TrivialLoggingEventBuilder(); + + for (int i = 0; i < 3; i++) { + doLoop(builder, LOOP_LEN); + noos.reset(); + } + double rt = doLoop(builder, LOOP_LEN); + System.out + .println("avetage time per logging event " + rt + " nanoseconds"); + + long averageSize = (long) (noos.size() / (LOOP_LEN)); + System.out.println("noos size " + noos.size() + " average size=" + + averageSize); + double averageSizeLimit = 60; + + assertTrue("average size " + averageSize + " should be less than " + + averageSizeLimit, averageSizeLimit > averageSize); + + // the reference was computed on Orion (Ceki's computer) + long referencePerf = 5000; + BogoPerf.assertDuration(rt, referencePerf, CoreConstants.REFERENCE_BIPS); + } + + @Test + public void testPerformanceWithParameters() { + if (Env.isLinux()) { + return; + } + LoggingEventWithParametersBuilder builder = new LoggingEventWithParametersBuilder(); + + // warm up + for (int i = 0; i < 3; i++) { + doLoop(builder, LOOP_LEN); + noos.reset(); + } + double rt = doLoop(builder, LOOP_LEN); + long averageSize = (long) (noos.size() / (LOOP_LEN)); + + System.out.println("noos size " + noos.size() + " average size=" + + averageSize); + + double averageSizeLimit = 160; + assertTrue("averageSize " + averageSize + " should be less than " + + averageSizeLimit, averageSizeLimit > averageSize); + + // the reference was computed on Orion (Ceki's computer) + long referencePerf = 7000; + BogoPerf.assertDuration(rt, referencePerf, CoreConstants.REFERENCE_BIPS); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationTest.java index ccc6265bc639b4c4d9a7698f0c2c4db18d162234..1caccf863e9fb49631e2cb0dd884025c9516f1e4 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationTest.java @@ -1,217 +1,217 @@ -/** - * 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.classic.spi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.Map; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.MDC; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.net.LoggingEventPreSerializationTransformer; -import ch.qos.logback.core.spi.PreSerializationTransformer; - -public class LoggingEventSerializationTest { - - LoggerContext lc; - Logger logger; - - ByteArrayOutputStream bos; - ObjectOutputStream oos; - ObjectInputStream inputStream; - PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); - - @Before - public void setUp() throws Exception { - lc = new LoggerContext(); - lc.setName("testContext"); - logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - // create the byte output stream - bos = new ByteArrayOutputStream(); - oos = new ObjectOutputStream(bos); - } - - @After - public void tearDown() throws Exception { - lc = null; - logger = null; - oos.close(); - } - - @Test - public void smoke() throws Exception { - ILoggingEvent event = createLoggingEvent(); - ILoggingEvent remoteEvent = writeAndRead(event); - checkForEquality(event, remoteEvent); - } - - @Test - public void context() throws Exception { - lc.putProperty("testKey", "testValue"); - ILoggingEvent event = createLoggingEvent(); - ILoggingEvent remoteEvent = writeAndRead(event); - checkForEquality(event, remoteEvent); - - assertNotNull(remoteEvent.getLoggerName()); - assertEquals(Logger.ROOT_LOGGER_NAME, remoteEvent.getLoggerName()); - - LoggerContextVO loggerContextRemoteView = remoteEvent.getLoggerContextVO(); - assertNotNull(loggerContextRemoteView); - assertEquals("testContext", loggerContextRemoteView.getName()); - Map props = loggerContextRemoteView.getPropertyMap(); - assertNotNull(props); - assertEquals("testValue", props.get("testKey")); - } - - @Test - public void MDC() throws Exception { - MDC.put("key", "testValue"); - ILoggingEvent event = createLoggingEvent(); - ILoggingEvent remoteEvent = writeAndRead(event); - checkForEquality(event, remoteEvent); - Map MDCPropertyMap = remoteEvent.getMDCPropertyMap(); - assertEquals("testValue", MDCPropertyMap.get("key")); - } - - @Test - public void updatedMDC() throws Exception { - MDC.put("key", "testValue"); - ILoggingEvent event1 = createLoggingEvent(); - Serializable s1 = pst.transform(event1); - oos.writeObject(s1); - - MDC.put("key", "updatedTestValue"); - ILoggingEvent event2 = createLoggingEvent(); - Serializable s2 = pst.transform(event2); - oos.writeObject(s2); - - // create the input stream based on the ouput stream - ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); - inputStream = new ObjectInputStream(bis); - - // skip over one object - inputStream.readObject(); - ILoggingEvent remoteEvent2 = (ILoggingEvent) inputStream.readObject(); - - // We observe the second logging event. It should provide us with - // the updated MDC property. - Map MDCPropertyMap = remoteEvent2.getMDCPropertyMap(); - assertEquals("updatedTestValue", MDCPropertyMap.get("key")); - } - - @Test - public void nonSerializableParameters() throws Exception { - LoggingEvent event = createLoggingEvent(); - LuckyCharms lucky0 = new LuckyCharms(0); - event.setArgumentArray(new Object[] { lucky0, null }); - ILoggingEvent remoteEvent = writeAndRead(event); - checkForEquality(event, remoteEvent); - - Object[] aa = remoteEvent.getArgumentArray(); - assertNotNull(aa); - assertEquals(2, aa.length); - assertEquals("LC(0)", aa[0]); - assertNull(aa[1]); - } - - @Test - public void _Throwable() throws Exception { - LoggingEvent event = createLoggingEvent(); - Throwable throwable = new Throwable("just testing"); - ThrowableProxy tp = new ThrowableProxy(throwable); - event.setThrowableProxy(tp); - ILoggingEvent remoteEvent = writeAndRead(event); - checkForEquality(event, remoteEvent); - } - - @Test - public void extendendeThrowable() throws Exception { - LoggingEvent event = createLoggingEvent(); - Throwable throwable = new Throwable("just testing"); - ThrowableProxy tp = new ThrowableProxy(throwable); - event.setThrowableProxy(tp); - tp.calculatePackagingData(); - - ILoggingEvent remoteEvent = writeAndRead(event); - checkForEquality(event, remoteEvent); - } - - @Test - public void serializeLargeArgs() throws Exception { - - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < 100000; i++) { - buffer.append("X"); - } - String largeString = buffer.toString(); - Object[] argArray = new Object[] { new LuckyCharms(2), largeString }; - - LoggingEvent event = createLoggingEvent(); - event.setArgumentArray(argArray); - - ILoggingEvent remoteEvent = writeAndRead(event); - checkForEquality(event, remoteEvent); - Object[] aa = remoteEvent.getArgumentArray(); - assertNotNull(aa); - assertEquals(2, aa.length); - String stringBack = (String) aa[1]; - assertEquals(largeString, stringBack); - } - - private LoggingEvent createLoggingEvent() { - LoggingEvent le = new LoggingEvent(this.getClass().getName(), logger, - Level.DEBUG, "test message", null, null); - return le; - } - - private void checkForEquality(ILoggingEvent original, - ILoggingEvent afterSerialization) { - assertEquals(original.getLevel(), afterSerialization.getLevel()); - assertEquals(original.getFormattedMessage(), afterSerialization - .getFormattedMessage()); - assertEquals(original.getMessage(), afterSerialization.getMessage()); - - System.out.println(); - - ThrowableProxyVO witness = ThrowableProxyVO.build(original - .getThrowableProxy()); - assertEquals(witness, afterSerialization.getThrowableProxy()); - - } - - private ILoggingEvent writeAndRead(ILoggingEvent event) throws IOException, - ClassNotFoundException { - Serializable ser = pst.transform(event); - oos.writeObject(ser); - ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); - inputStream = new ObjectInputStream(bis); - - return (ILoggingEvent) inputStream.readObject(); - } - -} +/** + * 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.classic.spi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Map; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.MDC; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.net.LoggingEventPreSerializationTransformer; +import ch.qos.logback.core.spi.PreSerializationTransformer; + +public class LoggingEventSerializationTest { + + LoggerContext lc; + Logger logger; + + ByteArrayOutputStream bos; + ObjectOutputStream oos; + ObjectInputStream inputStream; + PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); + + @Before + public void setUp() throws Exception { + lc = new LoggerContext(); + lc.setName("testContext"); + logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + // create the byte output stream + bos = new ByteArrayOutputStream(); + oos = new ObjectOutputStream(bos); + } + + @After + public void tearDown() throws Exception { + lc = null; + logger = null; + oos.close(); + } + + @Test + public void smoke() throws Exception { + ILoggingEvent event = createLoggingEvent(); + ILoggingEvent remoteEvent = writeAndRead(event); + checkForEquality(event, remoteEvent); + } + + @Test + public void context() throws Exception { + lc.putProperty("testKey", "testValue"); + ILoggingEvent event = createLoggingEvent(); + ILoggingEvent remoteEvent = writeAndRead(event); + checkForEquality(event, remoteEvent); + + assertNotNull(remoteEvent.getLoggerName()); + assertEquals(Logger.ROOT_LOGGER_NAME, remoteEvent.getLoggerName()); + + LoggerContextVO loggerContextRemoteView = remoteEvent.getLoggerContextVO(); + assertNotNull(loggerContextRemoteView); + assertEquals("testContext", loggerContextRemoteView.getName()); + Map props = loggerContextRemoteView.getPropertyMap(); + assertNotNull(props); + assertEquals("testValue", props.get("testKey")); + } + + @Test + public void MDC() throws Exception { + MDC.put("key", "testValue"); + ILoggingEvent event = createLoggingEvent(); + ILoggingEvent remoteEvent = writeAndRead(event); + checkForEquality(event, remoteEvent); + Map MDCPropertyMap = remoteEvent.getMDCPropertyMap(); + assertEquals("testValue", MDCPropertyMap.get("key")); + } + + @Test + public void updatedMDC() throws Exception { + MDC.put("key", "testValue"); + ILoggingEvent event1 = createLoggingEvent(); + Serializable s1 = pst.transform(event1); + oos.writeObject(s1); + + MDC.put("key", "updatedTestValue"); + ILoggingEvent event2 = createLoggingEvent(); + Serializable s2 = pst.transform(event2); + oos.writeObject(s2); + + // create the input stream based on the ouput stream + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + inputStream = new ObjectInputStream(bis); + + // skip over one object + inputStream.readObject(); + ILoggingEvent remoteEvent2 = (ILoggingEvent) inputStream.readObject(); + + // We observe the second logging event. It should provide us with + // the updated MDC property. + Map MDCPropertyMap = remoteEvent2.getMDCPropertyMap(); + assertEquals("updatedTestValue", MDCPropertyMap.get("key")); + } + + @Test + public void nonSerializableParameters() throws Exception { + LoggingEvent event = createLoggingEvent(); + LuckyCharms lucky0 = new LuckyCharms(0); + event.setArgumentArray(new Object[] { lucky0, null }); + ILoggingEvent remoteEvent = writeAndRead(event); + checkForEquality(event, remoteEvent); + + Object[] aa = remoteEvent.getArgumentArray(); + assertNotNull(aa); + assertEquals(2, aa.length); + assertEquals("LC(0)", aa[0]); + assertNull(aa[1]); + } + + @Test + public void _Throwable() throws Exception { + LoggingEvent event = createLoggingEvent(); + Throwable throwable = new Throwable("just testing"); + ThrowableProxy tp = new ThrowableProxy(throwable); + event.setThrowableProxy(tp); + ILoggingEvent remoteEvent = writeAndRead(event); + checkForEquality(event, remoteEvent); + } + + @Test + public void extendendeThrowable() throws Exception { + LoggingEvent event = createLoggingEvent(); + Throwable throwable = new Throwable("just testing"); + ThrowableProxy tp = new ThrowableProxy(throwable); + event.setThrowableProxy(tp); + tp.calculatePackagingData(); + + ILoggingEvent remoteEvent = writeAndRead(event); + checkForEquality(event, remoteEvent); + } + + @Test + public void serializeLargeArgs() throws Exception { + + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < 100000; i++) { + buffer.append("X"); + } + String largeString = buffer.toString(); + Object[] argArray = new Object[] { new LuckyCharms(2), largeString }; + + LoggingEvent event = createLoggingEvent(); + event.setArgumentArray(argArray); + + ILoggingEvent remoteEvent = writeAndRead(event); + checkForEquality(event, remoteEvent); + Object[] aa = remoteEvent.getArgumentArray(); + assertNotNull(aa); + assertEquals(2, aa.length); + String stringBack = (String) aa[1]; + assertEquals(largeString, stringBack); + } + + private LoggingEvent createLoggingEvent() { + LoggingEvent le = new LoggingEvent(this.getClass().getName(), logger, + Level.DEBUG, "test message", null, null); + return le; + } + + private void checkForEquality(ILoggingEvent original, + ILoggingEvent afterSerialization) { + assertEquals(original.getLevel(), afterSerialization.getLevel()); + assertEquals(original.getFormattedMessage(), afterSerialization + .getFormattedMessage()); + assertEquals(original.getMessage(), afterSerialization.getMessage()); + + System.out.println(); + + ThrowableProxyVO witness = ThrowableProxyVO.build(original + .getThrowableProxy()); + assertEquals(witness, afterSerialization.getThrowableProxy()); + + } + + private ILoggingEvent writeAndRead(ILoggingEvent event) throws IOException, + ClassNotFoundException { + Serializable ser = pst.transform(event); + oos.writeObject(ser); + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + inputStream = new ObjectInputStream(bis); + + return (ILoggingEvent) inputStream.readObject(); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LuckyCharms.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LuckyCharms.java index 6a6384dba9880a49503d27a940135b1f277d9e80..cd36438c034ba27813182d95204e461caf5b0b26 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LuckyCharms.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LuckyCharms.java @@ -1,28 +1,28 @@ -/** - * 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.classic.spi; - -// non serializable object -public class LuckyCharms { - int id; - - LuckyCharms(int id) { - this.id= id; - } - - @Override - public String toString() { - return "LC("+id+")"; - } -} +/** + * 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.classic.spi; + +// non serializable object +public class LuckyCharms { + int id; + + LuckyCharms(int id) { + this.id= id; + } + + @Override + public String toString() { + return "LC("+id+")"; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageTest.java index 39c19da9484aeb2e41aed7e499237edbed99a3d1..56dbd358cb768e2ca81252c2313b4ea35f203341 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageTest.java @@ -1,26 +1,26 @@ -/** - * 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.classic.spi; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses( { ContextListenerTest.class, CallerDataTest.class, - LoggerComparatorTest.class, LoggingEventSerializationTest.class, - LoggingEventSerializationPerfTest.class, ThrowableProxyTest.class, - PackagingDataCalculatorTest.class }) -public class PackageTest { +/** + * 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.classic.spi; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses( { ContextListenerTest.class, CallerDataTest.class, + LoggerComparatorTest.class, LoggingEventSerializationTest.class, + LoggingEventSerializationPerfTest.class, ThrowableProxyTest.class, + PackagingDataCalculatorTest.class }) +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackagingDataCalculatorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackagingDataCalculatorTest.java index d18c06d136b9436ee475839cc2500e298c8f8950..ee14d3f89873dcc6bb1e082bc351c76ab9a52466 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackagingDataCalculatorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackagingDataCalculatorTest.java @@ -1,127 +1,127 @@ -/** - * 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.classic.spi; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; - -import org.junit.Test; - -import ch.qos.logback.classic.util.TeztHelper; -import ch.qos.logback.core.util.SystemInfo; - -public class PackagingDataCalculatorTest { - - public void verify(ThrowableProxy tp) { - for (StackTraceElementProxy step : tp.getStackTraceElementProxyArray()) { - if (step != null) { - assertNotNull(step.getClassPackagingData()); - } - } - } - - @Test - public void smoke() throws Exception { - Throwable t = new Throwable("x"); - ThrowableProxy tp = new ThrowableProxy(t); - PackagingDataCalculator pdc = tp.getPackagingDataCalculator(); - pdc.calculate(tp); - verify(tp); - tp.fullDump(); - } - - @Test - public void nested() throws Exception { - Throwable t = TeztHelper.makeNestedException(3); - ThrowableProxy tp = new ThrowableProxy(t); - PackagingDataCalculator pdc = tp.getPackagingDataCalculator(); - pdc.calculate(tp); - verify(tp); - } - - public void doCalculateClassPackagingData( - boolean withClassPackagingCalculation) { - try { - throw new Exception("testing"); - } catch (Throwable e) { - ThrowableProxy tp = new ThrowableProxy(e); - if (withClassPackagingCalculation) { - PackagingDataCalculator pdc = tp.getPackagingDataCalculator(); - pdc.calculate(tp); - } - } - } - - double loop(int len, boolean withClassPackagingCalculation) { - long start = System.nanoTime(); - for (int i = 0; i < len; i++) { - doCalculateClassPackagingData(withClassPackagingCalculation); - } - return (1.0 * System.nanoTime() - start) / len / 1000; - } - - @Test - public void perfTest() { - int len = 1000; - loop(len, false); - loop(len, true); - - double d0 = loop(len, false); - System.out.println("without packaging info " + d0 + " microseconds"); - - double d1 = loop(len, true); - System.out.println("with packaging info " + d1 + " microseconds"); - - int slackFactor = 8; - if (!SystemInfo.getJavaVendor().contains("Sun")) { - // be more lenient with other JDKs - slackFactor = 10; - } - assertTrue("computing class packaging data (" + d1 - + ") should have been less than " + slackFactor - + " times the time it takes to process an exception " - + (d0 * slackFactor), d0 * slackFactor > d1); - - } - - private ClassLoader makeBogusClassLoader() throws MalformedURLException { - ClassLoader currentClassLoader = this.getClass().getClassLoader(); - BogusClassLoader bcl = new BogusClassLoader(new URL[] {}, - currentClassLoader); - return bcl; - } - - @Test - // Test http://jira.qos.ch/browse/LBCLASSIC-125 - public void noClassDefFoundError_LBCLASSIC_125Test() - throws MalformedURLException { - ClassLoader cl = (URLClassLoader) makeBogusClassLoader(); - Thread.currentThread().setContextClassLoader(cl); - Throwable t = new Throwable("x"); - ThrowableProxy tp = new ThrowableProxy(t); - StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); - StackTraceElement bogusSTE = new StackTraceElement("com.Bogus", "myMethod", - "myFile", 12); - stepArray[0] = new StackTraceElementProxy(bogusSTE); - PackagingDataCalculator pdc = tp.getPackagingDataCalculator(); - // NoClassDefFoundError should be caught - pdc.calculate(tp); - - } - -} +/** + * 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.classic.spi; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import ch.qos.logback.classic.util.TeztHelper; +import ch.qos.logback.core.util.SystemInfo; + +public class PackagingDataCalculatorTest { + + public void verify(ThrowableProxy tp) { + for (StackTraceElementProxy step : tp.getStackTraceElementProxyArray()) { + if (step != null) { + assertNotNull(step.getClassPackagingData()); + } + } + } + + @Test + public void smoke() throws Exception { + Throwable t = new Throwable("x"); + ThrowableProxy tp = new ThrowableProxy(t); + PackagingDataCalculator pdc = tp.getPackagingDataCalculator(); + pdc.calculate(tp); + verify(tp); + tp.fullDump(); + } + + @Test + public void nested() throws Exception { + Throwable t = TeztHelper.makeNestedException(3); + ThrowableProxy tp = new ThrowableProxy(t); + PackagingDataCalculator pdc = tp.getPackagingDataCalculator(); + pdc.calculate(tp); + verify(tp); + } + + public void doCalculateClassPackagingData( + boolean withClassPackagingCalculation) { + try { + throw new Exception("testing"); + } catch (Throwable e) { + ThrowableProxy tp = new ThrowableProxy(e); + if (withClassPackagingCalculation) { + PackagingDataCalculator pdc = tp.getPackagingDataCalculator(); + pdc.calculate(tp); + } + } + } + + double loop(int len, boolean withClassPackagingCalculation) { + long start = System.nanoTime(); + for (int i = 0; i < len; i++) { + doCalculateClassPackagingData(withClassPackagingCalculation); + } + return (1.0 * System.nanoTime() - start) / len / 1000; + } + + @Test + public void perfTest() { + int len = 1000; + loop(len, false); + loop(len, true); + + double d0 = loop(len, false); + System.out.println("without packaging info " + d0 + " microseconds"); + + double d1 = loop(len, true); + System.out.println("with packaging info " + d1 + " microseconds"); + + int slackFactor = 8; + if (!SystemInfo.getJavaVendor().contains("Sun")) { + // be more lenient with other JDKs + slackFactor = 10; + } + assertTrue("computing class packaging data (" + d1 + + ") should have been less than " + slackFactor + + " times the time it takes to process an exception " + + (d0 * slackFactor), d0 * slackFactor > d1); + + } + + private ClassLoader makeBogusClassLoader() throws MalformedURLException { + ClassLoader currentClassLoader = this.getClass().getClassLoader(); + BogusClassLoader bcl = new BogusClassLoader(new URL[] {}, + currentClassLoader); + return bcl; + } + + @Test + // Test http://jira.qos.ch/browse/LBCLASSIC-125 + public void noClassDefFoundError_LBCLASSIC_125Test() + throws MalformedURLException { + ClassLoader cl = (URLClassLoader) makeBogusClassLoader(); + Thread.currentThread().setContextClassLoader(cl); + Throwable t = new Throwable("x"); + ThrowableProxy tp = new ThrowableProxy(t); + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + StackTraceElement bogusSTE = new StackTraceElement("com.Bogus", "myMethod", + "myFile", 12); + stepArray[0] = new StackTraceElementProxy(bogusSTE); + PackagingDataCalculator pdc = tp.getPackagingDataCalculator(); + // NoClassDefFoundError should be caught + pdc.calculate(tp); + + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/PubLoggingEventVO.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/PubLoggingEventVO.java index bf90382298fcb437e19c9a28cb72556724225f2c..9946aab00b38ac1b5bd3e0df1bbd8ba077eca3f1 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/PubLoggingEventVO.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/PubLoggingEventVO.java @@ -1,240 +1,240 @@ -/** - * 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.classic.spi; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.Map; - -import org.slf4j.Marker; -import org.slf4j.helpers.MessageFormatter; - -import ch.qos.logback.classic.Level; - -/** - * A read/write and serializable implementation of {@link ILoggingEvent}. - * - * @author Ceki Gülcü - - */ -public class PubLoggingEventVO implements ILoggingEvent, Serializable { - - - private static final long serialVersionUID = -3385765861078946218L; - - private static final int NULL_ARGUMENT_ARRAY = -1; - private static final String NULL_ARGUMENT_ARRAY_ELEMENT = "NULL_ARGUMENT_ARRAY_ELEMENT"; - - public String threadName; - public String loggerName; - public LoggerContextVO loggerContextVO; - - public transient Level level; - public String message; - - private transient String formattedMessage; - - public Object[] argumentArray; - - public IThrowableProxy throwableProxy; - public StackTraceElement[] callerDataArray; - public Marker marker; - public Map mdcPropertyMap; - public long timeStamp; - - - - public String getThreadName() { - return threadName; - } - - public LoggerContextVO getLoggerContextVO() { - return loggerContextVO; - } - - public String getLoggerName() { - return loggerName; - } - - public Level getLevel() { - return level; - } - - public String getMessage() { - return message; - } - - public String getFormattedMessage() { - if (formattedMessage != null) { - return formattedMessage; - } - - if (argumentArray != null) { - formattedMessage = MessageFormatter.arrayFormat(message, argumentArray); - } else { - formattedMessage = message; - } - - return formattedMessage; - } - - public Object[] getArgumentArray() { - return argumentArray; - } - - public IThrowableProxy getThrowableProxy() { - return throwableProxy; - } - - public StackTraceElement[] getCallerData() { - return callerDataArray; - } - - public boolean hasCallerData() { - return callerDataArray != null; - } - - public Marker getMarker() { - return marker; - } - - public long getTimeStamp() { - return timeStamp; - } - - - - public long getContextBirthTime() { - return loggerContextVO.getBirthTime(); - } - - public LoggerContextVO getContextLoggerRemoteView() { - return loggerContextVO; - } - - public Map getMDCPropertyMap() { - return mdcPropertyMap; - } - - public void prepareForDeferredProcessing() { - } - - private void writeObject(ObjectOutputStream out) throws IOException { - out.defaultWriteObject(); - out.writeInt(level.levelInt); - if (argumentArray != null) { - int len = argumentArray.length; - out.writeInt(len); - for (int i = 0; i < argumentArray.length; i++) { - if (argumentArray[i] != null) { - out.writeObject(argumentArray[i].toString()); - } else { - out.writeObject(NULL_ARGUMENT_ARRAY_ELEMENT); - } - } - } else { - out.writeInt(NULL_ARGUMENT_ARRAY); - } - - } - - private void readObject(ObjectInputStream in) throws IOException, - ClassNotFoundException { - in.defaultReadObject(); - int levelInt = in.readInt(); - level = Level.toLevel(levelInt); - - int argArrayLen = in.readInt(); - if (argArrayLen != NULL_ARGUMENT_ARRAY) { - argumentArray = new String[argArrayLen]; - for (int i = 0; i < argArrayLen; i++) { - Object val = in.readObject(); - if (!NULL_ARGUMENT_ARRAY_ELEMENT.equals(val)) { - argumentArray[i] = val; - } - } - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((message == null) ? 0 : message.hashCode()); - result = prime * result - + ((threadName == null) ? 0 : threadName.hashCode()); - result = prime * result + (int) (timeStamp ^ (timeStamp >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final PubLoggingEventVO other = (PubLoggingEventVO) obj; - if (message == null) { - if (other.message != null) - return false; - } else if (!message.equals(other.message)) - return false; - - if (loggerName == null) { - if (other.loggerName != null) - return false; - } else if (!loggerName.equals(other.loggerName)) - return false; - - if (threadName == null) { - if (other.threadName != null) - return false; - } else if (!threadName.equals(other.threadName)) - return false; - if (timeStamp != other.timeStamp) - return false; - - if (marker == null) { - if (other.marker != null) - return false; - } else if (!marker.equals(other.marker)) - return false; - - if (mdcPropertyMap == null) { - if (other.mdcPropertyMap != null) - return false; - } else if (!mdcPropertyMap.equals(other.mdcPropertyMap)) - return false; - return true; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(timeStamp); - sb.append(" "); - sb.append(level); - sb.append(" ["); - sb.append(threadName); - sb.append("] "); - sb.append(loggerName); - sb.append(" - "); - sb.append(getFormattedMessage()); - return sb.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.classic.spi; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Map; + +import org.slf4j.Marker; +import org.slf4j.helpers.MessageFormatter; + +import ch.qos.logback.classic.Level; + +/** + * A read/write and serializable implementation of {@link ILoggingEvent}. + * + * @author Ceki Gülcü + + */ +public class PubLoggingEventVO implements ILoggingEvent, Serializable { + + + private static final long serialVersionUID = -3385765861078946218L; + + private static final int NULL_ARGUMENT_ARRAY = -1; + private static final String NULL_ARGUMENT_ARRAY_ELEMENT = "NULL_ARGUMENT_ARRAY_ELEMENT"; + + public String threadName; + public String loggerName; + public LoggerContextVO loggerContextVO; + + public transient Level level; + public String message; + + private transient String formattedMessage; + + public Object[] argumentArray; + + public IThrowableProxy throwableProxy; + public StackTraceElement[] callerDataArray; + public Marker marker; + public Map mdcPropertyMap; + public long timeStamp; + + + + public String getThreadName() { + return threadName; + } + + public LoggerContextVO getLoggerContextVO() { + return loggerContextVO; + } + + public String getLoggerName() { + return loggerName; + } + + public Level getLevel() { + return level; + } + + public String getMessage() { + return message; + } + + public String getFormattedMessage() { + if (formattedMessage != null) { + return formattedMessage; + } + + if (argumentArray != null) { + formattedMessage = MessageFormatter.arrayFormat(message, argumentArray); + } else { + formattedMessage = message; + } + + return formattedMessage; + } + + public Object[] getArgumentArray() { + return argumentArray; + } + + public IThrowableProxy getThrowableProxy() { + return throwableProxy; + } + + public StackTraceElement[] getCallerData() { + return callerDataArray; + } + + public boolean hasCallerData() { + return callerDataArray != null; + } + + public Marker getMarker() { + return marker; + } + + public long getTimeStamp() { + return timeStamp; + } + + + + public long getContextBirthTime() { + return loggerContextVO.getBirthTime(); + } + + public LoggerContextVO getContextLoggerRemoteView() { + return loggerContextVO; + } + + public Map getMDCPropertyMap() { + return mdcPropertyMap; + } + + public void prepareForDeferredProcessing() { + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeInt(level.levelInt); + if (argumentArray != null) { + int len = argumentArray.length; + out.writeInt(len); + for (int i = 0; i < argumentArray.length; i++) { + if (argumentArray[i] != null) { + out.writeObject(argumentArray[i].toString()); + } else { + out.writeObject(NULL_ARGUMENT_ARRAY_ELEMENT); + } + } + } else { + out.writeInt(NULL_ARGUMENT_ARRAY); + } + + } + + private void readObject(ObjectInputStream in) throws IOException, + ClassNotFoundException { + in.defaultReadObject(); + int levelInt = in.readInt(); + level = Level.toLevel(levelInt); + + int argArrayLen = in.readInt(); + if (argArrayLen != NULL_ARGUMENT_ARRAY) { + argumentArray = new String[argArrayLen]; + for (int i = 0; i < argArrayLen; i++) { + Object val = in.readObject(); + if (!NULL_ARGUMENT_ARRAY_ELEMENT.equals(val)) { + argumentArray[i] = val; + } + } + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((message == null) ? 0 : message.hashCode()); + result = prime * result + + ((threadName == null) ? 0 : threadName.hashCode()); + result = prime * result + (int) (timeStamp ^ (timeStamp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final PubLoggingEventVO other = (PubLoggingEventVO) obj; + if (message == null) { + if (other.message != null) + return false; + } else if (!message.equals(other.message)) + return false; + + if (loggerName == null) { + if (other.loggerName != null) + return false; + } else if (!loggerName.equals(other.loggerName)) + return false; + + if (threadName == null) { + if (other.threadName != null) + return false; + } else if (!threadName.equals(other.threadName)) + return false; + if (timeStamp != other.timeStamp) + return false; + + if (marker == null) { + if (other.marker != null) + return false; + } else if (!marker.equals(other.marker)) + return false; + + if (mdcPropertyMap == null) { + if (other.mdcPropertyMap != null) + return false; + } else if (!mdcPropertyMap.equals(other.mdcPropertyMap)) + return false; + return true; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(timeStamp); + sb.append(" "); + sb.append(level); + sb.append(" ["); + sb.append(threadName); + sb.append("] "); + sb.append(loggerName); + sb.append(" - "); + sb.append(getFormattedMessage()); + return sb.toString(); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/ThrowableProxyTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/ThrowableProxyTest.java index a69f9ebd896086632527e2af9fefd6c6f73de128..d0fc89e9db788fc93013df5885e907c3ac97116f 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/ThrowableProxyTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/ThrowableProxyTest.java @@ -1,96 +1,96 @@ -/** - * 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.classic.spi; - -import static org.junit.Assert.assertEquals; - -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class ThrowableProxyTest { - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - public void verify(Throwable t) { - t.printStackTrace(pw); - - IThrowableProxy tp = new ThrowableProxy(t); - - String result = ThrowableProxyUtil.asString(tp); - result = result.replace("common frames omitted", "more"); - - String expected = sw.toString(); - - System.out.println("========expected"); - System.out.println(expected); - - System.out.println("========result"); - System.out.println(result); - - assertEquals(expected, result); - } - - @Test - public void smoke() { - Exception e = new Exception("smoke"); - verify(e); - } - - @Test - public void nested() { - Exception w = null; - try { - someMethod(); - } catch (Exception e) { - w = new Exception("wrapping", e); - } - verify(w); - } - - @Test - public void multiNested() { - Exception w = null; - try { - someOtherMethod(); - } catch (Exception e) { - w = new Exception("wrapping", e); - } - verify(w); - } - - void someMethod() throws Exception { - throw new Exception("someMethod"); - } - - void someOtherMethod() throws Exception { - try { - someMethod(); - } catch (Exception e) { - throw new Exception("someOtherMethod", e); - } - } -} +/** + * 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.classic.spi; + +import static org.junit.Assert.assertEquals; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class ThrowableProxyTest { + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + public void verify(Throwable t) { + t.printStackTrace(pw); + + IThrowableProxy tp = new ThrowableProxy(t); + + String result = ThrowableProxyUtil.asString(tp); + result = result.replace("common frames omitted", "more"); + + String expected = sw.toString(); + + System.out.println("========expected"); + System.out.println(expected); + + System.out.println("========result"); + System.out.println(result); + + assertEquals(expected, result); + } + + @Test + public void smoke() { + Exception e = new Exception("smoke"); + verify(e); + } + + @Test + public void nested() { + Exception w = null; + try { + someMethod(); + } catch (Exception e) { + w = new Exception("wrapping", e); + } + verify(w); + } + + @Test + public void multiNested() { + Exception w = null; + try { + someOtherMethod(); + } catch (Exception e) { + w = new Exception("wrapping", e); + } + verify(w); + } + + void someMethod() throws Exception { + throw new Exception("someMethod"); + } + + void someOtherMethod() throws Exception { + try { + someMethod(); + } catch (Exception e) { + throw new Exception("someOtherMethod", e); + } + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/special/CPDCSpecialImpl.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/special/CPDCSpecialImpl.java index 8e4951c05b5bb893fbeefaac6731906bf9c3afa7..df45af313e5756e3eb4ebfce8c19cbe42fff614e 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/special/CPDCSpecialImpl.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/special/CPDCSpecialImpl.java @@ -1,45 +1,45 @@ -/** - * 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.classic.spi.special; - -import ch.qos.logback.classic.spi.CPDCSpecial; -import ch.qos.logback.classic.spi.IThrowableProxy; -import ch.qos.logback.classic.spi.PackagingDataCalculator; -import ch.qos.logback.classic.spi.ThrowableProxy; - - -public class CPDCSpecialImpl implements CPDCSpecial { - - - Throwable throwable; - IThrowableProxy throwableProxy; - - public void doTest() { - nesting(); - } - - private void nesting() { - throwable = new Throwable("x"); - throwableProxy = new ThrowableProxy(throwable); - PackagingDataCalculator pdc = new PackagingDataCalculator(); - pdc.calculate(throwableProxy); - } - - public Throwable getThrowable() { - return throwable; - } - public IThrowableProxy getThrowableProxy() { - return throwableProxy; - } -} +/** + * 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.classic.spi.special; + +import ch.qos.logback.classic.spi.CPDCSpecial; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.PackagingDataCalculator; +import ch.qos.logback.classic.spi.ThrowableProxy; + + +public class CPDCSpecialImpl implements CPDCSpecial { + + + Throwable throwable; + IThrowableProxy throwableProxy; + + public void doTest() { + nesting(); + } + + private void nesting() { + throwable = new Throwable("x"); + throwableProxy = new ThrowableProxy(throwable); + PackagingDataCalculator pdc = new PackagingDataCalculator(); + pdc.calculate(throwableProxy); + } + + public Throwable getThrowable() { + return throwable; + } + public IThrowableProxy getThrowableProxy() { + return throwableProxy; + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/testUtil/SampleConverter.java b/logback-classic/src/test/java/ch/qos/logback/classic/testUtil/SampleConverter.java index 992fe215445cbca1c348fac7ea7126573e0a7370..d0e9c418d6f176a05e9bb2ba406bf1273d78982e 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/testUtil/SampleConverter.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/testUtil/SampleConverter.java @@ -1,28 +1,28 @@ -/** - * 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.classic.testUtil; - -import ch.qos.logback.classic.pattern.ClassicConverter; -import ch.qos.logback.classic.spi.ILoggingEvent; - -public class SampleConverter extends ClassicConverter { - - static public final String SAMPLE_STR = "sample"; - - @Override - public String convert(ILoggingEvent event) { - return SAMPLE_STR; - } - -} +/** + * 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.classic.testUtil; + +import ch.qos.logback.classic.pattern.ClassicConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; + +public class SampleConverter extends ClassicConverter { + + static public final String SAMPLE_STR = "sample"; + + @Override + public String convert(ILoggingEvent event) { + return SAMPLE_STR; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DebugUsersTurboFilter.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DebugUsersTurboFilter.java index f80bedd33016dc6be4036b46a432e5701116a72d..f79cdf0f87e160e8bedd86ce03ad81ac2420d7b4 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DebugUsersTurboFilter.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DebugUsersTurboFilter.java @@ -1,63 +1,63 @@ -/** - * 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.classic.turbo; - -import java.util.ArrayList; -import java.util.List; - -import org.slf4j.MDC; -import org.slf4j.Marker; - -import ch.qos.logback.classic.ClassicConstants; -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.core.spi.FilterReply; - -/** - * This class allows output of debug level events to a certain list of users. - * - * If the level passed as a parameter is of level DEBUG, then the "user" value - * taken from the MDC is checked against the configured user list. When the user - * belongs to the list, the request is accepted. Otherwise a NEUTRAL response - * is sent, thus not influencing the filter chain. - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class DebugUsersTurboFilter extends TurboFilter { - - List userList = new ArrayList(); - - @Override - public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) { - if (!level.equals(Level.DEBUG)) { - return FilterReply.NEUTRAL; - } - String user = MDC.get(ClassicConstants.USER_MDC_KEY); - if (user != null && userList.contains(user)) { - return FilterReply.ACCEPT; - } - return FilterReply.NEUTRAL; - } - - public void addUser(String user) { - userList.add(user); - } - - //test in BasicJoranTest only, to be removed asap. - public List getUsers() { - return userList; - } - -} +/** + * 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.classic.turbo; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.MDC; +import org.slf4j.Marker; + +import ch.qos.logback.classic.ClassicConstants; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.spi.FilterReply; + +/** + * This class allows output of debug level events to a certain list of users. + * + * If the level passed as a parameter is of level DEBUG, then the "user" value + * taken from the MDC is checked against the configured user list. When the user + * belongs to the list, the request is accepted. Otherwise a NEUTRAL response + * is sent, thus not influencing the filter chain. + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class DebugUsersTurboFilter extends TurboFilter { + + List userList = new ArrayList(); + + @Override + public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) { + if (!level.equals(Level.DEBUG)) { + return FilterReply.NEUTRAL; + } + String user = MDC.get(ClassicConstants.USER_MDC_KEY); + if (user != null && userList.contains(user)) { + return FilterReply.ACCEPT; + } + return FilterReply.NEUTRAL; + } + + public void addUser(String user) { + userList.add(user); + } + + //test in BasicJoranTest only, to be removed asap. + public List getUsers() { + return userList; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java index da2549183b0b339b3c8b9af256b9475ec8454be9..5daddf33b3b5b9b07f967f479eb941c6f97f92aa 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java @@ -1,89 +1,89 @@ -/** - * 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.classic.turbo; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import ch.qos.logback.core.spi.FilterReply; - -public class DuplicateMessageFilterTest { - - @Test - public void smoke() { - DuplicateMessageFilter dmf = new DuplicateMessageFilter(); - dmf.setAllowedRepetitions(0); - dmf.start(); - assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "x", null, - null)); - assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "y", null, - null)); - assertEquals(FilterReply.DENY, dmf - .decide(null, null, null, "x", null, null)); - assertEquals(FilterReply.DENY, dmf - .decide(null, null, null, "y", null, null)); - } - - @Test - public void memoryLoss() { - DuplicateMessageFilter dmf = new DuplicateMessageFilter(); - dmf.setAllowedRepetitions(1); - dmf.setCacheSize(1); - dmf.start(); - assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a", null, - null)); - assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "b", null, - null)); - assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a", null, - null)); - } - - @Test - public void many() { - DuplicateMessageFilter dmf = new DuplicateMessageFilter(); - dmf.setAllowedRepetitions(0); - int cacheSize = 10; - int margin = 2; - dmf.setCacheSize(cacheSize); - dmf.start(); - for (int i = 0; i < cacheSize + margin; i++) { - assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a" + i, - null, null)); - } - for (int i = cacheSize - 1; i >= margin; i--) { - assertEquals(FilterReply.DENY, dmf.decide(null, null, null, "a" + i, - null, null)); - } - for (int i = margin - 1; i >= 0; i--) { - assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a" + i, - null, null)); - } - } - - @Test - // isXXXEnabled invokes decide with a null format - // http://jira.qos.ch/browse/LBCLASSIC-134 - public void nullFormat() { - DuplicateMessageFilter dmf = new DuplicateMessageFilter(); - dmf.setAllowedRepetitions(0); - dmf.setCacheSize(10); - dmf.start(); - assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, null, null, - null)); - assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, null, null, - null)); - } - -} +/** + * 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.classic.turbo; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ch.qos.logback.core.spi.FilterReply; + +public class DuplicateMessageFilterTest { + + @Test + public void smoke() { + DuplicateMessageFilter dmf = new DuplicateMessageFilter(); + dmf.setAllowedRepetitions(0); + dmf.start(); + assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "x", null, + null)); + assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "y", null, + null)); + assertEquals(FilterReply.DENY, dmf + .decide(null, null, null, "x", null, null)); + assertEquals(FilterReply.DENY, dmf + .decide(null, null, null, "y", null, null)); + } + + @Test + public void memoryLoss() { + DuplicateMessageFilter dmf = new DuplicateMessageFilter(); + dmf.setAllowedRepetitions(1); + dmf.setCacheSize(1); + dmf.start(); + assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a", null, + null)); + assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "b", null, + null)); + assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a", null, + null)); + } + + @Test + public void many() { + DuplicateMessageFilter dmf = new DuplicateMessageFilter(); + dmf.setAllowedRepetitions(0); + int cacheSize = 10; + int margin = 2; + dmf.setCacheSize(cacheSize); + dmf.start(); + for (int i = 0; i < cacheSize + margin; i++) { + assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a" + i, + null, null)); + } + for (int i = cacheSize - 1; i >= margin; i--) { + assertEquals(FilterReply.DENY, dmf.decide(null, null, null, "a" + i, + null, null)); + } + for (int i = margin - 1; i >= 0; i--) { + assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a" + i, + null, null)); + } + } + + @Test + // isXXXEnabled invokes decide with a null format + // http://jira.qos.ch/browse/LBCLASSIC-134 + public void nullFormat() { + DuplicateMessageFilter dmf = new DuplicateMessageFilter(); + dmf.setAllowedRepetitions(0); + dmf.setCacheSize(10); + dmf.start(); + assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, null, null, + null)); + assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, null, null, + null)); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java index ee1f7666753541c99c8db4df19eaf5b00731e4a3..33805dc38d6546b56b1d83576a92209471351346 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java @@ -1,57 +1,57 @@ -/** - * 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.classic.turbo; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.slf4j.Marker; -import org.slf4j.MarkerFactory; - -import ch.qos.logback.core.spi.FilterReply; - -public class MarkerFilterTest { - - static String MARKER_NAME = "toto"; - - Marker totoMarker = MarkerFactory.getMarker(MARKER_NAME); - - - @Test - public void testNoMarker() { - MarkerFilter mkt = new MarkerFilter(); - mkt.start(); - assertFalse(mkt.isStarted()); - assertEquals(FilterReply.NEUTRAL, mkt.decide(totoMarker, null, null, null, null, null)); - assertEquals(FilterReply.NEUTRAL, mkt.decide(null, null, null, null, null, null)); - - } - - - @Test - public void testBasic() { - MarkerFilter mkt = new MarkerFilter(); - mkt.setMarker(MARKER_NAME); - mkt.setOnMatch("ACCEPT"); - mkt.setOnMismatch("DENY"); - - mkt.start(); - assertTrue(mkt.isStarted()); - assertEquals(FilterReply.DENY, mkt.decide(null, null, null, null, null, null)); - assertEquals(FilterReply.ACCEPT, mkt.decide(totoMarker, null, null, null, null, null)); - } - -} +/** + * 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.classic.turbo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +import ch.qos.logback.core.spi.FilterReply; + +public class MarkerFilterTest { + + static String MARKER_NAME = "toto"; + + Marker totoMarker = MarkerFactory.getMarker(MARKER_NAME); + + + @Test + public void testNoMarker() { + MarkerFilter mkt = new MarkerFilter(); + mkt.start(); + assertFalse(mkt.isStarted()); + assertEquals(FilterReply.NEUTRAL, mkt.decide(totoMarker, null, null, null, null, null)); + assertEquals(FilterReply.NEUTRAL, mkt.decide(null, null, null, null, null, null)); + + } + + + @Test + public void testBasic() { + MarkerFilter mkt = new MarkerFilter(); + mkt.setMarker(MARKER_NAME); + mkt.setOnMatch("ACCEPT"); + mkt.setOnMismatch("DENY"); + + mkt.start(); + assertTrue(mkt.isStarted()); + assertEquals(FilterReply.DENY, mkt.decide(null, null, null, null, null, null)); + assertEquals(FilterReply.ACCEPT, mkt.decide(totoMarker, null, null, null, null, null)); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/NOPTurboFilter.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/NOPTurboFilter.java index d929a1e0909de2835cbb9fb6c8cb072b3591bc15..94528b7dfea5623f4e9f17a49a1da8527377bc53 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/NOPTurboFilter.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/NOPTurboFilter.java @@ -1,31 +1,31 @@ -/** - * 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.classic.turbo; - -import org.slf4j.Marker; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.core.spi.FilterReply; - -public class NOPTurboFilter extends TurboFilter { - - @Override - public FilterReply decide(final Marker marker, final Logger logger, final Level level, final String format, - final Object[] params, final Throwable t) { - - return FilterReply.NEUTRAL; - } - -} +/** + * 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.classic.turbo; + +import org.slf4j.Marker; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.spi.FilterReply; + +public class NOPTurboFilter extends TurboFilter { + + @Override + public FilterReply decide(final Marker marker, final Logger logger, final Level level, final String format, + final Object[] params, final Throwable t) { + + return FilterReply.NEUTRAL; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java index 474d6c9126e44f6a9f77898673b7d54c0ea92dda..d8e4b93695fcf4baa974ab55becadad6e5176916 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java @@ -1,24 +1,24 @@ -/** - * 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.classic.turbo; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses( { ReconfigureOnChangeTest.class, MarkerFilterTest.class, - DuplicateMessageFilterTest.class }) -public class PackageTest { +/** + * 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.classic.turbo; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses( { ReconfigureOnChangeTest.class, MarkerFilterTest.class, + DuplicateMessageFilterTest.class }) +public class PackageTest { } \ No newline at end of file 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 19c74a2ccf098a45499415c68dfda448313d46ef..6c6f52ff7c10f1dbe1748e7b2c09d91ed474677a 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 @@ -1,229 +1,229 @@ -/** - * 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.classic.turbo; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; - -import org.junit.Before; -import org.junit.Test; -import org.slf4j.helpers.BogoPerf; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.issue.lbclassic135.LoggingRunnable; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.util.TeztConstants; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.contention.MultiThreadedHarness; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.status.InfoStatus; -import ch.qos.logback.core.status.StatusChecker; -import ch.qos.logback.core.testUtil.Env; - -public class ReconfigureOnChangeTest { - final static int THREAD_COUNT = 5; - 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 SCAN1_FILE_AS_STR = TeztConstants.TEST_DIR_PREFIX - + "input/turbo/scan 1.xml"; - - // it actually takes time for Windows to propagate file modification changes - // values below 100 milliseconds can be problematic - // the same propagation latency occurs in Linux but is even larger (>600 ms) - final static int DEFAULT_SLEEP_BETWEEN_UPDATES = 250; - - int sleepBetweenUpdates = DEFAULT_SLEEP_BETWEEN_UPDATES; - - static int totalTestDuration; - - LoggerContext loggerContext = new LoggerContext(); - Logger logger = loggerContext.getLogger(this.getClass()); - MultiThreadedHarness harness; - - @Before - public void setUp() { - // take into account propagation latency occurs on Linux - if (Env.isLinux()) { - sleepBetweenUpdates = 850; - totalTestDuration = sleepBetweenUpdates * 5; - } else { - totalTestDuration = sleepBetweenUpdates * 10; - } - harness = new MultiThreadedHarness(totalTestDuration); - } - - void configure(File file) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(loggerContext); - jc.doConfigure(file); - } - - RunnableWithCounterAndDone[] buildRunnableArray(File configFile) { - RunnableWithCounterAndDone[] rArray = new RunnableWithCounterAndDone[THREAD_COUNT]; - rArray[0] = new Updater(configFile); - for (int i = 1; i < THREAD_COUNT; i++) { - rArray[i] = new LoggingRunnable(logger); - } - return rArray; - } - - @Test - // See http://jira.qos.ch/browse/LBCORE-119 - public void fileToURLAndBack() throws MalformedURLException { - File file = new File("a b.xml"); - URL url = file.toURI().toURL(); - ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter(); - File back = rocf.convertToFile(url); - assertEquals(file.getName(), back.getName()); - } - - // Tests whether ConfigurationAction is installing ReconfigureOnChangeFilter - @Test - public void scan1() throws JoranException, IOException, InterruptedException { - File file = new File(SCAN1_FILE_AS_STR); - configure(file); - RunnableWithCounterAndDone[] runnableArray = buildRunnableArray(file); - harness.execute(runnableArray); - - loggerContext.getStatusManager().add( - new InfoStatus("end of execution ", this)); - - long expectedRreconfigurations = runnableArray[0].getCounter(); - verify(expectedRreconfigurations); - } - - void verify(long expectedRreconfigurations) { - StatusChecker checker = new StatusChecker(loggerContext); - assertTrue(checker.isErrorFree()); - int effectiveResets = checker - .matchCount("Resetting and reconfiguring context"); - // the number of effective resets must be equal or less than - // expectedRreconfigurations - assertTrue(effectiveResets <= expectedRreconfigurations); - // however, there should be some effective resets - String failMsg = "effective=" + effectiveResets + ", expected=" - + expectedRreconfigurations; - assertTrue(failMsg, - (effectiveResets * 1.3) >= (expectedRreconfigurations * 1.0)); - } - - ReconfigureOnChangeFilter initROCF() throws MalformedURLException { - ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter(); - rocf.setContext(loggerContext); - File file = new File(SCAN1_FILE_AS_STR); - loggerContext.putObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN, - file.toURI().toURL()); - rocf.start(); - return rocf; - } - - @Test - public void directPerfTest() throws MalformedURLException { - if (Env.isLinux()) { - // for some reason this test does not pass on Linux (AMD 64 bit, - // Dual Core Opteron 170) - return; - } - - ReconfigureOnChangeFilter rocf = initROCF(); - assertTrue(rocf.isStarted()); - - for (int i = 0; i < 30; i++) { - directLoop(rocf); - } - double avg = directLoop(rocf); - System.out.println("directPerfTest: " + avg); - // the reference was computed on Orion (Ceki's computer) - long referencePerf = 18; - BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); - } - - 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); - } - - @Test - public void indirectPerfTest() throws MalformedURLException { - if (Env.isLinux()) { - // for some reason this test does not pass on Linux (AMD 64 bit, - // Dual Core - // Opteron 170) - return; - } - - ReconfigureOnChangeFilter rocf = initROCF(); - assertTrue(rocf.isStarted()); - loggerContext.addTurboFilter(rocf); - logger.setLevel(Level.ERROR); - - indirectLoop(); - double avg = indirectLoop(); - System.out.println(avg); - // the reference was computed on Orion (Ceki's computer) - long referencePerf = 68; - BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); - } - - void addInfo(String msg, Object o) { - loggerContext.getStatusManager().add(new InfoStatus(msg, o)); - } - - public double indirectLoop() { - long start = System.nanoTime(); - for (int i = 0; i < LOOP_LEN; i++) { - logger.debug("hello"); - } - long end = System.nanoTime(); - return (end - start) / (1.0d * LOOP_LEN); - } - - class Updater extends RunnableWithCounterAndDone { - File configFile; - - Updater(File configFile) { - this.configFile = configFile; - } - - public void run() { - while (!isDone()) { - try { - Thread.sleep(sleepBetweenUpdates); - } catch (InterruptedException e) { - } - if (isDone()) { - return; - } - counter++; - ReconfigureOnChangeTest.this.addInfo("***settting last modified", this); - configFile.setLastModified(System.currentTimeMillis()); - } - } - } - -} +/** + * 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.classic.turbo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import org.junit.Before; +import org.junit.Test; +import org.slf4j.helpers.BogoPerf; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.issue.lbclassic135.LoggingRunnable; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.util.TeztConstants; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.contention.MultiThreadedHarness; +import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.StatusChecker; +import ch.qos.logback.core.testUtil.Env; + +public class ReconfigureOnChangeTest { + final static int THREAD_COUNT = 5; + 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 SCAN1_FILE_AS_STR = TeztConstants.TEST_DIR_PREFIX + + "input/turbo/scan 1.xml"; + + // it actually takes time for Windows to propagate file modification changes + // values below 100 milliseconds can be problematic + // the same propagation latency occurs in Linux but is even larger (>600 ms) + final static int DEFAULT_SLEEP_BETWEEN_UPDATES = 250; + + int sleepBetweenUpdates = DEFAULT_SLEEP_BETWEEN_UPDATES; + + static int totalTestDuration; + + LoggerContext loggerContext = new LoggerContext(); + Logger logger = loggerContext.getLogger(this.getClass()); + MultiThreadedHarness harness; + + @Before + public void setUp() { + // take into account propagation latency occurs on Linux + if (Env.isLinux()) { + sleepBetweenUpdates = 850; + totalTestDuration = sleepBetweenUpdates * 5; + } else { + totalTestDuration = sleepBetweenUpdates * 10; + } + harness = new MultiThreadedHarness(totalTestDuration); + } + + void configure(File file) throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(loggerContext); + jc.doConfigure(file); + } + + RunnableWithCounterAndDone[] buildRunnableArray(File configFile) { + RunnableWithCounterAndDone[] rArray = new RunnableWithCounterAndDone[THREAD_COUNT]; + rArray[0] = new Updater(configFile); + for (int i = 1; i < THREAD_COUNT; i++) { + rArray[i] = new LoggingRunnable(logger); + } + return rArray; + } + + @Test + // See http://jira.qos.ch/browse/LBCORE-119 + public void fileToURLAndBack() throws MalformedURLException { + File file = new File("a b.xml"); + URL url = file.toURI().toURL(); + ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter(); + File back = rocf.convertToFile(url); + assertEquals(file.getName(), back.getName()); + } + + // Tests whether ConfigurationAction is installing ReconfigureOnChangeFilter + @Test + public void scan1() throws JoranException, IOException, InterruptedException { + File file = new File(SCAN1_FILE_AS_STR); + configure(file); + RunnableWithCounterAndDone[] runnableArray = buildRunnableArray(file); + harness.execute(runnableArray); + + loggerContext.getStatusManager().add( + new InfoStatus("end of execution ", this)); + + long expectedRreconfigurations = runnableArray[0].getCounter(); + verify(expectedRreconfigurations); + } + + void verify(long expectedRreconfigurations) { + StatusChecker checker = new StatusChecker(loggerContext); + assertTrue(checker.isErrorFree()); + int effectiveResets = checker + .matchCount("Resetting and reconfiguring context"); + // the number of effective resets must be equal or less than + // expectedRreconfigurations + assertTrue(effectiveResets <= expectedRreconfigurations); + // however, there should be some effective resets + String failMsg = "effective=" + effectiveResets + ", expected=" + + expectedRreconfigurations; + assertTrue(failMsg, + (effectiveResets * 1.3) >= (expectedRreconfigurations * 1.0)); + } + + ReconfigureOnChangeFilter initROCF() throws MalformedURLException { + ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter(); + rocf.setContext(loggerContext); + File file = new File(SCAN1_FILE_AS_STR); + loggerContext.putObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN, + file.toURI().toURL()); + rocf.start(); + return rocf; + } + + @Test + public void directPerfTest() throws MalformedURLException { + if (Env.isLinux()) { + // for some reason this test does not pass on Linux (AMD 64 bit, + // Dual Core Opteron 170) + return; + } + + ReconfigureOnChangeFilter rocf = initROCF(); + assertTrue(rocf.isStarted()); + + for (int i = 0; i < 30; i++) { + directLoop(rocf); + } + double avg = directLoop(rocf); + System.out.println("directPerfTest: " + avg); + // the reference was computed on Orion (Ceki's computer) + long referencePerf = 18; + BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); + } + + 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); + } + + @Test + public void indirectPerfTest() throws MalformedURLException { + if (Env.isLinux()) { + // for some reason this test does not pass on Linux (AMD 64 bit, + // Dual Core + // Opteron 170) + return; + } + + ReconfigureOnChangeFilter rocf = initROCF(); + assertTrue(rocf.isStarted()); + loggerContext.addTurboFilter(rocf); + logger.setLevel(Level.ERROR); + + indirectLoop(); + double avg = indirectLoop(); + System.out.println(avg); + // the reference was computed on Orion (Ceki's computer) + long referencePerf = 68; + BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); + } + + void addInfo(String msg, Object o) { + loggerContext.getStatusManager().add(new InfoStatus(msg, o)); + } + + public double indirectLoop() { + long start = System.nanoTime(); + for (int i = 0; i < LOOP_LEN; i++) { + logger.debug("hello"); + } + long end = System.nanoTime(); + return (end - start) / (1.0d * LOOP_LEN); + } + + class Updater extends RunnableWithCounterAndDone { + File configFile; + + Updater(File configFile) { + this.configFile = configFile; + } + + public void run() { + while (!isDone()) { + try { + Thread.sleep(sleepBetweenUpdates); + } catch (InterruptedException e) { + } + if (isDone()) { + return; + } + counter++; + ReconfigureOnChangeTest.this.addInfo("***settting last modified", this); + configFile.setLastModified(System.currentTimeMillis()); + } + } + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/util/InitializationTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/util/InitializationTest.java index cf2c0901e1c88d7ba5be5389bf7d110d65462c32..e71b4247257fbb8bb365277bca33b4cf71f6ff63 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/util/InitializationTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/util/InitializationTest.java @@ -1,121 +1,121 @@ -/** - * 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.classic.util; - - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertEquals; - -import java.util.List; - -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.ConsoleAppender; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.status.StatusListener; -import ch.qos.logback.core.status.TrivialStatusListener; - -public class InitializationTest { - - org.slf4j.Logger logger = LoggerFactory.getLogger(InitializationTest.class); - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - Logger root = (Logger) LoggerFactory.getLogger("root"); - - @Before - public void setUp() throws Exception { - logger.debug("Hello-didily-odily"); - } - - @After - public void tearDown() throws Exception { - System.clearProperty(ContextInitializer.CONFIG_FILE_PROPERTY); - System.clearProperty(ContextInitializer.STATUS_LISTENER_CLASS); - lc.reset(); // we are going to need this context - } - - @Test - @Ignore - // this test works only if logback-test.xml or logback.xml files are on the classpath. - // However, this is something we try to avoid in order to simplify the life - // of users trying to follows the manual and logback-examples from an IDE - public void atoconfig() { - Appender appender = root.getAppender("STDOUT"); - assertNotNull(appender); - assertTrue(appender instanceof ConsoleAppender); - } - - @Test - @Ignore - // this test works only if logback-test.xml or logback.xml files are on the classpath. - // However, this is something we try to avoid in order to simplify the life - // of users trying to follows the manual and logback-examples from an IDE - public void reset() throws JoranException { - { - new ContextInitializer(lc).autoConfig(); - Appender appender = root.getAppender("STDOUT"); - assertNotNull(appender); - assertTrue(appender instanceof ConsoleAppender); - } - { - lc.stop(); - Appender appender = root.getAppender("STDOUT"); - assertNull(appender); - } - } - - @Test - public void autoConfigFromSystemProperties() throws JoranException { - doAutoConfigFromSystemProperties(TeztConstants.TEST_DIR_PREFIX + "input/autoConfig.xml"); - doAutoConfigFromSystemProperties("autoConfigAsResource.xml"); - // test passing a URL. note the relative path syntax with file:src/test/... - doAutoConfigFromSystemProperties("file:"+TeztConstants.TEST_DIR_PREFIX + "input/autoConfig.xml"); - } - - public void doAutoConfigFromSystemProperties(String val) throws JoranException { - //lc.reset(); - System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, val); - new ContextInitializer(lc).autoConfig(); - Appender appender = root.getAppender("AUTO_BY_SYSTEM_PROPERTY"); - assertNotNull(appender); - } - - @Test - public void autoStatusListener() throws JoranException { - System.setProperty(ContextInitializer.STATUS_LISTENER_CLASS, TrivialStatusListener.class.getName()); - List sll = lc.getStatusManager().getCopyOfStatusListenerList(); - assertEquals(0, sll.size()); - doAutoConfigFromSystemProperties(TeztConstants.TEST_DIR_PREFIX + "input/autoConfig.xml"); - sll = lc.getStatusManager().getCopyOfStatusListenerList(); - assertTrue(sll.size() +" should be 1", sll.size() == 1); - } - - @Test - public void autoOnConsoleStatusListener() throws JoranException { - System.setProperty(ContextInitializer.STATUS_LISTENER_CLASS, ContextInitializer.SYSOUT); - List sll = lc.getStatusManager().getCopyOfStatusListenerList(); - assertEquals(0, sll.size()); - doAutoConfigFromSystemProperties(TeztConstants.TEST_DIR_PREFIX + "input/autoConfig.xml"); - sll = lc.getStatusManager().getCopyOfStatusListenerList(); - assertTrue(sll.size() +" should be 1", sll.size() == 1); - } -} +/** + * 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.classic.util; + + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.ConsoleAppender; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.status.TrivialStatusListener; + +public class InitializationTest { + + org.slf4j.Logger logger = LoggerFactory.getLogger(InitializationTest.class); + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + Logger root = (Logger) LoggerFactory.getLogger("root"); + + @Before + public void setUp() throws Exception { + logger.debug("Hello-didily-odily"); + } + + @After + public void tearDown() throws Exception { + System.clearProperty(ContextInitializer.CONFIG_FILE_PROPERTY); + System.clearProperty(ContextInitializer.STATUS_LISTENER_CLASS); + lc.reset(); // we are going to need this context + } + + @Test + @Ignore + // this test works only if logback-test.xml or logback.xml files are on the classpath. + // However, this is something we try to avoid in order to simplify the life + // of users trying to follows the manual and logback-examples from an IDE + public void atoconfig() { + Appender appender = root.getAppender("STDOUT"); + assertNotNull(appender); + assertTrue(appender instanceof ConsoleAppender); + } + + @Test + @Ignore + // this test works only if logback-test.xml or logback.xml files are on the classpath. + // However, this is something we try to avoid in order to simplify the life + // of users trying to follows the manual and logback-examples from an IDE + public void reset() throws JoranException { + { + new ContextInitializer(lc).autoConfig(); + Appender appender = root.getAppender("STDOUT"); + assertNotNull(appender); + assertTrue(appender instanceof ConsoleAppender); + } + { + lc.stop(); + Appender appender = root.getAppender("STDOUT"); + assertNull(appender); + } + } + + @Test + public void autoConfigFromSystemProperties() throws JoranException { + doAutoConfigFromSystemProperties(TeztConstants.TEST_DIR_PREFIX + "input/autoConfig.xml"); + doAutoConfigFromSystemProperties("autoConfigAsResource.xml"); + // test passing a URL. note the relative path syntax with file:src/test/... + doAutoConfigFromSystemProperties("file:"+TeztConstants.TEST_DIR_PREFIX + "input/autoConfig.xml"); + } + + public void doAutoConfigFromSystemProperties(String val) throws JoranException { + //lc.reset(); + System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, val); + new ContextInitializer(lc).autoConfig(); + Appender appender = root.getAppender("AUTO_BY_SYSTEM_PROPERTY"); + assertNotNull(appender); + } + + @Test + public void autoStatusListener() throws JoranException { + System.setProperty(ContextInitializer.STATUS_LISTENER_CLASS, TrivialStatusListener.class.getName()); + List sll = lc.getStatusManager().getCopyOfStatusListenerList(); + assertEquals(0, sll.size()); + doAutoConfigFromSystemProperties(TeztConstants.TEST_DIR_PREFIX + "input/autoConfig.xml"); + sll = lc.getStatusManager().getCopyOfStatusListenerList(); + assertTrue(sll.size() +" should be 1", sll.size() == 1); + } + + @Test + public void autoOnConsoleStatusListener() throws JoranException { + System.setProperty(ContextInitializer.STATUS_LISTENER_CLASS, ContextInitializer.SYSOUT); + List sll = lc.getStatusManager().getCopyOfStatusListenerList(); + assertEquals(0, sll.size()); + doAutoConfigFromSystemProperties(TeztConstants.TEST_DIR_PREFIX + "input/autoConfig.xml"); + sll = lc.getStatusManager().getCopyOfStatusListenerList(); + assertTrue(sll.size() +" should be 1", sll.size() == 1); + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/util/LevelToSyslogSeverityTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/util/LevelToSyslogSeverityTest.java index e8c0ee1b7745ef7124b3cf698ca0a8295da9dd19..f5f9d6cdf55dc8f85f77fb57e6eac8255e6d5343 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/util/LevelToSyslogSeverityTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/util/LevelToSyslogSeverityTest.java @@ -1,53 +1,53 @@ -/** - * 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.classic.util; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.core.net.SyslogConstants; - -public class LevelToSyslogSeverityTest { - - @Test - public void smoke() { - - assertEquals(SyslogConstants.DEBUG_SEVERITY, LevelToSyslogSeverity - .convert(createEventOfLevel(Level.TRACE))); - - assertEquals(SyslogConstants.DEBUG_SEVERITY, LevelToSyslogSeverity - .convert(createEventOfLevel(Level.DEBUG))); - - assertEquals(SyslogConstants.INFO_SEVERITY, LevelToSyslogSeverity - .convert(createEventOfLevel(Level.INFO))); - - assertEquals(SyslogConstants.WARNING_SEVERITY, LevelToSyslogSeverity - .convert(createEventOfLevel(Level.WARN))); - - assertEquals(SyslogConstants.ERROR_SEVERITY, LevelToSyslogSeverity - .convert(createEventOfLevel(Level.ERROR))); - - } - - ILoggingEvent createEventOfLevel(Level level) { - LoggingEvent event = new LoggingEvent(); - event.setLevel(level); - return event; - } - -} +/** + * 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.classic.util; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.net.SyslogConstants; + +public class LevelToSyslogSeverityTest { + + @Test + public void smoke() { + + assertEquals(SyslogConstants.DEBUG_SEVERITY, LevelToSyslogSeverity + .convert(createEventOfLevel(Level.TRACE))); + + assertEquals(SyslogConstants.DEBUG_SEVERITY, LevelToSyslogSeverity + .convert(createEventOfLevel(Level.DEBUG))); + + assertEquals(SyslogConstants.INFO_SEVERITY, LevelToSyslogSeverity + .convert(createEventOfLevel(Level.INFO))); + + assertEquals(SyslogConstants.WARNING_SEVERITY, LevelToSyslogSeverity + .convert(createEventOfLevel(Level.WARN))); + + assertEquals(SyslogConstants.ERROR_SEVERITY, LevelToSyslogSeverity + .convert(createEventOfLevel(Level.ERROR))); + + } + + ILoggingEvent createEventOfLevel(Level level) { + LoggingEvent event = new LoggingEvent(); + event.setLevel(level); + return event; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/util/MockInitialContext.java b/logback-classic/src/test/java/ch/qos/logback/classic/util/MockInitialContext.java index 1107cb50af91adb287d818a5892552a9b9626dd3..c9b1543064868becb2b0a8d55b2e94dbaf9b7d75 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/util/MockInitialContext.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/util/MockInitialContext.java @@ -1,39 +1,39 @@ -/** - * 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.classic.util; - -import java.util.HashMap; -import java.util.Map; - -import javax.naming.InitialContext; -import javax.naming.NamingException; - -public class MockInitialContext extends InitialContext { - - public Map map = new HashMap(); - - public MockInitialContext() throws NamingException { - super(); - } - - @Override - public Object lookup(String name) throws NamingException { - if (name == null) { - return null; - } - - return map.get(name); - } - -} +/** + * 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.classic.util; + +import java.util.HashMap; +import java.util.Map; + +import javax.naming.InitialContext; +import javax.naming.NamingException; + +public class MockInitialContext extends InitialContext { + + public Map map = new HashMap(); + + public MockInitialContext() throws NamingException { + super(); + } + + @Override + public Object lookup(String name) throws NamingException { + if (name == null) { + return null; + } + + return map.get(name); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/util/MockInitialContextFactory.java b/logback-classic/src/test/java/ch/qos/logback/classic/util/MockInitialContextFactory.java index acf56c96797c741fb84068805c5c72bb39037889..2e619c5b90806e06d5c55077bc4b73dff32da375 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/util/MockInitialContextFactory.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/util/MockInitialContextFactory.java @@ -1,48 +1,48 @@ -/** - * 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.classic.util; - -import java.util.Hashtable; - -import javax.naming.Context; -import javax.naming.NamingException; -import javax.naming.spi.InitialContextFactory; - - -public class MockInitialContextFactory implements InitialContextFactory { - static MockInitialContext mic; - - static { - System.out.println("MockInitialContextFactory static called"); - initialize(); - } - - public static void initialize() { - try { - mic = new MockInitialContext(); - } catch (NamingException e) { - e.printStackTrace(); - } - } - - public Context getInitialContext(Hashtable environment) - throws NamingException { - return mic; - } - - public static MockInitialContext getContext() { - return mic; - } - -} +/** + * 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.classic.util; + +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.spi.InitialContextFactory; + + +public class MockInitialContextFactory implements InitialContextFactory { + static MockInitialContext mic; + + static { + System.out.println("MockInitialContextFactory static called"); + initialize(); + } + + public static void initialize() { + try { + mic = new MockInitialContext(); + } catch (NamingException e) { + e.printStackTrace(); + } + } + + public Context getInitialContext(Hashtable environment) + throws NamingException { + return mic; + } + + public static MockInitialContext getContext() { + return mic; + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/util/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/util/PackageTest.java index 19d6ec543064f96cc169022bab1db1c985e5744e..4b63deda1e43b71f92e64ca3027412caa3a9a56f 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/util/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/util/PackageTest.java @@ -1,25 +1,25 @@ -/** - * 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.classic.util; - - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({InitializationTest.class, LevelToSyslogSeverityTest.class} ) - -public class PackageTest { +/** + * 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.classic.util; + + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({InitializationTest.class, LevelToSyslogSeverityTest.class} ) + +public class PackageTest { } \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/util/TeztConstants.java b/logback-classic/src/test/java/ch/qos/logback/classic/util/TeztConstants.java index a40cdfd55761c5bcb58c10c6fe0cb7d47fa098e0..f92a75f68ea65f02fef67df1f0611c3bed4624ab 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/util/TeztConstants.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/util/TeztConstants.java @@ -1,28 +1,28 @@ -/** - * 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.classic.util; - -/** - * - * It seems to bother - * - * @author gulcu - * - */ -public class TeztConstants { - - public static final String TEST_DIR_PREFIX = "src/test/"; - - -} +/** + * 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.classic.util; + +/** + * + * It seems to bother + * + * @author gulcu + * + */ +public class TeztConstants { + + public static final String TEST_DIR_PREFIX = "src/test/"; + + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/util/TeztHelper.java b/logback-classic/src/test/java/ch/qos/logback/classic/util/TeztHelper.java index ab7928ed9f7c262c9c4e90eb1c033893729fbce0..2301b5c09ba84dabdc1662ab191c93a5102ebd5a 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/util/TeztHelper.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/util/TeztHelper.java @@ -1,26 +1,26 @@ -/** - * 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.classic.util; - -public class TeztHelper { - - - static public Throwable makeNestedException(int level) { - if (level == 0) { - return new Exception("nesting level=" + level); - } - Throwable cause = makeNestedException(level - 1); - return new Exception("nesting level =" + level, cause); - } -} +/** + * 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.classic.util; + +public class TeztHelper { + + + static public Throwable makeNestedException(int level) { + if (level == 0) { + return new Exception("nesting level=" + level); + } + Throwable cause = makeNestedException(level - 1); + return new Exception("nesting level =" + level, cause); + } +} diff --git a/logback-classic/src/test/java/org/dummy/DummyLBAppender.java b/logback-classic/src/test/java/org/dummy/DummyLBAppender.java index 20bbc7e2dd2f52d279864aacf1110a2a8fa0bddd..e8b194d8ca1f208eae2da85c52e16dfe19057042 100644 --- a/logback-classic/src/test/java/org/dummy/DummyLBAppender.java +++ b/logback-classic/src/test/java/org/dummy/DummyLBAppender.java @@ -1,45 +1,45 @@ -/** - * 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 org.dummy; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; - -public class DummyLBAppender extends AppenderBase { - - public List list = new ArrayList(); - public List stringList = new ArrayList(); - - PatternLayout layout; - - DummyLBAppender() { - this(null); - } - - DummyLBAppender(PatternLayout layout) { - this.layout = layout; - } - - protected void append(ILoggingEvent e) { - list.add(e); - if(layout != null) { - String s = layout.doLayout(e); - stringList.add(s); - } - } -} +/** + * 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 org.dummy; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; + +public class DummyLBAppender extends AppenderBase { + + public List list = new ArrayList(); + public List stringList = new ArrayList(); + + PatternLayout layout; + + DummyLBAppender() { + this(null); + } + + DummyLBAppender(PatternLayout layout) { + this.layout = layout; + } + + protected void append(ILoggingEvent e) { + list.add(e); + if(layout != null) { + String s = layout.doLayout(e); + stringList.add(s); + } + } +} diff --git a/logback-classic/src/test/java/org/dummy/Log4jInvocation.java b/logback-classic/src/test/java/org/dummy/Log4jInvocation.java index 39bc0fdd330ca9c361fa810d4025c58cc8e9c93a..18b1646627560c96de43762e0b29830585d27055 100644 --- a/logback-classic/src/test/java/org/dummy/Log4jInvocation.java +++ b/logback-classic/src/test/java/org/dummy/Log4jInvocation.java @@ -1,91 +1,91 @@ -/** - * 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 org.dummy; - -import static org.junit.Assert.assertEquals; - -import org.apache.log4j.Logger; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; - -/** - * Used to test log4j-over-slf4j - * - * @author Ceki Gulcu - * - */ -public class Log4jInvocation { - - static final String HELLO = "Hello"; - - DummyLBAppender listAppender; - LoggerContext lc; - ch.qos.logback.classic.Logger rootLogger; - - @Before - public void fixture() { - lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - lc.reset(); - - listAppender = new DummyLBAppender(); - listAppender.setContext(lc); - listAppender.start(); - rootLogger = lc.getLogger("root"); - rootLogger.addAppender(listAppender); - } - - @Test - public void basic() { - assertEquals(0, listAppender.list.size()); - - Logger logger = Logger.getLogger("basic-test"); - logger.debug(HELLO); - - assertEquals(1, listAppender.list.size()); - ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); - assertEquals(HELLO, event.getMessage()); - } - - @Test - public void callerData() { - assertEquals(0, listAppender.list.size()); - - PatternLayout pl = new PatternLayout(); - pl.setPattern("%-5level [%class] %logger - %msg"); - pl.setContext(lc); - pl.start(); - listAppender.layout = pl; - - Logger logger = Logger.getLogger("basic-test"); - logger.trace("none"); - assertEquals(0, listAppender.list.size()); - - rootLogger.setLevel(Level.TRACE); - logger.trace(HELLO); - assertEquals(1, listAppender.list.size()); - - ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); - assertEquals(HELLO, event.getMessage()); - - assertEquals(1, listAppender.stringList.size()); - assertEquals("TRACE [" + Log4jInvocation.class.getName() - + "] basic-test - Hello", listAppender.stringList.get(0)); - } -} +/** + * 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 org.dummy; + +import static org.junit.Assert.assertEquals; + +import org.apache.log4j.Logger; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; + +/** + * Used to test log4j-over-slf4j + * + * @author Ceki Gulcu + * + */ +public class Log4jInvocation { + + static final String HELLO = "Hello"; + + DummyLBAppender listAppender; + LoggerContext lc; + ch.qos.logback.classic.Logger rootLogger; + + @Before + public void fixture() { + lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + lc.reset(); + + listAppender = new DummyLBAppender(); + listAppender.setContext(lc); + listAppender.start(); + rootLogger = lc.getLogger("root"); + rootLogger.addAppender(listAppender); + } + + @Test + public void basic() { + assertEquals(0, listAppender.list.size()); + + Logger logger = Logger.getLogger("basic-test"); + logger.debug(HELLO); + + assertEquals(1, listAppender.list.size()); + ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); + assertEquals(HELLO, event.getMessage()); + } + + @Test + public void callerData() { + assertEquals(0, listAppender.list.size()); + + PatternLayout pl = new PatternLayout(); + pl.setPattern("%-5level [%class] %logger - %msg"); + pl.setContext(lc); + pl.start(); + listAppender.layout = pl; + + Logger logger = Logger.getLogger("basic-test"); + logger.trace("none"); + assertEquals(0, listAppender.list.size()); + + rootLogger.setLevel(Level.TRACE); + logger.trace(HELLO); + assertEquals(1, listAppender.list.size()); + + ILoggingEvent event = (ILoggingEvent) listAppender.list.get(0); + assertEquals(HELLO, event.getMessage()); + + assertEquals(1, listAppender.stringList.size()); + assertEquals("TRACE [" + Log4jInvocation.class.getName() + + "] basic-test - Hello", listAppender.stringList.get(0)); + } +} diff --git a/logback-classic/src/test/java/org/slf4j/LoggerFactoryFriend.java b/logback-classic/src/test/java/org/slf4j/LoggerFactoryFriend.java index f5a0e183e01695052da396863c62f3352cb2f4aa..8dbd704043aee5512b90339c44ae61e63b2c9dda 100644 --- a/logback-classic/src/test/java/org/slf4j/LoggerFactoryFriend.java +++ b/logback-classic/src/test/java/org/slf4j/LoggerFactoryFriend.java @@ -1,20 +1,20 @@ -/** - * 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 org.slf4j; - -public class LoggerFactoryFriend { - static public void reset() { - LoggerFactory.reset(); - } -} +/** + * 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 org.slf4j; + +public class LoggerFactoryFriend { + static public void reset() { + LoggerFactory.reset(); + } +} diff --git a/logback-classic/src/test/java/org/slf4j/impl/LogbackMDCAdapterTest.java b/logback-classic/src/test/java/org/slf4j/impl/LogbackMDCAdapterTest.java index 6159243ca3e849f5730aa4fdb31bc68e628d3f0c..8546cca0c16a026540db2f610a1a2c9ddb9fd766 100644 --- a/logback-classic/src/test/java/org/slf4j/impl/LogbackMDCAdapterTest.java +++ b/logback-classic/src/test/java/org/slf4j/impl/LogbackMDCAdapterTest.java @@ -1,130 +1,130 @@ -/** - * 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 org.slf4j.impl; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.util.HashMap; -import java.util.Random; - -import org.junit.Test; -import org.slf4j.MDC; - -public class LogbackMDCAdapterTest { - - final static String A_SUFFIX = "A_SUFFIX"; - - int diff = new Random().nextInt(); - - /** - * Test that CopyOnInheritThreadLocal does not barf when the - * MDC hashmap is null - * - * @throws InterruptedException - */ - @Test - public void lbclassic77() throws InterruptedException { - LogbackMDCAdapter lma = new LogbackMDCAdapter(); - - HashMap parentHM = getHashMapFromMDCAdapter(lma); - assertNull(parentHM); - - ChildThreadForMDCAdapter childThread = new ChildThreadForMDCAdapter(lma); - childThread.start(); - childThread.join(); - assertTrue(childThread.successul); - assertNull(childThread.childHM); - } - - class ChildThreadForMDCAdapter extends Thread { - - LogbackMDCAdapter logbackMDCAdapter; - boolean successul; - HashMap childHM; - - ChildThreadForMDCAdapter(LogbackMDCAdapter logbackMDCAdapter) { - this.logbackMDCAdapter = logbackMDCAdapter; - } - - @Override - public void run() { - childHM = getHashMapFromMDCAdapter(logbackMDCAdapter); - logbackMDCAdapter.get(""); - successul = true; - } - } - - // ================================================= - /** - * Test that LogbackMDCAdapter copies its hashmap when a child - * thread inherits it. - * - * @throws InterruptedException - */ - @Test - public void copyOnInheritence() throws InterruptedException { - String mdcKey = "x" + diff; - String otherMDCKey = "o" + diff; - MDC.put(mdcKey, mdcKey + A_SUFFIX); - - HashMap parentHM = getHashMapFromMDC(); - - ChildThreadForMDC childThread = new ChildThreadForMDC(mdcKey, otherMDCKey); - childThread.start(); - childThread.join(); - - assertNull(MDC.get(otherMDCKey)); - assertTrue(childThread.successul); - assertTrue(parentHM != childThread.childHM); - } - - - class ChildThreadForMDC extends Thread { - - String mdcKey; - String otherMDCKey; - boolean successul; - HashMap childHM; - - ChildThreadForMDC(String mdcKey, String otherMDCKey) { - this.mdcKey = mdcKey; - this.otherMDCKey = otherMDCKey; - } - - @Override - public void run() { - childHM = getHashMapFromMDC(); - - MDC.put(otherMDCKey, otherMDCKey + A_SUFFIX); - assertNotNull(MDC.get(mdcKey)); - assertEquals(mdcKey + A_SUFFIX, MDC.get(mdcKey)); - assertEquals(otherMDCKey + A_SUFFIX, MDC.get(otherMDCKey)); - successul = true; - } - } - - HashMap getHashMapFromMDCAdapter(LogbackMDCAdapter lma) { - CopyOnInheritThreadLocal copyOnInheritThreadLocal = lma.copyOnInheritThreadLocal; - return copyOnInheritThreadLocal.get(); - } - - HashMap getHashMapFromMDC() { - LogbackMDCAdapter lma = (LogbackMDCAdapter) MDC.getMDCAdapter(); - CopyOnInheritThreadLocal copyOnInheritThreadLocal = lma.copyOnInheritThreadLocal; - return copyOnInheritThreadLocal.get(); - } -} +/** + * 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 org.slf4j.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Random; + +import org.junit.Test; +import org.slf4j.MDC; + +public class LogbackMDCAdapterTest { + + final static String A_SUFFIX = "A_SUFFIX"; + + int diff = new Random().nextInt(); + + /** + * Test that CopyOnInheritThreadLocal does not barf when the + * MDC hashmap is null + * + * @throws InterruptedException + */ + @Test + public void lbclassic77() throws InterruptedException { + LogbackMDCAdapter lma = new LogbackMDCAdapter(); + + HashMap parentHM = getHashMapFromMDCAdapter(lma); + assertNull(parentHM); + + ChildThreadForMDCAdapter childThread = new ChildThreadForMDCAdapter(lma); + childThread.start(); + childThread.join(); + assertTrue(childThread.successul); + assertNull(childThread.childHM); + } + + class ChildThreadForMDCAdapter extends Thread { + + LogbackMDCAdapter logbackMDCAdapter; + boolean successul; + HashMap childHM; + + ChildThreadForMDCAdapter(LogbackMDCAdapter logbackMDCAdapter) { + this.logbackMDCAdapter = logbackMDCAdapter; + } + + @Override + public void run() { + childHM = getHashMapFromMDCAdapter(logbackMDCAdapter); + logbackMDCAdapter.get(""); + successul = true; + } + } + + // ================================================= + /** + * Test that LogbackMDCAdapter copies its hashmap when a child + * thread inherits it. + * + * @throws InterruptedException + */ + @Test + public void copyOnInheritence() throws InterruptedException { + String mdcKey = "x" + diff; + String otherMDCKey = "o" + diff; + MDC.put(mdcKey, mdcKey + A_SUFFIX); + + HashMap parentHM = getHashMapFromMDC(); + + ChildThreadForMDC childThread = new ChildThreadForMDC(mdcKey, otherMDCKey); + childThread.start(); + childThread.join(); + + assertNull(MDC.get(otherMDCKey)); + assertTrue(childThread.successul); + assertTrue(parentHM != childThread.childHM); + } + + + class ChildThreadForMDC extends Thread { + + String mdcKey; + String otherMDCKey; + boolean successul; + HashMap childHM; + + ChildThreadForMDC(String mdcKey, String otherMDCKey) { + this.mdcKey = mdcKey; + this.otherMDCKey = otherMDCKey; + } + + @Override + public void run() { + childHM = getHashMapFromMDC(); + + MDC.put(otherMDCKey, otherMDCKey + A_SUFFIX); + assertNotNull(MDC.get(mdcKey)); + assertEquals(mdcKey + A_SUFFIX, MDC.get(mdcKey)); + assertEquals(otherMDCKey + A_SUFFIX, MDC.get(otherMDCKey)); + successul = true; + } + } + + HashMap getHashMapFromMDCAdapter(LogbackMDCAdapter lma) { + CopyOnInheritThreadLocal copyOnInheritThreadLocal = lma.copyOnInheritThreadLocal; + return copyOnInheritThreadLocal.get(); + } + + HashMap getHashMapFromMDC() { + LogbackMDCAdapter lma = (LogbackMDCAdapter) MDC.getMDCAdapter(); + CopyOnInheritThreadLocal copyOnInheritThreadLocal = lma.copyOnInheritThreadLocal; + return copyOnInheritThreadLocal.get(); + } +} diff --git a/logback-classic/src/test/java/org/slf4j/impl/PackageTest.java b/logback-classic/src/test/java/org/slf4j/impl/PackageTest.java index 2cbdfeee98f8c3be1d7312047161f8b3cf60a0f6..6f6bc9465cdf9c6f4ebe9f5adc1fc97c530f7e0e 100644 --- a/logback-classic/src/test/java/org/slf4j/impl/PackageTest.java +++ b/logback-classic/src/test/java/org/slf4j/impl/PackageTest.java @@ -1,26 +1,26 @@ -/** - * 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 org.slf4j.impl; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -import ch.qos.logback.classic.LoggerPerfTest; - -@RunWith(Suite.class) -@SuiteClasses( { RecursiveInitializationTest.class, LoggerPerfTest.class}) -public class PackageTest { - +/** + * 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 org.slf4j.impl; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import ch.qos.logback.classic.LoggerPerfTest; + +@RunWith(Suite.class) +@SuiteClasses( { RecursiveInitializationTest.class, LoggerPerfTest.class}) +public class PackageTest { + } \ No newline at end of file diff --git a/logback-classic/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java b/logback-classic/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java index ab21958c36bd7985f5b16c647eccfab8cb0281fd..c163434e518b41245395b732415ef1b1cd5263a7 100644 --- a/logback-classic/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java +++ b/logback-classic/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java @@ -1,64 +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 org.slf4j.impl; - -import static org.junit.Assert.assertEquals; - -import java.util.Random; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.LoggerFactoryFriend; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.util.ContextInitializer; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.util.StatusPrinter; - -public class RecursiveInitializationTest { - - int diff = new Random().nextInt(); - - @Before - public void setUp() throws Exception { - System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, - "recursiveInit.xml"); - StaticLoggerBinderFriend.reset(); - LoggerFactoryFriend.reset(); - - } - - @After - public void tearDown() throws Exception { - System.clearProperty(ContextInitializer.CONFIG_FILE_PROPERTY); - } - - @Test - public void recursiveLogbackInitialization() { - Logger logger = LoggerFactory.getLogger("RecursiveInitializationTest" - + diff); - logger.info("RecursiveInitializationTest"); - - LoggerContext loggerContext = (LoggerContext) LoggerFactory - .getILoggerFactory(); - StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); - StatusManager sm = loggerContext.getStatusManager(); - assertEquals("Was expecting no errors", Status.WARN, sm.getLevel()); - } - -} +/** + * 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 org.slf4j.impl; + +import static org.junit.Assert.assertEquals; + +import java.util.Random; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.LoggerFactoryFriend; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.util.ContextInitializer; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.StatusPrinter; + +public class RecursiveInitializationTest { + + int diff = new Random().nextInt(); + + @Before + public void setUp() throws Exception { + System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, + "recursiveInit.xml"); + StaticLoggerBinderFriend.reset(); + LoggerFactoryFriend.reset(); + + } + + @After + public void tearDown() throws Exception { + System.clearProperty(ContextInitializer.CONFIG_FILE_PROPERTY); + } + + @Test + public void recursiveLogbackInitialization() { + Logger logger = LoggerFactory.getLogger("RecursiveInitializationTest" + + diff); + logger.info("RecursiveInitializationTest"); + + LoggerContext loggerContext = (LoggerContext) LoggerFactory + .getILoggerFactory(); + StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); + StatusManager sm = loggerContext.getStatusManager(); + assertEquals("Was expecting no errors", Status.WARN, sm.getLevel()); + } + +} diff --git a/logback-classic/src/test/java/org/slf4j/impl/RecursiveLBAppender.java b/logback-classic/src/test/java/org/slf4j/impl/RecursiveLBAppender.java index 20bf47456231f36408f57a2c524c32b070bc72cc..c444d9c56caee5e0d1c9d5fccd1506567d80f04a 100644 --- a/logback-classic/src/test/java/org/slf4j/impl/RecursiveLBAppender.java +++ b/logback-classic/src/test/java/org/slf4j/impl/RecursiveLBAppender.java @@ -1,57 +1,57 @@ -/** - * 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 org.slf4j.impl; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; - -public class RecursiveLBAppender extends AppenderBase { - - public List list = new ArrayList(); - public List stringList = new ArrayList(); - - PatternLayout layout; - - public RecursiveLBAppender() { - this(null); - } - - public RecursiveLBAppender(PatternLayout layout) { - this.layout = layout; - } - - @Override - public void start() { - int diff = new Random().nextInt(); - Logger logger = LoggerFactory.getLogger("ResursiveLBAppender"+diff); - logger.info("testing"); - super.start(); - } - - protected void append(ILoggingEvent e) { - list.add(e); - if(layout != null) { - String s = layout.doLayout(e); - stringList.add(s); - } - } -} +/** + * 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 org.slf4j.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; + +public class RecursiveLBAppender extends AppenderBase { + + public List list = new ArrayList(); + public List stringList = new ArrayList(); + + PatternLayout layout; + + public RecursiveLBAppender() { + this(null); + } + + public RecursiveLBAppender(PatternLayout layout) { + this.layout = layout; + } + + @Override + public void start() { + int diff = new Random().nextInt(); + Logger logger = LoggerFactory.getLogger("ResursiveLBAppender"+diff); + logger.info("testing"); + super.start(); + } + + protected void append(ILoggingEvent e) { + list.add(e); + if(layout != null) { + String s = layout.doLayout(e); + stringList.add(s); + } + } +} diff --git a/logback-classic/src/test/java/org/slf4j/impl/StaticLoggerBinderFriend.java b/logback-classic/src/test/java/org/slf4j/impl/StaticLoggerBinderFriend.java index e9c19e721cd80475a1d7458dcbe6ecd18825d208..39e5bdf7b616349b8a0205e0910728858b3454ce 100644 --- a/logback-classic/src/test/java/org/slf4j/impl/StaticLoggerBinderFriend.java +++ b/logback-classic/src/test/java/org/slf4j/impl/StaticLoggerBinderFriend.java @@ -1,29 +1,29 @@ -/** - * 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 org.slf4j.impl; - -/** - * This class grants public access to package protected methods of - * StaticLoggerBinder. Used for testing purposes. - * - * @author Ceki Gulcu - * - */ -public class StaticLoggerBinderFriend { - - static public void reset() { - StaticLoggerBinder.reset(); - } - -} +/** + * 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 org.slf4j.impl; + +/** + * This class grants public access to package protected methods of + * StaticLoggerBinder. Used for testing purposes. + * + * @author Ceki Gulcu + * + */ +public class StaticLoggerBinderFriend { + + static public void reset() { + StaticLoggerBinder.reset(); + } + +} diff --git a/logback-classic/src/test/resources/BOO_logback-test.xml b/logback-classic/src/test/resources/BOO_logback-test.xml index 330433dc1531179a8ccba89a117953b82f30e039..612d3f92fe7c82e87cb7777e952a8668cc13616e 100644 --- a/logback-classic/src/test/resources/BOO_logback-test.xml +++ b/logback-classic/src/test/resources/BOO_logback-test.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/resources/README.txt b/logback-classic/src/test/resources/README.txt index dc94bfa2c187902164658bf538abec791a3a8788..baaf5317ecc737cb24d0e9b31e8964f85b56022d 100644 --- a/logback-classic/src/test/resources/README.txt +++ b/logback-classic/src/test/resources/README.txt @@ -1,5 +1,5 @@ - -Few test cases InitializationTest requite the presence of logback.xml or logback-test.xml -to be present in the classpath. However, this conflict with the logback-examples module. -In particular, when users attempt to follow the manual by importing the project in an IDE + +Few test cases InitializationTest requite the presence of logback.xml or logback-test.xml +to be present in the classpath. However, this conflict with the logback-examples module. +In particular, when users attempt to follow the manual by importing the project in an IDE such as Eclipse. \ No newline at end of file diff --git a/logback-classic/src/test/resources/autoConfigAsResource.xml b/logback-classic/src/test/resources/autoConfigAsResource.xml index 8c2ca779bc783fbd1aa43732e7fb73ed5f39610d..a8f5e7a5ccd65cee0d8c8f1ced1f2ec0e4ca5cae 100644 --- a/logback-classic/src/test/resources/autoConfigAsResource.xml +++ b/logback-classic/src/test/resources/autoConfigAsResource.xml @@ -1,15 +1,15 @@ - - - - - - - %msg%n" - - - - - - - + + + + + + + %msg%n" + + + + + + + diff --git a/logback-classic/src/test/resources/corpus/origin_of_species.txt b/logback-classic/src/test/resources/corpus/origin_of_species.txt index e39b0cc1e7a519850be317734edacddf50cda948..3fecbf5d54942379c16acb1440104e1b6ef28dcc 100644 --- a/logback-classic/src/test/resources/corpus/origin_of_species.txt +++ b/logback-classic/src/test/resources/corpus/origin_of_species.txt @@ -1,1276 +1,1276 @@ -Darwin, Charles, 1809-1882 - -ON THE ORIGIN OF SPECIES. - -INTRODUCTION. - -When on board H.M.S. 'Beagle,' as naturalist, I was much struck with -certain facts in the distribution of the inhabitants of South America, -and in the geological relations of the present to the past inhabitants -of that continent. These facts seemed to me to throw some light on the -origin of species--that mystery of mysteries, as it has been called by -one of our greatest philosophers. On my return home, it occurred to -me, in 1837, that something might perhaps be made out on this question -by patiently accumulating and reflecting on all sorts of facts which -could possibly have any bearing on it. After five years' work I -allowed myself to speculate on the subject, and drew up some short -notes; these I enlarged in 1844 into a sketch of the conclusions, -which then seemed to me probable: from that period to the present day -I have steadily pursued the same object. I hope that I may be excused -for entering on these personal details, as I give them to show that I -have not been hasty in coming to a decision. - -My work is now nearly finished; but as it will take me two or three -more years to complete it, and as my health is far from strong, I have -been urged to publish this Abstract. I have more especially been -induced to do this, as Mr. Wallace, who is now studying the natural -history of the Malay archipelago, has arrived at almost exactly the -same general conclusions that I have on the origin of species. Last -year he sent to me a memoir on this subject, with a request that I -would forward it to Sir Charles Lyell, who sent it to the Linnean -Society, and it is published in the third volume of the Journal of -that Society. Sir C. Lyell and Dr. Hooker, who both knew of my -work--the latter having read my sketch of 1844--honoured me by -thinking it advisable to publish, with Mr. Wallace's excellent memoir, -some brief extracts from my manuscripts. - -This Abstract, which I now publish, must necessarily be imperfect. I -cannot here give references and authorities for my several statements; -and I must trust to the reader reposing some confidence in my -accuracy. No doubt errors will have crept in, though I hope I have -always been cautious in trusting to good authorities alone. I can here -give only the general conclusions at which I have arrived, with a few -facts in illustration, but which, I hope, in most cases will suffice. -No one can feel more sensible than I do of the necessity of hereafter -publishing in detail all the facts, with references, on which my -conclusions have been grounded; and I hope in a future work to do -this. For I am well aware that scarcely a single point is discussed in -this volume on which facts cannot be adduced, often apparently leading -to conclusions directly opposite to those at which I have arrived. A -fair result can be obtained only by fully stating and balancing the -facts and arguments on both sides of each question; and this cannot -possibly be here done. - -I much regret that want of space prevents my having the satisfaction -of acknowledging the generous assistance which I have received from -very many naturalists, some of them personally unknown to me. I -cannot, however, let this opportunity pass without expressing my deep -obligations to Dr. Hooker, who for the last fifteen years has aided me -in every possible way by his large stores of knowledge and his -excellent judgment. - -In considering the Origin of Species, it is quite conceivable that a -naturalist, reflecting on the mutual affinities of organic beings, on -their embryological relations, their geographical distribution, -geological succession, and other such facts, might come to the -conclusion that each species had not been independently created, but -had descended, like varieties, from other species. Nevertheless, such -a conclusion, even if well founded, would be unsatisfactory, until it -could be shown how the innumerable species inhabiting this world have -been modified, so as to acquire that perfection of structure and -coadaptation which most justly excites our admiration. Naturalists -continually refer to external conditions, such as climate, food, etc., -as the only possible cause of variation. In one very limited sense, as -we shall hereafter see, this may be true; but it is preposterous to -attribute to mere external conditions, the structure, for instance, of -the woodpecker, with its feet, tail, beak, and tongue, so admirably -adapted to catch insects under the bark of trees. In the case of the -misseltoe, which draws its nourishment from certain trees, which has -seeds that must be transported by certain birds, and which has flowers -with separate sexes absolutely requiring the agency of certain insects -to bring pollen from one flower to the other, it is equally -preposterous to account for the structure of this parasite, with its -relations to several distinct organic beings, by the effects of -external conditions, or of habit, or of the volition of the plant -itself. - -The author of the 'Vestiges of Creation' would, I presume, say that, -after a certain unknown number of generations, some bird had given -birth to a woodpecker, and some plant to the misseltoe, and that these -had been produced perfect as we now see them; but this assumption -seems to me to be no explanation, for it leaves the case of the -coadaptations of organic beings to each other and to their physical -conditions of life, untouched and unexplained. - -It is, therefore, of the highest importance to gain a clear insight -into the means of modification and coadaptation. At the commencement -of my observations it seemed to me probable that a careful study of -domesticated animals and of cultivated plants would offer the best -chance of making out this obscure problem. Nor have I been -disappointed; in this and in all other perplexing cases I have -invariably found that our knowledge, imperfect though it be, of -variation under domestication, afforded the best and safest clue. I -may venture to express my conviction of the high value of such -studies, although they have been very commonly neglected by -naturalists. - -From these considerations, I shall devote the first chapter of this -Abstract to Variation under Domestication. We shall thus see that a -large amount of hereditary modification is at least possible, and, -what is equally or more important, we shall see how great is the power -of man in accumulating by his Selection successive slight variations. -I will then pass on to the variability of species in a state of -nature; but I shall, unfortunately, be compelled to treat this subject -far too briefly, as it can be treated properly only by giving long -catalogues of facts. We shall, however, be enabled to discuss what -circumstances are most favourable to variation. In the next chapter -the Struggle for Existence amongst all organic beings throughout the -world, which inevitably follows from their high geometrical powers of -increase, will be treated of. This is the doctrine of Malthus, applied -to the whole animal and vegetable kingdoms. As many more individuals -of each species are born than can possibly survive; and as, -consequently, there is a frequently recurring struggle for existence, -it follows that any being, if it vary however slightly in any manner -profitable to itself, under the complex and sometimes varying -conditions of life, will have a better chance of surviving, and thus -be NATURALLY SELECTED. From the strong principle of inheritance, any -selected variety will tend to propagate its new and modified form. - -This fundamental subject of Natural Selection will be treated at some -length in the fourth chapter; and we shall then see how Natural -Selection almost inevitably causes much Extinction of the less -improved forms of life and induces what I have called Divergence of -Character. In the next chapter I shall discuss the complex and little -known laws of variation and of correlation of growth. In the four -succeeding chapters, the most apparent and gravest difficulties on the -theory will be given: namely, first, the difficulties of transitions, -or in understanding how a simple being or a simple organ can be -changed and perfected into a highly developed being or elaborately -constructed organ; secondly the subject of Instinct, or the mental -powers of animals, thirdly, Hybridism, or the infertility of species -and the fertility of varieties when intercrossed; and fourthly, the -imperfection of the Geological Record. In the next chapter I shall -consider the geological succession of organic beings throughout time; -in the eleventh and twelfth, their geographical distribution -throughout space; in the thirteenth, their classification or mutual -affinities, both when mature and in an embryonic condition. In the -last chapter I shall give a brief recapitulation of the whole work, -and a few concluding remarks. - -No one ought to feel surprise at much remaining as yet unexplained in -regard to the origin of species and varieties, if he makes due -allowance for our profound ignorance in regard to the mutual relations -of all the beings which live around us. Who can explain why one -species ranges widely and is very numerous, and why another allied -species has a narrow range and is rare? Yet these relations are of the -highest importance, for they determine the present welfare, and, as I -believe, the future success and modification of every inhabitant of -this world. Still less do we know of the mutual relations of the -innumerable inhabitants of the world during the many past geological -epochs in its history. Although much remains obscure, and will long -remain obscure, I can entertain no doubt, after the most deliberate -study and dispassionate judgment of which I am capable, that the view -which most naturalists entertain, and which I formerly -entertained--namely, that each species has been independently -created--is erroneous. I am fully convinced that species are not -immutable; but that those belonging to what are called the same genera -are lineal descendants of some other and generally extinct species, in -the same manner as the acknowledged varieties of any one species are -the descendants of that species. Furthermore, I am convinced that -Natural Selection has been the main but not exclusive means of -modification. - -CHAPTER 1. VARIATION UNDER DOMESTICATION. - -Causes of Variability. -Effects of Habit. -Correlation of Growth. -Inheritance. -Character of Domestic Varieties. -Difficulty of distinguishing between Varieties and Species. -Origin of Domestic Varieties from one or more Species. -Domestic Pigeons, their Differences and Origin. -Principle of Selection anciently followed, its Effects. -Methodical and Unconscious Selection. -Unknown Origin of our Domestic Productions. -Circumstances favourable to Man's power of Selection. - -When we look to the individuals of the same variety or sub-variety of -our older cultivated plants and animals, one of the first points which -strikes us, is, that they generally differ much more from each other, -than do the individuals of any one species or variety in a state of -nature. When we reflect on the vast diversity of the plants and -animals which have been cultivated, and which have varied during all -ages under the most different climates and treatment, I think we are -driven to conclude that this greater variability is simply due to our -domestic productions having been raised under conditions of life not -so uniform as, and somewhat different from, those to which the -parent-species have been exposed under nature. There is, also, I -think, some probability in the view propounded by Andrew Knight, that -this variability may be partly connected with excess of food. It seems -pretty clear that organic beings must be exposed during several -generations to the new conditions of life to cause any appreciable -amount of variation; and that when the organisation has once begun to -vary, it generally continues to vary for many generations. No case is -on record of a variable being ceasing to be variable under -cultivation. Our oldest cultivated plants, such as wheat, still often -yield new varieties: our oldest domesticated animals are still capable -of rapid improvement or modification. - -It has been disputed at what period of life the causes of variability, -whatever they may be, generally act; whether during the early or late -period of development of the embryo, or at the instant of conception. -Geoffroy St. Hilaire's experiments show that unnatural treatment of -the embryo causes monstrosities; and monstrosities cannot be separated -by any clear line of distinction from mere variations. But I am -strongly inclined to suspect that the most frequent cause of -variability may be attributed to the male and female reproductive -elements having been affected prior to the act of conception. Several -reasons make me believe in this; but the chief one is the remarkable -effect which confinement or cultivation has on the functions of the -reproductive system; this system appearing to be far more susceptible -than any other part of the organisation, to the action of any change -in the conditions of life. Nothing is more easy than to tame an -animal, and few things more difficult than to get it to breed freely -under confinement, even in the many cases when the male and female -unite. How many animals there are which will not breed, though living -long under not very close confinement in their native country! This is -generally attributed to vitiated instincts; but how many cultivated -plants display the utmost vigour, and yet rarely or never seed! In -some few such cases it has been found out that very trifling changes, -such as a little more or less water at some particular period of -growth, will determine whether or not the plant sets a seed. I cannot -here enter on the copious details which I have collected on this -curious subject; but to show how singular the laws are which determine -the reproduction of animals under confinement, I may just mention that -carnivorous animals, even from the tropics, breed in this country -pretty freely under confinement, with the exception of the -plantigrades or bear family; whereas, carnivorous birds, with the -rarest exceptions, hardly ever lay fertile eggs. Many exotic plants -have pollen utterly worthless, in the same exact condition as in the -most sterile hybrids. When, on the one hand, we see domesticated -animals and plants, though often weak and sickly, yet breeding quite -freely under confinement; and when, on the other hand, we see -individuals, though taken young from a state of nature, perfectly -tamed, long-lived, and healthy (of which I could give numerous -instances), yet having their reproductive system so seriously affected -by unperceived causes as to fail in acting, we need not be surprised -at this system, when it does act under confinement, acting not quite -regularly, and producing offspring not perfectly like their parents or -variable. - -Sterility has been said to be the bane of horticulture; but on this -view we owe variability to the same cause which produces sterility; -and variability is the source of all the choicest productions of the -garden. I may add, that as some organisms will breed most freely under -the most unnatural conditions (for instance, the rabbit and ferret -kept in hutches), showing that their reproductive system has not been -thus affected; so will some animals and plants withstand domestication -or cultivation, and vary very slightly--perhaps hardly more than in a -state of nature. - -A long list could easily be given of "sporting plants;" by this term -gardeners mean a single bud or offset, which suddenly assumes a new -and sometimes very different character from that of the rest of the -plant. Such buds can be propagated by grafting, etc., and sometimes by -seed. These "sports" are extremely rare under nature, but far from -rare under cultivation; and in this case we see that the treatment of -the parent has affected a bud or offset, and not the ovules or pollen. -But it is the opinion of most physiologists that there is no essential -difference between a bud and an ovule in their earliest stages of -formation; so that, in fact, "sports" support my view, that -variability may be largely attributed to the ovules or pollen, or to -both, having been affected by the treatment of the parent prior to the -act of conception. These cases anyhow show that variation is not -necessarily connected, as some authors have supposed, with the act of -generation. - -Seedlings from the same fruit, and the young of the same litter, -sometimes differ considerably from each other, though both the young -and the parents, as Muller has remarked, have apparently been exposed -to exactly the same conditions of life; and this shows how unimportant -the direct effects of the conditions of life are in comparison with -the laws of reproduction, and of growth, and of inheritance; for had -the action of the conditions been direct, if any of the young had -varied, all would probably have varied in the same manner. To judge -how much, in the case of any variation, we should attribute to the -direct action of heat, moisture, light, food, etc., is most difficult: -my impression is, that with animals such agencies have produced very -little direct effect, though apparently more in the case of plants. -Under this point of view, Mr. Buckman's recent experiments on plants -seem extremely valuable. When all or nearly all the individuals -exposed to certain conditions are affected in the same way, the change -at first appears to be directly due to such conditions; but in some -cases it can be shown that quite opposite conditions produce similar -changes of structure. Nevertheless some slight amount of change may, I -think, be attributed to the direct action of the conditions of -life--as, in some cases, increased size from amount of food, colour -from particular kinds of food and from light, and perhaps the -thickness of fur from climate. - -Habit also has a decided influence, as in the period of flowering with -plants when transported from one climate to another. In animals it has -a more marked effect; for instance, I find in the domestic duck that -the bones of the wing weigh less and the bones of the leg more, in -proportion to the whole skeleton, than do the same bones in the -wild-duck; and I presume that this change may be safely attributed to -the domestic duck flying much less, and walking more, than its wild -parent. The great and inherited development of the udders in cows and -goats in countries where they are habitually milked, in comparison -with the state of these organs in other countries, is another instance -of the effect of use. Not a single domestic animal can be named which -has not in some country drooping ears; and the view suggested by some -authors, that the drooping is due to the disuse of the muscles of the -ear, from the animals not being much alarmed by danger, seems -probable. - -There are many laws regulating variation, some few of which can be -dimly seen, and will be hereafter briefly mentioned. I will here only -allude to what may be called correlation of growth. Any change in the -embryo or larva will almost certainly entail changes in the mature -animal. In monstrosities, the correlations between quite distinct -parts are very curious; and many instances are given in Isidore -Geoffroy St. Hilaire's great work on this subject. Breeders believe -that long limbs are almost always accompanied by an elongated head. -Some instances of correlation are quite whimsical; thus cats with blue -eyes are invariably deaf; colour and constitutional peculiarities go -together, of which many remarkable cases could be given amongst -animals and plants. From the facts collected by Heusinger, it appears -that white sheep and pigs are differently affected from coloured -individuals by certain vegetable poisons. Hairless dogs have imperfect -teeth; long-haired and coarse-haired animals are apt to have, as is -asserted, long or many horns; pigeons with feathered feet have skin -between their outer toes; pigeons with short beaks have small feet, -and those with long beaks large feet. Hence, if man goes on selecting, -and thus augmenting, any peculiarity, he will almost certainly -unconsciously modify other parts of the structure, owing to the -mysterious laws of the correlation of growth. - -The result of the various, quite unknown, or dimly seen laws of -variation is infinitely complex and diversified. It is well worth -while carefully to study the several treatises published on some of -our old cultivated plants, as on the hyacinth, potato, even the -dahlia, etc.; and it is really surprising to note the endless points -in structure and constitution in which the varieties and sub-varieties -differ slightly from each other. The whole organisation seems to have -become plastic, and tends to depart in some small degree from that of -the parental type. - -Any variation which is not inherited is unimportant for us. But the -number and diversity of inheritable deviations of structure, both -those of slight and those of considerable physiological importance, is -endless. Dr. Prosper Lucas's treatise, in two large volumes, is the -fullest and the best on this subject. No breeder doubts how strong is -the tendency to inheritance: like produces like is his fundamental -belief: doubts have been thrown on this principle by theoretical -writers alone. When a deviation appears not unfrequently, and we see -it in the father and child, we cannot tell whether it may not be due -to the same original cause acting on both; but when amongst -individuals, apparently exposed to the same conditions, any very rare -deviation, due to some extraordinary combination of circumstances, -appears in the parent--say, once amongst several million -individuals--and it reappears in the child, the mere doctrine of -chances almost compels us to attribute its reappearance to -inheritance. Every one must have heard of cases of albinism, prickly -skin, hairy bodies, etc., appearing in several members of the same -family. If strange and rare deviations of structure are truly -inherited, less strange and commoner deviations may be freely admitted -to be inheritable. Perhaps the correct way of viewing the whole -subject, would be, to look at the inheritance of every character -whatever as the rule, and non-inheritance as the anomaly. - -The laws governing inheritance are quite unknown; no one can say why -the same peculiarity in different individuals of the same species, and -in individuals of different species, is sometimes inherited and -sometimes not so; why the child often reverts in certain characters to -its grandfather or grandmother or other much more remote ancestor; why -a peculiarity is often transmitted from one sex to both sexes or to -one sex alone, more commonly but not exclusively to the like sex. It -is a fact of some little importance to us, that peculiarities -appearing in the males of our domestic breeds are often transmitted -either exclusively, or in a much greater degree, to males alone. A -much more important rule, which I think may be trusted, is that, at -whatever period of life a peculiarity first appears, it tends to -appear in the offspring at a corresponding age, though sometimes -earlier. In many cases this could not be otherwise: thus the inherited -peculiarities in the horns of cattle could appear only in the -offspring when nearly mature; peculiarities in the silkworm are known -to appear at the corresponding caterpillar or cocoon stage. But -hereditary diseases and some other facts make me believe that the rule -has a wider extension, and that when there is no apparent reason why a -peculiarity should appear at any particular age, yet that it does tend -to appear in the offspring at the same period at which it first -appeared in the parent. I believe this rule to be of the highest -importance in explaining the laws of embryology. These remarks are of -course confined to the first APPEARANCE of the peculiarity, and not to -its primary cause, which may have acted on the ovules or male element; -in nearly the same manner as in the crossed offspring from a -short-horned cow by a long-horned bull, the greater length of horn, -though appearing late in life, is clearly due to the male element. - -Having alluded to the subject of reversion, I may here refer to a -statement often made by naturalists--namely, that our domestic -varieties, when run wild, gradually but certainly revert in character -to their aboriginal stocks. Hence it has been argued that no -deductions can be drawn from domestic races to species in a state of -nature. I have in vain endeavoured to discover on what decisive facts -the above statement has so often and so boldly been made. There would -be great difficulty in proving its truth: we may safely conclude that -very many of the most strongly-marked domestic varieties could not -possibly live in a wild state. In many cases we do not know what the -aboriginal stock was, and so could not tell whether or not nearly -perfect reversion had ensued. It would be quite necessary, in order to -prevent the effects of intercrossing, that only a single variety -should be turned loose in its new home. Nevertheless, as our varieties -certainly do occasionally revert in some of their characters to -ancestral forms, it seems to me not improbable, that if we could -succeed in naturalising, or were to cultivate, during many -generations, the several races, for instance, of the cabbage, in very -poor soil (in which case, however, some effect would have to be -attributed to the direct action of the poor soil), that they would to -a large extent, or even wholly, revert to the wild aboriginal stock. -Whether or not the experiment would succeed, is not of great -importance for our line of argument; for by the experiment itself the -conditions of life are changed. If it could be shown that our domestic -varieties manifested a strong tendency to reversion,--that is, to lose -their acquired characters, whilst kept under unchanged conditions, and -whilst kept in a considerable body, so that free intercrossing might -check, by blending together, any slight deviations of structure, in -such case, I grant that we could deduce nothing from domestic -varieties in regard to species. But there is not a shadow of evidence -in favour of this view: to assert that we could not breed our cart and -race-horses, long and short-horned cattle, and poultry of various -breeds, and esculent vegetables, for an almost infinite number of -generations, would be opposed to all experience. I may add, that when -under nature the conditions of life do change, variations and -reversions of character probably do occur; but natural selection, as -will hereafter be explained, will determine how far the new characters -thus arising shall be preserved. - -When we look to the hereditary varieties or races of our domestic -animals and plants, and compare them with species closely allied -together, we generally perceive in each domestic race, as already -remarked, less uniformity of character than in true species. Domestic -races of the same species, also, often have a somewhat monstrous -character; by which I mean, that, although differing from each other, -and from the other species of the same genus, in several trifling -respects, they often differ in an extreme degree in some one part, -both when compared one with another, and more especially when compared -with all the species in nature to which they are nearest allied. With -these exceptions (and with that of the perfect fertility of varieties -when crossed,--a subject hereafter to be discussed), domestic races of -the same species differ from each other in the same manner as, only in -most cases in a lesser degree than, do closely-allied species of the -same genus in a state of nature. I think this must be admitted, when -we find that there are hardly any domestic races, either amongst -animals or plants, which have not been ranked by some competent judges -as mere varieties, and by other competent judges as the descendants of -aboriginally distinct species. If any marked distinction existed -between domestic races and species, this source of doubt could not so -perpetually recur. It has often been stated that domestic races do not -differ from each other in characters of generic value. I think it -could be shown that this statement is hardly correct; but naturalists -differ most widely in determining what characters are of generic -value; all such valuations being at present empirical. Moreover, on -the view of the origin of genera which I shall presently give, we have -no right to expect often to meet with generic differences in our -domesticated productions. - -When we attempt to estimate the amount of structural difference -between the domestic races of the same species, we are soon involved -in doubt, from not knowing whether they have descended from one or -several parent-species. This point, if it could be cleared up, would -be interesting; if, for instance, it could be shown that the -greyhound, bloodhound, terrier, spaniel, and bull-dog, which we all -know propagate their kind so truly, were the offspring of any single -species, then such facts would have great weight in making us doubt -about the immutability of the many very closely allied and natural -species--for instance, of the many foxes--inhabiting different -quarters of the world. I do not believe, as we shall presently see, -that all our dogs have descended from any one wild species; but, in -the case of some other domestic races, there is presumptive, or even -strong, evidence in favour of this view. - -It has often been assumed that man has chosen for domestication -animals and plants having an extraordinary inherent tendency to vary, -and likewise to withstand diverse climates. I do not dispute that -these capacities have added largely to the value of most of our -domesticated productions; but how could a savage possibly know, when -he first tamed an animal, whether it would vary in succeeding -generations, and whether it would endure other climates? Has the -little variability of the ass or guinea-fowl, or the small power of -endurance of warmth by the rein-deer, or of cold by the common camel, -prevented their domestication? I cannot doubt that if other animals -and plants, equal in number to our domesticated productions, and -belonging to equally diverse classes and countries, were taken from a -state of nature, and could be made to breed for an equal number of -generations under domestication, they would vary on an average as -largely as the parent species of our existing domesticated productions -have varied. - -In the case of most of our anciently domesticated animals and plants, -I do not think it is possible to come to any definite conclusion, -whether they have descended from one or several species. The argument -mainly relied on by those who believe in the multiple origin of our -domestic animals is, that we find in the most ancient records, more -especially on the monuments of Egypt, much diversity in the breeds; -and that some of the breeds closely resemble, perhaps are identical -with, those still existing. Even if this latter fact were found more -strictly and generally true than seems to me to be the case, what does -it show, but that some of our breeds originated there, four or five -thousand years ago? But Mr. Horner's researches have rendered it in -some degree probable that man sufficiently civilized to have -manufactured pottery existed in the valley of the Nile thirteen or -fourteen thousand years ago; and who will pretend to say how long -before these ancient periods, savages, like those of Tierra del Fuego -or Australia, who possess a semi-domestic dog, may not have existed in -Egypt? - -The whole subject must, I think, remain vague; nevertheless, I may, -without here entering on any details, state that, from geographical -and other considerations, I think it highly probable that our domestic -dogs have descended from several wild species. In regard to sheep and -goats I can form no opinion. I should think, from facts communicated -to me by Mr. Blyth, on the habits, voice, and constitution, etc., of -the humped Indian cattle, that these had descended from a different -aboriginal stock from our European cattle; and several competent -judges believe that these latter have had more than one wild parent. -With respect to horses, from reasons which I cannot give here, I am -doubtfully inclined to believe, in opposition to several authors, that -all the races have descended from one wild stock. Mr. Blyth, whose -opinion, from his large and varied stores of knowledge, I should value -more than that of almost any one, thinks that all the breeds of -poultry have proceeded from the common wild Indian fowl (Gallus -bankiva). In regard to ducks and rabbits, the breeds of which differ -considerably from each other in structure, I do not doubt that they -all have descended from the common wild duck and rabbit. - -The doctrine of the origin of our several domestic races from several -aboriginal stocks, has been carried to an absurd extreme by some -authors. They believe that every race which breeds true, let the -distinctive characters be ever so slight, has had its wild prototype. -At this rate there must have existed at least a score of species of -wild cattle, as many sheep, and several goats in Europe alone, and -several even within Great Britain. One author believes that there -formerly existed in Great Britain eleven wild species of sheep -peculiar to it! When we bear in mind that Britain has now hardly one -peculiar mammal, and France but few distinct from those of Germany and -conversely, and so with Hungary, Spain, etc., but that each of these -kingdoms possesses several peculiar breeds of cattle, sheep, etc., we -must admit that many domestic breeds have originated in Europe; for -whence could they have been derived, as these several countries do not -possess a number of peculiar species as distinct parent-stocks? So it -is in India. Even in the case of the domestic dogs of the whole world, -which I fully admit have probably descended from several wild species, -I cannot doubt that there has been an immense amount of inherited -variation. Who can believe that animals closely resembling the Italian -greyhound, the bloodhound, the bull-dog, or Blenheim spaniel, etc.--so -unlike all wild Canidae--ever existed freely in a state of nature? It -has often been loosely said that all our races of dogs have been -produced by the crossing of a few aboriginal species; but by crossing -we can get only forms in some degree intermediate between their -parents; and if we account for our several domestic races by this -process, we must admit the former existence of the most extreme forms, -as the Italian greyhound, bloodhound, bull-dog, etc., in the wild -state. Moreover, the possibility of making distinct races by crossing -has been greatly exaggerated. There can be no doubt that a race may be -modified by occasional crosses, if aided by the careful selection of -those individual mongrels, which present any desired character; but -that a race could be obtained nearly intermediate between two -extremely different races or species, I can hardly believe. Sir J. -Sebright expressly experimentised for this object, and failed. The -offspring from the first cross between two pure breeds is tolerably -and sometimes (as I have found with pigeons) extremely uniform, and -everything seems simple enough; but when these mongrels are crossed -one with another for several generations, hardly two of them will be -alike, and then the extreme difficulty, or rather utter hopelessness, -of the task becomes apparent. Certainly, a breed intermediate between -TWO VERY DISTINCT breeds could not be got without extreme care and -long-continued selection; nor can I find a single case on record of a -permanent race having been thus formed. - -ON THE BREEDS OF THE DOMESTIC PIGEON. - -Believing that it is always best to study some special group, I have, -after deliberation, taken up domestic pigeons. I have kept every breed -which I could purchase or obtain, and have been most kindly favoured -with skins from several quarters of the world, more especially by the -Honourable W. Elliot from India, and by the Honourable C. Murray from -Persia. Many treatises in different languages have been published on -pigeons, and some of them are very important, as being of considerable -antiquity. I have associated with several eminent fanciers, and have -been permitted to join two of the London Pigeon Clubs. The diversity -of the breeds is something astonishing. Compare the English carrier -and the short-faced tumbler, and see the wonderful difference in their -beaks, entailing corresponding differences in their skulls. The -carrier, more especially the male bird, is also remarkable from the -wonderful development of the carunculated skin about the head, and -this is accompanied by greatly elongated eyelids, very large external -orifices to the nostrils, and a wide gape of mouth. The short-faced -tumbler has a beak in outline almost like that of a finch; and the -common tumbler has the singular and strictly inherited habit of flying -at a great height in a compact flock, and tumbling in the air head -over heels. The runt is a bird of great size, with long, massive beak -and large feet; some of the sub-breeds of runts have very long necks, -others very long wings and tails, others singularly short tails. The -barb is allied to the carrier, but, instead of a very long beak, has a -very short and very broad one. The pouter has a much elongated body, -wings, and legs; and its enormously developed crop, which it glories -in inflating, may well excite astonishment and even laughter. The -turbit has a very short and conical beak, with a line of reversed -feathers down the breast; and it has the habit of continually -expanding slightly the upper part of the oesophagus. The Jacobin has -the feathers so much reversed along the back of the neck that they -form a hood, and it has, proportionally to its size, much elongated -wing and tail feathers. The trumpeter and laugher, as their names -express, utter a very different coo from the other breeds. The fantail -has thirty or even forty tail-feathers, instead of twelve or fourteen, -the normal number in all members of the great pigeon family; and these -feathers are kept expanded, and are carried so erect that in good -birds the head and tail touch; the oil-gland is quite aborted. Several -other less distinct breeds might have been specified. - -In the skeletons of the several breeds, the development of the bones -of the face in length and breadth and curvature differs enormously. -The shape, as well as the breadth and length of the ramus of the lower -jaw, varies in a highly remarkable manner. The number of the caudal -and sacral vertebrae vary; as does the number of the ribs, together -with their relative breadth and the presence of processes. The size -and shape of the apertures in the sternum are highly variable; so is -the degree of divergence and relative size of the two arms of the -furcula. The proportional width of the gape of mouth, the proportional -length of the eyelids, of the orifice of the nostrils, of the tongue -(not always in strict correlation with the length of beak), the size -of the crop and of the upper part of the oesophagus; the development -and abortion of the oil-gland; the number of the primary wing and -caudal feathers; the relative length of wing and tail to each other -and to the body; the relative length of leg and of the feet; the -number of scutellae on the toes, the development of skin between the -toes, are all points of structure which are variable. The period at -which the perfect plumage is acquired varies, as does the state of the -down with which the nestling birds are clothed when hatched. The shape -and size of the eggs vary. The manner of flight differs remarkably; as -does in some breeds the voice and disposition. Lastly, in certain -breeds, the males and females have come to differ to a slight degree -from each other. - -Altogether at least a score of pigeons might be chosen, which if shown -to an ornithologist, and he were told that they were wild birds, would -certainly, I think, be ranked by him as well-defined species. -Moreover, I do not believe that any ornithologist would place the -English carrier, the short-faced tumbler, the runt, the barb, pouter, -and fantail in the same genus; more especially as in each of these -breeds several truly-inherited sub-breeds, or species as he might have -called them, could be shown him. - -Great as the differences are between the breeds of pigeons, I am fully -convinced that the common opinion of naturalists is correct, namely, -that all have descended from the rock-pigeon (Columba livia), -including under this term several geographical races or sub-species, -which differ from each other in the most trifling respects. As several -of the reasons which have led me to this belief are in some degree -applicable in other cases, I will here briefly give them. If the -several breeds are not varieties, and have not proceeded from the -rock-pigeon, they must have descended from at least seven or eight -aboriginal stocks; for it is impossible to make the present domestic -breeds by the crossing of any lesser number: how, for instance, could -a pouter be produced by crossing two breeds unless one of the -parent-stocks possessed the characteristic enormous crop? The supposed -aboriginal stocks must all have been rock-pigeons, that is, not -breeding or willingly perching on trees. But besides C. livia, with -its geographical sub-species, only two or three other species of -rock-pigeons are known; and these have not any of the characters of -the domestic breeds. Hence the supposed aboriginal stocks must either -still exist in the countries where they were originally domesticated, -and yet be unknown to ornithologists; and this, considering their -size, habits, and remarkable characters, seems very improbable; or -they must have become extinct in the wild state. But birds breeding on -precipices, and good fliers, are unlikely to be exterminated; and the -common rock-pigeon, which has the same habits with the domestic -breeds, has not been exterminated even on several of the smaller -British islets, or on the shores of the Mediterranean. Hence the -supposed extermination of so many species having similar habits with -the rock-pigeon seems to me a very rash assumption. Moreover, the -several above-named domesticated breeds have been transported to all -parts of the world, and, therefore, some of them must have been -carried back again into their native country; but not one has ever -become wild or feral, though the dovecot-pigeon, which is the -rock-pigeon in a very slightly altered state, has become feral in -several places. Again, all recent experience shows that it is most -difficult to get any wild animal to breed freely under domestication; -yet on the hypothesis of the multiple origin of our pigeons, it must -be assumed that at least seven or eight species were so thoroughly -domesticated in ancient times by half-civilized man, as to be quite -prolific under confinement. - -An argument, as it seems to me, of great weight, and applicable in -several other cases, is, that the above-specified breeds, though -agreeing generally in constitution, habits, voice, colouring, and in -most parts of their structure, with the wild rock-pigeon, yet are -certainly highly abnormal in other parts of their structure: we may -look in vain throughout the whole great family of Columbidae for a -beak like that of the English carrier, or that of the short-faced -tumbler, or barb; for reversed feathers like those of the jacobin; for -a crop like that of the pouter; for tail-feathers like those of the -fantail. Hence it must be assumed not only that half-civilized man -succeeded in thoroughly domesticating several species, but that he -intentionally or by chance picked out extraordinarily abnormal -species; and further, that these very species have since all become -extinct or unknown. So many strange contingencies seem to me -improbable in the highest degree. - -Some facts in regard to the colouring of pigeons well deserve -consideration. The rock-pigeon is of a slaty-blue, and has a white -rump (the Indian sub-species, C. intermedia of Strickland, having it -bluish); the tail has a terminal dark bar, with the bases of the outer -feathers externally edged with white; the wings have two black bars; -some semi-domestic breeds and some apparently truly wild breeds have, -besides the two black bars, the wings chequered with black. These -several marks do not occur together in any other species of the whole -family. Now, in every one of the domestic breeds, taking thoroughly -well-bred birds, all the above marks, even to the white edging of the -outer tail-feathers, sometimes concur perfectly developed. Moreover, -when two birds belonging to two distinct breeds are crossed, neither -of which is blue or has any of the above-specified marks, the mongrel -offspring are very apt suddenly to acquire these characters; for -instance, I crossed some uniformly white fantails with some uniformly -black barbs, and they produced mottled brown and black birds; these I -again crossed together, and one grandchild of the pure white fantail -and pure black barb was of as beautiful a blue colour, with the white -rump, double black wing-bar, and barred and white-edged tail-feathers, -as any wild rock-pigeon! We can understand these facts, on the -well-known principle of reversion to ancestral characters, if all the -domestic breeds have descended from the rock-pigeon. But if we deny -this, we must make one of the two following highly improbable -suppositions. Either, firstly, that all the several imagined -aboriginal stocks were coloured and marked like the rock-pigeon, -although no other existing species is thus coloured and marked, so -that in each separate breed there might be a tendency to revert to the -very same colours and markings. Or, secondly, that each breed, even -the purest, has within a dozen or, at most, within a score of -generations, been crossed by the rock-pigeon: I say within a dozen or -twenty generations, for we know of no fact countenancing the belief -that the child ever reverts to some one ancestor, removed by a greater -number of generations. In a breed which has been crossed only once -with some distinct breed, the tendency to reversion to any character -derived from such cross will naturally become less and less, as in -each succeeding generation there will be less of the foreign blood; -but when there has been no cross with a distinct breed, and there is a -tendency in both parents to revert to a character, which has been lost -during some former generation, this tendency, for all that we can see -to the contrary, may be transmitted undiminished for an indefinite -number of generations. These two distinct cases are often confounded -in treatises on inheritance. - -Lastly, the hybrids or mongrels from between all the domestic breeds -of pigeons are perfectly fertile. I can state this from my own -observations, purposely made on the most distinct breeds. Now, it is -difficult, perhaps impossible, to bring forward one case of the hybrid -offspring of two animals CLEARLY DISTINCT being themselves perfectly -fertile. Some authors believe that long-continued domestication -eliminates this strong tendency to sterility: from the history of the -dog I think there is some probability in this hypothesis, if applied -to species closely related together, though it is unsupported by a -single experiment. But to extend the hypothesis so far as to suppose -that species, aboriginally as distinct as carriers, tumblers, pouters, -and fantails now are, should yield offspring perfectly fertile, inter -se, seems to me rash in the extreme. - -From these several reasons, namely, the improbability of man having -formerly got seven or eight supposed species of pigeons to breed -freely under domestication; these supposed species being quite unknown -in a wild state, and their becoming nowhere feral; these species -having very abnormal characters in certain respects, as compared with -all other Columbidae, though so like in most other respects to the -rock-pigeon; the blue colour and various marks occasionally appearing -in all the breeds, both when kept pure and when crossed; the mongrel -offspring being perfectly fertile;--from these several reasons, taken -together, I can feel no doubt that all our domestic breeds have -descended from the Columba livia with its geographical sub-species. - -In favour of this view, I may add, firstly, that C. livia, or the -rock-pigeon, has been found capable of domestication in Europe and in -India; and that it agrees in habits and in a great number of points of -structure with all the domestic breeds. Secondly, although an English -carrier or short-faced tumbler differs immensely in certain characters -from the rock-pigeon, yet by comparing the several sub-breeds of these -breeds, more especially those brought from distant countries, we can -make an almost perfect series between the extremes of structure. -Thirdly, those characters which are mainly distinctive of each breed, -for instance the wattle and length of beak of the carrier, the -shortness of that of the tumbler, and the number of tail-feathers in -the fantail, are in each breed eminently variable; and the explanation -of this fact will be obvious when we come to treat of selection. -Fourthly, pigeons have been watched, and tended with the utmost care, -and loved by many people. They have been domesticated for thousands of -years in several quarters of the world; the earliest known record of -pigeons is in the fifth Aegyptian dynasty, about 3000 B.C., as was -pointed out to me by Professor Lepsius; but Mr. Birch informs me that -pigeons are given in a bill of fare in the previous dynasty. In the -time of the Romans, as we hear from Pliny, immense prices were given -for pigeons; "nay, they are come to this pass, that they can reckon up -their pedigree and race." Pigeons were much valued by Akber Khan in -India, about the year 1600; never less than 20,000 pigeons were taken -with the court. "The monarchs of Iran and Turan sent him some very -rare birds;" and, continues the courtly historian, "His Majesty by -crossing the breeds, which method was never practised before, has -improved them astonishingly." About this same period the Dutch were as -eager about pigeons as were the old Romans. The paramount importance -of these considerations in explaining the immense amount of variation -which pigeons have undergone, will be obvious when we treat of -Selection. We shall then, also, see how it is that the breeds so often -have a somewhat monstrous character. It is also a most favourable -circumstance for the production of distinct breeds, that male and -female pigeons can be easily mated for life; and thus different breeds -can be kept together in the same aviary. - -I have discussed the probable origin of domestic pigeons at some, yet -quite insufficient, length; because when I first kept pigeons and -watched the several kinds, knowing well how true they bred, I felt -fully as much difficulty in believing that they could ever have -descended from a common parent, as any naturalist could in coming to a -similar conclusion in regard to the many species of finches, or other -large groups of birds, in nature. One circumstance has struck me much; -namely, that all the breeders of the various domestic animals and the -cultivators of plants, with whom I have ever conversed, or whose -treatises I have read, are firmly convinced that the several breeds to -which each has attended, are descended from so many aboriginally -distinct species. Ask, as I have asked, a celebrated raiser of -Hereford cattle, whether his cattle might not have descended from long -horns, and he will laugh you to scorn. I have never met a pigeon, or -poultry, or duck, or rabbit fancier, who was not fully convinced that -each main breed was descended from a distinct species. Van Mons, in -his treatise on pears and apples, shows how utterly he disbelieves -that the several sorts, for instance a Ribston-pippin or Codlin-apple, -could ever have proceeded from the seeds of the same tree. Innumerable -other examples could be given. The explanation, I think, is simple: -from long-continued study they are strongly impressed with the -differences between the several races; and though they well know that -each race varies slightly, for they win their prizes by selecting such -slight differences, yet they ignore all general arguments, and refuse -to sum up in their minds slight differences accumulated during many -successive generations. May not those naturalists who, knowing far -less of the laws of inheritance than does the breeder, and knowing no -more than he does of the intermediate links in the long lines of -descent, yet admit that many of our domestic races have descended from -the same parents--may they not learn a lesson of caution, when they -deride the idea of species in a state of nature being lineal -descendants of other species? - -SELECTION. - -Let us now briefly consider the steps by which domestic races have -been produced, either from one or from several allied species. Some -little effect may, perhaps, be attributed to the direct action of the -external conditions of life, and some little to habit; but he would be -a bold man who would account by such agencies for the differences of a -dray and race horse, a greyhound and bloodhound, a carrier and tumbler -pigeon. One of the most remarkable features in our domesticated races -is that we see in them adaptation, not indeed to the animal's or -plant's own good, but to man's use or fancy. Some variations useful to -him have probably arisen suddenly, or by one step; many botanists, for -instance, believe that the fuller's teazle, with its hooks, which -cannot be rivalled by any mechanical contrivance, is only a variety of -the wild Dipsacus; and this amount of change may have suddenly arisen -in a seedling. So it has probably been with the turnspit dog; and this -is known to have been the case with the ancon sheep. But when we -compare the dray-horse and race-horse, the dromedary and camel, the -various breeds of sheep fitted either for cultivated land or mountain -pasture, with the wool of one breed good for one purpose, and that of -another breed for another purpose; when we compare the many breeds of -dogs, each good for man in very different ways; when we compare the -game-cock, so pertinacious in battle, with other breeds so little -quarrelsome, with "everlasting layers" which never desire to sit, and -with the bantam so small and elegant; when we compare the host of -agricultural, culinary, orchard, and flower-garden races of plants, -most useful to man at different seasons and for different purposes, or -so beautiful in his eyes, we must, I think, look further than to mere -variability. We cannot suppose that all the breeds were suddenly -produced as perfect and as useful as we now see them; indeed, in -several cases, we know that this has not been their history. The key -is man's power of accumulative selection: nature gives successive -variations; man adds them up in certain directions useful to him. In -this sense he may be said to make for himself useful breeds. - -The great power of this principle of selection is not hypothetical. It -is certain that several of our eminent breeders have, even within a -single lifetime, modified to a large extent some breeds of cattle and -sheep. In order fully to realise what they have done, it is almost -necessary to read several of the many treatises devoted to this -subject, and to inspect the animals. Breeders habitually speak of an -animal's organisation as something quite plastic, which they can model -almost as they please. If I had space I could quote numerous passages -to this effect from highly competent authorities. Youatt, who was -probably better acquainted with the works of agriculturalists than -almost any other individual, and who was himself a very good judge of -an animal, speaks of the principle of selection as "that which enables -the agriculturist, not only to modify the character of his flock, but -to change it altogether. It is the magician's wand, by means of which -he may summon into life whatever form and mould he pleases." Lord -Somerville, speaking of what breeders have done for sheep, says:--"It -would seem as if they had chalked out upon a wall a form perfect in -itself, and then had given it existence." That most skilful breeder, -Sir John Sebright, used to say, with respect to pigeons, that "he -would produce any given feather in three years, but it would take him -six years to obtain head and beak." In Saxony the importance of the -principle of selection in regard to merino sheep is so fully -recognised, that men follow it as a trade: the sheep are placed on a -table and are studied, like a picture by a connoisseur; this is done -three times at intervals of months, and the sheep are each time marked -and classed, so that the very best may ultimately be selected for -breeding. - -What English breeders have actually effected is proved by the enormous -prices given for animals with a good pedigree; and these have now been -exported to almost every quarter of the world. The improvement is by -no means generally due to crossing different breeds; all the best -breeders are strongly opposed to this practice, except sometimes -amongst closely allied sub-breeds. And when a cross has been made, the -closest selection is far more indispensable even than in ordinary -cases. If selection consisted merely in separating some very distinct -variety, and breeding from it, the principle would be so obvious as -hardly to be worth notice; but its importance consists in the great -effect produced by the accumulation in one direction, during -successive generations, of differences absolutely inappreciable by an -uneducated eye--differences which I for one have vainly attempted to -appreciate. Not one man in a thousand has accuracy of eye and judgment -sufficient to become an eminent breeder. If gifted with these -qualities, and he studies his subject for years, and devotes his -lifetime to it with indomitable perseverance, he will succeed, and may -make great improvements; if he wants any of these qualities, he will -assuredly fail. Few would readily believe in the natural capacity and -years of practice requisite to become even a skilful pigeon-fancier. - -The same principles are followed by horticulturists; but the -variations are here often more abrupt. No one supposes that our -choicest productions have been produced by a single variation from the -aboriginal stock. We have proofs that this is not so in some cases, in -which exact records have been kept; thus, to give a very trifling -instance, the steadily-increasing size of the common gooseberry may be -quoted. We see an astonishing improvement in many florists' flowers, -when the flowers of the present day are compared with drawings made -only twenty or thirty years ago. When a race of plants is once pretty -well established, the seed-raisers do not pick out the best plants, -but merely go over their seed-beds, and pull up the "rogues," as they -call the plants that deviate from the proper standard. With animals -this kind of selection is, in fact, also followed; for hardly any one -is so careless as to allow his worst animals to breed. - -In regard to plants, there is another means of observing the -accumulated effects of selection--namely, by comparing the diversity -of flowers in the different varieties of the same species in the -flower-garden; the diversity of leaves, pods, or tubers, or whatever -part is valued, in the kitchen-garden, in comparison with the flowers -of the same varieties; and the diversity of fruit of the same species -in the orchard, in comparison with the leaves and flowers of the same -set of varieties. See how different the leaves of the cabbage are, and -how extremely alike the flowers; how unlike the flowers of the -heartsease are, and how alike the leaves; how much the fruit of the -different kinds of gooseberries differ in size, colour, shape, and -hairiness, and yet the flowers present very slight differences. It is -not that the varieties which differ largely in some one point do not -differ at all in other points; this is hardly ever, perhaps never, the -case. The laws of correlation of growth, the importance of which -should never be overlooked, will ensure some differences; but, as a -general rule, I cannot doubt that the continued selection of slight -variations, either in the leaves, the flowers, or the fruit, will -produce races differing from each other chiefly in these characters. - -It may be objected that the principle of selection has been reduced to -methodical practice for scarcely more than three-quarters of a -century; it has certainly been more attended to of late years, and -many treatises have been published on the subject; and the result, I -may add, has been, in a corresponding degree, rapid and important. But -it is very far from true that the principle is a modern discovery. I -could give several references to the full acknowledgment of the -importance of the principle in works of high antiquity. In rude and -barbarous periods of English history choice animals were often -imported, and laws were passed to prevent their exportation: the -destruction of horses under a certain size was ordered, and this may -be compared to the "roguing" of plants by nurserymen. The principle of -selection I find distinctly given in an ancient Chinese encyclopaedia. -Explicit rules are laid down by some of the Roman classical writers. -From passages in Genesis, it is clear that the colour of domestic -animals was at that early period attended to. Savages now sometimes -cross their dogs with wild canine animals, to improve the breed, and -they formerly did so, as is attested by passages in Pliny. The savages -in South Africa match their draught cattle by colour, as do some of -the Esquimaux their teams of dogs. Livingstone shows how much good -domestic breeds are valued by the negroes of the interior of Africa -who have not associated with Europeans. Some of these facts do not -show actual selection, but they show that the breeding of domestic -animals was carefully attended to in ancient times, and is now -attended to by the lowest savages. It would, indeed, have been a -strange fact, had attention not been paid to breeding, for the -inheritance of good and bad qualities is so obvious. - -At the present time, eminent breeders try by methodical selection, -with a distinct object in view, to make a new strain or sub-breed, -superior to anything existing in the country. But, for our purpose, a -kind of Selection, which may be called Unconscious, and which results -from every one trying to possess and breed from the best individual -animals, is more important. Thus, a man who intends keeping pointers -naturally tries to get as good dogs as he can, and afterwards breeds -from his own best dogs, but he has no wish or expectation of -permanently altering the breed. Nevertheless I cannot doubt that this -process, continued during centuries, would improve and modify any -breed, in the same way as Bakewell, Collins, etc., by this very same -process, only carried on more methodically, did greatly modify, even -during their own lifetimes, the forms and qualities of their cattle. -Slow and insensible changes of this kind could never be recognised -unless actual measurements or careful drawings of the breeds in -question had been made long ago, which might serve for comparison. In -some cases, however, unchanged or but little changed individuals of -the same breed may be found in less civilised districts, where the -breed has been less improved. There is reason to believe that King -Charles's spaniel has been unconsciously modified to a large extent -since the time of that monarch. Some highly competent authorities are -convinced that the setter is directly derived from the spaniel, and -has probably been slowly altered from it. It is known that the English -pointer has been greatly changed within the last century, and in this -case the change has, it is believed, been chiefly effected by crosses -with the fox-hound; but what concerns us is, that the change has been -effected unconsciously and gradually, and yet so effectually, that, -though the old Spanish pointer certainly came from Spain, Mr. Borrow -has not seen, as I am informed by him, any native dog in Spain like -our pointer. - -By a similar process of selection, and by careful training, the whole -body of English racehorses have come to surpass in fleetness and size -the parent Arab stock, so that the latter, by the regulations for the -Goodwood Races, are favoured in the weights they carry. Lord Spencer -and others have shown how the cattle of England have increased in -weight and in early maturity, compared with the stock formerly kept in -this country. By comparing the accounts given in old pigeon treatises -of carriers and tumblers with these breeds as now existing in Britain, -India, and Persia, we can, I think, clearly trace the stages through -which they have insensibly passed, and come to differ so greatly from -the rock-pigeon. - -Youatt gives an excellent illustration of the effects of a course of -selection, which may be considered as unconsciously followed, in so -far that the breeders could never have expected or even have wished to -have produced the result which ensued--namely, the production of two -distinct strains. The two flocks of Leicester sheep kept by Mr. -Buckley and Mr. Burgess, as Mr. Youatt remarks, "have been purely bred -from the original stock of Mr. Bakewell for upwards of fifty years. -There is not a suspicion existing in the mind of any one at all -acquainted with the subject that the owner of either of them has -deviated in any one instance from the pure blood of Mr. Bakewell's -flock, and yet the difference between the sheep possessed by these two -gentlemen is so great that they have the appearance of being quite -different varieties." - -If there exist savages so barbarous as never to think of the inherited -character of the offspring of their domestic animals, yet any one -animal particularly useful to them, for any special purpose, would be -carefully preserved during famines and other accidents, to which -savages are so liable, and such choice animals would thus generally -leave more offspring than the inferior ones; so that in this case -there would be a kind of unconscious selection going on. We see the -value set on animals even by the barbarians of Tierra del Fuego, by -their killing and devouring their old women, in times of dearth, as of -less value than their dogs. - -In plants the same gradual process of improvement, through the -occasional preservation of the best individuals, whether or not -sufficiently distinct to be ranked at their first appearance as -distinct varieties, and whether or not two or more species or races -have become blended together by crossing, may plainly be recognised in -the increased size and beauty which we now see in the varieties of the -heartsease, rose, pelargonium, dahlia, and other plants, when compared -with the older varieties or with their parent-stocks. No one would -ever expect to get a first-rate heartsease or dahlia from the seed of -a wild plant. No one would expect to raise a first-rate melting pear -from the seed of a wild pear, though he might succeed from a poor -seedling growing wild, if it had come from a garden-stock. The pear, -though cultivated in classical times, appears, from Pliny's -description, to have been a fruit of very inferior quality. I have -seen great surprise expressed in horticultural works at the wonderful -skill of gardeners, in having produced such splendid results from such -poor materials; but the art, I cannot doubt, has been simple, and, as -far as the final result is concerned, has been followed almost -unconsciously. It has consisted in always cultivating the best known -variety, sowing its seeds, and, when a slightly better variety has -chanced to appear, selecting it, and so onwards. But the gardeners of -the classical period, who cultivated the best pear they could procure, -never thought what splendid fruit we should eat; though we owe our -excellent fruit, in some small degree, to their having naturally -chosen and preserved the best varieties they could anywhere find. - -A large amount of change in our cultivated plants, thus slowly and -unconsciously accumulated, explains, as I believe, the well-known -fact, that in a vast number of cases we cannot recognise, and -therefore do not know, the wild parent-stocks of the plants which have -been longest cultivated in our flower and kitchen gardens. If it has -taken centuries or thousands of years to improve or modify most of our -plants up to their present standard of usefulness to man, we can -understand how it is that neither Australia, the Cape of Good Hope, -nor any other region inhabited by quite uncivilised man, has afforded -us a single plant worth culture. It is not that these countries, so -rich in species, do not by a strange chance possess the aboriginal -stocks of any useful plants, but that the native plants have not been -improved by continued selection up to a standard of perfection -comparable with that given to the plants in countries anciently -civilised. - -In regard to the domestic animals kept by uncivilised man, it should -not be overlooked that they almost always have to struggle for their -own food, at least during certain seasons. And in two countries very -differently circumstanced, individuals of the same species, having -slightly different constitutions or structure, would often succeed -better in the one country than in the other, and thus by a process of -"natural selection," as will hereafter be more fully explained, two -sub-breeds might be formed. This, perhaps, partly explains what has -been remarked by some authors, namely, that the varieties kept by -savages have more of the character of species than the varieties kept -in civilised countries. - -On the view here given of the all-important part which selection by -man has played, it becomes at once obvious, how it is that our -domestic races show adaptation in their structure or in their habits -to man's wants or fancies. We can, I think, further understand the -frequently abnormal character of our domestic races, and likewise -their differences being so great in external characters and relatively -so slight in internal parts or organs. Man can hardly select, or only -with much difficulty, any deviation of structure excepting such as is -externally visible; and indeed he rarely cares for what is internal. -He can never act by selection, excepting on variations which are first -given to him in some slight degree by nature. No man would ever try to -make a fantail, till he saw a pigeon with a tail developed in some -slight degree in an unusual manner, or a pouter till he saw a pigeon -with a crop of somewhat unusual size; and the more abnormal or unusual -any character was when it first appeared, the more likely it would be -to catch his attention. But to use such an expression as trying to -make a fantail, is, I have no doubt, in most cases, utterly incorrect. -The man who first selected a pigeon with a slightly larger tail, never -dreamed what the descendants of that pigeon would become through -long-continued, partly unconscious and partly methodical selection. -Perhaps the parent bird of all fantails had only fourteen -tail-feathers somewhat expanded, like the present Java fantail, or -like individuals of other and distinct breeds, in which as many as -seventeen tail-feathers have been counted. Perhaps the first -pouter-pigeon did not inflate its crop much more than the turbit now -does the upper part of its oesophagus,--a habit which is disregarded -by all fanciers, as it is not one of the points of the breed. - -Nor let it be thought that some great deviation of structure would be -necessary to catch the fancier's eye: he perceives extremely small -differences, and it is in human nature to value any novelty, however -slight, in one's own possession. Nor must the value which would -formerly be set on any slight differences in the individuals of the -same species, be judged of by the value which would now be set on -them, after several breeds have once fairly been established. Many -slight differences might, and indeed do now, arise amongst pigeons, -which are rejected as faults or deviations from the standard of -perfection of each breed. The common goose has not given rise to any -marked varieties; hence the Thoulouse and the common breed, which -differ only in colour, that most fleeting of characters, have lately -been exhibited as distinct at our poultry-shows. - -I think these views further explain what has sometimes been -noticed--namely that we know nothing about the origin or history of -any of our domestic breeds. But, in fact, a breed, like a dialect of a -language, can hardly be said to have had a definite origin. A man -preserves and breeds from an individual with some slight deviation of -structure, or takes more care than usual in matching his best animals -and thus improves them, and the improved individuals slowly spread in -the immediate neighbourhood. But as yet they will hardly have a -distinct name, and from being only slightly valued, their history will -be disregarded. When further improved by the same slow and gradual -process, they will spread more widely, and will get recognised as -something distinct and valuable, and will then probably first receive -a provincial name. In semi-civilised countries, with little free -communication, the spreading and knowledge of any new sub-breed will -be a slow process. As soon as the points of value of the new sub-breed -are once fully acknowledged, the principle, as I have called it, of -unconscious selection will always tend,--perhaps more at one period -than at another, as the breed rises or falls in fashion,--perhaps more -in one district than in another, according to the state of -civilisation of the inhabitants--slowly to add to the characteristic -features of the breed, whatever they may be. But the chance will be -infinitely small of any record having been preserved of such slow, -varying, and insensible changes. - -I must now say a few words on the circumstances, favourable, or the -reverse, to man's power of selection. A high degree of variability is -obviously favourable, as freely giving the materials for selection to -work on; not that mere individual differences are not amply -sufficient, with extreme care, to allow of the accumulation of a large -amount of modification in almost any desired direction. But as -variations manifestly useful or pleasing to man appear only -occasionally, the chance of their appearance will be much increased by -a large number of individuals being kept; and hence this comes to be -of the highest importance to success. On this principle Marshall has -remarked, with respect to the sheep of parts of Yorkshire, that "as -they generally belong to poor people, and are mostly IN SMALL LOTS, -they never can be improved." On the other hand, nurserymen, from -raising large stocks of the same plants, are generally far more -successful than amateurs in getting new and valuable varieties. The -keeping of a large number of individuals of a species in any country -requires that the species should be placed under favourable conditions -of life, so as to breed freely in that country. When the individuals -of any species are scanty, all the individuals, whatever their quality -may be, will generally be allowed to breed, and this will effectually -prevent selection. But probably the most important point of all, is, -that the animal or plant should be so highly useful to man, or so much -valued by him, that the closest attention should be paid to even the -slightest deviation in the qualities or structure of each individual. -Unless such attention be paid nothing can be effected. I have seen it -gravely remarked, that it was most fortunate that the strawberry began -to vary just when gardeners began to attend closely to this plant. No -doubt the strawberry had always varied since it was cultivated, but -the slight varieties had been neglected. As soon, however, as -gardeners picked out individual plants with slightly larger, earlier, -or better fruit, and raised seedlings from them, and again picked out -the best seedlings and bred from them, then, there appeared (aided by -some crossing with distinct species) those many admirable varieties of -the strawberry which have been raised during the last thirty or forty -years. - -In the case of animals with separate sexes, facility in preventing -crosses is an important element of success in the formation of new -races,--at least, in a country which is already stocked with other -races. In this respect enclosure of the land plays a part. Wandering -savages or the inhabitants of open plains rarely possess more than one -breed of the same species. Pigeons can be mated for life, and this is -a great convenience to the fancier, for thus many races may be kept -true, though mingled in the same aviary; and this circumstance must -have largely favoured the improvement and formation of new breeds. -Pigeons, I may add, can be propagated in great numbers and at a very -quick rate, and inferior birds may be freely rejected, as when killed -they serve for food. On the other hand, cats, from their nocturnal -rambling habits, cannot be matched, and, although so much valued by -women and children, we hardly ever see a distinct breed kept up; such -breeds as we do sometimes see are almost always imported from some -other country, often from islands. Although I do not doubt that some -domestic animals vary less than others, yet the rarity or absence of -distinct breeds of the cat, the donkey, peacock, goose, etc., may be -attributed in main part to selection not having been brought into -play: in cats, from the difficulty in pairing them; in donkeys, from -only a few being kept by poor people, and little attention paid to -their breeding; in peacocks, from not being very easily reared and a -large stock not kept; in geese, from being valuable only for two -purposes, food and feathers, and more especially from no pleasure -having been felt in the display of distinct breeds. - -To sum up on the origin of our Domestic Races of animals and plants. I -believe that the conditions of life, from their action on the -reproductive system, are so far of the highest importance as causing -variability. I do not believe that variability is an inherent and -necessary contingency, under all circumstances, with all organic -beings, as some authors have thought. The effects of variability are -modified by various degrees of inheritance and of reversion. -Variability is governed by many unknown laws, more especially by that -of correlation of growth. Something may be attributed to the direct -action of the conditions of life. Something must be attributed to use -and disuse. The final result is thus rendered infinitely complex. In -some cases, I do not doubt that the intercrossing of species, -aboriginally distinct, has played an important part in the origin of -our domestic productions. When in any country several domestic breeds -have once been established, their occasional intercrossing, with the -aid of selection, has, no doubt, largely aided in the formation of new -sub-breeds; but the importance of the crossing of varieties has, I -believe, been greatly exaggerated, both in regard to animals and to -those plants which are propagated by seed. In plants which are -temporarily propagated by cuttings, buds, etc., the importance of the -crossing both of distinct species and of varieties is immense; for the -cultivator here quite disregards the extreme variability both of -hybrids and mongrels, and the frequent sterility of hybrids; but the -cases of plants not propagated by seed are of little importance to us, -for their endurance is only temporary. Over all these causes of Change -I am convinced that the accumulative action of Selection, whether -applied methodically and more quickly, or unconsciously and more -slowly, but more efficiently, is by far the predominant Power. - - +Darwin, Charles, 1809-1882 + +ON THE ORIGIN OF SPECIES. + +INTRODUCTION. + +When on board H.M.S. 'Beagle,' as naturalist, I was much struck with +certain facts in the distribution of the inhabitants of South America, +and in the geological relations of the present to the past inhabitants +of that continent. These facts seemed to me to throw some light on the +origin of species--that mystery of mysteries, as it has been called by +one of our greatest philosophers. On my return home, it occurred to +me, in 1837, that something might perhaps be made out on this question +by patiently accumulating and reflecting on all sorts of facts which +could possibly have any bearing on it. After five years' work I +allowed myself to speculate on the subject, and drew up some short +notes; these I enlarged in 1844 into a sketch of the conclusions, +which then seemed to me probable: from that period to the present day +I have steadily pursued the same object. I hope that I may be excused +for entering on these personal details, as I give them to show that I +have not been hasty in coming to a decision. + +My work is now nearly finished; but as it will take me two or three +more years to complete it, and as my health is far from strong, I have +been urged to publish this Abstract. I have more especially been +induced to do this, as Mr. Wallace, who is now studying the natural +history of the Malay archipelago, has arrived at almost exactly the +same general conclusions that I have on the origin of species. Last +year he sent to me a memoir on this subject, with a request that I +would forward it to Sir Charles Lyell, who sent it to the Linnean +Society, and it is published in the third volume of the Journal of +that Society. Sir C. Lyell and Dr. Hooker, who both knew of my +work--the latter having read my sketch of 1844--honoured me by +thinking it advisable to publish, with Mr. Wallace's excellent memoir, +some brief extracts from my manuscripts. + +This Abstract, which I now publish, must necessarily be imperfect. I +cannot here give references and authorities for my several statements; +and I must trust to the reader reposing some confidence in my +accuracy. No doubt errors will have crept in, though I hope I have +always been cautious in trusting to good authorities alone. I can here +give only the general conclusions at which I have arrived, with a few +facts in illustration, but which, I hope, in most cases will suffice. +No one can feel more sensible than I do of the necessity of hereafter +publishing in detail all the facts, with references, on which my +conclusions have been grounded; and I hope in a future work to do +this. For I am well aware that scarcely a single point is discussed in +this volume on which facts cannot be adduced, often apparently leading +to conclusions directly opposite to those at which I have arrived. A +fair result can be obtained only by fully stating and balancing the +facts and arguments on both sides of each question; and this cannot +possibly be here done. + +I much regret that want of space prevents my having the satisfaction +of acknowledging the generous assistance which I have received from +very many naturalists, some of them personally unknown to me. I +cannot, however, let this opportunity pass without expressing my deep +obligations to Dr. Hooker, who for the last fifteen years has aided me +in every possible way by his large stores of knowledge and his +excellent judgment. + +In considering the Origin of Species, it is quite conceivable that a +naturalist, reflecting on the mutual affinities of organic beings, on +their embryological relations, their geographical distribution, +geological succession, and other such facts, might come to the +conclusion that each species had not been independently created, but +had descended, like varieties, from other species. Nevertheless, such +a conclusion, even if well founded, would be unsatisfactory, until it +could be shown how the innumerable species inhabiting this world have +been modified, so as to acquire that perfection of structure and +coadaptation which most justly excites our admiration. Naturalists +continually refer to external conditions, such as climate, food, etc., +as the only possible cause of variation. In one very limited sense, as +we shall hereafter see, this may be true; but it is preposterous to +attribute to mere external conditions, the structure, for instance, of +the woodpecker, with its feet, tail, beak, and tongue, so admirably +adapted to catch insects under the bark of trees. In the case of the +misseltoe, which draws its nourishment from certain trees, which has +seeds that must be transported by certain birds, and which has flowers +with separate sexes absolutely requiring the agency of certain insects +to bring pollen from one flower to the other, it is equally +preposterous to account for the structure of this parasite, with its +relations to several distinct organic beings, by the effects of +external conditions, or of habit, or of the volition of the plant +itself. + +The author of the 'Vestiges of Creation' would, I presume, say that, +after a certain unknown number of generations, some bird had given +birth to a woodpecker, and some plant to the misseltoe, and that these +had been produced perfect as we now see them; but this assumption +seems to me to be no explanation, for it leaves the case of the +coadaptations of organic beings to each other and to their physical +conditions of life, untouched and unexplained. + +It is, therefore, of the highest importance to gain a clear insight +into the means of modification and coadaptation. At the commencement +of my observations it seemed to me probable that a careful study of +domesticated animals and of cultivated plants would offer the best +chance of making out this obscure problem. Nor have I been +disappointed; in this and in all other perplexing cases I have +invariably found that our knowledge, imperfect though it be, of +variation under domestication, afforded the best and safest clue. I +may venture to express my conviction of the high value of such +studies, although they have been very commonly neglected by +naturalists. + +From these considerations, I shall devote the first chapter of this +Abstract to Variation under Domestication. We shall thus see that a +large amount of hereditary modification is at least possible, and, +what is equally or more important, we shall see how great is the power +of man in accumulating by his Selection successive slight variations. +I will then pass on to the variability of species in a state of +nature; but I shall, unfortunately, be compelled to treat this subject +far too briefly, as it can be treated properly only by giving long +catalogues of facts. We shall, however, be enabled to discuss what +circumstances are most favourable to variation. In the next chapter +the Struggle for Existence amongst all organic beings throughout the +world, which inevitably follows from their high geometrical powers of +increase, will be treated of. This is the doctrine of Malthus, applied +to the whole animal and vegetable kingdoms. As many more individuals +of each species are born than can possibly survive; and as, +consequently, there is a frequently recurring struggle for existence, +it follows that any being, if it vary however slightly in any manner +profitable to itself, under the complex and sometimes varying +conditions of life, will have a better chance of surviving, and thus +be NATURALLY SELECTED. From the strong principle of inheritance, any +selected variety will tend to propagate its new and modified form. + +This fundamental subject of Natural Selection will be treated at some +length in the fourth chapter; and we shall then see how Natural +Selection almost inevitably causes much Extinction of the less +improved forms of life and induces what I have called Divergence of +Character. In the next chapter I shall discuss the complex and little +known laws of variation and of correlation of growth. In the four +succeeding chapters, the most apparent and gravest difficulties on the +theory will be given: namely, first, the difficulties of transitions, +or in understanding how a simple being or a simple organ can be +changed and perfected into a highly developed being or elaborately +constructed organ; secondly the subject of Instinct, or the mental +powers of animals, thirdly, Hybridism, or the infertility of species +and the fertility of varieties when intercrossed; and fourthly, the +imperfection of the Geological Record. In the next chapter I shall +consider the geological succession of organic beings throughout time; +in the eleventh and twelfth, their geographical distribution +throughout space; in the thirteenth, their classification or mutual +affinities, both when mature and in an embryonic condition. In the +last chapter I shall give a brief recapitulation of the whole work, +and a few concluding remarks. + +No one ought to feel surprise at much remaining as yet unexplained in +regard to the origin of species and varieties, if he makes due +allowance for our profound ignorance in regard to the mutual relations +of all the beings which live around us. Who can explain why one +species ranges widely and is very numerous, and why another allied +species has a narrow range and is rare? Yet these relations are of the +highest importance, for they determine the present welfare, and, as I +believe, the future success and modification of every inhabitant of +this world. Still less do we know of the mutual relations of the +innumerable inhabitants of the world during the many past geological +epochs in its history. Although much remains obscure, and will long +remain obscure, I can entertain no doubt, after the most deliberate +study and dispassionate judgment of which I am capable, that the view +which most naturalists entertain, and which I formerly +entertained--namely, that each species has been independently +created--is erroneous. I am fully convinced that species are not +immutable; but that those belonging to what are called the same genera +are lineal descendants of some other and generally extinct species, in +the same manner as the acknowledged varieties of any one species are +the descendants of that species. Furthermore, I am convinced that +Natural Selection has been the main but not exclusive means of +modification. + +CHAPTER 1. VARIATION UNDER DOMESTICATION. + +Causes of Variability. +Effects of Habit. +Correlation of Growth. +Inheritance. +Character of Domestic Varieties. +Difficulty of distinguishing between Varieties and Species. +Origin of Domestic Varieties from one or more Species. +Domestic Pigeons, their Differences and Origin. +Principle of Selection anciently followed, its Effects. +Methodical and Unconscious Selection. +Unknown Origin of our Domestic Productions. +Circumstances favourable to Man's power of Selection. + +When we look to the individuals of the same variety or sub-variety of +our older cultivated plants and animals, one of the first points which +strikes us, is, that they generally differ much more from each other, +than do the individuals of any one species or variety in a state of +nature. When we reflect on the vast diversity of the plants and +animals which have been cultivated, and which have varied during all +ages under the most different climates and treatment, I think we are +driven to conclude that this greater variability is simply due to our +domestic productions having been raised under conditions of life not +so uniform as, and somewhat different from, those to which the +parent-species have been exposed under nature. There is, also, I +think, some probability in the view propounded by Andrew Knight, that +this variability may be partly connected with excess of food. It seems +pretty clear that organic beings must be exposed during several +generations to the new conditions of life to cause any appreciable +amount of variation; and that when the organisation has once begun to +vary, it generally continues to vary for many generations. No case is +on record of a variable being ceasing to be variable under +cultivation. Our oldest cultivated plants, such as wheat, still often +yield new varieties: our oldest domesticated animals are still capable +of rapid improvement or modification. + +It has been disputed at what period of life the causes of variability, +whatever they may be, generally act; whether during the early or late +period of development of the embryo, or at the instant of conception. +Geoffroy St. Hilaire's experiments show that unnatural treatment of +the embryo causes monstrosities; and monstrosities cannot be separated +by any clear line of distinction from mere variations. But I am +strongly inclined to suspect that the most frequent cause of +variability may be attributed to the male and female reproductive +elements having been affected prior to the act of conception. Several +reasons make me believe in this; but the chief one is the remarkable +effect which confinement or cultivation has on the functions of the +reproductive system; this system appearing to be far more susceptible +than any other part of the organisation, to the action of any change +in the conditions of life. Nothing is more easy than to tame an +animal, and few things more difficult than to get it to breed freely +under confinement, even in the many cases when the male and female +unite. How many animals there are which will not breed, though living +long under not very close confinement in their native country! This is +generally attributed to vitiated instincts; but how many cultivated +plants display the utmost vigour, and yet rarely or never seed! In +some few such cases it has been found out that very trifling changes, +such as a little more or less water at some particular period of +growth, will determine whether or not the plant sets a seed. I cannot +here enter on the copious details which I have collected on this +curious subject; but to show how singular the laws are which determine +the reproduction of animals under confinement, I may just mention that +carnivorous animals, even from the tropics, breed in this country +pretty freely under confinement, with the exception of the +plantigrades or bear family; whereas, carnivorous birds, with the +rarest exceptions, hardly ever lay fertile eggs. Many exotic plants +have pollen utterly worthless, in the same exact condition as in the +most sterile hybrids. When, on the one hand, we see domesticated +animals and plants, though often weak and sickly, yet breeding quite +freely under confinement; and when, on the other hand, we see +individuals, though taken young from a state of nature, perfectly +tamed, long-lived, and healthy (of which I could give numerous +instances), yet having their reproductive system so seriously affected +by unperceived causes as to fail in acting, we need not be surprised +at this system, when it does act under confinement, acting not quite +regularly, and producing offspring not perfectly like their parents or +variable. + +Sterility has been said to be the bane of horticulture; but on this +view we owe variability to the same cause which produces sterility; +and variability is the source of all the choicest productions of the +garden. I may add, that as some organisms will breed most freely under +the most unnatural conditions (for instance, the rabbit and ferret +kept in hutches), showing that their reproductive system has not been +thus affected; so will some animals and plants withstand domestication +or cultivation, and vary very slightly--perhaps hardly more than in a +state of nature. + +A long list could easily be given of "sporting plants;" by this term +gardeners mean a single bud or offset, which suddenly assumes a new +and sometimes very different character from that of the rest of the +plant. Such buds can be propagated by grafting, etc., and sometimes by +seed. These "sports" are extremely rare under nature, but far from +rare under cultivation; and in this case we see that the treatment of +the parent has affected a bud or offset, and not the ovules or pollen. +But it is the opinion of most physiologists that there is no essential +difference between a bud and an ovule in their earliest stages of +formation; so that, in fact, "sports" support my view, that +variability may be largely attributed to the ovules or pollen, or to +both, having been affected by the treatment of the parent prior to the +act of conception. These cases anyhow show that variation is not +necessarily connected, as some authors have supposed, with the act of +generation. + +Seedlings from the same fruit, and the young of the same litter, +sometimes differ considerably from each other, though both the young +and the parents, as Muller has remarked, have apparently been exposed +to exactly the same conditions of life; and this shows how unimportant +the direct effects of the conditions of life are in comparison with +the laws of reproduction, and of growth, and of inheritance; for had +the action of the conditions been direct, if any of the young had +varied, all would probably have varied in the same manner. To judge +how much, in the case of any variation, we should attribute to the +direct action of heat, moisture, light, food, etc., is most difficult: +my impression is, that with animals such agencies have produced very +little direct effect, though apparently more in the case of plants. +Under this point of view, Mr. Buckman's recent experiments on plants +seem extremely valuable. When all or nearly all the individuals +exposed to certain conditions are affected in the same way, the change +at first appears to be directly due to such conditions; but in some +cases it can be shown that quite opposite conditions produce similar +changes of structure. Nevertheless some slight amount of change may, I +think, be attributed to the direct action of the conditions of +life--as, in some cases, increased size from amount of food, colour +from particular kinds of food and from light, and perhaps the +thickness of fur from climate. + +Habit also has a decided influence, as in the period of flowering with +plants when transported from one climate to another. In animals it has +a more marked effect; for instance, I find in the domestic duck that +the bones of the wing weigh less and the bones of the leg more, in +proportion to the whole skeleton, than do the same bones in the +wild-duck; and I presume that this change may be safely attributed to +the domestic duck flying much less, and walking more, than its wild +parent. The great and inherited development of the udders in cows and +goats in countries where they are habitually milked, in comparison +with the state of these organs in other countries, is another instance +of the effect of use. Not a single domestic animal can be named which +has not in some country drooping ears; and the view suggested by some +authors, that the drooping is due to the disuse of the muscles of the +ear, from the animals not being much alarmed by danger, seems +probable. + +There are many laws regulating variation, some few of which can be +dimly seen, and will be hereafter briefly mentioned. I will here only +allude to what may be called correlation of growth. Any change in the +embryo or larva will almost certainly entail changes in the mature +animal. In monstrosities, the correlations between quite distinct +parts are very curious; and many instances are given in Isidore +Geoffroy St. Hilaire's great work on this subject. Breeders believe +that long limbs are almost always accompanied by an elongated head. +Some instances of correlation are quite whimsical; thus cats with blue +eyes are invariably deaf; colour and constitutional peculiarities go +together, of which many remarkable cases could be given amongst +animals and plants. From the facts collected by Heusinger, it appears +that white sheep and pigs are differently affected from coloured +individuals by certain vegetable poisons. Hairless dogs have imperfect +teeth; long-haired and coarse-haired animals are apt to have, as is +asserted, long or many horns; pigeons with feathered feet have skin +between their outer toes; pigeons with short beaks have small feet, +and those with long beaks large feet. Hence, if man goes on selecting, +and thus augmenting, any peculiarity, he will almost certainly +unconsciously modify other parts of the structure, owing to the +mysterious laws of the correlation of growth. + +The result of the various, quite unknown, or dimly seen laws of +variation is infinitely complex and diversified. It is well worth +while carefully to study the several treatises published on some of +our old cultivated plants, as on the hyacinth, potato, even the +dahlia, etc.; and it is really surprising to note the endless points +in structure and constitution in which the varieties and sub-varieties +differ slightly from each other. The whole organisation seems to have +become plastic, and tends to depart in some small degree from that of +the parental type. + +Any variation which is not inherited is unimportant for us. But the +number and diversity of inheritable deviations of structure, both +those of slight and those of considerable physiological importance, is +endless. Dr. Prosper Lucas's treatise, in two large volumes, is the +fullest and the best on this subject. No breeder doubts how strong is +the tendency to inheritance: like produces like is his fundamental +belief: doubts have been thrown on this principle by theoretical +writers alone. When a deviation appears not unfrequently, and we see +it in the father and child, we cannot tell whether it may not be due +to the same original cause acting on both; but when amongst +individuals, apparently exposed to the same conditions, any very rare +deviation, due to some extraordinary combination of circumstances, +appears in the parent--say, once amongst several million +individuals--and it reappears in the child, the mere doctrine of +chances almost compels us to attribute its reappearance to +inheritance. Every one must have heard of cases of albinism, prickly +skin, hairy bodies, etc., appearing in several members of the same +family. If strange and rare deviations of structure are truly +inherited, less strange and commoner deviations may be freely admitted +to be inheritable. Perhaps the correct way of viewing the whole +subject, would be, to look at the inheritance of every character +whatever as the rule, and non-inheritance as the anomaly. + +The laws governing inheritance are quite unknown; no one can say why +the same peculiarity in different individuals of the same species, and +in individuals of different species, is sometimes inherited and +sometimes not so; why the child often reverts in certain characters to +its grandfather or grandmother or other much more remote ancestor; why +a peculiarity is often transmitted from one sex to both sexes or to +one sex alone, more commonly but not exclusively to the like sex. It +is a fact of some little importance to us, that peculiarities +appearing in the males of our domestic breeds are often transmitted +either exclusively, or in a much greater degree, to males alone. A +much more important rule, which I think may be trusted, is that, at +whatever period of life a peculiarity first appears, it tends to +appear in the offspring at a corresponding age, though sometimes +earlier. In many cases this could not be otherwise: thus the inherited +peculiarities in the horns of cattle could appear only in the +offspring when nearly mature; peculiarities in the silkworm are known +to appear at the corresponding caterpillar or cocoon stage. But +hereditary diseases and some other facts make me believe that the rule +has a wider extension, and that when there is no apparent reason why a +peculiarity should appear at any particular age, yet that it does tend +to appear in the offspring at the same period at which it first +appeared in the parent. I believe this rule to be of the highest +importance in explaining the laws of embryology. These remarks are of +course confined to the first APPEARANCE of the peculiarity, and not to +its primary cause, which may have acted on the ovules or male element; +in nearly the same manner as in the crossed offspring from a +short-horned cow by a long-horned bull, the greater length of horn, +though appearing late in life, is clearly due to the male element. + +Having alluded to the subject of reversion, I may here refer to a +statement often made by naturalists--namely, that our domestic +varieties, when run wild, gradually but certainly revert in character +to their aboriginal stocks. Hence it has been argued that no +deductions can be drawn from domestic races to species in a state of +nature. I have in vain endeavoured to discover on what decisive facts +the above statement has so often and so boldly been made. There would +be great difficulty in proving its truth: we may safely conclude that +very many of the most strongly-marked domestic varieties could not +possibly live in a wild state. In many cases we do not know what the +aboriginal stock was, and so could not tell whether or not nearly +perfect reversion had ensued. It would be quite necessary, in order to +prevent the effects of intercrossing, that only a single variety +should be turned loose in its new home. Nevertheless, as our varieties +certainly do occasionally revert in some of their characters to +ancestral forms, it seems to me not improbable, that if we could +succeed in naturalising, or were to cultivate, during many +generations, the several races, for instance, of the cabbage, in very +poor soil (in which case, however, some effect would have to be +attributed to the direct action of the poor soil), that they would to +a large extent, or even wholly, revert to the wild aboriginal stock. +Whether or not the experiment would succeed, is not of great +importance for our line of argument; for by the experiment itself the +conditions of life are changed. If it could be shown that our domestic +varieties manifested a strong tendency to reversion,--that is, to lose +their acquired characters, whilst kept under unchanged conditions, and +whilst kept in a considerable body, so that free intercrossing might +check, by blending together, any slight deviations of structure, in +such case, I grant that we could deduce nothing from domestic +varieties in regard to species. But there is not a shadow of evidence +in favour of this view: to assert that we could not breed our cart and +race-horses, long and short-horned cattle, and poultry of various +breeds, and esculent vegetables, for an almost infinite number of +generations, would be opposed to all experience. I may add, that when +under nature the conditions of life do change, variations and +reversions of character probably do occur; but natural selection, as +will hereafter be explained, will determine how far the new characters +thus arising shall be preserved. + +When we look to the hereditary varieties or races of our domestic +animals and plants, and compare them with species closely allied +together, we generally perceive in each domestic race, as already +remarked, less uniformity of character than in true species. Domestic +races of the same species, also, often have a somewhat monstrous +character; by which I mean, that, although differing from each other, +and from the other species of the same genus, in several trifling +respects, they often differ in an extreme degree in some one part, +both when compared one with another, and more especially when compared +with all the species in nature to which they are nearest allied. With +these exceptions (and with that of the perfect fertility of varieties +when crossed,--a subject hereafter to be discussed), domestic races of +the same species differ from each other in the same manner as, only in +most cases in a lesser degree than, do closely-allied species of the +same genus in a state of nature. I think this must be admitted, when +we find that there are hardly any domestic races, either amongst +animals or plants, which have not been ranked by some competent judges +as mere varieties, and by other competent judges as the descendants of +aboriginally distinct species. If any marked distinction existed +between domestic races and species, this source of doubt could not so +perpetually recur. It has often been stated that domestic races do not +differ from each other in characters of generic value. I think it +could be shown that this statement is hardly correct; but naturalists +differ most widely in determining what characters are of generic +value; all such valuations being at present empirical. Moreover, on +the view of the origin of genera which I shall presently give, we have +no right to expect often to meet with generic differences in our +domesticated productions. + +When we attempt to estimate the amount of structural difference +between the domestic races of the same species, we are soon involved +in doubt, from not knowing whether they have descended from one or +several parent-species. This point, if it could be cleared up, would +be interesting; if, for instance, it could be shown that the +greyhound, bloodhound, terrier, spaniel, and bull-dog, which we all +know propagate their kind so truly, were the offspring of any single +species, then such facts would have great weight in making us doubt +about the immutability of the many very closely allied and natural +species--for instance, of the many foxes--inhabiting different +quarters of the world. I do not believe, as we shall presently see, +that all our dogs have descended from any one wild species; but, in +the case of some other domestic races, there is presumptive, or even +strong, evidence in favour of this view. + +It has often been assumed that man has chosen for domestication +animals and plants having an extraordinary inherent tendency to vary, +and likewise to withstand diverse climates. I do not dispute that +these capacities have added largely to the value of most of our +domesticated productions; but how could a savage possibly know, when +he first tamed an animal, whether it would vary in succeeding +generations, and whether it would endure other climates? Has the +little variability of the ass or guinea-fowl, or the small power of +endurance of warmth by the rein-deer, or of cold by the common camel, +prevented their domestication? I cannot doubt that if other animals +and plants, equal in number to our domesticated productions, and +belonging to equally diverse classes and countries, were taken from a +state of nature, and could be made to breed for an equal number of +generations under domestication, they would vary on an average as +largely as the parent species of our existing domesticated productions +have varied. + +In the case of most of our anciently domesticated animals and plants, +I do not think it is possible to come to any definite conclusion, +whether they have descended from one or several species. The argument +mainly relied on by those who believe in the multiple origin of our +domestic animals is, that we find in the most ancient records, more +especially on the monuments of Egypt, much diversity in the breeds; +and that some of the breeds closely resemble, perhaps are identical +with, those still existing. Even if this latter fact were found more +strictly and generally true than seems to me to be the case, what does +it show, but that some of our breeds originated there, four or five +thousand years ago? But Mr. Horner's researches have rendered it in +some degree probable that man sufficiently civilized to have +manufactured pottery existed in the valley of the Nile thirteen or +fourteen thousand years ago; and who will pretend to say how long +before these ancient periods, savages, like those of Tierra del Fuego +or Australia, who possess a semi-domestic dog, may not have existed in +Egypt? + +The whole subject must, I think, remain vague; nevertheless, I may, +without here entering on any details, state that, from geographical +and other considerations, I think it highly probable that our domestic +dogs have descended from several wild species. In regard to sheep and +goats I can form no opinion. I should think, from facts communicated +to me by Mr. Blyth, on the habits, voice, and constitution, etc., of +the humped Indian cattle, that these had descended from a different +aboriginal stock from our European cattle; and several competent +judges believe that these latter have had more than one wild parent. +With respect to horses, from reasons which I cannot give here, I am +doubtfully inclined to believe, in opposition to several authors, that +all the races have descended from one wild stock. Mr. Blyth, whose +opinion, from his large and varied stores of knowledge, I should value +more than that of almost any one, thinks that all the breeds of +poultry have proceeded from the common wild Indian fowl (Gallus +bankiva). In regard to ducks and rabbits, the breeds of which differ +considerably from each other in structure, I do not doubt that they +all have descended from the common wild duck and rabbit. + +The doctrine of the origin of our several domestic races from several +aboriginal stocks, has been carried to an absurd extreme by some +authors. They believe that every race which breeds true, let the +distinctive characters be ever so slight, has had its wild prototype. +At this rate there must have existed at least a score of species of +wild cattle, as many sheep, and several goats in Europe alone, and +several even within Great Britain. One author believes that there +formerly existed in Great Britain eleven wild species of sheep +peculiar to it! When we bear in mind that Britain has now hardly one +peculiar mammal, and France but few distinct from those of Germany and +conversely, and so with Hungary, Spain, etc., but that each of these +kingdoms possesses several peculiar breeds of cattle, sheep, etc., we +must admit that many domestic breeds have originated in Europe; for +whence could they have been derived, as these several countries do not +possess a number of peculiar species as distinct parent-stocks? So it +is in India. Even in the case of the domestic dogs of the whole world, +which I fully admit have probably descended from several wild species, +I cannot doubt that there has been an immense amount of inherited +variation. Who can believe that animals closely resembling the Italian +greyhound, the bloodhound, the bull-dog, or Blenheim spaniel, etc.--so +unlike all wild Canidae--ever existed freely in a state of nature? It +has often been loosely said that all our races of dogs have been +produced by the crossing of a few aboriginal species; but by crossing +we can get only forms in some degree intermediate between their +parents; and if we account for our several domestic races by this +process, we must admit the former existence of the most extreme forms, +as the Italian greyhound, bloodhound, bull-dog, etc., in the wild +state. Moreover, the possibility of making distinct races by crossing +has been greatly exaggerated. There can be no doubt that a race may be +modified by occasional crosses, if aided by the careful selection of +those individual mongrels, which present any desired character; but +that a race could be obtained nearly intermediate between two +extremely different races or species, I can hardly believe. Sir J. +Sebright expressly experimentised for this object, and failed. The +offspring from the first cross between two pure breeds is tolerably +and sometimes (as I have found with pigeons) extremely uniform, and +everything seems simple enough; but when these mongrels are crossed +one with another for several generations, hardly two of them will be +alike, and then the extreme difficulty, or rather utter hopelessness, +of the task becomes apparent. Certainly, a breed intermediate between +TWO VERY DISTINCT breeds could not be got without extreme care and +long-continued selection; nor can I find a single case on record of a +permanent race having been thus formed. + +ON THE BREEDS OF THE DOMESTIC PIGEON. + +Believing that it is always best to study some special group, I have, +after deliberation, taken up domestic pigeons. I have kept every breed +which I could purchase or obtain, and have been most kindly favoured +with skins from several quarters of the world, more especially by the +Honourable W. Elliot from India, and by the Honourable C. Murray from +Persia. Many treatises in different languages have been published on +pigeons, and some of them are very important, as being of considerable +antiquity. I have associated with several eminent fanciers, and have +been permitted to join two of the London Pigeon Clubs. The diversity +of the breeds is something astonishing. Compare the English carrier +and the short-faced tumbler, and see the wonderful difference in their +beaks, entailing corresponding differences in their skulls. The +carrier, more especially the male bird, is also remarkable from the +wonderful development of the carunculated skin about the head, and +this is accompanied by greatly elongated eyelids, very large external +orifices to the nostrils, and a wide gape of mouth. The short-faced +tumbler has a beak in outline almost like that of a finch; and the +common tumbler has the singular and strictly inherited habit of flying +at a great height in a compact flock, and tumbling in the air head +over heels. The runt is a bird of great size, with long, massive beak +and large feet; some of the sub-breeds of runts have very long necks, +others very long wings and tails, others singularly short tails. The +barb is allied to the carrier, but, instead of a very long beak, has a +very short and very broad one. The pouter has a much elongated body, +wings, and legs; and its enormously developed crop, which it glories +in inflating, may well excite astonishment and even laughter. The +turbit has a very short and conical beak, with a line of reversed +feathers down the breast; and it has the habit of continually +expanding slightly the upper part of the oesophagus. The Jacobin has +the feathers so much reversed along the back of the neck that they +form a hood, and it has, proportionally to its size, much elongated +wing and tail feathers. The trumpeter and laugher, as their names +express, utter a very different coo from the other breeds. The fantail +has thirty or even forty tail-feathers, instead of twelve or fourteen, +the normal number in all members of the great pigeon family; and these +feathers are kept expanded, and are carried so erect that in good +birds the head and tail touch; the oil-gland is quite aborted. Several +other less distinct breeds might have been specified. + +In the skeletons of the several breeds, the development of the bones +of the face in length and breadth and curvature differs enormously. +The shape, as well as the breadth and length of the ramus of the lower +jaw, varies in a highly remarkable manner. The number of the caudal +and sacral vertebrae vary; as does the number of the ribs, together +with their relative breadth and the presence of processes. The size +and shape of the apertures in the sternum are highly variable; so is +the degree of divergence and relative size of the two arms of the +furcula. The proportional width of the gape of mouth, the proportional +length of the eyelids, of the orifice of the nostrils, of the tongue +(not always in strict correlation with the length of beak), the size +of the crop and of the upper part of the oesophagus; the development +and abortion of the oil-gland; the number of the primary wing and +caudal feathers; the relative length of wing and tail to each other +and to the body; the relative length of leg and of the feet; the +number of scutellae on the toes, the development of skin between the +toes, are all points of structure which are variable. The period at +which the perfect plumage is acquired varies, as does the state of the +down with which the nestling birds are clothed when hatched. The shape +and size of the eggs vary. The manner of flight differs remarkably; as +does in some breeds the voice and disposition. Lastly, in certain +breeds, the males and females have come to differ to a slight degree +from each other. + +Altogether at least a score of pigeons might be chosen, which if shown +to an ornithologist, and he were told that they were wild birds, would +certainly, I think, be ranked by him as well-defined species. +Moreover, I do not believe that any ornithologist would place the +English carrier, the short-faced tumbler, the runt, the barb, pouter, +and fantail in the same genus; more especially as in each of these +breeds several truly-inherited sub-breeds, or species as he might have +called them, could be shown him. + +Great as the differences are between the breeds of pigeons, I am fully +convinced that the common opinion of naturalists is correct, namely, +that all have descended from the rock-pigeon (Columba livia), +including under this term several geographical races or sub-species, +which differ from each other in the most trifling respects. As several +of the reasons which have led me to this belief are in some degree +applicable in other cases, I will here briefly give them. If the +several breeds are not varieties, and have not proceeded from the +rock-pigeon, they must have descended from at least seven or eight +aboriginal stocks; for it is impossible to make the present domestic +breeds by the crossing of any lesser number: how, for instance, could +a pouter be produced by crossing two breeds unless one of the +parent-stocks possessed the characteristic enormous crop? The supposed +aboriginal stocks must all have been rock-pigeons, that is, not +breeding or willingly perching on trees. But besides C. livia, with +its geographical sub-species, only two or three other species of +rock-pigeons are known; and these have not any of the characters of +the domestic breeds. Hence the supposed aboriginal stocks must either +still exist in the countries where they were originally domesticated, +and yet be unknown to ornithologists; and this, considering their +size, habits, and remarkable characters, seems very improbable; or +they must have become extinct in the wild state. But birds breeding on +precipices, and good fliers, are unlikely to be exterminated; and the +common rock-pigeon, which has the same habits with the domestic +breeds, has not been exterminated even on several of the smaller +British islets, or on the shores of the Mediterranean. Hence the +supposed extermination of so many species having similar habits with +the rock-pigeon seems to me a very rash assumption. Moreover, the +several above-named domesticated breeds have been transported to all +parts of the world, and, therefore, some of them must have been +carried back again into their native country; but not one has ever +become wild or feral, though the dovecot-pigeon, which is the +rock-pigeon in a very slightly altered state, has become feral in +several places. Again, all recent experience shows that it is most +difficult to get any wild animal to breed freely under domestication; +yet on the hypothesis of the multiple origin of our pigeons, it must +be assumed that at least seven or eight species were so thoroughly +domesticated in ancient times by half-civilized man, as to be quite +prolific under confinement. + +An argument, as it seems to me, of great weight, and applicable in +several other cases, is, that the above-specified breeds, though +agreeing generally in constitution, habits, voice, colouring, and in +most parts of their structure, with the wild rock-pigeon, yet are +certainly highly abnormal in other parts of their structure: we may +look in vain throughout the whole great family of Columbidae for a +beak like that of the English carrier, or that of the short-faced +tumbler, or barb; for reversed feathers like those of the jacobin; for +a crop like that of the pouter; for tail-feathers like those of the +fantail. Hence it must be assumed not only that half-civilized man +succeeded in thoroughly domesticating several species, but that he +intentionally or by chance picked out extraordinarily abnormal +species; and further, that these very species have since all become +extinct or unknown. So many strange contingencies seem to me +improbable in the highest degree. + +Some facts in regard to the colouring of pigeons well deserve +consideration. The rock-pigeon is of a slaty-blue, and has a white +rump (the Indian sub-species, C. intermedia of Strickland, having it +bluish); the tail has a terminal dark bar, with the bases of the outer +feathers externally edged with white; the wings have two black bars; +some semi-domestic breeds and some apparently truly wild breeds have, +besides the two black bars, the wings chequered with black. These +several marks do not occur together in any other species of the whole +family. Now, in every one of the domestic breeds, taking thoroughly +well-bred birds, all the above marks, even to the white edging of the +outer tail-feathers, sometimes concur perfectly developed. Moreover, +when two birds belonging to two distinct breeds are crossed, neither +of which is blue or has any of the above-specified marks, the mongrel +offspring are very apt suddenly to acquire these characters; for +instance, I crossed some uniformly white fantails with some uniformly +black barbs, and they produced mottled brown and black birds; these I +again crossed together, and one grandchild of the pure white fantail +and pure black barb was of as beautiful a blue colour, with the white +rump, double black wing-bar, and barred and white-edged tail-feathers, +as any wild rock-pigeon! We can understand these facts, on the +well-known principle of reversion to ancestral characters, if all the +domestic breeds have descended from the rock-pigeon. But if we deny +this, we must make one of the two following highly improbable +suppositions. Either, firstly, that all the several imagined +aboriginal stocks were coloured and marked like the rock-pigeon, +although no other existing species is thus coloured and marked, so +that in each separate breed there might be a tendency to revert to the +very same colours and markings. Or, secondly, that each breed, even +the purest, has within a dozen or, at most, within a score of +generations, been crossed by the rock-pigeon: I say within a dozen or +twenty generations, for we know of no fact countenancing the belief +that the child ever reverts to some one ancestor, removed by a greater +number of generations. In a breed which has been crossed only once +with some distinct breed, the tendency to reversion to any character +derived from such cross will naturally become less and less, as in +each succeeding generation there will be less of the foreign blood; +but when there has been no cross with a distinct breed, and there is a +tendency in both parents to revert to a character, which has been lost +during some former generation, this tendency, for all that we can see +to the contrary, may be transmitted undiminished for an indefinite +number of generations. These two distinct cases are often confounded +in treatises on inheritance. + +Lastly, the hybrids or mongrels from between all the domestic breeds +of pigeons are perfectly fertile. I can state this from my own +observations, purposely made on the most distinct breeds. Now, it is +difficult, perhaps impossible, to bring forward one case of the hybrid +offspring of two animals CLEARLY DISTINCT being themselves perfectly +fertile. Some authors believe that long-continued domestication +eliminates this strong tendency to sterility: from the history of the +dog I think there is some probability in this hypothesis, if applied +to species closely related together, though it is unsupported by a +single experiment. But to extend the hypothesis so far as to suppose +that species, aboriginally as distinct as carriers, tumblers, pouters, +and fantails now are, should yield offspring perfectly fertile, inter +se, seems to me rash in the extreme. + +From these several reasons, namely, the improbability of man having +formerly got seven or eight supposed species of pigeons to breed +freely under domestication; these supposed species being quite unknown +in a wild state, and their becoming nowhere feral; these species +having very abnormal characters in certain respects, as compared with +all other Columbidae, though so like in most other respects to the +rock-pigeon; the blue colour and various marks occasionally appearing +in all the breeds, both when kept pure and when crossed; the mongrel +offspring being perfectly fertile;--from these several reasons, taken +together, I can feel no doubt that all our domestic breeds have +descended from the Columba livia with its geographical sub-species. + +In favour of this view, I may add, firstly, that C. livia, or the +rock-pigeon, has been found capable of domestication in Europe and in +India; and that it agrees in habits and in a great number of points of +structure with all the domestic breeds. Secondly, although an English +carrier or short-faced tumbler differs immensely in certain characters +from the rock-pigeon, yet by comparing the several sub-breeds of these +breeds, more especially those brought from distant countries, we can +make an almost perfect series between the extremes of structure. +Thirdly, those characters which are mainly distinctive of each breed, +for instance the wattle and length of beak of the carrier, the +shortness of that of the tumbler, and the number of tail-feathers in +the fantail, are in each breed eminently variable; and the explanation +of this fact will be obvious when we come to treat of selection. +Fourthly, pigeons have been watched, and tended with the utmost care, +and loved by many people. They have been domesticated for thousands of +years in several quarters of the world; the earliest known record of +pigeons is in the fifth Aegyptian dynasty, about 3000 B.C., as was +pointed out to me by Professor Lepsius; but Mr. Birch informs me that +pigeons are given in a bill of fare in the previous dynasty. In the +time of the Romans, as we hear from Pliny, immense prices were given +for pigeons; "nay, they are come to this pass, that they can reckon up +their pedigree and race." Pigeons were much valued by Akber Khan in +India, about the year 1600; never less than 20,000 pigeons were taken +with the court. "The monarchs of Iran and Turan sent him some very +rare birds;" and, continues the courtly historian, "His Majesty by +crossing the breeds, which method was never practised before, has +improved them astonishingly." About this same period the Dutch were as +eager about pigeons as were the old Romans. The paramount importance +of these considerations in explaining the immense amount of variation +which pigeons have undergone, will be obvious when we treat of +Selection. We shall then, also, see how it is that the breeds so often +have a somewhat monstrous character. It is also a most favourable +circumstance for the production of distinct breeds, that male and +female pigeons can be easily mated for life; and thus different breeds +can be kept together in the same aviary. + +I have discussed the probable origin of domestic pigeons at some, yet +quite insufficient, length; because when I first kept pigeons and +watched the several kinds, knowing well how true they bred, I felt +fully as much difficulty in believing that they could ever have +descended from a common parent, as any naturalist could in coming to a +similar conclusion in regard to the many species of finches, or other +large groups of birds, in nature. One circumstance has struck me much; +namely, that all the breeders of the various domestic animals and the +cultivators of plants, with whom I have ever conversed, or whose +treatises I have read, are firmly convinced that the several breeds to +which each has attended, are descended from so many aboriginally +distinct species. Ask, as I have asked, a celebrated raiser of +Hereford cattle, whether his cattle might not have descended from long +horns, and he will laugh you to scorn. I have never met a pigeon, or +poultry, or duck, or rabbit fancier, who was not fully convinced that +each main breed was descended from a distinct species. Van Mons, in +his treatise on pears and apples, shows how utterly he disbelieves +that the several sorts, for instance a Ribston-pippin or Codlin-apple, +could ever have proceeded from the seeds of the same tree. Innumerable +other examples could be given. The explanation, I think, is simple: +from long-continued study they are strongly impressed with the +differences between the several races; and though they well know that +each race varies slightly, for they win their prizes by selecting such +slight differences, yet they ignore all general arguments, and refuse +to sum up in their minds slight differences accumulated during many +successive generations. May not those naturalists who, knowing far +less of the laws of inheritance than does the breeder, and knowing no +more than he does of the intermediate links in the long lines of +descent, yet admit that many of our domestic races have descended from +the same parents--may they not learn a lesson of caution, when they +deride the idea of species in a state of nature being lineal +descendants of other species? + +SELECTION. + +Let us now briefly consider the steps by which domestic races have +been produced, either from one or from several allied species. Some +little effect may, perhaps, be attributed to the direct action of the +external conditions of life, and some little to habit; but he would be +a bold man who would account by such agencies for the differences of a +dray and race horse, a greyhound and bloodhound, a carrier and tumbler +pigeon. One of the most remarkable features in our domesticated races +is that we see in them adaptation, not indeed to the animal's or +plant's own good, but to man's use or fancy. Some variations useful to +him have probably arisen suddenly, or by one step; many botanists, for +instance, believe that the fuller's teazle, with its hooks, which +cannot be rivalled by any mechanical contrivance, is only a variety of +the wild Dipsacus; and this amount of change may have suddenly arisen +in a seedling. So it has probably been with the turnspit dog; and this +is known to have been the case with the ancon sheep. But when we +compare the dray-horse and race-horse, the dromedary and camel, the +various breeds of sheep fitted either for cultivated land or mountain +pasture, with the wool of one breed good for one purpose, and that of +another breed for another purpose; when we compare the many breeds of +dogs, each good for man in very different ways; when we compare the +game-cock, so pertinacious in battle, with other breeds so little +quarrelsome, with "everlasting layers" which never desire to sit, and +with the bantam so small and elegant; when we compare the host of +agricultural, culinary, orchard, and flower-garden races of plants, +most useful to man at different seasons and for different purposes, or +so beautiful in his eyes, we must, I think, look further than to mere +variability. We cannot suppose that all the breeds were suddenly +produced as perfect and as useful as we now see them; indeed, in +several cases, we know that this has not been their history. The key +is man's power of accumulative selection: nature gives successive +variations; man adds them up in certain directions useful to him. In +this sense he may be said to make for himself useful breeds. + +The great power of this principle of selection is not hypothetical. It +is certain that several of our eminent breeders have, even within a +single lifetime, modified to a large extent some breeds of cattle and +sheep. In order fully to realise what they have done, it is almost +necessary to read several of the many treatises devoted to this +subject, and to inspect the animals. Breeders habitually speak of an +animal's organisation as something quite plastic, which they can model +almost as they please. If I had space I could quote numerous passages +to this effect from highly competent authorities. Youatt, who was +probably better acquainted with the works of agriculturalists than +almost any other individual, and who was himself a very good judge of +an animal, speaks of the principle of selection as "that which enables +the agriculturist, not only to modify the character of his flock, but +to change it altogether. It is the magician's wand, by means of which +he may summon into life whatever form and mould he pleases." Lord +Somerville, speaking of what breeders have done for sheep, says:--"It +would seem as if they had chalked out upon a wall a form perfect in +itself, and then had given it existence." That most skilful breeder, +Sir John Sebright, used to say, with respect to pigeons, that "he +would produce any given feather in three years, but it would take him +six years to obtain head and beak." In Saxony the importance of the +principle of selection in regard to merino sheep is so fully +recognised, that men follow it as a trade: the sheep are placed on a +table and are studied, like a picture by a connoisseur; this is done +three times at intervals of months, and the sheep are each time marked +and classed, so that the very best may ultimately be selected for +breeding. + +What English breeders have actually effected is proved by the enormous +prices given for animals with a good pedigree; and these have now been +exported to almost every quarter of the world. The improvement is by +no means generally due to crossing different breeds; all the best +breeders are strongly opposed to this practice, except sometimes +amongst closely allied sub-breeds. And when a cross has been made, the +closest selection is far more indispensable even than in ordinary +cases. If selection consisted merely in separating some very distinct +variety, and breeding from it, the principle would be so obvious as +hardly to be worth notice; but its importance consists in the great +effect produced by the accumulation in one direction, during +successive generations, of differences absolutely inappreciable by an +uneducated eye--differences which I for one have vainly attempted to +appreciate. Not one man in a thousand has accuracy of eye and judgment +sufficient to become an eminent breeder. If gifted with these +qualities, and he studies his subject for years, and devotes his +lifetime to it with indomitable perseverance, he will succeed, and may +make great improvements; if he wants any of these qualities, he will +assuredly fail. Few would readily believe in the natural capacity and +years of practice requisite to become even a skilful pigeon-fancier. + +The same principles are followed by horticulturists; but the +variations are here often more abrupt. No one supposes that our +choicest productions have been produced by a single variation from the +aboriginal stock. We have proofs that this is not so in some cases, in +which exact records have been kept; thus, to give a very trifling +instance, the steadily-increasing size of the common gooseberry may be +quoted. We see an astonishing improvement in many florists' flowers, +when the flowers of the present day are compared with drawings made +only twenty or thirty years ago. When a race of plants is once pretty +well established, the seed-raisers do not pick out the best plants, +but merely go over their seed-beds, and pull up the "rogues," as they +call the plants that deviate from the proper standard. With animals +this kind of selection is, in fact, also followed; for hardly any one +is so careless as to allow his worst animals to breed. + +In regard to plants, there is another means of observing the +accumulated effects of selection--namely, by comparing the diversity +of flowers in the different varieties of the same species in the +flower-garden; the diversity of leaves, pods, or tubers, or whatever +part is valued, in the kitchen-garden, in comparison with the flowers +of the same varieties; and the diversity of fruit of the same species +in the orchard, in comparison with the leaves and flowers of the same +set of varieties. See how different the leaves of the cabbage are, and +how extremely alike the flowers; how unlike the flowers of the +heartsease are, and how alike the leaves; how much the fruit of the +different kinds of gooseberries differ in size, colour, shape, and +hairiness, and yet the flowers present very slight differences. It is +not that the varieties which differ largely in some one point do not +differ at all in other points; this is hardly ever, perhaps never, the +case. The laws of correlation of growth, the importance of which +should never be overlooked, will ensure some differences; but, as a +general rule, I cannot doubt that the continued selection of slight +variations, either in the leaves, the flowers, or the fruit, will +produce races differing from each other chiefly in these characters. + +It may be objected that the principle of selection has been reduced to +methodical practice for scarcely more than three-quarters of a +century; it has certainly been more attended to of late years, and +many treatises have been published on the subject; and the result, I +may add, has been, in a corresponding degree, rapid and important. But +it is very far from true that the principle is a modern discovery. I +could give several references to the full acknowledgment of the +importance of the principle in works of high antiquity. In rude and +barbarous periods of English history choice animals were often +imported, and laws were passed to prevent their exportation: the +destruction of horses under a certain size was ordered, and this may +be compared to the "roguing" of plants by nurserymen. The principle of +selection I find distinctly given in an ancient Chinese encyclopaedia. +Explicit rules are laid down by some of the Roman classical writers. +From passages in Genesis, it is clear that the colour of domestic +animals was at that early period attended to. Savages now sometimes +cross their dogs with wild canine animals, to improve the breed, and +they formerly did so, as is attested by passages in Pliny. The savages +in South Africa match their draught cattle by colour, as do some of +the Esquimaux their teams of dogs. Livingstone shows how much good +domestic breeds are valued by the negroes of the interior of Africa +who have not associated with Europeans. Some of these facts do not +show actual selection, but they show that the breeding of domestic +animals was carefully attended to in ancient times, and is now +attended to by the lowest savages. It would, indeed, have been a +strange fact, had attention not been paid to breeding, for the +inheritance of good and bad qualities is so obvious. + +At the present time, eminent breeders try by methodical selection, +with a distinct object in view, to make a new strain or sub-breed, +superior to anything existing in the country. But, for our purpose, a +kind of Selection, which may be called Unconscious, and which results +from every one trying to possess and breed from the best individual +animals, is more important. Thus, a man who intends keeping pointers +naturally tries to get as good dogs as he can, and afterwards breeds +from his own best dogs, but he has no wish or expectation of +permanently altering the breed. Nevertheless I cannot doubt that this +process, continued during centuries, would improve and modify any +breed, in the same way as Bakewell, Collins, etc., by this very same +process, only carried on more methodically, did greatly modify, even +during their own lifetimes, the forms and qualities of their cattle. +Slow and insensible changes of this kind could never be recognised +unless actual measurements or careful drawings of the breeds in +question had been made long ago, which might serve for comparison. In +some cases, however, unchanged or but little changed individuals of +the same breed may be found in less civilised districts, where the +breed has been less improved. There is reason to believe that King +Charles's spaniel has been unconsciously modified to a large extent +since the time of that monarch. Some highly competent authorities are +convinced that the setter is directly derived from the spaniel, and +has probably been slowly altered from it. It is known that the English +pointer has been greatly changed within the last century, and in this +case the change has, it is believed, been chiefly effected by crosses +with the fox-hound; but what concerns us is, that the change has been +effected unconsciously and gradually, and yet so effectually, that, +though the old Spanish pointer certainly came from Spain, Mr. Borrow +has not seen, as I am informed by him, any native dog in Spain like +our pointer. + +By a similar process of selection, and by careful training, the whole +body of English racehorses have come to surpass in fleetness and size +the parent Arab stock, so that the latter, by the regulations for the +Goodwood Races, are favoured in the weights they carry. Lord Spencer +and others have shown how the cattle of England have increased in +weight and in early maturity, compared with the stock formerly kept in +this country. By comparing the accounts given in old pigeon treatises +of carriers and tumblers with these breeds as now existing in Britain, +India, and Persia, we can, I think, clearly trace the stages through +which they have insensibly passed, and come to differ so greatly from +the rock-pigeon. + +Youatt gives an excellent illustration of the effects of a course of +selection, which may be considered as unconsciously followed, in so +far that the breeders could never have expected or even have wished to +have produced the result which ensued--namely, the production of two +distinct strains. The two flocks of Leicester sheep kept by Mr. +Buckley and Mr. Burgess, as Mr. Youatt remarks, "have been purely bred +from the original stock of Mr. Bakewell for upwards of fifty years. +There is not a suspicion existing in the mind of any one at all +acquainted with the subject that the owner of either of them has +deviated in any one instance from the pure blood of Mr. Bakewell's +flock, and yet the difference between the sheep possessed by these two +gentlemen is so great that they have the appearance of being quite +different varieties." + +If there exist savages so barbarous as never to think of the inherited +character of the offspring of their domestic animals, yet any one +animal particularly useful to them, for any special purpose, would be +carefully preserved during famines and other accidents, to which +savages are so liable, and such choice animals would thus generally +leave more offspring than the inferior ones; so that in this case +there would be a kind of unconscious selection going on. We see the +value set on animals even by the barbarians of Tierra del Fuego, by +their killing and devouring their old women, in times of dearth, as of +less value than their dogs. + +In plants the same gradual process of improvement, through the +occasional preservation of the best individuals, whether or not +sufficiently distinct to be ranked at their first appearance as +distinct varieties, and whether or not two or more species or races +have become blended together by crossing, may plainly be recognised in +the increased size and beauty which we now see in the varieties of the +heartsease, rose, pelargonium, dahlia, and other plants, when compared +with the older varieties or with their parent-stocks. No one would +ever expect to get a first-rate heartsease or dahlia from the seed of +a wild plant. No one would expect to raise a first-rate melting pear +from the seed of a wild pear, though he might succeed from a poor +seedling growing wild, if it had come from a garden-stock. The pear, +though cultivated in classical times, appears, from Pliny's +description, to have been a fruit of very inferior quality. I have +seen great surprise expressed in horticultural works at the wonderful +skill of gardeners, in having produced such splendid results from such +poor materials; but the art, I cannot doubt, has been simple, and, as +far as the final result is concerned, has been followed almost +unconsciously. It has consisted in always cultivating the best known +variety, sowing its seeds, and, when a slightly better variety has +chanced to appear, selecting it, and so onwards. But the gardeners of +the classical period, who cultivated the best pear they could procure, +never thought what splendid fruit we should eat; though we owe our +excellent fruit, in some small degree, to their having naturally +chosen and preserved the best varieties they could anywhere find. + +A large amount of change in our cultivated plants, thus slowly and +unconsciously accumulated, explains, as I believe, the well-known +fact, that in a vast number of cases we cannot recognise, and +therefore do not know, the wild parent-stocks of the plants which have +been longest cultivated in our flower and kitchen gardens. If it has +taken centuries or thousands of years to improve or modify most of our +plants up to their present standard of usefulness to man, we can +understand how it is that neither Australia, the Cape of Good Hope, +nor any other region inhabited by quite uncivilised man, has afforded +us a single plant worth culture. It is not that these countries, so +rich in species, do not by a strange chance possess the aboriginal +stocks of any useful plants, but that the native plants have not been +improved by continued selection up to a standard of perfection +comparable with that given to the plants in countries anciently +civilised. + +In regard to the domestic animals kept by uncivilised man, it should +not be overlooked that they almost always have to struggle for their +own food, at least during certain seasons. And in two countries very +differently circumstanced, individuals of the same species, having +slightly different constitutions or structure, would often succeed +better in the one country than in the other, and thus by a process of +"natural selection," as will hereafter be more fully explained, two +sub-breeds might be formed. This, perhaps, partly explains what has +been remarked by some authors, namely, that the varieties kept by +savages have more of the character of species than the varieties kept +in civilised countries. + +On the view here given of the all-important part which selection by +man has played, it becomes at once obvious, how it is that our +domestic races show adaptation in their structure or in their habits +to man's wants or fancies. We can, I think, further understand the +frequently abnormal character of our domestic races, and likewise +their differences being so great in external characters and relatively +so slight in internal parts or organs. Man can hardly select, or only +with much difficulty, any deviation of structure excepting such as is +externally visible; and indeed he rarely cares for what is internal. +He can never act by selection, excepting on variations which are first +given to him in some slight degree by nature. No man would ever try to +make a fantail, till he saw a pigeon with a tail developed in some +slight degree in an unusual manner, or a pouter till he saw a pigeon +with a crop of somewhat unusual size; and the more abnormal or unusual +any character was when it first appeared, the more likely it would be +to catch his attention. But to use such an expression as trying to +make a fantail, is, I have no doubt, in most cases, utterly incorrect. +The man who first selected a pigeon with a slightly larger tail, never +dreamed what the descendants of that pigeon would become through +long-continued, partly unconscious and partly methodical selection. +Perhaps the parent bird of all fantails had only fourteen +tail-feathers somewhat expanded, like the present Java fantail, or +like individuals of other and distinct breeds, in which as many as +seventeen tail-feathers have been counted. Perhaps the first +pouter-pigeon did not inflate its crop much more than the turbit now +does the upper part of its oesophagus,--a habit which is disregarded +by all fanciers, as it is not one of the points of the breed. + +Nor let it be thought that some great deviation of structure would be +necessary to catch the fancier's eye: he perceives extremely small +differences, and it is in human nature to value any novelty, however +slight, in one's own possession. Nor must the value which would +formerly be set on any slight differences in the individuals of the +same species, be judged of by the value which would now be set on +them, after several breeds have once fairly been established. Many +slight differences might, and indeed do now, arise amongst pigeons, +which are rejected as faults or deviations from the standard of +perfection of each breed. The common goose has not given rise to any +marked varieties; hence the Thoulouse and the common breed, which +differ only in colour, that most fleeting of characters, have lately +been exhibited as distinct at our poultry-shows. + +I think these views further explain what has sometimes been +noticed--namely that we know nothing about the origin or history of +any of our domestic breeds. But, in fact, a breed, like a dialect of a +language, can hardly be said to have had a definite origin. A man +preserves and breeds from an individual with some slight deviation of +structure, or takes more care than usual in matching his best animals +and thus improves them, and the improved individuals slowly spread in +the immediate neighbourhood. But as yet they will hardly have a +distinct name, and from being only slightly valued, their history will +be disregarded. When further improved by the same slow and gradual +process, they will spread more widely, and will get recognised as +something distinct and valuable, and will then probably first receive +a provincial name. In semi-civilised countries, with little free +communication, the spreading and knowledge of any new sub-breed will +be a slow process. As soon as the points of value of the new sub-breed +are once fully acknowledged, the principle, as I have called it, of +unconscious selection will always tend,--perhaps more at one period +than at another, as the breed rises or falls in fashion,--perhaps more +in one district than in another, according to the state of +civilisation of the inhabitants--slowly to add to the characteristic +features of the breed, whatever they may be. But the chance will be +infinitely small of any record having been preserved of such slow, +varying, and insensible changes. + +I must now say a few words on the circumstances, favourable, or the +reverse, to man's power of selection. A high degree of variability is +obviously favourable, as freely giving the materials for selection to +work on; not that mere individual differences are not amply +sufficient, with extreme care, to allow of the accumulation of a large +amount of modification in almost any desired direction. But as +variations manifestly useful or pleasing to man appear only +occasionally, the chance of their appearance will be much increased by +a large number of individuals being kept; and hence this comes to be +of the highest importance to success. On this principle Marshall has +remarked, with respect to the sheep of parts of Yorkshire, that "as +they generally belong to poor people, and are mostly IN SMALL LOTS, +they never can be improved." On the other hand, nurserymen, from +raising large stocks of the same plants, are generally far more +successful than amateurs in getting new and valuable varieties. The +keeping of a large number of individuals of a species in any country +requires that the species should be placed under favourable conditions +of life, so as to breed freely in that country. When the individuals +of any species are scanty, all the individuals, whatever their quality +may be, will generally be allowed to breed, and this will effectually +prevent selection. But probably the most important point of all, is, +that the animal or plant should be so highly useful to man, or so much +valued by him, that the closest attention should be paid to even the +slightest deviation in the qualities or structure of each individual. +Unless such attention be paid nothing can be effected. I have seen it +gravely remarked, that it was most fortunate that the strawberry began +to vary just when gardeners began to attend closely to this plant. No +doubt the strawberry had always varied since it was cultivated, but +the slight varieties had been neglected. As soon, however, as +gardeners picked out individual plants with slightly larger, earlier, +or better fruit, and raised seedlings from them, and again picked out +the best seedlings and bred from them, then, there appeared (aided by +some crossing with distinct species) those many admirable varieties of +the strawberry which have been raised during the last thirty or forty +years. + +In the case of animals with separate sexes, facility in preventing +crosses is an important element of success in the formation of new +races,--at least, in a country which is already stocked with other +races. In this respect enclosure of the land plays a part. Wandering +savages or the inhabitants of open plains rarely possess more than one +breed of the same species. Pigeons can be mated for life, and this is +a great convenience to the fancier, for thus many races may be kept +true, though mingled in the same aviary; and this circumstance must +have largely favoured the improvement and formation of new breeds. +Pigeons, I may add, can be propagated in great numbers and at a very +quick rate, and inferior birds may be freely rejected, as when killed +they serve for food. On the other hand, cats, from their nocturnal +rambling habits, cannot be matched, and, although so much valued by +women and children, we hardly ever see a distinct breed kept up; such +breeds as we do sometimes see are almost always imported from some +other country, often from islands. Although I do not doubt that some +domestic animals vary less than others, yet the rarity or absence of +distinct breeds of the cat, the donkey, peacock, goose, etc., may be +attributed in main part to selection not having been brought into +play: in cats, from the difficulty in pairing them; in donkeys, from +only a few being kept by poor people, and little attention paid to +their breeding; in peacocks, from not being very easily reared and a +large stock not kept; in geese, from being valuable only for two +purposes, food and feathers, and more especially from no pleasure +having been felt in the display of distinct breeds. + +To sum up on the origin of our Domestic Races of animals and plants. I +believe that the conditions of life, from their action on the +reproductive system, are so far of the highest importance as causing +variability. I do not believe that variability is an inherent and +necessary contingency, under all circumstances, with all organic +beings, as some authors have thought. The effects of variability are +modified by various degrees of inheritance and of reversion. +Variability is governed by many unknown laws, more especially by that +of correlation of growth. Something may be attributed to the direct +action of the conditions of life. Something must be attributed to use +and disuse. The final result is thus rendered infinitely complex. In +some cases, I do not doubt that the intercrossing of species, +aboriginally distinct, has played an important part in the origin of +our domestic productions. When in any country several domestic breeds +have once been established, their occasional intercrossing, with the +aid of selection, has, no doubt, largely aided in the formation of new +sub-breeds; but the importance of the crossing of varieties has, I +believe, been greatly exaggerated, both in regard to animals and to +those plants which are propagated by seed. In plants which are +temporarily propagated by cuttings, buds, etc., the importance of the +crossing both of distinct species and of varieties is immense; for the +cultivator here quite disregards the extreme variability both of +hybrids and mongrels, and the frequent sterility of hybrids; but the +cases of plants not propagated by seed are of little importance to us, +for their endurance is only temporary. Over all these causes of Change +I am convinced that the accumulative action of Selection, whether +applied methodically and more quickly, or unconsciously and more +slowly, but more efficiently, is by far the predominant Power. + + diff --git a/logback-classic/src/test/resources/recursiveInit.xml b/logback-classic/src/test/resources/recursiveInit.xml index 4a573ab07468219eefddd614002096ee4b4a6765..420f12843f6a128c40390c32480d2c8b5f3a0d31 100644 --- a/logback-classic/src/test/resources/recursiveInit.xml +++ b/logback-classic/src/test/resources/recursiveInit.xml @@ -1,18 +1,18 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/logback-core/LICENSE.txt b/logback-core/LICENSE.txt index 667c2b5dec1895f20ac8ed369045589dc26ff610..d5dac89e45b96875fa0e06a0cf7022e757c4fc52 100644 --- a/logback-core/LICENSE.txt +++ b/logback-core/LICENSE.txt @@ -1,22 +1,22 @@ -Logback LICENSE ---------------- - -Logback: the reliable, generic, fast and flexible logging library for -Java. - -Copyright (C) 2000-2008, QOS.ch - -Source code and binaries for logback, including logback-core, -logback-classic and logback-access modules, are distributed under the -GNU Lesser General Public License Version 2.1, as published by the -Free Software Foundation. - -This library is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as -published by the Free Software Foundation; either version 2.1 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. +Logback LICENSE +--------------- + +Logback: the reliable, generic, fast and flexible logging library for +Java. + +Copyright (C) 2000-2008, QOS.ch + +Source code and binaries for logback, including logback-core, +logback-classic and logback-access modules, are distributed under the +GNU Lesser General Public License Version 2.1, as published by the +Free Software Foundation. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. diff --git a/logback-core/pom.xml b/logback-core/pom.xml index 270ed8d28af424a536c8dcd574793adfe2195406..11df65869f52493f1f4d76f26ea8faaf0c72d418 100644 --- a/logback-core/pom.xml +++ b/logback-core/pom.xml @@ -1,151 +1,151 @@ - - - - ch.qos.logback - logback-parent - 0.9.18-SNAPSHOT - - - 4.0.0 - - ch.qos.logback - logback-core - ${parent.version} - jar - Logback Core Module - - http://logback.qos.ch - - - Logback: the generic, reliable, fast and flexible logging library for Java. - - - - - Eclipse Public License - v 1.0 - http://www.eclipse.org/legal/epl-v10.html - - - - GNU Lesser General Public License - http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - - - - - - janino - janino - compile - true - - - javax.mail - mail - compile - true - - - org.apache.geronimo.specs - geronimo-jms_1.1_spec - compile - true - - - - org.easymock - easymock - 2.4 - test - - - - javax.servlet - servlet-api - compile - true - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - - - - - org.apache.maven.plugins - maven-surefire-plugin - - once - plain - false - - **/All*Test.java - **/PackageTest.java - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - - - - bundle-test-jar - package - - jar - test-jar - - - - - - - org.apache.felix - maven-bundle-plugin - true - - - bundle-manifest - process-classes - - manifest - - - - - - ch.qos.logback.core.* - - javax.*;resolution:=optional, - org.xml.*;resolution:=optional, - org.codehaus.janino;resolution:=optional, - * - - J2SE-1.5 - - - - - - + + + + ch.qos.logback + logback-parent + 0.9.18-SNAPSHOT + + + 4.0.0 + + ch.qos.logback + logback-core + ${parent.version} + jar + Logback Core Module + + http://logback.qos.ch + + + Logback: the generic, reliable, fast and flexible logging library for Java. + + + + + Eclipse Public License - v 1.0 + http://www.eclipse.org/legal/epl-v10.html + + + + GNU Lesser General Public License + http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html + + + + + + janino + janino + compile + true + + + javax.mail + mail + compile + true + + + org.apache.geronimo.specs + geronimo-jms_1.1_spec + compile + true + + + + org.easymock + easymock + 2.4 + test + + + + javax.servlet + servlet-api + compile + true + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + org.apache.maven.plugins + maven-surefire-plugin + + once + plain + false + + **/All*Test.java + **/PackageTest.java + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + bundle-test-jar + package + + jar + test-jar + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + ch.qos.logback.core.* + + javax.*;resolution:=optional, + org.xml.*;resolution:=optional, + org.codehaus.janino;resolution:=optional, + * + + J2SE-1.5 + + + + + + \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/Appender.java b/logback-core/src/main/java/ch/qos/logback/core/Appender.java index 257b93d928dc8b421c13cd964fb7d1133b8e868c..856e3879f1723813a19512459df077a5be5f2932 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/Appender.java +++ b/logback-core/src/main/java/ch/qos/logback/core/Appender.java @@ -1,52 +1,52 @@ -/** - * 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; - -import ch.qos.logback.core.spi.ContextAware; -import ch.qos.logback.core.spi.FilterAttachable; -import ch.qos.logback.core.spi.LifeCycle; - - -public interface Appender extends LifeCycle, ContextAware, FilterAttachable { - - /** - * Get the name of this appender. The name uniquely identifies the appender. - */ - public String getName(); - - /** - * This is where an appender accomplishes its work. Note that the argument - * is of type Object. - * @param event - */ - void doAppend(E event) throws LogbackException; - - /** - * Set the {@link Layout} for this appender. - */ - public void setLayout(Layout layout); - - /** - * Returns this appenders layout. - */ - public Layout getLayout(); - - /** - * Set the name of this appender. The name is used by other components to - * identify this appender. - * - */ - public void setName(String name); - -} +/** + * 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; + +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.FilterAttachable; +import ch.qos.logback.core.spi.LifeCycle; + + +public interface Appender extends LifeCycle, ContextAware, FilterAttachable { + + /** + * Get the name of this appender. The name uniquely identifies the appender. + */ + public String getName(); + + /** + * This is where an appender accomplishes its work. Note that the argument + * is of type Object. + * @param event + */ + void doAppend(E event) throws LogbackException; + + /** + * Set the {@link Layout} for this appender. + */ + public void setLayout(Layout layout); + + /** + * Returns this appenders layout. + */ + public Layout getLayout(); + + /** + * Set the name of this appender. The name is used by other components to + * identify this appender. + * + */ + public void setName(String name); + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java index 4d8c6cb55ee193c4382677e796496f605cee46c2..4183767a169206efdb1d7b27b84cb1c20a8c9ba7 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java @@ -1,162 +1,162 @@ -/** - * 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; - -import java.util.List; - -import ch.qos.logback.core.filter.Filter; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.spi.FilterAttachableImpl; -import ch.qos.logback.core.spi.FilterReply; -import ch.qos.logback.core.status.WarnStatus; - -/** - * Sets a skeleton implementation for appenders. - * - *

For more information about this appender, please refer to the online - * manual at http://logback.qos.ch/manual/appenders.html#AppenderBase - * - * @author Ceki Gülcü - */ -abstract public class AppenderBase extends ContextAwareBase implements - Appender { - - /** - * The layout variable does not need to be set depending on the appender. Some - * appenders do not need a layout. - */ - protected Layout layout; - - protected boolean started = false; - - /** - * The guard prevents an appender from repeatedly calling its own doAppend - * method. - */ - private boolean guard = false; - - /** - * Appenders are named. - */ - protected String name; - - private FilterAttachableImpl fai = new FilterAttachableImpl(); - - public String getName() { - return name; - } - - private int statusRepeatCount = 0; - private int exceptionCount = 0; - - static final int ALLOWED_REPEATS = 5; - - public synchronized void doAppend(E eventObject) { - // WARNING: The guard check MUST be the first statement in the - // doAppend() method. - - // prevent re-entry. - if (guard) { - return; - } - - try { - guard = true; - - if (!this.started) { - if (statusRepeatCount++ < ALLOWED_REPEATS) { - addStatus(new WarnStatus( - "Attempted to append to non started appender [" + name + "].", - this)); - } - return; - } - - if (getFilterChainDecision(eventObject) == FilterReply.DENY) { - return; - } - - // ok, we now invoke derived class' implementation of append - this.append(eventObject); - - } catch (Exception e) { - if (exceptionCount++ < ALLOWED_REPEATS) { - addError("Appender [" + name + "] failed to append.", e); - } - } finally { - guard = false; - } - } - - abstract protected void append(E eventObject); - - /** - * Set the name of this appender. - */ - public void setName(String name) { - this.name = name; - } - - public void start() { - started = true; - } - - public void stop() { - started = false; - } - - public boolean isStarted() { - return started; - } - - public String toString() { - return this.getClass().getName() + "[" + name + "]"; - } - - public void addFilter(Filter newFilter) { - fai.addFilter(newFilter); - } - - public Filter getFirstFilter() { - return fai.getFirstFilter(); - } - - public void clearAllFilters() { - fai.clearAllFilters(); - } - - public List> getCopyOfAttachedFiltersList() { - return fai.getCopyOfAttachedFiltersList(); - } - - public FilterReply getFilterChainDecision(E event) { - return fai.getFilterChainDecision(event); - } - - /** - * Returns the layout of this appender. The returned value may be null if this - * appender does not have a layout. - */ - public Layout getLayout() { - return layout; - } - - /** - * Set the layout for this appender. Note that some appenders have their own - * (fixed) layouts or do not use any. - */ - public void setLayout(Layout layout) { - this.layout = layout; - } -} +/** + * 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; + +import java.util.List; + +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.FilterAttachableImpl; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.status.WarnStatus; + +/** + * Sets a skeleton implementation for appenders. + * + *

For more information about this appender, please refer to the online + * manual at http://logback.qos.ch/manual/appenders.html#AppenderBase + * + * @author Ceki Gülcü + */ +abstract public class AppenderBase extends ContextAwareBase implements + Appender { + + /** + * The layout variable does not need to be set depending on the appender. Some + * appenders do not need a layout. + */ + protected Layout layout; + + protected boolean started = false; + + /** + * The guard prevents an appender from repeatedly calling its own doAppend + * method. + */ + private boolean guard = false; + + /** + * Appenders are named. + */ + protected String name; + + private FilterAttachableImpl fai = new FilterAttachableImpl(); + + public String getName() { + return name; + } + + private int statusRepeatCount = 0; + private int exceptionCount = 0; + + static final int ALLOWED_REPEATS = 5; + + public synchronized void doAppend(E eventObject) { + // WARNING: The guard check MUST be the first statement in the + // doAppend() method. + + // prevent re-entry. + if (guard) { + return; + } + + try { + guard = true; + + if (!this.started) { + if (statusRepeatCount++ < ALLOWED_REPEATS) { + addStatus(new WarnStatus( + "Attempted to append to non started appender [" + name + "].", + this)); + } + return; + } + + if (getFilterChainDecision(eventObject) == FilterReply.DENY) { + return; + } + + // ok, we now invoke derived class' implementation of append + this.append(eventObject); + + } catch (Exception e) { + if (exceptionCount++ < ALLOWED_REPEATS) { + addError("Appender [" + name + "] failed to append.", e); + } + } finally { + guard = false; + } + } + + abstract protected void append(E eventObject); + + /** + * Set the name of this appender. + */ + public void setName(String name) { + this.name = name; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + + public boolean isStarted() { + return started; + } + + public String toString() { + return this.getClass().getName() + "[" + name + "]"; + } + + public void addFilter(Filter newFilter) { + fai.addFilter(newFilter); + } + + public Filter getFirstFilter() { + return fai.getFirstFilter(); + } + + public void clearAllFilters() { + fai.clearAllFilters(); + } + + public List> getCopyOfAttachedFiltersList() { + return fai.getCopyOfAttachedFiltersList(); + } + + public FilterReply getFilterChainDecision(E event) { + return fai.getFilterChainDecision(event); + } + + /** + * Returns the layout of this appender. The returned value may be null if this + * appender does not have a layout. + */ + public Layout getLayout() { + return layout; + } + + /** + * Set the layout for this appender. Note that some appenders have their own + * (fixed) layouts or do not use any. + */ + public void setLayout(Layout layout) { + this.layout = layout; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java b/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java index e578d8fbe9525bfbb1d008060f960b297e6b56db..54149f2f0ca072b916040035c2091d1ecd1ce163 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java +++ b/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java @@ -1,125 +1,125 @@ -/** - * 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; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.core.helpers.CyclicBuffer; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusListener; -import ch.qos.logback.core.status.StatusManager; - -public class BasicStatusManager implements StatusManager { - - public static final int MAX_HEADER_COUNT = 150; - public static final int TAIL_SIZE = 150; - - int count = 0; - - // protected access was requested in http://jira.qos.ch/browse/LBCORE-36 - final protected List statusList = new ArrayList(); - final protected CyclicBuffer tailBuffer = new CyclicBuffer( - TAIL_SIZE); - final protected Object statusListLock = new Object(); - - int level = Status.INFO; - - // protected access was requested in http://jira.qos.ch/browse/LBCORE-36 - final protected List statusListenerList = new ArrayList(); - final protected Object statusListenerListLock = new Object(); - - // Note on synchronization - // This class contains two separate locks statusListLock and - // statusListenerListLock guarding respectively the statusList+tailBuffer and - // statusListenerList fields. The locks are used internally - // without cycles. They are exposed to derived classes which should be careful - // not to create deadlock cycles. - - /** - * Add a new status object. - * - * @param Status - * the status message to add - */ - public void add(Status newStatus) { - // LBCORE-72: fire event before the count check - fireStatusAddEvent(newStatus); - - count++; - if (newStatus.getLevel() > level) { - level = newStatus.getLevel(); - } - - synchronized (statusListLock) { - if (statusList.size() < MAX_HEADER_COUNT) { - statusList.add(newStatus); - } else { - tailBuffer.add(newStatus); - } - } - - } - - public List getCopyOfStatusList() { - synchronized (statusListLock) { - List tList = new ArrayList(statusList); - tList.addAll(tailBuffer.asList()); - return tList; - } - } - - private void fireStatusAddEvent(Status status) { - synchronized (statusListenerListLock) { - for (StatusListener sl : statusListenerList) { - sl.addStatusEvent(status); - } - } - } - - public void clear() { - synchronized (statusListLock) { - count = 0; - statusList.clear(); - tailBuffer.clear(); - } - } - - public int getLevel() { - return level; - } - - public int getCount() { - return count; - } - - public void add(StatusListener listener) { - synchronized (statusListenerListLock) { - statusListenerList.add(listener); - } - } - - public void remove(StatusListener listener) { - synchronized (statusListenerListLock) { - statusListenerList.remove(listener); - } - } - - public List getCopyOfStatusListenerList() { - synchronized (statusListenerListLock) { - return new ArrayList(statusListenerList); - } - } - -} +/** + * 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; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.core.helpers.CyclicBuffer; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.status.StatusManager; + +public class BasicStatusManager implements StatusManager { + + public static final int MAX_HEADER_COUNT = 150; + public static final int TAIL_SIZE = 150; + + int count = 0; + + // protected access was requested in http://jira.qos.ch/browse/LBCORE-36 + final protected List statusList = new ArrayList(); + final protected CyclicBuffer tailBuffer = new CyclicBuffer( + TAIL_SIZE); + final protected Object statusListLock = new Object(); + + int level = Status.INFO; + + // protected access was requested in http://jira.qos.ch/browse/LBCORE-36 + final protected List statusListenerList = new ArrayList(); + final protected Object statusListenerListLock = new Object(); + + // Note on synchronization + // This class contains two separate locks statusListLock and + // statusListenerListLock guarding respectively the statusList+tailBuffer and + // statusListenerList fields. The locks are used internally + // without cycles. They are exposed to derived classes which should be careful + // not to create deadlock cycles. + + /** + * Add a new status object. + * + * @param Status + * the status message to add + */ + public void add(Status newStatus) { + // LBCORE-72: fire event before the count check + fireStatusAddEvent(newStatus); + + count++; + if (newStatus.getLevel() > level) { + level = newStatus.getLevel(); + } + + synchronized (statusListLock) { + if (statusList.size() < MAX_HEADER_COUNT) { + statusList.add(newStatus); + } else { + tailBuffer.add(newStatus); + } + } + + } + + public List getCopyOfStatusList() { + synchronized (statusListLock) { + List tList = new ArrayList(statusList); + tList.addAll(tailBuffer.asList()); + return tList; + } + } + + private void fireStatusAddEvent(Status status) { + synchronized (statusListenerListLock) { + for (StatusListener sl : statusListenerList) { + sl.addStatusEvent(status); + } + } + } + + public void clear() { + synchronized (statusListLock) { + count = 0; + statusList.clear(); + tailBuffer.clear(); + } + } + + public int getLevel() { + return level; + } + + public int getCount() { + return count; + } + + public void add(StatusListener listener) { + synchronized (statusListenerListLock) { + statusListenerList.add(listener); + } + } + + public void remove(StatusListener listener) { + synchronized (statusListenerListLock) { + statusListenerList.remove(listener); + } + } + + public List getCopyOfStatusListenerList() { + synchronized (statusListenerListLock) { + return new ArrayList(statusListenerList); + } + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/ConsoleAppender.java b/logback-core/src/main/java/ch/qos/logback/core/ConsoleAppender.java index c9a24ee2657ba25ed0e3ae6ab890b0c4d525e7ec..1c52db7d1f4f57bdfd9cda584194efc635c33217 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/ConsoleAppender.java +++ b/logback-core/src/main/java/ch/qos/logback/core/ConsoleAppender.java @@ -1,93 +1,93 @@ -/** - * 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; - -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.WarnStatus; - - -/** - * ConsoleAppender appends log events to System.out or - * System.err using a layout specified by the user. The default - * target is System.out. - * - * For more information about this appender, please refer to the online manual at - * http://logback.qos.ch/manual/appenders.html#ConsoleAppender - * - * @author Ceki Gülcü - */ - -public class ConsoleAppender extends WriterAppender { - - public static final String SYSTEM_OUT = "System.out"; - public static final String SYSTEM_ERR = "System.err"; - protected String target = SYSTEM_OUT; - - /** - * As in most logback components, the default constructor does nothing. - */ - public ConsoleAppender() { - } - - /** - * Sets the value of the Target option. Recognized values are - * "System.out" and "System.err". Any other value will be ignored. - */ - public void setTarget(String value) { - String v = value.trim(); - - if (SYSTEM_OUT.equalsIgnoreCase(v)) { - target = SYSTEM_OUT; - } else if (SYSTEM_ERR.equalsIgnoreCase(v)) { - target = SYSTEM_ERR; - } else { - targetWarn(value); - } - } - - /** - * Returns the current value of the Target property. The default - * value of the option is "System.out". - * - * See also {@link #setTarget}. - */ - public String getTarget() { - return target; - } - - void targetWarn(String val) { - Status status = new WarnStatus("["+val+" should be System.out or System.err.", this); - status.add(new WarnStatus("Using previously set target, System.out by default.", this)); - addStatus(status); - } - - public void start() { - if (target.equals(SYSTEM_OUT)) { - setWriter(createWriter(System.out)); - } else { - setWriter(createWriter(System.err)); - } - super.start(); - } - - /** - * This method overrides the parent {@link WriterAppender#closeWriter} - * implementation because the console stream is not ours to close. - */ - protected final void closeWriter() { - writeFooter(); - } - } - - +/** + * 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; + +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.WarnStatus; + + +/** + * ConsoleAppender appends log events to System.out or + * System.err using a layout specified by the user. The default + * target is System.out. + * + * For more information about this appender, please refer to the online manual at + * http://logback.qos.ch/manual/appenders.html#ConsoleAppender + * + * @author Ceki Gülcü + */ + +public class ConsoleAppender extends WriterAppender { + + public static final String SYSTEM_OUT = "System.out"; + public static final String SYSTEM_ERR = "System.err"; + protected String target = SYSTEM_OUT; + + /** + * As in most logback components, the default constructor does nothing. + */ + public ConsoleAppender() { + } + + /** + * Sets the value of the Target option. Recognized values are + * "System.out" and "System.err". Any other value will be ignored. + */ + public void setTarget(String value) { + String v = value.trim(); + + if (SYSTEM_OUT.equalsIgnoreCase(v)) { + target = SYSTEM_OUT; + } else if (SYSTEM_ERR.equalsIgnoreCase(v)) { + target = SYSTEM_ERR; + } else { + targetWarn(value); + } + } + + /** + * Returns the current value of the Target property. The default + * value of the option is "System.out". + * + * See also {@link #setTarget}. + */ + public String getTarget() { + return target; + } + + void targetWarn(String val) { + Status status = new WarnStatus("["+val+" should be System.out or System.err.", this); + status.add(new WarnStatus("Using previously set target, System.out by default.", this)); + addStatus(status); + } + + public void start() { + if (target.equals(SYSTEM_OUT)) { + setWriter(createWriter(System.out)); + } else { + setWriter(createWriter(System.err)); + } + super.start(); + } + + /** + * This method overrides the parent {@link WriterAppender#closeWriter} + * implementation because the console stream is not ours to close. + */ + protected final void closeWriter() { + writeFooter(); + } + } + + diff --git a/logback-core/src/main/java/ch/qos/logback/core/Context.java b/logback-core/src/main/java/ch/qos/logback/core/Context.java index 863896f344362d8cf90253b3cab75079c532315c..040be88c37682e30a71449b5479088efd2263620 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/Context.java +++ b/logback-core/src/main/java/ch/qos/logback/core/Context.java @@ -1,96 +1,96 @@ -/** - * 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; - -import ch.qos.logback.core.spi.PropertyContainer; -import ch.qos.logback.core.status.StatusManager; - -/** - * A context is the main anchorage point of all logback components. - * - * @author Ceki Gulcu - * - */ -public interface Context extends PropertyContainer { - - /** - * Return the StatusManager instance in use. - * - * @return the {@link StatusManager} instance in use. - */ - public StatusManager getStatusManager(); - - /** - * A Context can act as a store for various objects used by LOGBack - * components. - * - * @return The object stored under 'key'. - */ - public Object getObject(String key); - - /** - * Store an object under 'key'. If no object can be found, null is returned. - * - * @param key - * @param value - */ - public void putObject(String key, Object value); - - /** - * Get all the properties for this context as a Map. Note that the returned - * cop might be a copy not the original. Thus, modifying the returned Map will - * have no effect (on the original.) - * - * @return - */ - // public Map getPropertyMap(); - /** - * Get the property of this context. - */ - public String getProperty(String key); - - /** - * Set a property of this context. - */ - public void putProperty(String key, String value); - - /** - * Contexts are named objects. - * - * @return the name for this context - */ - public String getName(); - - /** - * The name of the context can be set only once. - * - * @param name - */ - public void setName(String name); - - /** - * The time at which this context was created, expressed in - * millisecond elapsed since the epoch (1.1.1970). - * - * @return The time as measured when this class was created. - */ - public long getBithTime(); - - /** - * Object used for synchronization purposes. - * INTENDED FOR INTERNAL USAGE. - */ - public Object getConfigurationLock(); - -} +/** + * 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; + +import ch.qos.logback.core.spi.PropertyContainer; +import ch.qos.logback.core.status.StatusManager; + +/** + * A context is the main anchorage point of all logback components. + * + * @author Ceki Gulcu + * + */ +public interface Context extends PropertyContainer { + + /** + * Return the StatusManager instance in use. + * + * @return the {@link StatusManager} instance in use. + */ + public StatusManager getStatusManager(); + + /** + * A Context can act as a store for various objects used by LOGBack + * components. + * + * @return The object stored under 'key'. + */ + public Object getObject(String key); + + /** + * Store an object under 'key'. If no object can be found, null is returned. + * + * @param key + * @param value + */ + public void putObject(String key, Object value); + + /** + * Get all the properties for this context as a Map. Note that the returned + * cop might be a copy not the original. Thus, modifying the returned Map will + * have no effect (on the original.) + * + * @return + */ + // public Map getPropertyMap(); + /** + * Get the property of this context. + */ + public String getProperty(String key); + + /** + * Set a property of this context. + */ + public void putProperty(String key, String value); + + /** + * Contexts are named objects. + * + * @return the name for this context + */ + public String getName(); + + /** + * The name of the context can be set only once. + * + * @param name + */ + public void setName(String name); + + /** + * The time at which this context was created, expressed in + * millisecond elapsed since the epoch (1.1.1970). + * + * @return The time as measured when this class was created. + */ + public long getBithTime(); + + /** + * Object used for synchronization purposes. + * INTENDED FOR INTERNAL USAGE. + */ + public Object getConfigurationLock(); + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/ContextBase.java b/logback-core/src/main/java/ch/qos/logback/core/ContextBase.java index 5e2fd6e23404cb43f10f163f4b8e9965757e07e6..73386912e35a0a04dbbcaf13c2eef90f45bbc154 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/ContextBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/ContextBase.java @@ -1,117 +1,117 @@ -/** - * 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; - -import java.util.HashMap; -import java.util.Map; - -import ch.qos.logback.core.status.StatusManager; - -public class ContextBase implements Context { - - private long birthTime = System.currentTimeMillis(); - - private String name; - private StatusManager sm = new BasicStatusManager(); - // TODO propertyMap should be observable so that we can be notified - // when it changes so that a new instance of propertyMap can be - // serialized. For the time being, we ignore this shortcoming. - Map propertyMap = new HashMap(); - Map objectMap = new HashMap(); - - Object configurationLock = new Object(); - - public StatusManager getStatusManager() { - return sm; - } - - /** - * Set the {@link StatusManager} for this context. Note that by default this - * context is initialized with a {@link BasicStatusManager}. A null value for - * the 'statusManager' argument is not allowed. - * - *

A malicious attacker can set the status manager to a dummy instance, - * disabling internal error reporting. - * - * @param statusManager - * the new status manager - */ - public void setStatusManager(StatusManager statusManager) { - // this method was added in response to http://jira.qos.ch/browse/LBCORE-35 - if (sm == null) { - throw new IllegalArgumentException("null StatusManager not allowed"); - } - this.sm = statusManager; - } - - public Map getCopyOfPropertyMap() { - return new HashMap(propertyMap); - } - - public void putProperty(String key, String val) { - this.propertyMap.put(key, val); - } - - public String getProperty(String key) { - return (String) this.propertyMap.get(key); - } - - public Object getObject(String key) { - return objectMap.get(key); - } - - public void putObject(String key, Object value) { - objectMap.put(key, value); - } - - public String getName() { - return name; - } - - /** - * Clear the internal objectMap and all properties. - */ - public void reset() { - propertyMap.clear(); - objectMap.clear(); - } - - /** - * The context name can be set only if it is not already set, or if the - * current name is the default context name, namely "default", or if the - * current name and the old name are the same. - * - * @throws IllegalStateException - * if the context already has a name, other than "default". - */ - public void setName(String name) throws IllegalStateException { - if (name != null && name.equals(this.name)) { - return; // idempotent naming - } - if (this.name == null - || CoreConstants.DEFAULT_CONTEXT_NAME.equals(this.name)) { - this.name = name; - } else { - throw new IllegalStateException("Context has been already given a name"); - } - } - - public long getBithTime() { - return birthTime; - } - - public Object getConfigurationLock() { - return configurationLock; - } -} +/** + * 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; + +import java.util.HashMap; +import java.util.Map; + +import ch.qos.logback.core.status.StatusManager; + +public class ContextBase implements Context { + + private long birthTime = System.currentTimeMillis(); + + private String name; + private StatusManager sm = new BasicStatusManager(); + // TODO propertyMap should be observable so that we can be notified + // when it changes so that a new instance of propertyMap can be + // serialized. For the time being, we ignore this shortcoming. + Map propertyMap = new HashMap(); + Map objectMap = new HashMap(); + + Object configurationLock = new Object(); + + public StatusManager getStatusManager() { + return sm; + } + + /** + * Set the {@link StatusManager} for this context. Note that by default this + * context is initialized with a {@link BasicStatusManager}. A null value for + * the 'statusManager' argument is not allowed. + * + *

A malicious attacker can set the status manager to a dummy instance, + * disabling internal error reporting. + * + * @param statusManager + * the new status manager + */ + public void setStatusManager(StatusManager statusManager) { + // this method was added in response to http://jira.qos.ch/browse/LBCORE-35 + if (sm == null) { + throw new IllegalArgumentException("null StatusManager not allowed"); + } + this.sm = statusManager; + } + + public Map getCopyOfPropertyMap() { + return new HashMap(propertyMap); + } + + public void putProperty(String key, String val) { + this.propertyMap.put(key, val); + } + + public String getProperty(String key) { + return (String) this.propertyMap.get(key); + } + + public Object getObject(String key) { + return objectMap.get(key); + } + + public void putObject(String key, Object value) { + objectMap.put(key, value); + } + + public String getName() { + return name; + } + + /** + * Clear the internal objectMap and all properties. + */ + public void reset() { + propertyMap.clear(); + objectMap.clear(); + } + + /** + * The context name can be set only if it is not already set, or if the + * current name is the default context name, namely "default", or if the + * current name and the old name are the same. + * + * @throws IllegalStateException + * if the context already has a name, other than "default". + */ + public void setName(String name) throws IllegalStateException { + if (name != null && name.equals(this.name)) { + return; // idempotent naming + } + if (this.name == null + || CoreConstants.DEFAULT_CONTEXT_NAME.equals(this.name)) { + this.name = name; + } else { + throw new IllegalStateException("Context has been already given a name"); + } + } + + public long getBithTime() { + return birthTime; + } + + public Object getConfigurationLock() { + return configurationLock; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java b/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java index 520c5f44f56a1f01b1043e573bf3f310ea7dd13e..d42c01578c3183238eb264012abcb4c10bab0923 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java +++ b/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java @@ -1,107 +1,107 @@ -/** - * 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; - -public class CoreConstants { - - // Note that the line.separator property can be looked up even by - // applets. - public static final String LINE_SEPARATOR = System.getProperty("line.separator"); - public static final int LINE_SEPARATOR_LEN = LINE_SEPARATOR.length(); - - - public static final String CODES_URL = "http://logback.qos.ch/codes.html"; - - /** - * The default context name. - */ - public static final String DEFAULT_CONTEXT_NAME = "default"; - /** - * Customized pattern conversion rules are stored under this key in the - * {@link Context} object store. - */ - public static final String PATTERN_RULE_REGISTRY = "PATTERN_RULE_REGISTRY"; - - public static final String ISO8601_STR = "ISO8601"; - public static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS"; - - /** - * Time format used in Common Log Format - */ - static public final String CLF_DATE_PATTERN = "dd/MM/yyyy:HH:mm:ss Z"; - - /** - * The key used in locating the evaluator map in context's object map. - */ - static public final String EVALUATOR_MAP = "EVALUATOR_MAP"; - - /** - * By convention, we assume that the static method named "valueOf" taking - * a string argument can restore a given object from its string - * representation. - * - *

Classes participating in this convention must be declared - * as stringStorable in a (logback) context. - */ - static public final String VALUE_OF = "valueOf"; - - /** - * An empty string. - */ - public final static String EMPTY_STRING = ""; - - /** - * An empty string array. - */ - public final static String[] EMPTY_STRING_ARRAY = new String[] {}; - - /** - * An empty Class array. - */ - public final static Class[] EMPTY_CLASS_ARRAY = new Class[] {}; - public final static String CAUSED_BY = "Caused by: "; - - - public final static char PERCENT_CHAR = '%'; - - /** - * Number of rows before in an HTML table before, - * we close the table and create a new one - */ - public static final int TABLE_ROW_LIMIT = 10000; - - - // reset the ObjectOutputStream every OOS_RESET_FREQUENCY calls - // this avoid serious memory leaks - public static final int OOS_RESET_FREQUENCY = 70; - - /** - * The reference bogo instructions per second on - * Ceki's machine (Orion) - */ - public static long REFERENCE_BIPS = 9000; - - - - static public final char DOT = '.'; - static public final char TAB = '\t'; - static public final char DOLLAR = '$'; - - static public final String SEE_FNP_NOT_SET = "See also http://logback.qos.ch/codes.html#tbr_fnp_not_set"; - - // The url used for the last configuration via Joran. If a file is used for the - // configuration, then file.getURL() is registered - public static String URL_OF_LAST_CONFIGURATION_VIA_JORAN = "URL_OF_LAST_CONFIGURATION_VIA_JORAN"; - -} +/** + * 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; + +public class CoreConstants { + + // Note that the line.separator property can be looked up even by + // applets. + public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + public static final int LINE_SEPARATOR_LEN = LINE_SEPARATOR.length(); + + + public static final String CODES_URL = "http://logback.qos.ch/codes.html"; + + /** + * The default context name. + */ + public static final String DEFAULT_CONTEXT_NAME = "default"; + /** + * Customized pattern conversion rules are stored under this key in the + * {@link Context} object store. + */ + public static final String PATTERN_RULE_REGISTRY = "PATTERN_RULE_REGISTRY"; + + public static final String ISO8601_STR = "ISO8601"; + public static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS"; + + /** + * Time format used in Common Log Format + */ + static public final String CLF_DATE_PATTERN = "dd/MM/yyyy:HH:mm:ss Z"; + + /** + * The key used in locating the evaluator map in context's object map. + */ + static public final String EVALUATOR_MAP = "EVALUATOR_MAP"; + + /** + * By convention, we assume that the static method named "valueOf" taking + * a string argument can restore a given object from its string + * representation. + * + *

Classes participating in this convention must be declared + * as stringStorable in a (logback) context. + */ + static public final String VALUE_OF = "valueOf"; + + /** + * An empty string. + */ + public final static String EMPTY_STRING = ""; + + /** + * An empty string array. + */ + public final static String[] EMPTY_STRING_ARRAY = new String[] {}; + + /** + * An empty Class array. + */ + public final static Class[] EMPTY_CLASS_ARRAY = new Class[] {}; + public final static String CAUSED_BY = "Caused by: "; + + + public final static char PERCENT_CHAR = '%'; + + /** + * Number of rows before in an HTML table before, + * we close the table and create a new one + */ + public static final int TABLE_ROW_LIMIT = 10000; + + + // reset the ObjectOutputStream every OOS_RESET_FREQUENCY calls + // this avoid serious memory leaks + public static final int OOS_RESET_FREQUENCY = 70; + + /** + * The reference bogo instructions per second on + * Ceki's machine (Orion) + */ + public static long REFERENCE_BIPS = 9000; + + + + static public final char DOT = '.'; + static public final char TAB = '\t'; + static public final char DOLLAR = '$'; + + static public final String SEE_FNP_NOT_SET = "See also http://logback.qos.ch/codes.html#tbr_fnp_not_set"; + + // The url used for the last configuration via Joran. If a file is used for the + // configuration, then file.getURL() is registered + public static String URL_OF_LAST_CONFIGURATION_VIA_JORAN = "URL_OF_LAST_CONFIGURATION_VIA_JORAN"; + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/FileAppender.java b/logback-core/src/main/java/ch/qos/logback/core/FileAppender.java index 64de4100a73e01b6c17d65fa8f522de1cbdd9cdf..dd3fda624a0721a0bd177c982e932b828ff0072d 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/FileAppender.java +++ b/logback-core/src/main/java/ch/qos/logback/core/FileAppender.java @@ -1,273 +1,273 @@ -/** - * 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; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.Writer; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; - -import ch.qos.logback.core.util.FileUtil; - -/** - * FileAppender appends log events to a file. - * - * For more information about this appender, please refer to the online manual - * at http://logback.qos.ch/manual/appenders.html#FileAppender - * - * @author Ceki Gülcü - */ -public class FileAppender extends WriterAppender { - - /** - * Append to or truncate the file? The default value for this variable is - * true, meaning that by default a FileAppender - * will append to an existing file and not truncate it. - */ - protected boolean append = true; - - /** - * The name of the active log file. - */ - protected String fileName = null; - - /** - * Do we do bufferedIO? - */ - protected boolean bufferedIO = false; - - /** - * The size of the IO buffer. Default is 8K. - */ - protected int bufferSize = 8 * 1024; - - private boolean prudent = false; - - private FileChannel fileChannel = null; - - /** - * As in most cases, the default constructor does nothing. - */ - public FileAppender() { - } - - /** - * The File property takes a string value which should be the name of - * the file to append to. - */ - public void setFile(String file) { - if (file == null) { - fileName = file; - } else { - // Trim spaces from both ends. The users probably does not want - // trailing spaces in file names. - String val = file.trim(); - fileName = val; - } - } - - /** - * @deprecated Use isAppend instead - */ - public boolean getAppend() { - return append; - } - - /** - * Returns the value of the Append property. - */ - public boolean isAppend() { - return append; - } - - /** - * This method is used by derived classes to obtain the raw file property. - * Regular users should not be calling this method. - * - * @return the value of the file property - */ - final public String rawFileProperty() { - return fileName; - } - - /** - * Returns the value of the File property. - * - *

This method may be overridden by derived classes. - * - */ - public String getFile() { - return fileName; - } - - /** - * If the value of File is not null, then - * {@link #openFile} is called with the values of File and Append - * properties. - */ - public void start() { - int errors = 0; - if (getFile() != null) { - addInfo("File property is set to [" + fileName + "]"); - - if (prudent) { - if (isAppend() == false) { - setAppend(true); - addWarn("Setting \"Append\" property to true on account of \"Prudent\" mode"); - } - if (getImmediateFlush() == false) { - setImmediateFlush(true); - addWarn("Setting \"ImmediateFlush\" to true on account of \"Prudent\" mode"); - } - - if (bufferedIO == true) { - setBufferedIO(false); - addWarn("Setting \"BufferedIO\" property to false on account of \"Prudent\" mode"); - } - } - - // In case both bufferedIO and immediateFlush are set, the former - // takes priority because 'immediateFlush' is set to true by default. - // If the user explicitly set bufferedIO, then we should follow her - // directives. - if (bufferedIO) { - setImmediateFlush(false); - addInfo("Setting \"ImmediateFlush\" property to false on account of \"bufferedIO\" property"); - } - - try { - openFile(getFile()); - } catch (java.io.IOException e) { - errors++; - addError("openFile(" + fileName + "," + append + ") call failed.", e); - } - } else { - errors++; - addError("\"File\" property not set for appender named [" + name + "]."); - } - if (errors == 0) { - super.start(); - } - } - - /** - *

Sets and opens the file where the log output will go. The - * specified file must be writable. - * - *

If there was already an opened file, then the previous file is closed - * first. - * - *

Do not use this method directly. To configure a FileAppender or one - * of its subclasses, set its properties one by one and then call start(). - * - * @param filename - * The path to the log file. - * @param append - * If true will append to fileName. Otherwise will truncate - * fileName. - * @param bufferedIO - * @param bufferSize - * - * @throws IOException - * - */ - public synchronized void openFile(String file_name) throws IOException { - File file = new File(file_name); - if (FileUtil.mustCreateParentDirectories(file)) { - boolean result = FileUtil.createMissingParentDirectories(file); - if (!result) { - addError("Failed to create parent directories for [" - + file.getAbsolutePath() + "]"); - } - } - - FileOutputStream fileOutputStream = new FileOutputStream(file_name, append); - if (prudent) { - fileChannel = fileOutputStream.getChannel(); - } - Writer w = createWriter(fileOutputStream); - if (bufferedIO) { - w = new BufferedWriter(w, bufferSize); - } - setWriter(w); - } - - public boolean isBufferedIO() { - return bufferedIO; - } - - public void setBufferedIO(boolean bufferedIO) { - this.bufferedIO = bufferedIO; - } - - public int getBufferSize() { - return bufferSize; - } - - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - } - - /** - * @see #setPrudent(boolean) - * - * @return true if in prudent mode - */ - public boolean isPrudent() { - return prudent; - } - - /** - * When prudent is set to true, file appenders from multiple JVMs can safely - * write to the same file. - * - * @param prudent - */ - public void setPrudent(boolean prudent) { - this.prudent = prudent; - } - - public void setAppend(boolean append) { - this.append = append; - } - - final private void safeWrite(String s) throws IOException { - FileLock fileLock = null; - try { - fileLock = fileChannel.lock(); - long position = fileChannel.position(); - long size = fileChannel.size(); - if (size != position) { - fileChannel.position(size); - } - super.writerWrite(s, true); - } finally { - if (fileLock != null) { - fileLock.release(); - } - } - } - - @Override - protected void writerWrite(String s, boolean flush) throws IOException { - if (prudent && fileChannel != null) { - safeWrite(s); - } else { - super.writerWrite(s, flush); - } - } -} +/** + * 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; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.Writer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; + +import ch.qos.logback.core.util.FileUtil; + +/** + * FileAppender appends log events to a file. + * + * For more information about this appender, please refer to the online manual + * at http://logback.qos.ch/manual/appenders.html#FileAppender + * + * @author Ceki Gülcü + */ +public class FileAppender extends WriterAppender { + + /** + * Append to or truncate the file? The default value for this variable is + * true, meaning that by default a FileAppender + * will append to an existing file and not truncate it. + */ + protected boolean append = true; + + /** + * The name of the active log file. + */ + protected String fileName = null; + + /** + * Do we do bufferedIO? + */ + protected boolean bufferedIO = false; + + /** + * The size of the IO buffer. Default is 8K. + */ + protected int bufferSize = 8 * 1024; + + private boolean prudent = false; + + private FileChannel fileChannel = null; + + /** + * As in most cases, the default constructor does nothing. + */ + public FileAppender() { + } + + /** + * The File property takes a string value which should be the name of + * the file to append to. + */ + public void setFile(String file) { + if (file == null) { + fileName = file; + } else { + // Trim spaces from both ends. The users probably does not want + // trailing spaces in file names. + String val = file.trim(); + fileName = val; + } + } + + /** + * @deprecated Use isAppend instead + */ + public boolean getAppend() { + return append; + } + + /** + * Returns the value of the Append property. + */ + public boolean isAppend() { + return append; + } + + /** + * This method is used by derived classes to obtain the raw file property. + * Regular users should not be calling this method. + * + * @return the value of the file property + */ + final public String rawFileProperty() { + return fileName; + } + + /** + * Returns the value of the File property. + * + *

This method may be overridden by derived classes. + * + */ + public String getFile() { + return fileName; + } + + /** + * If the value of File is not null, then + * {@link #openFile} is called with the values of File and Append + * properties. + */ + public void start() { + int errors = 0; + if (getFile() != null) { + addInfo("File property is set to [" + fileName + "]"); + + if (prudent) { + if (isAppend() == false) { + setAppend(true); + addWarn("Setting \"Append\" property to true on account of \"Prudent\" mode"); + } + if (getImmediateFlush() == false) { + setImmediateFlush(true); + addWarn("Setting \"ImmediateFlush\" to true on account of \"Prudent\" mode"); + } + + if (bufferedIO == true) { + setBufferedIO(false); + addWarn("Setting \"BufferedIO\" property to false on account of \"Prudent\" mode"); + } + } + + // In case both bufferedIO and immediateFlush are set, the former + // takes priority because 'immediateFlush' is set to true by default. + // If the user explicitly set bufferedIO, then we should follow her + // directives. + if (bufferedIO) { + setImmediateFlush(false); + addInfo("Setting \"ImmediateFlush\" property to false on account of \"bufferedIO\" property"); + } + + try { + openFile(getFile()); + } catch (java.io.IOException e) { + errors++; + addError("openFile(" + fileName + "," + append + ") call failed.", e); + } + } else { + errors++; + addError("\"File\" property not set for appender named [" + name + "]."); + } + if (errors == 0) { + super.start(); + } + } + + /** + *

Sets and opens the file where the log output will go. The + * specified file must be writable. + * + *

If there was already an opened file, then the previous file is closed + * first. + * + *

Do not use this method directly. To configure a FileAppender or one + * of its subclasses, set its properties one by one and then call start(). + * + * @param filename + * The path to the log file. + * @param append + * If true will append to fileName. Otherwise will truncate + * fileName. + * @param bufferedIO + * @param bufferSize + * + * @throws IOException + * + */ + public synchronized void openFile(String file_name) throws IOException { + File file = new File(file_name); + if (FileUtil.mustCreateParentDirectories(file)) { + boolean result = FileUtil.createMissingParentDirectories(file); + if (!result) { + addError("Failed to create parent directories for [" + + file.getAbsolutePath() + "]"); + } + } + + FileOutputStream fileOutputStream = new FileOutputStream(file_name, append); + if (prudent) { + fileChannel = fileOutputStream.getChannel(); + } + Writer w = createWriter(fileOutputStream); + if (bufferedIO) { + w = new BufferedWriter(w, bufferSize); + } + setWriter(w); + } + + public boolean isBufferedIO() { + return bufferedIO; + } + + public void setBufferedIO(boolean bufferedIO) { + this.bufferedIO = bufferedIO; + } + + public int getBufferSize() { + return bufferSize; + } + + public void setBufferSize(int bufferSize) { + this.bufferSize = bufferSize; + } + + /** + * @see #setPrudent(boolean) + * + * @return true if in prudent mode + */ + public boolean isPrudent() { + return prudent; + } + + /** + * When prudent is set to true, file appenders from multiple JVMs can safely + * write to the same file. + * + * @param prudent + */ + public void setPrudent(boolean prudent) { + this.prudent = prudent; + } + + public void setAppend(boolean append) { + this.append = append; + } + + final private void safeWrite(String s) throws IOException { + FileLock fileLock = null; + try { + fileLock = fileChannel.lock(); + long position = fileChannel.position(); + long size = fileChannel.size(); + if (size != position) { + fileChannel.position(size); + } + super.writerWrite(s, true); + } finally { + if (fileLock != null) { + fileLock.release(); + } + } + } + + @Override + protected void writerWrite(String s, boolean flush) throws IOException { + if (prudent && fileChannel != null) { + safeWrite(s); + } else { + super.writerWrite(s, flush); + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/Layout.java b/logback-core/src/main/java/ch/qos/logback/core/Layout.java index c5fbaf6bfe403cdcc760b44a8a062ea380be0595..702539e419787f8519ff404ecef63cc73b526089 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/Layout.java +++ b/logback-core/src/main/java/ch/qos/logback/core/Layout.java @@ -1,70 +1,70 @@ -/** - * 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; - -import ch.qos.logback.core.spi.ContextAware; -import ch.qos.logback.core.spi.LifeCycle; - -public interface Layout extends ContextAware, LifeCycle { - - /** - * Transform an event (of type Object) and return it as a String after - * appropriate formatting. - * - *

Taking in an object and returning a String is the least sophisticated - * way of formatting events. However, it is remarkably CPU-effective. - *

- * - * @param event The event to format - * @return the event formatted as a String - */ - String doLayout(E event); - - /** - * Return the file header for this layout. The returned value may be null. - * @return The header. - */ - String getFileHeader(); - - /** - * Return the header of the logging event formatting. The returned value - * may be null. - * - * @return The header. - */ - String getPresentationHeader(); - - /** - * Return the footer of the logging event formatting. The returned value - * may be null. - * - * @return The footer. - */ - - String getPresentationFooter(); - - /** - * Return the file footer for this layout. The returned value may be null. - * @return The footer. - */ - String getFileFooter(); - - /** - * Returns the content type as appropriate for the implementation. - * - * @return - */ - String getContentType(); - -} +/** + * 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; + +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.LifeCycle; + +public interface Layout extends ContextAware, LifeCycle { + + /** + * Transform an event (of type Object) and return it as a String after + * appropriate formatting. + * + *

Taking in an object and returning a String is the least sophisticated + * way of formatting events. However, it is remarkably CPU-effective. + *

+ * + * @param event The event to format + * @return the event formatted as a String + */ + String doLayout(E event); + + /** + * Return the file header for this layout. The returned value may be null. + * @return The header. + */ + String getFileHeader(); + + /** + * Return the header of the logging event formatting. The returned value + * may be null. + * + * @return The header. + */ + String getPresentationHeader(); + + /** + * Return the footer of the logging event formatting. The returned value + * may be null. + * + * @return The footer. + */ + + String getPresentationFooter(); + + /** + * Return the file footer for this layout. The returned value may be null. + * @return The footer. + */ + String getFileFooter(); + + /** + * Returns the content type as appropriate for the implementation. + * + * @return + */ + String getContentType(); + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/LayoutBase.java b/logback-core/src/main/java/ch/qos/logback/core/LayoutBase.java index c95a7fda5956ff2c00f02389d653e670191bc1fc..d27e472ca0a288b56ab0aa13cafbebfc44d8cf13 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/LayoutBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/LayoutBase.java @@ -1,82 +1,82 @@ -/** - * 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; - -import ch.qos.logback.core.spi.ContextAwareBase; - -abstract public class LayoutBase extends ContextAwareBase implements Layout { - - protected boolean started; - - String fileHeader; - String fileFooter; - String presentationHeader; - String presentationFooter; - - public void setContext(Context context) { - this.context = context; - } - - public Context getContext() { - return this.context; - } - - public void start() { - started = true; - } - - public void stop() { - started = false; - } - - public boolean isStarted() { - return started; - } - - public String getFileHeader() { - return fileHeader; - } - - public String getPresentationHeader() { - return presentationHeader; - } - - public String getPresentationFooter() { - return presentationFooter; - } - - public String getFileFooter() { - return fileFooter; - } - - public String getContentType() { - return "text/plain"; - } - - public void setFileHeader(String header) { - this.fileHeader = header; - } - - public void setFileFooter(String footer) { - this.fileFooter = footer; - } - - public void setPresentationHeader(String header) { - this.presentationHeader = header; - } - - public void setPresentationFooter(String footer) { - this.presentationFooter = footer; - } -} +/** + * 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; + +import ch.qos.logback.core.spi.ContextAwareBase; + +abstract public class LayoutBase extends ContextAwareBase implements Layout { + + protected boolean started; + + String fileHeader; + String fileFooter; + String presentationHeader; + String presentationFooter; + + public void setContext(Context context) { + this.context = context; + } + + public Context getContext() { + return this.context; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + + public boolean isStarted() { + return started; + } + + public String getFileHeader() { + return fileHeader; + } + + public String getPresentationHeader() { + return presentationHeader; + } + + public String getPresentationFooter() { + return presentationFooter; + } + + public String getFileFooter() { + return fileFooter; + } + + public String getContentType() { + return "text/plain"; + } + + public void setFileHeader(String header) { + this.fileHeader = header; + } + + public void setFileFooter(String footer) { + this.fileFooter = footer; + } + + public void setPresentationHeader(String header) { + this.presentationHeader = header; + } + + public void setPresentationFooter(String footer) { + this.presentationFooter = footer; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/LogbackException.java b/logback-core/src/main/java/ch/qos/logback/core/LogbackException.java index 5af618091e8321fb6d576c71fbadf55d738c16d7..cdc7f719b3bc58cee607b955ab43c61ad8defc79 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/LogbackException.java +++ b/logback-core/src/main/java/ch/qos/logback/core/LogbackException.java @@ -1,29 +1,29 @@ -/** - * 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; - -public class LogbackException extends RuntimeException { - - private static final long serialVersionUID = -799956346239073266L; - - public LogbackException(String msg) { - super(msg); - } - - - public LogbackException(String msg, Throwable nested) { - super(msg, nested); - } - -} +/** + * 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; + +public class LogbackException extends RuntimeException { + + private static final long serialVersionUID = -799956346239073266L; + + public LogbackException(String msg) { + super(msg); + } + + + public LogbackException(String msg, Throwable nested) { + super(msg, nested); + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/UnsynchronizedAppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/UnsynchronizedAppenderBase.java index ed42f3efd943ea01f249acacbec4f72aaac1b862..6a258d7c7e42580737157fdd70f44645a7d13dbe 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/UnsynchronizedAppenderBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/UnsynchronizedAppenderBase.java @@ -1,157 +1,157 @@ -/** - * 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; - -import java.util.List; - -import ch.qos.logback.core.filter.Filter; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.spi.FilterAttachableImpl; -import ch.qos.logback.core.spi.FilterReply; -import ch.qos.logback.core.status.WarnStatus; - -/** - * Similar to AppenderBase except that derived appenders need to handle - * thread synchronization on their own. - * - * @author Ceki Gülcü - * @author Ralph Goers - */ -abstract public class UnsynchronizedAppenderBase extends ContextAwareBase implements - Appender { - - protected Layout layout; - - protected boolean started = false; - - // using a ThreadLocal instead of a boolean add 75 nanoseconds per - // doAppend invocation. This is tolerable as doAppend takes at least a few microseconds - // on a real appender - /** - * The guard prevents an appender from repeatedly calling its own doAppend - * method. - */ - private ThreadLocal guard = new ThreadLocal() { - protected Boolean initialValue() { - return false; - } - }; - - /** - * Appenders are named. - */ - protected String name; - - private FilterAttachableImpl fai = new FilterAttachableImpl(); - - public String getName() { - return name; - } - - private int statusRepeatCount = 0; - private int exceptionCount = 0; - - static final int ALLOWED_REPEATS = 3; - - public void doAppend(E eventObject) { - // WARNING: The guard check MUST be the first statement in the - // doAppend() method. - - // prevent re-entry. - if (guard.get()) { - return; - } - - try { - guard.set(true); - - if (!this.started) { - if (statusRepeatCount++ < ALLOWED_REPEATS) { - addStatus(new WarnStatus( - "Attempted to append to non started appender [" + name + "].", - this)); - } - return; - } - - if (getFilterChainDecision(eventObject) == FilterReply.DENY) { - return; - } - - // ok, we now invoke derived class' implementation of append - this.append(eventObject); - - } catch (Exception e) { - if (exceptionCount++ < ALLOWED_REPEATS) { - addError("Appender [" + name + "] failed to append.", e); - } - } finally { - guard.set(false); - } - } - - abstract protected void append(E eventObject); - - /** - * Set the name of this appender. - */ - public void setName(String name) { - this.name = name; - } - - public void start() { - started = true; - } - - public void stop() { - started = false; - } - - public boolean isStarted() { - return started; - } - - public String toString() { - return this.getClass().getName() + "[" + name + "]"; - } - - public void addFilter(Filter newFilter) { - fai.addFilter(newFilter); - } - - public Filter getFirstFilter() { - return fai.getFirstFilter(); - } - - public void clearAllFilters() { - fai.clearAllFilters(); - } - - public List> getCopyOfAttachedFiltersList() { - return fai.getCopyOfAttachedFiltersList(); - } - - - public FilterReply getFilterChainDecision(E event) { - return fai.getFilterChainDecision(event); - } - - public Layout getLayout() { - return layout; - } - - public void setLayout(Layout layout) { - this.layout = layout; - } -} +/** + * 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; + +import java.util.List; + +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.FilterAttachableImpl; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.status.WarnStatus; + +/** + * Similar to AppenderBase except that derived appenders need to handle + * thread synchronization on their own. + * + * @author Ceki Gülcü + * @author Ralph Goers + */ +abstract public class UnsynchronizedAppenderBase extends ContextAwareBase implements + Appender { + + protected Layout layout; + + protected boolean started = false; + + // using a ThreadLocal instead of a boolean add 75 nanoseconds per + // doAppend invocation. This is tolerable as doAppend takes at least a few microseconds + // on a real appender + /** + * The guard prevents an appender from repeatedly calling its own doAppend + * method. + */ + private ThreadLocal guard = new ThreadLocal() { + protected Boolean initialValue() { + return false; + } + }; + + /** + * Appenders are named. + */ + protected String name; + + private FilterAttachableImpl fai = new FilterAttachableImpl(); + + public String getName() { + return name; + } + + private int statusRepeatCount = 0; + private int exceptionCount = 0; + + static final int ALLOWED_REPEATS = 3; + + public void doAppend(E eventObject) { + // WARNING: The guard check MUST be the first statement in the + // doAppend() method. + + // prevent re-entry. + if (guard.get()) { + return; + } + + try { + guard.set(true); + + if (!this.started) { + if (statusRepeatCount++ < ALLOWED_REPEATS) { + addStatus(new WarnStatus( + "Attempted to append to non started appender [" + name + "].", + this)); + } + return; + } + + if (getFilterChainDecision(eventObject) == FilterReply.DENY) { + return; + } + + // ok, we now invoke derived class' implementation of append + this.append(eventObject); + + } catch (Exception e) { + if (exceptionCount++ < ALLOWED_REPEATS) { + addError("Appender [" + name + "] failed to append.", e); + } + } finally { + guard.set(false); + } + } + + abstract protected void append(E eventObject); + + /** + * Set the name of this appender. + */ + public void setName(String name) { + this.name = name; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + + public boolean isStarted() { + return started; + } + + public String toString() { + return this.getClass().getName() + "[" + name + "]"; + } + + public void addFilter(Filter newFilter) { + fai.addFilter(newFilter); + } + + public Filter getFirstFilter() { + return fai.getFirstFilter(); + } + + public void clearAllFilters() { + fai.clearAllFilters(); + } + + public List> getCopyOfAttachedFiltersList() { + return fai.getCopyOfAttachedFiltersList(); + } + + + public FilterReply getFilterChainDecision(E event) { + return fai.getFilterChainDecision(event); + } + + public Layout getLayout() { + return layout; + } + + public void setLayout(Layout layout) { + this.layout = layout; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/WriterAppender.java b/logback-core/src/main/java/ch/qos/logback/core/WriterAppender.java index bf4880bdac3590284111adcf7e71d85c66ed769b..acc64300a20fb33190c1d18eeb2a731dd394ddf4 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/WriterAppender.java +++ b/logback-core/src/main/java/ch/qos/logback/core/WriterAppender.java @@ -1,281 +1,281 @@ -/** - * 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; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; - -import ch.qos.logback.core.status.ErrorStatus; - -/** - * WriterAppender appends events to a hava.io.Writer. This class provides basic - * services that other appenders build upon. - * - * For more information about this appender, please refer to the online manual - * at http://logback.qos.ch/manual/appenders.html#WriterAppender - * - * @author Ceki Gülcü - */ -public class WriterAppender extends UnsynchronizedAppenderBase { - - /** - * Immediate flush means that the underlying writer or output stream will be - * flushed at the end of each append operation. Immediate flush is slower but - * ensures that each append request is actually written. If - * immediateFlush is set to false, then there - * is a good chance that the last few logs events are not actually written to - * persistent media if and when the application crashes. - * - *

- * The immediateFlush variable is set to true by - * default. - */ - private boolean immediateFlush = true; - - /** - * The encoding to use when opening an InputStream. - *

- * The encoding variable is set to null by default - * which results in the use of the system's default encoding. - */ - private String encoding; - - /** - * This is the {@link Writer Writer} where we will write to. - */ - private Writer writer; - - /** - * The default constructor does nothing. - */ - public WriterAppender() { - } - - /** - * If the ImmediateFlush option is set to true, the - * appender will flush at the end of each write. This is the default behavior. - * If the option is set to false, then the underlying stream - * can defer writing to physical medium to a later time. - *

- * Avoiding the flush operation at the end of each append results in a - * performance gain of 10 to 20 percent. However, there is safety tradeoff - * involved in skipping flushing. Indeed, when flushing is skipped, then it is - * likely that the last few log events will not be recorded on disk when the - * application exits. This is a high price to pay even for a 20% performance - * gain. - */ - public void setImmediateFlush(boolean value) { - immediateFlush = value; - } - - /** - * Returns value of the ImmediateFlush option. - */ - public boolean getImmediateFlush() { - return immediateFlush; - } - - /** - * Checks that requires parameters are set and if everything is in order, - * activates this appender. - */ - public void start() { - int errors = 0; - if (this.layout == null) { - addStatus(new ErrorStatus("No layout set for the appender named \"" - + name + "\".", this)); - errors++; - } - - if (this.writer == null) { - addStatus(new ErrorStatus("No writer set for the appender named \"" - + name + "\".", this)); - errors++; - } - // only error free appenders should be activated - if (errors == 0) { - super.start(); - } - } - - @Override - protected void append(E eventObject) { - if (!isStarted()) { - return; - } - - subAppend(eventObject); - } - - /** - * Stop this appender instance. The underlying stream or writer is also - * closed. - * - *

- * Stopped appenders cannot be reused. - */ - public synchronized void stop() { - closeWriter(); - super.stop(); - } - - /** - * Close the underlying {@link java.io.Writer}. - */ - protected void closeWriter() { - if (this.writer != null) { - try { - // before closing we have to output out layout's footer - writeFooter(); - this.writer.close(); - this.writer = null; - } catch (IOException e) { - addStatus(new ErrorStatus("Could not close writer for WriterAppener.", - this, e)); - } - } - } - - /** - * Returns an OutputStreamWriter when passed an OutputStream. The encoding - * used will depend on the value of the encoding property. If - * the encoding value is specified incorrectly the writer will be opened using - * the default system encoding (an error message will be printed to the - * loglog. - */ - protected OutputStreamWriter createWriter(OutputStream os) { - OutputStreamWriter retval = null; - - String enc = getEncoding(); - - try { - if (enc != null) { - retval = new OutputStreamWriter(os, enc); - } else { - retval = new OutputStreamWriter(os); - } - } catch (IOException e) { - addStatus(new ErrorStatus("Error initializing output writer.", this, e)); - if (enc != null) { - addStatus(new ErrorStatus("Unsupported encoding?", this)); - } - } - return retval; - } - - public String getEncoding() { - return encoding; - } - - public void setEncoding(String value) { - encoding = value; - } - - void writeHeader() { - if (layout != null && (this.writer != null)) { - try { - StringBuilder sb = new StringBuilder(); - appendIfNotNull(sb, layout.getFileHeader()); - appendIfNotNull(sb, layout.getPresentationHeader()); - if (sb.length() > 0) { - sb.append(CoreConstants.LINE_SEPARATOR); - // If at least one of file header or presentation header were not - // null, then append a line separator. - // This should be useful in most cases and should not hurt. - writerWrite(sb.toString(), true); - } - - } catch (IOException ioe) { - this.started = false; - addStatus(new ErrorStatus("Failed to write header for appender named [" - + name + "].", this, ioe)); - } - } - } - - private void appendIfNotNull(StringBuilder sb, String s) { - if (s != null) { - sb.append(s); - } - } - - void writeFooter() { - if (layout != null && this.writer != null) { - try { - StringBuilder sb = new StringBuilder(); - appendIfNotNull(sb, layout.getPresentationFooter()); - appendIfNotNull(sb, layout.getFileFooter()); - if (sb.length() > 0) { - writerWrite(sb.toString(), true); // force flush - } - } catch (IOException ioe) { - this.started = false; - addStatus(new ErrorStatus("Failed to write footer for appender named [" - + name + "].", this, ioe)); - } - } - } - - /** - *

- * Sets the Writer where the log output will go. The specified Writer must be - * opened by the user and be writable. The java.io.Writer will - * be closed when the appender instance is closed. - * - * @param writer - * An already opened Writer. - */ - public synchronized void setWriter(Writer writer) { - // close any previously opened writer - closeWriter(); - - this.writer = writer; - writeHeader(); - } - - protected void writerWrite(String s, boolean flush) throws IOException { - this.writer.write(s); - if (flush) { - this.writer.flush(); - } - } - - /** - * Actual writing occurs here. - *

- * Most subclasses of WriterAppender will need to override this - * method. - * - * @since 0.9.0 - */ - protected void subAppend(E event) { - if (!isStarted()) { - return; - } - - try { - String output = this.layout.doLayout(event); - synchronized (this) { - writerWrite(output, this.immediateFlush); - } - } catch (IOException ioe) { - // as soon as an exception occurs, move to non-started state - // and add a single ErrorStatus to the SM. - this.started = false; - addStatus(new ErrorStatus("IO failure in appender", this, ioe)); - } - } -} +/** + * 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; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; + +import ch.qos.logback.core.status.ErrorStatus; + +/** + * WriterAppender appends events to a hava.io.Writer. This class provides basic + * services that other appenders build upon. + * + * For more information about this appender, please refer to the online manual + * at http://logback.qos.ch/manual/appenders.html#WriterAppender + * + * @author Ceki Gülcü + */ +public class WriterAppender extends UnsynchronizedAppenderBase { + + /** + * Immediate flush means that the underlying writer or output stream will be + * flushed at the end of each append operation. Immediate flush is slower but + * ensures that each append request is actually written. If + * immediateFlush is set to false, then there + * is a good chance that the last few logs events are not actually written to + * persistent media if and when the application crashes. + * + *

+ * The immediateFlush variable is set to true by + * default. + */ + private boolean immediateFlush = true; + + /** + * The encoding to use when opening an InputStream. + *

+ * The encoding variable is set to null by default + * which results in the use of the system's default encoding. + */ + private String encoding; + + /** + * This is the {@link Writer Writer} where we will write to. + */ + private Writer writer; + + /** + * The default constructor does nothing. + */ + public WriterAppender() { + } + + /** + * If the ImmediateFlush option is set to true, the + * appender will flush at the end of each write. This is the default behavior. + * If the option is set to false, then the underlying stream + * can defer writing to physical medium to a later time. + *

+ * Avoiding the flush operation at the end of each append results in a + * performance gain of 10 to 20 percent. However, there is safety tradeoff + * involved in skipping flushing. Indeed, when flushing is skipped, then it is + * likely that the last few log events will not be recorded on disk when the + * application exits. This is a high price to pay even for a 20% performance + * gain. + */ + public void setImmediateFlush(boolean value) { + immediateFlush = value; + } + + /** + * Returns value of the ImmediateFlush option. + */ + public boolean getImmediateFlush() { + return immediateFlush; + } + + /** + * Checks that requires parameters are set and if everything is in order, + * activates this appender. + */ + public void start() { + int errors = 0; + if (this.layout == null) { + addStatus(new ErrorStatus("No layout set for the appender named \"" + + name + "\".", this)); + errors++; + } + + if (this.writer == null) { + addStatus(new ErrorStatus("No writer set for the appender named \"" + + name + "\".", this)); + errors++; + } + // only error free appenders should be activated + if (errors == 0) { + super.start(); + } + } + + @Override + protected void append(E eventObject) { + if (!isStarted()) { + return; + } + + subAppend(eventObject); + } + + /** + * Stop this appender instance. The underlying stream or writer is also + * closed. + * + *

+ * Stopped appenders cannot be reused. + */ + public synchronized void stop() { + closeWriter(); + super.stop(); + } + + /** + * Close the underlying {@link java.io.Writer}. + */ + protected void closeWriter() { + if (this.writer != null) { + try { + // before closing we have to output out layout's footer + writeFooter(); + this.writer.close(); + this.writer = null; + } catch (IOException e) { + addStatus(new ErrorStatus("Could not close writer for WriterAppener.", + this, e)); + } + } + } + + /** + * Returns an OutputStreamWriter when passed an OutputStream. The encoding + * used will depend on the value of the encoding property. If + * the encoding value is specified incorrectly the writer will be opened using + * the default system encoding (an error message will be printed to the + * loglog. + */ + protected OutputStreamWriter createWriter(OutputStream os) { + OutputStreamWriter retval = null; + + String enc = getEncoding(); + + try { + if (enc != null) { + retval = new OutputStreamWriter(os, enc); + } else { + retval = new OutputStreamWriter(os); + } + } catch (IOException e) { + addStatus(new ErrorStatus("Error initializing output writer.", this, e)); + if (enc != null) { + addStatus(new ErrorStatus("Unsupported encoding?", this)); + } + } + return retval; + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String value) { + encoding = value; + } + + void writeHeader() { + if (layout != null && (this.writer != null)) { + try { + StringBuilder sb = new StringBuilder(); + appendIfNotNull(sb, layout.getFileHeader()); + appendIfNotNull(sb, layout.getPresentationHeader()); + if (sb.length() > 0) { + sb.append(CoreConstants.LINE_SEPARATOR); + // If at least one of file header or presentation header were not + // null, then append a line separator. + // This should be useful in most cases and should not hurt. + writerWrite(sb.toString(), true); + } + + } catch (IOException ioe) { + this.started = false; + addStatus(new ErrorStatus("Failed to write header for appender named [" + + name + "].", this, ioe)); + } + } + } + + private void appendIfNotNull(StringBuilder sb, String s) { + if (s != null) { + sb.append(s); + } + } + + void writeFooter() { + if (layout != null && this.writer != null) { + try { + StringBuilder sb = new StringBuilder(); + appendIfNotNull(sb, layout.getPresentationFooter()); + appendIfNotNull(sb, layout.getFileFooter()); + if (sb.length() > 0) { + writerWrite(sb.toString(), true); // force flush + } + } catch (IOException ioe) { + this.started = false; + addStatus(new ErrorStatus("Failed to write footer for appender named [" + + name + "].", this, ioe)); + } + } + } + + /** + *

+ * Sets the Writer where the log output will go. The specified Writer must be + * opened by the user and be writable. The java.io.Writer will + * be closed when the appender instance is closed. + * + * @param writer + * An already opened Writer. + */ + public synchronized void setWriter(Writer writer) { + // close any previously opened writer + closeWriter(); + + this.writer = writer; + writeHeader(); + } + + protected void writerWrite(String s, boolean flush) throws IOException { + this.writer.write(s); + if (flush) { + this.writer.flush(); + } + } + + /** + * Actual writing occurs here. + *

+ * Most subclasses of WriterAppender will need to override this + * method. + * + * @since 0.9.0 + */ + protected void subAppend(E event) { + if (!isStarted()) { + return; + } + + try { + String output = this.layout.doLayout(event); + synchronized (this) { + writerWrite(output, this.immediateFlush); + } + } catch (IOException ioe) { + // as soon as an exception occurs, move to non-started state + // and add a single ErrorStatus to the SM. + this.started = false; + addStatus(new ErrorStatus("IO failure in appender", this, ioe)); + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/boolex/EvaluationException.java b/logback-core/src/main/java/ch/qos/logback/core/boolex/EvaluationException.java index dc8ed8d9583d7590c4d73e302bbfd636d7f0aafb..621c90a40506b3224ae2d0c8267f6a0315e8787b 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/boolex/EvaluationException.java +++ b/logback-core/src/main/java/ch/qos/logback/core/boolex/EvaluationException.java @@ -1,37 +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.boolex; - -/** - * This exception wraps exceptions thrown while evaluating events. - * - * @author Ceki Gülcü - */ -public class EvaluationException extends Exception { - - private static final long serialVersionUID = 1L; - - public EvaluationException(String msg) { - super(msg); - } - - public EvaluationException(String msg, Throwable cause) { - super(msg, cause); - } - - public EvaluationException(Throwable cause) { - super(cause); - } - -} +/** + * 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.boolex; + +/** + * This exception wraps exceptions thrown while evaluating events. + * + * @author Ceki Gülcü + */ +public class EvaluationException extends Exception { + + private static final long serialVersionUID = 1L; + + public EvaluationException(String msg) { + super(msg); + } + + public EvaluationException(String msg, Throwable cause) { + super(msg, cause); + } + + public EvaluationException(Throwable cause) { + super(cause); + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluator.java b/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluator.java index 28b14acf1eaf2325fff25bc46618542d4441677f..ab91629efeb9db16490a76ca6aca170891bb4334 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluator.java +++ b/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluator.java @@ -1,60 +1,60 @@ -/** - * 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.boolex; - -import ch.qos.logback.core.spi.ContextAware; -import ch.qos.logback.core.spi.LifeCycle; - -/** - * Evaluates whether a given an event matches user-specified criteria. - * - *

- * Implementations are free to evaluate the event as they see fit. In - * particular, the evaluation results may depend on previous events. - * - * @author Ceki Gülcü - */ - -public interface EventEvaluator extends ContextAware, LifeCycle { - - /** - * Evaluates whether the event passed as parameter matches some user-specified - * criteria. - * - *

- * The Evaluator is free to evaluate the event as it pleases. In - * particular, the evaluation results may depend on previous events. - * - * @param event - * The event to evaluate - * @return true if there is a match, false otherwise. - * @throws NullPointerException - * can be thrown in presence of null values - * @throws EvaluationException - * may be thrown during faulty evaluation - */ - boolean evaluate(E event) throws NullPointerException, EvaluationException; - - /** - * Evaluators are named entities. - * - * @return The name of this evaluator. - */ - public String getName(); - - /** - * Evaluators are named entities. - */ - public void setName(String name); -} +/** + * 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.boolex; + +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.LifeCycle; + +/** + * Evaluates whether a given an event matches user-specified criteria. + * + *

+ * Implementations are free to evaluate the event as they see fit. In + * particular, the evaluation results may depend on previous events. + * + * @author Ceki Gülcü + */ + +public interface EventEvaluator extends ContextAware, LifeCycle { + + /** + * Evaluates whether the event passed as parameter matches some user-specified + * criteria. + * + *

+ * The Evaluator is free to evaluate the event as it pleases. In + * particular, the evaluation results may depend on previous events. + * + * @param event + * The event to evaluate + * @return true if there is a match, false otherwise. + * @throws NullPointerException + * can be thrown in presence of null values + * @throws EvaluationException + * may be thrown during faulty evaluation + */ + boolean evaluate(E event) throws NullPointerException, EvaluationException; + + /** + * Evaluators are named entities. + * + * @return The name of this evaluator. + */ + public String getName(); + + /** + * Evaluators are named entities. + */ + public void setName(String name); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluatorBase.java b/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluatorBase.java index 6b758cc743350676e458e10bc10cf32078ac314a..d85dcdacc702d3c46abb590cf2a833af5a409735 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluatorBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluatorBase.java @@ -1,48 +1,48 @@ -/** - * 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.boolex; - -import ch.qos.logback.core.spi.ContextAwareBase; - -abstract public class EventEvaluatorBase extends ContextAwareBase implements - EventEvaluator { - - String name; - boolean started; - - public String getName() { - - return name; - } - - public void setName(String name) { - if (this.name != null) { - throw new IllegalStateException("name has been already set"); - } - this.name = name; - } - - public boolean isStarted() { - return started; - } - - public void start() { - started = true; - } - - public void stop() { - started = false; - } - -} +/** + * 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.boolex; + +import ch.qos.logback.core.spi.ContextAwareBase; + +abstract public class EventEvaluatorBase extends ContextAwareBase implements + EventEvaluator { + + String name; + boolean started; + + public String getName() { + + return name; + } + + public void setName(String name) { + if (this.name != null) { + throw new IllegalStateException("name has been already set"); + } + this.name = name; + } + + public boolean isStarted() { + return started; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java b/logback-core/src/main/java/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java index fce2ad33f32f07a765f362e653d32fa43f5be602..6e0ebd88e14940ddf64b33076641ebb89bdde03d 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java @@ -1,100 +1,100 @@ -/** - * 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.boolex; - -import java.util.ArrayList; -import java.util.List; - -import org.codehaus.janino.ExpressionEvaluator; - -/** - * Abstract class which sets the groundwork for janino based evaluations. - * - * @author Ceki Gülcü - * - * @param - */ -abstract public class JaninoEventEvaluatorBase extends EventEvaluatorBase { - - static Class EXPRESSION_TYPE = boolean.class; - static Class[] THROWN_EXCEPTIONS = new Class[1]; - - static public final int ERROR_THRESHOLD = 4; - static { - THROWN_EXCEPTIONS[0] = EvaluationException.class; - } - - private String expression; - - ExpressionEvaluator ee; - private int errorCount = 0; - - abstract protected String getDecoratedExpression(); - - abstract protected String[] getParameterNames(); - - abstract protected Class[] getParameterTypes(); - - abstract protected Object[] getParameterValues(E event); - - protected List matcherList = new ArrayList(); - - @Override - public void start() { - try { - assert context != null; - ClassLoader cl = context.getClass().getClassLoader(); - ee = new ExpressionEvaluator(getDecoratedExpression(), EXPRESSION_TYPE, - getParameterNames(), getParameterTypes(), THROWN_EXCEPTIONS, cl); - super.start(); - } catch (Exception e) { - addError( - "Could not start evaluator with expression [" + expression + "]", e); - } - } - - public boolean evaluate(E event) throws EvaluationException { - if (!isStarted()) { - throw new IllegalStateException("Evaluator [" + name - + "] was called in stopped state"); - } - try { - Boolean result = (Boolean) ee.evaluate(getParameterValues(event)); - return result.booleanValue(); - } catch (Exception ex) { - errorCount++; - if (errorCount >= ERROR_THRESHOLD) { - stop(); - } - throw new EvaluationException("Evaluator [" + name - + "] caused an exception", ex); - } - } - - public String getExpression() { - return expression; - } - - public void setExpression(String expression) { - this.expression = expression; - } - - public void addMatcher(Matcher matcher) { - matcherList.add(matcher); - } - - public List getMatcherList() { - return matcherList; - } -} +/** + * 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.boolex; + +import java.util.ArrayList; +import java.util.List; + +import org.codehaus.janino.ExpressionEvaluator; + +/** + * Abstract class which sets the groundwork for janino based evaluations. + * + * @author Ceki Gülcü + * + * @param + */ +abstract public class JaninoEventEvaluatorBase extends EventEvaluatorBase { + + static Class EXPRESSION_TYPE = boolean.class; + static Class[] THROWN_EXCEPTIONS = new Class[1]; + + static public final int ERROR_THRESHOLD = 4; + static { + THROWN_EXCEPTIONS[0] = EvaluationException.class; + } + + private String expression; + + ExpressionEvaluator ee; + private int errorCount = 0; + + abstract protected String getDecoratedExpression(); + + abstract protected String[] getParameterNames(); + + abstract protected Class[] getParameterTypes(); + + abstract protected Object[] getParameterValues(E event); + + protected List matcherList = new ArrayList(); + + @Override + public void start() { + try { + assert context != null; + ClassLoader cl = context.getClass().getClassLoader(); + ee = new ExpressionEvaluator(getDecoratedExpression(), EXPRESSION_TYPE, + getParameterNames(), getParameterTypes(), THROWN_EXCEPTIONS, cl); + super.start(); + } catch (Exception e) { + addError( + "Could not start evaluator with expression [" + expression + "]", e); + } + } + + public boolean evaluate(E event) throws EvaluationException { + if (!isStarted()) { + throw new IllegalStateException("Evaluator [" + name + + "] was called in stopped state"); + } + try { + Boolean result = (Boolean) ee.evaluate(getParameterValues(event)); + return result.booleanValue(); + } catch (Exception ex) { + errorCount++; + if (errorCount >= ERROR_THRESHOLD) { + stop(); + } + throw new EvaluationException("Evaluator [" + name + + "] caused an exception", ex); + } + } + + public String getExpression() { + return expression; + } + + public void setExpression(String expression) { + this.expression = expression; + } + + public void addMatcher(Matcher matcher) { + matcherList.add(matcher); + } + + public List getMatcherList() { + return matcherList; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/boolex/Matcher.java b/logback-core/src/main/java/ch/qos/logback/core/boolex/Matcher.java index 022cd1d0a50f86c30ec0d92d836689d4f3b94b43..b9739ed363f3acd25cd2dd4cb992cfd25229e15d 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/boolex/Matcher.java +++ b/logback-core/src/main/java/ch/qos/logback/core/boolex/Matcher.java @@ -1,125 +1,125 @@ -/** - * 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.boolex; - -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.spi.LifeCycle; - -public class Matcher extends ContextAwareBase implements LifeCycle { - - private String regex; - private String name; - private boolean caseSensitive = true; - private boolean canonEq = false; - private boolean unicodeCase = false; - - private boolean start = false; - private Pattern pattern; - - public String getRegex() { - return regex; - } - - public void setRegex(String regex) { - this.regex = regex; - } - - public void start() { - if(name == null) { - addError("All Matcher objects must be named"); - return; - } - try { - int code = 0; - if(!caseSensitive) { - code |= Pattern.CASE_INSENSITIVE; - } - if(canonEq) { - code |= Pattern.CANON_EQ; - } - if(unicodeCase) { - code |= Pattern.UNICODE_CASE; - } - - //code |= Pattern.DOTALL; - - pattern = Pattern.compile(regex, code); - start = true; - } catch (PatternSyntaxException pse) { - addError("Failed to compile regex [" + regex + "]", pse); - } - } - - public void stop() { - start = false; - } - - public boolean isStarted() { - return start; - } - - //However, this method does - //not require that the entire region (of the input) be matched. - - /** - * Checks whether the input matches the regular expression. - * - * @param input - * @return - * @throws EvaluationException - */ - public boolean matches(String input) throws EvaluationException { - if(start) { - java.util.regex.Matcher matcher = pattern.matcher(input); - return matcher.find(); - } else { - throw new EvaluationException("Matcher ["+regex+"] not started"); - } - } - - public boolean isCanonEq() { - return canonEq; - } - - public void setCanonEq(boolean canonEq) { - this.canonEq = canonEq; - } - - public boolean isCaseSensitive() { - return caseSensitive; - } - - public void setCaseSensitive(boolean caseSensitive) { - this.caseSensitive = caseSensitive; - } - - public boolean isUnicodeCase() { - return unicodeCase; - } - - public void setUnicodeCase(boolean unicodeCase) { - this.unicodeCase = unicodeCase; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} +/** + * 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.boolex; + +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.LifeCycle; + +public class Matcher extends ContextAwareBase implements LifeCycle { + + private String regex; + private String name; + private boolean caseSensitive = true; + private boolean canonEq = false; + private boolean unicodeCase = false; + + private boolean start = false; + private Pattern pattern; + + public String getRegex() { + return regex; + } + + public void setRegex(String regex) { + this.regex = regex; + } + + public void start() { + if(name == null) { + addError("All Matcher objects must be named"); + return; + } + try { + int code = 0; + if(!caseSensitive) { + code |= Pattern.CASE_INSENSITIVE; + } + if(canonEq) { + code |= Pattern.CANON_EQ; + } + if(unicodeCase) { + code |= Pattern.UNICODE_CASE; + } + + //code |= Pattern.DOTALL; + + pattern = Pattern.compile(regex, code); + start = true; + } catch (PatternSyntaxException pse) { + addError("Failed to compile regex [" + regex + "]", pse); + } + } + + public void stop() { + start = false; + } + + public boolean isStarted() { + return start; + } + + //However, this method does + //not require that the entire region (of the input) be matched. + + /** + * Checks whether the input matches the regular expression. + * + * @param input + * @return + * @throws EvaluationException + */ + public boolean matches(String input) throws EvaluationException { + if(start) { + java.util.regex.Matcher matcher = pattern.matcher(input); + return matcher.find(); + } else { + throw new EvaluationException("Matcher ["+regex+"] not started"); + } + } + + public boolean isCanonEq() { + return canonEq; + } + + public void setCanonEq(boolean canonEq) { + this.canonEq = canonEq; + } + + public boolean isCaseSensitive() { + return caseSensitive; + } + + public void setCaseSensitive(boolean caseSensitive) { + this.caseSensitive = caseSensitive; + } + + public boolean isUnicodeCase() { + return unicodeCase; + } + + public void setUnicodeCase(boolean unicodeCase) { + this.unicodeCase = unicodeCase; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/boolex/package.html b/logback-core/src/main/java/ch/qos/logback/core/boolex/package.html index 4cc2471e0b51e7d436de3c7867b5e56a2e1af9ef..567de464e212b1299eed6b79d063c12abc21f957 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/boolex/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/boolex/package.html @@ -1,17 +1,17 @@ - - - - - - - - - -

Contains the EventEvaluator interface and subclasses.

- -

EventEvaluator is subclassed by JaninoEventEvaluatorBase. - Specific subclasses can be found in logback modules. -

- - + + + + + + + + + +

Contains the EventEvaluator interface and subclasses.

+ +

EventEvaluator is subclassed by JaninoEventEvaluatorBase. + Specific subclasses can be found in logback modules. +

+ + \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/db/BindDataSourceToJNDIAction.java b/logback-core/src/main/java/ch/qos/logback/core/db/BindDataSourceToJNDIAction.java index 81f79b752543e2fd396e575b60e0666f5e3011c7..3ed1ffa49927e1a73905a43026020097a4f9e730 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/db/BindDataSourceToJNDIAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/db/BindDataSourceToJNDIAction.java @@ -1,89 +1,89 @@ -/** - * 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.db; - - -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.sql.DataSource; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.joran.spi.PropertySetter; -import ch.qos.logback.core.util.OptionHelper; - -/** - * - * @author Ceki Gulcu - * - */ -public class BindDataSourceToJNDIAction extends Action { - - static final String DATA_SOURCE_CLASS = "dataSourceClass"; - static final String URL = "url"; - static final String USER = "user"; - static final String PASSWORD = "password"; - - /** - * Instantiates an a data source and bind it to JNDI - * Most of the required parameters are placed in the ec.substitutionProperties - */ - public void begin( - InterpretationContext ec, String localName, Attributes attributes) { - String dsClassName = ec.getProperty(DATA_SOURCE_CLASS); - - if (OptionHelper.isEmpty(dsClassName)) { - addWarn("dsClassName is a required parameter"); - ec.addError("dsClassName is a required parameter"); - - return; - } - - String urlStr = ec.getProperty(URL); - String userStr = ec.getProperty(USER); - String passwordStr = ec.getProperty(PASSWORD); - - try { - DataSource ds = - (DataSource) OptionHelper.instantiateByClassName(dsClassName, DataSource.class, context); - - PropertySetter setter = new PropertySetter(ds); - setter.setContext(context); - - if (!OptionHelper.isEmpty(urlStr)) { - setter.setProperty("url", urlStr); - } - - if (!OptionHelper.isEmpty(userStr)) { - setter.setProperty("user", userStr); - } - - if (!OptionHelper.isEmpty(passwordStr)) { - setter.setProperty("password", passwordStr); - } - - Context ctx = new InitialContext(); - ctx.rebind("dataSource", ds); - } catch (Exception oops) { - addError( - "Could not bind datasource. Reported error follows.", oops); - ec.addError("Could not not bind datasource of type [" + dsClassName + "]."); - } - } - - public void end(InterpretationContext ec, String name) { - } -} +/** + * 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.db; + + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.sql.DataSource; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.PropertySetter; +import ch.qos.logback.core.util.OptionHelper; + +/** + * + * @author Ceki Gulcu + * + */ +public class BindDataSourceToJNDIAction extends Action { + + static final String DATA_SOURCE_CLASS = "dataSourceClass"; + static final String URL = "url"; + static final String USER = "user"; + static final String PASSWORD = "password"; + + /** + * Instantiates an a data source and bind it to JNDI + * Most of the required parameters are placed in the ec.substitutionProperties + */ + public void begin( + InterpretationContext ec, String localName, Attributes attributes) { + String dsClassName = ec.getProperty(DATA_SOURCE_CLASS); + + if (OptionHelper.isEmpty(dsClassName)) { + addWarn("dsClassName is a required parameter"); + ec.addError("dsClassName is a required parameter"); + + return; + } + + String urlStr = ec.getProperty(URL); + String userStr = ec.getProperty(USER); + String passwordStr = ec.getProperty(PASSWORD); + + try { + DataSource ds = + (DataSource) OptionHelper.instantiateByClassName(dsClassName, DataSource.class, context); + + PropertySetter setter = new PropertySetter(ds); + setter.setContext(context); + + if (!OptionHelper.isEmpty(urlStr)) { + setter.setProperty("url", urlStr); + } + + if (!OptionHelper.isEmpty(userStr)) { + setter.setProperty("user", userStr); + } + + if (!OptionHelper.isEmpty(passwordStr)) { + setter.setProperty("password", passwordStr); + } + + Context ctx = new InitialContext(); + ctx.rebind("dataSource", ds); + } catch (Exception oops) { + addError( + "Could not bind datasource. Reported error follows.", oops); + ec.addError("Could not not bind datasource of type [" + dsClassName + "]."); + } + } + + public void end(InterpretationContext ec, String name) { + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/db/dialect/SQLDialectCode.java b/logback-core/src/main/java/ch/qos/logback/core/db/dialect/SQLDialectCode.java index 5387aac4aca725c580e2545d9a7c468341cfdce9..317603603d1bf521aecf16e1fb4561cc8f5766ea 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/db/dialect/SQLDialectCode.java +++ b/logback-core/src/main/java/ch/qos/logback/core/db/dialect/SQLDialectCode.java @@ -1,23 +1,23 @@ -/** - * 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.db.dialect; - -public enum SQLDialectCode { - UNKNOWN_DIALECT, - POSTGRES_DIALECT, - MYSQL_DIALECT, - ORACLE_DIALECT, - MSSQL_DIALECT, - HSQL_DIALECT; -} +/** + * 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.db.dialect; + +public enum SQLDialectCode { + UNKNOWN_DIALECT, + POSTGRES_DIALECT, + MYSQL_DIALECT, + ORACLE_DIALECT, + MSSQL_DIALECT, + HSQL_DIALECT; +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/db/dialect/package.html b/logback-core/src/main/java/ch/qos/logback/core/db/dialect/package.html index a14ba0a58bba887dc0045542102cf2c68ba0f428..d4f92b53c7ed6fbc7cd68c6136a8198863a4e70a 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/db/dialect/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/db/dialect/package.html @@ -1,14 +1,14 @@ - - - - - - - - - -

Contains the dialect classes used by logback to log to different databases, and the - SQL scripts to created the necessary tables.

- - + + + + + + + + + +

Contains the dialect classes used by logback to log to different databases, and the + SQL scripts to created the necessary tables.

+ + \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/db/package.html b/logback-core/src/main/java/ch/qos/logback/core/db/package.html index f6c6161170b82f759e744bfdb1c96ad5219ec502..213e220342b634c0935a695329e56611d911b005 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/db/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/db/package.html @@ -1,22 +1,22 @@ - - - - - - - - -

The ch.qos.logback.core.db package provides bases classes to append objects -into various databases. -

- -

Most popular database systems, such as PostgreSQL, MySQL, Oracle, DB2 and MsSQL -are supported. -

- -

Just as importantly, the way for obtaining JDBC connections is pluggable. Connections can -be obtained through the tradinal way of DriverManager, or alternatively as a DataSource. -A DataSource can be instantiated directly or it can obtained through JNDI. -

- + + + + + + + + +

The ch.qos.logback.core.db package provides bases classes to append objects +into various databases. +

+ +

Most popular database systems, such as PostgreSQL, MySQL, Oracle, DB2 and MsSQL +are supported. +

+ +

Just as importantly, the way for obtaining JDBC connections is pluggable. Connections can +be obtained through the tradinal way of DriverManager, or alternatively as a DataSource. +A DataSource can be instantiated directly or it can obtained through JNDI. +

+ \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/filter/AbstractMatcherFilter.java b/logback-core/src/main/java/ch/qos/logback/core/filter/AbstractMatcherFilter.java index bbae62b25dbd8fa569982e84be2ba640ea0a17e8..f0c3d4d0de67aac27b4595e0464069fa9bddaefd 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/filter/AbstractMatcherFilter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/filter/AbstractMatcherFilter.java @@ -1,38 +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.filter; - -import ch.qos.logback.core.spi.FilterReply; - -public abstract class AbstractMatcherFilter extends Filter { - - protected FilterReply onMatch = FilterReply.NEUTRAL; - protected FilterReply onMismatch = FilterReply.NEUTRAL; - - final public void setOnMatch(FilterReply reply) { - this.onMatch = reply; - } - - final public void setOnMismatch(FilterReply reply) { - this.onMismatch = reply; - } - - final public FilterReply getOnMatch() { - return onMatch; - } - - final public FilterReply getOnMismatch() { - return onMismatch; - } -} +/** + * 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.filter; + +import ch.qos.logback.core.spi.FilterReply; + +public abstract class AbstractMatcherFilter extends Filter { + + protected FilterReply onMatch = FilterReply.NEUTRAL; + protected FilterReply onMismatch = FilterReply.NEUTRAL; + + final public void setOnMatch(FilterReply reply) { + this.onMatch = reply; + } + + final public void setOnMismatch(FilterReply reply) { + this.onMismatch = reply; + } + + final public FilterReply getOnMatch() { + return onMatch; + } + + final public FilterReply getOnMismatch() { + return onMismatch; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/filter/EvaluatorFilter.java b/logback-core/src/main/java/ch/qos/logback/core/filter/EvaluatorFilter.java index 9a850eb09b33baf9a5e6818ac017d1f48ee15835..d19e43cdd651dfaf348e7f909fe2c12acc23138b 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/filter/EvaluatorFilter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/filter/EvaluatorFilter.java @@ -1,76 +1,76 @@ -/** - * 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.filter; - -import ch.qos.logback.core.boolex.EvaluationException; -import ch.qos.logback.core.boolex.EventEvaluator; -import ch.qos.logback.core.spi.FilterReply; - -/** - * The value of the {@link #onMatch} and {@link #onMismatch} attributes is set - * to {@link Filter.NEUTRAL}, so that a badly configured evaluator filter does - * not disturb the functioning of the filter chain. - * - *

It is expected that one of the two attributes will have its value changed - * to {@link Filter.ACCEPT} or {@link Filter.DENY}. That way, it is possible to - * decide if a given result must be returned after the evaluation either failed - * or succeeded. - * - * - *

For more information about filters, please refer to the online manual at - * http://logback.qos.ch/manual/filters.html - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public class EvaluatorFilter extends AbstractMatcherFilter { - - EventEvaluator evaluator; - - @Override - public void start() { - if (evaluator != null) { - super.start(); - } else { - addError("No evaluator set for filter " + this.getName()); - } - } - - public EventEvaluator getEvaluator() { - return evaluator; - } - - public void setEvaluator(EventEvaluator evaluator) { - this.evaluator = evaluator; - } - - public FilterReply decide(E event) { - // let us not throw an exception - // see also bug #17. - if (!isStarted() || !evaluator.isStarted()) { - return FilterReply.NEUTRAL; - } - try { - if (evaluator.evaluate(event)) { - return onMatch; - } else { - return onMismatch; - } - } catch (EvaluationException e) { - addError("Evaluator " + evaluator.getName() + " threw an exception", e); - return FilterReply.NEUTRAL; - } - } - -} +/** + * 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.filter; + +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.spi.FilterReply; + +/** + * The value of the {@link #onMatch} and {@link #onMismatch} attributes is set + * to {@link Filter.NEUTRAL}, so that a badly configured evaluator filter does + * not disturb the functioning of the filter chain. + * + *

It is expected that one of the two attributes will have its value changed + * to {@link Filter.ACCEPT} or {@link Filter.DENY}. That way, it is possible to + * decide if a given result must be returned after the evaluation either failed + * or succeeded. + * + * + *

For more information about filters, please refer to the online manual at + * http://logback.qos.ch/manual/filters.html + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public class EvaluatorFilter extends AbstractMatcherFilter { + + EventEvaluator evaluator; + + @Override + public void start() { + if (evaluator != null) { + super.start(); + } else { + addError("No evaluator set for filter " + this.getName()); + } + } + + public EventEvaluator getEvaluator() { + return evaluator; + } + + public void setEvaluator(EventEvaluator evaluator) { + this.evaluator = evaluator; + } + + public FilterReply decide(E event) { + // let us not throw an exception + // see also bug #17. + if (!isStarted() || !evaluator.isStarted()) { + return FilterReply.NEUTRAL; + } + try { + if (evaluator.evaluate(event)) { + return onMatch; + } else { + return onMismatch; + } + } catch (EvaluationException e) { + addError("Evaluator " + evaluator.getName() + " threw an exception", e); + return FilterReply.NEUTRAL; + } + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/filter/Filter.java b/logback-core/src/main/java/ch/qos/logback/core/filter/Filter.java index 62f4cb45128d1b8e6ed823416f248cd1589b70d4..db4647e10efe4a3c968bf087cef570d8c3692162 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/filter/Filter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/filter/Filter.java @@ -1,68 +1,68 @@ -/** - * 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.filter; - -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.spi.FilterReply; -import ch.qos.logback.core.spi.LifeCycle; - -/** - * Users should extend this class to implement customized event filtering. - * - *

We suggest that you first try to use the built-in rules before rushing to - * write your own custom filters. - * - *

For more information about filters, please refer to the online manual at - * http://logback.qos.ch/manual/filters.html - * - * @author Ceki Gülcü - */ -public abstract class Filter extends ContextAwareBase implements LifeCycle { - - private String name; - - boolean start = false; - - public void start() { - this.start = true; - } - - public boolean isStarted() { - return this.start; - } - - public void stop() { - this.start = false; - } - - /** - * If the decision is {@link #DENY}, then the event will be - * dropped. If the decision is {@link #NEUTRAL}, then the next - * filter, if any, will be invoked. If the decision is - * {@link #ACCEPT} then the event will be logged without - * consulting with other filters in the chain. - * - * @param event - * The event to decide upon. - */ - public abstract FilterReply decide(E event); - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} +/** + * 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.filter; + +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.spi.LifeCycle; + +/** + * Users should extend this class to implement customized event filtering. + * + *

We suggest that you first try to use the built-in rules before rushing to + * write your own custom filters. + * + *

For more information about filters, please refer to the online manual at + * http://logback.qos.ch/manual/filters.html + * + * @author Ceki Gülcü + */ +public abstract class Filter extends ContextAwareBase implements LifeCycle { + + private String name; + + boolean start = false; + + public void start() { + this.start = true; + } + + public boolean isStarted() { + return this.start; + } + + public void stop() { + this.start = false; + } + + /** + * If the decision is {@link #DENY}, then the event will be + * dropped. If the decision is {@link #NEUTRAL}, then the next + * filter, if any, will be invoked. If the decision is + * {@link #ACCEPT} then the event will be logged without + * consulting with other filters in the chain. + * + * @param event + * The event to decide upon. + */ + public abstract FilterReply decide(E event); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/filter/package.html b/logback-core/src/main/java/ch/qos/logback/core/filter/package.html index 405ad029756b8a3f0b069d791bfb846f050dd826..c757da6f9a97f5e619a9b21148f39be7695752e9 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/filter/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/filter/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains base classes to the event filtering functionnalities of logback.

- - + + + + + + + + + +

Contains base classes to the event filtering functionnalities of logback.

+ + \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java b/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java index 5d51a6f541382bbb0b7aefc1445a1e1dc46298c3..1e654d0425a2f6618fbf242e4b7189ca60a4a0ea 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java +++ b/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java @@ -1,166 +1,166 @@ -/** - * 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.helpers; - -import java.util.ArrayList; -import java.util.List; - -/** - * CyclicBuffer holds values in a cyclic array. - * - *

It allows read access to any element in the buffer not just the first or - * last element. - * - * @author Ceki Gülcü - */ -public class CyclicBuffer { - - E[] ea; - int first; - int last; - int numElems; - int maxSize; - - /** - * Instantiate a new CyclicBuffer of at most maxSize events. - * - * The maxSize argument must a positive integer. - * - * @param maxSize - * The maximum number of elements in the buffer. - */ - public CyclicBuffer(int maxSize) throws IllegalArgumentException { - if (maxSize < 1) { - throw new IllegalArgumentException("The maxSize argument (" + maxSize - + ") is not a positive integer."); - } - init(maxSize); - } - - @SuppressWarnings("unchecked") - private void init(int maxSize) { - this.maxSize = maxSize; - ea = (E[]) new Object[maxSize]; - first = 0; - last = 0; - numElems = 0; - } - - /** - * Clears the buffer and resets all attributes. - */ - public void clear() { - init(this.maxSize); - } - - /** - * Add an event as the last event in the buffer. - * - */ - public void add(E event) { - ea[last] = event; - if (++last == maxSize) - last = 0; - - if (numElems < maxSize) - numElems++; - else if (++first == maxSize) - first = 0; - } - - /** - * Get the ith oldest event currently in the buffer. If i - * is outside the range 0 to the number of elements currently in the buffer, - * then null is returned. - */ - public E get(int i) { - if (i < 0 || i >= numElems) - return null; - - return ea[(first + i) % maxSize]; - } - - public int getMaxSize() { - return maxSize; - } - - /** - * Get the oldest (first) element in the buffer. The oldest element is removed - * from the buffer. - */ - public E get() { - E r = null; - if (numElems > 0) { - numElems--; - r = ea[first]; - ea[first] = null; - if (++first == maxSize) - first = 0; - } - return r; - } - - public List asList() { - List tList = new ArrayList(); - for(int i = 0; i < length(); i++) { - tList.add(get(i)); - } - return tList; - } - - /** - * Get the number of elements in the buffer. This number is guaranteed to be - * in the range 0 to maxSize (inclusive). - */ - public int length() { - return numElems; - } - - /** - * Resize the cyclic buffer to newSize. - * - * @throws IllegalArgumentException - * if newSize is negative. - */ - @SuppressWarnings("unchecked") - public void resize(int newSize) { - if (newSize < 0) { - throw new IllegalArgumentException("Negative array size [" + newSize - + "] not allowed."); - } - if (newSize == numElems) - return; // nothing to do - - // - E[] temp = (E[]) new Object[newSize]; - - int loopLen = newSize < numElems ? newSize : numElems; - - for (int i = 0; i < loopLen; i++) { - temp[i] = ea[first]; - ea[first] = null; - if (++first == numElems) - first = 0; - } - ea = temp; - first = 0; - numElems = loopLen; - maxSize = newSize; - if (loopLen == newSize) { - last = 0; - } else { - last = loopLen; - } - } -} +/** + * 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.helpers; + +import java.util.ArrayList; +import java.util.List; + +/** + * CyclicBuffer holds values in a cyclic array. + * + *

It allows read access to any element in the buffer not just the first or + * last element. + * + * @author Ceki Gülcü + */ +public class CyclicBuffer { + + E[] ea; + int first; + int last; + int numElems; + int maxSize; + + /** + * Instantiate a new CyclicBuffer of at most maxSize events. + * + * The maxSize argument must a positive integer. + * + * @param maxSize + * The maximum number of elements in the buffer. + */ + public CyclicBuffer(int maxSize) throws IllegalArgumentException { + if (maxSize < 1) { + throw new IllegalArgumentException("The maxSize argument (" + maxSize + + ") is not a positive integer."); + } + init(maxSize); + } + + @SuppressWarnings("unchecked") + private void init(int maxSize) { + this.maxSize = maxSize; + ea = (E[]) new Object[maxSize]; + first = 0; + last = 0; + numElems = 0; + } + + /** + * Clears the buffer and resets all attributes. + */ + public void clear() { + init(this.maxSize); + } + + /** + * Add an event as the last event in the buffer. + * + */ + public void add(E event) { + ea[last] = event; + if (++last == maxSize) + last = 0; + + if (numElems < maxSize) + numElems++; + else if (++first == maxSize) + first = 0; + } + + /** + * Get the ith oldest event currently in the buffer. If i + * is outside the range 0 to the number of elements currently in the buffer, + * then null is returned. + */ + public E get(int i) { + if (i < 0 || i >= numElems) + return null; + + return ea[(first + i) % maxSize]; + } + + public int getMaxSize() { + return maxSize; + } + + /** + * Get the oldest (first) element in the buffer. The oldest element is removed + * from the buffer. + */ + public E get() { + E r = null; + if (numElems > 0) { + numElems--; + r = ea[first]; + ea[first] = null; + if (++first == maxSize) + first = 0; + } + return r; + } + + public List asList() { + List tList = new ArrayList(); + for(int i = 0; i < length(); i++) { + tList.add(get(i)); + } + return tList; + } + + /** + * Get the number of elements in the buffer. This number is guaranteed to be + * in the range 0 to maxSize (inclusive). + */ + public int length() { + return numElems; + } + + /** + * Resize the cyclic buffer to newSize. + * + * @throws IllegalArgumentException + * if newSize is negative. + */ + @SuppressWarnings("unchecked") + public void resize(int newSize) { + if (newSize < 0) { + throw new IllegalArgumentException("Negative array size [" + newSize + + "] not allowed."); + } + if (newSize == numElems) + return; // nothing to do + + // + E[] temp = (E[]) new Object[newSize]; + + int loopLen = newSize < numElems ? newSize : numElems; + + for (int i = 0; i < loopLen; i++) { + temp[i] = ea[first]; + ea[first] = null; + if (++first == numElems) + first = 0; + } + ea = temp; + first = 0; + numElems = loopLen; + maxSize = newSize; + if (loopLen == newSize) { + last = 0; + } else { + last = loopLen; + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToStringArray.java b/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToStringArray.java index 292e5a31dc9c14e400eecb22de5996a2ef6408b2..9beadd68960b2ad4d50e1e26e330110a67ce4832 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToStringArray.java +++ b/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToStringArray.java @@ -1,86 +1,86 @@ -/** - * 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.helpers; - -import java.util.LinkedList; -import java.util.List; - -import ch.qos.logback.core.CoreConstants; - -public class ThrowableToStringArray { - - public static String[] convert(Throwable t) { - List strList = new LinkedList(); - extract(strList, t, null); - return strList.toArray(new String[0]); - - } - - private static void extract(List strList, Throwable t, - StackTraceElement[] parentSTE) { - - StackTraceElement[] ste = t.getStackTrace(); - final int numberOfcommonFrames = findNumberOfCommonFrames(ste, parentSTE); - - strList.add(formatFirstLine(t, parentSTE)); - for (int i = 0; i < (ste.length - numberOfcommonFrames); i++) { - strList.add("\tat "+ste[i].toString()); - } - - if (numberOfcommonFrames != 0) { - strList.add("\t... "+numberOfcommonFrames + " common frames omitted"); - } - - Throwable cause = t.getCause(); - if (cause != null) { - ThrowableToStringArray.extract(strList, cause, ste); - } - } - - private static String formatFirstLine(Throwable t, - StackTraceElement[] parentSTE) { - String prefix = ""; - if (parentSTE != null) { - prefix = CoreConstants.CAUSED_BY; - } - - String result = prefix + t.getClass().getName(); - if (t.getMessage() != null) { - result += ": " + t.getMessage(); - } - return result; - } - - private static int findNumberOfCommonFrames(StackTraceElement[] ste, - StackTraceElement[] parentSTE) { - if (parentSTE == null) { - return 0; - } - - int steIndex = ste.length - 1; - int parentIndex = parentSTE.length - 1; - int count = 0; - while (steIndex >= 0 && parentIndex >= 0) { - if (ste[steIndex].equals(parentSTE[parentIndex])) { - count++; - } else { - break; - } - steIndex--; - parentIndex--; - } - return count; - } - -} +/** + * 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.helpers; + +import java.util.LinkedList; +import java.util.List; + +import ch.qos.logback.core.CoreConstants; + +public class ThrowableToStringArray { + + public static String[] convert(Throwable t) { + List strList = new LinkedList(); + extract(strList, t, null); + return strList.toArray(new String[0]); + + } + + private static void extract(List strList, Throwable t, + StackTraceElement[] parentSTE) { + + StackTraceElement[] ste = t.getStackTrace(); + final int numberOfcommonFrames = findNumberOfCommonFrames(ste, parentSTE); + + strList.add(formatFirstLine(t, parentSTE)); + for (int i = 0; i < (ste.length - numberOfcommonFrames); i++) { + strList.add("\tat "+ste[i].toString()); + } + + if (numberOfcommonFrames != 0) { + strList.add("\t... "+numberOfcommonFrames + " common frames omitted"); + } + + Throwable cause = t.getCause(); + if (cause != null) { + ThrowableToStringArray.extract(strList, cause, ste); + } + } + + private static String formatFirstLine(Throwable t, + StackTraceElement[] parentSTE) { + String prefix = ""; + if (parentSTE != null) { + prefix = CoreConstants.CAUSED_BY; + } + + String result = prefix + t.getClass().getName(); + if (t.getMessage() != null) { + result += ": " + t.getMessage(); + } + return result; + } + + private static int findNumberOfCommonFrames(StackTraceElement[] ste, + StackTraceElement[] parentSTE) { + if (parentSTE == null) { + return 0; + } + + int steIndex = ste.length - 1; + int parentIndex = parentSTE.length - 1; + int count = 0; + while (steIndex >= 0 && parentIndex >= 0) { + if (ste[steIndex].equals(parentSTE[parentIndex])) { + count++; + } else { + break; + } + steIndex--; + parentIndex--; + } + return count; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/helpers/Transform.java b/logback-core/src/main/java/ch/qos/logback/core/helpers/Transform.java index 09992500097500aa450ded8cac05a92f24796022..36420059b87017380989553d2b69ab1b4b0830cf 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/helpers/Transform.java +++ b/logback-core/src/main/java/ch/qos/logback/core/helpers/Transform.java @@ -1,111 +1,111 @@ -/** - * 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.helpers; - -/** - * Utility class for transforming strings. - * - * @author Ceki Gülcü - * @author Michael A. McAngus - */ -public class Transform { - private static final String CDATA_START = ""; - private static final String CDATA_PSEUDO_END = "]]>"; - private static final String CDATA_EMBEDED_END = CDATA_END + CDATA_PSEUDO_END - + CDATA_START; - private static final int CDATA_END_LEN = CDATA_END.length(); - - /** - * This method takes a string which may contain HTML tags (ie, <b>, - * <table>, etc) and replaces any '<' and '>' characters with - * respective predefined entity references. - * - * @param input - * The text to be converted. - */ - public static String escapeTags(final String input) { - // Check if the string is null or zero length -- if so, return - // what was sent in. - if ((input == null) || (input.length() == 0) - || (input.indexOf("<") == -1 && input.indexOf(">") == -1)) { - return input; - } - - StringBuffer buf = new StringBuffer(input); - return escapeTags(buf); - } - - - /** - * This method takes a StringBuilder which may contain HTML tags (ie, <b>, - * <table>, etc) and replaces any '<' and '>' characters with - * respective predefined entity references. - * @param buf - * @return - */ - public static String escapeTags(final StringBuffer buf) { - for (int i = 0; i < buf.length(); i++) { - char ch = buf.charAt(i); - if (ch == '<') { - buf.replace(i, i + 1, "<"); - } else if (ch == '>') { - buf.replace(i, i + 1, ">"); - } - } - return buf.toString(); - } - - - /** - * Ensures that embeded CDEnd strings (]]>) are handled properly within - * message, NDC and throwable tag text. - * - * @param output - * Writer. The initial CDSutart () of - * the CDATA section are the responsibility of the calling method. - * - * @param str - * The String that is inserted into an existing CDATA Section. - */ - public static void appendEscapingCDATA(StringBuilder output, String str) { - if (str == null) { - return; - } - - int end = str.indexOf(CDATA_END); - - if (end < 0) { - output.append(str); - - return; - } - - int start = 0; - - while (end > -1) { - output.append(str.substring(start, end)); - output.append(CDATA_EMBEDED_END); - start = end + CDATA_END_LEN; - - if (start < str.length()) { - end = str.indexOf(CDATA_END, start); - } else { - return; - } - } - - output.append(str.substring(start)); - } -} +/** + * 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.helpers; + +/** + * Utility class for transforming strings. + * + * @author Ceki Gülcü + * @author Michael A. McAngus + */ +public class Transform { + private static final String CDATA_START = ""; + private static final String CDATA_PSEUDO_END = "]]>"; + private static final String CDATA_EMBEDED_END = CDATA_END + CDATA_PSEUDO_END + + CDATA_START; + private static final int CDATA_END_LEN = CDATA_END.length(); + + /** + * This method takes a string which may contain HTML tags (ie, <b>, + * <table>, etc) and replaces any '<' and '>' characters with + * respective predefined entity references. + * + * @param input + * The text to be converted. + */ + public static String escapeTags(final String input) { + // Check if the string is null or zero length -- if so, return + // what was sent in. + if ((input == null) || (input.length() == 0) + || (input.indexOf("<") == -1 && input.indexOf(">") == -1)) { + return input; + } + + StringBuffer buf = new StringBuffer(input); + return escapeTags(buf); + } + + + /** + * This method takes a StringBuilder which may contain HTML tags (ie, <b>, + * <table>, etc) and replaces any '<' and '>' characters with + * respective predefined entity references. + * @param buf + * @return + */ + public static String escapeTags(final StringBuffer buf) { + for (int i = 0; i < buf.length(); i++) { + char ch = buf.charAt(i); + if (ch == '<') { + buf.replace(i, i + 1, "<"); + } else if (ch == '>') { + buf.replace(i, i + 1, ">"); + } + } + return buf.toString(); + } + + + /** + * Ensures that embeded CDEnd strings (]]>) are handled properly within + * message, NDC and throwable tag text. + * + * @param output + * Writer. The initial CDSutart () of + * the CDATA section are the responsibility of the calling method. + * + * @param str + * The String that is inserted into an existing CDATA Section. + */ + public static void appendEscapingCDATA(StringBuilder output, String str) { + if (str == null) { + return; + } + + int end = str.indexOf(CDATA_END); + + if (end < 0) { + output.append(str); + + return; + } + + int start = 0; + + while (end > -1) { + output.append(str.substring(start, end)); + output.append(CDATA_EMBEDED_END); + start = end + CDATA_END_LEN; + + if (start < str.length()) { + end = str.indexOf(CDATA_END, start); + } else { + return; + } + } + + output.append(str.substring(start)); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/helpers/package.html b/logback-core/src/main/java/ch/qos/logback/core/helpers/package.html index 94d21446e4a142dd29673ebed05e72c060178f70..b2ecf85c559e4ef8c9d3ca34e40dbd5263e429c5 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/helpers/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/helpers/package.html @@ -1,14 +1,14 @@ - - - - - - - - - -

Helpers package.

- - - + + + + + + + + + +

Helpers package.

+ + + \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/html/CssBuilder.java b/logback-core/src/main/java/ch/qos/logback/core/html/CssBuilder.java index 8328982c16904c4a64f57698e732ca249e7e6270..080a4c6355a40bb25391480cc3f082a5f8280479 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/html/CssBuilder.java +++ b/logback-core/src/main/java/ch/qos/logback/core/html/CssBuilder.java @@ -1,20 +1,20 @@ -/** - * 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.html; - -public interface CssBuilder { - - public void addCss(StringBuilder sbuf); - -} +/** + * 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.html; + +public interface CssBuilder { + + public void addCss(StringBuilder sbuf); + +} 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 2ec5f6c20f69f01bb8b93ab93fa5ade7d34d702c..43282dcbcd1d3e101f44b54f441fdee85942f45e 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 @@ -1,266 +1,266 @@ -/** - * 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.html; - -import java.util.HashMap; -import java.util.Map; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.CoreConstants; -import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; -import ch.qos.logback.core.LayoutBase; -import ch.qos.logback.core.pattern.Converter; -import ch.qos.logback.core.pattern.ConverterUtil; -import ch.qos.logback.core.pattern.parser.Node; -import ch.qos.logback.core.pattern.parser.Parser; -import ch.qos.logback.core.pattern.parser.ScanException; - -/** - * This class is a base class for HTMLLayout classes part of - * other logback modules such as logback-classic and logback-access. - * - * - * @author Sébastien Pennec - */ -public abstract class HTMLLayoutBase extends LayoutBase { - - protected String pattern; - - protected Converter head; - - protected String title = "Logback Log Messages"; - - //It is the responsibility of derived classes to set - //this variable in their constructor to a default value. - protected CssBuilder cssBuilder; - - // counter keeping track of the rows output - protected long counter = 0; - - /** - * Set the ConversionPattern option. This is the string which controls - * formatting and consists of a mix of literal content and conversion - * specifiers. - */ - public void setPattern(String conversionPattern) { - pattern = conversionPattern; - } - - /** - * Returns the value of the ConversionPattern option. - */ - public String getPattern() { - return pattern; - } - - public CssBuilder getCssBuilder() { - return cssBuilder; - } - - public void setCssBuilder(CssBuilder cssBuilder) { - this.cssBuilder = cssBuilder; - } - - /** - * Parses the pattern and creates the Converter linked list. - */ - @Override - public void start() { - int errorCount = 0; - - try { - Parser p = new Parser(pattern); - p.setContext(getContext()); - Node t = p.parse(); - this.head = p.compile(t, getEffectiveConverterMap()); - ConverterUtil.startConverters(this.head); - } catch (ScanException ex) { - addError("Incorrect pattern found", ex); - errorCount++; - } - - if (errorCount == 0) { - super.started = true; - } - } - - protected abstract Map getDefaultConverterMap(); - - - /** - * Returns a map where the default converter map is merged with the map - * contained in the context. - */ - public Map getEffectiveConverterMap() { - Map effectiveMap = new HashMap(); - - // add the least specific map fist - Map defaultMap = getDefaultConverterMap(); - if (defaultMap != null) { - effectiveMap.putAll(defaultMap); - } - - // contextMap is more specific than the default map - Context context = getContext(); - if (context != null) { - @SuppressWarnings("unchecked") - Map contextMap = (Map) context - .getObject(CoreConstants.PATTERN_RULE_REGISTRY); - if (contextMap != null) { - effectiveMap.putAll(contextMap); - } - } - return effectiveMap; - } - - /** - * The Title option takes a String value. This option sets the - * document title of the generated HTML document. - * - *

- * Defaults to 'Logback Log Messages'. - */ - public void setTitle(String title) { - this.title = title; - } - - /** - * Returns the current value of the Title option. - */ - public String getTitle() { - return title; - } - - /** - * Returns the content type output by this layout, i.e "text/html". - */ - @Override - public String getContentType() { - return "text/html"; - } - - /** - * Returns appropriate HTML headers. - */ - @Override - public String getFileHeader() { - StringBuilder sbuf = new StringBuilder(); - sbuf.append(""); - sbuf.append(LINE_SEPARATOR); - sbuf.append(""); - sbuf.append(LINE_SEPARATOR); - sbuf.append(" "); - sbuf.append(LINE_SEPARATOR); - sbuf.append(" "); - sbuf.append(title); - sbuf.append(""); - sbuf.append(LINE_SEPARATOR); - - cssBuilder.addCss(sbuf); -// if (cssBuilder == null) { -// DefaultCssBuilder.addDefaultCSS(sbuf); -// } else { -// cssBuilder.addExternalCSS(sbuf); -// } - sbuf.append(LINE_SEPARATOR); - sbuf.append(" "); - sbuf.append(LINE_SEPARATOR); - sbuf.append(""); - sbuf.append(LINE_SEPARATOR); - - return sbuf.toString(); - } - - public String getPresentationHeader() { - StringBuilder sbuf = new StringBuilder(); - sbuf.append("


"); - sbuf.append(LINE_SEPARATOR); - sbuf.append("

Log session start time "); - sbuf.append(new java.util.Date()); - sbuf.append("

"); - sbuf.append(LINE_SEPARATOR); - sbuf.append(LINE_SEPARATOR); - sbuf.append(""); - sbuf.append(LINE_SEPARATOR); - - buildHeaderRowForTable(sbuf); - - return sbuf.toString(); - } - - - private void buildHeaderRowForTable(StringBuilder sbuf) { - Converter c = head; - String name; - sbuf.append(""); - sbuf.append(LINE_SEPARATOR); - while (c != null) { - name = computeConverterName(c); - if (name == null) { - c = c.getNext(); - continue; - } - sbuf.append(""); - sbuf.append(LINE_SEPARATOR); - c = c.getNext(); - } - sbuf.append(""); - sbuf.append(LINE_SEPARATOR); - } - - public String getPresentationFooter() { - StringBuilder sbuf = new StringBuilder(); - sbuf.append("
"); - sbuf.append(computeConverterName(c)); - sbuf.append("
"); - return sbuf.toString(); - } - - /** - * Returns the appropriate HTML footers. - */ - @Override - public String getFileFooter() { - StringBuilder sbuf = new StringBuilder(); - sbuf.append(LINE_SEPARATOR); - sbuf.append(""); - return sbuf.toString(); - } - - protected void startNewTableIfLimitReached(StringBuilder sbuf) { - if (this.counter >= CoreConstants.TABLE_ROW_LIMIT) { - counter = 0; - sbuf.append(""); - sbuf.append(LINE_SEPARATOR); - sbuf.append("

"); - sbuf.append(""); - sbuf.append(LINE_SEPARATOR); - buildHeaderRowForTable(sbuf); - } - } - - protected String computeConverterName(Converter c) { - String className = c.getClass().getSimpleName(); - int index = className.indexOf("Converter"); - if (index == -1) { - return className; - } else { - return className.substring(0, index); - } - } - -} +/** + * 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.html; + +import java.util.HashMap; +import java.util.Map; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; +import ch.qos.logback.core.LayoutBase; +import ch.qos.logback.core.pattern.Converter; +import ch.qos.logback.core.pattern.ConverterUtil; +import ch.qos.logback.core.pattern.parser.Node; +import ch.qos.logback.core.pattern.parser.Parser; +import ch.qos.logback.core.pattern.parser.ScanException; + +/** + * This class is a base class for HTMLLayout classes part of + * other logback modules such as logback-classic and logback-access. + * + * + * @author Sébastien Pennec + */ +public abstract class HTMLLayoutBase extends LayoutBase { + + protected String pattern; + + protected Converter head; + + protected String title = "Logback Log Messages"; + + //It is the responsibility of derived classes to set + //this variable in their constructor to a default value. + protected CssBuilder cssBuilder; + + // counter keeping track of the rows output + protected long counter = 0; + + /** + * Set the ConversionPattern option. This is the string which controls + * formatting and consists of a mix of literal content and conversion + * specifiers. + */ + public void setPattern(String conversionPattern) { + pattern = conversionPattern; + } + + /** + * Returns the value of the ConversionPattern option. + */ + public String getPattern() { + return pattern; + } + + public CssBuilder getCssBuilder() { + return cssBuilder; + } + + public void setCssBuilder(CssBuilder cssBuilder) { + this.cssBuilder = cssBuilder; + } + + /** + * Parses the pattern and creates the Converter linked list. + */ + @Override + public void start() { + int errorCount = 0; + + try { + Parser p = new Parser(pattern); + p.setContext(getContext()); + Node t = p.parse(); + this.head = p.compile(t, getEffectiveConverterMap()); + ConverterUtil.startConverters(this.head); + } catch (ScanException ex) { + addError("Incorrect pattern found", ex); + errorCount++; + } + + if (errorCount == 0) { + super.started = true; + } + } + + protected abstract Map getDefaultConverterMap(); + + + /** + * Returns a map where the default converter map is merged with the map + * contained in the context. + */ + public Map getEffectiveConverterMap() { + Map effectiveMap = new HashMap(); + + // add the least specific map fist + Map defaultMap = getDefaultConverterMap(); + if (defaultMap != null) { + effectiveMap.putAll(defaultMap); + } + + // contextMap is more specific than the default map + Context context = getContext(); + if (context != null) { + @SuppressWarnings("unchecked") + Map contextMap = (Map) context + .getObject(CoreConstants.PATTERN_RULE_REGISTRY); + if (contextMap != null) { + effectiveMap.putAll(contextMap); + } + } + return effectiveMap; + } + + /** + * The Title option takes a String value. This option sets the + * document title of the generated HTML document. + * + *

+ * Defaults to 'Logback Log Messages'. + */ + public void setTitle(String title) { + this.title = title; + } + + /** + * Returns the current value of the Title option. + */ + public String getTitle() { + return title; + } + + /** + * Returns the content type output by this layout, i.e "text/html". + */ + @Override + public String getContentType() { + return "text/html"; + } + + /** + * Returns appropriate HTML headers. + */ + @Override + public String getFileHeader() { + StringBuilder sbuf = new StringBuilder(); + sbuf.append(""); + sbuf.append(LINE_SEPARATOR); + sbuf.append(""); + sbuf.append(LINE_SEPARATOR); + sbuf.append(" "); + sbuf.append(LINE_SEPARATOR); + sbuf.append(" "); + sbuf.append(title); + sbuf.append(""); + sbuf.append(LINE_SEPARATOR); + + cssBuilder.addCss(sbuf); +// if (cssBuilder == null) { +// DefaultCssBuilder.addDefaultCSS(sbuf); +// } else { +// cssBuilder.addExternalCSS(sbuf); +// } + sbuf.append(LINE_SEPARATOR); + sbuf.append(" "); + sbuf.append(LINE_SEPARATOR); + sbuf.append(""); + sbuf.append(LINE_SEPARATOR); + + return sbuf.toString(); + } + + public String getPresentationHeader() { + StringBuilder sbuf = new StringBuilder(); + sbuf.append("


"); + sbuf.append(LINE_SEPARATOR); + sbuf.append("

Log session start time "); + sbuf.append(new java.util.Date()); + sbuf.append("

"); + sbuf.append(LINE_SEPARATOR); + sbuf.append(LINE_SEPARATOR); + sbuf.append("
"); + sbuf.append(LINE_SEPARATOR); + + buildHeaderRowForTable(sbuf); + + return sbuf.toString(); + } + + + private void buildHeaderRowForTable(StringBuilder sbuf) { + Converter c = head; + String name; + sbuf.append(""); + sbuf.append(LINE_SEPARATOR); + while (c != null) { + name = computeConverterName(c); + if (name == null) { + c = c.getNext(); + continue; + } + sbuf.append(""); + sbuf.append(LINE_SEPARATOR); + c = c.getNext(); + } + sbuf.append(""); + sbuf.append(LINE_SEPARATOR); + } + + public String getPresentationFooter() { + StringBuilder sbuf = new StringBuilder(); + sbuf.append("
"); + sbuf.append(computeConverterName(c)); + sbuf.append("
"); + return sbuf.toString(); + } + + /** + * Returns the appropriate HTML footers. + */ + @Override + public String getFileFooter() { + StringBuilder sbuf = new StringBuilder(); + sbuf.append(LINE_SEPARATOR); + sbuf.append(""); + return sbuf.toString(); + } + + protected void startNewTableIfLimitReached(StringBuilder sbuf) { + if (this.counter >= CoreConstants.TABLE_ROW_LIMIT) { + counter = 0; + sbuf.append(""); + sbuf.append(LINE_SEPARATOR); + sbuf.append("

"); + sbuf.append(""); + sbuf.append(LINE_SEPARATOR); + buildHeaderRowForTable(sbuf); + } + } + + protected String computeConverterName(Converter c) { + String className = c.getClass().getSimpleName(); + int index = className.indexOf("Converter"); + if (index == -1) { + return className; + } else { + return className.substring(0, index); + } + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/html/IThrowableRenderer.java b/logback-core/src/main/java/ch/qos/logback/core/html/IThrowableRenderer.java index 36b28f9cca8b031de24d2ada973eec374a329637..542c4839547b569b2a27cf90e9531804f8d757fa 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/html/IThrowableRenderer.java +++ b/logback-core/src/main/java/ch/qos/logback/core/html/IThrowableRenderer.java @@ -1,21 +1,21 @@ -/** - * 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.html; - - -public interface IThrowableRenderer { - - public void render(StringBuilder sbuf, E event); - -} +/** + * 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.html; + + +public interface IThrowableRenderer { + + public void render(StringBuilder sbuf, E event); + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/html/NOPThrowableRenderer.java b/logback-core/src/main/java/ch/qos/logback/core/html/NOPThrowableRenderer.java index 74e7f1fffcbd92ca9d796261f2f2bde38701d226..422510d56d26562505f685a17b1ae7ceb559108e 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/html/NOPThrowableRenderer.java +++ b/logback-core/src/main/java/ch/qos/logback/core/html/NOPThrowableRenderer.java @@ -1,25 +1,25 @@ -/** - * 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.html; - -import ch.qos.logback.core.html.IThrowableRenderer; - - -public class NOPThrowableRenderer implements IThrowableRenderer { - - public void render(StringBuilder sbuf, Object event) { - return; - } - -} +/** + * 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.html; + +import ch.qos.logback.core.html.IThrowableRenderer; + + +public class NOPThrowableRenderer implements IThrowableRenderer { + + public void render(StringBuilder sbuf, Object event) { + return; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/html/package.html b/logback-core/src/main/java/ch/qos/logback/core/html/package.html index 41dd062c563ca51af3d4b021288857e759bf475b..01a5548e9e33334762c61d75b808b9b50f409f07 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/html/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/html/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains the base classes needed to format logging events to HTML.

- - + + + + + + + + + +

Contains the base classes needed to format logging events to HTML.

+ + \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java b/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java index 80a83cc38d29a658fb544034198b1c47fd6e0a48..be9f466322cda93b2e95e1f81344499dcbc00725 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java @@ -1,136 +1,136 @@ -/** - * 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.joran; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.util.List; - -import org.xml.sax.InputSource; - -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.joran.event.SaxEventRecorder; -import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; -import ch.qos.logback.core.joran.spi.EventPlayer; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.joran.spi.Interpreter; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.joran.spi.RuleStore; -import ch.qos.logback.core.joran.spi.SimpleRuleStore; -import ch.qos.logback.core.spi.ContextAwareBase; - -public abstract class GenericConfigurator extends ContextAwareBase { - - protected Interpreter interpreter; - - final public void doConfigure(URL url) throws JoranException { - try { - informContextOfURLUsedForConfiguration(url); - URLConnection urlConnection = url.openConnection(); - // per http://jira.qos.ch/browse/LBCORE-105 - // per http://jira.qos.ch/browse/LBCORE-127 - urlConnection.setUseCaches(false); - - InputStream in = urlConnection.getInputStream(); - doConfigure(in); - in.close(); - } catch (IOException ioe) { - String errMsg = "Could not open URL [" + url + "]."; - addError(errMsg, ioe); - throw new JoranException(errMsg, ioe); - } - } - - final public void doConfigure(String filename) throws JoranException { - doConfigure(new File(filename)); - } - - final public void doConfigure(File file) throws JoranException { - FileInputStream fis = null; - try { - informContextOfURLUsedForConfiguration(file.toURI().toURL()); - fis = new FileInputStream(file); - doConfigure(fis); - } catch (IOException ioe) { - String errMsg = "Could not open [" + file.getName() + "]."; - addError(errMsg, ioe); - throw new JoranException(errMsg, ioe); - } finally { - if (fis != null) { - try { - fis.close(); - } catch (java.io.IOException ioe) { - String errMsg = "Could not close [" + file.getName() + "]."; - addError(errMsg, ioe); - throw new JoranException(errMsg, ioe); - } - } - } - } - - protected void informContextOfURLUsedForConfiguration(URL url) { - getContext().putObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN, url); - } - - final public void doConfigure(InputStream inputStream) throws JoranException { - doConfigure(new InputSource(inputStream)); - } - - abstract protected void addInstanceRules(RuleStore rs); - - abstract protected void addImplicitRules(Interpreter interpreter); - - protected void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) { - - } - - protected Pattern initialPattern() { - return new Pattern(); - } - - protected void buildInterpreter() { - RuleStore rs = new SimpleRuleStore(context); - addInstanceRules(rs); - this.interpreter = new Interpreter(context, rs, initialPattern()); - InterpretationContext ec = interpreter.getInterpretationContext(); - ec.setContext(context); - addImplicitRules(interpreter); - addDefaultNestedComponentRegistryRules(ec.getDefaultNestedComponentRegistry()); - } - - final public void doConfigure(final InputSource inputSource) - throws JoranException { - SaxEventRecorder recorder = new SaxEventRecorder(); - recorder.setContext(context); - recorder.recordEvents(inputSource); - buildInterpreter(); - // disallow simultaneous configurations of the same context - synchronized (context.getConfigurationLock()) { - interpreter.play(recorder.saxEventList); - } - } - - public void doConfigure(final List eventList) - throws JoranException { - buildInterpreter(); - EventPlayer player = new EventPlayer(interpreter); - player.play(eventList); - } -} +/** + * 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.joran; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.List; + +import org.xml.sax.InputSource; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.event.SaxEventRecorder; +import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; +import ch.qos.logback.core.joran.spi.EventPlayer; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.joran.spi.RuleStore; +import ch.qos.logback.core.joran.spi.SimpleRuleStore; +import ch.qos.logback.core.spi.ContextAwareBase; + +public abstract class GenericConfigurator extends ContextAwareBase { + + protected Interpreter interpreter; + + final public void doConfigure(URL url) throws JoranException { + try { + informContextOfURLUsedForConfiguration(url); + URLConnection urlConnection = url.openConnection(); + // per http://jira.qos.ch/browse/LBCORE-105 + // per http://jira.qos.ch/browse/LBCORE-127 + urlConnection.setUseCaches(false); + + InputStream in = urlConnection.getInputStream(); + doConfigure(in); + in.close(); + } catch (IOException ioe) { + String errMsg = "Could not open URL [" + url + "]."; + addError(errMsg, ioe); + throw new JoranException(errMsg, ioe); + } + } + + final public void doConfigure(String filename) throws JoranException { + doConfigure(new File(filename)); + } + + final public void doConfigure(File file) throws JoranException { + FileInputStream fis = null; + try { + informContextOfURLUsedForConfiguration(file.toURI().toURL()); + fis = new FileInputStream(file); + doConfigure(fis); + } catch (IOException ioe) { + String errMsg = "Could not open [" + file.getName() + "]."; + addError(errMsg, ioe); + throw new JoranException(errMsg, ioe); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (java.io.IOException ioe) { + String errMsg = "Could not close [" + file.getName() + "]."; + addError(errMsg, ioe); + throw new JoranException(errMsg, ioe); + } + } + } + } + + protected void informContextOfURLUsedForConfiguration(URL url) { + getContext().putObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN, url); + } + + final public void doConfigure(InputStream inputStream) throws JoranException { + doConfigure(new InputSource(inputStream)); + } + + abstract protected void addInstanceRules(RuleStore rs); + + abstract protected void addImplicitRules(Interpreter interpreter); + + protected void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) { + + } + + protected Pattern initialPattern() { + return new Pattern(); + } + + protected void buildInterpreter() { + RuleStore rs = new SimpleRuleStore(context); + addInstanceRules(rs); + this.interpreter = new Interpreter(context, rs, initialPattern()); + InterpretationContext ec = interpreter.getInterpretationContext(); + ec.setContext(context); + addImplicitRules(interpreter); + addDefaultNestedComponentRegistryRules(ec.getDefaultNestedComponentRegistry()); + } + + final public void doConfigure(final InputSource inputSource) + throws JoranException { + SaxEventRecorder recorder = new SaxEventRecorder(); + recorder.setContext(context); + recorder.recordEvents(inputSource); + buildInterpreter(); + // disallow simultaneous configurations of the same context + synchronized (context.getConfigurationLock()) { + interpreter.play(recorder.saxEventList); + } + } + + public void doConfigure(final List eventList) + throws JoranException { + buildInterpreter(); + EventPlayer player = new EventPlayer(interpreter); + player.play(eventList); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/AbstractEventEvaluatorAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/AbstractEventEvaluatorAction.java index 885db1417bb25131d06bc0713f9a9f94e772ce69..b442394bb4c6c3053afcf07d6f8015e812886d08 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/AbstractEventEvaluatorAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/AbstractEventEvaluatorAction.java @@ -1,118 +1,118 @@ -/** - * 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.joran.action; - -import java.util.Map; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.boolex.EventEvaluator; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.spi.LifeCycle; -import ch.qos.logback.core.util.OptionHelper; - -abstract public class AbstractEventEvaluatorAction extends Action { - - EventEvaluator evaluator; - boolean inError = false; - - /** - * Instantiates an evaluator of the given class and sets its name. - */ - public void begin(InterpretationContext ec, String name, Attributes attributes) { - // Let us forget about previous errors (in this instance) - inError = false; - evaluator = null; - - String className = attributes.getValue(CLASS_ATTRIBUTE); - if (OptionHelper.isEmpty(className)) { - className = defaultClassName(); - addWarn("Assuming default evaluator class [" + className + "]"); - } - - if (OptionHelper.isEmpty(className)) { - className = defaultClassName(); - inError = true; - addError("Mandatory \"" + CLASS_ATTRIBUTE - + "\" attribute not set for "); - return; - } - - String evaluatorName = attributes.getValue(Action.NAME_ATTRIBUTE); - if (OptionHelper.isEmpty(evaluatorName)) { - inError = true; - addError("Mandatory \"" + NAME_ATTRIBUTE - + "\" attribute not set for "); - return; - } - try { - evaluator = (EventEvaluator) OptionHelper.instantiateByClassName( - className, ch.qos.logback.core.boolex.EventEvaluator.class, context); - - evaluator.setContext(this.context); - evaluator.setName(evaluatorName); - - ec.pushObject(evaluator); - addInfo("Adding evaluator named [" + evaluatorName - + "] to the object stack"); - - } catch (Exception oops) { - inError = true; - addError("Could not create evaluator of type " + className + "].", oops); - } - } - - /** - * Returns a default class name in case the class attribute is not specified - * - * @return - */ - abstract protected String defaultClassName(); - - /** - * Once the children elements are also parsed, now is the time to activate the - * evaluator options. - */ - @SuppressWarnings("unchecked") - public void end(InterpretationContext ec, String e) { - if (inError) { - return; - } - - if (evaluator instanceof LifeCycle) { - ((LifeCycle) evaluator).start(); - addInfo("Starting evaluator named [" + evaluator.getName() + "]"); - } - - Object o = ec.peekObject(); - - if (o != evaluator) { - addWarn("The object on the top the of the stack is not the evaluator pushed earlier."); - } else { - ec.popObject(); - - try { - Map evaluatorMap = (Map) context - .getObject(CoreConstants.EVALUATOR_MAP); - evaluatorMap.put(evaluator.getName(), evaluator); - } catch (Exception ex) { - addError("Could not set evaluator named [" + evaluator + "].", ex); - } - } - } - - public void finish(InterpretationContext ec) { - } -} +/** + * 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.joran.action; + +import java.util.Map; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.util.OptionHelper; + +abstract public class AbstractEventEvaluatorAction extends Action { + + EventEvaluator evaluator; + boolean inError = false; + + /** + * Instantiates an evaluator of the given class and sets its name. + */ + public void begin(InterpretationContext ec, String name, Attributes attributes) { + // Let us forget about previous errors (in this instance) + inError = false; + evaluator = null; + + String className = attributes.getValue(CLASS_ATTRIBUTE); + if (OptionHelper.isEmpty(className)) { + className = defaultClassName(); + addWarn("Assuming default evaluator class [" + className + "]"); + } + + if (OptionHelper.isEmpty(className)) { + className = defaultClassName(); + inError = true; + addError("Mandatory \"" + CLASS_ATTRIBUTE + + "\" attribute not set for "); + return; + } + + String evaluatorName = attributes.getValue(Action.NAME_ATTRIBUTE); + if (OptionHelper.isEmpty(evaluatorName)) { + inError = true; + addError("Mandatory \"" + NAME_ATTRIBUTE + + "\" attribute not set for "); + return; + } + try { + evaluator = (EventEvaluator) OptionHelper.instantiateByClassName( + className, ch.qos.logback.core.boolex.EventEvaluator.class, context); + + evaluator.setContext(this.context); + evaluator.setName(evaluatorName); + + ec.pushObject(evaluator); + addInfo("Adding evaluator named [" + evaluatorName + + "] to the object stack"); + + } catch (Exception oops) { + inError = true; + addError("Could not create evaluator of type " + className + "].", oops); + } + } + + /** + * Returns a default class name in case the class attribute is not specified + * + * @return + */ + abstract protected String defaultClassName(); + + /** + * Once the children elements are also parsed, now is the time to activate the + * evaluator options. + */ + @SuppressWarnings("unchecked") + public void end(InterpretationContext ec, String e) { + if (inError) { + return; + } + + if (evaluator instanceof LifeCycle) { + ((LifeCycle) evaluator).start(); + addInfo("Starting evaluator named [" + evaluator.getName() + "]"); + } + + Object o = ec.peekObject(); + + if (o != evaluator) { + addWarn("The object on the top the of the stack is not the evaluator pushed earlier."); + } else { + ec.popObject(); + + try { + Map evaluatorMap = (Map) context + .getObject(CoreConstants.EVALUATOR_MAP); + evaluatorMap.put(evaluator.getName(), evaluator); + } catch (Exception ex) { + addError("Could not set evaluator named [" + evaluator + "].", ex); + } + } + } + + public void finish(InterpretationContext ec) { + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java index c9ef89b8566b3ebb36fec8dad84629210236bf26..abbe4f613b750f932604cf02cddee63096a43b81 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java @@ -1,95 +1,95 @@ -/** - * 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.joran.action; - -import org.xml.sax.Attributes; -import org.xml.sax.Locator; - -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.joran.spi.Interpreter; -import ch.qos.logback.core.spi.ContextAwareBase; - -/** - * - * Most of the work for configuring logback is done by Actions. - * - *

Action methods are invoked as the XML file is parsed. - * - *

This class is largely inspired from the relevant class in the - * commons-digester project of the Apache Software Foundation. - * - * @author Craig McClanahan - * @author Christopher Lenz - * @author Ceki Gülcü - * - */ -public abstract class Action extends ContextAwareBase { - - public static final String NAME_ATTRIBUTE = "name"; - public static final String KEY_ATTRIBUTE = "key"; - public static final String VALUE_ATTRIBUTE = "value"; - public static final String FILE_ATTRIBUTE = "file"; - public static final String CLASS_ATTRIBUTE = "class"; - public static final String PATTERN_ATTRIBUTE = "pattern"; - - public static final String ACTION_CLASS_ATTRIBUTE = "actionClass"; - - /** - * Called when the parser encounters an element matching a - * {@link ch.qos.logback.core.joran.spi.Pattern Pattern}. - */ - public abstract void begin(InterpretationContext ec, String name, - Attributes attributes) throws ActionException; - - public void body(InterpretationContext ec, String body) - throws ActionException { - // NOP - } - - /* - * Called when the parser encounters an endElement event matching a - * {@link ch.qos.logback.core.joran.spi.Pattern Pattern}. - */ - public abstract void end(InterpretationContext ec, String name) - throws ActionException; - - public String toString() { - return this.getClass().getName(); - } - - protected int getColumnNumber(InterpretationContext ec) { - Interpreter jp = ec.getJoranInterpreter(); - Locator locator = jp.getLocator(); - if (locator != null) { - return locator.getColumnNumber(); - } - return -1; - } - - protected int getLineNumber(InterpretationContext ec) { - Interpreter jp = ec.getJoranInterpreter(); - Locator locator = jp.getLocator(); - if (locator != null) { - return locator.getLineNumber(); - } - return -1; - } - - protected String getLineColStr(InterpretationContext ec) { - String line = "line: " + getLineNumber(ec) + ", column: " - + getColumnNumber(ec); - return line; - } -} +/** + * 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.joran.action; + +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.spi.ContextAwareBase; + +/** + * + * Most of the work for configuring logback is done by Actions. + * + *

Action methods are invoked as the XML file is parsed. + * + *

This class is largely inspired from the relevant class in the + * commons-digester project of the Apache Software Foundation. + * + * @author Craig McClanahan + * @author Christopher Lenz + * @author Ceki Gülcü + * + */ +public abstract class Action extends ContextAwareBase { + + public static final String NAME_ATTRIBUTE = "name"; + public static final String KEY_ATTRIBUTE = "key"; + public static final String VALUE_ATTRIBUTE = "value"; + public static final String FILE_ATTRIBUTE = "file"; + public static final String CLASS_ATTRIBUTE = "class"; + public static final String PATTERN_ATTRIBUTE = "pattern"; + + public static final String ACTION_CLASS_ATTRIBUTE = "actionClass"; + + /** + * Called when the parser encounters an element matching a + * {@link ch.qos.logback.core.joran.spi.Pattern Pattern}. + */ + public abstract void begin(InterpretationContext ec, String name, + Attributes attributes) throws ActionException; + + public void body(InterpretationContext ec, String body) + throws ActionException { + // NOP + } + + /* + * Called when the parser encounters an endElement event matching a + * {@link ch.qos.logback.core.joran.spi.Pattern Pattern}. + */ + public abstract void end(InterpretationContext ec, String name) + throws ActionException; + + public String toString() { + return this.getClass().getName(); + } + + protected int getColumnNumber(InterpretationContext ec) { + Interpreter jp = ec.getJoranInterpreter(); + Locator locator = jp.getLocator(); + if (locator != null) { + return locator.getColumnNumber(); + } + return -1; + } + + protected int getLineNumber(InterpretationContext ec) { + Interpreter jp = ec.getJoranInterpreter(); + Locator locator = jp.getLocator(); + if (locator != null) { + return locator.getLineNumber(); + } + return -1; + } + + protected String getLineColStr(InterpretationContext ec) { + String line = "line: " + getLineNumber(ec) + ", column: " + + getColumnNumber(ec); + return line; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ActionConst.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ActionConst.java index 30b5ca9b9a012dcbf737ee8f1d406214b972ce6c..17b0222650713baf185d71fa2a95c1317677f13d 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ActionConst.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ActionConst.java @@ -1,41 +1,41 @@ -/** - * 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.joran.action; - -/** - * - * This class contains costants used by other Actions. - * - * @author Ceki Gülcü - * - */ -public abstract class ActionConst { - - public static final String APPENDER_TAG = "appender"; - public static final String REF_ATTRIBUTE = "ref"; - public static final String ADDITIVITY_ATTRIBUTE = "additivity"; - public static final String LEVEL_ATTRIBUTE = "level"; - public static final String CONVERTER_CLASS_ATTRIBUTE = "converterClass"; - public static final String CONVERSION_WORD_ATTRIBUTE = "conversionWord"; - public static final String PATTERN_ATTRIBUTE = "pattern"; - public static final String VALUE_ATTR = "value"; - public static final String ACTION_CLASS_ATTRIBUTE = "actionClass"; - - public static final String INHERITED = "INHERITED"; - public static final String NULL = "NULL"; - static final Class[] ONE_STRING_PARAM = new Class[] { String.class }; - - public static final String APPENDER_BAG = "APPENDER_BAG"; - public static final String FILTER_CHAIN_BAG = "FILTER_CHAIN_BAG"; -} +/** + * 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.joran.action; + +/** + * + * This class contains costants used by other Actions. + * + * @author Ceki Gülcü + * + */ +public abstract class ActionConst { + + public static final String APPENDER_TAG = "appender"; + public static final String REF_ATTRIBUTE = "ref"; + public static final String ADDITIVITY_ATTRIBUTE = "additivity"; + public static final String LEVEL_ATTRIBUTE = "level"; + public static final String CONVERTER_CLASS_ATTRIBUTE = "converterClass"; + public static final String CONVERSION_WORD_ATTRIBUTE = "conversionWord"; + public static final String PATTERN_ATTRIBUTE = "pattern"; + public static final String VALUE_ATTR = "value"; + public static final String ACTION_CLASS_ATTRIBUTE = "actionClass"; + + public static final String INHERITED = "INHERITED"; + public static final String NULL = "NULL"; + static final Class[] ONE_STRING_PARAM = new Class[] { String.class }; + + public static final String APPENDER_BAG = "APPENDER_BAG"; + public static final String FILTER_CHAIN_BAG = "FILTER_CHAIN_BAG"; +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java index 9a8e586397698bf71aee2f35659e7a607c4bf198..7604a5ffab7fc3d4490deddb5892fa64cbeec3ea 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java @@ -1,110 +1,110 @@ -/** - * 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.joran.action; - -import java.util.HashMap; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.spi.LifeCycle; -import ch.qos.logback.core.util.OptionHelper; - -public class AppenderAction extends Action { - Appender appender; - private boolean inError = false; - - /** - * Instantiates an appender of the given class and sets its name. - * - * The appender thus generated is placed in the {@link InterpretationContext}'s - * appender bag. - */ - @SuppressWarnings("unchecked") - public void begin(InterpretationContext ec, String localName, - Attributes attributes) throws ActionException { - // We are just beginning, reset variables - appender = null; - inError = false; - - String className = attributes.getValue(CLASS_ATTRIBUTE); - if (OptionHelper.isEmpty(className)) { - addError("Missing class name for appender. Near [" + localName - + "] line " + getLineNumber(ec)); - inError = true; - return; - } - - try { - addInfo("About to instantiate appender of type [" + className + "]"); - - appender = (Appender) OptionHelper.instantiateByClassName(className, - ch.qos.logback.core.Appender.class, context); - - appender.setContext(context); - - String appenderName = ec.subst(attributes.getValue(NAME_ATTRIBUTE)); - - if (OptionHelper.isEmpty(appenderName)) { - addWarn("No appender name given for appender of type " + className - + "]."); - } else { - appender.setName(appenderName); - addInfo("Naming appender as [" + appenderName + "]"); - } - - // The execution context contains a bag which contains the appenders - // created thus far. - HashMap appenderBag = (HashMap) ec.getObjectMap().get( - ActionConst.APPENDER_BAG); - - // add the appender just created to the appender bag. - appenderBag.put(appenderName, appender); - - ec.pushObject(appender); - } catch (Exception oops) { - inError = true; - addError("Could not create an Appender of type [" + className + "].", - oops); - throw new ActionException(oops); - } - } - - /** - * Once the children elements are also parsed, now is the time to activate the - * appender options. - */ - public void end(InterpretationContext ec, String name) { - if (inError) { - return; - } - - if (appender instanceof LifeCycle) { - ((LifeCycle) appender).start(); - } - - Object o = ec.peekObject(); - - if (o != appender) { - addWarn("The object at the of the stack is not the appender named [" - + appender.getName() + "] pushed earlier."); - } else { - addInfo("Popping appender named [" + appender.getName() - + "] from the object stack"); - ec.popObject(); - } - } -} +/** + * 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.joran.action; + +import java.util.HashMap; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.util.OptionHelper; + +public class AppenderAction extends Action { + Appender appender; + private boolean inError = false; + + /** + * Instantiates an appender of the given class and sets its name. + * + * The appender thus generated is placed in the {@link InterpretationContext}'s + * appender bag. + */ + @SuppressWarnings("unchecked") + public void begin(InterpretationContext ec, String localName, + Attributes attributes) throws ActionException { + // We are just beginning, reset variables + appender = null; + inError = false; + + String className = attributes.getValue(CLASS_ATTRIBUTE); + if (OptionHelper.isEmpty(className)) { + addError("Missing class name for appender. Near [" + localName + + "] line " + getLineNumber(ec)); + inError = true; + return; + } + + try { + addInfo("About to instantiate appender of type [" + className + "]"); + + appender = (Appender) OptionHelper.instantiateByClassName(className, + ch.qos.logback.core.Appender.class, context); + + appender.setContext(context); + + String appenderName = ec.subst(attributes.getValue(NAME_ATTRIBUTE)); + + if (OptionHelper.isEmpty(appenderName)) { + addWarn("No appender name given for appender of type " + className + + "]."); + } else { + appender.setName(appenderName); + addInfo("Naming appender as [" + appenderName + "]"); + } + + // The execution context contains a bag which contains the appenders + // created thus far. + HashMap appenderBag = (HashMap) ec.getObjectMap().get( + ActionConst.APPENDER_BAG); + + // add the appender just created to the appender bag. + appenderBag.put(appenderName, appender); + + ec.pushObject(appender); + } catch (Exception oops) { + inError = true; + addError("Could not create an Appender of type [" + className + "].", + oops); + throw new ActionException(oops); + } + } + + /** + * Once the children elements are also parsed, now is the time to activate the + * appender options. + */ + public void end(InterpretationContext ec, String name) { + if (inError) { + return; + } + + if (appender instanceof LifeCycle) { + ((LifeCycle) appender).start(); + } + + Object o = ec.peekObject(); + + if (o != appender) { + addWarn("The object at the of the stack is not the appender named [" + + appender.getName() + "] pushed earlier."); + } else { + addInfo("Popping appender named [" + appender.getName() + + "] from the object stack"); + ec.popObject(); + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderRefAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderRefAction.java index 97e0b19b6a666ca55e0a9e866bfb2646956e4cd1..8923f3b6014ea85963c91891688050293c5a0a7d 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderRefAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderRefAction.java @@ -1,82 +1,82 @@ -/** - * 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.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.spi.AppenderAttachable; -import ch.qos.logback.core.util.OptionHelper; - - -import java.util.HashMap; - -public class AppenderRefAction extends Action { - boolean inError = false; - - @SuppressWarnings("unchecked") - public void begin(InterpretationContext ec, String tagName, Attributes attributes) { - // Let us forget about previous errors (in this object) - inError = false; - - // logger.debug("begin called"); - - Object o = ec.peekObject(); - - if (!(o instanceof AppenderAttachable)) { - String errMsg = "Could not find an AppenderAttachable at the top of execution stack. Near [" - + tagName + "] line " + getLineNumber(ec); - inError = true; - addError(errMsg); - return; - } - - AppenderAttachable appenderAttachable = (AppenderAttachable) o; - - String appenderName = attributes.getValue(ActionConst.REF_ATTRIBUTE); - - if (OptionHelper.isEmpty(appenderName)) { - // print a meaningful error message and return - String errMsg = "Missing appender ref attribute in tag."; - inError = true; - addError(errMsg); - - return; - } - - HashMap appenderBag = (HashMap) ec.getObjectMap().get( - ActionConst.APPENDER_BAG); - Appender appender = (Appender) appenderBag.get(appenderName); - - if (appender == null) { - String msg = "Could not find an appender named [" + appenderName - + "]. Did you define it below in the config file?"; - inError = true; - addError(msg); - addError("See " + CoreConstants.CODES_URL - + "#appender_order for more details."); - return; - } - - addInfo("Attaching appender named [" + appenderName + "] to " - + appenderAttachable); - appenderAttachable.addAppender(appender); - } - - public void end(InterpretationContext ec, String n) { - } - -} +/** + * 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.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.spi.AppenderAttachable; +import ch.qos.logback.core.util.OptionHelper; + + +import java.util.HashMap; + +public class AppenderRefAction extends Action { + boolean inError = false; + + @SuppressWarnings("unchecked") + public void begin(InterpretationContext ec, String tagName, Attributes attributes) { + // Let us forget about previous errors (in this object) + inError = false; + + // logger.debug("begin called"); + + Object o = ec.peekObject(); + + if (!(o instanceof AppenderAttachable)) { + String errMsg = "Could not find an AppenderAttachable at the top of execution stack. Near [" + + tagName + "] line " + getLineNumber(ec); + inError = true; + addError(errMsg); + return; + } + + AppenderAttachable appenderAttachable = (AppenderAttachable) o; + + String appenderName = attributes.getValue(ActionConst.REF_ATTRIBUTE); + + if (OptionHelper.isEmpty(appenderName)) { + // print a meaningful error message and return + String errMsg = "Missing appender ref attribute in tag."; + inError = true; + addError(errMsg); + + return; + } + + HashMap appenderBag = (HashMap) ec.getObjectMap().get( + ActionConst.APPENDER_BAG); + Appender appender = (Appender) appenderBag.get(appenderName); + + if (appender == null) { + String msg = "Could not find an appender named [" + appenderName + + "]. Did you define it below in the config file?"; + inError = true; + addError(msg); + addError("See " + CoreConstants.CODES_URL + + "#appender_order for more details."); + return; + } + + addInfo("Attaching appender named [" + appenderName + "] to " + + appenderAttachable); + appenderAttachable.addAppender(appender); + } + + public void end(InterpretationContext ec, String n) { + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ContextPropertyAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ContextPropertyAction.java index 558398620ac3f41a2e252ffa4f55a9c53982a648..eb129da2e49472bf6d0187b283e27686242fb830 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ContextPropertyAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ContextPropertyAction.java @@ -1,36 +1,36 @@ -/** - * 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.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; - -/** - * @author Ceki Gulcu - */ -public class ContextPropertyAction extends Action { - - @Override - public void begin(InterpretationContext ec, String name, Attributes attributes) - throws ActionException { - addError("The [contextProperty] element has been removed. Please use [substitutionProperty] element instead"); - } - - @Override - public void end(InterpretationContext ec, String name) throws ActionException { - } - -} +/** + * 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.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; + +/** + * @author Ceki Gulcu + */ +public class ContextPropertyAction extends Action { + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + addError("The [contextProperty] element has been removed. Please use [substitutionProperty] element instead"); + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ConversionRuleAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ConversionRuleAction.java index f3f2ad2161d9938f6b36da3a0d8518b02a8d617c..7640ed75072e39dd49f1c604ddc4902d5c994ccb 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ConversionRuleAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ConversionRuleAction.java @@ -1,87 +1,87 @@ -/** - * 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.joran.action; - -import java.util.HashMap; -import java.util.Map; - - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.util.OptionHelper; - - - -public class ConversionRuleAction extends Action { - boolean inError = false; - - /** - * Instantiates an layout of the given class and sets its name. - * - */ - @SuppressWarnings("unchecked") - public void begin(InterpretationContext ec, String localName, Attributes attributes) { - // Let us forget about previous errors (in this object) - inError = false; - - String errorMsg; - String conversionWord = - attributes.getValue(ActionConst.CONVERSION_WORD_ATTRIBUTE); - String converterClass = - attributes.getValue(ActionConst.CONVERTER_CLASS_ATTRIBUTE); - - if (OptionHelper.isEmpty(conversionWord)) { - inError = true; - errorMsg = "No 'conversionWord' attribute in "; - addError(errorMsg); - - return; - } - - if (OptionHelper.isEmpty(converterClass)) { - inError = true; - errorMsg = "No 'converterClass' attribute in "; - ec.addError(errorMsg); - - return; - } - - try { - Map ruleRegistry = (Map) context.getObject(CoreConstants.PATTERN_RULE_REGISTRY); - if(ruleRegistry == null) { - ruleRegistry = new HashMap(); - context.putObject(CoreConstants.PATTERN_RULE_REGISTRY, ruleRegistry); - } - // put the new rule into the rule registry - addInfo("registering conversion word "+conversionWord+" with class ["+converterClass+"]"); - ruleRegistry.put(conversionWord, converterClass); - } catch (Exception oops) { - inError = true; - errorMsg = "Could not add conversion rule to PatternLayout."; - addError(errorMsg); - } - } - - /** - * Once the children elements are also parsed, now is the time to activate - * the appender options. - */ - public void end(InterpretationContext ec, String n) { - } - - public void finish(InterpretationContext ec) { - } -} +/** + * 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.joran.action; + +import java.util.HashMap; +import java.util.Map; + + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; + + + +public class ConversionRuleAction extends Action { + boolean inError = false; + + /** + * Instantiates an layout of the given class and sets its name. + * + */ + @SuppressWarnings("unchecked") + public void begin(InterpretationContext ec, String localName, Attributes attributes) { + // Let us forget about previous errors (in this object) + inError = false; + + String errorMsg; + String conversionWord = + attributes.getValue(ActionConst.CONVERSION_WORD_ATTRIBUTE); + String converterClass = + attributes.getValue(ActionConst.CONVERTER_CLASS_ATTRIBUTE); + + if (OptionHelper.isEmpty(conversionWord)) { + inError = true; + errorMsg = "No 'conversionWord' attribute in "; + addError(errorMsg); + + return; + } + + if (OptionHelper.isEmpty(converterClass)) { + inError = true; + errorMsg = "No 'converterClass' attribute in "; + ec.addError(errorMsg); + + return; + } + + try { + Map ruleRegistry = (Map) context.getObject(CoreConstants.PATTERN_RULE_REGISTRY); + if(ruleRegistry == null) { + ruleRegistry = new HashMap(); + context.putObject(CoreConstants.PATTERN_RULE_REGISTRY, ruleRegistry); + } + // put the new rule into the rule registry + addInfo("registering conversion word "+conversionWord+" with class ["+converterClass+"]"); + ruleRegistry.put(conversionWord, converterClass); + } catch (Exception oops) { + inError = true; + errorMsg = "Could not add conversion rule to PatternLayout."; + addError(errorMsg); + } + } + + /** + * Once the children elements are also parsed, now is the time to activate + * the appender options. + */ + public void end(InterpretationContext ec, String n) { + } + + public void finish(InterpretationContext ec) { + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForBasicProperty.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForBasicProperty.java index 193b1b452860fb7a1e81e60f287d97c2cdae057a..ba46eac986477f0fff02264910f40f3f4e19d196 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForBasicProperty.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForBasicProperty.java @@ -1,35 +1,35 @@ -/** - * 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.joran.action; - -import ch.qos.logback.core.joran.spi.PropertySetter; -import ch.qos.logback.core.util.AggregationType; - -/** - * Lump together several fields for use by {@link NestedBasicPropertyIA}. - * - * @author Ceki Gulcu - */ -class IADataForBasicProperty { - final PropertySetter parentBean; - final AggregationType aggregationType; - final String propertyName; - boolean inError; - - IADataForBasicProperty(PropertySetter parentBean, AggregationType aggregationType, String propertyName) { - this.parentBean = parentBean; - this.aggregationType = aggregationType; - this.propertyName = propertyName; - } -} +/** + * 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.joran.action; + +import ch.qos.logback.core.joran.spi.PropertySetter; +import ch.qos.logback.core.util.AggregationType; + +/** + * Lump together several fields for use by {@link NestedBasicPropertyIA}. + * + * @author Ceki Gulcu + */ +class IADataForBasicProperty { + final PropertySetter parentBean; + final AggregationType aggregationType; + final String propertyName; + boolean inError; + + IADataForBasicProperty(PropertySetter parentBean, AggregationType aggregationType, String propertyName) { + this.parentBean = parentBean; + this.aggregationType = aggregationType; + this.propertyName = propertyName; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForComplexProperty.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForComplexProperty.java index 653ff31bfa4028d5b950b9bce67e3729908c591a..e59b277ffd1d67d42a5853ad18911b57b68de6d9 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForComplexProperty.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForComplexProperty.java @@ -1,54 +1,54 @@ -/** - * 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.joran.action; - -import ch.qos.logback.core.joran.spi.PropertySetter; -import ch.qos.logback.core.util.AggregationType; - -/** - * Lump together several fields for use by {@link NestedComplexPropertyIA}. - * - * @author Ceki - */ -public class IADataForComplexProperty { - final PropertySetter parentBean; - final AggregationType aggregationType; - final String complexPropertyName; - private Object nestedComplexProperty; - boolean inError; - - public IADataForComplexProperty(PropertySetter parentBean, AggregationType aggregationType, String complexPropertyName) { - this.parentBean = parentBean; - this.aggregationType = aggregationType; - this.complexPropertyName = complexPropertyName; - } - - public AggregationType getAggregationType() { - return aggregationType; - } - - public Object getNestedComplexProperty() { - return nestedComplexProperty; - } - - public String getComplexPropertyName() { - return complexPropertyName; - } - - public void setNestedComplexProperty(Object nestedComplexProperty) { - this.nestedComplexProperty = nestedComplexProperty; - } - - -} +/** + * 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.joran.action; + +import ch.qos.logback.core.joran.spi.PropertySetter; +import ch.qos.logback.core.util.AggregationType; + +/** + * Lump together several fields for use by {@link NestedComplexPropertyIA}. + * + * @author Ceki + */ +public class IADataForComplexProperty { + final PropertySetter parentBean; + final AggregationType aggregationType; + final String complexPropertyName; + private Object nestedComplexProperty; + boolean inError; + + public IADataForComplexProperty(PropertySetter parentBean, AggregationType aggregationType, String complexPropertyName) { + this.parentBean = parentBean; + this.aggregationType = aggregationType; + this.complexPropertyName = complexPropertyName; + } + + public AggregationType getAggregationType() { + return aggregationType; + } + + public Object getNestedComplexProperty() { + return nestedComplexProperty; + } + + public String getComplexPropertyName() { + return complexPropertyName; + } + + public void setNestedComplexProperty(Object nestedComplexProperty) { + this.nestedComplexProperty = nestedComplexProperty; + } + + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitAction.java index b3f0c61e51d5656221e2ceac7dc7f29c216ac050..37ee11f118e4c212436b5975f678a26770ab09c6 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitAction.java @@ -1,47 +1,47 @@ -/** - * 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.joran.action; - - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.joran.spi.Pattern; - - -/** - * ImplcitActions are like normal (explicit) actions except that are applied - * by the parser when no other pattern applies. Since there can be many implicit - * actions, each action is asked whether it applies in the given context. The - * first implicit action to respond positively is then applied. See also the - * {@link #isApplicable} method. - * - * @author Ceki Gülcü - */ -public abstract class ImplicitAction extends Action { - - /** - * Check whether this implicit action is appropriate in the current context. - * - * @param currentPattern This pattern contains the tag name of the current - * element being parsed at the top of the stack. - * @param attributes The attributes of the current element to process. - * @param ec - * @return Whether the implicit action is applicable in the current context - */ - public abstract boolean isApplicable( - Pattern currentPattern, Attributes attributes, InterpretationContext ec); - - -} +/** + * 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.joran.action; + + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Pattern; + + +/** + * ImplcitActions are like normal (explicit) actions except that are applied + * by the parser when no other pattern applies. Since there can be many implicit + * actions, each action is asked whether it applies in the given context. The + * first implicit action to respond positively is then applied. See also the + * {@link #isApplicable} method. + * + * @author Ceki Gülcü + */ +public abstract class ImplicitAction extends Action { + + /** + * Check whether this implicit action is appropriate in the current context. + * + * @param currentPattern This pattern contains the tag name of the current + * element being parsed at the top of the stack. + * @param attributes The attributes of the current element to process. + * @param ec + * @return Whether the implicit action is applicable in the current context + */ + public abstract boolean isApplicable( + Pattern currentPattern, Attributes attributes, InterpretationContext ec); + + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/IncludeAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/IncludeAction.java index ffd85288295096d3449994eb4f2dfd859279421e..51aa4dff5dac02e4157892383b70f8a102522b6d 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/IncludeAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/IncludeAction.java @@ -1,208 +1,208 @@ -/** - * 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.joran.action; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.List; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.joran.event.SaxEventRecorder; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.util.Loader; -import ch.qos.logback.core.util.OptionHelper; - -public class IncludeAction extends Action { - - private static final String INCLUDED_TAG = "included"; - private static final String FILE_ATTR = "file"; - private static final String URL_ATTR = "url"; - private static final String RESOURCE_ATTR = "resource"; - - private String attributeInUse; - - @Override - public void begin(InterpretationContext ec, String name, Attributes attributes) - throws ActionException { - - SaxEventRecorder recorder = new SaxEventRecorder(); - - this.attributeInUse = null; - - if (!checkAttributes(attributes)) { - return; - } - - InputStream in = getInputStream(ec, attributes); - - try { - if (in != null) { - parseAndRecord(in, recorder); - } - } catch (JoranException e) { - addError("Error while parsing " + attributeInUse, e); - } finally { - close(in); - } - // remove the tag from the beginning and from the end - trimHeadAndTail(recorder); - - ec.getJoranInterpreter().addEventsDynamically(recorder.saxEventList); - } - - void close(InputStream in) { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - } - } - } - - private boolean checkAttributes(Attributes attributes) { - String fileAttribute = attributes.getValue(FILE_ATTR); - String urlAttribute = attributes.getValue(URL_ATTR); - String resourceAttribute = attributes.getValue(RESOURCE_ATTR); - - int count = 0; - - if (!OptionHelper.isEmpty(fileAttribute)) { - count++; - } - if (!OptionHelper.isEmpty(urlAttribute)) { - count++; - } - if (!OptionHelper.isEmpty(resourceAttribute)) { - count++; - } - - if (count == 0) { - addError("One of \"path\", \"resource\" or \"url\" attributes must be set."); - return false; - } else if (count > 1) { - addError("Only one of \"file\", \"url\" or \"resource\" attributes should be set."); - return false; - } else if (count == 1) { - return true; - } - throw new IllegalStateException("Count value [" + count - + "] is not expected"); - } - - private InputStream getInputStreamByFilePath(String pathToFile) { - try { - return new FileInputStream(pathToFile); - } catch (IOException ioe) { - String errMsg = "File [" + pathToFile + "] does not exist."; - addError(errMsg, ioe); - return null; - } - } - - private InputStream getInputStreamByUrl(String urlAttribute) { - URL url; - try { - url = new URL(urlAttribute); - } catch (MalformedURLException mue) { - String errMsg = "URL [" + urlAttribute + "] is not well formed."; - addError(errMsg, mue); - return null; - } - return openURL(url); - } - - InputStream openURL(URL url) { - try { - return url.openStream(); - } catch (IOException e) { - String errMsg = "Failed to open [" + url.toString() + "]"; - addError(errMsg, e); - return null; - } - } - - private InputStream getInputStreamByResource(String resourceAttribute) { - URL url = Loader.getResourceBySelfClassLoader(resourceAttribute); - if (url == null) { - String errMsg = "Could not find resource corresponding to [" - + resourceAttribute + "]"; - addError(errMsg); - return null; - } - return openURL(url); - } - - InputStream getInputStream(InterpretationContext ec, Attributes attributes) { - String fileAttribute = attributes.getValue(FILE_ATTR); - String urlAttribute = attributes.getValue(URL_ATTR); - String resourceAttribute = attributes.getValue(RESOURCE_ATTR); - - if (!OptionHelper.isEmpty(fileAttribute)) { - attributeInUse = ec.subst(fileAttribute); - return getInputStreamByFilePath(attributeInUse); - } - - if (!OptionHelper.isEmpty(urlAttribute)) { - attributeInUse = ec.subst(urlAttribute); - return getInputStreamByUrl(attributeInUse); - } - - if (!OptionHelper.isEmpty(resourceAttribute)) { - attributeInUse = ec.subst(resourceAttribute); - return getInputStreamByResource(attributeInUse); - } - // given previous checkAttributes() check we cannot reach this line - throw new IllegalStateException("A input stream should have been returned"); - } - - private void trimHeadAndTail(SaxEventRecorder recorder) { - // Let's remove the two events before - // adding the events to the player. - - List saxEventList = recorder.saxEventList; - - if (saxEventList.size() == 0) { - return; - } - - SaxEvent first = saxEventList.get(0); - if (first != null && first.qName.equalsIgnoreCase(INCLUDED_TAG)) { - saxEventList.remove(0); - } - - SaxEvent last = saxEventList.get(recorder.saxEventList.size() - 1); - if (last != null && last.qName.equalsIgnoreCase(INCLUDED_TAG)) { - saxEventList.remove(recorder.saxEventList.size() - 1); - } - } - - private void parseAndRecord(InputStream inputSource, SaxEventRecorder recorder) - throws JoranException { - recorder.setContext(context); - recorder.recordEvents(inputSource); - } - - @Override - public void end(InterpretationContext ec, String name) throws ActionException { - // do nothing - } - -} +/** + * 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.joran.action; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.event.SaxEventRecorder; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; + +public class IncludeAction extends Action { + + private static final String INCLUDED_TAG = "included"; + private static final String FILE_ATTR = "file"; + private static final String URL_ATTR = "url"; + private static final String RESOURCE_ATTR = "resource"; + + private String attributeInUse; + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + + SaxEventRecorder recorder = new SaxEventRecorder(); + + this.attributeInUse = null; + + if (!checkAttributes(attributes)) { + return; + } + + InputStream in = getInputStream(ec, attributes); + + try { + if (in != null) { + parseAndRecord(in, recorder); + } + } catch (JoranException e) { + addError("Error while parsing " + attributeInUse, e); + } finally { + close(in); + } + // remove the tag from the beginning and from the end + trimHeadAndTail(recorder); + + ec.getJoranInterpreter().addEventsDynamically(recorder.saxEventList); + } + + void close(InputStream in) { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + } + } + } + + private boolean checkAttributes(Attributes attributes) { + String fileAttribute = attributes.getValue(FILE_ATTR); + String urlAttribute = attributes.getValue(URL_ATTR); + String resourceAttribute = attributes.getValue(RESOURCE_ATTR); + + int count = 0; + + if (!OptionHelper.isEmpty(fileAttribute)) { + count++; + } + if (!OptionHelper.isEmpty(urlAttribute)) { + count++; + } + if (!OptionHelper.isEmpty(resourceAttribute)) { + count++; + } + + if (count == 0) { + addError("One of \"path\", \"resource\" or \"url\" attributes must be set."); + return false; + } else if (count > 1) { + addError("Only one of \"file\", \"url\" or \"resource\" attributes should be set."); + return false; + } else if (count == 1) { + return true; + } + throw new IllegalStateException("Count value [" + count + + "] is not expected"); + } + + private InputStream getInputStreamByFilePath(String pathToFile) { + try { + return new FileInputStream(pathToFile); + } catch (IOException ioe) { + String errMsg = "File [" + pathToFile + "] does not exist."; + addError(errMsg, ioe); + return null; + } + } + + private InputStream getInputStreamByUrl(String urlAttribute) { + URL url; + try { + url = new URL(urlAttribute); + } catch (MalformedURLException mue) { + String errMsg = "URL [" + urlAttribute + "] is not well formed."; + addError(errMsg, mue); + return null; + } + return openURL(url); + } + + InputStream openURL(URL url) { + try { + return url.openStream(); + } catch (IOException e) { + String errMsg = "Failed to open [" + url.toString() + "]"; + addError(errMsg, e); + return null; + } + } + + private InputStream getInputStreamByResource(String resourceAttribute) { + URL url = Loader.getResourceBySelfClassLoader(resourceAttribute); + if (url == null) { + String errMsg = "Could not find resource corresponding to [" + + resourceAttribute + "]"; + addError(errMsg); + return null; + } + return openURL(url); + } + + InputStream getInputStream(InterpretationContext ec, Attributes attributes) { + String fileAttribute = attributes.getValue(FILE_ATTR); + String urlAttribute = attributes.getValue(URL_ATTR); + String resourceAttribute = attributes.getValue(RESOURCE_ATTR); + + if (!OptionHelper.isEmpty(fileAttribute)) { + attributeInUse = ec.subst(fileAttribute); + return getInputStreamByFilePath(attributeInUse); + } + + if (!OptionHelper.isEmpty(urlAttribute)) { + attributeInUse = ec.subst(urlAttribute); + return getInputStreamByUrl(attributeInUse); + } + + if (!OptionHelper.isEmpty(resourceAttribute)) { + attributeInUse = ec.subst(resourceAttribute); + return getInputStreamByResource(attributeInUse); + } + // given previous checkAttributes() check we cannot reach this line + throw new IllegalStateException("A input stream should have been returned"); + } + + private void trimHeadAndTail(SaxEventRecorder recorder) { + // Let's remove the two events before + // adding the events to the player. + + List saxEventList = recorder.saxEventList; + + if (saxEventList.size() == 0) { + return; + } + + SaxEvent first = saxEventList.get(0); + if (first != null && first.qName.equalsIgnoreCase(INCLUDED_TAG)) { + saxEventList.remove(0); + } + + SaxEvent last = saxEventList.get(recorder.saxEventList.size() - 1); + if (last != null && last.qName.equalsIgnoreCase(INCLUDED_TAG)) { + saxEventList.remove(recorder.saxEventList.size() - 1); + } + } + + private void parseAndRecord(InputStream inputSource, SaxEventRecorder recorder) + throws JoranException { + recorder.setContext(context); + recorder.recordEvents(inputSource); + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + // do nothing + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/NOPAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/NOPAction.java index 89155be97425b029e1d96c42e763ed3d766457be..9579cc77231d1e51e8700d81794a3a72911b4c58 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/NOPAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/NOPAction.java @@ -1,37 +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.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.InterpretationContext; - - -/** - * No operation (NOP) action that does strictly nothing. - * Setting a rule to this pattern is sometimes useful in order - * to prevent implicit actions to kick in. - * - * @author Ceki Gülcü - */ -public class NOPAction extends Action { - - public void begin(InterpretationContext ec, String name, Attributes attributes) { - } - - - public void end(InterpretationContext ec, String name) { - } -} +/** + * 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.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; + + +/** + * No operation (NOP) action that does strictly nothing. + * Setting a rule to this pattern is sometimes useful in order + * to prevent implicit actions to kick in. + * + * @author Ceki Gülcü + */ +public class NOPAction extends Action { + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + } + + + public void end(InterpretationContext ec, String name) { + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedBasicPropertyIA.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedBasicPropertyIA.java index 86ed1872df58ee00d03f6535aaaa3d00ee72c532..28e6f1d955e097b1728035c974bcdf46354a149e 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedBasicPropertyIA.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedBasicPropertyIA.java @@ -1,105 +1,105 @@ -/** - * 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.joran.action; - -import java.util.Stack; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.joran.spi.PropertySetter; -import ch.qos.logback.core.util.AggregationType; - -/** - * This action is responsible for tying together a parent object with one of its - * simple properties specified as an element but for which there is - * no explicit rule. - * - * @author Ceki Gülcü - */ -public class NestedBasicPropertyIA extends ImplicitAction { - - - // We use a stack of IADataForBasicProperty objects in order to - // support nested elements which are handled by the same NestedBasicPropertyIA instance. - // We push a IADataForBasicProperty instance in the isApplicable method (if the - // action is applicable) and pop it in the end() method. - // The XML well-formedness property will guarantee that a push will eventually - // be followed by the corresponding pop. - Stack actionDataStack = new Stack(); - - public boolean isApplicable(Pattern pattern, Attributes attributes, - InterpretationContext ec) { - // System.out.println("in NestedSimplePropertyIA.isApplicable [" + pattern + - // "]"); - String nestedElementTagName = pattern.peekLast(); - - // no point in attempting if there is no parent object - if (ec.isEmpty()) { - return false; - } - - Object o = ec.peekObject(); - PropertySetter parentBean = new PropertySetter(o); - parentBean.setContext(context); - - AggregationType aggregationType = parentBean - .computeAggregationType(nestedElementTagName); - - switch (aggregationType) { - case NOT_FOUND: - case AS_COMPLEX_PROPERTY: - case AS_COMPLEX_PROPERTY_COLLECTION: - return false; - - case AS_BASIC_PROPERTY: - case AS_BASIC_PROPERTY_COLLECTION: - IADataForBasicProperty ad = new IADataForBasicProperty(parentBean, - aggregationType, nestedElementTagName); - actionDataStack.push(ad); - // addInfo("NestedSimplePropertyIA deemed applicable [" + pattern + "]"); - return true; - default: - addError("PropertySetter.canContainComponent returned " + aggregationType); - return false; - } - } - - public void begin(InterpretationContext ec, String localName, - Attributes attributes) { - // NOP - } - - public void body(InterpretationContext ec, String body) { - - String finalBody = ec.subst(body); - // System.out.println("body "+body+", finalBody="+finalBody); - // get the action data object pushed in isApplicable() method call - IADataForBasicProperty actionData = (IADataForBasicProperty) actionDataStack.peek(); - switch (actionData.aggregationType) { - case AS_BASIC_PROPERTY: - actionData.parentBean.setProperty(actionData.propertyName, finalBody); - break; - case AS_BASIC_PROPERTY_COLLECTION: - actionData.parentBean - .addBasicProperty(actionData.propertyName, finalBody); - } - } - - public void end(InterpretationContext ec, String tagName) { - // pop the action data object pushed in isApplicable() method call - actionDataStack.pop(); - } -} +/** + * 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.joran.action; + +import java.util.Stack; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.joran.spi.PropertySetter; +import ch.qos.logback.core.util.AggregationType; + +/** + * This action is responsible for tying together a parent object with one of its + * simple properties specified as an element but for which there is + * no explicit rule. + * + * @author Ceki Gülcü + */ +public class NestedBasicPropertyIA extends ImplicitAction { + + + // We use a stack of IADataForBasicProperty objects in order to + // support nested elements which are handled by the same NestedBasicPropertyIA instance. + // We push a IADataForBasicProperty instance in the isApplicable method (if the + // action is applicable) and pop it in the end() method. + // The XML well-formedness property will guarantee that a push will eventually + // be followed by the corresponding pop. + Stack actionDataStack = new Stack(); + + public boolean isApplicable(Pattern pattern, Attributes attributes, + InterpretationContext ec) { + // System.out.println("in NestedSimplePropertyIA.isApplicable [" + pattern + + // "]"); + String nestedElementTagName = pattern.peekLast(); + + // no point in attempting if there is no parent object + if (ec.isEmpty()) { + return false; + } + + Object o = ec.peekObject(); + PropertySetter parentBean = new PropertySetter(o); + parentBean.setContext(context); + + AggregationType aggregationType = parentBean + .computeAggregationType(nestedElementTagName); + + switch (aggregationType) { + case NOT_FOUND: + case AS_COMPLEX_PROPERTY: + case AS_COMPLEX_PROPERTY_COLLECTION: + return false; + + case AS_BASIC_PROPERTY: + case AS_BASIC_PROPERTY_COLLECTION: + IADataForBasicProperty ad = new IADataForBasicProperty(parentBean, + aggregationType, nestedElementTagName); + actionDataStack.push(ad); + // addInfo("NestedSimplePropertyIA deemed applicable [" + pattern + "]"); + return true; + default: + addError("PropertySetter.canContainComponent returned " + aggregationType); + return false; + } + } + + public void begin(InterpretationContext ec, String localName, + Attributes attributes) { + // NOP + } + + public void body(InterpretationContext ec, String body) { + + String finalBody = ec.subst(body); + // System.out.println("body "+body+", finalBody="+finalBody); + // get the action data object pushed in isApplicable() method call + IADataForBasicProperty actionData = (IADataForBasicProperty) actionDataStack.peek(); + switch (actionData.aggregationType) { + case AS_BASIC_PROPERTY: + actionData.parentBean.setProperty(actionData.propertyName, finalBody); + break; + case AS_BASIC_PROPERTY_COLLECTION: + actionData.parentBean + .addBasicProperty(actionData.propertyName, finalBody); + } + } + + public void end(InterpretationContext ec, String tagName) { + // pop the action data object pushed in isApplicable() method call + actionDataStack.pop(); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java index f40a9f6d491bc6739ea5c2aeb0e6aeb8f2339e91..ceb5bbf4d232bf7c3b81e127cf46c4da5bb676bb 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java @@ -1,193 +1,193 @@ -/** - * 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.joran.action; - -import java.util.Stack; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.joran.spi.NoAutoStartUtil; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.joran.spi.PropertySetter; -import ch.qos.logback.core.spi.ContextAware; -import ch.qos.logback.core.spi.LifeCycle; -import ch.qos.logback.core.util.AggregationType; -import ch.qos.logback.core.util.Loader; -import ch.qos.logback.core.util.OptionHelper; - -/** - * This action is responsible for tying together a parent object with a child - * element for which there is no explicit rule. - * - * @author Ceki Gülcü - */ -public class NestedComplexPropertyIA extends ImplicitAction { - - // actionDataStack contains ActionData instances - // We use a stack of ActionData objects in order to support nested - // elements which are handled by the same NestedComplexPropertyIA instance. - // We push a ActionData instance in the isApplicable method (if the - // action is applicable) and pop it in the end() method. - // The XML well-formedness property will guarantee that a push will eventually - // be followed by a corresponding pop. - Stack actionDataStack = new Stack(); - - public boolean isApplicable(Pattern pattern, Attributes attributes, - InterpretationContext ic) { - - String nestedElementTagName = pattern.peekLast(); - - // calling ic.peekObject with an empty stack will throw an exception - if (ic.isEmpty()) { - return false; - } - - Object o = ic.peekObject(); - PropertySetter parentBean = new PropertySetter(o); - parentBean.setContext(context); - - AggregationType aggregationType = parentBean - .computeAggregationType(nestedElementTagName); - - switch (aggregationType) { - case NOT_FOUND: - case AS_BASIC_PROPERTY: - case AS_BASIC_PROPERTY_COLLECTION: - return false; - - // we only push action data if NestComponentIA is applicable - case AS_COMPLEX_PROPERTY_COLLECTION: - case AS_COMPLEX_PROPERTY: - IADataForComplexProperty ad = new IADataForComplexProperty(parentBean, - aggregationType, nestedElementTagName); - actionDataStack.push(ad); - - return true; - default: - addError("PropertySetter.computeAggregationType returned " - + aggregationType); - return false; - } - } - - public void begin(InterpretationContext ec, String localName, - Attributes attributes) { - // LogLog.debug("in NestComponentIA begin method"); - // get the action data object pushed in isApplicable() method call - IADataForComplexProperty actionData = (IADataForComplexProperty) actionDataStack - .peek(); - - String className = attributes.getValue(CLASS_ATTRIBUTE); - // perform variable name substitution - className = ec.subst(className); - - Class componentClass = null; - try { - - if (!OptionHelper.isEmpty(className)) { - componentClass = Loader.loadClass(className, context); - } else { - // guess class name via implicit rules - PropertySetter parentBean = actionData.parentBean; - componentClass = parentBean.getClassNameViaImplicitRules(actionData - .getComplexPropertyName(), actionData.getAggregationType(), ec - .getDefaultNestedComponentRegistry()); - } - - if (componentClass == null) { - actionData.inError = true; - String errMsg = "Could not find an appropriate class for property [" - + localName + "]"; - addError(errMsg); - return; - } - - if (OptionHelper.isEmpty(className)) { - addInfo("Assuming default type [" + componentClass.getName() - + "] for [" + localName + "] property"); - } - - actionData.setNestedComplexProperty(componentClass.newInstance()); - - // pass along the repository - if (actionData.getNestedComplexProperty() instanceof ContextAware) { - ((ContextAware) actionData.getNestedComplexProperty()) - .setContext(this.context); - } - // getLogger().debug( - addInfo("Pushing component [" + localName - + "] on top of the object stack."); - ec.pushObject(actionData.getNestedComplexProperty()); - - } catch (Exception oops) { - actionData.inError = true; - String msg = "Could not create component [" + localName + "] of type [" - + className + "]"; - addError(msg, oops); - } - - } - - public void end(InterpretationContext ec, String tagName) { - - // pop the action data object pushed in isApplicable() method call - // we assume that each this begin - IADataForComplexProperty actionData = (IADataForComplexProperty) actionDataStack - .pop(); - - if (actionData.inError) { - return; - } - - PropertySetter nestedBean = new PropertySetter(actionData - .getNestedComplexProperty()); - nestedBean.setContext(context); - - // have the nested element point to its parent if possible - if (nestedBean.computeAggregationType("parent") == AggregationType.AS_COMPLEX_PROPERTY) { - nestedBean.setComplexProperty("parent", actionData.parentBean.getObj()); - } - - // start the nested complex property if it implements LifeCycle and is not - // marked with a @NoAutoStart annotation - Object nestedComplexProperty = actionData.getNestedComplexProperty(); - if (nestedComplexProperty instanceof LifeCycle - && NoAutoStartUtil.notMarkedWithNoAutoStart(nestedComplexProperty)) { - ((LifeCycle) nestedComplexProperty).start(); - } - - Object o = ec.peekObject(); - - if (o != actionData.getNestedComplexProperty()) { - addError("The object on the top the of the stack is not the component pushed earlier."); - } else { - ec.popObject(); - // Now let us attach the component - switch (actionData.aggregationType) { - case AS_COMPLEX_PROPERTY: - actionData.parentBean.setComplexProperty(tagName, actionData - .getNestedComplexProperty()); - - break; - case AS_COMPLEX_PROPERTY_COLLECTION: - actionData.parentBean.addComplexProperty(tagName, actionData - .getNestedComplexProperty()); - - break; - } - } - } - -} +/** + * 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.joran.action; + +import java.util.Stack; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.NoAutoStartUtil; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.joran.spi.PropertySetter; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.util.AggregationType; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; + +/** + * This action is responsible for tying together a parent object with a child + * element for which there is no explicit rule. + * + * @author Ceki Gülcü + */ +public class NestedComplexPropertyIA extends ImplicitAction { + + // actionDataStack contains ActionData instances + // We use a stack of ActionData objects in order to support nested + // elements which are handled by the same NestedComplexPropertyIA instance. + // We push a ActionData instance in the isApplicable method (if the + // action is applicable) and pop it in the end() method. + // The XML well-formedness property will guarantee that a push will eventually + // be followed by a corresponding pop. + Stack actionDataStack = new Stack(); + + public boolean isApplicable(Pattern pattern, Attributes attributes, + InterpretationContext ic) { + + String nestedElementTagName = pattern.peekLast(); + + // calling ic.peekObject with an empty stack will throw an exception + if (ic.isEmpty()) { + return false; + } + + Object o = ic.peekObject(); + PropertySetter parentBean = new PropertySetter(o); + parentBean.setContext(context); + + AggregationType aggregationType = parentBean + .computeAggregationType(nestedElementTagName); + + switch (aggregationType) { + case NOT_FOUND: + case AS_BASIC_PROPERTY: + case AS_BASIC_PROPERTY_COLLECTION: + return false; + + // we only push action data if NestComponentIA is applicable + case AS_COMPLEX_PROPERTY_COLLECTION: + case AS_COMPLEX_PROPERTY: + IADataForComplexProperty ad = new IADataForComplexProperty(parentBean, + aggregationType, nestedElementTagName); + actionDataStack.push(ad); + + return true; + default: + addError("PropertySetter.computeAggregationType returned " + + aggregationType); + return false; + } + } + + public void begin(InterpretationContext ec, String localName, + Attributes attributes) { + // LogLog.debug("in NestComponentIA begin method"); + // get the action data object pushed in isApplicable() method call + IADataForComplexProperty actionData = (IADataForComplexProperty) actionDataStack + .peek(); + + String className = attributes.getValue(CLASS_ATTRIBUTE); + // perform variable name substitution + className = ec.subst(className); + + Class componentClass = null; + try { + + if (!OptionHelper.isEmpty(className)) { + componentClass = Loader.loadClass(className, context); + } else { + // guess class name via implicit rules + PropertySetter parentBean = actionData.parentBean; + componentClass = parentBean.getClassNameViaImplicitRules(actionData + .getComplexPropertyName(), actionData.getAggregationType(), ec + .getDefaultNestedComponentRegistry()); + } + + if (componentClass == null) { + actionData.inError = true; + String errMsg = "Could not find an appropriate class for property [" + + localName + "]"; + addError(errMsg); + return; + } + + if (OptionHelper.isEmpty(className)) { + addInfo("Assuming default type [" + componentClass.getName() + + "] for [" + localName + "] property"); + } + + actionData.setNestedComplexProperty(componentClass.newInstance()); + + // pass along the repository + if (actionData.getNestedComplexProperty() instanceof ContextAware) { + ((ContextAware) actionData.getNestedComplexProperty()) + .setContext(this.context); + } + // getLogger().debug( + addInfo("Pushing component [" + localName + + "] on top of the object stack."); + ec.pushObject(actionData.getNestedComplexProperty()); + + } catch (Exception oops) { + actionData.inError = true; + String msg = "Could not create component [" + localName + "] of type [" + + className + "]"; + addError(msg, oops); + } + + } + + public void end(InterpretationContext ec, String tagName) { + + // pop the action data object pushed in isApplicable() method call + // we assume that each this begin + IADataForComplexProperty actionData = (IADataForComplexProperty) actionDataStack + .pop(); + + if (actionData.inError) { + return; + } + + PropertySetter nestedBean = new PropertySetter(actionData + .getNestedComplexProperty()); + nestedBean.setContext(context); + + // have the nested element point to its parent if possible + if (nestedBean.computeAggregationType("parent") == AggregationType.AS_COMPLEX_PROPERTY) { + nestedBean.setComplexProperty("parent", actionData.parentBean.getObj()); + } + + // start the nested complex property if it implements LifeCycle and is not + // marked with a @NoAutoStart annotation + Object nestedComplexProperty = actionData.getNestedComplexProperty(); + if (nestedComplexProperty instanceof LifeCycle + && NoAutoStartUtil.notMarkedWithNoAutoStart(nestedComplexProperty)) { + ((LifeCycle) nestedComplexProperty).start(); + } + + Object o = ec.peekObject(); + + if (o != actionData.getNestedComplexProperty()) { + addError("The object on the top the of the stack is not the component pushed earlier."); + } else { + ec.popObject(); + // Now let us attach the component + switch (actionData.aggregationType) { + case AS_COMPLEX_PROPERTY: + actionData.parentBean.setComplexProperty(tagName, actionData + .getNestedComplexProperty()); + + break; + case AS_COMPLEX_PROPERTY_COLLECTION: + actionData.parentBean.addComplexProperty(tagName, actionData + .getNestedComplexProperty()); + + break; + } + } + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/NewRuleAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/NewRuleAction.java index 19c599dd3e3134d0398f6436d774cd6eebda8316..e5be37477731d4eccaa8bd7ac13d86ba8c133d48 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/NewRuleAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/NewRuleAction.java @@ -1,72 +1,72 @@ -/** - * 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.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.util.OptionHelper; - - -public class NewRuleAction extends Action { - boolean inError = false; - - /** - * Instantiates an layout of the given class and sets its name. - */ - public void begin(InterpretationContext ec, String localName, Attributes attributes) { - // Let us forget about previous errors (in this object) - inError = false; - String errorMsg; - String pattern = attributes.getValue(Action.PATTERN_ATTRIBUTE); - String actionClass = attributes.getValue(Action.ACTION_CLASS_ATTRIBUTE); - - if (OptionHelper.isEmpty(pattern)) { - inError = true; - errorMsg = "No 'pattern' attribute in "; - addError(errorMsg); - return; - } - - if (OptionHelper.isEmpty(actionClass)) { - inError = true; - errorMsg = "No 'actionClass' attribute in "; - addError(errorMsg); - return; - } - - try { - addInfo("About to add new Joran parsing rule [" + pattern + "," - + actionClass + "]."); - ec.getJoranInterpreter().getRuleStore().addRule(new Pattern(pattern), - actionClass); - } catch (Exception oops) { - inError = true; - errorMsg = "Could not add new Joran parsing rule [" + pattern + "," - + actionClass + "]"; - addError(errorMsg); - } - } - - /** - * Once the children elements are also parsed, now is the time to activate the - * appender options. - */ - public void end(InterpretationContext ec, String n) { - } - - public void finish(InterpretationContext ec) { - } -} +/** + * 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.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.util.OptionHelper; + + +public class NewRuleAction extends Action { + boolean inError = false; + + /** + * Instantiates an layout of the given class and sets its name. + */ + public void begin(InterpretationContext ec, String localName, Attributes attributes) { + // Let us forget about previous errors (in this object) + inError = false; + String errorMsg; + String pattern = attributes.getValue(Action.PATTERN_ATTRIBUTE); + String actionClass = attributes.getValue(Action.ACTION_CLASS_ATTRIBUTE); + + if (OptionHelper.isEmpty(pattern)) { + inError = true; + errorMsg = "No 'pattern' attribute in "; + addError(errorMsg); + return; + } + + if (OptionHelper.isEmpty(actionClass)) { + inError = true; + errorMsg = "No 'actionClass' attribute in "; + addError(errorMsg); + return; + } + + try { + addInfo("About to add new Joran parsing rule [" + pattern + "," + + actionClass + "]."); + ec.getJoranInterpreter().getRuleStore().addRule(new Pattern(pattern), + actionClass); + } catch (Exception oops) { + inError = true; + errorMsg = "Could not add new Joran parsing rule [" + pattern + "," + + actionClass + "]"; + addError(errorMsg); + } + } + + /** + * Once the children elements are also parsed, now is the time to activate the + * appender options. + */ + public void end(InterpretationContext ec, String n) { + } + + public void finish(InterpretationContext ec) { + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ParamAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ParamAction.java index 9d65b25a83c5a678564de2caba9b526fbdc2846b..af33532df9a4d59b020e1fc3df44a5d8391b6963 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ParamAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ParamAction.java @@ -1,67 +1,67 @@ -/** - * 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.joran.action; - - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.joran.spi.PropertySetter; - - - -public class ParamAction extends Action { - static String NO_NAME = "No name attribute in element"; - static String NO_VALUE = "No name attribute in element"; - boolean inError = false; - - public void begin( - InterpretationContext ec, String localName, Attributes attributes) { - String name = attributes.getValue(NAME_ATTRIBUTE); - String value = attributes.getValue(VALUE_ATTRIBUTE); - - if (name == null) { - inError = true; - addError(NO_NAME); - return; - } - - if (value == null) { - inError = true; - addError(NO_VALUE); - return; - } - - // remove both leading and trailing spaces - value = value.trim(); - - Object o = ec.peekObject(); - PropertySetter propSetter = new PropertySetter(o); - propSetter.setContext(context); - value = ec.subst(value); - - // allow for variable substitution for name as well - name = ec.subst(name); - - //getLogger().debug( - // "In ParamAction setting parameter [{}] to value [{}].", name, value); - propSetter.setProperty(name, value); - } - - public void end(InterpretationContext ec, String localName) { - } - - public void finish(InterpretationContext ec) { - } -} +/** + * 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.joran.action; + + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.PropertySetter; + + + +public class ParamAction extends Action { + static String NO_NAME = "No name attribute in element"; + static String NO_VALUE = "No name attribute in element"; + boolean inError = false; + + public void begin( + InterpretationContext ec, String localName, Attributes attributes) { + String name = attributes.getValue(NAME_ATTRIBUTE); + String value = attributes.getValue(VALUE_ATTRIBUTE); + + if (name == null) { + inError = true; + addError(NO_NAME); + return; + } + + if (value == null) { + inError = true; + addError(NO_VALUE); + return; + } + + // remove both leading and trailing spaces + value = value.trim(); + + Object o = ec.peekObject(); + PropertySetter propSetter = new PropertySetter(o); + propSetter.setContext(context); + value = ec.subst(value); + + // allow for variable substitution for name as well + name = ec.subst(name); + + //getLogger().debug( + // "In ParamAction setting parameter [{}] to value [{}].", name, value); + propSetter.setProperty(name, value); + } + + public void end(InterpretationContext ec, String localName) { + } + + public void finish(InterpretationContext ec) { + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java index 93374b77756a2c0217f4ff08f9a4733e24e22973..b6f9a39440edbe1b3f62da8a51e3244d30c45a80 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java @@ -1,154 +1,154 @@ -/** - * 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.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.pattern.util.RegularEscapeUtil; -import ch.qos.logback.core.util.Loader; -import ch.qos.logback.core.util.OptionHelper; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; - -import java.util.Properties; - -/** - * This class serves as a base for other actions, which similar to the ANT - * task which add/set properties of a given object. - * - * This action sets new substitution properties in the logging context by name, - * value pair, or adds all the properties passed in "file" or "resource" - * attribute. - * - * @author Ceki Gülcü - */ -public class PropertyAction extends Action { - - static final String RESOURCE_ATTRIBUTE = "resource"; - - static String INVALID_ATTRIBUTES = "In element, either the \"file\" attribute alone, or " - + "the \"resource\" element alone, or both the \"name\" and \"value\" attributes must be set."; - - /** - * Add all the properties found in the argument named 'props' to an - * InterpretationContext. - */ - public void setProperties(InterpretationContext ec, Properties props) { - ec.addSubstitutionProperties(props); - } - - public void setProperty(InterpretationContext ec, String key, String value) { - ec.addSubstitutionProperty(key, value); - } - - /** - * Set a new property for the execution context by name, value pair, or adds - * all the properties found in the given file. - * - */ - public void begin(InterpretationContext ec, String localName, - Attributes attributes) { - - if ("substitutionProperty".equals(localName)) { - addWarn("[substitutionProperty] element has been deprecated. Plase use the [property] element instead."); - } - - String name = attributes.getValue(NAME_ATTRIBUTE); - String value = attributes.getValue(VALUE_ATTRIBUTE); - - if (checkFileAttributeSanity(attributes)) { - String file = attributes.getValue(FILE_ATTRIBUTE); - file = ec.subst(file); - try { - FileInputStream istream = new FileInputStream(file); - loadAndSetProperties(ec, istream); - } catch (IOException e) { - addError("Could not read properties file [" + file + "].", e); - } - } else if (checkResourceAttributeSanity(attributes)) { - String resource = attributes.getValue(RESOURCE_ATTRIBUTE); - resource = ec.subst(resource); - URL resourceURL = Loader.getResourceBySelfClassLoader(resource); - if (resourceURL == null) { - addError("Could not find resource [" + resource + "]."); - } else { - try { - InputStream istream = resourceURL.openStream(); - loadAndSetProperties(ec, istream); - } catch (IOException e) { - addError("Could not read resource file [" + resource + "].", e); - } - } - } else if (checkValueNameAttributesSanity(attributes)) { - value = RegularEscapeUtil.basicEscape(value); - // now remove both leading and trailing spaces - value = value.trim(); - value = ec.subst(value); - setProperty(ec, name, value); - - } else { - addError(INVALID_ATTRIBUTES); - } - } - - void loadAndSetProperties(InterpretationContext ec, InputStream istream) - throws IOException { - Properties props = new Properties(); - props.load(istream); - istream.close(); - setProperties(ec, props); - } - - boolean checkFileAttributeSanity(Attributes attributes) { - String file = attributes.getValue(FILE_ATTRIBUTE); - String name = attributes.getValue(NAME_ATTRIBUTE); - String value = attributes.getValue(VALUE_ATTRIBUTE); - String resource = attributes.getValue(RESOURCE_ATTRIBUTE); - - return !(OptionHelper.isEmpty(file)) - && (OptionHelper.isEmpty(name) && OptionHelper.isEmpty(value) && OptionHelper - .isEmpty(resource)); - } - - boolean checkResourceAttributeSanity(Attributes attributes) { - String file = attributes.getValue(FILE_ATTRIBUTE); - String name = attributes.getValue(NAME_ATTRIBUTE); - String value = attributes.getValue(VALUE_ATTRIBUTE); - String resource = attributes.getValue(RESOURCE_ATTRIBUTE); - - return !(OptionHelper.isEmpty(resource)) - && (OptionHelper.isEmpty(name) && OptionHelper.isEmpty(value) && OptionHelper - .isEmpty(file)); - } - - boolean checkValueNameAttributesSanity(Attributes attributes) { - String file = attributes.getValue(FILE_ATTRIBUTE); - String name = attributes.getValue(NAME_ATTRIBUTE); - String value = attributes.getValue(VALUE_ATTRIBUTE); - String resource = attributes.getValue(RESOURCE_ATTRIBUTE); - - return (!(OptionHelper.isEmpty(name) || OptionHelper.isEmpty(value)) && (OptionHelper - .isEmpty(file) && OptionHelper.isEmpty(resource))); - } - - public void end(InterpretationContext ec, String name) { - } - - public void finish(InterpretationContext ec) { - } -} +/** + * 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.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.pattern.util.RegularEscapeUtil; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import java.util.Properties; + +/** + * This class serves as a base for other actions, which similar to the ANT + * task which add/set properties of a given object. + * + * This action sets new substitution properties in the logging context by name, + * value pair, or adds all the properties passed in "file" or "resource" + * attribute. + * + * @author Ceki Gülcü + */ +public class PropertyAction extends Action { + + static final String RESOURCE_ATTRIBUTE = "resource"; + + static String INVALID_ATTRIBUTES = "In element, either the \"file\" attribute alone, or " + + "the \"resource\" element alone, or both the \"name\" and \"value\" attributes must be set."; + + /** + * Add all the properties found in the argument named 'props' to an + * InterpretationContext. + */ + public void setProperties(InterpretationContext ec, Properties props) { + ec.addSubstitutionProperties(props); + } + + public void setProperty(InterpretationContext ec, String key, String value) { + ec.addSubstitutionProperty(key, value); + } + + /** + * Set a new property for the execution context by name, value pair, or adds + * all the properties found in the given file. + * + */ + public void begin(InterpretationContext ec, String localName, + Attributes attributes) { + + if ("substitutionProperty".equals(localName)) { + addWarn("[substitutionProperty] element has been deprecated. Plase use the [property] element instead."); + } + + String name = attributes.getValue(NAME_ATTRIBUTE); + String value = attributes.getValue(VALUE_ATTRIBUTE); + + if (checkFileAttributeSanity(attributes)) { + String file = attributes.getValue(FILE_ATTRIBUTE); + file = ec.subst(file); + try { + FileInputStream istream = new FileInputStream(file); + loadAndSetProperties(ec, istream); + } catch (IOException e) { + addError("Could not read properties file [" + file + "].", e); + } + } else if (checkResourceAttributeSanity(attributes)) { + String resource = attributes.getValue(RESOURCE_ATTRIBUTE); + resource = ec.subst(resource); + URL resourceURL = Loader.getResourceBySelfClassLoader(resource); + if (resourceURL == null) { + addError("Could not find resource [" + resource + "]."); + } else { + try { + InputStream istream = resourceURL.openStream(); + loadAndSetProperties(ec, istream); + } catch (IOException e) { + addError("Could not read resource file [" + resource + "].", e); + } + } + } else if (checkValueNameAttributesSanity(attributes)) { + value = RegularEscapeUtil.basicEscape(value); + // now remove both leading and trailing spaces + value = value.trim(); + value = ec.subst(value); + setProperty(ec, name, value); + + } else { + addError(INVALID_ATTRIBUTES); + } + } + + void loadAndSetProperties(InterpretationContext ec, InputStream istream) + throws IOException { + Properties props = new Properties(); + props.load(istream); + istream.close(); + setProperties(ec, props); + } + + boolean checkFileAttributeSanity(Attributes attributes) { + String file = attributes.getValue(FILE_ATTRIBUTE); + String name = attributes.getValue(NAME_ATTRIBUTE); + String value = attributes.getValue(VALUE_ATTRIBUTE); + String resource = attributes.getValue(RESOURCE_ATTRIBUTE); + + return !(OptionHelper.isEmpty(file)) + && (OptionHelper.isEmpty(name) && OptionHelper.isEmpty(value) && OptionHelper + .isEmpty(resource)); + } + + boolean checkResourceAttributeSanity(Attributes attributes) { + String file = attributes.getValue(FILE_ATTRIBUTE); + String name = attributes.getValue(NAME_ATTRIBUTE); + String value = attributes.getValue(VALUE_ATTRIBUTE); + String resource = attributes.getValue(RESOURCE_ATTRIBUTE); + + return !(OptionHelper.isEmpty(resource)) + && (OptionHelper.isEmpty(name) && OptionHelper.isEmpty(value) && OptionHelper + .isEmpty(file)); + } + + boolean checkValueNameAttributesSanity(Attributes attributes) { + String file = attributes.getValue(FILE_ATTRIBUTE); + String name = attributes.getValue(NAME_ATTRIBUTE); + String value = attributes.getValue(VALUE_ATTRIBUTE); + String resource = attributes.getValue(RESOURCE_ATTRIBUTE); + + return (!(OptionHelper.isEmpty(name) || OptionHelper.isEmpty(value)) && (OptionHelper + .isEmpty(file) && OptionHelper.isEmpty(resource))); + } + + public void end(InterpretationContext ec, String name) { + } + + public void finish(InterpretationContext ec) { + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/StatusListenerAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/StatusListenerAction.java index 5b87fab269617bd4d5a44fe688eed54fcafbe37f..7e06e343281587ebc231dc75c0a6e80c1aa7e321 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/StatusListenerAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/StatusListenerAction.java @@ -1,74 +1,74 @@ -/** - * 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.joran.action; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.spi.LifeCycle; -import ch.qos.logback.core.status.StatusListener; -import ch.qos.logback.core.util.OptionHelper; - - -public class StatusListenerAction extends Action { - - - boolean inError = false; - StatusListener statusListener = null; - - public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException { - inError = false; - String className = attributes.getValue(CLASS_ATTRIBUTE); - if(OptionHelper.isEmpty(className)) { - addError( - "Missing class name for statusListener. Near [" - + name + "] line " + getLineNumber(ec)); - inError = true; - return; - } - - try { - statusListener = (StatusListener) OptionHelper.instantiateByClassName( - className, StatusListener.class, context); - ec.getContext().getStatusManager().add(statusListener); - ec.pushObject(statusListener); - } catch (Exception e) { - inError = true; - addError( - "Could not create an StatusListener of type ["+className+"].", e); - throw new ActionException(e); - } - - } - - public void finish(InterpretationContext ec) { - } - - public void end(InterpretationContext ec, String e) { - if (inError) { - return; - } - if (statusListener instanceof LifeCycle) { - ((LifeCycle) statusListener).start(); - } - Object o = ec.peekObject(); - if (o != statusListener) { - addWarn( - "The object at the of the stack is not the statusListener pushed earlier."); - } else { - ec.popObject(); - } - } -} +/** + * 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.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.util.OptionHelper; + + +public class StatusListenerAction extends Action { + + + boolean inError = false; + StatusListener statusListener = null; + + public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException { + inError = false; + String className = attributes.getValue(CLASS_ATTRIBUTE); + if(OptionHelper.isEmpty(className)) { + addError( + "Missing class name for statusListener. Near [" + + name + "] line " + getLineNumber(ec)); + inError = true; + return; + } + + try { + statusListener = (StatusListener) OptionHelper.instantiateByClassName( + className, StatusListener.class, context); + ec.getContext().getStatusManager().add(statusListener); + ec.pushObject(statusListener); + } catch (Exception e) { + inError = true; + addError( + "Could not create an StatusListener of type ["+className+"].", e); + throw new ActionException(e); + } + + } + + public void finish(InterpretationContext ec) { + } + + public void end(InterpretationContext ec, String e) { + if (inError) { + return; + } + if (statusListener instanceof LifeCycle) { + ((LifeCycle) statusListener).start(); + } + Object o = ec.peekObject(); + if (o != statusListener) { + addWarn( + "The object at the of the stack is not the statusListener pushed earlier."); + } else { + ec.popObject(); + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/TimestampAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/TimestampAction.java index 1829677eca031093726f8da580bff65782333304..6c1ad3ab3483001b7a78748919fbff53fe98e616 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/TimestampAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/TimestampAction.java @@ -1,68 +1,68 @@ -/** - * 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.joran.action; - -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.util.OptionHelper; - -/** - * Given a key and a date-and-time pattern, puts a property to the context, with - * the specified key and value equal to the current time in the format - * corresponding to the specified date-and-time pattern. - * - * @author Ceki Gülcü - * - */ -public class TimestampAction extends Action { - static String DATE_PATTERN_ATTRIBUTE = "datePattern"; - - boolean inError = false; - - @Override - public void begin(InterpretationContext ec, String name, Attributes attributes) - throws ActionException { - String keyStr = attributes.getValue(KEY_ATTRIBUTE); - if (OptionHelper.isEmpty(keyStr)) { - addError("Attrubute named [" + KEY_ATTRIBUTE + "] cannot be empty"); - inError = true; - } - String datePatternStr = attributes.getValue(DATE_PATTERN_ATTRIBUTE); - if (OptionHelper.isEmpty(datePatternStr)) { - addError("Attribute named [" + DATE_PATTERN_ATTRIBUTE - + "] cannot be empty"); - inError = true; - } - - if (inError) - return; - - SimpleDateFormat sdf = new SimpleDateFormat(datePatternStr); - String val = sdf.format(new Date()); - - addInfo("Adding property to the context with key=\"" + keyStr - + "\" and value=\"" + val + "\" to the context"); - context.putProperty(keyStr, val); - } - - @Override - public void end(InterpretationContext ec, String name) throws ActionException { - } - -} +/** + * 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.joran.action; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; + +/** + * Given a key and a date-and-time pattern, puts a property to the context, with + * the specified key and value equal to the current time in the format + * corresponding to the specified date-and-time pattern. + * + * @author Ceki Gülcü + * + */ +public class TimestampAction extends Action { + static String DATE_PATTERN_ATTRIBUTE = "datePattern"; + + boolean inError = false; + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + String keyStr = attributes.getValue(KEY_ATTRIBUTE); + if (OptionHelper.isEmpty(keyStr)) { + addError("Attrubute named [" + KEY_ATTRIBUTE + "] cannot be empty"); + inError = true; + } + String datePatternStr = attributes.getValue(DATE_PATTERN_ATTRIBUTE); + if (OptionHelper.isEmpty(datePatternStr)) { + addError("Attribute named [" + DATE_PATTERN_ATTRIBUTE + + "] cannot be empty"); + inError = true; + } + + if (inError) + return; + + SimpleDateFormat sdf = new SimpleDateFormat(datePatternStr); + String val = sdf.format(new Date()); + + addInfo("Adding property to the context with key=\"" + keyStr + + "\" and value=\"" + val + "\" to the context"); + context.putProperty(keyStr, val); + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/event/BodyEvent.java b/logback-core/src/main/java/ch/qos/logback/core/joran/event/BodyEvent.java index d58a6419a597ead3296ea8174f7830c03070d5de..1ab4f17b17249107ff5e664e7a98e69b91feb28c 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/event/BodyEvent.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/event/BodyEvent.java @@ -1,42 +1,42 @@ -/** - * 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.joran.event; - -import org.xml.sax.Locator; - - -public class BodyEvent extends SaxEvent { - - private String text; - - BodyEvent(String text, Locator locator) { - super(null, null, null, locator); - this.text = text; - } - - public String getText() { - return text; - } - - @Override - public String toString() { - return "BodyEvent(" + getText() + ")" + locator.getLineNumber() + "," - + locator.getColumnNumber(); - } - - public void append(String str) { - text += str; - } - -} +/** + * 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.joran.event; + +import org.xml.sax.Locator; + + +public class BodyEvent extends SaxEvent { + + private String text; + + BodyEvent(String text, Locator locator) { + super(null, null, null, locator); + this.text = text; + } + + public String getText() { + return text; + } + + @Override + public String toString() { + return "BodyEvent(" + getText() + ")" + locator.getLineNumber() + "," + + locator.getColumnNumber(); + } + + public void append(String str) { + text += str; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/event/EndEvent.java b/logback-core/src/main/java/ch/qos/logback/core/joran/event/EndEvent.java index bea1986d1ad4007c6060fa9f3073888b39638c41..0163d6f698c294fafc7c935f31aa777d010b2189 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/event/EndEvent.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/event/EndEvent.java @@ -1,31 +1,31 @@ -/** - * 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.joran.event; - -import org.xml.sax.Locator; - - -public class EndEvent extends SaxEvent { - - EndEvent(String namespaceURI, String localName, String qName, Locator locator) { - super(namespaceURI, localName, qName, locator); - } - - @Override - public String toString() { - return " EndEvent("+getQName()+") ["+locator.getLineNumber()+","+locator.getColumnNumber()+"]"; - } - - -} +/** + * 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.joran.event; + +import org.xml.sax.Locator; + + +public class EndEvent extends SaxEvent { + + EndEvent(String namespaceURI, String localName, String qName, Locator locator) { + super(namespaceURI, localName, qName, locator); + } + + @Override + public String toString() { + return " EndEvent("+getQName()+") ["+locator.getLineNumber()+","+locator.getColumnNumber()+"]"; + } + + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/event/InPlayListener.java b/logback-core/src/main/java/ch/qos/logback/core/joran/event/InPlayListener.java index 69218993dbedf80e0e2a755740289220db866e29..25a04e1f416f1acb79e8204a30e2aaadea682e58 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/event/InPlayListener.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/event/InPlayListener.java @@ -1,19 +1,19 @@ -/** - * 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.joran.event; - - -public interface InPlayListener { - public void inPlay(SaxEvent event); -} +/** + * 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.joran.event; + + +public interface InPlayListener { + public void inPlay(SaxEvent event); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/event/SaxEvent.java b/logback-core/src/main/java/ch/qos/logback/core/joran/event/SaxEvent.java index 90d30fd013f6ed86c0d589fbe4f66bf498954643..92886da97e7e9b827e148064cf0e20106b13d745 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/event/SaxEvent.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/event/SaxEvent.java @@ -1,49 +1,49 @@ -/** - * 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.joran.event; - -import org.xml.sax.Locator; -import org.xml.sax.helpers.LocatorImpl; - -public class SaxEvent { - - final public String namespaceURI; - final public String localName; - final public String qName; - final public Locator locator; - - SaxEvent(String namespaceURI, String localName, String qName, Locator locator) { - this.namespaceURI = namespaceURI; - this.localName = localName; - this.qName = qName; - // locator impl is used to take a snapshot! - this.locator = new LocatorImpl(locator); - } - - public String getLocalName() { - return localName; - } - - public Locator getLocator() { - return locator; - } - - public String getNamespaceURI() { - return namespaceURI; - } - - public String getQName() { - return qName; - } -} +/** + * 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.joran.event; + +import org.xml.sax.Locator; +import org.xml.sax.helpers.LocatorImpl; + +public class SaxEvent { + + final public String namespaceURI; + final public String localName; + final public String qName; + final public Locator locator; + + SaxEvent(String namespaceURI, String localName, String qName, Locator locator) { + this.namespaceURI = namespaceURI; + this.localName = localName; + this.qName = qName; + // locator impl is used to take a snapshot! + this.locator = new LocatorImpl(locator); + } + + public String getLocalName() { + return localName; + } + + public Locator getLocator() { + return locator; + } + + public String getNamespaceURI() { + return namespaceURI; + } + + public String getQName() { + return qName; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/event/SaxEventRecorder.java b/logback-core/src/main/java/ch/qos/logback/core/joran/event/SaxEventRecorder.java index 17bca1e80b69c93a5fea28ab75d0f9e34f31700e..9afddd095c6234bddf5e9b942e1d0bf07ab34914 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/event/SaxEventRecorder.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/event/SaxEventRecorder.java @@ -1,208 +1,208 @@ -/** - * 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.joran.event; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.DefaultHandler; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.spi.ContextAware; -import ch.qos.logback.core.spi.ContextAwareImpl; -import ch.qos.logback.core.status.Status; - -public class SaxEventRecorder extends DefaultHandler implements ContextAware { - - - final ContextAwareImpl cai; - - public SaxEventRecorder() { - cai = new ContextAwareImpl(this); - } - public List saxEventList = new ArrayList(); - Locator locator; - Pattern globalPattern = new Pattern(); - - - final public void recordEvents(InputStream inputStream) throws JoranException { - recordEvents(new InputSource(inputStream)); - } - - public List recordEvents(InputSource inputSource) - throws JoranException { - SAXParser saxParser = null; - try { - SAXParserFactory spf = SAXParserFactory.newInstance(); - spf.setValidating(false); - spf.setNamespaceAware(true); - saxParser = spf.newSAXParser(); - } catch (Exception pce) { - String errMsg = "Parser configuration error occured"; - addError(errMsg, pce); - throw new JoranException(errMsg, pce); - } - - try { - saxParser.parse(inputSource, this); - return saxEventList; - - } catch (IOException ie) { - String errMsg = "I/O error occurred while parsing xml file"; - addError(errMsg, ie); - throw new JoranException(errMsg, ie); - } catch (Exception ex) { - String errMsg = "Problem parsing XML document. See previously reported errors. Abandoning all further processing."; - addError(errMsg, ex); - throw new JoranException(errMsg, ex); - } - - } - - public void startDocument() { - } - - public Locator getLocator() { - return locator; - } - - public void setDocumentLocator(Locator l) { - locator = l; - } - - public void startElement(String namespaceURI, String localName, String qName, - Attributes atts) { - - String tagName = getTagName(localName, qName); - globalPattern.push(tagName); - Pattern current = (Pattern) globalPattern.clone(); - saxEventList.add(new StartEvent(current, namespaceURI, localName, qName, - atts, getLocator())); - } - - public void characters(char[] ch, int start, int length) { - - String body = new String(ch, start, length); - if (body == null) { - return; - } - - // if the body string is null - if (body != null) { - String bodyTrimmed = body.trim(); - if (bodyTrimmed.length() == 0) { - return; - } - } - - SaxEvent lastEvent = getLastEvent(); - if (lastEvent instanceof BodyEvent) { - BodyEvent be = (BodyEvent) lastEvent; - be.append(body); - } else { - saxEventList.add(new BodyEvent(body, getLocator())); - } - - } - - SaxEvent getLastEvent() { - if (saxEventList.isEmpty()) { - return null; - } - int size = saxEventList.size(); - return saxEventList.get(size - 1); - } - - public void endElement(String namespaceURI, String localName, String qName) { - saxEventList - .add(new EndEvent(namespaceURI, localName, qName, getLocator())); - globalPattern.pop(); - } - - String getTagName(String localName, String qName) { - String tagName = localName; - if ((tagName == null) || (tagName.length() < 1)) { - tagName = qName; - } - return tagName; - } - - public void error(SAXParseException spe) throws SAXException { - addError("Parsing error on line " + spe.getLineNumber() + " and column " - + spe.getColumnNumber(), spe); - } - - public void fatalError(SAXParseException spe) throws SAXException { - addError("Parsing fatal error on line " + spe.getLineNumber() + " and column " - + spe.getColumnNumber(), spe); - } - - public void warning(SAXParseException spe) throws SAXException { - addWarn("Parsing warning on line " + spe.getLineNumber() + " and column " - + spe.getColumnNumber(), spe); - } - - public void addError(String msg) { - cai.addError(msg); - } - - public void addError(String msg, Throwable ex) { - cai.addError(msg, ex); - } - - public void addInfo(String msg) { - cai.addInfo(msg); - } - - public void addInfo(String msg, Throwable ex) { - cai.addInfo(msg, ex); - } - - public void addStatus(Status status) { - cai.addStatus(status); - } - - public void addWarn(String msg) { - cai.addWarn(msg); - } - - public void addWarn(String msg, Throwable ex) { - cai.addWarn(msg, ex); - } - - public Context getContext() { - return cai.getContext(); - } - - public void setContext(Context context) { - cai.setContext(context); - } - - public List getSaxEventList() { - return saxEventList; - } - -} +/** + * 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.joran.event; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.ContextAwareImpl; +import ch.qos.logback.core.status.Status; + +public class SaxEventRecorder extends DefaultHandler implements ContextAware { + + + final ContextAwareImpl cai; + + public SaxEventRecorder() { + cai = new ContextAwareImpl(this); + } + public List saxEventList = new ArrayList(); + Locator locator; + Pattern globalPattern = new Pattern(); + + + final public void recordEvents(InputStream inputStream) throws JoranException { + recordEvents(new InputSource(inputStream)); + } + + public List recordEvents(InputSource inputSource) + throws JoranException { + SAXParser saxParser = null; + try { + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setValidating(false); + spf.setNamespaceAware(true); + saxParser = spf.newSAXParser(); + } catch (Exception pce) { + String errMsg = "Parser configuration error occured"; + addError(errMsg, pce); + throw new JoranException(errMsg, pce); + } + + try { + saxParser.parse(inputSource, this); + return saxEventList; + + } catch (IOException ie) { + String errMsg = "I/O error occurred while parsing xml file"; + addError(errMsg, ie); + throw new JoranException(errMsg, ie); + } catch (Exception ex) { + String errMsg = "Problem parsing XML document. See previously reported errors. Abandoning all further processing."; + addError(errMsg, ex); + throw new JoranException(errMsg, ex); + } + + } + + public void startDocument() { + } + + public Locator getLocator() { + return locator; + } + + public void setDocumentLocator(Locator l) { + locator = l; + } + + public void startElement(String namespaceURI, String localName, String qName, + Attributes atts) { + + String tagName = getTagName(localName, qName); + globalPattern.push(tagName); + Pattern current = (Pattern) globalPattern.clone(); + saxEventList.add(new StartEvent(current, namespaceURI, localName, qName, + atts, getLocator())); + } + + public void characters(char[] ch, int start, int length) { + + String body = new String(ch, start, length); + if (body == null) { + return; + } + + // if the body string is null + if (body != null) { + String bodyTrimmed = body.trim(); + if (bodyTrimmed.length() == 0) { + return; + } + } + + SaxEvent lastEvent = getLastEvent(); + if (lastEvent instanceof BodyEvent) { + BodyEvent be = (BodyEvent) lastEvent; + be.append(body); + } else { + saxEventList.add(new BodyEvent(body, getLocator())); + } + + } + + SaxEvent getLastEvent() { + if (saxEventList.isEmpty()) { + return null; + } + int size = saxEventList.size(); + return saxEventList.get(size - 1); + } + + public void endElement(String namespaceURI, String localName, String qName) { + saxEventList + .add(new EndEvent(namespaceURI, localName, qName, getLocator())); + globalPattern.pop(); + } + + String getTagName(String localName, String qName) { + String tagName = localName; + if ((tagName == null) || (tagName.length() < 1)) { + tagName = qName; + } + return tagName; + } + + public void error(SAXParseException spe) throws SAXException { + addError("Parsing error on line " + spe.getLineNumber() + " and column " + + spe.getColumnNumber(), spe); + } + + public void fatalError(SAXParseException spe) throws SAXException { + addError("Parsing fatal error on line " + spe.getLineNumber() + " and column " + + spe.getColumnNumber(), spe); + } + + public void warning(SAXParseException spe) throws SAXException { + addWarn("Parsing warning on line " + spe.getLineNumber() + " and column " + + spe.getColumnNumber(), spe); + } + + public void addError(String msg) { + cai.addError(msg); + } + + public void addError(String msg, Throwable ex) { + cai.addError(msg, ex); + } + + public void addInfo(String msg) { + cai.addInfo(msg); + } + + public void addInfo(String msg, Throwable ex) { + cai.addInfo(msg, ex); + } + + public void addStatus(Status status) { + cai.addStatus(status); + } + + public void addWarn(String msg) { + cai.addWarn(msg); + } + + public void addWarn(String msg, Throwable ex) { + cai.addWarn(msg, ex); + } + + public Context getContext() { + return cai.getContext(); + } + + public void setContext(Context context) { + cai.setContext(context); + } + + public List getSaxEventList() { + return saxEventList; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/event/StartEvent.java b/logback-core/src/main/java/ch/qos/logback/core/joran/event/StartEvent.java index b68e95c3a64f5617579dbdb4beb60ec2317496e6..32d0a4dbe659ad3ac7be498e482cefd5d2082483 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/event/StartEvent.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/event/StartEvent.java @@ -1,45 +1,45 @@ -/** - * 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.joran.event; - -import org.xml.sax.Attributes; -import org.xml.sax.Locator; -import org.xml.sax.helpers.AttributesImpl; - -import ch.qos.logback.core.joran.spi.Pattern; - -public class StartEvent extends SaxEvent { - - final public Attributes attributes; - final public Pattern pattern; - - StartEvent(Pattern pattern, String namespaceURI, String localName, String qName, - Attributes attributes, Locator locator) { - super(namespaceURI, localName, qName, locator); - // locator impl is used to take a snapshot! - this.attributes = new AttributesImpl(attributes); - this.pattern = pattern; - } - - public Attributes getAttributes() { - return attributes; - } - - - @Override - public String toString() { - return "StartEvent("+getQName()+") ["+locator.getLineNumber()+","+locator.getColumnNumber()+"]"; - } - -} +/** + * 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.joran.event; + +import org.xml.sax.Attributes; +import org.xml.sax.Locator; +import org.xml.sax.helpers.AttributesImpl; + +import ch.qos.logback.core.joran.spi.Pattern; + +public class StartEvent extends SaxEvent { + + final public Attributes attributes; + final public Pattern pattern; + + StartEvent(Pattern pattern, String namespaceURI, String localName, String qName, + Attributes attributes, Locator locator) { + super(namespaceURI, localName, qName, locator); + // locator impl is used to take a snapshot! + this.attributes = new AttributesImpl(attributes); + this.pattern = pattern; + } + + public Attributes getAttributes() { + return attributes; + } + + + @Override + public String toString() { + return "StartEvent("+getQName()+") ["+locator.getLineNumber()+","+locator.getColumnNumber()+"]"; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/package.html b/logback-core/src/main/java/ch/qos/logback/core/joran/package.html index 93578185093ec98b865766ceeed823425b4b1c0b..26491f9d7921f30b14a1e22a0fa9f49389a7978f 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains Joran configuration classes.

- - + + + + + + + + + +

Contains Joran configuration classes.

+ + \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ActionException.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ActionException.java index 02cd351999cb30e6507104ba426b1f1ab706f2e6..80a7fac02f31e1eab3110a2a22f2ed18e526ffdb 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ActionException.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ActionException.java @@ -1,36 +1,36 @@ -/** - * 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.joran.spi; - - -/** - * By throwing an exception an action can signal the Interpreter to skip - * processing of all the nested (child) elements of the element associated with - * the action causing the exception. - * - * @author Ceki Gulcu - */ -public class ActionException extends Exception { - - - private static final long serialVersionUID = 2743349809995319806L; - - public ActionException() { - } - - public ActionException(final Throwable rootCause) { - super(rootCause); - } - -} +/** + * 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.joran.spi; + + +/** + * By throwing an exception an action can signal the Interpreter to skip + * processing of all the nested (child) elements of the element associated with + * the action causing the exception. + * + * @author Ceki Gulcu + */ +public class ActionException extends Exception { + + + private static final long serialVersionUID = 2743349809995319806L; + + public ActionException() { + } + + public ActionException(final Throwable rootCause) { + super(rootCause); + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/DefaultClass.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/DefaultClass.java index e7e5f71fd8825fbb7522e60caa013a988f7aa18a..c37dc46ef34f34f32a14c0e47717f2b44ad5419e 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/DefaultClass.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/DefaultClass.java @@ -1,25 +1,25 @@ -/** - * 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.joran.spi; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface DefaultClass { - Class value(); -} +/** + * 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.joran.spi; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface DefaultClass { + Class value(); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/DefaultNestedComponentRegistry.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/DefaultNestedComponentRegistry.java index f579a5b7650448c13a65f5066cd64accb6a06738..7b1985eb4b23003ca420db80aa0ef3e7216222e4 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/DefaultNestedComponentRegistry.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/DefaultNestedComponentRegistry.java @@ -1,53 +1,53 @@ -/** - * 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.joran.spi; - -import java.util.HashMap; -import java.util.Map; - -/** - * A registry which maps a property in a host class to a default class. - * - * @author Cek Gülcü - * - */ -public class DefaultNestedComponentRegistry { - - Map defaultComponentMap = new HashMap(); - - public void add(Class hostClass, String propertyName, Class componentClass) { - HostClassAndPropertyDouble hpDouble = new HostClassAndPropertyDouble( - hostClass, propertyName.toLowerCase()); - defaultComponentMap.put(hpDouble, componentClass); - } - - public Class findDefaultComponentType(Class hostClass, String propertyName) { - propertyName = propertyName.toLowerCase(); - while (hostClass != null) { - Class componentClass = oneShotFind(hostClass, propertyName); - if (componentClass != null) { - return componentClass; - } - hostClass = hostClass.getSuperclass(); - } - return null; - } - - private Class oneShotFind(Class hostClass, String propertyName) { - HostClassAndPropertyDouble hpDouble = new HostClassAndPropertyDouble( - hostClass, propertyName); - return defaultComponentMap.get(hpDouble); - } - -} +/** + * 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.joran.spi; + +import java.util.HashMap; +import java.util.Map; + +/** + * A registry which maps a property in a host class to a default class. + * + * @author Cek Gülcü + * + */ +public class DefaultNestedComponentRegistry { + + Map defaultComponentMap = new HashMap(); + + public void add(Class hostClass, String propertyName, Class componentClass) { + HostClassAndPropertyDouble hpDouble = new HostClassAndPropertyDouble( + hostClass, propertyName.toLowerCase()); + defaultComponentMap.put(hpDouble, componentClass); + } + + public Class findDefaultComponentType(Class hostClass, String propertyName) { + propertyName = propertyName.toLowerCase(); + while (hostClass != null) { + Class componentClass = oneShotFind(hostClass, propertyName); + if (componentClass != null) { + return componentClass; + } + hostClass = hostClass.getSuperclass(); + } + return null; + } + + private Class oneShotFind(Class hostClass, String propertyName) { + HostClassAndPropertyDouble hpDouble = new HostClassAndPropertyDouble( + hostClass, propertyName); + return defaultComponentMap.get(hpDouble); + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/EventPlayer.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/EventPlayer.java index 10ab04b029a442986b9d85e24d8d457b92a56979..7f383f6b59a45883492e26a2db62fa37f2086d3f 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/EventPlayer.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/EventPlayer.java @@ -1,61 +1,61 @@ -/** - * 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.joran.spi; - -import java.util.List; - -import ch.qos.logback.core.joran.event.BodyEvent; -import ch.qos.logback.core.joran.event.EndEvent; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.joran.event.StartEvent; - -public class EventPlayer { - - final Interpreter interpreter; - List eventList; - int currentIndex; - - public EventPlayer(Interpreter interpreter) { - this.interpreter = interpreter; - } - - public void play(List seList) { - eventList = seList; - SaxEvent se; - for(currentIndex = 0; currentIndex < eventList.size(); currentIndex++) { - se = eventList.get(currentIndex); - - if(se instanceof StartEvent) { - interpreter.startElement((StartEvent) se); - // invoke fireInPlay after startElement processing - interpreter.getInterpretationContext().fireInPlay(se); - } - if(se instanceof BodyEvent) { - // invoke fireInPlay before characters processing - interpreter.getInterpretationContext().fireInPlay(se); - interpreter.characters((BodyEvent) se); - } - if(se instanceof EndEvent) { - // invoke fireInPlay before endElement processing - interpreter.getInterpretationContext().fireInPlay(se); - interpreter.endElement((EndEvent) se); - } - - } - } - - public void addEventsDynamically(List eventList) { - this.eventList.addAll(currentIndex+2, eventList); - } -} +/** + * 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.joran.spi; + +import java.util.List; + +import ch.qos.logback.core.joran.event.BodyEvent; +import ch.qos.logback.core.joran.event.EndEvent; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.event.StartEvent; + +public class EventPlayer { + + final Interpreter interpreter; + List eventList; + int currentIndex; + + public EventPlayer(Interpreter interpreter) { + this.interpreter = interpreter; + } + + public void play(List seList) { + eventList = seList; + SaxEvent se; + for(currentIndex = 0; currentIndex < eventList.size(); currentIndex++) { + se = eventList.get(currentIndex); + + if(se instanceof StartEvent) { + interpreter.startElement((StartEvent) se); + // invoke fireInPlay after startElement processing + interpreter.getInterpretationContext().fireInPlay(se); + } + if(se instanceof BodyEvent) { + // invoke fireInPlay before characters processing + interpreter.getInterpretationContext().fireInPlay(se); + interpreter.characters((BodyEvent) se); + } + if(se instanceof EndEvent) { + // invoke fireInPlay before endElement processing + interpreter.getInterpretationContext().fireInPlay(se); + interpreter.endElement((EndEvent) se); + } + + } + } + + public void addEventsDynamically(List eventList) { + this.eventList.addAll(currentIndex+2, eventList); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/HostClassAndPropertyDouble.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/HostClassAndPropertyDouble.java index d5d0170bc8a6075f2a2b3d4ed18153bcde224dfd..4f1e4d0489b39c46fcc8e8112c0f6c1c4c442887 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/HostClassAndPropertyDouble.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/HostClassAndPropertyDouble.java @@ -1,76 +1,76 @@ -/** - * 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.joran.spi; - -/** - * A 2-tuple (a double) consisting of a Class and a String. The Class references - * the hosting class of a component and the String represents the property name - * under which a nested component is referenced the host. - * - * This class is used by {@link DefaultNestedComponentRegistry}. - * - * @author Ceki Gulcu - * - */ -public class HostClassAndPropertyDouble { - - final Class hostClass; - final String propertyName; - - public HostClassAndPropertyDouble(Class hostClass, String propertyName) { - this.hostClass = hostClass; - this.propertyName = propertyName; - } - - public Class getHostClass() { - return hostClass; - } - - public String getPropertyName() { - return propertyName; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((hostClass == null) ? 0 : hostClass.hashCode()); - result = prime * result - + ((propertyName == null) ? 0 : propertyName.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final HostClassAndPropertyDouble other = (HostClassAndPropertyDouble) obj; - if (hostClass == null) { - if (other.hostClass != null) - return false; - } else if (!hostClass.equals(other.hostClass)) - return false; - if (propertyName == null) { - if (other.propertyName != null) - return false; - } else if (!propertyName.equals(other.propertyName)) - return false; - return true; - } - -} +/** + * 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.joran.spi; + +/** + * A 2-tuple (a double) consisting of a Class and a String. The Class references + * the hosting class of a component and the String represents the property name + * under which a nested component is referenced the host. + * + * This class is used by {@link DefaultNestedComponentRegistry}. + * + * @author Ceki Gulcu + * + */ +public class HostClassAndPropertyDouble { + + final Class hostClass; + final String propertyName; + + public HostClassAndPropertyDouble(Class hostClass, String propertyName) { + this.hostClass = hostClass; + this.propertyName = propertyName; + } + + public Class getHostClass() { + return hostClass; + } + + public String getPropertyName() { + return propertyName; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((hostClass == null) ? 0 : hostClass.hashCode()); + result = prime * result + + ((propertyName == null) ? 0 : propertyName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final HostClassAndPropertyDouble other = (HostClassAndPropertyDouble) obj; + if (hostClass == null) { + if (other.hostClass != null) + return false; + } else if (!hostClass.equals(other.hostClass)) + return false; + if (propertyName == null) { + if (other.propertyName != null) + return false; + } else if (!propertyName.equals(other.propertyName)) + return false; + return true; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/InterpretationContext.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/InterpretationContext.java index 3987fc3916b56ef4698de5a71e5da679438d9fce..ccdc9a3634e812cd58cd1621077e1a9e35b22c7c 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/InterpretationContext.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/InterpretationContext.java @@ -1,193 +1,193 @@ -/** - * 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.joran.spi; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Stack; - -import org.xml.sax.Locator; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.event.InPlayListener; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.spi.PropertyContainer; -import ch.qos.logback.core.util.OptionHelper; - -/** - * - * An InterpretationContext contains the contextual state of a Joran parsing - * session. {@link Action} objects depend on this context to exchange and store - * information. - * - * @author Ceki Gülcü - */ -public class InterpretationContext extends ContextAwareBase implements - PropertyContainer { - Stack objectStack; - Map objectMap; - Map propertiesMap; - - Interpreter joranInterpreter; - final List listenerList = new ArrayList(); - DefaultNestedComponentRegistry defaultNestedComponentRegistry = new DefaultNestedComponentRegistry(); - - public InterpretationContext(Context context, Interpreter joranInterpreter) { - this.context = context; - this.joranInterpreter = joranInterpreter; - objectStack = new Stack(); - objectMap = new HashMap(5); - propertiesMap = new HashMap(5); - } - - - public DefaultNestedComponentRegistry getDefaultNestedComponentRegistry() { - return defaultNestedComponentRegistry; - } - - void setPropertiesMap(Map propertiesMap) { - this.propertiesMap = propertiesMap; - } - - String updateLocationInfo(String msg) { - Locator locator = joranInterpreter.getLocator(); - - if (locator != null) { - return msg + locator.getLineNumber() + ":" + locator.getColumnNumber(); - } else { - return msg; - } - } - - public Locator getLocator() { - return joranInterpreter.getLocator(); - } - - public Interpreter getJoranInterpreter() { - return joranInterpreter; - } - - public Stack getObjectStack() { - return objectStack; - } - - public boolean isEmpty() { - return objectStack.isEmpty(); - } - - public Object peekObject() { - return objectStack.peek(); - } - - public void pushObject(Object o) { - objectStack.push(o); - } - - public Object popObject() { - return objectStack.pop(); - } - - public Object getObject(int i) { - return objectStack.get(i); - } - - public Map getObjectMap() { - return objectMap; - } - - /** - * Add a property to the properties of this execution context. If the property - * exists already, it is overwritten. - */ - public void addSubstitutionProperty(String key, String value) { - if (key == null || value == null) { - return; - } - // if (substitutionProperties.contains(key)) { - // LogLog.warn( - // "key [" + key - // + "] already contained in the EC properties. Overwriting."); - // } - - // values with leading or trailing spaces are bad. We remove them now. - value = value.trim(); - context.putProperty(key, value); - } - - public void addSubstitutionProperties(Properties props) { - if (props == null) { - return; - } - Iterator i = props.keySet().iterator(); - while (i.hasNext()) { - String key = (String) i.next(); - addSubstitutionProperty(key, props.getProperty(key)); - } - } - - public void addSubstitutionProperties(Map propertyMap) { - if (propertyMap == null) { - return; - } - Iterator i = propertyMap.keySet().iterator(); - while (i.hasNext()) { - String key = (String) i.next(); - addSubstitutionProperty(key, propertyMap.get(key)); - } - } - - /** - * If a key is found in propertiesMap then return it. Otherwise, delegate to - * the context. - */ - public String getProperty(String key) { - String v = propertiesMap.get(key); - if (v != null) { - return v; - } else { - return context.getProperty(key); - } - } - - public String subst(String value) { - if (value == null) { - return null; - } - return OptionHelper.substVars(value, this); - } - - public void addInPlayListener(InPlayListener ipl) { - if (listenerList.contains(ipl)) { - addWarn("InPlayListener " + ipl + " has been already registered"); - } else { - listenerList.add(ipl); - } - } - - public boolean removeInPlayListener(InPlayListener ipl) { - return listenerList.remove(ipl); - } - - void fireInPlay(SaxEvent event) { - for (InPlayListener ipl : listenerList) { - ipl.inPlay(event); - } - } -} +/** + * 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.joran.spi; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Stack; + +import org.xml.sax.Locator; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.event.InPlayListener; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.PropertyContainer; +import ch.qos.logback.core.util.OptionHelper; + +/** + * + * An InterpretationContext contains the contextual state of a Joran parsing + * session. {@link Action} objects depend on this context to exchange and store + * information. + * + * @author Ceki Gülcü + */ +public class InterpretationContext extends ContextAwareBase implements + PropertyContainer { + Stack objectStack; + Map objectMap; + Map propertiesMap; + + Interpreter joranInterpreter; + final List listenerList = new ArrayList(); + DefaultNestedComponentRegistry defaultNestedComponentRegistry = new DefaultNestedComponentRegistry(); + + public InterpretationContext(Context context, Interpreter joranInterpreter) { + this.context = context; + this.joranInterpreter = joranInterpreter; + objectStack = new Stack(); + objectMap = new HashMap(5); + propertiesMap = new HashMap(5); + } + + + public DefaultNestedComponentRegistry getDefaultNestedComponentRegistry() { + return defaultNestedComponentRegistry; + } + + void setPropertiesMap(Map propertiesMap) { + this.propertiesMap = propertiesMap; + } + + String updateLocationInfo(String msg) { + Locator locator = joranInterpreter.getLocator(); + + if (locator != null) { + return msg + locator.getLineNumber() + ":" + locator.getColumnNumber(); + } else { + return msg; + } + } + + public Locator getLocator() { + return joranInterpreter.getLocator(); + } + + public Interpreter getJoranInterpreter() { + return joranInterpreter; + } + + public Stack getObjectStack() { + return objectStack; + } + + public boolean isEmpty() { + return objectStack.isEmpty(); + } + + public Object peekObject() { + return objectStack.peek(); + } + + public void pushObject(Object o) { + objectStack.push(o); + } + + public Object popObject() { + return objectStack.pop(); + } + + public Object getObject(int i) { + return objectStack.get(i); + } + + public Map getObjectMap() { + return objectMap; + } + + /** + * Add a property to the properties of this execution context. If the property + * exists already, it is overwritten. + */ + public void addSubstitutionProperty(String key, String value) { + if (key == null || value == null) { + return; + } + // if (substitutionProperties.contains(key)) { + // LogLog.warn( + // "key [" + key + // + "] already contained in the EC properties. Overwriting."); + // } + + // values with leading or trailing spaces are bad. We remove them now. + value = value.trim(); + context.putProperty(key, value); + } + + public void addSubstitutionProperties(Properties props) { + if (props == null) { + return; + } + Iterator i = props.keySet().iterator(); + while (i.hasNext()) { + String key = (String) i.next(); + addSubstitutionProperty(key, props.getProperty(key)); + } + } + + public void addSubstitutionProperties(Map propertyMap) { + if (propertyMap == null) { + return; + } + Iterator i = propertyMap.keySet().iterator(); + while (i.hasNext()) { + String key = (String) i.next(); + addSubstitutionProperty(key, propertyMap.get(key)); + } + } + + /** + * If a key is found in propertiesMap then return it. Otherwise, delegate to + * the context. + */ + public String getProperty(String key) { + String v = propertiesMap.get(key); + if (v != null) { + return v; + } else { + return context.getProperty(key); + } + } + + public String subst(String value) { + if (value == null) { + return null; + } + return OptionHelper.substVars(value, this); + } + + public void addInPlayListener(InPlayListener ipl) { + if (listenerList.contains(ipl)) { + addWarn("InPlayListener " + ipl + " has been already registered"); + } else { + listenerList.add(ipl); + } + } + + public boolean removeInPlayListener(InPlayListener ipl) { + return listenerList.remove(ipl); + } + + void fireInPlay(SaxEvent event) { + for (InPlayListener ipl : listenerList) { + ipl.inPlay(event); + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Interpreter.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Interpreter.java index 7e28c6f4abc13820018da2b77d5f8122b706900a..696ada9f47cd19c6e4ce80f09a85876c676d0971 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Interpreter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Interpreter.java @@ -1,362 +1,362 @@ -/** - * 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.joran.spi; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Stack; -import java.util.Vector; - -import org.xml.sax.Attributes; -import org.xml.sax.Locator; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.action.ImplicitAction; -import ch.qos.logback.core.joran.event.BodyEvent; -import ch.qos.logback.core.joran.event.EndEvent; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.joran.event.StartEvent; -import ch.qos.logback.core.spi.ContextAwareImpl; - -/** - * Interpreter is Joran's main driving class. It extends SAX - * {@link org.xml.sax.helpers.DefaultHandler DefaultHandler} which invokes - * various {@link Action actions} according to predefined patterns. - * - *

- * Patterns are kept in a {@link RuleStore} which is programmed to store and - * then later produce the applicable actions for a given pattern. - * - *

- * The pattern corresponding to a top level <a> element is the string - * "a". - * - *

- * The pattern corresponding to an element <b> embedded within a top level - * <a> element is the string "a/b". - * - *

- * The pattern corresponding to an <b> and any level of nesting is - * "*/b. Thus, the * character placed at the beginning of a pattern - * serves as a wildcard for the level of nesting. - * - * Conceptually, this is very similar to the API of commons-digester. Joran - * offers several small advantages. First and foremost, it offers support for - * implicit actions which result in a significant leap in flexibility. Second, - * in our opinion better error reporting capability. Third, it is self-reliant. - * It does not depend on other APIs, in particular commons-logging which is too - * unreliable. Last but not least, Joran is quite tiny and is expected to remain - * so. - * - * @author Ceki Gülcuü - * - */ -public class Interpreter { - private static List EMPTY_LIST = new Vector(0); - - final private RuleStore ruleStore; - final private InterpretationContext interpretationContext; - final private ArrayList implicitActions; - final private CAI_WithLocatorSupport cai; - Pattern pattern; - Locator locator; - EventPlayer player; - - /** - * The actionListStack contains a list of actions that are executing - * for the given XML element. - * - * A list of actions is pushed by the {link #startElement} and popped by - * {@link #endElement}. - * - */ - Stack actionListStack; - - /** - * If the skip nested is set, then we skip all its nested elements until it is - * set back to null at when the element's end is reached. - */ - Pattern skip = null; - - public Interpreter(Context context, RuleStore rs, Pattern initialPattern) { - this.cai = new CAI_WithLocatorSupport(this); - this.cai.setContext(context); - ruleStore = rs; - interpretationContext = new InterpretationContext(context, this); - implicitActions = new ArrayList(3); - this.pattern = initialPattern; - actionListStack = new Stack(); - player = new EventPlayer(this); - } - - public void setInterpretationContextPropertiesMap(Map propertiesMap) { - interpretationContext.setPropertiesMap(propertiesMap); - } - /** - * @deprecated replaced by {@link #getInterpretationContext()} - */ - public InterpretationContext getExecutionContext() { - return getInterpretationContext(); - } - - public InterpretationContext getInterpretationContext() { - return interpretationContext; - } - - public void startDocument() { - } - - public void startElement(StartEvent se) { - setDocumentLocator(se.getLocator()); - startElement(se.namespaceURI, se.localName, se.qName, se.attributes); - } - - private void startElement(String namespaceURI, String localName, - String qName, Attributes atts) { - - String tagName = getTagName(localName, qName); - pattern.push(tagName); - - if (skip != null) { - // every startElement pushes an action list - pushEmptyActionList(); - return; - } - - List applicableActionList = getApplicableActionList(pattern, atts); - if (applicableActionList != null) { - actionListStack.add(applicableActionList); - callBeginAction(applicableActionList, tagName, atts); - } else { - // every startElement pushes an action list - pushEmptyActionList(); - String errMsg = "no applicable action for [" + tagName - + "], current pattern is [" + pattern + "]"; - cai.addError(errMsg); - } - } - - /** - * This method is used to - */ - private void pushEmptyActionList() { - actionListStack.add(EMPTY_LIST); - } - - public void characters(BodyEvent be) { - - setDocumentLocator(be.locator); - - String body = be.getText(); - List applicableActionList = (List) actionListStack.peek(); - - if (body != null) { - body = body.trim(); - } - if (body.length() > 0) { - // System.out.println("calling body method with ["+body+ "]"); - callBodyAction(applicableActionList, body); - } - } - - public void endElement(EndEvent endEvent) { - setDocumentLocator(endEvent.locator); - endElement(endEvent.namespaceURI, endEvent.localName, endEvent.qName); - } - - private void endElement(String namespaceURI, String localName, String qName) { - // given that an action list is always pushed for every startElement, we need - // to always pop for every endElement - List applicableActionList = (List) actionListStack.pop(); - - if (skip != null) { - if (skip.equals(pattern)) { - skip = null; - } - } else if (applicableActionList != EMPTY_LIST) { - callEndAction(applicableActionList, getTagName(localName, qName)); - } - - // given that we always push, we must also pop the pattern - pattern.pop(); - } - - public Locator getLocator() { - return locator; - } - - public void setDocumentLocator(Locator l) { - locator = l; - } - - String getTagName(String localName, String qName) { - String tagName = localName; - - if ((tagName == null) || (tagName.length() < 1)) { - tagName = qName; - } - - return tagName; - } - - public void addImplicitAction(ImplicitAction ia) { - implicitActions.add(ia); - } - - /** - * Check if any implicit actions are applicable. As soon as an applicable - * action is found, it is returned. Thus, the returned list will have at most - * one element. - */ - List lookupImplicitAction(Pattern pattern, Attributes attributes, - InterpretationContext ec) { - int len = implicitActions.size(); - - for (int i = 0; i < len; i++) { - ImplicitAction ia = (ImplicitAction) implicitActions.get(i); - - if (ia.isApplicable(pattern, attributes, ec)) { - List actionList = new ArrayList(1); - actionList.add(ia); - - return actionList; - } - } - - return null; - } - - /** - * Return the list of applicable patterns for this - */ - List getApplicableActionList(Pattern pattern, Attributes attributes) { - List applicableActionList = ruleStore.matchActions(pattern); - - // logger.debug("set of applicable patterns: " + applicableActionList); - if (applicableActionList == null) { - applicableActionList = lookupImplicitAction(pattern, attributes, interpretationContext); - } - - return applicableActionList; - } - - void callBeginAction(List applicableActionList, String tagName, - Attributes atts) { - if (applicableActionList == null) { - return; - } - - Iterator i = applicableActionList.iterator(); - while (i.hasNext()) { - Action action = (Action) i.next(); - // now let us invoke the action. We catch and report any eventual - // exceptions - try { - action.begin(interpretationContext, tagName, atts); - } catch (ActionException e) { - skip = (Pattern) pattern.clone(); - cai.addError("ActionException in Action for tag [" + tagName + "]", e); - } catch (RuntimeException e) { - skip = (Pattern) pattern.clone(); - cai.addError("RuntimeException in Action for tag [" + tagName + "]", e); - } - } - } - - private void callBodyAction(List applicableActionList, String body) { - if (applicableActionList == null) { - return; - } - Iterator i = applicableActionList.iterator(); - - while (i.hasNext()) { - Action action = (Action) i.next(); - try { - action.body(interpretationContext, body); - } catch (ActionException ae) { - cai - .addError("Exception in end() methd for action [" + action + "]", - ae); - } - } - } - - private void callEndAction(List applicableActionList, String tagName) { - if (applicableActionList == null) { - return; - } - - // logger.debug("About to call end actions on node: [" + localName + "]"); - Iterator i = applicableActionList.iterator(); - - while (i.hasNext()) { - Action action = (Action) i.next(); - // now let us invoke the end method of the action. We catch and report - // any eventual exceptions - try { - action.end(interpretationContext, tagName); - } catch (ActionException ae) { - // at this point endAction, there is no point in skipping children as - // they have been already processed - cai.addError("ActionException in Action for tag [" + tagName + "]", ae); - } catch (RuntimeException e) { - // no point in setting skip - cai.addError("RuntimeException in Action for tag [" + tagName + "]", e); - } - } - } - - public RuleStore getRuleStore() { - return ruleStore; - } - - public void play(List eventList) { - player.play(eventList); - } - - public void addEventsDynamically(List eventList) { - if (player != null) { - player.addEventsDynamically(eventList); - } - } -} - -/** - * When {@link Interpreter} class is used as the origin of an - * {@link ContextAwareImpl} instance, then XML locator information is lost. This - * class preserves locator information (as a string). - * - * @author ceki - */ -class CAI_WithLocatorSupport extends ContextAwareImpl { - - CAI_WithLocatorSupport(Interpreter interpreter) { - super(interpreter); - } - - @Override - protected Object getOrigin() { - Interpreter i = (Interpreter) super.getOrigin(); - Locator locator = i.locator; - if (locator != null) { - return Interpreter.class.getName() + "@" + locator.getLineNumber() + ":" - + locator.getColumnNumber(); - } else { - return Interpreter.class.getName() + "@NA:NA"; - } - } -} +/** + * 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.joran.spi; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.Vector; + +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.action.ImplicitAction; +import ch.qos.logback.core.joran.event.BodyEvent; +import ch.qos.logback.core.joran.event.EndEvent; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.event.StartEvent; +import ch.qos.logback.core.spi.ContextAwareImpl; + +/** + * Interpreter is Joran's main driving class. It extends SAX + * {@link org.xml.sax.helpers.DefaultHandler DefaultHandler} which invokes + * various {@link Action actions} according to predefined patterns. + * + *

+ * Patterns are kept in a {@link RuleStore} which is programmed to store and + * then later produce the applicable actions for a given pattern. + * + *

+ * The pattern corresponding to a top level <a> element is the string + * "a". + * + *

+ * The pattern corresponding to an element <b> embedded within a top level + * <a> element is the string "a/b". + * + *

+ * The pattern corresponding to an <b> and any level of nesting is + * "*/b. Thus, the * character placed at the beginning of a pattern + * serves as a wildcard for the level of nesting. + * + * Conceptually, this is very similar to the API of commons-digester. Joran + * offers several small advantages. First and foremost, it offers support for + * implicit actions which result in a significant leap in flexibility. Second, + * in our opinion better error reporting capability. Third, it is self-reliant. + * It does not depend on other APIs, in particular commons-logging which is too + * unreliable. Last but not least, Joran is quite tiny and is expected to remain + * so. + * + * @author Ceki Gülcuü + * + */ +public class Interpreter { + private static List EMPTY_LIST = new Vector(0); + + final private RuleStore ruleStore; + final private InterpretationContext interpretationContext; + final private ArrayList implicitActions; + final private CAI_WithLocatorSupport cai; + Pattern pattern; + Locator locator; + EventPlayer player; + + /** + * The actionListStack contains a list of actions that are executing + * for the given XML element. + * + * A list of actions is pushed by the {link #startElement} and popped by + * {@link #endElement}. + * + */ + Stack actionListStack; + + /** + * If the skip nested is set, then we skip all its nested elements until it is + * set back to null at when the element's end is reached. + */ + Pattern skip = null; + + public Interpreter(Context context, RuleStore rs, Pattern initialPattern) { + this.cai = new CAI_WithLocatorSupport(this); + this.cai.setContext(context); + ruleStore = rs; + interpretationContext = new InterpretationContext(context, this); + implicitActions = new ArrayList(3); + this.pattern = initialPattern; + actionListStack = new Stack(); + player = new EventPlayer(this); + } + + public void setInterpretationContextPropertiesMap(Map propertiesMap) { + interpretationContext.setPropertiesMap(propertiesMap); + } + /** + * @deprecated replaced by {@link #getInterpretationContext()} + */ + public InterpretationContext getExecutionContext() { + return getInterpretationContext(); + } + + public InterpretationContext getInterpretationContext() { + return interpretationContext; + } + + public void startDocument() { + } + + public void startElement(StartEvent se) { + setDocumentLocator(se.getLocator()); + startElement(se.namespaceURI, se.localName, se.qName, se.attributes); + } + + private void startElement(String namespaceURI, String localName, + String qName, Attributes atts) { + + String tagName = getTagName(localName, qName); + pattern.push(tagName); + + if (skip != null) { + // every startElement pushes an action list + pushEmptyActionList(); + return; + } + + List applicableActionList = getApplicableActionList(pattern, atts); + if (applicableActionList != null) { + actionListStack.add(applicableActionList); + callBeginAction(applicableActionList, tagName, atts); + } else { + // every startElement pushes an action list + pushEmptyActionList(); + String errMsg = "no applicable action for [" + tagName + + "], current pattern is [" + pattern + "]"; + cai.addError(errMsg); + } + } + + /** + * This method is used to + */ + private void pushEmptyActionList() { + actionListStack.add(EMPTY_LIST); + } + + public void characters(BodyEvent be) { + + setDocumentLocator(be.locator); + + String body = be.getText(); + List applicableActionList = (List) actionListStack.peek(); + + if (body != null) { + body = body.trim(); + } + if (body.length() > 0) { + // System.out.println("calling body method with ["+body+ "]"); + callBodyAction(applicableActionList, body); + } + } + + public void endElement(EndEvent endEvent) { + setDocumentLocator(endEvent.locator); + endElement(endEvent.namespaceURI, endEvent.localName, endEvent.qName); + } + + private void endElement(String namespaceURI, String localName, String qName) { + // given that an action list is always pushed for every startElement, we need + // to always pop for every endElement + List applicableActionList = (List) actionListStack.pop(); + + if (skip != null) { + if (skip.equals(pattern)) { + skip = null; + } + } else if (applicableActionList != EMPTY_LIST) { + callEndAction(applicableActionList, getTagName(localName, qName)); + } + + // given that we always push, we must also pop the pattern + pattern.pop(); + } + + public Locator getLocator() { + return locator; + } + + public void setDocumentLocator(Locator l) { + locator = l; + } + + String getTagName(String localName, String qName) { + String tagName = localName; + + if ((tagName == null) || (tagName.length() < 1)) { + tagName = qName; + } + + return tagName; + } + + public void addImplicitAction(ImplicitAction ia) { + implicitActions.add(ia); + } + + /** + * Check if any implicit actions are applicable. As soon as an applicable + * action is found, it is returned. Thus, the returned list will have at most + * one element. + */ + List lookupImplicitAction(Pattern pattern, Attributes attributes, + InterpretationContext ec) { + int len = implicitActions.size(); + + for (int i = 0; i < len; i++) { + ImplicitAction ia = (ImplicitAction) implicitActions.get(i); + + if (ia.isApplicable(pattern, attributes, ec)) { + List actionList = new ArrayList(1); + actionList.add(ia); + + return actionList; + } + } + + return null; + } + + /** + * Return the list of applicable patterns for this + */ + List getApplicableActionList(Pattern pattern, Attributes attributes) { + List applicableActionList = ruleStore.matchActions(pattern); + + // logger.debug("set of applicable patterns: " + applicableActionList); + if (applicableActionList == null) { + applicableActionList = lookupImplicitAction(pattern, attributes, interpretationContext); + } + + return applicableActionList; + } + + void callBeginAction(List applicableActionList, String tagName, + Attributes atts) { + if (applicableActionList == null) { + return; + } + + Iterator i = applicableActionList.iterator(); + while (i.hasNext()) { + Action action = (Action) i.next(); + // now let us invoke the action. We catch and report any eventual + // exceptions + try { + action.begin(interpretationContext, tagName, atts); + } catch (ActionException e) { + skip = (Pattern) pattern.clone(); + cai.addError("ActionException in Action for tag [" + tagName + "]", e); + } catch (RuntimeException e) { + skip = (Pattern) pattern.clone(); + cai.addError("RuntimeException in Action for tag [" + tagName + "]", e); + } + } + } + + private void callBodyAction(List applicableActionList, String body) { + if (applicableActionList == null) { + return; + } + Iterator i = applicableActionList.iterator(); + + while (i.hasNext()) { + Action action = (Action) i.next(); + try { + action.body(interpretationContext, body); + } catch (ActionException ae) { + cai + .addError("Exception in end() methd for action [" + action + "]", + ae); + } + } + } + + private void callEndAction(List applicableActionList, String tagName) { + if (applicableActionList == null) { + return; + } + + // logger.debug("About to call end actions on node: [" + localName + "]"); + Iterator i = applicableActionList.iterator(); + + while (i.hasNext()) { + Action action = (Action) i.next(); + // now let us invoke the end method of the action. We catch and report + // any eventual exceptions + try { + action.end(interpretationContext, tagName); + } catch (ActionException ae) { + // at this point endAction, there is no point in skipping children as + // they have been already processed + cai.addError("ActionException in Action for tag [" + tagName + "]", ae); + } catch (RuntimeException e) { + // no point in setting skip + cai.addError("RuntimeException in Action for tag [" + tagName + "]", e); + } + } + } + + public RuleStore getRuleStore() { + return ruleStore; + } + + public void play(List eventList) { + player.play(eventList); + } + + public void addEventsDynamically(List eventList) { + if (player != null) { + player.addEventsDynamically(eventList); + } + } +} + +/** + * When {@link Interpreter} class is used as the origin of an + * {@link ContextAwareImpl} instance, then XML locator information is lost. This + * class preserves locator information (as a string). + * + * @author ceki + */ +class CAI_WithLocatorSupport extends ContextAwareImpl { + + CAI_WithLocatorSupport(Interpreter interpreter) { + super(interpreter); + } + + @Override + protected Object getOrigin() { + Interpreter i = (Interpreter) super.getOrigin(); + Locator locator = i.locator; + if (locator != null) { + return Interpreter.class.getName() + "@" + locator.getLineNumber() + ":" + + locator.getColumnNumber(); + } else { + return Interpreter.class.getName() + "@NA:NA"; + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/JoranException.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/JoranException.java index eb32d09c13c19226240a3e314319939215fd9de2..92ac3d970f6e1634b674d595d4dc988827fd85d4 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/JoranException.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/JoranException.java @@ -1,27 +1,27 @@ -/** - * 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.joran.spi; - -public class JoranException extends Exception { - - private static final long serialVersionUID = 1112493363728774021L; - - public JoranException(String msg) { - super(msg); - } - - public JoranException(String msg, Throwable cause) { - super(msg, cause); - } -} +/** + * 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.joran.spi; + +public class JoranException extends Exception { + + private static final long serialVersionUID = 1112493363728774021L; + + public JoranException(String msg) { + super(msg); + } + + public JoranException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/NoAutoStart.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/NoAutoStart.java index 01ba3486652ff2224b372d1574e8e4a61af020a9..056678a805c58f5c0a4d9d0a2ff944d2ea590f62 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/NoAutoStart.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/NoAutoStart.java @@ -1,31 +1,31 @@ -/** - * 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.joran.spi; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * If a type (a class) has this annotation, then it will not be automatically - * started by Joran at configuration time. - * - * @author Ceki Gülcü - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface NoAutoStart { -} +/** + * 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.joran.spi; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * If a type (a class) has this annotation, then it will not be automatically + * started by Joran at configuration time. + * + * @author Ceki Gülcü + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface NoAutoStart { +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/NoAutoStartUtil.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/NoAutoStartUtil.java index 5c81b22ebee1ce7dd72d51f64884e4607a4f0821..c4868d7454cf464e02c9cffb2566290ae944b707 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/NoAutoStartUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/NoAutoStartUtil.java @@ -1,34 +1,34 @@ -/** - * 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.joran.spi; - -public class NoAutoStartUtil { - - /** - * Returns true if the class of the object 'o' passed as parameter is *not* - * marked with the NoAutoStart annotation. Return true otherwise. - * - * @param o - * @return true for classes not marked with the NoAutoStart annotation - */ - static public boolean notMarkedWithNoAutoStart(Object o) { - if (o == null) { - return false; - } - Class clazz = o.getClass(); - NoAutoStart a = clazz.getAnnotation(NoAutoStart.class); - return a == null; - } - -} +/** + * 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.joran.spi; + +public class NoAutoStartUtil { + + /** + * Returns true if the class of the object 'o' passed as parameter is *not* + * marked with the NoAutoStart annotation. Return true otherwise. + * + * @param o + * @return true for classes not marked with the NoAutoStart annotation + */ + static public boolean notMarkedWithNoAutoStart(Object o) { + if (o == null) { + return false; + } + Class clazz = o.getClass(); + NoAutoStart a = clazz.getAnnotation(NoAutoStart.class); + return a == null; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Pattern.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Pattern.java index fc14d735952b5c1d3fceb5be3d95b489e3866dbe..52c36a75b54d04069ad7551fb0b978b8de4370a7 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Pattern.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Pattern.java @@ -1,229 +1,229 @@ -/** - * 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.joran.spi; - -import java.util.ArrayList; - -/** - * A pattern is used to designate XML elements in a document. - * - *

For more information see - * http://logback.qos.ch/manual/onJoran.html#pattern - * - * @author Ceki Gülcü - */ -public class Pattern { - - // contains String instances - ArrayList partList = new ArrayList(); - - public Pattern() { - } - - /** - * Build a pattern from a string. - * - * Note that "/x" is considered equivalent to "x" and to "x/" - * - */ - public Pattern(String p) { - this(); - - if (p == null) { - return; - } - - int lastIndex = 0; - - // System.out.println("p is "+ p); - while (true) { - int k = p.indexOf('/', lastIndex); - - // System.out.println("k is "+ k); - if (k == -1) { - String lastPart = p.substring(lastIndex); - if (lastPart != null && lastPart.length() > 0) { - partList.add(p.substring(lastIndex)); - } - break; - } else { - String c = p.substring(lastIndex, k); - - if (c.length() > 0) { - partList.add(c); - } - - lastIndex = k + 1; - } - } - - // System.out.println(components); - } - - public Object clone() { - Pattern p = new Pattern(); - p.partList.addAll(this.partList); - return p; - } - - public void push(String s) { - partList.add(s); - } - - public int size() { - return partList.size(); - } - - public String get(int i) { - return (String) partList.get(i); - } - - public void pop() { - if (!partList.isEmpty()) { - partList.remove(partList.size() - 1); - } - } - - public String peekLast() { - if (!partList.isEmpty()) { - int size = partList.size(); - return (String) partList.get(size - 1); - } else { - return null; - } - } - - /** - * Returns the number of "tail" components that this pattern has in common - * with the pattern p passed as parameter. By "tail" components we mean the - * components at the end of the pattern. - */ - public int getTailMatchLength(Pattern p) { - if (p == null) { - return 0; - } - - int lSize = this.partList.size(); - int rSize = p.partList.size(); - - // no match possible for empty sets - if ((lSize == 0) || (rSize == 0)) { - return 0; - } - - int minLen = (lSize <= rSize) ? lSize : rSize; - int match = 0; - - // loop from the end to the front - for (int i = 1; i <= minLen; i++) { - String l = (String) this.partList.get(lSize - i); - String r = (String) p.partList.get(rSize - i); - - if (equalityCheck(l, r)) { - match++; - } else { - break; - } - } - - return match; - } - - /** - * Returns the number of "prefix" components that this pattern has in common - * with the pattern p passed as parameter. By "prefix" components we mean the - * components at the beginning of the pattern. - */ - public int getPrefixMatchLength(Pattern p) { - if (p == null) { - return 0; - } - - int lSize = this.partList.size(); - int rSize = p.partList.size(); - - // no match possible for empty sets - if ((lSize == 0) || (rSize == 0)) { - return 0; - } - - int minLen = (lSize <= rSize) ? lSize : rSize; - int match = 0; - - for (int i = 0; i < minLen; i++) { - String l = (String) this.partList.get(i); - String r = (String) p.partList.get(i); - - if (equalityCheck(l, r)) { - match++; - } else { - break; - } - } - - return match; - } - - private boolean equalityCheck(String x, String y) { - return x.equalsIgnoreCase(y); - } - - @Override - public boolean equals(Object o) { - if ((o == null) || !(o instanceof Pattern)) { - return false; - } - - Pattern r = (Pattern) o; - - if (r.size() != size()) { - return false; - } - - int len = size(); - - for (int i = 0; i < len; i++) { - if (!equalityCheck(get(i), r.get(i))) { - return false; - } - } - - // if everything matches, then the two patterns are equal - return true; - } - - @Override - public int hashCode() { - int hc = 0; - int len = size(); - - for (int i = 0; i < len; i++) { - // make Pattern comparisons case insensitive - // http://jira.qos.ch/browse/LBCORE-76 - hc ^= get(i).toLowerCase().hashCode(); - } - - return hc; - } - - @Override - public String toString() { - int size = partList.size(); - String result = ""; - for (int i = 0; i < size; i++) { - result += "[" + partList.get(i) + "]"; - } - return result; - } -} +/** + * 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.joran.spi; + +import java.util.ArrayList; + +/** + * A pattern is used to designate XML elements in a document. + * + *

For more information see + * http://logback.qos.ch/manual/onJoran.html#pattern + * + * @author Ceki Gülcü + */ +public class Pattern { + + // contains String instances + ArrayList partList = new ArrayList(); + + public Pattern() { + } + + /** + * Build a pattern from a string. + * + * Note that "/x" is considered equivalent to "x" and to "x/" + * + */ + public Pattern(String p) { + this(); + + if (p == null) { + return; + } + + int lastIndex = 0; + + // System.out.println("p is "+ p); + while (true) { + int k = p.indexOf('/', lastIndex); + + // System.out.println("k is "+ k); + if (k == -1) { + String lastPart = p.substring(lastIndex); + if (lastPart != null && lastPart.length() > 0) { + partList.add(p.substring(lastIndex)); + } + break; + } else { + String c = p.substring(lastIndex, k); + + if (c.length() > 0) { + partList.add(c); + } + + lastIndex = k + 1; + } + } + + // System.out.println(components); + } + + public Object clone() { + Pattern p = new Pattern(); + p.partList.addAll(this.partList); + return p; + } + + public void push(String s) { + partList.add(s); + } + + public int size() { + return partList.size(); + } + + public String get(int i) { + return (String) partList.get(i); + } + + public void pop() { + if (!partList.isEmpty()) { + partList.remove(partList.size() - 1); + } + } + + public String peekLast() { + if (!partList.isEmpty()) { + int size = partList.size(); + return (String) partList.get(size - 1); + } else { + return null; + } + } + + /** + * Returns the number of "tail" components that this pattern has in common + * with the pattern p passed as parameter. By "tail" components we mean the + * components at the end of the pattern. + */ + public int getTailMatchLength(Pattern p) { + if (p == null) { + return 0; + } + + int lSize = this.partList.size(); + int rSize = p.partList.size(); + + // no match possible for empty sets + if ((lSize == 0) || (rSize == 0)) { + return 0; + } + + int minLen = (lSize <= rSize) ? lSize : rSize; + int match = 0; + + // loop from the end to the front + for (int i = 1; i <= minLen; i++) { + String l = (String) this.partList.get(lSize - i); + String r = (String) p.partList.get(rSize - i); + + if (equalityCheck(l, r)) { + match++; + } else { + break; + } + } + + return match; + } + + /** + * Returns the number of "prefix" components that this pattern has in common + * with the pattern p passed as parameter. By "prefix" components we mean the + * components at the beginning of the pattern. + */ + public int getPrefixMatchLength(Pattern p) { + if (p == null) { + return 0; + } + + int lSize = this.partList.size(); + int rSize = p.partList.size(); + + // no match possible for empty sets + if ((lSize == 0) || (rSize == 0)) { + return 0; + } + + int minLen = (lSize <= rSize) ? lSize : rSize; + int match = 0; + + for (int i = 0; i < minLen; i++) { + String l = (String) this.partList.get(i); + String r = (String) p.partList.get(i); + + if (equalityCheck(l, r)) { + match++; + } else { + break; + } + } + + return match; + } + + private boolean equalityCheck(String x, String y) { + return x.equalsIgnoreCase(y); + } + + @Override + public boolean equals(Object o) { + if ((o == null) || !(o instanceof Pattern)) { + return false; + } + + Pattern r = (Pattern) o; + + if (r.size() != size()) { + return false; + } + + int len = size(); + + for (int i = 0; i < len; i++) { + if (!equalityCheck(get(i), r.get(i))) { + return false; + } + } + + // if everything matches, then the two patterns are equal + return true; + } + + @Override + public int hashCode() { + int hc = 0; + int len = size(); + + for (int i = 0; i < len; i++) { + // make Pattern comparisons case insensitive + // http://jira.qos.ch/browse/LBCORE-76 + hc ^= get(i).toLowerCase().hashCode(); + } + + return hc; + } + + @Override + public String toString() { + int size = partList.size(); + String result = ""; + for (int i = 0; i < size; i++) { + result += "[" + partList.get(i) + "]"; + } + return result; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java index c7e9eeb0adb44530469acbb6aac0f00ebf2d5ff3..c0c69d504b55593efdd4d2e25413b2215e528866 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java @@ -1,603 +1,603 @@ -/** - * 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. - */ -// Contributors: Georg Lundesgaard -package ch.qos.logback.core.joran.spi; - -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.MethodDescriptor; -import java.beans.PropertyDescriptor; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.joran.action.IADataForComplexProperty; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.util.AggregationType; -import ch.qos.logback.core.util.PropertySetterException; - -/** - * General purpose Object property setter. Clients repeatedly invokes - * {@link #setProperty setProperty(name,value)} in order to invoke setters on - * the Object specified in the constructor. This class relies on the JavaBeans - * {@link Introspector} to analyze the given Object Class using reflection. - * - *

Usage: - * - *

- * PropertySetter ps = new PropertySetter(anObject);
- * ps.set("name", "Joe");
- * ps.set("age", "32");
- * ps.set("isMale", "true");
- * 
- * - * will cause the invocations anObject.setName("Joe"), anObject.setAge(32), and - * setMale(true) if such methods exist with those signatures. Otherwise an - * {@link IntrospectionException} are thrown. - * - * @author Anders Kristensen - * @author Ceki Gulcu - */ -public class PropertySetter extends ContextAwareBase { - private static final Class[] STING_CLASS_PARAMETER = new Class[] { String.class }; - - protected Object obj; - protected Class objClass; - protected PropertyDescriptor[] propertyDescriptors; - protected MethodDescriptor[] methodDescriptors; - - /** - * Create a new PropertySetter for the specified Object. This is done in - * preparation for invoking {@link #setProperty} one or more times. - * - * @param obj - * the object for which to set properties - */ - public PropertySetter(Object obj) { - this.obj = obj; - this.objClass = obj.getClass(); - } - - /** - * Uses JavaBeans {@link Introspector} to computer setters of object to be - * configured. - */ - protected void introspect() { - try { - BeanInfo bi = Introspector.getBeanInfo(obj.getClass()); - propertyDescriptors = bi.getPropertyDescriptors(); - methodDescriptors = bi.getMethodDescriptors(); - } catch (IntrospectionException ex) { - addError("Failed to introspect " + obj + ": " + ex.getMessage()); - propertyDescriptors = new PropertyDescriptor[0]; - methodDescriptors = new MethodDescriptor[0]; - } - } - - /** - * Set a property on this PropertySetter's Object. If successful, this method - * will invoke a setter method on the underlying Object. The setter is the one - * for the specified property name and the value is determined partly from the - * setter argument type and partly from the value specified in the call to - * this method. - * - *

If the setter expects a String no conversion is necessary. If it - * expects an int, then an attempt is made to convert 'value' to an int using - * new Integer(value). If the setter expects a boolean, the conversion is by - * new Boolean(value). - * - * @param name - * name of the property - * @param value - * String value of the property - */ - public void setProperty(String name, String value) { - if (value == null) { - return; - } - - name = Introspector.decapitalize(name); - - PropertyDescriptor prop = getPropertyDescriptor(name); - - if (prop == null) { - addWarn("No such property [" + name + "] in " + objClass.getName() + "."); - } else { - try { - setProperty(prop, name, value); - } catch (PropertySetterException ex) { - addWarn("Failed to set property [" + name + "] to value \"" + value - + "\". ", ex); - } - } - } - - /** - * Set the named property given a {@link PropertyDescriptor}. - * - * @param prop - * A PropertyDescriptor describing the characteristics of the - * property to set. - * @param name - * The named of the property to set. - * @param value - * The value of the property. - */ - public void setProperty(PropertyDescriptor prop, String name, String value) - throws PropertySetterException { - Method setter = prop.getWriteMethod(); - - if (setter == null) { - throw new PropertySetterException("No setter for property [" + name - + "]."); - } - - Class[] paramTypes = setter.getParameterTypes(); - - if (paramTypes.length != 1) { - throw new PropertySetterException("#params for setter != 1"); - } - - Object arg; - - try { - arg = convertArg(value, paramTypes[0]); - } catch (Throwable t) { - throw new PropertySetterException("Conversion to type [" + paramTypes[0] - + "] failed. ", t); - } - - if (arg == null) { - throw new PropertySetterException("Conversion to type [" + paramTypes[0] - + "] failed."); - } - try { - setter.invoke(obj, arg); - } catch (Exception ex) { - throw new PropertySetterException(ex); - } - } - - public AggregationType computeAggregationType(String name) { - String cName = capitalizeFirstLetter(name); - - Method addMethod = findAdderMethod(cName); - - // if the - if (addMethod != null) { - AggregationType type = computeRawAggregationType(addMethod); - switch (type) { - case NOT_FOUND: - return AggregationType.NOT_FOUND; - case AS_BASIC_PROPERTY: - return AggregationType.AS_BASIC_PROPERTY_COLLECTION; - case AS_COMPLEX_PROPERTY: - return AggregationType.AS_COMPLEX_PROPERTY_COLLECTION; - } - } - - Method setterMethod = findSetterMethod(name); - if (setterMethod != null) { - return computeRawAggregationType(setterMethod); - } else { - // we have failed - return AggregationType.NOT_FOUND; - } - } - - private Method findAdderMethod(String name) { - name = capitalizeFirstLetter(name); - Method adderMethod = getMethod("add" + name); - return adderMethod; - } - - private Method findSetterMethod(String name) { - String dName = Introspector.decapitalize(name); - PropertyDescriptor propertyDescriptor = getPropertyDescriptor(dName); - if (propertyDescriptor != null) { - return propertyDescriptor.getWriteMethod(); - } else { - return null; - } - } - - private Class getParameterClassForMethod(Method method) { - if (method == null) { - return null; - } - Class[] classArray = method.getParameterTypes(); - if (classArray.length != 1) { - return null; - } else { - return classArray[0]; - } - } - - private AggregationType computeRawAggregationType(Method method) { - Class parameterClass = getParameterClassForMethod(method); - if (parameterClass == null) { - return AggregationType.NOT_FOUND; - } else { - Package p = parameterClass.getPackage(); - if (parameterClass.isPrimitive()) { - return AggregationType.AS_BASIC_PROPERTY; - } else if (p != null && "java.lang".equals(p.getName())) { - return AggregationType.AS_BASIC_PROPERTY; - } else if (isBuildableFromString(parameterClass)) { - return AggregationType.AS_BASIC_PROPERTY; - } else if (parameterClass.isEnum()) { - return AggregationType.AS_BASIC_PROPERTY; - } else { - return AggregationType.AS_COMPLEX_PROPERTY; - } - } - } - - public Class findUnequivocallyInstantiableClass( - IADataForComplexProperty actionData) { - Class clazz; - AggregationType at = actionData.getAggregationType(); - switch (at) { - case AS_COMPLEX_PROPERTY: - Method setterMethod = findSetterMethod(actionData - .getComplexPropertyName()); - clazz = getParameterClassForMethod(setterMethod); - if (clazz != null && isUnequivocallyInstantiable(clazz)) { - return clazz; - } else { - return null; - } - case AS_COMPLEX_PROPERTY_COLLECTION: - Method adderMethod = findAdderMethod(actionData.getComplexPropertyName()); - clazz = getParameterClassForMethod(adderMethod); - if (clazz != null && isUnequivocallyInstantiable(clazz)) { - return clazz; - } else { - return null; - } - default: - throw new IllegalArgumentException(at - + " is not valid type in this method"); - } - } - - /** - * Can the given clazz instantiable with certainty? - * - * @param clazz The class to test for instantiability - * @return true if clazz can be instantiated, and false otherwise. - */ - private boolean isUnequivocallyInstantiable(Class clazz) { - if (clazz.isInterface()) { - return false; - } - // checking for constructors would be more elegant, but in - // classes without any declared constructors, Class.getConstructor() - // returns null. - Object o; - try { - o = clazz.newInstance(); - if (o != null) { - return true; - } else { - return false; - } - } catch (InstantiationException e) { - return false; - } catch (IllegalAccessException e) { - return false; - } - } - - public Class getObjClass() { - return objClass; - } - - public void addComplexProperty(String name, Object complexProperty) { - Method adderMethod = findAdderMethod(name); - // first let us use the addXXX method - if (adderMethod != null) { - Class[] paramTypes = adderMethod.getParameterTypes(); - if (!isSanityCheckSuccessful(name, adderMethod, paramTypes, - complexProperty)) { - return; - } - invokeMethodWithSingleParameterOnThisObject(adderMethod, complexProperty); - } else { - addError("Could not find method [" + "add" + name + "] in class [" - + objClass.getName() + "]."); - } - } - - void invokeMethodWithSingleParameterOnThisObject(Method method, - Object parameter) { - Class ccc = parameter.getClass(); - try { - method.invoke(this.obj, parameter); - } catch (Exception e) { - addError("Could not invoke method " + method.getName() + " in class " - + obj.getClass().getName() + " with parameter of type " - + ccc.getName(), e); - } - } - - public void addBasicProperty(String name, String strValue) { - - if (strValue == null) { - return; - } - - name = capitalizeFirstLetter(name); - Method adderMethod = findAdderMethod(name); - - if (adderMethod == null) { - addError("No adder for property [" + name + "]."); - return; - } - - Class[] paramTypes = adderMethod.getParameterTypes(); - isSanityCheckSuccessful(name, adderMethod, paramTypes, strValue); - - Object arg; - try { - arg = convertArg(strValue, paramTypes[0]); - } catch (Throwable t) { - addError("Conversion to type [" + paramTypes[0] + "] failed. ", t); - return; - } - if (arg != null) { - invokeMethodWithSingleParameterOnThisObject(adderMethod, strValue); - } - } - - public void setComplexProperty(String name, Object complexProperty) { - String dName = Introspector.decapitalize(name); - PropertyDescriptor propertyDescriptor = getPropertyDescriptor(dName); - - if (propertyDescriptor == null) { - addWarn("Could not find PropertyDescriptor for [" + name + "] in " - + objClass.getName()); - - return; - } - - Method setter = propertyDescriptor.getWriteMethod(); - - if (setter == null) { - addWarn("Not setter method for property [" + name + "] in " - + obj.getClass().getName()); - - return; - } - - Class[] paramTypes = setter.getParameterTypes(); - - if (!isSanityCheckSuccessful(name, setter, paramTypes, complexProperty)) { - return; - } - try { - invokeMethodWithSingleParameterOnThisObject(setter, complexProperty); - - } catch (Exception e) { - addError("Could not set component " + obj + " for parent component " - + obj, e); - } - } - - private boolean isSanityCheckSuccessful(String name, Method method, - Class[] params, Object complexProperty) { - Class ccc = complexProperty.getClass(); - if (params.length != 1) { - addError("Wrong number of parameters in setter method for property [" - + name + "] in " + obj.getClass().getName()); - - return false; - } - - if (!params[0].isAssignableFrom(complexProperty.getClass())) { - addError("A \"" + ccc.getName() + "\" object is not assignable to a \"" - + params[0].getName() + "\" variable."); - addError("The class \"" + params[0].getName() + "\" was loaded by "); - addError("[" + params[0].getClassLoader() + "] whereas object of type "); - addError("\"" + ccc.getName() + "\" was loaded by [" - + ccc.getClassLoader() + "]."); - return false; - } - - return true; - } - - private String capitalizeFirstLetter(String name) { - return name.substring(0, 1).toUpperCase() + name.substring(1); - } - - /** - * Convert val a String parameter to an object of a given type. - */ - protected Object convertArg(String val, Class type) { - if (val == null) { - return null; - } - String v = val.trim(); - if (String.class.isAssignableFrom(type)) { - return v; - } else if (Integer.TYPE.isAssignableFrom(type)) { - return new Integer(v); - } else if (Long.TYPE.isAssignableFrom(type)) { - return new Long(v); - } else if (Float.TYPE.isAssignableFrom(type)) { - return new Float(v); - } else if (Double.TYPE.isAssignableFrom(type)) { - return new Double(v); - } else if (Boolean.TYPE.isAssignableFrom(type)) { - if ("true".equalsIgnoreCase(v)) { - return Boolean.TRUE; - } else if ("false".equalsIgnoreCase(v)) { - return Boolean.FALSE; - } - } else if (type.isEnum()) { - return convertEnum(v, type); - } else if (isBuildableFromString(type)) { - return buildFromString(type, v); - } - - return null; - } - - boolean isBuildableFromString(Class parameterClass) { - try { - Method valueOfMethod = parameterClass.getMethod(CoreConstants.VALUE_OF, - STING_CLASS_PARAMETER); - int mod = valueOfMethod.getModifiers(); - if (Modifier.isStatic(mod)) { - return true; - } - } catch (SecurityException e) { - // nop - } catch (NoSuchMethodException e) { - // nop - } - return false; - } - - Object buildFromString(Class type, String val) { - try { - Method valueOfMethod = type.getMethod(CoreConstants.VALUE_OF, - STING_CLASS_PARAMETER); - return valueOfMethod.invoke(null, val); - } catch (Exception e) { - addError("Failed to invoke " + CoreConstants.VALUE_OF - + "{} method in class [" + type.getName() + "] with value [" + val - + "]"); - return null; - } - } - - protected Object convertEnum(String val, Class type) { - try { - Method m = type.getMethod(CoreConstants.VALUE_OF, STING_CLASS_PARAMETER); - return m.invoke(null, val); - } catch (Exception e) { - addError("Failed to convert value [" + val + "] to enum [" - + type.getName() + "]", e); - } - return null; - } - - protected Method getMethod(String methodName) { - if (methodDescriptors == null) { - introspect(); - } - - for (int i = 0; i < methodDescriptors.length; i++) { - if (methodName.equals(methodDescriptors[i].getName())) { - return methodDescriptors[i].getMethod(); - } - } - - return null; - } - - protected PropertyDescriptor getPropertyDescriptor(String name) { - if (propertyDescriptors == null) { - introspect(); - } - - for (int i = 0; i < propertyDescriptors.length; i++) { - // System.out.println("Comparing " + name + " against " - // + propertyDescriptors[i].getName()); - if (name.equals(propertyDescriptors[i].getName())) { - // System.out.println("matched"); - return propertyDescriptors[i]; - } - } - - return null; - } - - public Object getObj() { - return obj; - } - - Method getRelevantMethod(String name, AggregationType aggregationType) { - String cName = capitalizeFirstLetter(name); - Method relevantMethod; - if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY_COLLECTION) { - relevantMethod = findAdderMethod(cName); - } else if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY) { - relevantMethod = findSetterMethod(cName); - } else { - throw new IllegalStateException(aggregationType + " not allowed here"); - } - return relevantMethod; - } - - T getAnnotation(String name, Class annonationClass, - Method relevantMethod) { - - if (relevantMethod != null) { - return relevantMethod.getAnnotation(annonationClass); - } else { - return null; - } - } - - Class getDefaultClassNameByAnnonation(String name, Method relevantMethod) { - DefaultClass defaultClassAnnon = getAnnotation(name, DefaultClass.class, - relevantMethod); - if (defaultClassAnnon != null) { - Class defaultClass = defaultClassAnnon.value(); - return defaultClass; - } - return null; - } - - Class getByConcreteType(String name, Method relevantMethod) { - - Class paramType = getParameterClassForMethod(relevantMethod); - if (paramType == null) { - return null; - } - - boolean isUnequivocallyInstantiable = isUnequivocallyInstantiable(paramType); - if(isUnequivocallyInstantiable) { - return paramType; - } else { - return null; - } - - } - - public Class getClassNameViaImplicitRules(String name, - AggregationType aggregationType, DefaultNestedComponentRegistry registry) { - - Class registryResult = registry.findDefaultComponentType(obj.getClass(), name); - if(registryResult!= null) { - return registryResult; - } - // find the relevant method for the given property name and aggregationType - Method relevantMethod = getRelevantMethod(name, aggregationType); - if (relevantMethod == null) { - return null; - } - Class byAnnotation = getDefaultClassNameByAnnonation(name, relevantMethod); - if (byAnnotation != null) { - return byAnnotation; - } - return getByConcreteType(name, relevantMethod); - } - -} +/** + * 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. + */ +// Contributors: Georg Lundesgaard +package ch.qos.logback.core.joran.spi; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.MethodDescriptor; +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.joran.action.IADataForComplexProperty; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.util.AggregationType; +import ch.qos.logback.core.util.PropertySetterException; + +/** + * General purpose Object property setter. Clients repeatedly invokes + * {@link #setProperty setProperty(name,value)} in order to invoke setters on + * the Object specified in the constructor. This class relies on the JavaBeans + * {@link Introspector} to analyze the given Object Class using reflection. + * + *

Usage: + * + *

+ * PropertySetter ps = new PropertySetter(anObject);
+ * ps.set("name", "Joe");
+ * ps.set("age", "32");
+ * ps.set("isMale", "true");
+ * 
+ * + * will cause the invocations anObject.setName("Joe"), anObject.setAge(32), and + * setMale(true) if such methods exist with those signatures. Otherwise an + * {@link IntrospectionException} are thrown. + * + * @author Anders Kristensen + * @author Ceki Gulcu + */ +public class PropertySetter extends ContextAwareBase { + private static final Class[] STING_CLASS_PARAMETER = new Class[] { String.class }; + + protected Object obj; + protected Class objClass; + protected PropertyDescriptor[] propertyDescriptors; + protected MethodDescriptor[] methodDescriptors; + + /** + * Create a new PropertySetter for the specified Object. This is done in + * preparation for invoking {@link #setProperty} one or more times. + * + * @param obj + * the object for which to set properties + */ + public PropertySetter(Object obj) { + this.obj = obj; + this.objClass = obj.getClass(); + } + + /** + * Uses JavaBeans {@link Introspector} to computer setters of object to be + * configured. + */ + protected void introspect() { + try { + BeanInfo bi = Introspector.getBeanInfo(obj.getClass()); + propertyDescriptors = bi.getPropertyDescriptors(); + methodDescriptors = bi.getMethodDescriptors(); + } catch (IntrospectionException ex) { + addError("Failed to introspect " + obj + ": " + ex.getMessage()); + propertyDescriptors = new PropertyDescriptor[0]; + methodDescriptors = new MethodDescriptor[0]; + } + } + + /** + * Set a property on this PropertySetter's Object. If successful, this method + * will invoke a setter method on the underlying Object. The setter is the one + * for the specified property name and the value is determined partly from the + * setter argument type and partly from the value specified in the call to + * this method. + * + *

If the setter expects a String no conversion is necessary. If it + * expects an int, then an attempt is made to convert 'value' to an int using + * new Integer(value). If the setter expects a boolean, the conversion is by + * new Boolean(value). + * + * @param name + * name of the property + * @param value + * String value of the property + */ + public void setProperty(String name, String value) { + if (value == null) { + return; + } + + name = Introspector.decapitalize(name); + + PropertyDescriptor prop = getPropertyDescriptor(name); + + if (prop == null) { + addWarn("No such property [" + name + "] in " + objClass.getName() + "."); + } else { + try { + setProperty(prop, name, value); + } catch (PropertySetterException ex) { + addWarn("Failed to set property [" + name + "] to value \"" + value + + "\". ", ex); + } + } + } + + /** + * Set the named property given a {@link PropertyDescriptor}. + * + * @param prop + * A PropertyDescriptor describing the characteristics of the + * property to set. + * @param name + * The named of the property to set. + * @param value + * The value of the property. + */ + public void setProperty(PropertyDescriptor prop, String name, String value) + throws PropertySetterException { + Method setter = prop.getWriteMethod(); + + if (setter == null) { + throw new PropertySetterException("No setter for property [" + name + + "]."); + } + + Class[] paramTypes = setter.getParameterTypes(); + + if (paramTypes.length != 1) { + throw new PropertySetterException("#params for setter != 1"); + } + + Object arg; + + try { + arg = convertArg(value, paramTypes[0]); + } catch (Throwable t) { + throw new PropertySetterException("Conversion to type [" + paramTypes[0] + + "] failed. ", t); + } + + if (arg == null) { + throw new PropertySetterException("Conversion to type [" + paramTypes[0] + + "] failed."); + } + try { + setter.invoke(obj, arg); + } catch (Exception ex) { + throw new PropertySetterException(ex); + } + } + + public AggregationType computeAggregationType(String name) { + String cName = capitalizeFirstLetter(name); + + Method addMethod = findAdderMethod(cName); + + // if the + if (addMethod != null) { + AggregationType type = computeRawAggregationType(addMethod); + switch (type) { + case NOT_FOUND: + return AggregationType.NOT_FOUND; + case AS_BASIC_PROPERTY: + return AggregationType.AS_BASIC_PROPERTY_COLLECTION; + case AS_COMPLEX_PROPERTY: + return AggregationType.AS_COMPLEX_PROPERTY_COLLECTION; + } + } + + Method setterMethod = findSetterMethod(name); + if (setterMethod != null) { + return computeRawAggregationType(setterMethod); + } else { + // we have failed + return AggregationType.NOT_FOUND; + } + } + + private Method findAdderMethod(String name) { + name = capitalizeFirstLetter(name); + Method adderMethod = getMethod("add" + name); + return adderMethod; + } + + private Method findSetterMethod(String name) { + String dName = Introspector.decapitalize(name); + PropertyDescriptor propertyDescriptor = getPropertyDescriptor(dName); + if (propertyDescriptor != null) { + return propertyDescriptor.getWriteMethod(); + } else { + return null; + } + } + + private Class getParameterClassForMethod(Method method) { + if (method == null) { + return null; + } + Class[] classArray = method.getParameterTypes(); + if (classArray.length != 1) { + return null; + } else { + return classArray[0]; + } + } + + private AggregationType computeRawAggregationType(Method method) { + Class parameterClass = getParameterClassForMethod(method); + if (parameterClass == null) { + return AggregationType.NOT_FOUND; + } else { + Package p = parameterClass.getPackage(); + if (parameterClass.isPrimitive()) { + return AggregationType.AS_BASIC_PROPERTY; + } else if (p != null && "java.lang".equals(p.getName())) { + return AggregationType.AS_BASIC_PROPERTY; + } else if (isBuildableFromString(parameterClass)) { + return AggregationType.AS_BASIC_PROPERTY; + } else if (parameterClass.isEnum()) { + return AggregationType.AS_BASIC_PROPERTY; + } else { + return AggregationType.AS_COMPLEX_PROPERTY; + } + } + } + + public Class findUnequivocallyInstantiableClass( + IADataForComplexProperty actionData) { + Class clazz; + AggregationType at = actionData.getAggregationType(); + switch (at) { + case AS_COMPLEX_PROPERTY: + Method setterMethod = findSetterMethod(actionData + .getComplexPropertyName()); + clazz = getParameterClassForMethod(setterMethod); + if (clazz != null && isUnequivocallyInstantiable(clazz)) { + return clazz; + } else { + return null; + } + case AS_COMPLEX_PROPERTY_COLLECTION: + Method adderMethod = findAdderMethod(actionData.getComplexPropertyName()); + clazz = getParameterClassForMethod(adderMethod); + if (clazz != null && isUnequivocallyInstantiable(clazz)) { + return clazz; + } else { + return null; + } + default: + throw new IllegalArgumentException(at + + " is not valid type in this method"); + } + } + + /** + * Can the given clazz instantiable with certainty? + * + * @param clazz The class to test for instantiability + * @return true if clazz can be instantiated, and false otherwise. + */ + private boolean isUnequivocallyInstantiable(Class clazz) { + if (clazz.isInterface()) { + return false; + } + // checking for constructors would be more elegant, but in + // classes without any declared constructors, Class.getConstructor() + // returns null. + Object o; + try { + o = clazz.newInstance(); + if (o != null) { + return true; + } else { + return false; + } + } catch (InstantiationException e) { + return false; + } catch (IllegalAccessException e) { + return false; + } + } + + public Class getObjClass() { + return objClass; + } + + public void addComplexProperty(String name, Object complexProperty) { + Method adderMethod = findAdderMethod(name); + // first let us use the addXXX method + if (adderMethod != null) { + Class[] paramTypes = adderMethod.getParameterTypes(); + if (!isSanityCheckSuccessful(name, adderMethod, paramTypes, + complexProperty)) { + return; + } + invokeMethodWithSingleParameterOnThisObject(adderMethod, complexProperty); + } else { + addError("Could not find method [" + "add" + name + "] in class [" + + objClass.getName() + "]."); + } + } + + void invokeMethodWithSingleParameterOnThisObject(Method method, + Object parameter) { + Class ccc = parameter.getClass(); + try { + method.invoke(this.obj, parameter); + } catch (Exception e) { + addError("Could not invoke method " + method.getName() + " in class " + + obj.getClass().getName() + " with parameter of type " + + ccc.getName(), e); + } + } + + public void addBasicProperty(String name, String strValue) { + + if (strValue == null) { + return; + } + + name = capitalizeFirstLetter(name); + Method adderMethod = findAdderMethod(name); + + if (adderMethod == null) { + addError("No adder for property [" + name + "]."); + return; + } + + Class[] paramTypes = adderMethod.getParameterTypes(); + isSanityCheckSuccessful(name, adderMethod, paramTypes, strValue); + + Object arg; + try { + arg = convertArg(strValue, paramTypes[0]); + } catch (Throwable t) { + addError("Conversion to type [" + paramTypes[0] + "] failed. ", t); + return; + } + if (arg != null) { + invokeMethodWithSingleParameterOnThisObject(adderMethod, strValue); + } + } + + public void setComplexProperty(String name, Object complexProperty) { + String dName = Introspector.decapitalize(name); + PropertyDescriptor propertyDescriptor = getPropertyDescriptor(dName); + + if (propertyDescriptor == null) { + addWarn("Could not find PropertyDescriptor for [" + name + "] in " + + objClass.getName()); + + return; + } + + Method setter = propertyDescriptor.getWriteMethod(); + + if (setter == null) { + addWarn("Not setter method for property [" + name + "] in " + + obj.getClass().getName()); + + return; + } + + Class[] paramTypes = setter.getParameterTypes(); + + if (!isSanityCheckSuccessful(name, setter, paramTypes, complexProperty)) { + return; + } + try { + invokeMethodWithSingleParameterOnThisObject(setter, complexProperty); + + } catch (Exception e) { + addError("Could not set component " + obj + " for parent component " + + obj, e); + } + } + + private boolean isSanityCheckSuccessful(String name, Method method, + Class[] params, Object complexProperty) { + Class ccc = complexProperty.getClass(); + if (params.length != 1) { + addError("Wrong number of parameters in setter method for property [" + + name + "] in " + obj.getClass().getName()); + + return false; + } + + if (!params[0].isAssignableFrom(complexProperty.getClass())) { + addError("A \"" + ccc.getName() + "\" object is not assignable to a \"" + + params[0].getName() + "\" variable."); + addError("The class \"" + params[0].getName() + "\" was loaded by "); + addError("[" + params[0].getClassLoader() + "] whereas object of type "); + addError("\"" + ccc.getName() + "\" was loaded by [" + + ccc.getClassLoader() + "]."); + return false; + } + + return true; + } + + private String capitalizeFirstLetter(String name) { + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + + /** + * Convert val a String parameter to an object of a given type. + */ + protected Object convertArg(String val, Class type) { + if (val == null) { + return null; + } + String v = val.trim(); + if (String.class.isAssignableFrom(type)) { + return v; + } else if (Integer.TYPE.isAssignableFrom(type)) { + return new Integer(v); + } else if (Long.TYPE.isAssignableFrom(type)) { + return new Long(v); + } else if (Float.TYPE.isAssignableFrom(type)) { + return new Float(v); + } else if (Double.TYPE.isAssignableFrom(type)) { + return new Double(v); + } else if (Boolean.TYPE.isAssignableFrom(type)) { + if ("true".equalsIgnoreCase(v)) { + return Boolean.TRUE; + } else if ("false".equalsIgnoreCase(v)) { + return Boolean.FALSE; + } + } else if (type.isEnum()) { + return convertEnum(v, type); + } else if (isBuildableFromString(type)) { + return buildFromString(type, v); + } + + return null; + } + + boolean isBuildableFromString(Class parameterClass) { + try { + Method valueOfMethod = parameterClass.getMethod(CoreConstants.VALUE_OF, + STING_CLASS_PARAMETER); + int mod = valueOfMethod.getModifiers(); + if (Modifier.isStatic(mod)) { + return true; + } + } catch (SecurityException e) { + // nop + } catch (NoSuchMethodException e) { + // nop + } + return false; + } + + Object buildFromString(Class type, String val) { + try { + Method valueOfMethod = type.getMethod(CoreConstants.VALUE_OF, + STING_CLASS_PARAMETER); + return valueOfMethod.invoke(null, val); + } catch (Exception e) { + addError("Failed to invoke " + CoreConstants.VALUE_OF + + "{} method in class [" + type.getName() + "] with value [" + val + + "]"); + return null; + } + } + + protected Object convertEnum(String val, Class type) { + try { + Method m = type.getMethod(CoreConstants.VALUE_OF, STING_CLASS_PARAMETER); + return m.invoke(null, val); + } catch (Exception e) { + addError("Failed to convert value [" + val + "] to enum [" + + type.getName() + "]", e); + } + return null; + } + + protected Method getMethod(String methodName) { + if (methodDescriptors == null) { + introspect(); + } + + for (int i = 0; i < methodDescriptors.length; i++) { + if (methodName.equals(methodDescriptors[i].getName())) { + return methodDescriptors[i].getMethod(); + } + } + + return null; + } + + protected PropertyDescriptor getPropertyDescriptor(String name) { + if (propertyDescriptors == null) { + introspect(); + } + + for (int i = 0; i < propertyDescriptors.length; i++) { + // System.out.println("Comparing " + name + " against " + // + propertyDescriptors[i].getName()); + if (name.equals(propertyDescriptors[i].getName())) { + // System.out.println("matched"); + return propertyDescriptors[i]; + } + } + + return null; + } + + public Object getObj() { + return obj; + } + + Method getRelevantMethod(String name, AggregationType aggregationType) { + String cName = capitalizeFirstLetter(name); + Method relevantMethod; + if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY_COLLECTION) { + relevantMethod = findAdderMethod(cName); + } else if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY) { + relevantMethod = findSetterMethod(cName); + } else { + throw new IllegalStateException(aggregationType + " not allowed here"); + } + return relevantMethod; + } + + T getAnnotation(String name, Class annonationClass, + Method relevantMethod) { + + if (relevantMethod != null) { + return relevantMethod.getAnnotation(annonationClass); + } else { + return null; + } + } + + Class getDefaultClassNameByAnnonation(String name, Method relevantMethod) { + DefaultClass defaultClassAnnon = getAnnotation(name, DefaultClass.class, + relevantMethod); + if (defaultClassAnnon != null) { + Class defaultClass = defaultClassAnnon.value(); + return defaultClass; + } + return null; + } + + Class getByConcreteType(String name, Method relevantMethod) { + + Class paramType = getParameterClassForMethod(relevantMethod); + if (paramType == null) { + return null; + } + + boolean isUnequivocallyInstantiable = isUnequivocallyInstantiable(paramType); + if(isUnequivocallyInstantiable) { + return paramType; + } else { + return null; + } + + } + + public Class getClassNameViaImplicitRules(String name, + AggregationType aggregationType, DefaultNestedComponentRegistry registry) { + + Class registryResult = registry.findDefaultComponentType(obj.getClass(), name); + if(registryResult!= null) { + return registryResult; + } + // find the relevant method for the given property name and aggregationType + Method relevantMethod = getRelevantMethod(name, aggregationType); + if (relevantMethod == null) { + return null; + } + Class byAnnotation = getDefaultClassNameByAnnonation(name, relevantMethod); + if (byAnnotation != null) { + return byAnnotation; + } + return getByConcreteType(name, relevantMethod); + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/RuleStore.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/RuleStore.java index 260c607597b5bd67c0dbeba0619cf315e48e7652..0193fd951f9ecd337455a084375b607c9e2da713 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/RuleStore.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/RuleStore.java @@ -1,39 +1,39 @@ -/** - * 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.joran.spi; - -import java.util.List; - -import ch.qos.logback.core.joran.action.Action; - -/** - * - * As its name indicates, a RuleStore contains 2-tuples consists of a Pattern - * and an Action. - * - *

As a joran configurator goes through the elements in a document, it asks - * the rule store whether there are rules matching the current pattern by - * invoking the {@link #matchActions(Pattern)} method. - * - * @author Ceki Gülcü - * - */ -public interface RuleStore { - public void addRule(Pattern pattern, String actionClassStr) - throws ClassNotFoundException; - - public void addRule(Pattern pattern, Action action); - - public List matchActions(Pattern currentPatern); -} +/** + * 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.joran.spi; + +import java.util.List; + +import ch.qos.logback.core.joran.action.Action; + +/** + * + * As its name indicates, a RuleStore contains 2-tuples consists of a Pattern + * and an Action. + * + *

As a joran configurator goes through the elements in a document, it asks + * the rule store whether there are rules matching the current pattern by + * invoking the {@link #matchActions(Pattern)} method. + * + * @author Ceki Gülcü + * + */ +public interface RuleStore { + public void addRule(Pattern pattern, String actionClassStr) + throws ClassNotFoundException; + + public void addRule(Pattern pattern, Action action); + + public List matchActions(Pattern currentPatern); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/SimpleRuleStore.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/SimpleRuleStore.java index 9c7a442844aec75a7ec8ccd17470ada8776fa59d..9a97c211896d2756d8fbc8adad384b506d927942 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/SimpleRuleStore.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/SimpleRuleStore.java @@ -1,161 +1,161 @@ -/** - * 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.joran.spi; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.util.OptionHelper; - -/** - * This class implements the {@link RuleStore} interface. It is the rule store - * implementation used by default in Joran. - * - * @author Ceki Gülcü - * - */ -public class SimpleRuleStore extends ContextAwareBase implements RuleStore { - - // key: Pattern instance, value: ArrayList containing actions - HashMap> rules = new HashMap>(); - - // public SimpleRuleStore() { - // } - - public SimpleRuleStore(Context context) { - setContext(context); - } - - /** - * Add a new rule, i.e. a pattern, action pair to the rule store.

Note - * that the added action's LoggerRepository will be set in the process. - */ - public void addRule(Pattern pattern, Action action) { - action.setContext(context); - - List a4p = rules.get(pattern); - - if (a4p == null) { - a4p = new ArrayList(); - rules.put(pattern, a4p); - } - - a4p.add(action); - } - - public void addRule(Pattern pattern, String actionClassName) { - Action action = null; - - try { - action = (Action) OptionHelper.instantiateByClassName(actionClassName, - Action.class, context); - } catch (Exception e) { - addError("Could not instantiate class [" + actionClassName + "]", e); - } - if (action != null) { - addRule(pattern, action); - } - } - - // exact match has highest priority - // if no exact match, check for tail match, i.e matches of type */x/y - // tail match for */x/y has higher priority than match for */x - // if no tail match, check for prefix match, i.e. matches for x/* - // match for x/y/* has higher priority than matches for x/* - - public List matchActions(Pattern currentPattern) { - List actionList; - - if ((actionList = rules.get(currentPattern)) != null) { - return actionList; - } else if ((actionList = tailMatch(currentPattern)) != null) { - return actionList; - } else if ((actionList = prefixMatch(currentPattern)) != null) { - // System.out.println(currentPattern + " prefixMatches "+actionList); - return actionList; - } else { - return null; - } - } - - List tailMatch(Pattern currentPattern) { - int max = 0; - Pattern longestMatchingPattern = null; - - for (Pattern p : rules.keySet()) { - - if ((p.size() > 1) && p.get(0).equals("*")) { - int r = currentPattern.getTailMatchLength(p); - - // System.out.println("tailMatch " +r); - if (r > max) { - // System.out.println("New longest tailMatch "+p); - max = r; - longestMatchingPattern = p; - } - } - } - - if (longestMatchingPattern != null) { - return rules.get(longestMatchingPattern); - } else { - return null; - } - } - - List prefixMatch(Pattern currentPattern) { - int max = 0; - Pattern longestMatchingPattern = null; - - for (Pattern p : rules.keySet()) { - String last = p.peekLast(); - if ("*".equals(last)) { - int r = currentPattern.getPrefixMatchLength(p); - - // System.out.println("r = "+ r + ", p= "+p); - - // to qualify the match length must equal p's size omitting the '*' - if ((r == p.size() - 1) && (r > max)) { - // System.out.println("New longest prefixMatch "+p); - max = r; - longestMatchingPattern = p; - } - } - } - - if (longestMatchingPattern != null) { - // System.out.println("prefixMatch will return" - // +rules.get(longestMatchingPattern)); - return rules.get(longestMatchingPattern); - } else { - return null; - } - } - - public String toString() { - final String TAB = " "; - - StringBuilder retValue = new StringBuilder(); - - retValue.append("SimpleRuleStore ( ").append("rules = ").append(this.rules) - .append(TAB).append(" )"); - - return retValue.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.joran.spi; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.util.OptionHelper; + +/** + * This class implements the {@link RuleStore} interface. It is the rule store + * implementation used by default in Joran. + * + * @author Ceki Gülcü + * + */ +public class SimpleRuleStore extends ContextAwareBase implements RuleStore { + + // key: Pattern instance, value: ArrayList containing actions + HashMap> rules = new HashMap>(); + + // public SimpleRuleStore() { + // } + + public SimpleRuleStore(Context context) { + setContext(context); + } + + /** + * Add a new rule, i.e. a pattern, action pair to the rule store.

Note + * that the added action's LoggerRepository will be set in the process. + */ + public void addRule(Pattern pattern, Action action) { + action.setContext(context); + + List a4p = rules.get(pattern); + + if (a4p == null) { + a4p = new ArrayList(); + rules.put(pattern, a4p); + } + + a4p.add(action); + } + + public void addRule(Pattern pattern, String actionClassName) { + Action action = null; + + try { + action = (Action) OptionHelper.instantiateByClassName(actionClassName, + Action.class, context); + } catch (Exception e) { + addError("Could not instantiate class [" + actionClassName + "]", e); + } + if (action != null) { + addRule(pattern, action); + } + } + + // exact match has highest priority + // if no exact match, check for tail match, i.e matches of type */x/y + // tail match for */x/y has higher priority than match for */x + // if no tail match, check for prefix match, i.e. matches for x/* + // match for x/y/* has higher priority than matches for x/* + + public List matchActions(Pattern currentPattern) { + List actionList; + + if ((actionList = rules.get(currentPattern)) != null) { + return actionList; + } else if ((actionList = tailMatch(currentPattern)) != null) { + return actionList; + } else if ((actionList = prefixMatch(currentPattern)) != null) { + // System.out.println(currentPattern + " prefixMatches "+actionList); + return actionList; + } else { + return null; + } + } + + List tailMatch(Pattern currentPattern) { + int max = 0; + Pattern longestMatchingPattern = null; + + for (Pattern p : rules.keySet()) { + + if ((p.size() > 1) && p.get(0).equals("*")) { + int r = currentPattern.getTailMatchLength(p); + + // System.out.println("tailMatch " +r); + if (r > max) { + // System.out.println("New longest tailMatch "+p); + max = r; + longestMatchingPattern = p; + } + } + } + + if (longestMatchingPattern != null) { + return rules.get(longestMatchingPattern); + } else { + return null; + } + } + + List prefixMatch(Pattern currentPattern) { + int max = 0; + Pattern longestMatchingPattern = null; + + for (Pattern p : rules.keySet()) { + String last = p.peekLast(); + if ("*".equals(last)) { + int r = currentPattern.getPrefixMatchLength(p); + + // System.out.println("r = "+ r + ", p= "+p); + + // to qualify the match length must equal p's size omitting the '*' + if ((r == p.size() - 1) && (r > max)) { + // System.out.println("New longest prefixMatch "+p); + max = r; + longestMatchingPattern = p; + } + } + } + + if (longestMatchingPattern != null) { + // System.out.println("prefixMatch will return" + // +rules.get(longestMatchingPattern)); + return rules.get(longestMatchingPattern); + } else { + return null; + } + } + + public String toString() { + final String TAB = " "; + + StringBuilder retValue = new StringBuilder(); + + retValue.append("SimpleRuleStore ( ").append("rules = ").append(this.rules) + .append(TAB).append(" )"); + + return retValue.toString(); + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/XMLUtil.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/XMLUtil.java index 8faa35a16d49605fc1ba83274b7cbb14637b38de..fc70f98d4c439409ae1f68d5ac1633693f21e9a1 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/XMLUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/XMLUtil.java @@ -1,30 +1,30 @@ -/** - * 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.joran.spi; - -import java.net.URL; - -import ch.qos.logback.core.status.StatusManager; - -public class XMLUtil { - - - static public final int ILL_FORMED = 1; - static public final int UNRECOVERABLE_ERROR = 2; - - static public int checkIfWellFormed(URL url, StatusManager sm) { - return 0; - } - -} +/** + * 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.joran.spi; + +import java.net.URL; + +import ch.qos.logback.core.status.StatusManager; + +public class XMLUtil { + + + static public final int ILL_FORMED = 1; + static public final int UNRECOVERABLE_ERROR = 2; + + static public int checkIfWellFormed(URL url, StatusManager sm) { + return 0; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/layout/EchoLayout.java b/logback-core/src/main/java/ch/qos/logback/core/layout/EchoLayout.java index e897728ca0beaeb04135f885d4d6f22f7fc7b70b..427c79d4a08fe0275f2d2259f391856ab668bf2e 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/layout/EchoLayout.java +++ b/logback-core/src/main/java/ch/qos/logback/core/layout/EchoLayout.java @@ -1,30 +1,30 @@ -/** - * 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.layout; - -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.LayoutBase; - -/** - * Echos the incoming object adding a line separator character(s) at the end. - * - * @author Ceki - */ -public class EchoLayout extends LayoutBase { - - public String doLayout(E event) { - return event+CoreConstants.LINE_SEPARATOR; - } - -} +/** + * 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.layout; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.LayoutBase; + +/** + * Echos the incoming object adding a line separator character(s) at the end. + * + * @author Ceki + */ +public class EchoLayout extends LayoutBase { + + public String doLayout(E event) { + return event+CoreConstants.LINE_SEPARATOR; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/JMSAppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/net/JMSAppenderBase.java index fca163469fec333af03063a2eb8ce37bf0d45b9f..d5d8f905c47cbf1d30cf71db904d1c7c3cd2407b 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/net/JMSAppenderBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/net/JMSAppenderBase.java @@ -1,177 +1,177 @@ -/** - * 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.net; - -import java.util.Hashtable; -import java.util.Properties; - -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NameNotFoundException; -import javax.naming.NamingException; - -import ch.qos.logback.core.AppenderBase; - -/** - * This class serves as a base class for - * JMSTopicAppender and JMSQueueAppender - * - * For more information about this appender, please refer to: - * http://logback.qos.ch/manual/appenders.html#JMSAppenderBase - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public abstract class JMSAppenderBase extends AppenderBase { - - protected String securityPrincipalName; - protected String securityCredentials; - protected String initialContextFactoryName; - protected String urlPkgPrefixes; - protected String providerURL; - protected String userName; - protected String password; - - - protected Object lookup(Context ctx, String name) throws NamingException { - try { - return ctx.lookup(name); - } catch (NameNotFoundException e) { - addError("Could not find name [" + name + "]."); - throw e; - } - } - - public Context buildJNDIContext() throws NamingException { - Context jndi = null; - - // addInfo("Getting initial context."); - if (initialContextFactoryName != null) { - Properties env = buildEnvProperties(); - jndi = new InitialContext(env); - } else { - jndi = new InitialContext(); - } - return jndi; - } - - public Properties buildEnvProperties() { - Properties env = new Properties(); - env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName); - if (providerURL != null) { - env.put(Context.PROVIDER_URL, providerURL); - } else { - addWarn("You have set InitialContextFactoryName option but not the " - + "ProviderURL. This is likely to cause problems."); - } - if (urlPkgPrefixes != null) { - env.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes); - } - - if (securityPrincipalName != null) { - env.put(Context.SECURITY_PRINCIPAL, securityPrincipalName); - if (securityCredentials != null) { - env.put(Context.SECURITY_CREDENTIALS, securityCredentials); - } else { - addWarn("You have set SecurityPrincipalName option but not the " - + "SecurityCredentials. This is likely to cause problems."); - } - } - return env; - } - - - - /** - * Returns the value of the InitialContextFactoryName option. See - * {@link #setInitialContextFactoryName} for more details on the meaning of - * this option. - */ - public String getInitialContextFactoryName() { - return initialContextFactoryName; - } - - /** - * Setting the InitialContextFactoryName method will cause this - * JMSAppender instance to use the {@link - * InitialContext#InitialContext(Hashtable)} method instead of the no-argument - * constructor. If you set this option, you should also at least set the - * ProviderURL option. - * - *

- * See also {@link #setProviderURL(String)}. - */ - public void setInitialContextFactoryName(String initialContextFactoryName) { - this.initialContextFactoryName = initialContextFactoryName; - } - - public String getProviderURL() { - return providerURL; - } - - public void setProviderURL(String providerURL) { - this.providerURL = providerURL; - } - - public String getURLPkgPrefixes() { - return urlPkgPrefixes; - } - - public void setURLPkgPrefixes(String urlPkgPrefixes) { - this.urlPkgPrefixes = urlPkgPrefixes; - } - - public String getSecurityCredentials() { - return securityCredentials; - } - - public void setSecurityCredentials(String securityCredentials) { - this.securityCredentials = securityCredentials; - } - - public String getSecurityPrincipalName() { - return securityPrincipalName; - } - - public void setSecurityPrincipalName(String securityPrincipalName) { - this.securityPrincipalName = securityPrincipalName; - } - - public String getUserName() { - return userName; - } - - /** - * The user name to use when {@link - * javax.jms.TopicConnectionFactory#createTopicConnection(String, String)} - * creating a topic session}. If you set this option, you should also set the - * Password option. See {@link #setPassword(String)}. - */ - public void setUserName(String userName) { - this.userName = userName; - } - - public String getPassword() { - return password; - } - - /** - * The paswword to use when creating a topic session. - */ - public void setPassword(String password) { - this.password = password; - } - - -} +/** + * 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.net; + +import java.util.Hashtable; +import java.util.Properties; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; + +import ch.qos.logback.core.AppenderBase; + +/** + * This class serves as a base class for + * JMSTopicAppender and JMSQueueAppender + * + * For more information about this appender, please refer to: + * http://logback.qos.ch/manual/appenders.html#JMSAppenderBase + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public abstract class JMSAppenderBase extends AppenderBase { + + protected String securityPrincipalName; + protected String securityCredentials; + protected String initialContextFactoryName; + protected String urlPkgPrefixes; + protected String providerURL; + protected String userName; + protected String password; + + + protected Object lookup(Context ctx, String name) throws NamingException { + try { + return ctx.lookup(name); + } catch (NameNotFoundException e) { + addError("Could not find name [" + name + "]."); + throw e; + } + } + + public Context buildJNDIContext() throws NamingException { + Context jndi = null; + + // addInfo("Getting initial context."); + if (initialContextFactoryName != null) { + Properties env = buildEnvProperties(); + jndi = new InitialContext(env); + } else { + jndi = new InitialContext(); + } + return jndi; + } + + public Properties buildEnvProperties() { + Properties env = new Properties(); + env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName); + if (providerURL != null) { + env.put(Context.PROVIDER_URL, providerURL); + } else { + addWarn("You have set InitialContextFactoryName option but not the " + + "ProviderURL. This is likely to cause problems."); + } + if (urlPkgPrefixes != null) { + env.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes); + } + + if (securityPrincipalName != null) { + env.put(Context.SECURITY_PRINCIPAL, securityPrincipalName); + if (securityCredentials != null) { + env.put(Context.SECURITY_CREDENTIALS, securityCredentials); + } else { + addWarn("You have set SecurityPrincipalName option but not the " + + "SecurityCredentials. This is likely to cause problems."); + } + } + return env; + } + + + + /** + * Returns the value of the InitialContextFactoryName option. See + * {@link #setInitialContextFactoryName} for more details on the meaning of + * this option. + */ + public String getInitialContextFactoryName() { + return initialContextFactoryName; + } + + /** + * Setting the InitialContextFactoryName method will cause this + * JMSAppender instance to use the {@link + * InitialContext#InitialContext(Hashtable)} method instead of the no-argument + * constructor. If you set this option, you should also at least set the + * ProviderURL option. + * + *

+ * See also {@link #setProviderURL(String)}. + */ + public void setInitialContextFactoryName(String initialContextFactoryName) { + this.initialContextFactoryName = initialContextFactoryName; + } + + public String getProviderURL() { + return providerURL; + } + + public void setProviderURL(String providerURL) { + this.providerURL = providerURL; + } + + public String getURLPkgPrefixes() { + return urlPkgPrefixes; + } + + public void setURLPkgPrefixes(String urlPkgPrefixes) { + this.urlPkgPrefixes = urlPkgPrefixes; + } + + public String getSecurityCredentials() { + return securityCredentials; + } + + public void setSecurityCredentials(String securityCredentials) { + this.securityCredentials = securityCredentials; + } + + public String getSecurityPrincipalName() { + return securityPrincipalName; + } + + public void setSecurityPrincipalName(String securityPrincipalName) { + this.securityPrincipalName = securityPrincipalName; + } + + public String getUserName() { + return userName; + } + + /** + * The user name to use when {@link + * javax.jms.TopicConnectionFactory#createTopicConnection(String, String)} + * creating a topic session}. If you set this option, you should also set the + * Password option. See {@link #setPassword(String)}. + */ + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassword() { + return password; + } + + /** + * The paswword to use when creating a topic session. + */ + public void setPassword(String password) { + this.password = password; + } + + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/LoginAuthenticator.java b/logback-core/src/main/java/ch/qos/logback/core/net/LoginAuthenticator.java index 57ffa84746ff996f7a5819e7e2798b0c5f130cbd..28d9a7b3849722299ebf9fdf4590d892c0350afa 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/net/LoginAuthenticator.java +++ b/logback-core/src/main/java/ch/qos/logback/core/net/LoginAuthenticator.java @@ -1,33 +1,33 @@ -/** - * 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.net; - -import javax.mail.Authenticator; -import javax.mail.PasswordAuthentication; - -public class LoginAuthenticator extends Authenticator { - - String username; - String password; - - LoginAuthenticator(String username, String password) { - this.username = username; - this.password = password; - } - - public PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); -} - -} +/** + * 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.net; + +import javax.mail.Authenticator; +import javax.mail.PasswordAuthentication; + +public class LoginAuthenticator extends Authenticator { + + String username; + String password; + + LoginAuthenticator(String username, String password) { + this.username = username; + this.password = password; + } + + public PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); +} + +} 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 2d8ba8de302c6cfff19eee457be3ea90cc0c4f04..469c1ce1bcf26f521b3a07e446a316adc74c196b 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 @@ -1,430 +1,430 @@ -/** - * 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.net; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Properties; - -import javax.mail.Message; -import javax.mail.MessagingException; -import javax.mail.Multipart; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.internet.AddressException; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; - -import ch.qos.logback.core.AppenderBase; -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.util.ContentTypeUtil; -import ch.qos.logback.core.util.OptionHelper; - -// Contributors: -// Andrey Rybin charset encoding support http://jira.qos.ch/browse/LBCORE-69 - -/** - * An abstract class that provides support for sending events to an email - * address. - * - *

See http://logback.qos.ch/manual/appenders.html#SMTPAppender for further - * documentation. - * - * @author Ceki Gülcü - * @author Sébastien Pennec - */ -public abstract class SMTPAppenderBase extends AppenderBase { - - protected Layout subjectLayout; - - private List to = new ArrayList(); - private String from; - private String subjectStr = null; - private String smtpHost; - private int smtpPort = 25; - private boolean starttls = false; - private boolean ssl = false; - - String username; - String password; - - private String charsetEncoding = "UTF-8"; - - protected MimeMessage mimeMsg; - - protected EventEvaluator eventEvaluator; - - /** - * return a layout for the subjet string as appropriate for the module. If the - * subjectStr parameter is null, then a default value for subjectStr should be - * used. - * - * @param subjectStr - * - * @return a layout as appropriate for the module - */ - abstract protected Layout makeSubjectLayout(String subjectStr); - - /** - * Start the appender - */ - public void start() { - Properties props = new Properties(OptionHelper.getSystemProperties()); - if (smtpHost != null) { - props.put("mail.smtp.host", smtpHost); - } - props.put("mail.smtp.port", Integer.toString(smtpPort)); - - LoginAuthenticator loginAuthenticator = null; - - if (username != null) { - loginAuthenticator = new LoginAuthenticator(username, password); - props.put("mail.smtp.auth", "true"); - } - - if (isSTARTTLS() && isSSL()) { - addError("Both SSL and StartTLS cannot be enabled simultaneously"); - } else { - if (isSTARTTLS()) { - props.setProperty("mail.smtp.auth", "true"); - props.put("mail.smtp.starttls.enable", "true"); - } - if (isSSL()) { - String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; - props.put("mail.smtp.socketFactory.port", Integer.toString(smtpPort)); - props.put("mail.smtp.socketFactory.class", SSL_FACTORY); - props.put("mail.smtp.socketFactory.fallback", "true"); - } - } - - // props.put("mail.debug", "true"); - - Session session = Session.getInstance(props, loginAuthenticator); - mimeMsg = new MimeMessage(session); - - try { - if (from != null) { - mimeMsg.setFrom(getAddress(from)); - } else { - mimeMsg.setFrom(); - } - - mimeMsg.setRecipients(Message.RecipientType.TO, parseAddress(to)); - - subjectLayout = makeSubjectLayout(subjectStr); - - started = true; - - } catch (MessagingException e) { - addError("Could not activate SMTPAppender options.", e); - } - } - - /** - * Perform SMTPAppender specific appending actions, delegating some of them to - * a subclass and checking if the event triggers an e-mail to be sent. - */ - protected void append(E eventObject) { - - if (!checkEntryConditions()) { - return; - } - - subAppend(eventObject); - - try { - if (eventEvaluator.evaluate(eventObject)) { - sendBuffer(eventObject); - } - } catch (EvaluationException ex) { - addError("SMTPAppender's EventEvaluator threw an Exception" + ex); - } - } - - abstract protected void subAppend(E eventObject); - - /** - * This method determines if there is a sense in attempting to append. - * - *

It checks whether there is a set output target and also if there is a - * set layout. If these checks fail, then the boolean value false - * is returned. - */ - public boolean checkEntryConditions() { - if (!this.started) { - addError("Attempting to append to a non-started appender: " - + this.getName()); - return false; - } - - if (this.mimeMsg == null) { - addError("Message object not configured."); - return false; - } - - if (this.eventEvaluator == null) { - addError("No EventEvaluator is set for appender [" + name + "]."); - return false; - } - - if (this.layout == null) { - addError("No layout set for appender named [" - + name - + "]. For more information, please visit http://logback.qos.ch/codes.html#smtp_no_layout"); - return false; - } - return true; - } - - synchronized public void stop() { - this.started = false; - } - - InternetAddress getAddress(String addressStr) { - try { - return new InternetAddress(addressStr); - } catch (AddressException e) { - addError("Could not parse address [" + addressStr + "].", e); - return null; - } - } - - InternetAddress[] parseAddress(List addressList) { - - InternetAddress[] iaArray = new InternetAddress[addressList.size()]; - - for (int i = 0; i < addressList.size(); i++) { - try { - InternetAddress[] tmp = InternetAddress.parse(addressList.get(i), true); - // one element should contain one email address - iaArray[i] = tmp[0]; - } catch (AddressException e) { - addError("Could not parse address [" + addressList.get(i) + "].", e); - return null; - } - } - - return iaArray; - } - - /** - * Returns value of the To option. - */ - public List getTo() { - return to; - } - - /** - * Send the contents of the cyclic buffer as an e-mail message. - */ - protected void sendBuffer(E lastEventObject) { - - // Note: this code already owns the monitor for this - // appender. This frees us from needing to synchronize on 'cb'. - try { - MimeBodyPart part = new MimeBodyPart(); - - StringBuffer sbuf = new StringBuffer(); - - String header = layout.getFileHeader(); - if (header != null) { - sbuf.append(header); - } - String presentationHeader = layout.getPresentationHeader(); - if (presentationHeader != null) { - sbuf.append(presentationHeader); - } - fillBuffer(sbuf); - String presentationFooter = layout.getPresentationFooter(); - if (presentationFooter != null) { - sbuf.append(presentationFooter); - } - String footer = layout.getFileFooter(); - if (footer != null) { - sbuf.append(footer); - } - - if (subjectLayout != null) { - mimeMsg.setSubject(subjectLayout.doLayout(lastEventObject), - charsetEncoding); - } - - String contentType = layout.getContentType(); - - if (ContentTypeUtil.isTextual(contentType)) { - part.setText(sbuf.toString(), charsetEncoding, ContentTypeUtil - .getSubType(contentType)); - } else { - part.setContent(sbuf.toString(), layout.getContentType()); - } - - Multipart mp = new MimeMultipart(); - mp.addBodyPart(part); - mimeMsg.setContent(mp); - - mimeMsg.setSentDate(new Date()); - Transport.send(mimeMsg); - } catch (Exception e) { - addError("Error occured while sending e-mail notification.", e); - } - } - - abstract protected void fillBuffer(StringBuffer sbuf); - - /** - * Returns value of the From option. - */ - public String getFrom() { - return from; - } - - /** - * Returns value of the Subject option. - */ - public String getSubject() { - return subjectStr; - } - - /** - * The From option takes a string value which should be a e-mail - * address of the sender. - */ - public void setFrom(String from) { - this.from = from; - } - - /** - * The Subject option takes a string value which should be a the - * subject of the e-mail message. - */ - public void setSubject(String subject) { - this.subjectStr = subject; - } - - /** - * The SMTPHost option takes a string value which should be a the host - * name of the SMTP server that will send the e-mail message. - */ - public void setSMTPHost(String smtpHost) { - this.smtpHost = smtpHost; - } - - /** - * Returns value of the SMTPHost option. - */ - public String getSMTPHost() { - return smtpHost; - } - - /** - * The port where the SMTP server is running. Default value is 25. - * - * @param port - */ - public void setSMTPPort(int port) { - this.smtpPort = port; - } - - /** - * @see #setSMTPPort(int) - * @return - */ - public int getSMTPPort() { - return smtpPort; - } - - /** - * The To option takes a string value which should be an e-mail - * address of one of the recipients. - */ - public void addTo(String to) { - this.to.add(to); - } - - // for testing purpose only - public Message getMessage() { - return mimeMsg; - } - - // for testing purpose only - public void setMessage(MimeMessage msg) { - this.mimeMsg = msg; - } - - public boolean isSTARTTLS() { - return starttls; - } - - public void setSTARTTLS(boolean startTLS) { - this.starttls = startTLS; - } - - public boolean isSSL() { - return ssl; - } - - public void setSSL(boolean ssl) { - this.ssl = ssl; - } - - /** - * The EventEvaluator option takes a string value representing the - * name of the class implementing the {@link EventEvaluators} interface. A - * corresponding object will be instantiated and assigned as the event - * evaluator for the SMTPAppender. - */ - public void setEvaluator(EventEvaluator eventEvaluator) { - this.eventEvaluator = eventEvaluator; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - /** - * @see #setCharsetEncoding(String) - * @return the charset encoding value - */ - String getCharsetEncoding() { - return charsetEncoding; - } - - /** - * Set the character set encoding of the outgoing email messages. The default - * encoding is "UTF-8" which usually works well for most purposes. - * - * @param charsetEncoding - */ - void setCharsetEncoding(String charsetEncoding) { - this.charsetEncoding = charsetEncoding; - } - -} +/** + * 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.net; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Properties; + +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Multipart; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; + +import ch.qos.logback.core.AppenderBase; +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.util.ContentTypeUtil; +import ch.qos.logback.core.util.OptionHelper; + +// Contributors: +// Andrey Rybin charset encoding support http://jira.qos.ch/browse/LBCORE-69 + +/** + * An abstract class that provides support for sending events to an email + * address. + * + *

See http://logback.qos.ch/manual/appenders.html#SMTPAppender for further + * documentation. + * + * @author Ceki Gülcü + * @author Sébastien Pennec + */ +public abstract class SMTPAppenderBase extends AppenderBase { + + protected Layout subjectLayout; + + private List to = new ArrayList(); + private String from; + private String subjectStr = null; + private String smtpHost; + private int smtpPort = 25; + private boolean starttls = false; + private boolean ssl = false; + + String username; + String password; + + private String charsetEncoding = "UTF-8"; + + protected MimeMessage mimeMsg; + + protected EventEvaluator eventEvaluator; + + /** + * return a layout for the subjet string as appropriate for the module. If the + * subjectStr parameter is null, then a default value for subjectStr should be + * used. + * + * @param subjectStr + * + * @return a layout as appropriate for the module + */ + abstract protected Layout makeSubjectLayout(String subjectStr); + + /** + * Start the appender + */ + public void start() { + Properties props = new Properties(OptionHelper.getSystemProperties()); + if (smtpHost != null) { + props.put("mail.smtp.host", smtpHost); + } + props.put("mail.smtp.port", Integer.toString(smtpPort)); + + LoginAuthenticator loginAuthenticator = null; + + if (username != null) { + loginAuthenticator = new LoginAuthenticator(username, password); + props.put("mail.smtp.auth", "true"); + } + + if (isSTARTTLS() && isSSL()) { + addError("Both SSL and StartTLS cannot be enabled simultaneously"); + } else { + if (isSTARTTLS()) { + props.setProperty("mail.smtp.auth", "true"); + props.put("mail.smtp.starttls.enable", "true"); + } + if (isSSL()) { + String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; + props.put("mail.smtp.socketFactory.port", Integer.toString(smtpPort)); + props.put("mail.smtp.socketFactory.class", SSL_FACTORY); + props.put("mail.smtp.socketFactory.fallback", "true"); + } + } + + // props.put("mail.debug", "true"); + + Session session = Session.getInstance(props, loginAuthenticator); + mimeMsg = new MimeMessage(session); + + try { + if (from != null) { + mimeMsg.setFrom(getAddress(from)); + } else { + mimeMsg.setFrom(); + } + + mimeMsg.setRecipients(Message.RecipientType.TO, parseAddress(to)); + + subjectLayout = makeSubjectLayout(subjectStr); + + started = true; + + } catch (MessagingException e) { + addError("Could not activate SMTPAppender options.", e); + } + } + + /** + * Perform SMTPAppender specific appending actions, delegating some of them to + * a subclass and checking if the event triggers an e-mail to be sent. + */ + protected void append(E eventObject) { + + if (!checkEntryConditions()) { + return; + } + + subAppend(eventObject); + + try { + if (eventEvaluator.evaluate(eventObject)) { + sendBuffer(eventObject); + } + } catch (EvaluationException ex) { + addError("SMTPAppender's EventEvaluator threw an Exception" + ex); + } + } + + abstract protected void subAppend(E eventObject); + + /** + * This method determines if there is a sense in attempting to append. + * + *

It checks whether there is a set output target and also if there is a + * set layout. If these checks fail, then the boolean value false + * is returned. + */ + public boolean checkEntryConditions() { + if (!this.started) { + addError("Attempting to append to a non-started appender: " + + this.getName()); + return false; + } + + if (this.mimeMsg == null) { + addError("Message object not configured."); + return false; + } + + if (this.eventEvaluator == null) { + addError("No EventEvaluator is set for appender [" + name + "]."); + return false; + } + + if (this.layout == null) { + addError("No layout set for appender named [" + + name + + "]. For more information, please visit http://logback.qos.ch/codes.html#smtp_no_layout"); + return false; + } + return true; + } + + synchronized public void stop() { + this.started = false; + } + + InternetAddress getAddress(String addressStr) { + try { + return new InternetAddress(addressStr); + } catch (AddressException e) { + addError("Could not parse address [" + addressStr + "].", e); + return null; + } + } + + InternetAddress[] parseAddress(List addressList) { + + InternetAddress[] iaArray = new InternetAddress[addressList.size()]; + + for (int i = 0; i < addressList.size(); i++) { + try { + InternetAddress[] tmp = InternetAddress.parse(addressList.get(i), true); + // one element should contain one email address + iaArray[i] = tmp[0]; + } catch (AddressException e) { + addError("Could not parse address [" + addressList.get(i) + "].", e); + return null; + } + } + + return iaArray; + } + + /** + * Returns value of the To option. + */ + public List getTo() { + return to; + } + + /** + * Send the contents of the cyclic buffer as an e-mail message. + */ + protected void sendBuffer(E lastEventObject) { + + // Note: this code already owns the monitor for this + // appender. This frees us from needing to synchronize on 'cb'. + try { + MimeBodyPart part = new MimeBodyPart(); + + StringBuffer sbuf = new StringBuffer(); + + String header = layout.getFileHeader(); + if (header != null) { + sbuf.append(header); + } + String presentationHeader = layout.getPresentationHeader(); + if (presentationHeader != null) { + sbuf.append(presentationHeader); + } + fillBuffer(sbuf); + String presentationFooter = layout.getPresentationFooter(); + if (presentationFooter != null) { + sbuf.append(presentationFooter); + } + String footer = layout.getFileFooter(); + if (footer != null) { + sbuf.append(footer); + } + + if (subjectLayout != null) { + mimeMsg.setSubject(subjectLayout.doLayout(lastEventObject), + charsetEncoding); + } + + String contentType = layout.getContentType(); + + if (ContentTypeUtil.isTextual(contentType)) { + part.setText(sbuf.toString(), charsetEncoding, ContentTypeUtil + .getSubType(contentType)); + } else { + part.setContent(sbuf.toString(), layout.getContentType()); + } + + Multipart mp = new MimeMultipart(); + mp.addBodyPart(part); + mimeMsg.setContent(mp); + + mimeMsg.setSentDate(new Date()); + Transport.send(mimeMsg); + } catch (Exception e) { + addError("Error occured while sending e-mail notification.", e); + } + } + + abstract protected void fillBuffer(StringBuffer sbuf); + + /** + * Returns value of the From option. + */ + public String getFrom() { + return from; + } + + /** + * Returns value of the Subject option. + */ + public String getSubject() { + return subjectStr; + } + + /** + * The From option takes a string value which should be a e-mail + * address of the sender. + */ + public void setFrom(String from) { + this.from = from; + } + + /** + * The Subject option takes a string value which should be a the + * subject of the e-mail message. + */ + public void setSubject(String subject) { + this.subjectStr = subject; + } + + /** + * The SMTPHost option takes a string value which should be a the host + * name of the SMTP server that will send the e-mail message. + */ + public void setSMTPHost(String smtpHost) { + this.smtpHost = smtpHost; + } + + /** + * Returns value of the SMTPHost option. + */ + public String getSMTPHost() { + return smtpHost; + } + + /** + * The port where the SMTP server is running. Default value is 25. + * + * @param port + */ + public void setSMTPPort(int port) { + this.smtpPort = port; + } + + /** + * @see #setSMTPPort(int) + * @return + */ + public int getSMTPPort() { + return smtpPort; + } + + /** + * The To option takes a string value which should be an e-mail + * address of one of the recipients. + */ + public void addTo(String to) { + this.to.add(to); + } + + // for testing purpose only + public Message getMessage() { + return mimeMsg; + } + + // for testing purpose only + public void setMessage(MimeMessage msg) { + this.mimeMsg = msg; + } + + public boolean isSTARTTLS() { + return starttls; + } + + public void setSTARTTLS(boolean startTLS) { + this.starttls = startTLS; + } + + public boolean isSSL() { + return ssl; + } + + public void setSSL(boolean ssl) { + this.ssl = ssl; + } + + /** + * The EventEvaluator option takes a string value representing the + * name of the class implementing the {@link EventEvaluators} interface. A + * corresponding object will be instantiated and assigned as the event + * evaluator for the SMTPAppender. + */ + public void setEvaluator(EventEvaluator eventEvaluator) { + this.eventEvaluator = eventEvaluator; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + /** + * @see #setCharsetEncoding(String) + * @return the charset encoding value + */ + String getCharsetEncoding() { + return charsetEncoding; + } + + /** + * Set the character set encoding of the outgoing email messages. The default + * encoding is "UTF-8" which usually works well for most purposes. + * + * @param charsetEncoding + */ + void setCharsetEncoding(String charsetEncoding) { + this.charsetEncoding = charsetEncoding; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/SyslogAppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/net/SyslogAppenderBase.java index 01275c953fcbcb5a4dfbdaa8f7e0a1e020cd8408..8c0d6607efd5137319808d1afcb673b135e0de1e 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/net/SyslogAppenderBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/net/SyslogAppenderBase.java @@ -1,243 +1,243 @@ -/** - * 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.net; - -import java.io.IOException; -import java.net.SocketException; -import java.net.UnknownHostException; - -import ch.qos.logback.core.AppenderBase; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.Layout; - -/** - * Base class for SyslogAppender. - * - * @author Ceki Gülcü - * - * @param - */ -public abstract class SyslogAppenderBase extends AppenderBase { - - final static String SYSLOG_LAYOUT_URL = CoreConstants.CODES_URL + "#syslog_layout"; - final static int MSG_SIZE_LIMIT = 256*1024; - - String facilityStr; - String syslogHost; - protected String suffixPattern; - SyslogWriter sw; - int port = SyslogConstants.SYSLOG_PORT; - - public void start() { - int errorCount = 0; - if (facilityStr == null) { - addError("The Facility option is mandatory"); - errorCount++; - } - - try { - sw = new SyslogWriter(syslogHost, port); - } catch (UnknownHostException e) { - addError("Could not create SyslogWriter", e); - errorCount++; - } catch (SocketException e) { - errorCount++; - addError("Failed to bind to a random datagram socket ", e); - } - - if (layout == null) { - layout = buildLayout(facilityStr); - } - - if (errorCount == 0) { - super.start(); - } - } - - abstract public Layout buildLayout(String facilityStr); - - abstract public int getSeverityForEvent(Object eventObject); - - @Override - protected void append(E eventObject) { - if (!isStarted()) { - return; - } - - try { - String msg = layout.doLayout(eventObject); - if(msg != null && msg.length() > MSG_SIZE_LIMIT) { - msg = msg.substring(0, MSG_SIZE_LIMIT); - } - sw.write(msg); - sw.flush(); - postProcess(eventObject, sw); - } catch (IOException ioe) { - addError("Failed to send diagram to " + syslogHost, ioe); - stop(); - } - } - - protected void postProcess(Object event, SyslogWriter sw) { - - } - - /** - * Returns the integer value corresponding to the named syslog facility. - * - * @throws IllegalArgumentException - * if the facility string is not recognized - */ - static public int facilityStringToint(String facilityStr) { - if ("KERN".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_KERN; - } else if ("USER".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_USER; - } else if ("MAIL".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_MAIL; - } else if ("DAEMON".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_DAEMON; - } else if ("AUTH".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_AUTH; - } else if ("SYSLOG".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_SYSLOG; - } else if ("LPR".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_LPR; - } else if ("NEWS".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_NEWS; - } else if ("UUCP".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_UUCP; - } else if ("CRON".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_CRON; - } else if ("AUTHPRIV".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_AUTHPRIV; - } else if ("FTP".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_FTP; - } else if ("LOCAL0".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_LOCAL0; - } else if ("LOCAL1".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_LOCAL1; - } else if ("LOCAL2".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_LOCAL2; - } else if ("LOCAL3".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_LOCAL3; - } else if ("LOCAL4".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_LOCAL4; - } else if ("LOCAL5".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_LOCAL5; - } else if ("LOCAL6".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_LOCAL6; - } else if ("LOCAL7".equalsIgnoreCase(facilityStr)) { - return SyslogConstants.LOG_LOCAL7; - } else { - throw new IllegalArgumentException(facilityStr - + " is not a valid syslog facility string"); - } - } - - /** - * Returns the value of the SyslogHost option. - */ - public String getSyslogHost() { - return syslogHost; - } - - /** - * The SyslogHost option is the name of the the syslog host where log - * output should go. - * - * WARNING If the SyslogHost is not set, then this appender will fail. - */ - public void setSyslogHost(String syslogHost) { - this.syslogHost = syslogHost; - } - - /** - * Returns the string value of the Facility option. - * - * See {@link #setFacility} for the set of allowed values. - */ - public String getFacility() { - return facilityStr; - } - - /** - * The Facility option must be set one of the strings KERN, USER, - * MAIL, DAEMON, AUTH, SYSLOG, LPR, NEWS, UUCP, CRON, AUTHPRIV, FTP, NTP, - * AUDIT, ALERT, CLOCK, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, - * LOCAL6, LOCAL7. Case is not important. - * - *

- * See {@link SyslogConstants} and RFC 3164 for more information about the - * Facility option. - */ - public void setFacility(String facilityStr) { - if (facilityStr != null) { - facilityStr = facilityStr.trim(); - } - this.facilityStr = facilityStr; - } - - /** - * - * @return - */ - public int getPort() { - return port; - } - - /** - * The port number on the syslog server to connect to. Nornally, wou would not - * want to change the default value, that is 514. - */ - public void setPort(int port) { - this.port = port; - } - - - @Override - public Layout getLayout() { - return layout; - } - - @Override - public void setLayout(Layout layout) { - addWarn("The layout of a SyslogAppender cannot be set directly. See also "+SYSLOG_LAYOUT_URL); - } - - @Override - public void stop() { - sw.close(); - super.stop(); - } - - /** - * See {@link #setSuffixPattern(String). - * - * @return - */ - public String getSuffixPattern() { - return suffixPattern; - } - - /** - * The suffixPattern option specifies the fortmat of the - * non-standardized part the message sent to the syslog server. - * - * @param pattern - */ - public void setSuffixPattern(String suffixPattern) { - this.suffixPattern = suffixPattern; - } -} +/** + * 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.net; + +import java.io.IOException; +import java.net.SocketException; +import java.net.UnknownHostException; + +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.Layout; + +/** + * Base class for SyslogAppender. + * + * @author Ceki Gülcü + * + * @param + */ +public abstract class SyslogAppenderBase extends AppenderBase { + + final static String SYSLOG_LAYOUT_URL = CoreConstants.CODES_URL + "#syslog_layout"; + final static int MSG_SIZE_LIMIT = 256*1024; + + String facilityStr; + String syslogHost; + protected String suffixPattern; + SyslogWriter sw; + int port = SyslogConstants.SYSLOG_PORT; + + public void start() { + int errorCount = 0; + if (facilityStr == null) { + addError("The Facility option is mandatory"); + errorCount++; + } + + try { + sw = new SyslogWriter(syslogHost, port); + } catch (UnknownHostException e) { + addError("Could not create SyslogWriter", e); + errorCount++; + } catch (SocketException e) { + errorCount++; + addError("Failed to bind to a random datagram socket ", e); + } + + if (layout == null) { + layout = buildLayout(facilityStr); + } + + if (errorCount == 0) { + super.start(); + } + } + + abstract public Layout buildLayout(String facilityStr); + + abstract public int getSeverityForEvent(Object eventObject); + + @Override + protected void append(E eventObject) { + if (!isStarted()) { + return; + } + + try { + String msg = layout.doLayout(eventObject); + if(msg != null && msg.length() > MSG_SIZE_LIMIT) { + msg = msg.substring(0, MSG_SIZE_LIMIT); + } + sw.write(msg); + sw.flush(); + postProcess(eventObject, sw); + } catch (IOException ioe) { + addError("Failed to send diagram to " + syslogHost, ioe); + stop(); + } + } + + protected void postProcess(Object event, SyslogWriter sw) { + + } + + /** + * Returns the integer value corresponding to the named syslog facility. + * + * @throws IllegalArgumentException + * if the facility string is not recognized + */ + static public int facilityStringToint(String facilityStr) { + if ("KERN".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_KERN; + } else if ("USER".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_USER; + } else if ("MAIL".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_MAIL; + } else if ("DAEMON".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_DAEMON; + } else if ("AUTH".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_AUTH; + } else if ("SYSLOG".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_SYSLOG; + } else if ("LPR".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_LPR; + } else if ("NEWS".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_NEWS; + } else if ("UUCP".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_UUCP; + } else if ("CRON".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_CRON; + } else if ("AUTHPRIV".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_AUTHPRIV; + } else if ("FTP".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_FTP; + } else if ("LOCAL0".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_LOCAL0; + } else if ("LOCAL1".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_LOCAL1; + } else if ("LOCAL2".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_LOCAL2; + } else if ("LOCAL3".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_LOCAL3; + } else if ("LOCAL4".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_LOCAL4; + } else if ("LOCAL5".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_LOCAL5; + } else if ("LOCAL6".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_LOCAL6; + } else if ("LOCAL7".equalsIgnoreCase(facilityStr)) { + return SyslogConstants.LOG_LOCAL7; + } else { + throw new IllegalArgumentException(facilityStr + + " is not a valid syslog facility string"); + } + } + + /** + * Returns the value of the SyslogHost option. + */ + public String getSyslogHost() { + return syslogHost; + } + + /** + * The SyslogHost option is the name of the the syslog host where log + * output should go. + * + * WARNING If the SyslogHost is not set, then this appender will fail. + */ + public void setSyslogHost(String syslogHost) { + this.syslogHost = syslogHost; + } + + /** + * Returns the string value of the Facility option. + * + * See {@link #setFacility} for the set of allowed values. + */ + public String getFacility() { + return facilityStr; + } + + /** + * The Facility option must be set one of the strings KERN, USER, + * MAIL, DAEMON, AUTH, SYSLOG, LPR, NEWS, UUCP, CRON, AUTHPRIV, FTP, NTP, + * AUDIT, ALERT, CLOCK, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, + * LOCAL6, LOCAL7. Case is not important. + * + *

+ * See {@link SyslogConstants} and RFC 3164 for more information about the + * Facility option. + */ + public void setFacility(String facilityStr) { + if (facilityStr != null) { + facilityStr = facilityStr.trim(); + } + this.facilityStr = facilityStr; + } + + /** + * + * @return + */ + public int getPort() { + return port; + } + + /** + * The port number on the syslog server to connect to. Nornally, wou would not + * want to change the default value, that is 514. + */ + public void setPort(int port) { + this.port = port; + } + + + @Override + public Layout getLayout() { + return layout; + } + + @Override + public void setLayout(Layout layout) { + addWarn("The layout of a SyslogAppender cannot be set directly. See also "+SYSLOG_LAYOUT_URL); + } + + @Override + public void stop() { + sw.close(); + super.stop(); + } + + /** + * See {@link #setSuffixPattern(String). + * + * @return + */ + public String getSuffixPattern() { + return suffixPattern; + } + + /** + * The suffixPattern option specifies the fortmat of the + * non-standardized part the message sent to the syslog server. + * + * @param pattern + */ + public void setSuffixPattern(String suffixPattern) { + this.suffixPattern = suffixPattern; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/SyslogConstants.java b/logback-core/src/main/java/ch/qos/logback/core/net/SyslogConstants.java index 833fba454d9beb5eb0367c9264c7cf2beb9c7c08..0e47e6c960f75081854aa157666f5b8b5ca747f4 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/net/SyslogConstants.java +++ b/logback-core/src/main/java/ch/qos/logback/core/net/SyslogConstants.java @@ -1,96 +1,96 @@ -/** - * 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.net; - -/** - * Constants used by syslog daemon and transitively by {@link SyslogAppenderBase}. - * - * @author Ceki Gülcü - **/ -public class SyslogConstants { - - static public final int SYSLOG_PORT = 514; - - - // Following constants extracted from RFC 3164, we multiply them by 8 - // in order to precompute the facility part of PRI. - // See RFC 3164, Section 4.1.1 for exact details. - - /** Emergency: system is unusable */ - public static final int EMERGENCY_SEVERITY = 0; - /** Alert: action must be taken immediately */ - public static final int ALERT_SEVERITY = 1; - /** Critical: critical conditions */ - public static final int CRITICAL_SEVERITY = 2; - /** Error: error conditions */ - public static final int ERROR_SEVERITY = 3; - /** Warning: warning conditions */ - public static final int WARNING_SEVERITY = 4; - /** Notice: normal but significant condition */ - public static final int NOTICE_SEVERITY = 5; - /** Informational: informational messages */ - public static final int INFO_SEVERITY = 6; - /** Debug: debug-level messages */ - public static final int DEBUG_SEVERITY = 7; - - - /** kernel messages, numerical code 0. */ - public static final int LOG_KERN = 0; - /** user-level messages, numerical code 1. */ - public static final int LOG_USER = 1 << 3; - /** mail system, numerical code 2. */ - public static final int LOG_MAIL = 2 << 3; - /** system daemons, numerical code 3. */ - public static final int LOG_DAEMON = 3 << 3; - /** security/authorization messages, numerical code 4. */ - public static final int LOG_AUTH = 4 << 3; - /** messages generated internally by syslogd, numerical code 5. */ - public static final int LOG_SYSLOG = 5 << 3; - /** line printer subsystem, numerical code 6. */ - public static final int LOG_LPR = 6 << 3; - /** network news subsystem, numerical code 7. */ - public static final int LOG_NEWS = 7 << 3; - /** UUCP subsystem, numerical code 8 */ - public static final int LOG_UUCP = 8 << 3; - /** clock daemon, numerical code 9. */ - public static final int LOG_CRON = 9 << 3; - /** security/authorization messages, numerical code 10. */ - public static final int LOG_AUTHPRIV = 10 << 3; - /** ftp daemon, numerical code 11. */ - public static final int LOG_FTP = 11 << 3; - /** NTP subsystem, numerical code 12. */ - public static final int LOG_NTP = 12 << 3; - /** log audit, numerical code 13. */ - public static final int LOG_AUDIT = 13 << 3; - /** log alert, numerical code 14. */ - public static final int LOG_ALERT = 14 << 3; - /** clock daemon, numerical code 15. */ - public static final int LOG_CLOCK = 15 << 3; - /** reserved for local use, numerical code 16. */ - public static final int LOG_LOCAL0 = 16 << 3; - /** reserved for local use, numerical code 17. */ - public static final int LOG_LOCAL1 = 17 << 3; - /** reserved for local use, numerical code 18. */ - public static final int LOG_LOCAL2 = 18 << 3; - /** reserved for local use, numerical code 19. */ - public static final int LOG_LOCAL3 = 19 << 3; - /** reserved for local use, numerical code 20. */ - public static final int LOG_LOCAL4 = 20 << 3; - /** reserved for local use, numerical code 21. */ - public static final int LOG_LOCAL5 = 21 << 3; - /** reserved for local use, numerical code 22. */ - public static final int LOG_LOCAL6 = 22 << 3; - /** reserved for local use, numerical code 23.*/ - public static final int LOG_LOCAL7 = 23 << 3; -} +/** + * 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.net; + +/** + * Constants used by syslog daemon and transitively by {@link SyslogAppenderBase}. + * + * @author Ceki Gülcü + **/ +public class SyslogConstants { + + static public final int SYSLOG_PORT = 514; + + + // Following constants extracted from RFC 3164, we multiply them by 8 + // in order to precompute the facility part of PRI. + // See RFC 3164, Section 4.1.1 for exact details. + + /** Emergency: system is unusable */ + public static final int EMERGENCY_SEVERITY = 0; + /** Alert: action must be taken immediately */ + public static final int ALERT_SEVERITY = 1; + /** Critical: critical conditions */ + public static final int CRITICAL_SEVERITY = 2; + /** Error: error conditions */ + public static final int ERROR_SEVERITY = 3; + /** Warning: warning conditions */ + public static final int WARNING_SEVERITY = 4; + /** Notice: normal but significant condition */ + public static final int NOTICE_SEVERITY = 5; + /** Informational: informational messages */ + public static final int INFO_SEVERITY = 6; + /** Debug: debug-level messages */ + public static final int DEBUG_SEVERITY = 7; + + + /** kernel messages, numerical code 0. */ + public static final int LOG_KERN = 0; + /** user-level messages, numerical code 1. */ + public static final int LOG_USER = 1 << 3; + /** mail system, numerical code 2. */ + public static final int LOG_MAIL = 2 << 3; + /** system daemons, numerical code 3. */ + public static final int LOG_DAEMON = 3 << 3; + /** security/authorization messages, numerical code 4. */ + public static final int LOG_AUTH = 4 << 3; + /** messages generated internally by syslogd, numerical code 5. */ + public static final int LOG_SYSLOG = 5 << 3; + /** line printer subsystem, numerical code 6. */ + public static final int LOG_LPR = 6 << 3; + /** network news subsystem, numerical code 7. */ + public static final int LOG_NEWS = 7 << 3; + /** UUCP subsystem, numerical code 8 */ + public static final int LOG_UUCP = 8 << 3; + /** clock daemon, numerical code 9. */ + public static final int LOG_CRON = 9 << 3; + /** security/authorization messages, numerical code 10. */ + public static final int LOG_AUTHPRIV = 10 << 3; + /** ftp daemon, numerical code 11. */ + public static final int LOG_FTP = 11 << 3; + /** NTP subsystem, numerical code 12. */ + public static final int LOG_NTP = 12 << 3; + /** log audit, numerical code 13. */ + public static final int LOG_AUDIT = 13 << 3; + /** log alert, numerical code 14. */ + public static final int LOG_ALERT = 14 << 3; + /** clock daemon, numerical code 15. */ + public static final int LOG_CLOCK = 15 << 3; + /** reserved for local use, numerical code 16. */ + public static final int LOG_LOCAL0 = 16 << 3; + /** reserved for local use, numerical code 17. */ + public static final int LOG_LOCAL1 = 17 << 3; + /** reserved for local use, numerical code 18. */ + public static final int LOG_LOCAL2 = 18 << 3; + /** reserved for local use, numerical code 19. */ + public static final int LOG_LOCAL3 = 19 << 3; + /** reserved for local use, numerical code 20. */ + public static final int LOG_LOCAL4 = 20 << 3; + /** reserved for local use, numerical code 21. */ + public static final int LOG_LOCAL5 = 21 << 3; + /** reserved for local use, numerical code 22. */ + public static final int LOG_LOCAL6 = 22 << 3; + /** reserved for local use, numerical code 23.*/ + public static final int LOG_LOCAL7 = 23 << 3; +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/SyslogWriter.java b/logback-core/src/main/java/ch/qos/logback/core/net/SyslogWriter.java index d9998af6da96e60ddd2e07646cf0ff89a862b17b..bedecd3863ac769197d3d51ff7c89afc21b83cc1 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/net/SyslogWriter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/net/SyslogWriter.java @@ -1,82 +1,82 @@ -/** - * 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.net; - -import java.io.IOException; -import java.io.Writer; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.SocketException; -import java.net.UnknownHostException; - -/** - * SyslogWriter is a wrapper around the {@link DatagramSocket} class so that it - * behaves like a {@link Writer}. - */ -public class SyslogWriter extends Writer { - - /** - * The maximum length after which we discard the existing string buffer and - * start anew. - */ - private static final int MAX_LEN = 1024; - - private InetAddress address; - private DatagramSocket ds; - private StringBuffer buf = new StringBuffer(); - final private int port; - - public SyslogWriter(String syslogHost, int port) throws UnknownHostException, - SocketException { - this.address = InetAddress.getByName(syslogHost); - this.port = port; - this.ds = new DatagramSocket(); - } - - public void write(char[] charArray, int offset, int len) throws IOException { - buf.append(charArray, offset, len); - } - - public void write(String str) throws IOException { - buf.append(str); - - } - - public void flush() throws IOException { - byte[] bytes = buf.toString().getBytes(); - DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, - port); - - if (this.ds != null) { - ds.send(packet); - } - // clean up for next round - if (buf.length() > MAX_LEN) { - buf = new StringBuffer(); - } else { - buf.setLength(0); - } - } - - public void close() { - address = null; - ds = null; - } - - public int getPort() { - return port; - } - -} +/** + * 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.net; + +import java.io.IOException; +import java.io.Writer; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; +import java.net.UnknownHostException; + +/** + * SyslogWriter is a wrapper around the {@link DatagramSocket} class so that it + * behaves like a {@link Writer}. + */ +public class SyslogWriter extends Writer { + + /** + * The maximum length after which we discard the existing string buffer and + * start anew. + */ + private static final int MAX_LEN = 1024; + + private InetAddress address; + private DatagramSocket ds; + private StringBuffer buf = new StringBuffer(); + final private int port; + + public SyslogWriter(String syslogHost, int port) throws UnknownHostException, + SocketException { + this.address = InetAddress.getByName(syslogHost); + this.port = port; + this.ds = new DatagramSocket(); + } + + public void write(char[] charArray, int offset, int len) throws IOException { + buf.append(charArray, offset, len); + } + + public void write(String str) throws IOException { + buf.append(str); + + } + + public void flush() throws IOException { + byte[] bytes = buf.toString().getBytes(); + DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, + port); + + if (this.ds != null) { + ds.send(packet); + } + // clean up for next round + if (buf.length() > MAX_LEN) { + buf = new StringBuffer(); + } else { + buf.setLength(0); + } + } + + public void close() { + address = null; + ds = null; + } + + public int getPort() { + return port; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/TelnetAppender.java b/logback-core/src/main/java/ch/qos/logback/core/net/TelnetAppender.java index c9bbb42bb3eb6d0b22042510be920e395fa59374..a97e00023c14af1c98e02d1cea89ecdeff1adbef 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/net/TelnetAppender.java +++ b/logback-core/src/main/java/ch/qos/logback/core/net/TelnetAppender.java @@ -1,49 +1,49 @@ -/** - * 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.net; - -import ch.qos.logback.core.AppenderBase; - -public class TelnetAppender extends AppenderBase { - - int port; - - @Override - public void start() { - int errorCount = 0; - if (port == 0) { - errorCount++; - addError("No port was configured for appender" - + name - + " For more information, please visit http://logback.qos.ch/codes.html#socket_no_port"); - } - - //ServerSocket serverSocket = new ServerSocket(port); - -// connect(address, port); - - if (errorCount == 0) { - this.started = true; - } - } - - @Override - protected void append(Object eventObject) { - // TODO Auto-generated method stub - - } - - - -} +/** + * 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.net; + +import ch.qos.logback.core.AppenderBase; + +public class TelnetAppender extends AppenderBase { + + int port; + + @Override + public void start() { + int errorCount = 0; + if (port == 0) { + errorCount++; + addError("No port was configured for appender" + + name + + " For more information, please visit http://logback.qos.ch/codes.html#socket_no_port"); + } + + //ServerSocket serverSocket = new ServerSocket(port); + +// connect(address, port); + + if (errorCount == 0) { + this.started = true; + } + } + + @Override + protected void append(Object eventObject) { + // TODO Auto-generated method stub + + } + + + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/package.html b/logback-core/src/main/java/ch/qos/logback/core/net/package.html index 26ca4620fd770f7493a2e60a5dc109eeba70a860..9e93088c69eaf5810486127eba52df63bc3656d7 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/net/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/net/package.html @@ -1,17 +1,17 @@ - - - - - - - - - -

Contains the base classes used by logback to log to remote -destinations.

- -

SMTPAppender logs events and sends an email when appropriate. -SyslogAppender logs to a Syslog deamon.

- - - + + + + + + + + + +

Contains the base classes used by logback to log to remote +destinations.

+ +

SMTPAppender logs events and sends an email when appropriate. +SyslogAppender logs to a Syslog deamon.

+ + + diff --git a/logback-core/src/main/java/ch/qos/logback/core/package.html b/logback-core/src/main/java/ch/qos/logback/core/package.html index a8c3e7fdbb10e5e736fb7694eddeae27e72651b0..608e010fdb79548cc303c076074a727b79593d8c 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains the main classes of logback core.

- - + + + + + + + + + +

Contains the main classes of logback core.

+ + \ No newline at end of file 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 c812d80e13cd0808b0b2ce635b4a7a6d711473a0..824a349c852e198e25f31906afeaf983371d3459 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,51 +1,51 @@ -/** - * 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; - -public class CompositeConverter extends FormattingConverter { - - StringBuffer buf = new StringBuffer(); - Converter childConverter; - - public String convert(E event) { - if (buf.capacity() > MAX_CAPACITY) { - buf = new StringBuffer(INITIAL_BUF_SIZE); - } else { - buf.setLength(0); - } - - for (Converter c = childConverter; c != null; c = c.next) { - c.write(buf, event); - } - return buf.toString(); - } - - public void setChildConverter(Converter child) { - childConverter = child; - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append("CompositeConverter<"); - - if(formattingInfo != null) - buf.append(formattingInfo); - - if (childConverter != null) { - buf.append(", children: "+childConverter); - } - buf.append(">"); - 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; + +public class CompositeConverter extends FormattingConverter { + + StringBuffer buf = new StringBuffer(); + Converter childConverter; + + public String convert(E event) { + if (buf.capacity() > MAX_CAPACITY) { + buf = new StringBuffer(INITIAL_BUF_SIZE); + } else { + buf.setLength(0); + } + + for (Converter c = childConverter; c != null; c = c.next) { + c.write(buf, event); + } + return buf.toString(); + } + + public void setChildConverter(Converter child) { + childConverter = child; + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("CompositeConverter<"); + + if(formattingInfo != null) + buf.append(formattingInfo); + + if (childConverter != null) { + buf.append(", children: "+childConverter); + } + buf.append(">"); + return buf.toString(); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/Converter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/Converter.java index 894dde3daf1fbe13c4dcdfc43ccac66f0472bfaa..5a140d8462fc6739ece58d58d23411437d89b60b 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/Converter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/Converter.java @@ -1,55 +1,55 @@ -/** - * 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; - -/** - * A minimal converter which sets up the general interface for derived classes. - * It also implements the functionality to chain converters in a linked list. - * - * @author ceki - */ -abstract public class Converter { - - Converter next; - - /** - * The convert method is responsible for extracting data from the event and - * storing it for later use by the write method. - * - * @param event - */ - public abstract String convert(E event); - - /** - * In its simplest incarnation, a convert simply appends the data extracted from - * the event to the buffer passed as parameter. - * - * @param buf The input buffer where data is appended - * @param event The event from where data is extracted - */ - public void write(StringBuffer buf, E event) { - buf.append(convert(event)); - } - - public final void setNext(Converter next) { - if (this.next != null) { - throw new IllegalStateException("Next converter has been already set"); - } - this.next = next; - } - - public final Converter getNext() { - return next; - } -} +/** + * 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; + +/** + * A minimal converter which sets up the general interface for derived classes. + * It also implements the functionality to chain converters in a linked list. + * + * @author ceki + */ +abstract public class Converter { + + Converter next; + + /** + * The convert method is responsible for extracting data from the event and + * storing it for later use by the write method. + * + * @param event + */ + public abstract String convert(E event); + + /** + * In its simplest incarnation, a convert simply appends the data extracted from + * the event to the buffer passed as parameter. + * + * @param buf The input buffer where data is appended + * @param event The event from where data is extracted + */ + public void write(StringBuffer buf, E event) { + buf.append(convert(event)); + } + + public final void setNext(Converter next) { + if (this.next != null) { + throw new IllegalStateException("Next converter has been already set"); + } + this.next = next; + } + + public final Converter getNext() { + return next; + } +} 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 de2f8b62bdea7efe02216e47e1c72587cc8e47e2..19c8628655c5ff8af25883a8afc4f28e2ad9bf45 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 @@ -1,50 +1,50 @@ -/** - * 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; - -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 cc = (CompositeConverter) c; - Converter childConverter = cc.childConverter; - startConverters(childConverter); - } - c = c.getNext(); - } - } - - - public static Converter findTail(Converter head) { - Converter c = head; - while (c != null) { - Converter next = c.getNext(); - if (next == null) { - break; - } else { - c = next; - } - } - return c; - } -} +/** + * 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; + +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 cc = (CompositeConverter) c; + Converter childConverter = cc.childConverter; + startConverters(childConverter); + } + c = c.getNext(); + } + } + + + public static Converter findTail(Converter head) { + Converter c = head; + while (c != null) { + Converter next = c.getNext(); + if (next == null) { + break; + } else { + c = next; + } + } + return c; + } +} 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 9dce2f2a5f7315ce19391a7c5295975e723d0498..9e0f5165fc17f2ff4c971feac38e929bea4de2d3 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 @@ -1,70 +1,70 @@ -/** - * 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; - -import java.util.List; - -import ch.qos.logback.core.spi.LifeCycle; - -abstract public class DynamicConverter extends FormattingConverter - implements LifeCycle { - - // Contains a list of option Strings. - private List optionList; - - /** - * Is this component active? - */ - boolean started = false; - - /** - * Components that depend on options passed during configuration can override - * this method in order to make appropriate use of those options. For simpler - * components, the trivial implementation found in this abstract class will be - * sufficient. - */ - public void start() { - started = true; - } - - public void stop() { - started = false; - } - - public boolean isStarted() { - return started; - } - - public void setOptionList(List optionList) { - this.optionList = optionList; - } - - /** - * Return the first option passed to this component. The returned value may be - * null if there are no options. - * - * @return First option, may be null. - */ - protected String getFirstOption() { - if (optionList == null || optionList.size() == 0) { - return null; - } else { - return (String) optionList.get(0); - } - } - - protected List getOptionList() { - return optionList; - } -} +/** + * 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; + +import java.util.List; + +import ch.qos.logback.core.spi.LifeCycle; + +abstract public class DynamicConverter extends FormattingConverter + implements LifeCycle { + + // Contains a list of option Strings. + private List optionList; + + /** + * Is this component active? + */ + boolean started = false; + + /** + * Components that depend on options passed during configuration can override + * this method in order to make appropriate use of those options. For simpler + * components, the trivial implementation found in this abstract class will be + * sufficient. + */ + public void start() { + started = true; + } + + public void stop() { + started = false; + } + + public boolean isStarted() { + return started; + } + + public void setOptionList(List optionList) { + this.optionList = optionList; + } + + /** + * Return the first option passed to this component. The returned value may be + * null if there are no options. + * + * @return First option, may be null. + */ + protected String getFirstOption() { + if (optionList == null || optionList.size() == 0) { + return null; + } else { + return (String) optionList.get(0); + } + } + + protected List getOptionList() { + return optionList; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/FormatInfo.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/FormatInfo.java index 1717f196a29a5055f9e3abc6900b53ca51bc4b65..a42436108083f57d92d180dcc2962648896b134e 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/FormatInfo.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/FormatInfo.java @@ -1,146 +1,146 @@ -/** - * 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; - -/** - * FormattingInfo instances contain the information obtained when parsing - * formatting modifiers in conversion modifiers. - * - * @author Ceki Gülcü - */ -public class FormatInfo { - private int min = Integer.MIN_VALUE; - private int max = Integer.MAX_VALUE; - private boolean leftPad = true; - private boolean leftTruncate = true; - - public FormatInfo() { - } - - public FormatInfo(int min, int max) { - this.min = min; - this.max = max; - } - - public FormatInfo(int min, int max, boolean leftPad, boolean leftTruncate) { - this.min = min; - this.max = max; - this.leftPad = leftPad; - this.leftTruncate = leftTruncate; - } - - /** - * This method is used to parse a string such as "5", ".7", "5.7" or "-5.7" into - * a FormatInfo. - * - * @param str A String to convert into a FormatInfo object - * @return A newly created and approprioately initialized FormatInfo object. - * @throws IllegalArgumentException - */ - public static FormatInfo valueOf(String str) throws IllegalArgumentException { - if (str == null) { - new NullPointerException("Argument cannot be null"); - } - - FormatInfo fi = new FormatInfo(); - - int indexOfDot = str.indexOf('.'); - String minPart = null; - String maxPart = null; - if (indexOfDot != -1) { - minPart = str.substring(0, indexOfDot); - if (indexOfDot + 1 == str.length()) { - throw new IllegalArgumentException("Formatting string [" + str - + "] should not end with '.'"); - } else { - maxPart = str.substring(indexOfDot + 1); - } - } else { - minPart = str; - } - - if (minPart != null && minPart.length() > 0) { - int min = Integer.parseInt(minPart); - if (min >= 0) { - fi.min = min; - } else { - fi.min = -min; - fi.leftPad = false; - } - } - - if (maxPart != null && maxPart.length() > 0) { - int max = Integer.parseInt(maxPart); - if (max >= 0) { - fi.max = max; - } else { - fi.max = -max; - fi.leftTruncate = false; - } - } - - return fi; - - } - - public boolean isLeftPad() { - return leftPad; - } - - public void setLeftPad(boolean leftAlign) { - this.leftPad = leftAlign; - } - - public int getMax() { - return max; - } - - public void setMax(int max) { - this.max = max; - } - - public int getMin() { - return min; - } - - public void setMin(int min) { - this.min = min; - } - - public boolean isLeftTruncate() { - return leftTruncate; - } - - public void setLeftTruncate(boolean leftTruncate) { - this.leftTruncate = leftTruncate; - } - - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof FormatInfo)) { - return false; - } - FormatInfo r = (FormatInfo) o; - - return (min == r.min) && (max == r.max) && (leftPad == r.leftPad) - && (leftTruncate == r.leftTruncate); - } - - public String toString() { - return "FormatInfo(" + min + ", " + max + ", " + leftPad + ", " - + leftTruncate + ")"; - } +/** + * 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; + +/** + * FormattingInfo instances contain the information obtained when parsing + * formatting modifiers in conversion modifiers. + * + * @author Ceki Gülcü + */ +public class FormatInfo { + private int min = Integer.MIN_VALUE; + private int max = Integer.MAX_VALUE; + private boolean leftPad = true; + private boolean leftTruncate = true; + + public FormatInfo() { + } + + public FormatInfo(int min, int max) { + this.min = min; + this.max = max; + } + + public FormatInfo(int min, int max, boolean leftPad, boolean leftTruncate) { + this.min = min; + this.max = max; + this.leftPad = leftPad; + this.leftTruncate = leftTruncate; + } + + /** + * This method is used to parse a string such as "5", ".7", "5.7" or "-5.7" into + * a FormatInfo. + * + * @param str A String to convert into a FormatInfo object + * @return A newly created and approprioately initialized FormatInfo object. + * @throws IllegalArgumentException + */ + public static FormatInfo valueOf(String str) throws IllegalArgumentException { + if (str == null) { + new NullPointerException("Argument cannot be null"); + } + + FormatInfo fi = new FormatInfo(); + + int indexOfDot = str.indexOf('.'); + String minPart = null; + String maxPart = null; + if (indexOfDot != -1) { + minPart = str.substring(0, indexOfDot); + if (indexOfDot + 1 == str.length()) { + throw new IllegalArgumentException("Formatting string [" + str + + "] should not end with '.'"); + } else { + maxPart = str.substring(indexOfDot + 1); + } + } else { + minPart = str; + } + + if (minPart != null && minPart.length() > 0) { + int min = Integer.parseInt(minPart); + if (min >= 0) { + fi.min = min; + } else { + fi.min = -min; + fi.leftPad = false; + } + } + + if (maxPart != null && maxPart.length() > 0) { + int max = Integer.parseInt(maxPart); + if (max >= 0) { + fi.max = max; + } else { + fi.max = -max; + fi.leftTruncate = false; + } + } + + return fi; + + } + + public boolean isLeftPad() { + return leftPad; + } + + public void setLeftPad(boolean leftAlign) { + this.leftPad = leftAlign; + } + + public int getMax() { + return max; + } + + public void setMax(int max) { + this.max = max; + } + + public int getMin() { + return min; + } + + public void setMin(int min) { + this.min = min; + } + + public boolean isLeftTruncate() { + return leftTruncate; + } + + public void setLeftTruncate(boolean leftTruncate) { + this.leftTruncate = leftTruncate; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof FormatInfo)) { + return false; + } + FormatInfo r = (FormatInfo) o; + + return (min == r.min) && (max == r.max) && (leftPad == r.leftPad) + && (leftTruncate == r.leftTruncate); + } + + public String toString() { + return "FormatInfo(" + min + ", " + max + ", " + leftPad + ", " + + leftTruncate + ")"; + } } \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/FormattingConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/FormattingConverter.java index fe58ff2cdb056cf0f9d1b46a5305c6ec5b7c2bda..b228d0de7c942596523791ec9a2124bb47ba72c7 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/FormattingConverter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/FormattingConverter.java @@ -1,71 +1,71 @@ -/** - * 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; - -abstract public class FormattingConverter extends Converter { - - static final int INITIAL_BUF_SIZE = 256; - static final int MAX_CAPACITY = 1024; - - - FormatInfo formattingInfo; - - final public FormatInfo getFormattingInfo() { - return formattingInfo; - } - - final public void setFormattingInfo(FormatInfo formattingInfo) { - if (this.formattingInfo != null) { - throw new IllegalStateException("FormattingInfo has been already set"); - } - this.formattingInfo = formattingInfo; - } - - final public void write(StringBuffer buf, E event) { - String s = convert(event); - - if(formattingInfo == null) { - buf.append(s); - return; - } - - int min = formattingInfo.getMin(); - int max = formattingInfo.getMax(); - - - if (s == null) { - if (0 < min) - SpacePadder.spacePad(buf, min); - return; - } - - int len = s.length(); - - if (len > max) { - if(formattingInfo.isLeftTruncate()) { - buf.append(s.substring(len - max)); - } else { - buf.append(s.substring(0, max)); - } - } else if (len < min) { - if (formattingInfo.isLeftPad()) { - SpacePadder.leftPad(buf, s, min); - } else { - SpacePadder.rightPad(buf, s, min); - } - } else { - buf.append(s); - } - } -} +/** + * 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; + +abstract public class FormattingConverter extends Converter { + + static final int INITIAL_BUF_SIZE = 256; + static final int MAX_CAPACITY = 1024; + + + FormatInfo formattingInfo; + + final public FormatInfo getFormattingInfo() { + return formattingInfo; + } + + final public void setFormattingInfo(FormatInfo formattingInfo) { + if (this.formattingInfo != null) { + throw new IllegalStateException("FormattingInfo has been already set"); + } + this.formattingInfo = formattingInfo; + } + + final public void write(StringBuffer buf, E event) { + String s = convert(event); + + if(formattingInfo == null) { + buf.append(s); + return; + } + + int min = formattingInfo.getMin(); + int max = formattingInfo.getMax(); + + + if (s == null) { + if (0 < min) + SpacePadder.spacePad(buf, min); + return; + } + + int len = s.length(); + + if (len > max) { + if(formattingInfo.isLeftTruncate()) { + buf.append(s.substring(len - max)); + } else { + buf.append(s.substring(0, max)); + } + } else if (len < min) { + if (formattingInfo.isLeftPad()) { + SpacePadder.leftPad(buf, s, min); + } else { + SpacePadder.rightPad(buf, s, min); + } + } else { + buf.append(s); + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/LiteralConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/LiteralConverter.java index 27e083e07564899dfcc0df80fab6ae2cfc513c24..546adc50bae4dfa7da14981e26f18e7478af089d 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/LiteralConverter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/LiteralConverter.java @@ -1,29 +1,29 @@ -/** - * 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; - -public final class LiteralConverter extends Converter { - - String literal; - - public LiteralConverter(String literal) { - this.literal = literal; - } - - public String convert(E o) { - return literal; - } - - -} +/** + * 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; + +public final class LiteralConverter extends Converter { + + String literal; + + public LiteralConverter(String literal) { + this.literal = literal; + } + + public String convert(E o) { + return literal; + } + + +} 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 cb6f795b170c205e0676d8d1bde12d403c9cb2b6..021048423703da9bfbe77e1bf587e07b1d70f5e5 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 @@ -1,135 +1,135 @@ -/** - * 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; - -import java.util.HashMap; -import java.util.Map; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.LayoutBase; -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.spi.ContextAware; -import ch.qos.logback.core.status.ErrorStatus; -import ch.qos.logback.core.status.StatusManager; - -abstract public class PatternLayoutBase extends LayoutBase { - - Converter head; - String pattern; - protected PostCompileProcessor postCompileProcessor; - - Map instanceConverterMap = new HashMap(); - - /** - * Concrete implementations of this class are responsible for elaborating the - * mapping between pattern words and converters. - * - * @return A map associating pattern words to the names of converter classes - */ - abstract public Map getDefaultConverterMap(); - - /** - * Returns a map where the default converter map is merged with the map - * contained in the context. - */ - public Map getEffectiveConverterMap() { - Map effectiveMap = new HashMap(); - - // add the least specific map fist - Map defaultMap = getDefaultConverterMap(); - if (defaultMap != null) { - effectiveMap.putAll(defaultMap); - } - - // contextMap is more specific than the default map - Context context = getContext(); - if (context != null) { - @SuppressWarnings("unchecked") - Map contextMap = (Map) context - .getObject(CoreConstants.PATTERN_RULE_REGISTRY); - if (contextMap != null) { - effectiveMap.putAll(contextMap); - } - } - // set the most specific map last - effectiveMap.putAll(instanceConverterMap); - return effectiveMap; - } - - public void start() { - try { - Parser p = new Parser(pattern); - if (getContext() != null) { - p.setContext(getContext()); - } - Node t = p.parse(); - this.head = p.compile(t, getEffectiveConverterMap()); - if (postCompileProcessor != null) { - postCompileProcessor.process(head); - } - setContextForConverters(head); - ConverterUtil.startConverters(this.head); - super.start(); - } catch (ScanException sce) { - StatusManager sm = getContext().getStatusManager(); - sm.add(new ErrorStatus("Failed to parse pattern \"" + getPattern() - + "\".", this, sce)); - } - } - - public void setPostCompileProcessor( - PostCompileProcessor postCompileProcessor) { - this.postCompileProcessor = postCompileProcessor; - } - - protected void setContextForConverters(Converter head) { - Context context = getContext(); - Converter c = head; - while (c != null) { - if (c instanceof ContextAware) { - ((ContextAware) c).setContext(context); - } - c = c.getNext(); - } - } - - protected String writeLoopOnConverters(E event) { - StringBuffer buf = new StringBuffer(128); - Converter c = head; - while (c != null) { - c.write(buf, event); - c = c.getNext(); - } - return buf.toString(); - } - - public String getPattern() { - return pattern; - } - - public void setPattern(String pattern) { - this.pattern = pattern; - } - - public String toString() { - return this.getClass().getName() + "(" + getPattern() + ")"; - } - - public Map getInstanceConverterMap() { - return instanceConverterMap; - } -} +/** + * 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; + +import java.util.HashMap; +import java.util.Map; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.LayoutBase; +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.spi.ContextAware; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.StatusManager; + +abstract public class PatternLayoutBase extends LayoutBase { + + Converter head; + String pattern; + protected PostCompileProcessor postCompileProcessor; + + Map instanceConverterMap = new HashMap(); + + /** + * Concrete implementations of this class are responsible for elaborating the + * mapping between pattern words and converters. + * + * @return A map associating pattern words to the names of converter classes + */ + abstract public Map getDefaultConverterMap(); + + /** + * Returns a map where the default converter map is merged with the map + * contained in the context. + */ + public Map getEffectiveConverterMap() { + Map effectiveMap = new HashMap(); + + // add the least specific map fist + Map defaultMap = getDefaultConverterMap(); + if (defaultMap != null) { + effectiveMap.putAll(defaultMap); + } + + // contextMap is more specific than the default map + Context context = getContext(); + if (context != null) { + @SuppressWarnings("unchecked") + Map contextMap = (Map) context + .getObject(CoreConstants.PATTERN_RULE_REGISTRY); + if (contextMap != null) { + effectiveMap.putAll(contextMap); + } + } + // set the most specific map last + effectiveMap.putAll(instanceConverterMap); + return effectiveMap; + } + + public void start() { + try { + Parser p = new Parser(pattern); + if (getContext() != null) { + p.setContext(getContext()); + } + Node t = p.parse(); + this.head = p.compile(t, getEffectiveConverterMap()); + if (postCompileProcessor != null) { + postCompileProcessor.process(head); + } + setContextForConverters(head); + ConverterUtil.startConverters(this.head); + super.start(); + } catch (ScanException sce) { + StatusManager sm = getContext().getStatusManager(); + sm.add(new ErrorStatus("Failed to parse pattern \"" + getPattern() + + "\".", this, sce)); + } + } + + public void setPostCompileProcessor( + PostCompileProcessor postCompileProcessor) { + this.postCompileProcessor = postCompileProcessor; + } + + protected void setContextForConverters(Converter head) { + Context context = getContext(); + Converter c = head; + while (c != null) { + if (c instanceof ContextAware) { + ((ContextAware) c).setContext(context); + } + c = c.getNext(); + } + } + + protected String writeLoopOnConverters(E event) { + StringBuffer buf = new StringBuffer(128); + Converter c = head; + while (c != null) { + c.write(buf, event); + c = c.getNext(); + } + return buf.toString(); + } + + public String getPattern() { + return pattern; + } + + public void setPattern(String pattern) { + this.pattern = pattern; + } + + public String toString() { + return this.getClass().getName() + "(" + getPattern() + ")"; + } + + public Map getInstanceConverterMap() { + return instanceConverterMap; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/PostCompileProcessor.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/PostCompileProcessor.java index bc1125b9e102767a5099f078bd40a01364cb6990..a61ca2e4a584c456fd50c425d2e0e321f658e047 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/PostCompileProcessor.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/PostCompileProcessor.java @@ -1,34 +1,34 @@ -/** - * 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; - - -/** - * Implements this to perform post compile processing for a PatternLayout. - * - * For example, PatternLayot in the classic module should add a converter for - * exception handling (otherwise exceptions would not be printed). - * - * @author Ceki Gulcu - */ -public interface PostCompileProcessor { - - /** - * Post compile processing of the converter chain. - * - * @param head - * The first converter in the chain - */ - void process(Converter head); -} +/** + * 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; + + +/** + * Implements this to perform post compile processing for a PatternLayout. + * + * For example, PatternLayot in the classic module should add a converter for + * exception handling (otherwise exceptions would not be printed). + * + * @author Ceki Gulcu + */ +public interface PostCompileProcessor { + + /** + * Post compile processing of the converter chain. + * + * @param head + * The first converter in the chain + */ + void process(Converter head); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/SpacePadder.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/SpacePadder.java index 7ad99ed28e649ee4a577fa62cb8d19aed31068a5..b7b444ec515abec685375ba287911c573cb9b940 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/SpacePadder.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/SpacePadder.java @@ -1,64 +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; - -public class SpacePadder { - - final static String[] SPACES = { " ", " ", " ", " ", // 1,2,4,8 - // spaces - " ", // 16 spaces - " " }; // 32 spaces - - final static public void leftPad(StringBuffer buf, String s, int desiredLength) { - int actualLen = 0; - if (s != null) { - actualLen = s.length(); - } - if (actualLen < desiredLength) { - spacePad(buf, desiredLength - actualLen); - } - if (s != null) { - buf.append(s); - } - } - - final static public void rightPad(StringBuffer buf, String s, int desiredLength) { - int actualLen = 0; - if (s != null) { - actualLen = s.length(); - } - if (s != null) { - buf.append(s); - } - if (actualLen < desiredLength) { - spacePad(buf, desiredLength - actualLen); - } - } - - /** - * Fast space padding method. - */ - final static public void spacePad(StringBuffer sbuf, int length) { - while (length >= 32) { - sbuf.append(SPACES[5]); - length -= 32; - } - - for (int i = 4; i >= 0; i--) { - if ((length & (1 << i)) != 0) { - sbuf.append(SPACES[i]); - } - } - } -} +/** + * 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; + +public class SpacePadder { + + final static String[] SPACES = { " ", " ", " ", " ", // 1,2,4,8 + // spaces + " ", // 16 spaces + " " }; // 32 spaces + + final static public void leftPad(StringBuffer buf, String s, int desiredLength) { + int actualLen = 0; + if (s != null) { + actualLen = s.length(); + } + if (actualLen < desiredLength) { + spacePad(buf, desiredLength - actualLen); + } + if (s != null) { + buf.append(s); + } + } + + final static public void rightPad(StringBuffer buf, String s, int desiredLength) { + int actualLen = 0; + if (s != null) { + actualLen = s.length(); + } + if (s != null) { + buf.append(s); + } + if (actualLen < desiredLength) { + spacePad(buf, desiredLength - actualLen); + } + } + + /** + * Fast space padding method. + */ + final static public void spacePad(StringBuffer sbuf, int length) { + while (length >= 32) { + sbuf.append(SPACES[5]); + length -= 32; + } + + for (int i = 4; i >= 0; i--) { + if ((length & (1 << i)) != 0) { + sbuf.append(SPACES[i]); + } + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/package.html b/logback-core/src/main/java/ch/qos/logback/core/pattern/package.html index 4ad405fec58ae681f5ba132ef5fa2bd83dbb7f10..a9526beb021c244da59674688635b9b144f4241b 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/package.html @@ -1,17 +1,17 @@ - - - - - - - - - -

Contains the base classes used by PatternLayout.

- -

These classes lay the groundwork so that subclasses of PatternLayoutBase - can use module-specific patterns. -

- - + + + + + + + + + +

Contains the base classes used by PatternLayout.

+ +

These classes lay the groundwork so that subclasses of PatternLayoutBase + can use module-specific patterns. +

+ + \ No newline at end of file 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 0fb842041b8614f3ff522957b303c4d51f5f61ea..7b5512a4654be8ecb66bc02b37de3ccf02c4dc3f 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 @@ -1,124 +1,124 @@ -/** - * 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.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.spi.ContextAwareBase; -import ch.qos.logback.core.status.ErrorStatus; -import ch.qos.logback.core.util.OptionHelper; - -class Compiler extends ContextAwareBase { - - Converter head; - Converter tail; - final Node top; - final Map converterMap; - - Compiler(final Node top, final Map converterMap) { - this.top = top; - this.converterMap = converterMap; - } - - Converter compile() { - head = tail = null; - for (Node n = top; n != null; n = n.next) { - switch (n.type) { - case Node.LITERAL: - addToList(new LiteralConverter((String) n.getValue())); - break; - case Node.COMPOSITE: - CompositeNode cn = (CompositeNode) n; - CompositeConverter compositeConverter = new CompositeConverter(); - compositeConverter.setFormattingInfo(cn.getFormatInfo()); - Compiler childCompiler = new Compiler(cn.getChildNode(), - converterMap); - childCompiler.setContext(context); - Converter childConverter = childCompiler.compile(); - compositeConverter.setChildConverter(childConverter); - addToList(compositeConverter); - break; - case Node.KEYWORD: - KeywordNode kn = (KeywordNode) n; - DynamicConverter 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 errConveter = new LiteralConverter("%PARSER_ERROR_" - + kn.getValue()); - addStatus(new ErrorStatus("[" + kn.getValue() - + "] is not a valid conversion word", this)); - addToList(errConveter); - } - - } - } - return head; - } - - private void addToList(Converter c) { - if (head == null) { - head = tail = c; - } else { - tail.setNext(c); - tail = c; - } - } - - /** - * Attempt to create a converter using the information found in - * 'converterMap'. - * - * @param kn - * @return - */ - @SuppressWarnings("unchecked") - DynamicConverter createConverter(KeywordNode kn) { - String keyword = (String) kn.getValue(); - String converterClassStr = (String) converterMap.get(keyword); - - if (converterClassStr != null) { - try { - return (DynamicConverter) OptionHelper.instantiateByClassName( - converterClassStr, DynamicConverter.class, context); - } catch (Exception e) { - addError("Failed to instantiate converter class [" + converterClassStr - + "]", e); - return null; - } - } else { - addError("There is no conversion class registered for conversion word [" - + keyword + "]"); - return null; - } - } - - // public void setStatusManager(StatusManager statusManager) { - // this.statusManager = statusManager; - // } - // - // void addStatus(Status status) { - // if(statusManager != null) { - // statusManager.add(status); - // } - // } +/** + * 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.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.spi.ContextAwareBase; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.util.OptionHelper; + +class Compiler extends ContextAwareBase { + + Converter head; + Converter tail; + final Node top; + final Map converterMap; + + Compiler(final Node top, final Map converterMap) { + this.top = top; + this.converterMap = converterMap; + } + + Converter compile() { + head = tail = null; + for (Node n = top; n != null; n = n.next) { + switch (n.type) { + case Node.LITERAL: + addToList(new LiteralConverter((String) n.getValue())); + break; + case Node.COMPOSITE: + CompositeNode cn = (CompositeNode) n; + CompositeConverter compositeConverter = new CompositeConverter(); + compositeConverter.setFormattingInfo(cn.getFormatInfo()); + Compiler childCompiler = new Compiler(cn.getChildNode(), + converterMap); + childCompiler.setContext(context); + Converter childConverter = childCompiler.compile(); + compositeConverter.setChildConverter(childConverter); + addToList(compositeConverter); + break; + case Node.KEYWORD: + KeywordNode kn = (KeywordNode) n; + DynamicConverter 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 errConveter = new LiteralConverter("%PARSER_ERROR_" + + kn.getValue()); + addStatus(new ErrorStatus("[" + kn.getValue() + + "] is not a valid conversion word", this)); + addToList(errConveter); + } + + } + } + return head; + } + + private void addToList(Converter c) { + if (head == null) { + head = tail = c; + } else { + tail.setNext(c); + tail = c; + } + } + + /** + * Attempt to create a converter using the information found in + * 'converterMap'. + * + * @param kn + * @return + */ + @SuppressWarnings("unchecked") + DynamicConverter createConverter(KeywordNode kn) { + String keyword = (String) kn.getValue(); + String converterClassStr = (String) converterMap.get(keyword); + + if (converterClassStr != null) { + try { + return (DynamicConverter) OptionHelper.instantiateByClassName( + converterClassStr, DynamicConverter.class, context); + } catch (Exception e) { + addError("Failed to instantiate converter class [" + converterClassStr + + "]", e); + return null; + } + } else { + addError("There is no conversion class registered for conversion word [" + + keyword + "]"); + return null; + } + } + + // public void setStatusManager(StatusManager statusManager) { + // this.statusManager = statusManager; + // } + // + // void addStatus(Status status) { + // if(statusManager != null) { + // statusManager.add(status); + // } + // } } \ No newline at end of file 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 4fe0d9687643feb5b8bc192601dab4b4bd0b9ab3..8fd2029da1bc671048c320eed5036295f3933dfc 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 @@ -1,55 +1,55 @@ -/** - * 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; - -public class CompositeNode extends FormattingNode { - Node childNode; - - CompositeNode() { - super(Node.COMPOSITE); - } - - public Node getChildNode() { - return childNode; - } - - public void setChildNode(Node childNode) { - this.childNode = childNode; - } - - public boolean equals(Object o) { - //System.out.println("CompositeNode.equals()"); - if(!super.equals(o)) { - return false; - } - if (!(o instanceof CompositeNode)) { - return false; - } - CompositeNode r = (CompositeNode) o; - - return (childNode != null) ? childNode.equals(r.childNode) - : (r.childNode == null); - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - if(childNode != null) { - buf.append("CompositeNode("+childNode+")"); - } else { - buf.append("CompositeNode(no child)"); - } - 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; + +public class CompositeNode extends FormattingNode { + Node childNode; + + CompositeNode() { + super(Node.COMPOSITE); + } + + public Node getChildNode() { + return childNode; + } + + public void setChildNode(Node childNode) { + this.childNode = childNode; + } + + public boolean equals(Object o) { + //System.out.println("CompositeNode.equals()"); + if(!super.equals(o)) { + return false; + } + if (!(o instanceof CompositeNode)) { + return false; + } + CompositeNode r = (CompositeNode) o; + + return (childNode != null) ? childNode.equals(r.childNode) + : (r.childNode == null); + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + if(childNode != null) { + buf.append("CompositeNode("+childNode+")"); + } else { + buf.append("CompositeNode(no child)"); + } + buf.append(printNext()); + return buf.toString(); + } } \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/FormattingNode.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/FormattingNode.java index f5fbcc24d8067ba807c85a1c48a84cfffc8f7cae..f0b9b2e1d719c4499a27886f1b15ca4f82d102d4 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/FormattingNode.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/FormattingNode.java @@ -1,51 +1,51 @@ -/** - * 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 ch.qos.logback.core.pattern.FormatInfo; - -public class FormattingNode extends Node { - - FormatInfo formatInfo; - - FormattingNode(int type) { - super(type); - } - - FormattingNode(int type, Object value) { - super(type, value); - } - - public FormatInfo getFormatInfo() { - return formatInfo; - } - - public void setFormatInfo(FormatInfo formatInfo) { - this.formatInfo = formatInfo; - } - - public boolean equals(Object o) { - if (!super.equals(o)) { - return false; - } - - if(!(o instanceof FormattingNode)) { - return false; - } - FormattingNode r = (FormattingNode) o; - - return (formatInfo != null ? formatInfo.equals(r.formatInfo) - : r.formatInfo == null); - } -} +/** + * 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 ch.qos.logback.core.pattern.FormatInfo; + +public class FormattingNode extends Node { + + FormatInfo formatInfo; + + FormattingNode(int type) { + super(type); + } + + FormattingNode(int type, Object value) { + super(type, value); + } + + public FormatInfo getFormatInfo() { + return formatInfo; + } + + public void setFormatInfo(FormatInfo formatInfo) { + this.formatInfo = formatInfo; + } + + public boolean equals(Object o) { + if (!super.equals(o)) { + return false; + } + + if(!(o instanceof FormattingNode)) { + return false; + } + FormattingNode r = (FormattingNode) o; + + return (formatInfo != null ? formatInfo.equals(r.formatInfo) + : r.formatInfo == null); + } +} 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/KeywordNode.java index 79244d90367121d7c3f1d98795cf1f4a3db5f869..3d2879cf5220b7714d407fe2b021db2a799ef676 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/KeywordNode.java @@ -1,60 +1,60 @@ -/** - * 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 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(); + } +} 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 3c490a086c5dd742853ad463204647a2e3f3ff3e..615e2e9a520633953445cdfdd4ea38fef138c77e 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 @@ -1,92 +1,92 @@ -/** - * 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; - -public class Node { - static final int LITERAL = 0; - static final int KEYWORD = 1; - static final int COMPOSITE = 2; - - final int type; - final Object value; - Node next; - - Node(int type) { - this(type, null); - } - - Node(int type, Object value) { - this.type = type; - this.value = value; - } - - /** - * @return Returns the type. - */ - public int getType() { - return type; - } - - /** - * @return Returns the value. - */ - public Object getValue() { - return value; - } - - public Node getNext() { - return next; - } - - public void setNext(Node next) { - this.next = next; - } - - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Node)) { - return false; - } - Node r = (Node) o; - - return (type == r.type) - && (value != null ? value.equals(r.value) : r.value == null) - && (next != null ? next.equals(r.next) : r.next == null); - } - - String printNext() { - if (next != null) { - return " -> " + next; - } else { - return ""; - } - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - switch (type) { - case LITERAL: - buf.append("LITERAL(" + value + ")"); - break; - default: - buf.append(super.toString()); - } - - 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; + +public class Node { + static final int LITERAL = 0; + static final int KEYWORD = 1; + static final int COMPOSITE = 2; + + final int type; + final Object value; + Node next; + + Node(int type) { + this(type, null); + } + + Node(int type, Object value) { + this.type = type; + this.value = value; + } + + /** + * @return Returns the type. + */ + public int getType() { + return type; + } + + /** + * @return Returns the value. + */ + public Object getValue() { + return value; + } + + public Node getNext() { + return next; + } + + public void setNext(Node next) { + this.next = next; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Node)) { + return false; + } + Node r = (Node) o; + + return (type == r.type) + && (value != null ? value.equals(r.value) : r.value == null) + && (next != null ? next.equals(r.next) : r.next == null); + } + + String printNext() { + if (next != null) { + return " -> " + next; + } else { + return ""; + } + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + switch (type) { + case LITERAL: + buf.append("LITERAL(" + value + ")"); + break; + default: + buf.append(super.toString()); + } + + buf.append(printNext()); + + return buf.toString(); + } } \ 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 ac6cbcb22329710e5c6b4293df9aefda3777c4bb..65308dba303dcc03862f5a56592ef7209e2e873f 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 @@ -1,127 +1,127 @@ -/** - * 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.ArrayList; -import java.util.List; - -import ch.qos.logback.core.pattern.util.IEscapeUtil; -import ch.qos.logback.core.pattern.util.RegularEscapeUtil; - -public class OptionTokenizer { - - private final static int EXPECTING_STATE = 0; - private final static int COLLECTING_STATE = 1; - private final static int QUOTED_COLLECTING_STATE = 2; - - private static final char ESCAPE_CHAR = '\\'; - private static final char COMMA_CHAR = ','; - private static final char DOUBLE_QUOTE_CHAR = '"'; - private static final char SINGLE_QUOTE_CHAR = '\''; - - 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 { - List tokenList = new ArrayList(); - StringBuffer buf = new StringBuffer(); - - while (pointer < patternLength) { - char c = pattern.charAt(pointer); - pointer++; - - switch (state) { - case EXPECTING_STATE: - switch (c) { - case ' ': - case '\t': - case '\r': - case '\n': - break; - case SINGLE_QUOTE_CHAR: - case DOUBLE_QUOTE_CHAR: - state = QUOTED_COLLECTING_STATE; - quoteChar = c; - break; - default: - buf.append(c); - state = COLLECTING_STATE; - } - break; - case COLLECTING_STATE: - switch (c) { - case COMMA_CHAR: - tokenList.add(buf.toString().trim()); - buf.setLength(0); - state = EXPECTING_STATE; - break; - default: - buf.append(c); - } - break; - case QUOTED_COLLECTING_STATE: - if (c == quoteChar) { - tokenList.add(buf.toString()); - buf.setLength(0); - state = EXPECTING_STATE; - } else if (c == ESCAPE_CHAR) { - escape(String.valueOf(quoteChar), buf); - } else { - buf.append(c); - } - - break; - } - } - - // EOS - switch (state) { - case EXPECTING_STATE: - break; - case COLLECTING_STATE: - tokenList.add(buf.toString().trim()); - break; - default: - throw new ScanException("Unexpected end of pattern string"); - } - - return tokenList; - } - - void escape(String escapeChars, StringBuffer buf) { - if ((pointer < patternLength)) { - char next = pattern.charAt(pointer++); - escapeUtil.escape(escapeChars, buf, next, pointer); - } - } +/** + * 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.ArrayList; +import java.util.List; + +import ch.qos.logback.core.pattern.util.IEscapeUtil; +import ch.qos.logback.core.pattern.util.RegularEscapeUtil; + +public class OptionTokenizer { + + private final static int EXPECTING_STATE = 0; + private final static int COLLECTING_STATE = 1; + private final static int QUOTED_COLLECTING_STATE = 2; + + private static final char ESCAPE_CHAR = '\\'; + private static final char COMMA_CHAR = ','; + private static final char DOUBLE_QUOTE_CHAR = '"'; + private static final char SINGLE_QUOTE_CHAR = '\''; + + 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 { + List tokenList = new ArrayList(); + StringBuffer buf = new StringBuffer(); + + while (pointer < patternLength) { + char c = pattern.charAt(pointer); + pointer++; + + switch (state) { + case EXPECTING_STATE: + switch (c) { + case ' ': + case '\t': + case '\r': + case '\n': + break; + case SINGLE_QUOTE_CHAR: + case DOUBLE_QUOTE_CHAR: + state = QUOTED_COLLECTING_STATE; + quoteChar = c; + break; + default: + buf.append(c); + state = COLLECTING_STATE; + } + break; + case COLLECTING_STATE: + switch (c) { + case COMMA_CHAR: + tokenList.add(buf.toString().trim()); + buf.setLength(0); + state = EXPECTING_STATE; + break; + default: + buf.append(c); + } + break; + case QUOTED_COLLECTING_STATE: + if (c == quoteChar) { + tokenList.add(buf.toString()); + buf.setLength(0); + state = EXPECTING_STATE; + } else if (c == ESCAPE_CHAR) { + escape(String.valueOf(quoteChar), buf); + } else { + buf.append(c); + } + + break; + } + } + + // EOS + switch (state) { + case EXPECTING_STATE: + break; + case COLLECTING_STATE: + tokenList.add(buf.toString().trim()); + break; + default: + throw new ScanException("Unexpected end of pattern string"); + } + + return tokenList; + } + + void escape(String escapeChars, StringBuffer buf) { + if ((pointer < patternLength)) { + char next = pattern.charAt(pointer++); + escapeUtil.escape(escapeChars, buf, next, pointer); + } + } } \ No newline at end of file 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 793acf8d1812931ac5975d171747d3ae73438143..c0321f029dc2059e028b6e5df75eef3bad7958f9 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 @@ -1,211 +1,211 @@ -/** - * 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; -import java.util.Map; - -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; - - -public class Parser extends ContextAwareBase { - - final List tokenList; - int pointer = 0; - - 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 { - try { - TokenStream ts = new TokenStream(pattern, escapeUtil); - this.tokenList = ts.tokenize(); - } catch (NullPointerException npe) { - throw new ScanException("Failed to initialize Parser", npe); - } - } - - 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 compile(final Node top, Map converterMap) { - Compiler compiler = new Compiler(top, converterMap); - compiler.setContext(context); - //compiler.setStatusManager(statusManager); - return compiler.compile(); - } - - 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; - } - - Node T() throws ScanException { - // System.out.println("in T()"); - Token t = getCurentToken(); - if (t == null) { - throw new IllegalStateException("a LITERAL or '%'"); - } - - // System.out.println("Current token is " + t); - - switch (t.getType()) { - case Token.LITERAL: - advanceTokenPointer(); - return new Node(Node.LITERAL, t.getValue()); - case Token.PERCENT: - advanceTokenPointer(); - // System.out.println("% token found"); - FormatInfo fi; - Token u = getCurentToken(); - FormattingNode c; - expectNotNull(u, "a FORMAT_MODIFIER, KEYWORD or LEFT_PARENTHESIS"); - if (u.getType() == Token.FORMAT_MODIFIER) { - fi = FormatInfo.valueOf((String) u.getValue()); - advanceTokenPointer(); - c = C(); - c.setFormatInfo(fi); - } else { - c = C(); - } - return c; - - default: - return null; - - } - - } - - 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()"); - // System.out.println("Current token is " + t); - expectNotNull(t, "a LEFT_PARENTHESIS or KEYWORD"); - int type = t.getType(); - switch (type) { - case Token.KEYWORD: - return SINGLE(); - case Token.LEFT_PARENTHESIS: - advanceTokenPointer(); - return COMPOSITE(); - default: - throw new IllegalStateException("Unexpected token " + t); - } - } - - FormattingNode SINGLE() throws ScanException { - // System.out.println("in SINGLE()"); - Token t = getNextToken(); - // System.out.println("==" + t); - KeywordNode keywordNode = new KeywordNode(t.getValue()); - - Token ot = getCurentToken(); - if (ot != null && ot.getType() == Token.OPTION) { - List optionList = new OptionTokenizer((String) ot.getValue()).tokenize(); - keywordNode.setOptions(optionList); - advanceTokenPointer(); - } - return keywordNode; - } - - FormattingNode COMPOSITE() throws ScanException { - CompositeNode compositeNode = new CompositeNode(); - - Node childNode = E(); - // System.out.println("Child node: " + childNode); - - compositeNode.setChildNode(childNode); - - Token t = getNextToken(); - // System.out.println("Next token is" + t); - - if (t.getType() != Token.RIGHT_PARENTHESIS) { - throw new IllegalStateException( - "Expecting RIGHT_PARENTHESIS token but got " + t); - } else { - // System.out.println("got expected ')'"); - } - return compositeNode; - } - - Token getNextToken() { - if (pointer < tokenList.size()) { - return (Token) tokenList.get(pointer++); - } - return null; - } - - Token getCurentToken() { - if (pointer < tokenList.size()) { - return (Token) tokenList.get(pointer); - } - return null; - } - - void advanceTokenPointer() { - pointer++; - } - - void expectNotNull(Token t, String expected) { - if (t == null) { - throw new IllegalStateException("All tokens consumed but was expecting " - + expected); - } - } - -// public void setStatusManager(StatusManager statusManager) { -// this.statusManager = statusManager; -// } +/** + * 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; +import java.util.Map; + +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; + + +public class Parser extends ContextAwareBase { + + final List tokenList; + int pointer = 0; + + 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 { + try { + TokenStream ts = new TokenStream(pattern, escapeUtil); + this.tokenList = ts.tokenize(); + } catch (NullPointerException npe) { + throw new ScanException("Failed to initialize Parser", npe); + } + } + + 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 compile(final Node top, Map converterMap) { + Compiler compiler = new Compiler(top, converterMap); + compiler.setContext(context); + //compiler.setStatusManager(statusManager); + return compiler.compile(); + } + + 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; + } + + Node T() throws ScanException { + // System.out.println("in T()"); + Token t = getCurentToken(); + if (t == null) { + throw new IllegalStateException("a LITERAL or '%'"); + } + + // System.out.println("Current token is " + t); + + switch (t.getType()) { + case Token.LITERAL: + advanceTokenPointer(); + return new Node(Node.LITERAL, t.getValue()); + case Token.PERCENT: + advanceTokenPointer(); + // System.out.println("% token found"); + FormatInfo fi; + Token u = getCurentToken(); + FormattingNode c; + expectNotNull(u, "a FORMAT_MODIFIER, KEYWORD or LEFT_PARENTHESIS"); + if (u.getType() == Token.FORMAT_MODIFIER) { + fi = FormatInfo.valueOf((String) u.getValue()); + advanceTokenPointer(); + c = C(); + c.setFormatInfo(fi); + } else { + c = C(); + } + return c; + + default: + return null; + + } + + } + + 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()"); + // System.out.println("Current token is " + t); + expectNotNull(t, "a LEFT_PARENTHESIS or KEYWORD"); + int type = t.getType(); + switch (type) { + case Token.KEYWORD: + return SINGLE(); + case Token.LEFT_PARENTHESIS: + advanceTokenPointer(); + return COMPOSITE(); + default: + throw new IllegalStateException("Unexpected token " + t); + } + } + + FormattingNode SINGLE() throws ScanException { + // System.out.println("in SINGLE()"); + Token t = getNextToken(); + // System.out.println("==" + t); + KeywordNode keywordNode = new KeywordNode(t.getValue()); + + Token ot = getCurentToken(); + if (ot != null && ot.getType() == Token.OPTION) { + List optionList = new OptionTokenizer((String) ot.getValue()).tokenize(); + keywordNode.setOptions(optionList); + advanceTokenPointer(); + } + return keywordNode; + } + + FormattingNode COMPOSITE() throws ScanException { + CompositeNode compositeNode = new CompositeNode(); + + Node childNode = E(); + // System.out.println("Child node: " + childNode); + + compositeNode.setChildNode(childNode); + + Token t = getNextToken(); + // System.out.println("Next token is" + t); + + if (t.getType() != Token.RIGHT_PARENTHESIS) { + throw new IllegalStateException( + "Expecting RIGHT_PARENTHESIS token but got " + t); + } else { + // System.out.println("got expected ')'"); + } + return compositeNode; + } + + Token getNextToken() { + if (pointer < tokenList.size()) { + return (Token) tokenList.get(pointer++); + } + return null; + } + + Token getCurentToken() { + if (pointer < tokenList.size()) { + return (Token) tokenList.get(pointer); + } + return null; + } + + void advanceTokenPointer() { + pointer++; + } + + void expectNotNull(Token t, String expected) { + if (t == null) { + throw new IllegalStateException("All tokens consumed but was expecting " + + expected); + } + } + +// public void setStatusManager(StatusManager statusManager) { +// this.statusManager = statusManager; +// } } \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/ScanException.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/ScanException.java index 190729fce98a812ab07651c9908ef27470b18cad..f38d9e8bad7d3229509b8319ded32230bc596c77 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/ScanException.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/ScanException.java @@ -1,35 +1,35 @@ -/** - * 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; - -public class ScanException extends Exception { - - private static final long serialVersionUID = -3132040414328475658L; - - Throwable cause; - - public ScanException(String msg) { - super(msg); - } - - public ScanException(String msg, Throwable rootCause) { - super(msg); - this.cause = rootCause; - } - - public Throwable getCause() { - return cause; - } -} - +/** + * 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; + +public class ScanException extends Exception { + + private static final long serialVersionUID = -3132040414328475658L; + + Throwable cause; + + public ScanException(String msg) { + super(msg); + } + + public ScanException(String msg, Throwable rootCause) { + super(msg); + this.cause = rootCause; + } + + public Throwable getCause() { + return cause; + } +} + 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 0653f65298e98d7b1288064ff9242a4638d895b6..2965a1c00eb743636c47f6dc4afdbcec737a7458 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 @@ -1,114 +1,114 @@ -/** - * 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; - -class Token { - - static final int PERCENT = 37; - static final int LEFT_PARENTHESIS = 40; - static final int RIGHT_PARENTHESIS = 41; - static final int MINUS = 45; - static final int DOT = 46; - static final int CURLY_LEFT = 123; - 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 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 PERCENT_TOKEN = new Token(PERCENT); - - private final int type; - private final Object value; - - - public Token(int type) { - this(type, null); - } - - public Token(int type, Object value) { - this.type = type; - this.value = value; - } - - public int getType() { - return type; - } - - public Object getValue() { - return value; - } - - - public String toString() { - String typeStr = null; - switch (type) { - - case PERCENT: - typeStr = "%"; - break; - case FORMAT_MODIFIER: - typeStr = "FormatModifier"; - break; - case LITERAL: - typeStr = "LITERAL"; - break; - case OPTION: - typeStr = "OPTION"; - break; - case KEYWORD: - typeStr = "KEYWORD"; - break; - case RIGHT_PARENTHESIS: - typeStr = "RIGHT_PARENTHESIS"; - break; - case LEFT_PARENTHESIS: - typeStr = "LEFT_PARENTHESIS"; - break; - default: - typeStr = "UNKNOWN"; - } - if (value == null) { - return "Token(" + typeStr + ")"; - - } else { - return "Token(" + typeStr + ", \"" + value + "\")"; - } - } - - public int hashCode() { - int result; - result = type; - result = 29 * result + (value != null ? value.hashCode() : 0); - return result; - } - - - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Token)) return false; - - final Token token = (Token) o; - - if (type != token.type) return false; - if (value != null ? !value.equals(token.value) : token.value != null) return false; - - return true; - } -} +/** + * 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; + +class Token { + + static final int PERCENT = 37; + static final int LEFT_PARENTHESIS = 40; + static final int RIGHT_PARENTHESIS = 41; + static final int MINUS = 45; + static final int DOT = 46; + static final int CURLY_LEFT = 123; + 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 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 PERCENT_TOKEN = new Token(PERCENT); + + private final int type; + private final Object value; + + + public Token(int type) { + this(type, null); + } + + public Token(int type, Object value) { + this.type = type; + this.value = value; + } + + public int getType() { + return type; + } + + public Object getValue() { + return value; + } + + + public String toString() { + String typeStr = null; + switch (type) { + + case PERCENT: + typeStr = "%"; + break; + case FORMAT_MODIFIER: + typeStr = "FormatModifier"; + break; + case LITERAL: + typeStr = "LITERAL"; + break; + case OPTION: + typeStr = "OPTION"; + break; + case KEYWORD: + typeStr = "KEYWORD"; + break; + case RIGHT_PARENTHESIS: + typeStr = "RIGHT_PARENTHESIS"; + break; + case LEFT_PARENTHESIS: + typeStr = "LEFT_PARENTHESIS"; + break; + default: + typeStr = "UNKNOWN"; + } + if (value == null) { + return "Token(" + typeStr + ")"; + + } else { + return "Token(" + typeStr + ", \"" + value + "\")"; + } + } + + public int hashCode() { + int result; + result = type; + result = 29 * result + (value != null ? value.hashCode() : 0); + return result; + } + + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Token)) return false; + + final Token token = (Token) o; + + if (type != token.type) return false; + if (value != null ? !value.equals(token.value) : token.value != null) return false; + + return true; + } +} 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 146150e6e74cdb2bc30f9360020ec38a80cefe87..522964d4471e233b2cf5c4fe00bc5ce90e20c038 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 @@ -1,196 +1,196 @@ -/** - * 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; -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; - - - -/** - *

Return a steady stream of tokens.

- * - *

The returned tokens are one of: - * LITERAL, '%', FORMAT_MODIFIER, KEYWWORD, OPTION, LEFT_PARENTHESIS, and - * RIGHT_PARENTHESIS.

- * - *

The '\' character is used as escape. It can be used to escape '_', '%', '(' and - * '('.

- * - *

Note that there is no EOS token returned.

- */ -class TokenStream { - - private static final char ESCAPE_CHAR = '\\'; - private static final char PERCENT_CHAR = CoreConstants.PERCENT_CHAR; - private static final char LEFT_PARENTHESIS = '('; - private static final char RIGHT_PARENTHESIS = ')'; - private static final char CURLY_LEFT = '{'; - private static final char CURLY_RIGHT = '}'; - - private static final int LITERAL_STATE = 0; - private static final int FORMAT_MODIFIER_STATE = 1; - private static final int KEYWORD_STATE = 2; - private static final int OPTION_STATE = 3; - - 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 { - List tokenList = new ArrayList(); - StringBuffer buf = new StringBuffer(); - - while (pointer < patternLength) { - char c = pattern.charAt(pointer); - pointer++; - - switch (state) { - - case LITERAL_STATE: - switch (c) { - case ESCAPE_CHAR: - escape("%()", buf); - break; - case PERCENT_CHAR: - addValuedToken(Token.LITERAL, buf, tokenList); - tokenList.add(Token.PERCENT_TOKEN); - state = FORMAT_MODIFIER_STATE; - break; - - case RIGHT_PARENTHESIS: - if (buf.length() >= 1 && buf.charAt(buf.length() - 1) == '\\') { - buf.deleteCharAt(buf.length() - 1); - buf.append(RIGHT_PARENTHESIS); - } else { - addValuedToken(Token.LITERAL, buf, tokenList); - tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); - } - break; - - default: - buf.append(c); - } - break; - // - case FORMAT_MODIFIER_STATE: - if (c == LEFT_PARENTHESIS) { - 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); - } - 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); - } - 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; - } else { - addValuedToken(Token.KEYWORD, buf, tokenList); - if (c == RIGHT_PARENTHESIS) { - // 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; - } - break; - - default: - } - } - - // 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"); - } - - return tokenList; - } - - void escape(String escapeChars, StringBuffer buf) { - if ((pointer < patternLength)) { - char next = pattern.charAt(pointer++); - escapeUtil.escape(escapeChars, buf, next, pointer); - } - } - - private void addValuedToken(int type, StringBuffer buf, List tokenList) { - if (buf.length() > 0) { - tokenList.add(new Token(type, buf.toString())); - buf.setLength(0); - } - } +/** + * 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; +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; + + + +/** + *

Return a steady stream of tokens.

+ * + *

The returned tokens are one of: + * LITERAL, '%', FORMAT_MODIFIER, KEYWWORD, OPTION, LEFT_PARENTHESIS, and + * RIGHT_PARENTHESIS.

+ * + *

The '\' character is used as escape. It can be used to escape '_', '%', '(' and + * '('.

+ * + *

Note that there is no EOS token returned.

+ */ +class TokenStream { + + private static final char ESCAPE_CHAR = '\\'; + private static final char PERCENT_CHAR = CoreConstants.PERCENT_CHAR; + private static final char LEFT_PARENTHESIS = '('; + private static final char RIGHT_PARENTHESIS = ')'; + private static final char CURLY_LEFT = '{'; + private static final char CURLY_RIGHT = '}'; + + private static final int LITERAL_STATE = 0; + private static final int FORMAT_MODIFIER_STATE = 1; + private static final int KEYWORD_STATE = 2; + private static final int OPTION_STATE = 3; + + 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 { + List tokenList = new ArrayList(); + StringBuffer buf = new StringBuffer(); + + while (pointer < patternLength) { + char c = pattern.charAt(pointer); + pointer++; + + switch (state) { + + case LITERAL_STATE: + switch (c) { + case ESCAPE_CHAR: + escape("%()", buf); + break; + case PERCENT_CHAR: + addValuedToken(Token.LITERAL, buf, tokenList); + tokenList.add(Token.PERCENT_TOKEN); + state = FORMAT_MODIFIER_STATE; + break; + + case RIGHT_PARENTHESIS: + if (buf.length() >= 1 && buf.charAt(buf.length() - 1) == '\\') { + buf.deleteCharAt(buf.length() - 1); + buf.append(RIGHT_PARENTHESIS); + } else { + addValuedToken(Token.LITERAL, buf, tokenList); + tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); + } + break; + + default: + buf.append(c); + } + break; + // + case FORMAT_MODIFIER_STATE: + if (c == LEFT_PARENTHESIS) { + 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); + } + 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); + } + 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; + } else { + addValuedToken(Token.KEYWORD, buf, tokenList); + if (c == RIGHT_PARENTHESIS) { + // 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; + } + break; + + default: + } + } + + // 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"); + } + + return tokenList; + } + + void escape(String escapeChars, StringBuffer buf) { + if ((pointer < patternLength)) { + char next = pattern.charAt(pointer++); + escapeUtil.escape(escapeChars, buf, next, pointer); + } + } + + private void addValuedToken(int type, StringBuffer buf, List tokenList) { + if (buf.length() > 0) { + tokenList.add(new Token(type, buf.toString())); + buf.setLength(0); + } + } } \ No newline at end of file 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 8f15fea1bf7534a38212301769f2a2a46b4d386f..367c0c8cba9386c76e2fb54857e01a083594f43a 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 @@ -1,53 +1,53 @@ -/** - * 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; - -/** - * 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 '%'. - * - *

- * 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 - * '%'. - * - *

- * 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 == CoreConstants.PERCENT_CHAR) { - buf.append(CoreConstants.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); - } - } -} +/** + * 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; + +/** + * 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 '%'. + * + *

+ * 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 + * '%'. + * + *

+ * 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 == CoreConstants.PERCENT_CHAR) { + buf.append(CoreConstants.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); + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/IEscapeUtil.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/IEscapeUtil.java index 8729b4ca3bdf493dc3ca84b731b5b73b32b9ae82..88ac3472f0d757dc4a8c5baad7ae2562a13cba8f 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/IEscapeUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/IEscapeUtil.java @@ -1,19 +1,19 @@ -/** - * 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; - -public interface IEscapeUtil { - - void escape(String additionalEscapeChars, StringBuffer buf, char next, int pointer); +/** + * 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; + +public interface IEscapeUtil { + + void escape(String additionalEscapeChars, StringBuffer buf, char next, int pointer); } \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java index 91a913f99caaf874a6417e6919550c1b6018d2d9..d4feaa0d6c7eb5c6562294c120b76d489a83e9b6 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java @@ -1,92 +1,92 @@ -/** - * 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 RegularEscapeUtil implements IEscapeUtil { - - public void escape(String escapeChars, StringBuffer buf, char next, - int pointer) { - if (escapeChars.indexOf(next) >= 0) { - buf.append(next); - } else - switch (next) { - case '_': - // the \_ sequence is swallowed - break; - case '\\': - buf.append(next); - break; - case 't': - buf.append('\t'); - break; - case 'r': - buf.append('\r'); - break; - case 'n': - buf.append('\n'); - break; - default: - String commaSeperatedEscapeChars = formatEscapeCharsForListing(escapeChars); - new IllegalArgumentException("Illegal char '" + next + " at column " - + 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(); - StringBuffer sbuf = new StringBuffer(len); - - int i = 0; - while (i < len) { - c = s.charAt(i++); - if (c == '\\') { - c = s.charAt(i++); - if (c == 'n') { - c = '\n'; - } else if (c == 'r') { - c = '\r'; - } else if (c == 't') { - c = '\t'; - } else if (c == 'f') { - c = '\f'; - } else if (c == '\b') { - c = '\b'; - } else if (c == '\"') { - c = '\"'; - } else if (c == '\'') { - c = '\''; - } else if (c == '\\') { - c = '\\'; - } - } - sbuf.append(c); - } - return sbuf.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.util; + +/** + * This implementation is intended for use in PatternLayout. + * + * @author Ceki Gülcü + */ +public class RegularEscapeUtil implements IEscapeUtil { + + public void escape(String escapeChars, StringBuffer buf, char next, + int pointer) { + if (escapeChars.indexOf(next) >= 0) { + buf.append(next); + } else + switch (next) { + case '_': + // the \_ sequence is swallowed + break; + case '\\': + buf.append(next); + break; + case 't': + buf.append('\t'); + break; + case 'r': + buf.append('\r'); + break; + case 'n': + buf.append('\n'); + break; + default: + String commaSeperatedEscapeChars = formatEscapeCharsForListing(escapeChars); + new IllegalArgumentException("Illegal char '" + next + " at column " + + 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(); + StringBuffer sbuf = new StringBuffer(len); + + int i = 0; + while (i < len) { + c = s.charAt(i++); + if (c == '\\') { + c = s.charAt(i++); + if (c == 'n') { + c = '\n'; + } else if (c == 'r') { + c = '\r'; + } else if (c == 't') { + c = '\t'; + } else if (c == 'f') { + c = '\f'; + } else if (c == '\b') { + c = '\b'; + } else if (c == '\"') { + c = '\"'; + } else if (c == '\'') { + c = '\''; + } else if (c == '\\') { + c = '\\'; + } + } + sbuf.append(c); + } + return sbuf.toString(); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/read/CyclicBufferAppender.java b/logback-core/src/main/java/ch/qos/logback/core/read/CyclicBufferAppender.java index 02f8878399af9d414479ed1cbcd05a515989a1ba..eeba8cbfbd9460c44d4b59d55fb41b7f6c7ba508 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/read/CyclicBufferAppender.java +++ b/logback-core/src/main/java/ch/qos/logback/core/read/CyclicBufferAppender.java @@ -1,76 +1,76 @@ -/** - * 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.read; - -import ch.qos.logback.core.AppenderBase; -import ch.qos.logback.core.helpers.CyclicBuffer; - -/** - * CyclicBufferAppender stores events in a cyclic buffer of user-specified size. As the - * name suggests, if the size of the buffer is N, only the latest N events are available. - * - * - * @author Ceki Gulcu - */ -public class CyclicBufferAppender extends AppenderBase { - - CyclicBuffer cb; - int maxSize = 512; - - public void start() { - cb = new CyclicBuffer(maxSize); - super.start(); - } - - public void stop() { - cb = null; - super.stop(); - } - - @Override - protected void append(E eventObject) { - if (!isStarted()) { - return; - } - cb.add(eventObject); - } - - public int getLength() { - if (isStarted()) { - return cb.length(); - } else { - return 0; - } - } - - public Object get(int i) { - if (isStarted()) { - return cb.get(i); - } else { - return null; - } - } - - /** - * Set the size of the cyclic buffer. - */ - public int getMaxSize() { - return maxSize; - } - - public void setMaxSize(int maxSize) { - this.maxSize = maxSize; - } - -} +/** + * 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.read; + +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.helpers.CyclicBuffer; + +/** + * CyclicBufferAppender stores events in a cyclic buffer of user-specified size. As the + * name suggests, if the size of the buffer is N, only the latest N events are available. + * + * + * @author Ceki Gulcu + */ +public class CyclicBufferAppender extends AppenderBase { + + CyclicBuffer cb; + int maxSize = 512; + + public void start() { + cb = new CyclicBuffer(maxSize); + super.start(); + } + + public void stop() { + cb = null; + super.stop(); + } + + @Override + protected void append(E eventObject) { + if (!isStarted()) { + return; + } + cb.add(eventObject); + } + + public int getLength() { + if (isStarted()) { + return cb.length(); + } else { + return 0; + } + } + + public Object get(int i) { + if (isStarted()) { + return cb.get(i); + } else { + return null; + } + } + + /** + * Set the size of the cyclic buffer. + */ + public int getMaxSize() { + return maxSize; + } + + public void setMaxSize(int maxSize) { + this.maxSize = maxSize; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java b/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java index b9a1b59eeb446ee1e8c65695070551024c84dcd4..2034dadc09485020b23854be4250c809caea4cb4 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java +++ b/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java @@ -1,28 +1,28 @@ -/** - * 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.read; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.core.AppenderBase; - -public class ListAppender extends AppenderBase { - - public List list = new ArrayList(); - - protected void append(E e) { - list.add(e); - } -} +/** + * 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.read; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.core.AppenderBase; + +public class ListAppender extends AppenderBase { + + public List list = new ArrayList(); + + protected void append(E e) { + list.add(e); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/DefaultTimeBasedFileNamingAndTriggeringPolicy.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/DefaultTimeBasedFileNamingAndTriggeringPolicy.java index 3d2594096ed370b6a6cef61fcb631d4b1ce89da9..19be55a1212d1b928220b5f840d950aa15f4c0aa 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/DefaultTimeBasedFileNamingAndTriggeringPolicy.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/DefaultTimeBasedFileNamingAndTriggeringPolicy.java @@ -1,50 +1,50 @@ -/** - * 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.rolling; - -import java.io.File; -import java.util.Date; - -import ch.qos.logback.core.rolling.helper.DefaultArchiveRemover; - -/** - * - * @author Ceki Gülcü - * - * @param - */ -public class DefaultTimeBasedFileNamingAndTriggeringPolicy extends TimeBasedFileNamingAndTriggeringPolicyBase { - - @Override - public void start() { - super.start(); - archiveRemover = new DefaultArchiveRemover(tbrp.fileNamePattern, rc); - archiveRemover.setContext(context); - started = true; - } - - public boolean isTriggeringEvent(File activeFile, final E event) { - long time = getCurrentTime(); - if (time >= nextCheck) { - Date dateOfElapsedPeriod = dateInCurrentPeriod; - elapsedPeriodsFileName = tbrp.fileNamePatternWCS - .convert(dateOfElapsedPeriod); - setDateInCurrentPeriod(time); - computeNextCheck(); - return true; - } else { - return false; - } - } -} +/** + * 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.rolling; + +import java.io.File; +import java.util.Date; + +import ch.qos.logback.core.rolling.helper.DefaultArchiveRemover; + +/** + * + * @author Ceki Gülcü + * + * @param + */ +public class DefaultTimeBasedFileNamingAndTriggeringPolicy extends TimeBasedFileNamingAndTriggeringPolicyBase { + + @Override + public void start() { + super.start(); + archiveRemover = new DefaultArchiveRemover(tbrp.fileNamePattern, rc); + archiveRemover.setContext(context); + started = true; + } + + public boolean isTriggeringEvent(File activeFile, final E event) { + long time = getCurrentTime(); + if (time >= nextCheck) { + Date dateOfElapsedPeriod = dateInCurrentPeriod; + elapsedPeriodsFileName = tbrp.fileNamePatternWCS + .convert(dateOfElapsedPeriod); + setDateInCurrentPeriod(time); + computeNextCheck(); + return true; + } else { + return false; + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/FixedWindowRollingPolicy.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/FixedWindowRollingPolicy.java index 8775fb1915586dfb163d9b7a2579a5ac048e573f..034c7206694142e8d8bae159b073cfe2df069899 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/FixedWindowRollingPolicy.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/FixedWindowRollingPolicy.java @@ -1,163 +1,163 @@ -/** - * 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.rolling; - -import java.io.File; - -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.rolling.helper.Compressor; -import ch.qos.logback.core.rolling.helper.FileNamePattern; -import ch.qos.logback.core.rolling.helper.IntegerTokenConverter; -import ch.qos.logback.core.rolling.helper.RenameUtil; - -/** - * When rolling over, FixedWindowRollingPolicy renames files - * according to a fixed window algorithm. - * - * For more information about this policy, please refer to the online manual at - * http://logback.qos.ch/manual/appenders.html#FixedWindowRollingPolicy - * - * @author Ceki Gülcü - */ -public class FixedWindowRollingPolicy extends RollingPolicyBase { - static final String FNP_NOT_SET = "The \"FileNamePattern\" property must be set before using FixedWindowRollingPolicy. "; - static final String PRUDENT_MODE_UNSUPPORTED = "See also http://logback.qos.ch/codes.html#tbr_fnp_prudent_unsupported"; - static final String SEE_PARENT_FN_NOT_SET = "Please refer to http://logback.qos.ch/codes.html#fwrp_parentFileName_not_set"; - int maxIndex; - int minIndex; - RenameUtil util = new RenameUtil(); - Compressor compressor; - - /** - * It's almost always a bad idea to have a large window size, say over 12. - */ - private static int MAX_WINDOW_SIZE = 12; - - public FixedWindowRollingPolicy() { - minIndex = 1; - maxIndex = 7; - } - - public void start() { - util.setContext(this.context); - - if (fileNamePatternStr != null) { - fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context); - determineCompressionMode(); - } else { - addError(FNP_NOT_SET); - addError(CoreConstants.SEE_FNP_NOT_SET); - throw new IllegalStateException(FNP_NOT_SET + CoreConstants.SEE_FNP_NOT_SET); - } - - if(isParentPrudent()) { - addError("Prudent mode is not supported with FixedWindowRollingPolicy."); - addError(PRUDENT_MODE_UNSUPPORTED); - throw new IllegalStateException("Prudent mode is not supported."); - } - - if (getParentsRawFileProperty() == null) { - addError("The File name property must be set before using this rolling policy."); - addError(SEE_PARENT_FN_NOT_SET); - throw new IllegalStateException("The \"File\" option must be set."); - } - - if (maxIndex < minIndex) { - addWarn("MaxIndex (" + maxIndex + ") cannot be smaller than MinIndex (" - + minIndex + ")."); - addWarn("Setting maxIndex to equal minIndex."); - maxIndex = minIndex; - } - - if ((maxIndex - minIndex) > MAX_WINDOW_SIZE) { - addWarn("Large window sizes are not allowed."); - maxIndex = minIndex + MAX_WINDOW_SIZE; - addWarn("MaxIndex reduced to " + maxIndex); - } - - IntegerTokenConverter itc = fileNamePattern.getIntegerTokenConverter(); - - if (itc == null) { - throw new IllegalStateException("FileNamePattern [" - + fileNamePattern.getPattern() - + "] does not contain a valid IntegerToken"); - } - - compressor = new Compressor(compressionMode); - compressor.setContext(this.context); - } - - public void rollover() throws RolloverFailure { - // Inside this method it is guaranteed that the hereto active log file is - // closed. - // If maxIndex <= 0, then there is no file renaming to be done. - if (maxIndex >= 0) { - // Delete the oldest file, to keep Windows happy. - File file = new File(fileNamePattern.convertInt(maxIndex)); - - if (file.exists()) { - file.delete(); - } - - // Map {(maxIndex - 1), ..., minIndex} to {maxIndex, ..., minIndex+1} - for (int i = maxIndex - 1; i >= minIndex; i--) { - String toRenameStr = fileNamePattern.convertInt(i); - File toRename = new File(toRenameStr); - // no point in trying to rename an inexistent file - if (toRename.exists()) { - util.rename(toRenameStr, fileNamePattern.convertInt(i + 1)); - } else { - addInfo("Skipping roll-over for inexistent file " + toRenameStr); - } - } - - // move active file name to min - switch (compressionMode) { - case NONE: - util.rename(getActiveFileName(), fileNamePattern - .convertInt(minIndex)); - break; - case GZ: - case ZIP: - compressor.compress(getActiveFileName(), fileNamePattern.convertInt(minIndex)); - break; - } - } - } - - /** - * Return the value of the ActiveFile option. - * - * @see {@link setActiveFileName}. - */ - public String getActiveFileName() { - return getParentsRawFileProperty(); - } - - public int getMaxIndex() { - return maxIndex; - } - - public int getMinIndex() { - return minIndex; - } - - public void setMaxIndex(int maxIndex) { - this.maxIndex = maxIndex; - } - - public void setMinIndex(int minIndex) { - this.minIndex = minIndex; - } -} +/** + * 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.rolling; + +import java.io.File; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.rolling.helper.Compressor; +import ch.qos.logback.core.rolling.helper.FileNamePattern; +import ch.qos.logback.core.rolling.helper.IntegerTokenConverter; +import ch.qos.logback.core.rolling.helper.RenameUtil; + +/** + * When rolling over, FixedWindowRollingPolicy renames files + * according to a fixed window algorithm. + * + * For more information about this policy, please refer to the online manual at + * http://logback.qos.ch/manual/appenders.html#FixedWindowRollingPolicy + * + * @author Ceki Gülcü + */ +public class FixedWindowRollingPolicy extends RollingPolicyBase { + static final String FNP_NOT_SET = "The \"FileNamePattern\" property must be set before using FixedWindowRollingPolicy. "; + static final String PRUDENT_MODE_UNSUPPORTED = "See also http://logback.qos.ch/codes.html#tbr_fnp_prudent_unsupported"; + static final String SEE_PARENT_FN_NOT_SET = "Please refer to http://logback.qos.ch/codes.html#fwrp_parentFileName_not_set"; + int maxIndex; + int minIndex; + RenameUtil util = new RenameUtil(); + Compressor compressor; + + /** + * It's almost always a bad idea to have a large window size, say over 12. + */ + private static int MAX_WINDOW_SIZE = 12; + + public FixedWindowRollingPolicy() { + minIndex = 1; + maxIndex = 7; + } + + public void start() { + util.setContext(this.context); + + if (fileNamePatternStr != null) { + fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context); + determineCompressionMode(); + } else { + addError(FNP_NOT_SET); + addError(CoreConstants.SEE_FNP_NOT_SET); + throw new IllegalStateException(FNP_NOT_SET + CoreConstants.SEE_FNP_NOT_SET); + } + + if(isParentPrudent()) { + addError("Prudent mode is not supported with FixedWindowRollingPolicy."); + addError(PRUDENT_MODE_UNSUPPORTED); + throw new IllegalStateException("Prudent mode is not supported."); + } + + if (getParentsRawFileProperty() == null) { + addError("The File name property must be set before using this rolling policy."); + addError(SEE_PARENT_FN_NOT_SET); + throw new IllegalStateException("The \"File\" option must be set."); + } + + if (maxIndex < minIndex) { + addWarn("MaxIndex (" + maxIndex + ") cannot be smaller than MinIndex (" + + minIndex + ")."); + addWarn("Setting maxIndex to equal minIndex."); + maxIndex = minIndex; + } + + if ((maxIndex - minIndex) > MAX_WINDOW_SIZE) { + addWarn("Large window sizes are not allowed."); + maxIndex = minIndex + MAX_WINDOW_SIZE; + addWarn("MaxIndex reduced to " + maxIndex); + } + + IntegerTokenConverter itc = fileNamePattern.getIntegerTokenConverter(); + + if (itc == null) { + throw new IllegalStateException("FileNamePattern [" + + fileNamePattern.getPattern() + + "] does not contain a valid IntegerToken"); + } + + compressor = new Compressor(compressionMode); + compressor.setContext(this.context); + } + + public void rollover() throws RolloverFailure { + // Inside this method it is guaranteed that the hereto active log file is + // closed. + // If maxIndex <= 0, then there is no file renaming to be done. + if (maxIndex >= 0) { + // Delete the oldest file, to keep Windows happy. + File file = new File(fileNamePattern.convertInt(maxIndex)); + + if (file.exists()) { + file.delete(); + } + + // Map {(maxIndex - 1), ..., minIndex} to {maxIndex, ..., minIndex+1} + for (int i = maxIndex - 1; i >= minIndex; i--) { + String toRenameStr = fileNamePattern.convertInt(i); + File toRename = new File(toRenameStr); + // no point in trying to rename an inexistent file + if (toRename.exists()) { + util.rename(toRenameStr, fileNamePattern.convertInt(i + 1)); + } else { + addInfo("Skipping roll-over for inexistent file " + toRenameStr); + } + } + + // move active file name to min + switch (compressionMode) { + case NONE: + util.rename(getActiveFileName(), fileNamePattern + .convertInt(minIndex)); + break; + case GZ: + case ZIP: + compressor.compress(getActiveFileName(), fileNamePattern.convertInt(minIndex)); + break; + } + } + } + + /** + * Return the value of the ActiveFile option. + * + * @see {@link setActiveFileName}. + */ + public String getActiveFileName() { + return getParentsRawFileProperty(); + } + + public int getMaxIndex() { + return maxIndex; + } + + public int getMinIndex() { + return minIndex; + } + + public void setMaxIndex(int maxIndex) { + this.maxIndex = maxIndex; + } + + public void setMinIndex(int minIndex) { + this.minIndex = minIndex; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingFileAppender.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingFileAppender.java index cddef708497ce41f6824ff586dd44fb43fd801e6..af5e2d83e7cb60c2fc3db1cb0c5699941d242651 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingFileAppender.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingFileAppender.java @@ -1,179 +1,179 @@ -/** - * 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.rolling; - -import java.io.File; -import java.io.IOException; - -import ch.qos.logback.core.FileAppender; -import ch.qos.logback.core.rolling.helper.CompressionMode; - -/** - * RollingFileAppender extends {@link FileAppender} to backup the - * log files depending on {@link RollingPolicy} and {@link TriggeringPolicy}. - *

- * - * For more information about this appender, please refer to the online manual - * at http://logback.qos.ch/manual/appenders.html#RollingFileAppender - * - * @author Heinz Richter - * @author Ceki Gülcü - */ -public class RollingFileAppender extends FileAppender { - File currentlyActiveFile; - TriggeringPolicy triggeringPolicy; - RollingPolicy rollingPolicy; - - /** - * The default constructor simply calls its {@link FileAppender#FileAppender - * parents constructor}. - */ - public RollingFileAppender() { - } - - public void start() { - if (triggeringPolicy == null) { - addWarn("No TriggeringPolicy was set for the RollingFileAppender named " - + getName()); - addWarn("For more information, please visit http://logback.qos.ch/codes.html#rfa_no_tp"); - return; - } - - // we don't want to void existing log files - if (!append) { - addWarn("Append mode is mandatory for RollingFileAppender"); - append = true; - } - - if (rollingPolicy == null) { - addError("No RollingPolicy was set for the RollingFileAppender named " - + getName()); - addError("For more information, please visit http://logback.qos.ch/codes.html#rfa_no_rp"); - return; - } - - if (isPrudent()) { - if (rawFileProperty() != null) { - addWarn("Setting \"File\" property to null on account of prudent mode"); - setFile(null); - } - if (rollingPolicy.getCompressionMode() != CompressionMode.NONE) { - addError("Compression is not supported in prudent mode. Aborting"); - return; - } - } - - currentlyActiveFile = new File(getFile()); - addInfo("Active log file name: " + getFile()); - super.start(); - } - - @Override - public void setFile(String file) { - // http://jira.qos.ch/browse/LBCORE-94 - // allow setting the file name to null if mandated by prudent mode - if (file != null && ((triggeringPolicy != null) || (rollingPolicy != null))) { - addError("File property must be set before any triggeringPolicy or rollingPolicy properties"); - addError("Visit http://logback.qos.ch/codes.html#rfa_file_after for more information"); - } - super.setFile(file); - } - - @Override - public String getFile() { - return rollingPolicy.getActiveFileName(); - } - - /** - * Implemented by delegating most of the rollover work to a rolling policy. - */ - public synchronized void rollover() { - // Note: This method needs to be synchronized because it needs exclusive - // access while it closes and then re-opens the target file. - // - // make sure to close the hereto active log file! Renaming under windows - // does not work for open files. - this.closeWriter(); - - try { - rollingPolicy.rollover(); - } catch (RolloverFailure rf) { - addWarn("RolloverFailure occurred. Deferring roll-over."); - // we failed to roll-over, let us not truncate and risk data loss - this.append = true; - } - - try { - // update the currentlyActiveFile - // http://jira.qos.ch/browse/LBCORE-90 - currentlyActiveFile = new File(rollingPolicy.getActiveFileName()); - - // This will also close the file. This is OK since multiple - // close operations are safe. - this.openFile(rollingPolicy.getActiveFileName()); - } catch (IOException e) { - addError("setFile(" + fileName + ", false) call failed.", e); - } - } - - /** - * This method differentiates RollingFileAppender from its super class. - */ - @Override - protected void subAppend(E event) { - // The roll-over check must precede actual writing. This is the - // only correct behavior for time driven triggers. - - // We need to synchronize on triggeringPolicy so that only one rollover - // occurs at a time - synchronized (triggeringPolicy) { - if (triggeringPolicy.isTriggeringEvent(currentlyActiveFile, event)) { - rollover(); - } - } - - super.subAppend(event); - } - - public RollingPolicy getRollingPolicy() { - return rollingPolicy; - } - - public TriggeringPolicy getTriggeringPolicy() { - return triggeringPolicy; - } - - /** - * Sets the rolling policy. In case the 'policy' argument also implements - * {@link TriggeringPolicy}, then the triggering policy for this appender is - * automatically set to be the policy argument. - * - * @param policy - */ - @SuppressWarnings("unchecked") - public void setRollingPolicy(RollingPolicy policy) { - rollingPolicy = policy; - if (rollingPolicy instanceof TriggeringPolicy) { - triggeringPolicy = (TriggeringPolicy) policy; - } - - } - - public void setTriggeringPolicy(TriggeringPolicy policy) { - triggeringPolicy = policy; - if (policy instanceof RollingPolicy) { - rollingPolicy = (RollingPolicy) policy; - } - } -} +/** + * 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.rolling; + +import java.io.File; +import java.io.IOException; + +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.rolling.helper.CompressionMode; + +/** + * RollingFileAppender extends {@link FileAppender} to backup the + * log files depending on {@link RollingPolicy} and {@link TriggeringPolicy}. + *

+ * + * For more information about this appender, please refer to the online manual + * at http://logback.qos.ch/manual/appenders.html#RollingFileAppender + * + * @author Heinz Richter + * @author Ceki Gülcü + */ +public class RollingFileAppender extends FileAppender { + File currentlyActiveFile; + TriggeringPolicy triggeringPolicy; + RollingPolicy rollingPolicy; + + /** + * The default constructor simply calls its {@link FileAppender#FileAppender + * parents constructor}. + */ + public RollingFileAppender() { + } + + public void start() { + if (triggeringPolicy == null) { + addWarn("No TriggeringPolicy was set for the RollingFileAppender named " + + getName()); + addWarn("For more information, please visit http://logback.qos.ch/codes.html#rfa_no_tp"); + return; + } + + // we don't want to void existing log files + if (!append) { + addWarn("Append mode is mandatory for RollingFileAppender"); + append = true; + } + + if (rollingPolicy == null) { + addError("No RollingPolicy was set for the RollingFileAppender named " + + getName()); + addError("For more information, please visit http://logback.qos.ch/codes.html#rfa_no_rp"); + return; + } + + if (isPrudent()) { + if (rawFileProperty() != null) { + addWarn("Setting \"File\" property to null on account of prudent mode"); + setFile(null); + } + if (rollingPolicy.getCompressionMode() != CompressionMode.NONE) { + addError("Compression is not supported in prudent mode. Aborting"); + return; + } + } + + currentlyActiveFile = new File(getFile()); + addInfo("Active log file name: " + getFile()); + super.start(); + } + + @Override + public void setFile(String file) { + // http://jira.qos.ch/browse/LBCORE-94 + // allow setting the file name to null if mandated by prudent mode + if (file != null && ((triggeringPolicy != null) || (rollingPolicy != null))) { + addError("File property must be set before any triggeringPolicy or rollingPolicy properties"); + addError("Visit http://logback.qos.ch/codes.html#rfa_file_after for more information"); + } + super.setFile(file); + } + + @Override + public String getFile() { + return rollingPolicy.getActiveFileName(); + } + + /** + * Implemented by delegating most of the rollover work to a rolling policy. + */ + public synchronized void rollover() { + // Note: This method needs to be synchronized because it needs exclusive + // access while it closes and then re-opens the target file. + // + // make sure to close the hereto active log file! Renaming under windows + // does not work for open files. + this.closeWriter(); + + try { + rollingPolicy.rollover(); + } catch (RolloverFailure rf) { + addWarn("RolloverFailure occurred. Deferring roll-over."); + // we failed to roll-over, let us not truncate and risk data loss + this.append = true; + } + + try { + // update the currentlyActiveFile + // http://jira.qos.ch/browse/LBCORE-90 + currentlyActiveFile = new File(rollingPolicy.getActiveFileName()); + + // This will also close the file. This is OK since multiple + // close operations are safe. + this.openFile(rollingPolicy.getActiveFileName()); + } catch (IOException e) { + addError("setFile(" + fileName + ", false) call failed.", e); + } + } + + /** + * This method differentiates RollingFileAppender from its super class. + */ + @Override + protected void subAppend(E event) { + // The roll-over check must precede actual writing. This is the + // only correct behavior for time driven triggers. + + // We need to synchronize on triggeringPolicy so that only one rollover + // occurs at a time + synchronized (triggeringPolicy) { + if (triggeringPolicy.isTriggeringEvent(currentlyActiveFile, event)) { + rollover(); + } + } + + super.subAppend(event); + } + + public RollingPolicy getRollingPolicy() { + return rollingPolicy; + } + + public TriggeringPolicy getTriggeringPolicy() { + return triggeringPolicy; + } + + /** + * Sets the rolling policy. In case the 'policy' argument also implements + * {@link TriggeringPolicy}, then the triggering policy for this appender is + * automatically set to be the policy argument. + * + * @param policy + */ + @SuppressWarnings("unchecked") + public void setRollingPolicy(RollingPolicy policy) { + rollingPolicy = policy; + if (rollingPolicy instanceof TriggeringPolicy) { + triggeringPolicy = (TriggeringPolicy) policy; + } + + } + + public void setTriggeringPolicy(TriggeringPolicy policy) { + triggeringPolicy = policy; + if (policy instanceof RollingPolicy) { + rollingPolicy = (RollingPolicy) policy; + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicy.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicy.java index 33cf792216c7e35b49f960cf3ff1c9c2beca9464..208ffe202b19ebd31e6e1ce6120a81114ecef5be 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicy.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicy.java @@ -1,67 +1,67 @@ -/** - * 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.rolling; - -import ch.qos.logback.core.FileAppender; -import ch.qos.logback.core.rolling.helper.CompressionMode; -import ch.qos.logback.core.spi.LifeCycle; - -/** - * A RollingPolicy is responsible for performing the rolling over - * of the active log file. The RollingPolicy is also responsible - * for providing the active log file, that is the live file where - * logging output will be directed. - * - * @author Ceki Gülcü - */ -public interface RollingPolicy extends LifeCycle { - - /** - * Rolls over log files according to implementation policy. - * - *

This method is invoked by {@link RollingFileAppender}, usually at the - * behest of its {@link TriggeringPolicy}. - * - * @throws RolloverFailure - * Thrown if the rollover operation fails for any reason. - */ - public void rollover() throws RolloverFailure; - - /** - * Get the name of the active log file. - * - *

With implementations such as {@link TimeBasedRollingPolicy}, this - * method returns a new file name, where the actual output will be sent. - * - *

On other implementations, this method might return the FileAppender's - * file property. - */ - public String getActiveFileName(); - - /** - * The compression mode for this policy. - * - * @return - */ - public CompressionMode getCompressionMode(); - - /** - * This method allows RollingPolicy implementations to be aware of their - * containing appender. - * - * @param appender - */ - - public void setParent(FileAppender appender); -} +/** + * 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.rolling; + +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.rolling.helper.CompressionMode; +import ch.qos.logback.core.spi.LifeCycle; + +/** + * A RollingPolicy is responsible for performing the rolling over + * of the active log file. The RollingPolicy is also responsible + * for providing the active log file, that is the live file where + * logging output will be directed. + * + * @author Ceki Gülcü + */ +public interface RollingPolicy extends LifeCycle { + + /** + * Rolls over log files according to implementation policy. + * + *

This method is invoked by {@link RollingFileAppender}, usually at the + * behest of its {@link TriggeringPolicy}. + * + * @throws RolloverFailure + * Thrown if the rollover operation fails for any reason. + */ + public void rollover() throws RolloverFailure; + + /** + * Get the name of the active log file. + * + *

With implementations such as {@link TimeBasedRollingPolicy}, this + * method returns a new file name, where the actual output will be sent. + * + *

On other implementations, this method might return the FileAppender's + * file property. + */ + public String getActiveFileName(); + + /** + * The compression mode for this policy. + * + * @return + */ + public CompressionMode getCompressionMode(); + + /** + * This method allows RollingPolicy implementations to be aware of their + * containing appender. + * + * @param appender + */ + + public void setParent(FileAppender appender); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicyBase.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicyBase.java index 04a09118af9196427aca2bd0072bf75b5f203b7b..757a43b7d9c7d4645a866ea867b59267770db008 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicyBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicyBase.java @@ -1,94 +1,94 @@ -/** - * 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.rolling; - -import ch.qos.logback.core.FileAppender; -import ch.qos.logback.core.rolling.helper.CompressionMode; -import ch.qos.logback.core.rolling.helper.FileNamePattern; -import ch.qos.logback.core.spi.ContextAwareBase; - -/** - * Implements methods common to most, it not all, rolling policies. Currently - * such methods are limited to a compression mode getter/setter. - * - * @author Ceki Gülcü - */ -public abstract class RollingPolicyBase extends ContextAwareBase implements - RollingPolicy { - protected CompressionMode compressionMode = CompressionMode.NONE; - protected FileNamePattern fileNamePattern; - // fileNamePatternStr is always slashified, see setter - protected String fileNamePatternStr; - - private FileAppender parent; - - private boolean started; - - /** - * Given the FileNamePattern string, this method determines the compression - * mode depending on last letters of the fileNamePatternStr. Patterns ending - * with .gz imply GZIP compression, endings with '.zip' imply ZIP compression. - * Otherwise and by default, there is no compression. - * - */ - protected void determineCompressionMode() { - if (fileNamePatternStr.endsWith(".gz")) { - addInfo("Will use gz compression"); - compressionMode = CompressionMode.GZ; - } else if (fileNamePatternStr.endsWith(".zip")) { - addInfo("Will use zip compression"); - compressionMode = CompressionMode.ZIP; - } else { - addInfo("No compression will be used"); - compressionMode = CompressionMode.NONE; - } - } - - - public void setFileNamePattern(String fnp) { - fileNamePatternStr = fnp; - } - - public String getFileNamePattern() { - return fileNamePatternStr; - } - - public CompressionMode getCompressionMode() { - return compressionMode; - } - - public boolean isStarted() { - return started; - } - - public void start() { - started = true; - } - - public void stop() { - started = false; - } - - public void setParent(FileAppender appender) { - this.parent = appender; - } - - public boolean isParentPrudent() { - return parent.isPrudent(); - } - - public String getParentsRawFileProperty() { - return parent.rawFileProperty(); - } -} +/** + * 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.rolling; + +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.rolling.helper.CompressionMode; +import ch.qos.logback.core.rolling.helper.FileNamePattern; +import ch.qos.logback.core.spi.ContextAwareBase; + +/** + * Implements methods common to most, it not all, rolling policies. Currently + * such methods are limited to a compression mode getter/setter. + * + * @author Ceki Gülcü + */ +public abstract class RollingPolicyBase extends ContextAwareBase implements + RollingPolicy { + protected CompressionMode compressionMode = CompressionMode.NONE; + protected FileNamePattern fileNamePattern; + // fileNamePatternStr is always slashified, see setter + protected String fileNamePatternStr; + + private FileAppender parent; + + private boolean started; + + /** + * Given the FileNamePattern string, this method determines the compression + * mode depending on last letters of the fileNamePatternStr. Patterns ending + * with .gz imply GZIP compression, endings with '.zip' imply ZIP compression. + * Otherwise and by default, there is no compression. + * + */ + protected void determineCompressionMode() { + if (fileNamePatternStr.endsWith(".gz")) { + addInfo("Will use gz compression"); + compressionMode = CompressionMode.GZ; + } else if (fileNamePatternStr.endsWith(".zip")) { + addInfo("Will use zip compression"); + compressionMode = CompressionMode.ZIP; + } else { + addInfo("No compression will be used"); + compressionMode = CompressionMode.NONE; + } + } + + + public void setFileNamePattern(String fnp) { + fileNamePatternStr = fnp; + } + + public String getFileNamePattern() { + return fileNamePatternStr; + } + + public CompressionMode getCompressionMode() { + return compressionMode; + } + + public boolean isStarted() { + return started; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + + public void setParent(FileAppender appender) { + this.parent = appender; + } + + public boolean isParentPrudent() { + return parent.isPrudent(); + } + + public String getParentsRawFileProperty() { + return parent.rawFileProperty(); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/RolloverFailure.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/RolloverFailure.java index 0e682f4c36548297fcd44da605bae9179c339076..00c5c294b364e15bd8ee6860f2b894acb6ea3ad6 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/RolloverFailure.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/RolloverFailure.java @@ -1,29 +1,29 @@ -/** - * 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.rolling; - - -/** - * A RolloverFailure occurs if, for whatever reason a rollover fails. - * - * @author Ceki Gulcu - */ -public class RolloverFailure extends Exception { - - private static final long serialVersionUID = -4407533730831239458L; - - public RolloverFailure(String msg) { - super(msg); - } -} +/** + * 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.rolling; + + +/** + * A RolloverFailure occurs if, for whatever reason a rollover fails. + * + * @author Ceki Gulcu + */ +public class RolloverFailure extends Exception { + + private static final long serialVersionUID = -4407533730831239458L; + + public RolloverFailure(String msg) { + super(msg); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP.java index 7e7206c55a0e3dc2de9b0d8f487121230cd708a4..887ad295caadc9ef7ebbc1eb27aa3a014fe6fe28 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP.java @@ -1,114 +1,114 @@ -/** - * 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.rolling; - -import java.io.File; -import java.util.Date; - -import ch.qos.logback.core.joran.spi.NoAutoStart; -import ch.qos.logback.core.rolling.helper.FileFilterUtil; -import ch.qos.logback.core.rolling.helper.SizeAndTimeBasedArchiveRemover; -import ch.qos.logback.core.util.FileSize; - -@NoAutoStart -public class SizeAndTimeBasedFNATP extends - TimeBasedFileNamingAndTriggeringPolicyBase { - - int currentPeriodsCounter = 0; - FileSize maxFileSize; - String maxFileSizeAsString; - - @Override - public void start() { - // we depend on certain fields having been initialized - // in super.start() - super.start(); - - archiveRemover = new SizeAndTimeBasedArchiveRemover(tbrp.fileNamePattern, rc); - archiveRemover.setContext(context); - - // we need to get the correct value of currentPeriodsCounter. - // usually the value is 0, unless the appender or the application - // is stopped and restarted within the same period - if (tbrp.getParentsRawFileProperty() == null) { - String regex = tbrp.fileNamePattern.toRegex(dateInCurrentPeriod); - String stemRegex = FileFilterUtil.afterLastSlash(regex); - computeCurrentPeriodsHighestCounterValue(stemRegex); - } - started = true; - } - - void computeCurrentPeriodsHighestCounterValue(final String stemRegex) { - File file = new File(getCurrentPeriodsFileNameWithoutCompressionSuffix()); - - File parentDir = file.getParentFile(); - File[] matchingFileArray = FileFilterUtil - .filesInFolderMatchingStemRegex(parentDir, stemRegex); - - if (matchingFileArray == null || matchingFileArray.length == 0) { - return; - } - FileFilterUtil.reverseSortFileArrayByName(matchingFileArray); - currentPeriodsCounter = FileFilterUtil.extractCounter(matchingFileArray[0], stemRegex); - } - - // IMPORTANT: This field can be updated by multiple threads. It follows that - // 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; - - public boolean isTriggeringEvent(File activeFile, final E event) { - - long time = getCurrentTime(); - if (time >= nextCheck) { - Date dateInElapsedPeriod = dateInCurrentPeriod; - elapsedPeriodsFileName = tbrp.fileNamePatternWCS - .convertMultipleArguments(dateInElapsedPeriod, currentPeriodsCounter); - currentPeriodsCounter = 0; - setDateInCurrentPeriod(time); - computeNextCheck(); - return true; - } - - // for performance reasons, check for changes every 16 invocations - if (((invocationCounter++) & 0xF) != 0xF) { - return false; - } - - if (activeFile.length() >= maxFileSize.getSize()) { - elapsedPeriodsFileName = tbrp.fileNamePatternWCS - .convertMultipleArguments(dateInCurrentPeriod, currentPeriodsCounter); - currentPeriodsCounter++; - return true; - } - - return false; - } - - @Override - public String getCurrentPeriodsFileNameWithoutCompressionSuffix() { - return tbrp.fileNamePatternWCS.convertMultipleArguments( - dateInCurrentPeriod, currentPeriodsCounter); - } - - public String getMaxFileSize() { - return maxFileSizeAsString; - } - - public void setMaxFileSize(String maxFileSize) { - this.maxFileSizeAsString = maxFileSize; - this.maxFileSize = FileSize.valueOf(maxFileSize); - } -} +/** + * 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.rolling; + +import java.io.File; +import java.util.Date; + +import ch.qos.logback.core.joran.spi.NoAutoStart; +import ch.qos.logback.core.rolling.helper.FileFilterUtil; +import ch.qos.logback.core.rolling.helper.SizeAndTimeBasedArchiveRemover; +import ch.qos.logback.core.util.FileSize; + +@NoAutoStart +public class SizeAndTimeBasedFNATP extends + TimeBasedFileNamingAndTriggeringPolicyBase { + + int currentPeriodsCounter = 0; + FileSize maxFileSize; + String maxFileSizeAsString; + + @Override + public void start() { + // we depend on certain fields having been initialized + // in super.start() + super.start(); + + archiveRemover = new SizeAndTimeBasedArchiveRemover(tbrp.fileNamePattern, rc); + archiveRemover.setContext(context); + + // we need to get the correct value of currentPeriodsCounter. + // usually the value is 0, unless the appender or the application + // is stopped and restarted within the same period + if (tbrp.getParentsRawFileProperty() == null) { + String regex = tbrp.fileNamePattern.toRegex(dateInCurrentPeriod); + String stemRegex = FileFilterUtil.afterLastSlash(regex); + computeCurrentPeriodsHighestCounterValue(stemRegex); + } + started = true; + } + + void computeCurrentPeriodsHighestCounterValue(final String stemRegex) { + File file = new File(getCurrentPeriodsFileNameWithoutCompressionSuffix()); + + File parentDir = file.getParentFile(); + File[] matchingFileArray = FileFilterUtil + .filesInFolderMatchingStemRegex(parentDir, stemRegex); + + if (matchingFileArray == null || matchingFileArray.length == 0) { + return; + } + FileFilterUtil.reverseSortFileArrayByName(matchingFileArray); + currentPeriodsCounter = FileFilterUtil.extractCounter(matchingFileArray[0], stemRegex); + } + + // IMPORTANT: This field can be updated by multiple threads. It follows that + // 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; + + public boolean isTriggeringEvent(File activeFile, final E event) { + + long time = getCurrentTime(); + if (time >= nextCheck) { + Date dateInElapsedPeriod = dateInCurrentPeriod; + elapsedPeriodsFileName = tbrp.fileNamePatternWCS + .convertMultipleArguments(dateInElapsedPeriod, currentPeriodsCounter); + currentPeriodsCounter = 0; + setDateInCurrentPeriod(time); + computeNextCheck(); + return true; + } + + // for performance reasons, check for changes every 16 invocations + if (((invocationCounter++) & 0xF) != 0xF) { + return false; + } + + if (activeFile.length() >= maxFileSize.getSize()) { + elapsedPeriodsFileName = tbrp.fileNamePatternWCS + .convertMultipleArguments(dateInCurrentPeriod, currentPeriodsCounter); + currentPeriodsCounter++; + return true; + } + + return false; + } + + @Override + public String getCurrentPeriodsFileNameWithoutCompressionSuffix() { + return tbrp.fileNamePatternWCS.convertMultipleArguments( + dateInCurrentPeriod, currentPeriodsCounter); + } + + public String getMaxFileSize() { + return maxFileSizeAsString; + } + + public void setMaxFileSize(String maxFileSize) { + this.maxFileSizeAsString = maxFileSize; + this.maxFileSize = FileSize.valueOf(maxFileSize); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java index 8a3cbb80f87cc640fa95c2f6f7e508154c288181..eacffa8c481d5632ab3b48aa3b10c3184b2ee8ea 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java @@ -1,102 +1,102 @@ -/** - * 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.rolling; - -import java.io.File; - -import ch.qos.logback.core.util.FileSize; - -/** - * SizeBasedTriggeringPolicy looks at size of the file being currently written - * to. If it grows bigger than the specified size, the FileAppender using the - * SizeBasedTriggeringPolicy rolls the file and creates a new one. - * - * For more information about this policy, please refer to the online manual at - * http://logback.qos.ch/manual/appenders.html#SizeBasedTriggeringPolicy - * - * @author Ceki Gülcü - * - */ -public class SizeBasedTriggeringPolicy extends TriggeringPolicyBase { - - public static final String SEE_SIZE_FORMAT = "http://logback.qos.ch/codes.html#sbtp_size_format"; - /** - * The default maximum file size. - */ - public static final long DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB - - String maxFileSizeAsString = Long.toString(DEFAULT_MAX_FILE_SIZE); - FileSize maxFileSize; - - public SizeBasedTriggeringPolicy() { - } - - public SizeBasedTriggeringPolicy(final String maxFileSize) { - setMaxFileSize(maxFileSize); - } - - // IMPORTANT: This field can be updated by multiple threads. It follows that - // 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; - - public boolean isTriggeringEvent(final File activeFile, final E event) { - // for performance reasons, check for changes every 16 invocations - if (((invocationCounter++) & 0xF) != 0xF) { - return false; - } - - return (activeFile.length() >= maxFileSize.getSize()); - } - - public String getMaxFileSize() { - return maxFileSizeAsString; - } - - public void setMaxFileSize(String maxFileSize) { - this.maxFileSizeAsString = maxFileSize; - this.maxFileSize = FileSize.valueOf(maxFileSize); - } - - long toFileSize(String value) { - if (value == null) - return DEFAULT_MAX_FILE_SIZE; - - String s = value.trim().toUpperCase(); - long multiplier = 1; - int index; - - if ((index = s.indexOf("KB")) != -1) { - multiplier = 1024; - s = s.substring(0, index); - } else if ((index = s.indexOf("MB")) != -1) { - multiplier = 1024 * 1024; - s = s.substring(0, index); - } else if ((index = s.indexOf("GB")) != -1) { - multiplier = 1024 * 1024 * 1024; - s = s.substring(0, index); - } - if (s != null) { - try { - return Long.valueOf(s).longValue() * multiplier; - } catch (NumberFormatException e) { - addError("[" + s + "] is not in proper int format. Please refer to " - + SEE_SIZE_FORMAT); - addError("[" + value + "] not in expected format.", e); - } - } - return DEFAULT_MAX_FILE_SIZE; - } -} +/** + * 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.rolling; + +import java.io.File; + +import ch.qos.logback.core.util.FileSize; + +/** + * SizeBasedTriggeringPolicy looks at size of the file being currently written + * to. If it grows bigger than the specified size, the FileAppender using the + * SizeBasedTriggeringPolicy rolls the file and creates a new one. + * + * For more information about this policy, please refer to the online manual at + * http://logback.qos.ch/manual/appenders.html#SizeBasedTriggeringPolicy + * + * @author Ceki Gülcü + * + */ +public class SizeBasedTriggeringPolicy extends TriggeringPolicyBase { + + public static final String SEE_SIZE_FORMAT = "http://logback.qos.ch/codes.html#sbtp_size_format"; + /** + * The default maximum file size. + */ + public static final long DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB + + String maxFileSizeAsString = Long.toString(DEFAULT_MAX_FILE_SIZE); + FileSize maxFileSize; + + public SizeBasedTriggeringPolicy() { + } + + public SizeBasedTriggeringPolicy(final String maxFileSize) { + setMaxFileSize(maxFileSize); + } + + // IMPORTANT: This field can be updated by multiple threads. It follows that + // 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; + + public boolean isTriggeringEvent(final File activeFile, final E event) { + // for performance reasons, check for changes every 16 invocations + if (((invocationCounter++) & 0xF) != 0xF) { + return false; + } + + return (activeFile.length() >= maxFileSize.getSize()); + } + + public String getMaxFileSize() { + return maxFileSizeAsString; + } + + public void setMaxFileSize(String maxFileSize) { + this.maxFileSizeAsString = maxFileSize; + this.maxFileSize = FileSize.valueOf(maxFileSize); + } + + long toFileSize(String value) { + if (value == null) + return DEFAULT_MAX_FILE_SIZE; + + String s = value.trim().toUpperCase(); + long multiplier = 1; + int index; + + if ((index = s.indexOf("KB")) != -1) { + multiplier = 1024; + s = s.substring(0, index); + } else if ((index = s.indexOf("MB")) != -1) { + multiplier = 1024 * 1024; + s = s.substring(0, index); + } else if ((index = s.indexOf("GB")) != -1) { + multiplier = 1024 * 1024 * 1024; + s = s.substring(0, index); + } + if (s != null) { + try { + return Long.valueOf(s).longValue() * multiplier; + } catch (NumberFormatException e) { + addError("[" + s + "] is not in proper int format. Please refer to " + + SEE_SIZE_FORMAT); + addError("[" + value + "] not in expected format.", e); + } + } + return DEFAULT_MAX_FILE_SIZE; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicy.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicy.java index fbdd13c45e0935985d79cc4ff828b31369ca8dda..e76b0f0018287a4893179174dae1dc58c6b25b8f 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicy.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicy.java @@ -1,84 +1,84 @@ -/** - * 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.rolling; - -import ch.qos.logback.core.rolling.helper.ArchiveRemover; -import ch.qos.logback.core.spi.ContextAware; - -/** - * This interface lists the set of methods that need to be implemented by - * triggering policies which are nested within a {@link TimeBasedRollingPolicy}. - * - * @author Ceki Gülcü - * - * @param - */ -public interface TimeBasedFileNamingAndTriggeringPolicy extends - TriggeringPolicy, ContextAware { - - /** - * Set the host/parent {@link TimeBasedRollingPolicy}. - * - * @param the - * parent TimeBasedRollingPolicy - */ - void setTimeBasedRollingPolicy(TimeBasedRollingPolicy tbrp); - - /** - * Return the file name for the elapsed periods file name. - * - * @return - */ - String getElapsedPeriodsFileName(); - - /** - * Return the current periods file name without the compression suffix. This - * value is equivalent to the active file name. - * - * @return current period's file name (without compression suffix) - */ - String getCurrentPeriodsFileNameWithoutCompressionSuffix(); - - /** - * Return the archive remover appropriate for this instance. - */ - public ArchiveRemover getArchiveRemover(); - - /** - * Return the current time which is usually the value returned by - * System.currentMillis(). However, for testing purposed this value - * may be different than the real time. - * - * @return current time value - */ - long getCurrentTime(); - - /** - * Set the current time. Only unit tests should invoke this method. - * - * @param now - */ - void setCurrentTime(long now); - - /** - * Set some date in the current period. Only unit tests should invoke this - * method. - * - * WARNING: method removed. A unit test should not set the - * date in current period. It is the job of the FNATP to compute that. - * - * @param date - */ - //void setDateInCurrentPeriod(Date date); -} +/** + * 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.rolling; + +import ch.qos.logback.core.rolling.helper.ArchiveRemover; +import ch.qos.logback.core.spi.ContextAware; + +/** + * This interface lists the set of methods that need to be implemented by + * triggering policies which are nested within a {@link TimeBasedRollingPolicy}. + * + * @author Ceki Gülcü + * + * @param + */ +public interface TimeBasedFileNamingAndTriggeringPolicy extends + TriggeringPolicy, ContextAware { + + /** + * Set the host/parent {@link TimeBasedRollingPolicy}. + * + * @param the + * parent TimeBasedRollingPolicy + */ + void setTimeBasedRollingPolicy(TimeBasedRollingPolicy tbrp); + + /** + * Return the file name for the elapsed periods file name. + * + * @return + */ + String getElapsedPeriodsFileName(); + + /** + * Return the current periods file name without the compression suffix. This + * value is equivalent to the active file name. + * + * @return current period's file name (without compression suffix) + */ + String getCurrentPeriodsFileNameWithoutCompressionSuffix(); + + /** + * Return the archive remover appropriate for this instance. + */ + public ArchiveRemover getArchiveRemover(); + + /** + * Return the current time which is usually the value returned by + * System.currentMillis(). However, for testing purposed this value + * may be different than the real time. + * + * @return current time value + */ + long getCurrentTime(); + + /** + * Set the current time. Only unit tests should invoke this method. + * + * @param now + */ + void setCurrentTime(long now); + + /** + * Set some date in the current period. Only unit tests should invoke this + * method. + * + * WARNING: method removed. A unit test should not set the + * date in current period. It is the job of the FNATP to compute that. + * + * @param date + */ + //void setDateInCurrentPeriod(Date date); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicyBase.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicyBase.java index b7f5fd8f4c5b6ad9035fe67e44e7d457f515e08b..55dd78e118f9d172f2b9b60402c50f14cce658a8 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicyBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicyBase.java @@ -1,127 +1,127 @@ -/** - * 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.rolling; - -import java.io.File; -import java.util.Date; - -import ch.qos.logback.core.rolling.helper.ArchiveRemover; -import ch.qos.logback.core.rolling.helper.DateTokenConverter; -import ch.qos.logback.core.rolling.helper.RollingCalendar; -import ch.qos.logback.core.spi.ContextAwareBase; - -abstract public class TimeBasedFileNamingAndTriggeringPolicyBase extends - ContextAwareBase implements TimeBasedFileNamingAndTriggeringPolicy { - - protected TimeBasedRollingPolicy tbrp; - - protected ArchiveRemover archiveRemover = null; - protected String elapsedPeriodsFileName; - protected RollingCalendar rc; - - protected long currentTime; - // indicate whether the time has been forced or not - protected boolean isTimeForced = false; - protected Date dateInCurrentPeriod = null; - - protected long nextCheck; - protected boolean started = false; - - public boolean isStarted() { - return started; - } - - public void start() { - DateTokenConverter dtc = tbrp.fileNamePattern.getDateTokenConverter(); - if (dtc == null) { - throw new IllegalStateException("FileNamePattern [" - + tbrp.fileNamePattern.getPattern() - + "] does not contain a valid DateToken"); - } - - rc = new RollingCalendar(); - rc.init(dtc.getDatePattern()); - addInfo("The date pattern is '" + dtc.getDatePattern() - + "' from file name pattern '" + tbrp.fileNamePattern.getPattern() - + "'."); - rc.printPeriodicity(this); - - - if (dateInCurrentPeriod == null) { - setDateInCurrentPeriod(new Date(getCurrentTime())); - - if (tbrp.getParentsRawFileProperty() != null) { - File currentFile = new File(tbrp.getParentsRawFileProperty()); - if (currentFile.exists() && currentFile.canRead()) { - setDateInCurrentPeriod(new Date(currentFile.lastModified())); - } - } - } - computeNextCheck(); - } - - public void stop() { - started = false; - } - - protected void computeNextCheck() { - nextCheck = rc.getNextTriggeringMillis(dateInCurrentPeriod); - } - - protected void setDateInCurrentPeriod(long now) { - dateInCurrentPeriod.setTime(now); - } - - // allow Test classes to act on the dateInCurrentPeriod field to simulate old - // log files needing rollover - public void setDateInCurrentPeriod(Date _dateInCurrentPeriod) { - this.dateInCurrentPeriod = _dateInCurrentPeriod; - } - - public Date getDateInCurrentPeriod() { - return dateInCurrentPeriod; - } - - public String getElapsedPeriodsFileName() { - return elapsedPeriodsFileName; - } - - public String getCurrentPeriodsFileNameWithoutCompressionSuffix() { - return tbrp.fileNamePatternWCS.convert(dateInCurrentPeriod); - } - - public void setCurrentTime(long timeInMillis) { - currentTime = timeInMillis; - isTimeForced = true; - } - - public long getCurrentTime() { - // if time is forced return the time set by user - if (isTimeForced) { - return currentTime; - } else { - return System.currentTimeMillis(); - } - } - - public void setTimeBasedRollingPolicy(TimeBasedRollingPolicy _tbrp) { - this.tbrp = _tbrp; - - } - - public ArchiveRemover getArchiveRemover() { - return archiveRemover; - } - -} +/** + * 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.rolling; + +import java.io.File; +import java.util.Date; + +import ch.qos.logback.core.rolling.helper.ArchiveRemover; +import ch.qos.logback.core.rolling.helper.DateTokenConverter; +import ch.qos.logback.core.rolling.helper.RollingCalendar; +import ch.qos.logback.core.spi.ContextAwareBase; + +abstract public class TimeBasedFileNamingAndTriggeringPolicyBase extends + ContextAwareBase implements TimeBasedFileNamingAndTriggeringPolicy { + + protected TimeBasedRollingPolicy tbrp; + + protected ArchiveRemover archiveRemover = null; + protected String elapsedPeriodsFileName; + protected RollingCalendar rc; + + protected long currentTime; + // indicate whether the time has been forced or not + protected boolean isTimeForced = false; + protected Date dateInCurrentPeriod = null; + + protected long nextCheck; + protected boolean started = false; + + public boolean isStarted() { + return started; + } + + public void start() { + DateTokenConverter dtc = tbrp.fileNamePattern.getDateTokenConverter(); + if (dtc == null) { + throw new IllegalStateException("FileNamePattern [" + + tbrp.fileNamePattern.getPattern() + + "] does not contain a valid DateToken"); + } + + rc = new RollingCalendar(); + rc.init(dtc.getDatePattern()); + addInfo("The date pattern is '" + dtc.getDatePattern() + + "' from file name pattern '" + tbrp.fileNamePattern.getPattern() + + "'."); + rc.printPeriodicity(this); + + + if (dateInCurrentPeriod == null) { + setDateInCurrentPeriod(new Date(getCurrentTime())); + + if (tbrp.getParentsRawFileProperty() != null) { + File currentFile = new File(tbrp.getParentsRawFileProperty()); + if (currentFile.exists() && currentFile.canRead()) { + setDateInCurrentPeriod(new Date(currentFile.lastModified())); + } + } + } + computeNextCheck(); + } + + public void stop() { + started = false; + } + + protected void computeNextCheck() { + nextCheck = rc.getNextTriggeringMillis(dateInCurrentPeriod); + } + + protected void setDateInCurrentPeriod(long now) { + dateInCurrentPeriod.setTime(now); + } + + // allow Test classes to act on the dateInCurrentPeriod field to simulate old + // log files needing rollover + public void setDateInCurrentPeriod(Date _dateInCurrentPeriod) { + this.dateInCurrentPeriod = _dateInCurrentPeriod; + } + + public Date getDateInCurrentPeriod() { + return dateInCurrentPeriod; + } + + public String getElapsedPeriodsFileName() { + return elapsedPeriodsFileName; + } + + public String getCurrentPeriodsFileNameWithoutCompressionSuffix() { + return tbrp.fileNamePatternWCS.convert(dateInCurrentPeriod); + } + + public void setCurrentTime(long timeInMillis) { + currentTime = timeInMillis; + isTimeForced = true; + } + + public long getCurrentTime() { + // if time is forced return the time set by user + if (isTimeForced) { + return currentTime; + } else { + return System.currentTimeMillis(); + } + } + + public void setTimeBasedRollingPolicy(TimeBasedRollingPolicy _tbrp) { + this.tbrp = _tbrp; + + } + + public ArchiveRemover getArchiveRemover() { + return archiveRemover; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java index b98706973d7e17d1734731de13974ca286e9d324..9de332bbcf4afa79a28a8e35eeb572c11efa103f 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java @@ -1,214 +1,214 @@ -/** - * 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.rolling; - -import java.io.File; -import java.util.Date; -import java.util.concurrent.Future; - -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.rolling.helper.ArchiveRemover; -import ch.qos.logback.core.rolling.helper.AsynchronousCompressor; -import ch.qos.logback.core.rolling.helper.CompressionMode; -import ch.qos.logback.core.rolling.helper.Compressor; -import ch.qos.logback.core.rolling.helper.FileNamePattern; -import ch.qos.logback.core.rolling.helper.RenameUtil; - -/** - * TimeBasedRollingPolicy is both easy to configure and quite - * powerful. It allows the roll over to be made based on time. It is possible to - * specify that the roll over occur once per day, per week or per month. - * - *

For more information, please refer to the online manual at - * http://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy - * - * @author Ceki Gülcü - */ -public class TimeBasedRollingPolicy extends RollingPolicyBase implements - TriggeringPolicy { - static final String FNP_NOT_SET = "The FileNamePattern option must be set before using TimeBasedRollingPolicy. "; - static final int NO_DELETE_HISTORY = 0; - - // WCS: without compression suffix - FileNamePattern fileNamePatternWCS; - - private Compressor compressor; - private RenameUtil renameUtil = new RenameUtil(); - Future future; - - private int maxHistory = NO_DELETE_HISTORY; - private ArchiveRemover archiveRemover; - - TimeBasedFileNamingAndTriggeringPolicy timeBasedTriggering; - - public void start() { - // set the LR for our utility object - renameUtil.setContext(this.context); - - // find out period from the filename pattern - if (fileNamePatternStr != null) { - fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context); - determineCompressionMode(); - } else { - addWarn(FNP_NOT_SET); - addWarn(CoreConstants.SEE_FNP_NOT_SET); - throw new IllegalStateException(FNP_NOT_SET - + CoreConstants.SEE_FNP_NOT_SET); - } - - compressor = new Compressor(compressionMode); - compressor.setContext(context); - - fileNamePatternWCS = new FileNamePattern(computeFileNameStr_WCS( - fileNamePatternStr, compressionMode), this.context); - - addInfo("Will use the pattern " + fileNamePatternWCS - + " for the active file"); - - if (timeBasedTriggering == null) { - timeBasedTriggering = new DefaultTimeBasedFileNamingAndTriggeringPolicy(); - } - timeBasedTriggering.setContext(context); - timeBasedTriggering.setTimeBasedRollingPolicy(this); - timeBasedTriggering.start(); - - // the maxHistory property is given to TimeBasedRollingPolicy instead of to - // the TimeBasedFileNamingAndTriggeringPolicy. This makes it more convenient - // for the user at the cost of inconsistency at the level of this code. - if (maxHistory != NO_DELETE_HISTORY) { - archiveRemover = timeBasedTriggering.getArchiveRemover(); - archiveRemover.setMaxHistory(maxHistory); - } - } - - public void setTimeBasedFileNamingAndTriggeringPolicy( - TimeBasedFileNamingAndTriggeringPolicy timeBasedTriggering) { - this.timeBasedTriggering = timeBasedTriggering; - } - - public TimeBasedFileNamingAndTriggeringPolicy getTimeBasedFileNamingAndTriggeringPolicy() { - return timeBasedTriggering; - } - - static public String computeFileNameStr_WCS(String fileNamePatternStr, - CompressionMode compressionMode) { - int len = fileNamePatternStr.length(); - switch (compressionMode) { - case GZ: - return fileNamePatternStr.substring(0, len - 3); - case ZIP: - return fileNamePatternStr.substring(0, len - 4); - case NONE: - return fileNamePatternStr; - } - throw new IllegalStateException("Execution should not reach this point"); - } - - public void rollover() throws RolloverFailure { - - // when rollover is called the elapsed period's file has - // been already closed. This is a working assumption of this method. - - String elapsedPeriodsFileName = timeBasedTriggering - .getElapsedPeriodsFileName(); - - if (compressionMode == CompressionMode.NONE) { - if (getParentsRawFileProperty() != null) { - renameUtil.rename(getParentsRawFileProperty(), elapsedPeriodsFileName); - } - } else { - if (getParentsRawFileProperty() == null) { - future = asyncCompress(elapsedPeriodsFileName, elapsedPeriodsFileName); - } else { - future = renamedRawAndAsyncCompress(elapsedPeriodsFileName); - } - } - - if (archiveRemover != null) { - archiveRemover.clean(new Date(timeBasedTriggering.getCurrentTime())); - } - } - - Future asyncCompress(String nameOfFile2Compress, String nameOfCompressedFile) - throws RolloverFailure { - AsynchronousCompressor ac = new AsynchronousCompressor(compressor); - return ac.compressAsynchronously(nameOfFile2Compress, nameOfCompressedFile); - } - - Future renamedRawAndAsyncCompress(String nameOfCompressedFile) - throws RolloverFailure { - String parentsRawFile = getParentsRawFileProperty(); - String tmpTarget = parentsRawFile + System.nanoTime() + ".tmp"; - renameUtil.rename(parentsRawFile, tmpTarget); - return asyncCompress(tmpTarget, nameOfCompressedFile); - } - - /** - * - * The active log file is determined by the value of the parent's filename - * option. However, in case the file name is left blank, then, the active log - * file equals the file name for the current period as computed by the - * FileNamePattern option. - * - *

The RollingPolicy must know whether it is responsible for changing the - * name of the active file or not. If the active file name is set by the user - * via the configuration file, then the RollingPolicy must let it like it is. - * If the user does not specify an active file name, then the RollingPolicy - * generates one. - * - *

To be sure that the file name used by the parent class has been - * generated by the RollingPolicy and not specified by the user, we keep track - * of the last generated name object and compare its reference to the parent - * file name. If they match, then the RollingPolicy knows it's responsible for - * the change of the file name. - * - */ - public String getActiveFileName() { - String parentsRawFileProperty = getParentsRawFileProperty(); - if (parentsRawFileProperty != null) { - return parentsRawFileProperty; - } else { - return timeBasedTriggering - .getCurrentPeriodsFileNameWithoutCompressionSuffix(); - } - } - - public boolean isTriggeringEvent(File activeFile, final E event) { - return timeBasedTriggering.isTriggeringEvent(activeFile, event); - } - - /** - * Get the number of archive files to keep. - * - * @return number of archive files to keep - */ - public int getMaxHistory() { - return maxHistory; - } - - /** - * Set the maximum number of archive files to keep. - * - * @param maxHistory - * number of archive files to keep - */ - public void setMaxHistory(int maxHistory) { - this.maxHistory = maxHistory; - } - - @Override - public String toString() { - return "c.q.l.core.rolling.TimeBasedRollingPolicy"; - } -} +/** + * 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.rolling; + +import java.io.File; +import java.util.Date; +import java.util.concurrent.Future; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.rolling.helper.ArchiveRemover; +import ch.qos.logback.core.rolling.helper.AsynchronousCompressor; +import ch.qos.logback.core.rolling.helper.CompressionMode; +import ch.qos.logback.core.rolling.helper.Compressor; +import ch.qos.logback.core.rolling.helper.FileNamePattern; +import ch.qos.logback.core.rolling.helper.RenameUtil; + +/** + * TimeBasedRollingPolicy is both easy to configure and quite + * powerful. It allows the roll over to be made based on time. It is possible to + * specify that the roll over occur once per day, per week or per month. + * + *

For more information, please refer to the online manual at + * http://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy + * + * @author Ceki Gülcü + */ +public class TimeBasedRollingPolicy extends RollingPolicyBase implements + TriggeringPolicy { + static final String FNP_NOT_SET = "The FileNamePattern option must be set before using TimeBasedRollingPolicy. "; + static final int NO_DELETE_HISTORY = 0; + + // WCS: without compression suffix + FileNamePattern fileNamePatternWCS; + + private Compressor compressor; + private RenameUtil renameUtil = new RenameUtil(); + Future future; + + private int maxHistory = NO_DELETE_HISTORY; + private ArchiveRemover archiveRemover; + + TimeBasedFileNamingAndTriggeringPolicy timeBasedTriggering; + + public void start() { + // set the LR for our utility object + renameUtil.setContext(this.context); + + // find out period from the filename pattern + if (fileNamePatternStr != null) { + fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context); + determineCompressionMode(); + } else { + addWarn(FNP_NOT_SET); + addWarn(CoreConstants.SEE_FNP_NOT_SET); + throw new IllegalStateException(FNP_NOT_SET + + CoreConstants.SEE_FNP_NOT_SET); + } + + compressor = new Compressor(compressionMode); + compressor.setContext(context); + + fileNamePatternWCS = new FileNamePattern(computeFileNameStr_WCS( + fileNamePatternStr, compressionMode), this.context); + + addInfo("Will use the pattern " + fileNamePatternWCS + + " for the active file"); + + if (timeBasedTriggering == null) { + timeBasedTriggering = new DefaultTimeBasedFileNamingAndTriggeringPolicy(); + } + timeBasedTriggering.setContext(context); + timeBasedTriggering.setTimeBasedRollingPolicy(this); + timeBasedTriggering.start(); + + // the maxHistory property is given to TimeBasedRollingPolicy instead of to + // the TimeBasedFileNamingAndTriggeringPolicy. This makes it more convenient + // for the user at the cost of inconsistency at the level of this code. + if (maxHistory != NO_DELETE_HISTORY) { + archiveRemover = timeBasedTriggering.getArchiveRemover(); + archiveRemover.setMaxHistory(maxHistory); + } + } + + public void setTimeBasedFileNamingAndTriggeringPolicy( + TimeBasedFileNamingAndTriggeringPolicy timeBasedTriggering) { + this.timeBasedTriggering = timeBasedTriggering; + } + + public TimeBasedFileNamingAndTriggeringPolicy getTimeBasedFileNamingAndTriggeringPolicy() { + return timeBasedTriggering; + } + + static public String computeFileNameStr_WCS(String fileNamePatternStr, + CompressionMode compressionMode) { + int len = fileNamePatternStr.length(); + switch (compressionMode) { + case GZ: + return fileNamePatternStr.substring(0, len - 3); + case ZIP: + return fileNamePatternStr.substring(0, len - 4); + case NONE: + return fileNamePatternStr; + } + throw new IllegalStateException("Execution should not reach this point"); + } + + public void rollover() throws RolloverFailure { + + // when rollover is called the elapsed period's file has + // been already closed. This is a working assumption of this method. + + String elapsedPeriodsFileName = timeBasedTriggering + .getElapsedPeriodsFileName(); + + if (compressionMode == CompressionMode.NONE) { + if (getParentsRawFileProperty() != null) { + renameUtil.rename(getParentsRawFileProperty(), elapsedPeriodsFileName); + } + } else { + if (getParentsRawFileProperty() == null) { + future = asyncCompress(elapsedPeriodsFileName, elapsedPeriodsFileName); + } else { + future = renamedRawAndAsyncCompress(elapsedPeriodsFileName); + } + } + + if (archiveRemover != null) { + archiveRemover.clean(new Date(timeBasedTriggering.getCurrentTime())); + } + } + + Future asyncCompress(String nameOfFile2Compress, String nameOfCompressedFile) + throws RolloverFailure { + AsynchronousCompressor ac = new AsynchronousCompressor(compressor); + return ac.compressAsynchronously(nameOfFile2Compress, nameOfCompressedFile); + } + + Future renamedRawAndAsyncCompress(String nameOfCompressedFile) + throws RolloverFailure { + String parentsRawFile = getParentsRawFileProperty(); + String tmpTarget = parentsRawFile + System.nanoTime() + ".tmp"; + renameUtil.rename(parentsRawFile, tmpTarget); + return asyncCompress(tmpTarget, nameOfCompressedFile); + } + + /** + * + * The active log file is determined by the value of the parent's filename + * option. However, in case the file name is left blank, then, the active log + * file equals the file name for the current period as computed by the + * FileNamePattern option. + * + *

The RollingPolicy must know whether it is responsible for changing the + * name of the active file or not. If the active file name is set by the user + * via the configuration file, then the RollingPolicy must let it like it is. + * If the user does not specify an active file name, then the RollingPolicy + * generates one. + * + *

To be sure that the file name used by the parent class has been + * generated by the RollingPolicy and not specified by the user, we keep track + * of the last generated name object and compare its reference to the parent + * file name. If they match, then the RollingPolicy knows it's responsible for + * the change of the file name. + * + */ + public String getActiveFileName() { + String parentsRawFileProperty = getParentsRawFileProperty(); + if (parentsRawFileProperty != null) { + return parentsRawFileProperty; + } else { + return timeBasedTriggering + .getCurrentPeriodsFileNameWithoutCompressionSuffix(); + } + } + + public boolean isTriggeringEvent(File activeFile, final E event) { + return timeBasedTriggering.isTriggeringEvent(activeFile, event); + } + + /** + * Get the number of archive files to keep. + * + * @return number of archive files to keep + */ + public int getMaxHistory() { + return maxHistory; + } + + /** + * Set the maximum number of archive files to keep. + * + * @param maxHistory + * number of archive files to keep + */ + public void setMaxHistory(int maxHistory) { + this.maxHistory = maxHistory; + } + + @Override + public String toString() { + return "c.q.l.core.rolling.TimeBasedRollingPolicy"; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/TriggeringPolicy.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/TriggeringPolicy.java index 91a45f0f5ecb1ad1a654843a7417935716c0f4ac..8043a2b50d47aa5a827ee0d014631950902babb5 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/TriggeringPolicy.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/TriggeringPolicy.java @@ -1,39 +1,39 @@ -/** - * 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.rolling; - -import java.io.File; - -import ch.qos.logback.core.spi.LifeCycle; - - -/** - * A TriggeringPolicy controls the conditions under which roll-over - * occurs. Such conditions include time of day, file size, an - * external event, the log request or a combination thereof. - * - * @author Ceki Gülcü - * */ - -public interface TriggeringPolicy extends LifeCycle { - - /** - * Should roll-over be triggered at this time? - * - * @param activeFile A reference to the currently active log file. - * @param event A reference to the currently event. - * @return true if a roll-over should occur. - */ - public boolean isTriggeringEvent(final File activeFile, final E event); -} +/** + * 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.rolling; + +import java.io.File; + +import ch.qos.logback.core.spi.LifeCycle; + + +/** + * A TriggeringPolicy controls the conditions under which roll-over + * occurs. Such conditions include time of day, file size, an + * external event, the log request or a combination thereof. + * + * @author Ceki Gülcü + * */ + +public interface TriggeringPolicy extends LifeCycle { + + /** + * Should roll-over be triggered at this time? + * + * @param activeFile A reference to the currently active log file. + * @param event A reference to the currently event. + * @return true if a roll-over should occur. + */ + public boolean isTriggeringEvent(final File activeFile, final E event); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/TriggeringPolicyBase.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/TriggeringPolicyBase.java index a35728b4e029b049e23d1375cf0c95925faeb628..4b7b747631f1b3e2c0007f4dea854b380adecef4 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/TriggeringPolicyBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/TriggeringPolicyBase.java @@ -1,44 +1,44 @@ -/** - * 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.rolling; - -import ch.qos.logback.core.spi.ContextAwareBase; - - -/** - * SizeBasedTriggeringPolicy looks at size of the file being - * currently written to. - * - * @author Ceki Gülcü - * - */ -abstract public class TriggeringPolicyBase extends ContextAwareBase implements TriggeringPolicy { - - private boolean start; - - public void start() { - start = true; - } - - public void stop() { - start = false; - } - - public boolean isStarted() { - return start; - } - - - -} +/** + * 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.rolling; + +import ch.qos.logback.core.spi.ContextAwareBase; + + +/** + * SizeBasedTriggeringPolicy looks at size of the file being + * currently written to. + * + * @author Ceki Gülcü + * + */ +abstract public class TriggeringPolicyBase extends ContextAwareBase implements TriggeringPolicy { + + private boolean start; + + public void start() { + start = true; + } + + public void stop() { + start = false; + } + + public boolean isStarted() { + return start; + } + + + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/ArchiveRemover.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/ArchiveRemover.java index a8b5c10b43043702cad86ae32c09ca0ef30edc1e..8af5a3be4cf3dd02f27507f637d4cabc46c4eabe 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/ArchiveRemover.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/ArchiveRemover.java @@ -1,28 +1,28 @@ -/** - * 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.rolling.helper; - -import java.util.Date; - -import ch.qos.logback.core.spi.ContextAware; - -/** - * Given a date remove older archived log files. - * - * @author Ceki Gülcü - */ -public interface ArchiveRemover extends ContextAware { - public void clean(Date now); - public void setMaxHistory(int maxHistory); +/** + * 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.rolling.helper; + +import java.util.Date; + +import ch.qos.logback.core.spi.ContextAware; + +/** + * Given a date remove older archived log files. + * + * @author Ceki Gülcü + */ +public interface ArchiveRemover extends ContextAware { + public void clean(Date now); + public void setMaxHistory(int maxHistory); } \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/AsynchronousCompressor.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/AsynchronousCompressor.java index 44f1c9263f3f6da29bdd9d4fb1604696cd42cdfe..569221ab379dfd4d851113553fddba5ebc9d7a9e 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/AsynchronousCompressor.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/AsynchronousCompressor.java @@ -1,36 +1,36 @@ -/** - * 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.rolling.helper; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -public class AsynchronousCompressor { - Compressor compressor; - - public AsynchronousCompressor(Compressor compressor) { - this.compressor = compressor; - } - - public Future compressAsynchronously(String nameOfFile2Compress, - String nameOfCompressedFile) { - ExecutorService executor = Executors.newScheduledThreadPool(1); - Future future = executor.submit(new CompressionRunnable(compressor, - nameOfFile2Compress, nameOfCompressedFile)); - executor.shutdown(); - return future; - } - -} +/** + * 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.rolling.helper; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class AsynchronousCompressor { + Compressor compressor; + + public AsynchronousCompressor(Compressor compressor) { + this.compressor = compressor; + } + + public Future compressAsynchronously(String nameOfFile2Compress, + String nameOfCompressedFile) { + ExecutorService executor = Executors.newScheduledThreadPool(1); + Future future = executor.submit(new CompressionRunnable(compressor, + nameOfFile2Compress, nameOfCompressedFile)); + executor.shutdown(); + return future; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/CompressionMode.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/CompressionMode.java index 507c631008a5d7f07dc8415a46951470d907283d..102c6a27960b97cba5daad22fdb2ebd3004b51f5 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/CompressionMode.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/CompressionMode.java @@ -1,18 +1,18 @@ -/** - * 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.rolling.helper; - -public enum CompressionMode { - NONE, GZ, ZIP; -} +/** + * 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.rolling.helper; + +public enum CompressionMode { + NONE, GZ, ZIP; +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/CompressionRunnable.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/CompressionRunnable.java index e195bbd0964d443cde29de05700bf3a75fa0313a..425282fd2d5f534725c75c956d4787c89d4f18be 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/CompressionRunnable.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/CompressionRunnable.java @@ -1,33 +1,33 @@ -/** - * 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.rolling.helper; - - -public class CompressionRunnable implements Runnable { - - final Compressor compressor; - final String nameOfFile2Compress; - final String nameOfCompressedFile; - - public CompressionRunnable(Compressor compressor, String nameOfFile2Compress, - String nameOfCompressedFile) { - this.compressor = compressor; - this.nameOfFile2Compress = nameOfFile2Compress; - this.nameOfCompressedFile = nameOfCompressedFile; - } - - public void run() { - compressor.compress(nameOfFile2Compress, nameOfCompressedFile); - } -} +/** + * 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.rolling.helper; + + +public class CompressionRunnable implements Runnable { + + final Compressor compressor; + final String nameOfFile2Compress; + final String nameOfCompressedFile; + + public CompressionRunnable(Compressor compressor, String nameOfFile2Compress, + String nameOfCompressedFile) { + this.compressor = compressor; + this.nameOfFile2Compress = nameOfFile2Compress; + this.nameOfCompressedFile = nameOfCompressedFile; + } + + public void run() { + compressor.compress(nameOfFile2Compress, nameOfCompressedFile); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/Compressor.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/Compressor.java index 4a620e24a8eea95d8006012a8d8dbbb72ee6fc27..d664d66fed8ba80009cc0c4230a5a0b2706d9ac0 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/Compressor.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/Compressor.java @@ -1,192 +1,192 @@ -/** - * 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.rolling.helper; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.util.zip.GZIPOutputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import ch.qos.logback.core.rolling.TimeBasedRollingPolicy; -import ch.qos.logback.core.spi.ContextAwareBase; -import ch.qos.logback.core.status.ErrorStatus; -import ch.qos.logback.core.status.WarnStatus; - -/** - * The Compression class implements ZIP and GZ file - * compression/decompression methods. - * - * @author Ceki Gülcü - */ -public class Compressor extends ContextAwareBase { - - final CompressionMode compressionMode; - - // final String nameOfFile2Compress; - // final String nameOfCompressedFile; - - public Compressor(CompressionMode compressionMode) { - this.compressionMode = compressionMode; - } - - // public Compressor(CompressionMode compressionMode, String - // nameOfFile2Compress, String nameOfCompressedFile) { - // this.compressionMode = compressionMode; - // //this.nameOfFile2Compress = nameOfFile2Compress; - // //this.nameOfCompressedFile = nameOfCompressedFile; - // } - - public void compress(String nameOfFile2Compress, String nameOfCompressedFile) { - switch (compressionMode) { - case GZ: - addInfo("GZ compressing [" + nameOfFile2Compress + "]."); - gzCompress(nameOfFile2Compress, nameOfCompressedFile); - break; - case ZIP: - addInfo("ZIP compressing [" + nameOfFile2Compress + "]."); - zipCompress(nameOfFile2Compress, nameOfCompressedFile); - break; - case NONE: - throw new UnsupportedOperationException( - "compress method called in NONE compression mode"); - } - } - - private void zipCompress(String nameOfFile2zip, String nameOfZippedFile) { - File file2zip = new File(nameOfFile2zip); - - if (!file2zip.exists()) { - addStatus(new WarnStatus("The file to compress named [" + nameOfFile2zip - + "] does not exist.", this)); - - return; - } - - if (!nameOfZippedFile.endsWith(".zip")) { - nameOfZippedFile = nameOfZippedFile + ".zip"; - } - - File zippedFile = new File(nameOfZippedFile); - - if (zippedFile.exists()) { - addStatus(new WarnStatus("The target compressed file named [" - + nameOfZippedFile + "] exist already.", this)); - - return; - } - - try { - FileOutputStream fos = new FileOutputStream(nameOfZippedFile); - ZipOutputStream zos = new ZipOutputStream(fos); - FileInputStream fis = new FileInputStream(nameOfFile2zip); - - ZipEntry zipEntry = computeZipEntry(zippedFile); - zos.putNextEntry(zipEntry); - - byte[] inbuf = new byte[8102]; - int n; - - while ((n = fis.read(inbuf)) != -1) { - zos.write(inbuf, 0, n); - } - - fis.close(); - zos.close(); - - if (!file2zip.delete()) { - addStatus(new WarnStatus("Could not delete [" + nameOfFile2zip + "].", - this)); - } - } catch (Exception e) { - addStatus(new ErrorStatus("Error occurred while compressing [" - + nameOfFile2zip + "] into [" + nameOfZippedFile + "].", this, e)); - } - } - - // http://jira.qos.ch/browse/LBCORE-98 - // The name of the compressed file as nested within the zip archive - // - // Case 1: RawFile = null, Patern = foo-%d.zip - // nestedFilename = foo-${current-date} - // - // Case 2: RawFile = hello.txtm, Pattern = = foo-%d.zip - // nestedFilename = foo-${current-date} - // - // in both cases, the strategy consisting of removing the compression - // suffix of zip file works reasonably well. The alternative strategy - // whereby the nested file name was based on the value of the raw file name - // (applicable to case 2 only) has the disadvantage of the nested files - // all having the same name, which could make it harder for the user - // to unzip the file without collisions - ZipEntry computeZipEntry(File zippedFile) { - String nameOfFileNestedWithinArchive = TimeBasedRollingPolicy - .computeFileNameStr_WCS(zippedFile.getName(), compressionMode); - return new ZipEntry(nameOfFileNestedWithinArchive); - } - - private void gzCompress(String nameOfFile2gz, String nameOfgzedFile) { - File file2gz = new File(nameOfFile2gz); - - if (!file2gz.exists()) { - addStatus(new WarnStatus("The file to compress named [" + nameOfFile2gz - + "] does not exist.", this)); - - return; - } - - if (!nameOfgzedFile.endsWith(".gz")) { - nameOfgzedFile = nameOfgzedFile + ".gz"; - } - - File gzedFile = new File(nameOfgzedFile); - - if (gzedFile.exists()) { - addStatus(new WarnStatus("The target compressed file named [" - + nameOfgzedFile + "] exist already.", this)); - - return; - } - - try { - FileOutputStream fos = new FileOutputStream(nameOfgzedFile); - GZIPOutputStream gzos = new GZIPOutputStream(fos); - FileInputStream fis = new FileInputStream(nameOfFile2gz); - byte[] inbuf = new byte[8102]; - int n; - - while ((n = fis.read(inbuf)) != -1) { - gzos.write(inbuf, 0, n); - } - - fis.close(); - gzos.close(); - - if (!file2gz.delete()) { - addStatus(new WarnStatus("Could not delete [" + nameOfFile2gz + "].", - this)); - } - } catch (Exception e) { - addStatus(new ErrorStatus("Error occurred while compressing [" - + nameOfFile2gz + "] into [" + nameOfgzedFile + "].", this, e)); - } - } - - @Override - public String toString() { - return "c.q.l.core.rolling.helper.Compress"; - } - -} +/** + * 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.rolling.helper; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.zip.GZIPOutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import ch.qos.logback.core.rolling.TimeBasedRollingPolicy; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.WarnStatus; + +/** + * The Compression class implements ZIP and GZ file + * compression/decompression methods. + * + * @author Ceki Gülcü + */ +public class Compressor extends ContextAwareBase { + + final CompressionMode compressionMode; + + // final String nameOfFile2Compress; + // final String nameOfCompressedFile; + + public Compressor(CompressionMode compressionMode) { + this.compressionMode = compressionMode; + } + + // public Compressor(CompressionMode compressionMode, String + // nameOfFile2Compress, String nameOfCompressedFile) { + // this.compressionMode = compressionMode; + // //this.nameOfFile2Compress = nameOfFile2Compress; + // //this.nameOfCompressedFile = nameOfCompressedFile; + // } + + public void compress(String nameOfFile2Compress, String nameOfCompressedFile) { + switch (compressionMode) { + case GZ: + addInfo("GZ compressing [" + nameOfFile2Compress + "]."); + gzCompress(nameOfFile2Compress, nameOfCompressedFile); + break; + case ZIP: + addInfo("ZIP compressing [" + nameOfFile2Compress + "]."); + zipCompress(nameOfFile2Compress, nameOfCompressedFile); + break; + case NONE: + throw new UnsupportedOperationException( + "compress method called in NONE compression mode"); + } + } + + private void zipCompress(String nameOfFile2zip, String nameOfZippedFile) { + File file2zip = new File(nameOfFile2zip); + + if (!file2zip.exists()) { + addStatus(new WarnStatus("The file to compress named [" + nameOfFile2zip + + "] does not exist.", this)); + + return; + } + + if (!nameOfZippedFile.endsWith(".zip")) { + nameOfZippedFile = nameOfZippedFile + ".zip"; + } + + File zippedFile = new File(nameOfZippedFile); + + if (zippedFile.exists()) { + addStatus(new WarnStatus("The target compressed file named [" + + nameOfZippedFile + "] exist already.", this)); + + return; + } + + try { + FileOutputStream fos = new FileOutputStream(nameOfZippedFile); + ZipOutputStream zos = new ZipOutputStream(fos); + FileInputStream fis = new FileInputStream(nameOfFile2zip); + + ZipEntry zipEntry = computeZipEntry(zippedFile); + zos.putNextEntry(zipEntry); + + byte[] inbuf = new byte[8102]; + int n; + + while ((n = fis.read(inbuf)) != -1) { + zos.write(inbuf, 0, n); + } + + fis.close(); + zos.close(); + + if (!file2zip.delete()) { + addStatus(new WarnStatus("Could not delete [" + nameOfFile2zip + "].", + this)); + } + } catch (Exception e) { + addStatus(new ErrorStatus("Error occurred while compressing [" + + nameOfFile2zip + "] into [" + nameOfZippedFile + "].", this, e)); + } + } + + // http://jira.qos.ch/browse/LBCORE-98 + // The name of the compressed file as nested within the zip archive + // + // Case 1: RawFile = null, Patern = foo-%d.zip + // nestedFilename = foo-${current-date} + // + // Case 2: RawFile = hello.txtm, Pattern = = foo-%d.zip + // nestedFilename = foo-${current-date} + // + // in both cases, the strategy consisting of removing the compression + // suffix of zip file works reasonably well. The alternative strategy + // whereby the nested file name was based on the value of the raw file name + // (applicable to case 2 only) has the disadvantage of the nested files + // all having the same name, which could make it harder for the user + // to unzip the file without collisions + ZipEntry computeZipEntry(File zippedFile) { + String nameOfFileNestedWithinArchive = TimeBasedRollingPolicy + .computeFileNameStr_WCS(zippedFile.getName(), compressionMode); + return new ZipEntry(nameOfFileNestedWithinArchive); + } + + private void gzCompress(String nameOfFile2gz, String nameOfgzedFile) { + File file2gz = new File(nameOfFile2gz); + + if (!file2gz.exists()) { + addStatus(new WarnStatus("The file to compress named [" + nameOfFile2gz + + "] does not exist.", this)); + + return; + } + + if (!nameOfgzedFile.endsWith(".gz")) { + nameOfgzedFile = nameOfgzedFile + ".gz"; + } + + File gzedFile = new File(nameOfgzedFile); + + if (gzedFile.exists()) { + addStatus(new WarnStatus("The target compressed file named [" + + nameOfgzedFile + "] exist already.", this)); + + return; + } + + try { + FileOutputStream fos = new FileOutputStream(nameOfgzedFile); + GZIPOutputStream gzos = new GZIPOutputStream(fos); + FileInputStream fis = new FileInputStream(nameOfFile2gz); + byte[] inbuf = new byte[8102]; + int n; + + while ((n = fis.read(inbuf)) != -1) { + gzos.write(inbuf, 0, n); + } + + fis.close(); + gzos.close(); + + if (!file2gz.delete()) { + addStatus(new WarnStatus("Could not delete [" + nameOfFile2gz + "].", + this)); + } + } catch (Exception e) { + addStatus(new ErrorStatus("Error occurred while compressing [" + + nameOfFile2gz + "] into [" + nameOfgzedFile + "].", this, e)); + } + } + + @Override + public String toString() { + return "c.q.l.core.rolling.helper.Compress"; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexUtil.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexUtil.java index 9196ea11513d8f8a40c864e29dbf26a424de5699..e639ded02a61c4a1d6b4816ffe866b2524d51931 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexUtil.java @@ -1,66 +1,66 @@ -/** - * 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.rolling.helper; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; - -/** - * This class is concerned with computing a regex corresponding to a date - * pattern (in {@link SimpleDateFormat} format). - * - * @author Ceki Gülcü - * - */ -public class DatePatternToRegexUtil { - - final String datePattern; - final int length; - - DatePatternToRegexUtil(String datePattern) { - this.datePattern = datePattern; - length = datePattern.length(); - } - - String toRegex() { - List sequenceList = tokenize(); - StringBuilder sb = new StringBuilder(); - for (SequenceToRegex4SDF seq : sequenceList) { - sb.append(seq.toRegex()); - } - return sb.toString(); - } - - private List tokenize() { - List sequenceList = new ArrayList(); - SequenceToRegex4SDF sequence = null; - for (int i = 0; i < length; i++) { - char t = datePattern.charAt(i); - if (sequence == null || sequence.c != t) { - sequence = addNewSequence(sequenceList, t); - } else { - sequence.inc(); - } - } - return sequenceList; - } - - SequenceToRegex4SDF addNewSequence(List sequenceList, - char t) { - SequenceToRegex4SDF token = new SequenceToRegex4SDF(t); - sequenceList.add(token); - return token; - } -} +/** + * 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.rolling.helper; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is concerned with computing a regex corresponding to a date + * pattern (in {@link SimpleDateFormat} format). + * + * @author Ceki Gülcü + * + */ +public class DatePatternToRegexUtil { + + final String datePattern; + final int length; + + DatePatternToRegexUtil(String datePattern) { + this.datePattern = datePattern; + length = datePattern.length(); + } + + String toRegex() { + List sequenceList = tokenize(); + StringBuilder sb = new StringBuilder(); + for (SequenceToRegex4SDF seq : sequenceList) { + sb.append(seq.toRegex()); + } + return sb.toString(); + } + + private List tokenize() { + List sequenceList = new ArrayList(); + SequenceToRegex4SDF sequence = null; + for (int i = 0; i < length; i++) { + char t = datePattern.charAt(i); + if (sequence == null || sequence.c != t) { + sequence = addNewSequence(sequenceList, t); + } else { + sequence.inc(); + } + } + return sequenceList; + } + + SequenceToRegex4SDF addNewSequence(List sequenceList, + char t) { + SequenceToRegex4SDF token = new SequenceToRegex4SDF(t); + sequenceList.add(token); + return token; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DateTokenConverter.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DateTokenConverter.java index 36122e5a2e35e80aebe36fe9e80fae45d0151b2b..353e99274e3a1dcb78a41f7856fa9a386393a810 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DateTokenConverter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DateTokenConverter.java @@ -1,77 +1,77 @@ -/** - * 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.rolling.helper; - -import java.text.SimpleDateFormat; -import java.util.Date; - -import ch.qos.logback.core.pattern.DynamicConverter; - -/** - * Returns a date formatted by SimpleDateFormatter. - * - * @author Ceki Gücü - */ -public class DateTokenConverter extends DynamicConverter implements MonoTypedConverter { - - /** - * The conversion word/character with which this converter is registered. - */ - public final static String CONVERTER_KEY = "d"; - - private String datePattern; - private SimpleDateFormat sdf; - - public DateTokenConverter() { - } - - public void start() { - this.datePattern = getFirstOption(); - if (this.datePattern == null) { - this.datePattern = "yyyy-MM-dd"; - ; - } - sdf = new SimpleDateFormat(datePattern); - } - - public String convert(Date date) { - return sdf.format(date); - } - - public String convert(Object o) { - if (o == null) { - throw new IllegalArgumentException("Null argument forbidden"); - } - if (o instanceof Date) { - return convert((Date) o); - } - throw new IllegalArgumentException("Cannot convert "+o+" of type"+o.getClass().getName()); - } - - /** - * Return the date pattern. - */ - public String getDatePattern() { - return datePattern; - } - - public boolean isApplicable(Object o) { - return (o instanceof Date); - } - - public String toRegex() { - DatePatternToRegexUtil toRegex = new DatePatternToRegexUtil(datePattern); - return toRegex.toRegex(); - } -} +/** + * 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.rolling.helper; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import ch.qos.logback.core.pattern.DynamicConverter; + +/** + * Returns a date formatted by SimpleDateFormatter. + * + * @author Ceki Gücü + */ +public class DateTokenConverter extends DynamicConverter implements MonoTypedConverter { + + /** + * The conversion word/character with which this converter is registered. + */ + public final static String CONVERTER_KEY = "d"; + + private String datePattern; + private SimpleDateFormat sdf; + + public DateTokenConverter() { + } + + public void start() { + this.datePattern = getFirstOption(); + if (this.datePattern == null) { + this.datePattern = "yyyy-MM-dd"; + ; + } + sdf = new SimpleDateFormat(datePattern); + } + + public String convert(Date date) { + return sdf.format(date); + } + + public String convert(Object o) { + if (o == null) { + throw new IllegalArgumentException("Null argument forbidden"); + } + if (o instanceof Date) { + return convert((Date) o); + } + throw new IllegalArgumentException("Cannot convert "+o+" of type"+o.getClass().getName()); + } + + /** + * Return the date pattern. + */ + public String getDatePattern() { + return datePattern; + } + + public boolean isApplicable(Object o) { + return (o instanceof Date); + } + + public String toRegex() { + DatePatternToRegexUtil toRegex = new DatePatternToRegexUtil(datePattern); + return toRegex.toRegex(); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DefaultArchiveRemover.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DefaultArchiveRemover.java index 32e7e5661349548cc3671d8c4549610d769526b0..45227588ecf175e077e134dbebc131319f13e8ed 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DefaultArchiveRemover.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DefaultArchiveRemover.java @@ -1,109 +1,109 @@ -/** - * 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.rolling.helper; - -import java.io.File; -import java.util.Date; - -import ch.qos.logback.core.pattern.Converter; -import ch.qos.logback.core.pattern.LiteralConverter; -import ch.qos.logback.core.spi.ContextAwareBase; - -public class DefaultArchiveRemover extends ContextAwareBase implements - ArchiveRemover { - - final FileNamePattern fileNamePattern; - final RollingCalendar rc; - int periodOffsetForDeletionTarget; - final boolean parentClean; - - public DefaultArchiveRemover(FileNamePattern fileNamePattern, - RollingCalendar rc) { - this.fileNamePattern = fileNamePattern; - this.rc = rc; - this.parentClean = computeParentCleaningFlag(fileNamePattern); - } - - boolean computeParentCleaningFlag(FileNamePattern fileNamePattern) { - DateTokenConverter dtc = fileNamePattern.getDateTokenConverter(); - // if the date pattern has a /, then we need parent cleaning - if (dtc.getDatePattern().indexOf('/') != -1) { - return true; - } - // if the literal string subsequent to the dtc contains a /, we also - // need - // parent cleaning - - Converter p = fileNamePattern.headTokenConverter; - - // find the date converter - while (p != null) { - if (p instanceof DateTokenConverter) { - break; - } - p = p.getNext(); - } - - while (p != null) { - if (p instanceof LiteralConverter) { - String s = p.convert(null); - if (s.indexOf('/') != -1) { - return true; - } - } - p = p.getNext(); - } - - // no /, so we don't need parent cleaning - return false; - } - - public void clean(Date now) { - Date date2delete = rc.getRelativeDate(now, periodOffsetForDeletionTarget); - String filename = fileNamePattern.convert(date2delete); - File file2Delete = new File(filename); - if (file2Delete.exists() && file2Delete.isFile()) { - file2Delete.delete(); - addInfo("deleting " + file2Delete); - if (parentClean) { - removeFolderIfEmpty(file2Delete.getParentFile(), 0); - } - } - } - - /** - * Will remove the directory passed as parameter if empty. After that, if the - * parent is also becomes empty, remove the parent dir as well but at most 3 - * times. - * - * @param dir - * @param recursivityCount - */ - void removeFolderIfEmpty(File dir, int recursivityCount) { - // we should never go more than 3 levels higher - if (recursivityCount >= 3) { - return; - } - if (dir.isDirectory() && FileFilterUtil.isEmptyDirectory(dir)) { - addInfo("deleting folder [" + dir +"]"); - dir.delete(); - removeFolderIfEmpty(dir.getParentFile(), recursivityCount + 1); - } - } - - public void setMaxHistory(int maxHistory) { - this.periodOffsetForDeletionTarget = -maxHistory - 1; - } - -} +/** + * 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.rolling.helper; + +import java.io.File; +import java.util.Date; + +import ch.qos.logback.core.pattern.Converter; +import ch.qos.logback.core.pattern.LiteralConverter; +import ch.qos.logback.core.spi.ContextAwareBase; + +public class DefaultArchiveRemover extends ContextAwareBase implements + ArchiveRemover { + + final FileNamePattern fileNamePattern; + final RollingCalendar rc; + int periodOffsetForDeletionTarget; + final boolean parentClean; + + public DefaultArchiveRemover(FileNamePattern fileNamePattern, + RollingCalendar rc) { + this.fileNamePattern = fileNamePattern; + this.rc = rc; + this.parentClean = computeParentCleaningFlag(fileNamePattern); + } + + boolean computeParentCleaningFlag(FileNamePattern fileNamePattern) { + DateTokenConverter dtc = fileNamePattern.getDateTokenConverter(); + // if the date pattern has a /, then we need parent cleaning + if (dtc.getDatePattern().indexOf('/') != -1) { + return true; + } + // if the literal string subsequent to the dtc contains a /, we also + // need + // parent cleaning + + Converter p = fileNamePattern.headTokenConverter; + + // find the date converter + while (p != null) { + if (p instanceof DateTokenConverter) { + break; + } + p = p.getNext(); + } + + while (p != null) { + if (p instanceof LiteralConverter) { + String s = p.convert(null); + if (s.indexOf('/') != -1) { + return true; + } + } + p = p.getNext(); + } + + // no /, so we don't need parent cleaning + return false; + } + + public void clean(Date now) { + Date date2delete = rc.getRelativeDate(now, periodOffsetForDeletionTarget); + String filename = fileNamePattern.convert(date2delete); + File file2Delete = new File(filename); + if (file2Delete.exists() && file2Delete.isFile()) { + file2Delete.delete(); + addInfo("deleting " + file2Delete); + if (parentClean) { + removeFolderIfEmpty(file2Delete.getParentFile(), 0); + } + } + } + + /** + * Will remove the directory passed as parameter if empty. After that, if the + * parent is also becomes empty, remove the parent dir as well but at most 3 + * times. + * + * @param dir + * @param recursivityCount + */ + void removeFolderIfEmpty(File dir, int recursivityCount) { + // we should never go more than 3 levels higher + if (recursivityCount >= 3) { + return; + } + if (dir.isDirectory() && FileFilterUtil.isEmptyDirectory(dir)) { + addInfo("deleting folder [" + dir +"]"); + dir.delete(); + removeFolderIfEmpty(dir.getParentFile(), recursivityCount + 1); + } + } + + public void setMaxHistory(int maxHistory) { + this.periodOffsetForDeletionTarget = -maxHistory - 1; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileFilterUtil.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileFilterUtil.java index c7dad7212a0ac5601f11dbd79a2069f8294e4c8c..1faea621539247f6bcdb65b4550dcada95a8ff8f 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileFilterUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileFilterUtil.java @@ -1,121 +1,121 @@ -/** - * 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.rolling.helper; - -import java.io.File; -import java.io.FilenameFilter; -import java.util.Arrays; -import java.util.Comparator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class FileFilterUtil { - - public static void sortFileArrayByName(File[] fileArray) { - Arrays.sort(fileArray, new Comparator() { - public int compare(File o1, File o2) { - String o1Name = o1.getName(); - String o2Name = o2.getName(); - return (o1Name.compareTo(o2Name)); - } - }); - } - - public static void reverseSortFileArrayByName(File[] fileArray) { - Arrays.sort(fileArray, new Comparator() { - public int compare(File o1, File o2) { - String o1Name = o1.getName(); - String o2Name = o2.getName(); - return (o2Name.compareTo(o1Name)); - } - }); - } - - public static String afterLastSlash(String sregex) { - int i = sregex.lastIndexOf('/'); - if (i == -1) { - return sregex; - } else { - return sregex.substring(i + 1); - } - } - - static public boolean isEmptyDirectory(File dir) { - if (!dir.isDirectory()) { - throw new IllegalArgumentException("[" + dir + "] must be a directory"); - } - String[] filesInDir = dir.list(); - if (filesInDir == null || filesInDir.length == 0) { - return true; - } else { - return false; - } - } - - /** - * Return the set of files matching the stemRegex as found in 'directory'. A - * stemRegex does not contain any slash characters or any folder seperators. - * - * @param file - * @param stemRegex - * @return - */ - public static File[] filesInFolderMatchingStemRegex(File file, - final String stemRegex) { - - if (file == null) { - return new File[0]; - } - if (!file.exists() || !file.isDirectory()) { - return new File[0]; - } - File[] matchingFileArray = file.listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.matches(stemRegex); - } - }); - return matchingFileArray; - } - - static public int extractCounter(File file, final String stemRegex) { - Pattern p = Pattern.compile(stemRegex); - String lastFileName = file.getName(); - - Matcher m = p.matcher(lastFileName); - if (!m.matches()) { - throw new IllegalStateException("The regex [" + stemRegex - + "] should match [" + lastFileName + "]"); - } - String counterAsStr = m.group(1); - int counter = new Integer(counterAsStr).intValue(); - return counter; - } - - public static String slashify(String in) { - return in.replace('\\', '/'); - } - - public static void removeEmptyParentDirectories(File file, - int recursivityCount) { - // we should never go more than 3 levels higher - if (recursivityCount >= 3) { - return; - } - File parent = file.getParentFile(); - if (parent.isDirectory() && FileFilterUtil.isEmptyDirectory(parent)) { - parent.delete(); - removeEmptyParentDirectories(parent, recursivityCount + 1); - } - } -} +/** + * 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.rolling.helper; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.Arrays; +import java.util.Comparator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FileFilterUtil { + + public static void sortFileArrayByName(File[] fileArray) { + Arrays.sort(fileArray, new Comparator() { + public int compare(File o1, File o2) { + String o1Name = o1.getName(); + String o2Name = o2.getName(); + return (o1Name.compareTo(o2Name)); + } + }); + } + + public static void reverseSortFileArrayByName(File[] fileArray) { + Arrays.sort(fileArray, new Comparator() { + public int compare(File o1, File o2) { + String o1Name = o1.getName(); + String o2Name = o2.getName(); + return (o2Name.compareTo(o1Name)); + } + }); + } + + public static String afterLastSlash(String sregex) { + int i = sregex.lastIndexOf('/'); + if (i == -1) { + return sregex; + } else { + return sregex.substring(i + 1); + } + } + + static public boolean isEmptyDirectory(File dir) { + if (!dir.isDirectory()) { + throw new IllegalArgumentException("[" + dir + "] must be a directory"); + } + String[] filesInDir = dir.list(); + if (filesInDir == null || filesInDir.length == 0) { + return true; + } else { + return false; + } + } + + /** + * Return the set of files matching the stemRegex as found in 'directory'. A + * stemRegex does not contain any slash characters or any folder seperators. + * + * @param file + * @param stemRegex + * @return + */ + public static File[] filesInFolderMatchingStemRegex(File file, + final String stemRegex) { + + if (file == null) { + return new File[0]; + } + if (!file.exists() || !file.isDirectory()) { + return new File[0]; + } + File[] matchingFileArray = file.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.matches(stemRegex); + } + }); + return matchingFileArray; + } + + static public int extractCounter(File file, final String stemRegex) { + Pattern p = Pattern.compile(stemRegex); + String lastFileName = file.getName(); + + Matcher m = p.matcher(lastFileName); + if (!m.matches()) { + throw new IllegalStateException("The regex [" + stemRegex + + "] should match [" + lastFileName + "]"); + } + String counterAsStr = m.group(1); + int counter = new Integer(counterAsStr).intValue(); + return counter; + } + + public static String slashify(String in) { + return in.replace('\\', '/'); + } + + public static void removeEmptyParentDirectories(File file, + int recursivityCount) { + // we should never go more than 3 levels higher + if (recursivityCount >= 3) { + return; + } + File parent = file.getParentFile(); + if (parent.isDirectory() && FileFilterUtil.isEmptyDirectory(parent)) { + parent.delete(); + removeEmptyParentDirectories(parent, recursivityCount + 1); + } + } +} 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 c5efefdd90838b146db630746d9136858eab45b6..cc425e132de91b193a40561bf0d1980da97d01b6 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 @@ -1,185 +1,185 @@ -/** - * 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.rolling.helper; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.pattern.Converter; -import ch.qos.logback.core.pattern.ConverterUtil; -import ch.qos.logback.core.pattern.LiteralConverter; -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; - -/** - * After parsing file name patterns, given a number or a date, instances of this - * class can be used to compute a file name according to the file name pattern - * and the given integer or date. - * - * @author Ceki Gülcü - * - */ -public class FileNamePattern extends ContextAwareBase { - - static final Map CONVERTER_MAP = new HashMap(); - static { - CONVERTER_MAP.put(IntegerTokenConverter.CONVERTER_KEY, - IntegerTokenConverter.class.getName()); - CONVERTER_MAP.put(DateTokenConverter.CONVERTER_KEY, - DateTokenConverter.class.getName()); - } - - String pattern; - Converter headTokenConverter; - - public FileNamePattern(String patternArg, Context contextArg) { - // the pattern is slashified - setPattern(FileFilterUtil.slashify(patternArg)); - setContext(contextArg); - parse(); - ConverterUtil.startConverters(this.headTokenConverter); - } - - void parse() { - try { - Parser p = new Parser(pattern, new AlmostAsIsEscapeUtil()); - p.setContext(context); - Node t = p.parse(); - this.headTokenConverter = p.compile(t, CONVERTER_MAP); - - } catch (ScanException sce) { - addError("Failed to parse pattern \"" + pattern + "\".", sce); - } - } - - public String toString() { - return pattern; - } - - public DateTokenConverter getDateTokenConverter() { - Converter p = headTokenConverter; - - while (p != null) { - if (p instanceof DateTokenConverter) { - return (DateTokenConverter) p; - } - - p = p.getNext(); - } - - return null; - } - - public IntegerTokenConverter getIntegerTokenConverter() { - Converter p = headTokenConverter; - - while (p != null) { - if (p instanceof IntegerTokenConverter) { - return (IntegerTokenConverter) p; - } - - p = p.getNext(); - } - return null; - } - - public String convertMultipleArguments(Object... objectList) { - StringBuilder buf = new StringBuilder(); - Converter c = headTokenConverter; - while (c != null) { - if (c instanceof MonoTypedConverter) { - MonoTypedConverter monoTyped = (MonoTypedConverter) c; - for (Object o : objectList) { - if (monoTyped.isApplicable(o)) { - buf.append(c.convert(o)); - } - } - } else { - buf.append(c.convert(objectList)); - } - c = c.getNext(); - } - return buf.toString(); - } - - public String convert(Object o) { - StringBuilder buf = new StringBuilder(); - Converter p = headTokenConverter; - while (p != null) { - buf.append(p.convert(o)); - p = p.getNext(); - } - return buf.toString(); - } - - public String convertInt(int i) { - Integer integerArg = new Integer(i); - return convert(integerArg); - } - - public void setPattern(String pattern) { - if (pattern != null) { - // Trailing spaces in the pattern are assumed to be undesired. - this.pattern = pattern.trim(); - } - } - - public String getPattern() { - return pattern; - } - - /** - * Given date, convert this instance to a regular expression. - */ - public String toRegex(Date date) { - StringBuilder buf = new StringBuilder(); - Converter p = headTokenConverter; - while (p != null) { - if (p instanceof LiteralConverter) { - buf.append(p.convert(null)); - } else if (p instanceof IntegerTokenConverter) { - buf.append("(\\d{1,2})"); - } else if (p instanceof DateTokenConverter) { - buf.append(p.convert(date)); - } - p = p.getNext(); - } - return buf.toString(); - } - - /** - * Given date, convert this instance to a regular expression - */ - public String toRegex() { - StringBuilder buf = new StringBuilder(); - Converter p = headTokenConverter; - while (p != null) { - if (p instanceof LiteralConverter) { - buf.append(p.convert(null)); - } else if (p instanceof IntegerTokenConverter) { - buf.append("\\d{1,2}"); - } else if (p instanceof DateTokenConverter) { - DateTokenConverter dtc = (DateTokenConverter) p; - buf.append(dtc.toRegex()); - } - p = p.getNext(); - } - 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.rolling.helper; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.pattern.Converter; +import ch.qos.logback.core.pattern.ConverterUtil; +import ch.qos.logback.core.pattern.LiteralConverter; +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; + +/** + * After parsing file name patterns, given a number or a date, instances of this + * class can be used to compute a file name according to the file name pattern + * and the given integer or date. + * + * @author Ceki Gülcü + * + */ +public class FileNamePattern extends ContextAwareBase { + + static final Map CONVERTER_MAP = new HashMap(); + static { + CONVERTER_MAP.put(IntegerTokenConverter.CONVERTER_KEY, + IntegerTokenConverter.class.getName()); + CONVERTER_MAP.put(DateTokenConverter.CONVERTER_KEY, + DateTokenConverter.class.getName()); + } + + String pattern; + Converter headTokenConverter; + + public FileNamePattern(String patternArg, Context contextArg) { + // the pattern is slashified + setPattern(FileFilterUtil.slashify(patternArg)); + setContext(contextArg); + parse(); + ConverterUtil.startConverters(this.headTokenConverter); + } + + void parse() { + try { + Parser p = new Parser(pattern, new AlmostAsIsEscapeUtil()); + p.setContext(context); + Node t = p.parse(); + this.headTokenConverter = p.compile(t, CONVERTER_MAP); + + } catch (ScanException sce) { + addError("Failed to parse pattern \"" + pattern + "\".", sce); + } + } + + public String toString() { + return pattern; + } + + public DateTokenConverter getDateTokenConverter() { + Converter p = headTokenConverter; + + while (p != null) { + if (p instanceof DateTokenConverter) { + return (DateTokenConverter) p; + } + + p = p.getNext(); + } + + return null; + } + + public IntegerTokenConverter getIntegerTokenConverter() { + Converter p = headTokenConverter; + + while (p != null) { + if (p instanceof IntegerTokenConverter) { + return (IntegerTokenConverter) p; + } + + p = p.getNext(); + } + return null; + } + + public String convertMultipleArguments(Object... objectList) { + StringBuilder buf = new StringBuilder(); + Converter c = headTokenConverter; + while (c != null) { + if (c instanceof MonoTypedConverter) { + MonoTypedConverter monoTyped = (MonoTypedConverter) c; + for (Object o : objectList) { + if (monoTyped.isApplicable(o)) { + buf.append(c.convert(o)); + } + } + } else { + buf.append(c.convert(objectList)); + } + c = c.getNext(); + } + return buf.toString(); + } + + public String convert(Object o) { + StringBuilder buf = new StringBuilder(); + Converter p = headTokenConverter; + while (p != null) { + buf.append(p.convert(o)); + p = p.getNext(); + } + return buf.toString(); + } + + public String convertInt(int i) { + Integer integerArg = new Integer(i); + return convert(integerArg); + } + + public void setPattern(String pattern) { + if (pattern != null) { + // Trailing spaces in the pattern are assumed to be undesired. + this.pattern = pattern.trim(); + } + } + + public String getPattern() { + return pattern; + } + + /** + * Given date, convert this instance to a regular expression. + */ + public String toRegex(Date date) { + StringBuilder buf = new StringBuilder(); + Converter p = headTokenConverter; + while (p != null) { + if (p instanceof LiteralConverter) { + buf.append(p.convert(null)); + } else if (p instanceof IntegerTokenConverter) { + buf.append("(\\d{1,2})"); + } else if (p instanceof DateTokenConverter) { + buf.append(p.convert(date)); + } + p = p.getNext(); + } + return buf.toString(); + } + + /** + * Given date, convert this instance to a regular expression + */ + public String toRegex() { + StringBuilder buf = new StringBuilder(); + Converter p = headTokenConverter; + while (p != null) { + if (p instanceof LiteralConverter) { + buf.append(p.convert(null)); + } else if (p instanceof IntegerTokenConverter) { + buf.append("\\d{1,2}"); + } else if (p instanceof DateTokenConverter) { + DateTokenConverter dtc = (DateTokenConverter) p; + buf.append(dtc.toRegex()); + } + p = p.getNext(); + } + return buf.toString(); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/IntegerTokenConverter.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/IntegerTokenConverter.java index 213b9204c055f8a86fec56f4bf3fe73dec1bfe1c..aec1c821af8d913123a8ee9e6a4d68036bdcb3d2 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/IntegerTokenConverter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/IntegerTokenConverter.java @@ -1,49 +1,49 @@ -/** - * 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.rolling.helper; - -import ch.qos.logback.core.pattern.DynamicConverter; - -/** - * When asked to convert an integer, IntegerTokenConverter the - * string value of that integer. - * - * @author Ceki Gulcu - */ -public class IntegerTokenConverter extends DynamicConverter implements MonoTypedConverter { - - public final static String CONVERTER_KEY = "i"; - - public IntegerTokenConverter() { - } - - public String convert(int i) { - return Integer.toString(i); - } - - public String convert(Object o) { - if(o == null) { - throw new IllegalArgumentException("Null argument forbidden"); - } - if(o instanceof Integer) { - Integer i = (Integer) o; - return convert(i.intValue()); - } - throw new IllegalArgumentException("Cannot convert "+o+" of type"+o.getClass().getName()); - } - - public boolean isApplicable(Object o) { - return (o instanceof Integer); - } -} +/** + * 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.rolling.helper; + +import ch.qos.logback.core.pattern.DynamicConverter; + +/** + * When asked to convert an integer, IntegerTokenConverter the + * string value of that integer. + * + * @author Ceki Gulcu + */ +public class IntegerTokenConverter extends DynamicConverter implements MonoTypedConverter { + + public final static String CONVERTER_KEY = "i"; + + public IntegerTokenConverter() { + } + + public String convert(int i) { + return Integer.toString(i); + } + + public String convert(Object o) { + if(o == null) { + throw new IllegalArgumentException("Null argument forbidden"); + } + if(o instanceof Integer) { + Integer i = (Integer) o; + return convert(i.intValue()); + } + throw new IllegalArgumentException("Cannot convert "+o+" of type"+o.getClass().getName()); + } + + public boolean isApplicable(Object o) { + return (o instanceof Integer); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/MonoTypedConverter.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/MonoTypedConverter.java index 59594156228e737c8b911c26d55b3f2722b1ffe1..d66cfa6938720edd988c874d52ff5f9ff80fd946 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/MonoTypedConverter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/MonoTypedConverter.java @@ -1,24 +1,24 @@ -/** - * 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.rolling.helper; - -/** - * Converters which can deal only with one type should implement this interface. - * - * @author Ceki G&ulcu;lcü - * - */ -public interface MonoTypedConverter { - boolean isApplicable(Object o); -} +/** + * 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.rolling.helper; + +/** + * Converters which can deal only with one type should implement this interface. + * + * @author Ceki G&ulcu;lcü + * + */ +public interface MonoTypedConverter { + boolean isApplicable(Object o); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/PeriodicityType.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/PeriodicityType.java index d626ca4f0057a2838b38ce9d60ea659c43d86eda..bfebee522447ddd858b04d87b05e0fe66487b78a 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/PeriodicityType.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/PeriodicityType.java @@ -1,28 +1,28 @@ -/** - * 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.rolling.helper; - -public enum PeriodicityType { - - ERRONEOUS, TOP_OF_MILLISECOND, TOP_OF_SECOND, TOP_OF_MINUTE, TOP_OF_HOUR, HALF_DAY, TOP_OF_DAY, TOP_OF_WEEK, TOP_OF_MONTH; - - // The followed list consists of valid periodicy types in increasing period - // lengths - static PeriodicityType[] VALID_ORDERED_LIST = new PeriodicityType[] { - TOP_OF_MILLISECOND, PeriodicityType.TOP_OF_SECOND, - PeriodicityType.TOP_OF_MINUTE, PeriodicityType.TOP_OF_HOUR, - PeriodicityType.TOP_OF_DAY, PeriodicityType.TOP_OF_WEEK, - PeriodicityType.TOP_OF_MONTH }; - -} +/** + * 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.rolling.helper; + +public enum PeriodicityType { + + ERRONEOUS, TOP_OF_MILLISECOND, TOP_OF_SECOND, TOP_OF_MINUTE, TOP_OF_HOUR, HALF_DAY, TOP_OF_DAY, TOP_OF_WEEK, TOP_OF_MONTH; + + // The followed list consists of valid periodicy types in increasing period + // lengths + static PeriodicityType[] VALID_ORDERED_LIST = new PeriodicityType[] { + TOP_OF_MILLISECOND, PeriodicityType.TOP_OF_SECOND, + PeriodicityType.TOP_OF_MINUTE, PeriodicityType.TOP_OF_HOUR, + PeriodicityType.TOP_OF_DAY, PeriodicityType.TOP_OF_WEEK, + PeriodicityType.TOP_OF_MONTH }; + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RenameUtil.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RenameUtil.java index 6e2fe3cad80ce4a5586d42496b81921f48626a76..81b9a33578328c824029733ce6e19dcde5f9c598 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RenameUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RenameUtil.java @@ -1,98 +1,98 @@ -/** - * 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.rolling.helper; - - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -import ch.qos.logback.core.rolling.RolloverFailure; -import ch.qos.logback.core.spi.ContextAwareBase; - - -/** - * Utility class to help solving problems encountered while renaming files. - * @author Ceki Gulcu - */ -public class RenameUtil extends ContextAwareBase { - - - /** - * A robust file renaming method which in case of failure falls back to - * renaming by copying. In case, the file to be renamed is open by another - * process, renaming by copying will succeed whereas regular renaming will - * fail. However, renaming by copying is much slower. - * - * @param from - * @param to - * @throws RolloverFailure - */ - public void rename(String from, String to) throws RolloverFailure { - if(from.equals(to)) { - addWarn("From and to file are the same ["+from+"]. Skipping."); - return; - } - File fromFile = new File(from); - - if (fromFile.exists()) { - File toFile = new File(to); - addInfo("Renaming file ["+fromFile+"] to ["+toFile+"]"); - - boolean result = fromFile.renameTo(toFile); - - if (!result) { - addWarn("Failed to rename file ["+fromFile+"] to ["+toFile+"]."); - addWarn("Attempting to rename by copying."); - renameByCopying(from, to); - } - } else { - throw new RolloverFailure("File [" + from + "] does not exist."); - } - } - - static final int BUF_SIZE = 32*1024; - - public void renameByCopying(String from, String to) - throws RolloverFailure { - try { - FileInputStream fis = new FileInputStream(from); - FileOutputStream fos = new FileOutputStream(to); - byte[] inbuf = new byte[BUF_SIZE]; - int n; - - while ((n = fis.read(inbuf)) != -1) { - fos.write(inbuf, 0, n); - } - - fis.close(); - fos.close(); - - File fromFile = new File(from); - - if (!fromFile.delete()) { - addWarn("Could not delete "+ from); - } - } catch (IOException ioe) { - addError("Failed to rename file by copying", ioe); - throw new RolloverFailure("Failed to rename file by copying"); - } - } - - @Override - public String toString() { - return "c.q.l.co.rolling.helper.RenameUtil"; - } +/** + * 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.rolling.helper; + + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +import ch.qos.logback.core.rolling.RolloverFailure; +import ch.qos.logback.core.spi.ContextAwareBase; + + +/** + * Utility class to help solving problems encountered while renaming files. + * @author Ceki Gulcu + */ +public class RenameUtil extends ContextAwareBase { + + + /** + * A robust file renaming method which in case of failure falls back to + * renaming by copying. In case, the file to be renamed is open by another + * process, renaming by copying will succeed whereas regular renaming will + * fail. However, renaming by copying is much slower. + * + * @param from + * @param to + * @throws RolloverFailure + */ + public void rename(String from, String to) throws RolloverFailure { + if(from.equals(to)) { + addWarn("From and to file are the same ["+from+"]. Skipping."); + return; + } + File fromFile = new File(from); + + if (fromFile.exists()) { + File toFile = new File(to); + addInfo("Renaming file ["+fromFile+"] to ["+toFile+"]"); + + boolean result = fromFile.renameTo(toFile); + + if (!result) { + addWarn("Failed to rename file ["+fromFile+"] to ["+toFile+"]."); + addWarn("Attempting to rename by copying."); + renameByCopying(from, to); + } + } else { + throw new RolloverFailure("File [" + from + "] does not exist."); + } + } + + static final int BUF_SIZE = 32*1024; + + public void renameByCopying(String from, String to) + throws RolloverFailure { + try { + FileInputStream fis = new FileInputStream(from); + FileOutputStream fos = new FileOutputStream(to); + byte[] inbuf = new byte[BUF_SIZE]; + int n; + + while ((n = fis.read(inbuf)) != -1) { + fos.write(inbuf, 0, n); + } + + fis.close(); + fos.close(); + + File fromFile = new File(from); + + if (!fromFile.delete()) { + addWarn("Could not delete "+ from); + } + } catch (IOException ioe) { + addError("Failed to rename file by copying", ioe); + throw new RolloverFailure("Failed to rename file by copying"); + } + } + + @Override + public String toString() { + return "c.q.l.co.rolling.helper.RenameUtil"; + } } \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RollingCalendar.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RollingCalendar.java index 51e5b59b4148a3aef8140f08afbed7df7c8c7f62..293759b157eb5b2ddbd277bbab895e7f6a02e744 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RollingCalendar.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RollingCalendar.java @@ -1,201 +1,201 @@ -/** - * 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.rolling.helper; - -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.Locale; -import java.util.TimeZone; - -import ch.qos.logback.core.spi.ContextAwareBase; - -/** - * RollingCalendar is a helper class to - * {@link ch.qos.logback.core.rolling.TimeBasedRollingPolicy } or similar - * timed-based rolling policies. Given a periodicity type and the current time, - * it computes the start of the next interval (i.e. the triggering date). - * - * @author Ceki Gülcü - * - */ -public class RollingCalendar extends GregorianCalendar { - - private static final long serialVersionUID = -5937537740925066161L; - - // The gmtTimeZone is used only in computeCheckPeriod() method. - static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT"); - - PeriodicityType type = PeriodicityType.ERRONEOUS; - - public RollingCalendar() { - super(); - } - - public RollingCalendar(TimeZone tz, Locale locale) { - super(tz, locale); - } - - public void init(String datePattern) { - type = computePeriodicity(datePattern); - } - - private void setType(PeriodicityType type) { - this.type = type; - } - - public long getNextTriggeringMillis(Date now) { - return getNextTriggeringDate(now).getTime(); - } - - // This method computes the roll over period by looping over the - // periods, starting with the shortest, and stopping when the r0 is - // different from from r1, where r0 is the epoch formatted according - // the datePattern (supplied by the user) and r1 is the - // epoch+nextMillis(i) formatted according to datePattern. All date - // formatting is done in GMT and not local format because the test - // logic is based on comparisons relative to 1970-01-01 00:00:00 - // GMT (the epoch). - public PeriodicityType computePeriodicity(String datePattern) { - RollingCalendar rollingCalendar = new RollingCalendar(GMT_TIMEZONE, Locale - .getDefault()); - - // set sate to 1970-01-01 00:00:00 GMT - Date epoch = new Date(0); - - if (datePattern != null) { - for (PeriodicityType i : PeriodicityType.VALID_ORDERED_LIST) { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern); - simpleDateFormat.setTimeZone(GMT_TIMEZONE); // all date formatting done - // in GMT - - String r0 = simpleDateFormat.format(epoch); - rollingCalendar.setType(i); - - Date next = new Date(rollingCalendar.getNextTriggeringMillis(epoch)); - String r1 = simpleDateFormat.format(next); - - // System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1); - if ((r0 != null) && (r1 != null) && !r0.equals(r1)) { - return i; - } - } - } - // we failed - return PeriodicityType.ERRONEOUS; - } - - public void printPeriodicity(ContextAwareBase cab) { - switch (type) { - case TOP_OF_MILLISECOND: - cab.addInfo("Roll-over every millisecond."); - break; - - case TOP_OF_SECOND: - cab.addInfo("Roll-over every second."); - break; - - case TOP_OF_MINUTE: - cab.addInfo("Roll-over every minute."); - break; - - case TOP_OF_HOUR: - cab.addInfo("Roll-over at the top of every hour."); - break; - - case HALF_DAY: - cab.addInfo("Roll-over at midday and midnight."); - break; - - case TOP_OF_DAY: - cab.addInfo("Roll-over at midnight."); - break; - - case TOP_OF_WEEK: - cab.addInfo("Rollover at the start of week."); - break; - - case TOP_OF_MONTH: - cab.addInfo("Rollover at start of every month."); - break; - - default: - cab.addInfo("Unknown periodicity."); - } - } - - public Date getRelativeDate(Date now, int periods) { - this.setTime(now); - - switch (type) { - case TOP_OF_MILLISECOND: - this.add(Calendar.MILLISECOND, periods); - break; - - case TOP_OF_SECOND: - this.set(Calendar.MILLISECOND, 0); - this.add(Calendar.SECOND, periods); - break; - - case TOP_OF_MINUTE: - this.set(Calendar.SECOND, 0); - this.set(Calendar.MILLISECOND, 0); - this.add(Calendar.MINUTE, periods); - break; - - case TOP_OF_HOUR: - this.set(Calendar.MINUTE, 0); - this.set(Calendar.SECOND, 0); - this.set(Calendar.MILLISECOND, 0); - this.add(Calendar.HOUR_OF_DAY, periods); - break; - - case TOP_OF_DAY: - this.set(Calendar.HOUR_OF_DAY, 0); - this.set(Calendar.MINUTE, 0); - this.set(Calendar.SECOND, 0); - this.set(Calendar.MILLISECOND, 0); - this.add(Calendar.DATE, periods); - break; - - case TOP_OF_WEEK: - this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek()); - this.set(Calendar.HOUR_OF_DAY, 0); - this.set(Calendar.MINUTE, 0); - this.set(Calendar.SECOND, 0); - this.set(Calendar.MILLISECOND, 0); - this.add(Calendar.WEEK_OF_YEAR, periods); - break; - - case TOP_OF_MONTH: - this.set(Calendar.DATE, 1); - this.set(Calendar.HOUR_OF_DAY, 0); - this.set(Calendar.MINUTE, 0); - this.set(Calendar.SECOND, 0); - this.set(Calendar.MILLISECOND, 0); - this.add(Calendar.MONTH, periods); - break; - - default: - throw new IllegalStateException("Unknown periodicity type."); - } - - return getTime(); - } - - public Date getNextTriggeringDate(Date now) { - return getRelativeDate(now, 1); - } -} +/** + * 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.rolling.helper; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; + +import ch.qos.logback.core.spi.ContextAwareBase; + +/** + * RollingCalendar is a helper class to + * {@link ch.qos.logback.core.rolling.TimeBasedRollingPolicy } or similar + * timed-based rolling policies. Given a periodicity type and the current time, + * it computes the start of the next interval (i.e. the triggering date). + * + * @author Ceki Gülcü + * + */ +public class RollingCalendar extends GregorianCalendar { + + private static final long serialVersionUID = -5937537740925066161L; + + // The gmtTimeZone is used only in computeCheckPeriod() method. + static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT"); + + PeriodicityType type = PeriodicityType.ERRONEOUS; + + public RollingCalendar() { + super(); + } + + public RollingCalendar(TimeZone tz, Locale locale) { + super(tz, locale); + } + + public void init(String datePattern) { + type = computePeriodicity(datePattern); + } + + private void setType(PeriodicityType type) { + this.type = type; + } + + public long getNextTriggeringMillis(Date now) { + return getNextTriggeringDate(now).getTime(); + } + + // This method computes the roll over period by looping over the + // periods, starting with the shortest, and stopping when the r0 is + // different from from r1, where r0 is the epoch formatted according + // the datePattern (supplied by the user) and r1 is the + // epoch+nextMillis(i) formatted according to datePattern. All date + // formatting is done in GMT and not local format because the test + // logic is based on comparisons relative to 1970-01-01 00:00:00 + // GMT (the epoch). + public PeriodicityType computePeriodicity(String datePattern) { + RollingCalendar rollingCalendar = new RollingCalendar(GMT_TIMEZONE, Locale + .getDefault()); + + // set sate to 1970-01-01 00:00:00 GMT + Date epoch = new Date(0); + + if (datePattern != null) { + for (PeriodicityType i : PeriodicityType.VALID_ORDERED_LIST) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern); + simpleDateFormat.setTimeZone(GMT_TIMEZONE); // all date formatting done + // in GMT + + String r0 = simpleDateFormat.format(epoch); + rollingCalendar.setType(i); + + Date next = new Date(rollingCalendar.getNextTriggeringMillis(epoch)); + String r1 = simpleDateFormat.format(next); + + // System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1); + if ((r0 != null) && (r1 != null) && !r0.equals(r1)) { + return i; + } + } + } + // we failed + return PeriodicityType.ERRONEOUS; + } + + public void printPeriodicity(ContextAwareBase cab) { + switch (type) { + case TOP_OF_MILLISECOND: + cab.addInfo("Roll-over every millisecond."); + break; + + case TOP_OF_SECOND: + cab.addInfo("Roll-over every second."); + break; + + case TOP_OF_MINUTE: + cab.addInfo("Roll-over every minute."); + break; + + case TOP_OF_HOUR: + cab.addInfo("Roll-over at the top of every hour."); + break; + + case HALF_DAY: + cab.addInfo("Roll-over at midday and midnight."); + break; + + case TOP_OF_DAY: + cab.addInfo("Roll-over at midnight."); + break; + + case TOP_OF_WEEK: + cab.addInfo("Rollover at the start of week."); + break; + + case TOP_OF_MONTH: + cab.addInfo("Rollover at start of every month."); + break; + + default: + cab.addInfo("Unknown periodicity."); + } + } + + public Date getRelativeDate(Date now, int periods) { + this.setTime(now); + + switch (type) { + case TOP_OF_MILLISECOND: + this.add(Calendar.MILLISECOND, periods); + break; + + case TOP_OF_SECOND: + this.set(Calendar.MILLISECOND, 0); + this.add(Calendar.SECOND, periods); + break; + + case TOP_OF_MINUTE: + this.set(Calendar.SECOND, 0); + this.set(Calendar.MILLISECOND, 0); + this.add(Calendar.MINUTE, periods); + break; + + case TOP_OF_HOUR: + this.set(Calendar.MINUTE, 0); + this.set(Calendar.SECOND, 0); + this.set(Calendar.MILLISECOND, 0); + this.add(Calendar.HOUR_OF_DAY, periods); + break; + + case TOP_OF_DAY: + this.set(Calendar.HOUR_OF_DAY, 0); + this.set(Calendar.MINUTE, 0); + this.set(Calendar.SECOND, 0); + this.set(Calendar.MILLISECOND, 0); + this.add(Calendar.DATE, periods); + break; + + case TOP_OF_WEEK: + this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek()); + this.set(Calendar.HOUR_OF_DAY, 0); + this.set(Calendar.MINUTE, 0); + this.set(Calendar.SECOND, 0); + this.set(Calendar.MILLISECOND, 0); + this.add(Calendar.WEEK_OF_YEAR, periods); + break; + + case TOP_OF_MONTH: + this.set(Calendar.DATE, 1); + this.set(Calendar.HOUR_OF_DAY, 0); + this.set(Calendar.MINUTE, 0); + this.set(Calendar.SECOND, 0); + this.set(Calendar.MILLISECOND, 0); + this.add(Calendar.MONTH, periods); + break; + + default: + throw new IllegalStateException("Unknown periodicity type."); + } + + return getTime(); + } + + public Date getNextTriggeringDate(Date now) { + return getRelativeDate(now, 1); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SequenceToRegex4SDF.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SequenceToRegex4SDF.java index 5b4c7ae35c5f546f7aadbadff5dc8caaaa5f7c00..60ebf7049ef612a15902397b454680b64eb4ef55 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SequenceToRegex4SDF.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SequenceToRegex4SDF.java @@ -1,89 +1,89 @@ -/** - * 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.rolling.helper; - -/** - * This class supports mapping tokens (set of same character sequences) to - * regular expressions as appropriate for SimpleDateFormatter. - * - * @author ceki - * - */ -class SequenceToRegex4SDF { - final char c; - int occurrences; - - public SequenceToRegex4SDF(char c) { - this.c = c; - this.occurrences = 1; - } - - void inc() { - occurrences++; - } - - String toRegex() { - switch (c) { - case 'G': - return ".*"; - case 'M': - if (occurrences >= 3) { - return ".*"; - } else { - return number(occurrences); - } - case 'y': - case 'w': - case 'W': - case 'D': - case 'd': - case 'F': - case 'H': - case 'k': - case 'K': - case 'h': - case 'm': - case 's': - case 'S': - return number(occurrences); - case 'E': - return ".{3,12}"; - case 'a': - return ".{2}"; - case 'z': - return ".*"; - case 'Z': - return "(\\+|-)\\d{4}"; - case '.': - return "\\."; - case '\\': - throw new IllegalStateException("Forward slashes are not allowed"); - default: - if (occurrences == 1) { - return "" + c; - } else { - return c + "{" + occurrences + "}"; - } - } - } - - @Override - public String toString() { - return c + "(" + occurrences + ")"; - } - - private String number(int occurences) { - return "\\d{" + occurrences + "}"; - } +/** + * 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.rolling.helper; + +/** + * This class supports mapping tokens (set of same character sequences) to + * regular expressions as appropriate for SimpleDateFormatter. + * + * @author ceki + * + */ +class SequenceToRegex4SDF { + final char c; + int occurrences; + + public SequenceToRegex4SDF(char c) { + this.c = c; + this.occurrences = 1; + } + + void inc() { + occurrences++; + } + + String toRegex() { + switch (c) { + case 'G': + return ".*"; + case 'M': + if (occurrences >= 3) { + return ".*"; + } else { + return number(occurrences); + } + case 'y': + case 'w': + case 'W': + case 'D': + case 'd': + case 'F': + case 'H': + case 'k': + case 'K': + case 'h': + case 'm': + case 's': + case 'S': + return number(occurrences); + case 'E': + return ".{3,12}"; + case 'a': + return ".{2}"; + case 'z': + return ".*"; + case 'Z': + return "(\\+|-)\\d{4}"; + case '.': + return "\\."; + case '\\': + throw new IllegalStateException("Forward slashes are not allowed"); + default: + if (occurrences == 1) { + return "" + c; + } else { + return c + "{" + occurrences + "}"; + } + } + } + + @Override + public String toString() { + return c + "(" + occurrences + ")"; + } + + private String number(int occurences) { + return "\\d{" + occurrences + "}"; + } } \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SizeAndTimeBasedArchiveRemover.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SizeAndTimeBasedArchiveRemover.java index 397ad9aa1c8f6290f18e9272b162c733f2f74c6e..716844c86e1c7880911b6dce2214bacc42da4a50 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SizeAndTimeBasedArchiveRemover.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SizeAndTimeBasedArchiveRemover.java @@ -1,48 +1,48 @@ -/** - * 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.rolling.helper; - -import java.io.File; -import java.util.Date; - -public class SizeAndTimeBasedArchiveRemover extends DefaultArchiveRemover { - - public SizeAndTimeBasedArchiveRemover(FileNamePattern fileNamePattern, - RollingCalendar rc) { - super(fileNamePattern, rc); - } - - @Override - public void clean(Date now) { - Date dateOfPeriodToClean = rc.getRelativeDate(now, periodOffsetForDeletionTarget); - - String regex = fileNamePattern.toRegex(dateOfPeriodToClean); - String stemRegex = FileFilterUtil.afterLastSlash(regex); - File archive0 = new File(fileNamePattern.convertMultipleArguments( - dateOfPeriodToClean, 0)); - - File parentDir = archive0.getParentFile(); - File[] matchingFileArray = FileFilterUtil.filesInFolderMatchingStemRegex( - parentDir, stemRegex); - - for (File f : matchingFileArray) { - f.delete(); - } - - if (parentClean) { - removeFolderIfEmpty(parentDir, 0); - } - } - -} +/** + * 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.rolling.helper; + +import java.io.File; +import java.util.Date; + +public class SizeAndTimeBasedArchiveRemover extends DefaultArchiveRemover { + + public SizeAndTimeBasedArchiveRemover(FileNamePattern fileNamePattern, + RollingCalendar rc) { + super(fileNamePattern, rc); + } + + @Override + public void clean(Date now) { + Date dateOfPeriodToClean = rc.getRelativeDate(now, periodOffsetForDeletionTarget); + + String regex = fileNamePattern.toRegex(dateOfPeriodToClean); + String stemRegex = FileFilterUtil.afterLastSlash(regex); + File archive0 = new File(fileNamePattern.convertMultipleArguments( + dateOfPeriodToClean, 0)); + + File parentDir = archive0.getParentFile(); + File[] matchingFileArray = FileFilterUtil.filesInFolderMatchingStemRegex( + parentDir, stemRegex); + + for (File f : matchingFileArray) { + f.delete(); + } + + if (parentClean) { + removeFolderIfEmpty(parentDir, 0); + } + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/TokenConverter.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/TokenConverter.java index fd8e93e02b1390978b9b207686c0d48601bda567..5378b80bf1174efa7b9ae246df0a2fa8bebee079 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/TokenConverter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/TokenConverter.java @@ -1,56 +1,56 @@ -/** - * 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.rolling.helper; - - -/** - * TokenConverter offers some basic functionality used by more - * specific token converters. - *

- * It basically sets up the chained architecture for tokens. It also forces - * derived classes to fix their type. - * - * @author Ceki - * @since 1.3 - */ -public class TokenConverter { - - - static final int IDENTITY = 0; - static final int INTEGER = 1; - static final int DATE = 1; - int type; - TokenConverter next; - - protected TokenConverter(int t) { - type = t; - } - - public TokenConverter getNext() { - return next; - } - - public void setNext(TokenConverter next) { - this.next = next; - } - - public int getType() { - return type; - } - - public void setType(int i) { - type = i; - } - -} +/** + * 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.rolling.helper; + + +/** + * TokenConverter offers some basic functionality used by more + * specific token converters. + *

+ * It basically sets up the chained architecture for tokens. It also forces + * derived classes to fix their type. + * + * @author Ceki + * @since 1.3 + */ +public class TokenConverter { + + + static final int IDENTITY = 0; + static final int INTEGER = 1; + static final int DATE = 1; + int type; + TokenConverter next; + + protected TokenConverter(int t) { + type = t; + } + + public TokenConverter getNext() { + return next; + } + + public void setNext(TokenConverter next) { + this.next = next; + } + + public int getType() { + return type; + } + + public void setType(int i) { + type = i; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/package.html b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/package.html index ba64fe0f7c6be947193c40d09629993b7ae728da..6c5e455880b2c47f670e88b787b855421c39a524 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/package.html @@ -1,11 +1,11 @@ - - - - - - - -

Internal helper classes used by {@link ch.qos.logback.core.rolling} package.

- -
- + + + + + + + +

Internal helper classes used by {@link ch.qos.logback.core.rolling} package.

+ +
+ diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/package.html b/logback-core/src/main/java/ch/qos/logback/core/rolling/package.html index 65fa6db7ffd26a6c67fd868e41bdaecd56a61201..b34dcc19b2097df8c79515cfe561f7419b2161c4 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/package.html @@ -1,20 +1,20 @@ - - - - - - - - - -

Implements various file rolling policies.

- -

The {@link ch.qos.logback.core.rolling.RollingFileAppender} class - serves as the linchpin of this package. Its behaviour is - controlled by two subcomponents of type {@link - ch.qos.logback.core.rolling.RollingPolicy} and {@link - ch.qos.logback.core.rolling.TriggeringPolicy}. -

- - + + + + + + + + + +

Implements various file rolling policies.

+ +

The {@link ch.qos.logback.core.rolling.RollingFileAppender} class + serves as the linchpin of this package. Its behaviour is + controlled by two subcomponents of type {@link + ch.qos.logback.core.rolling.RollingPolicy} and {@link + ch.qos.logback.core.rolling.TriggeringPolicy}. +

+ + \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java b/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java index 41966aa3fd00be017f74e1511c4daffabb182019..88d6d343b6646063047d1f4f1d24911ad1019185 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java @@ -1,52 +1,52 @@ -/** - * 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.sift; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.joran.spi.JoranException; - -public abstract class AppenderFactoryBase { - - final List eventList; - - protected AppenderFactoryBase(List eventList) { - this.eventList = new ArrayList(eventList); - removeHoardElement(); - - } - - void removeHoardElement() { - eventList.remove(0); - eventList.remove(eventList.size() - 1); - } - - public abstract SiftingJoranConfiguratorBase getSiftingJoranConfigurator(String k); - - Appender buildAppender(Context context, String discriminatingValue) throws JoranException { - SiftingJoranConfiguratorBase sjc = getSiftingJoranConfigurator(discriminatingValue); - sjc.setContext(context); - sjc.doConfigure(eventList); - return sjc.getAppender(); - } - - public List getEventList() { - return eventList; - } - -} +/** + * 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.sift; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.JoranException; + +public abstract class AppenderFactoryBase { + + final List eventList; + + protected AppenderFactoryBase(List eventList) { + this.eventList = new ArrayList(eventList); + removeHoardElement(); + + } + + void removeHoardElement() { + eventList.remove(0); + eventList.remove(eventList.size() - 1); + } + + public abstract SiftingJoranConfiguratorBase getSiftingJoranConfigurator(String k); + + Appender buildAppender(Context context, String discriminatingValue) throws JoranException { + SiftingJoranConfiguratorBase sjc = getSiftingJoranConfigurator(discriminatingValue); + sjc.setContext(context); + sjc.doConfigure(eventList); + return sjc.getAppender(); + } + + public List getEventList() { + return eventList; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java b/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java index 4837aebf8a64d4afdaa3bf71462d31152f4bbf56..de3cea314d3543da8e0172eba1118514870d6f3c 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java +++ b/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java @@ -1,32 +1,32 @@ -/** - * 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.sift; - -import java.util.List; - -import ch.qos.logback.core.Appender; - -public interface AppenderTracker { - - static int MILLIS_IN_ONE_SECOND = 1000; - static int THRESHOLD = 30 * 60 * MILLIS_IN_ONE_SECOND; // 30 minutes - - void put(String key, Appender value, long timestamp); - Appender get(String key, long timestamp); - void stopStaleAppenders(long timestamp); - List keyList(); - List> valueList(); - - +/** + * 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.sift; + +import java.util.List; + +import ch.qos.logback.core.Appender; + +public interface AppenderTracker { + + static int MILLIS_IN_ONE_SECOND = 1000; + static int THRESHOLD = 30 * 60 * MILLIS_IN_ONE_SECOND; // 30 minutes + + void put(String key, Appender value, long timestamp); + Appender get(String key, long timestamp); + void stopStaleAppenders(long timestamp); + List keyList(); + List> valueList(); + + } \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java b/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java index 20cc37c5a9f93fef36671a088b9c3d5c86010597..e6ef0f77c07c38e41f9a9a60c8a15193424f271c 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java +++ b/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java @@ -1,211 +1,211 @@ -/** - * 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.sift; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import ch.qos.logback.core.Appender; - -/** - * Track appenders by a key. When an appender is not used for - * longer than THRESHOLD, stop it. - * @author Ceki Gulcu - */ -public class AppenderTrackerImpl implements AppenderTracker { - - Map map = new HashMap(); - - Entry head; // least recently used entries are towards the head - Entry tail; // most recently used entries are towards the tail - - long lastCheck = 0; - - AppenderTrackerImpl() { - head = new Entry(null, null, 0); - tail = head; - } - - - public synchronized void put(String key, Appender value, long timestamp) { - Entry entry = map.get(key); - if (entry == null) { - entry = new Entry(key, value, timestamp); - map.put(key, entry); - } - moveToTail(entry); - } - - public synchronized Appender get(String key, long timestamp) { - Entry existing = map.get(key); - if (existing == null) { - return null; - } else { - existing.setTimestamp(timestamp); - moveToTail(existing); - return existing.value; - } - } - - - public synchronized void stopStaleAppenders(long now) { - if (lastCheck + MILLIS_IN_ONE_SECOND > now) { - return; - } - lastCheck = now; - while (head.value != null && isEntryStale(head,now)) { - Appender appender = head.value; - //System.out.println(" stopping "+appender); - appender.stop(); - removeHead(); - } - } - - public List keyList() { - List result = new LinkedList(); - Entry e = head; - while (e != tail) { - result.add(e.key); - e = e.next; - } - return result; - } - - - final private boolean isEntryStale(Entry entry, long now) { - return ((entry.timestamp + THRESHOLD) < now); - } - - - private void removeHead() { - // System.out.println("RemoveHead called"); - map.remove(head.key); - head = head.next; - head.prev = null; - } - - private void moveToTail(Entry e) { - rearrangePreexistingLinks(e); - rearrangeTailLinks(e); - } - - private void rearrangePreexistingLinks(Entry e) { - if (e.prev != null) { - e.prev.next = e.next; - } - if (e.next != null) { - e.next.prev = e.prev; - } - if (head == e) { - head = e.next; - } - } - - private void rearrangeTailLinks(Entry e) { - if (head == tail) { - head = e; - } - Entry preTail = tail.prev; - if (preTail != null) { - preTail.next = e; - } - e.prev = preTail; - e.next = tail; - tail.prev = e; - } - - public void dump() { - Entry e = head; - System.out.print("N:"); - while (e != null) { - // System.out.print(e+"->"); - System.out.print(e.key + ", "); - e = e.next; - } - System.out.println(); - } - - - - public List> valueList() { - List> result = new LinkedList>(); - Entry e = head; - while (e != tail) { - result.add(e.value); - e = e.next; - } - return result; - } - - // ================================================================ - private class Entry { - Entry next; - Entry prev; - - String key; - Appender value; - long timestamp; - - Entry(String k, Appender v, long timestamp) { - this.key = k; - this.value = v; - this.timestamp = timestamp; - } - -// public long getTimestamp() { -// return timestamp; -// } - - public void setTimestamp(long timestamp) { - this.timestamp = timestamp; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((key == null) ? 0 : key.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final Entry other = (Entry) obj; - if (key == null) { - if (other.key != null) - return false; - } else if (!key.equals(other.key)) - return false; - if (value == null) { - if (other.value != null) - return false; - } else if (!value.equals(other.value)) - return false; - return true; - } - - @Override - public String toString() { - return "(" + key + ", " + value + ")"; - } - } -} +/** + * 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.sift; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import ch.qos.logback.core.Appender; + +/** + * Track appenders by a key. When an appender is not used for + * longer than THRESHOLD, stop it. + * @author Ceki Gulcu + */ +public class AppenderTrackerImpl implements AppenderTracker { + + Map map = new HashMap(); + + Entry head; // least recently used entries are towards the head + Entry tail; // most recently used entries are towards the tail + + long lastCheck = 0; + + AppenderTrackerImpl() { + head = new Entry(null, null, 0); + tail = head; + } + + + public synchronized void put(String key, Appender value, long timestamp) { + Entry entry = map.get(key); + if (entry == null) { + entry = new Entry(key, value, timestamp); + map.put(key, entry); + } + moveToTail(entry); + } + + public synchronized Appender get(String key, long timestamp) { + Entry existing = map.get(key); + if (existing == null) { + return null; + } else { + existing.setTimestamp(timestamp); + moveToTail(existing); + return existing.value; + } + } + + + public synchronized void stopStaleAppenders(long now) { + if (lastCheck + MILLIS_IN_ONE_SECOND > now) { + return; + } + lastCheck = now; + while (head.value != null && isEntryStale(head,now)) { + Appender appender = head.value; + //System.out.println(" stopping "+appender); + appender.stop(); + removeHead(); + } + } + + public List keyList() { + List result = new LinkedList(); + Entry e = head; + while (e != tail) { + result.add(e.key); + e = e.next; + } + return result; + } + + + final private boolean isEntryStale(Entry entry, long now) { + return ((entry.timestamp + THRESHOLD) < now); + } + + + private void removeHead() { + // System.out.println("RemoveHead called"); + map.remove(head.key); + head = head.next; + head.prev = null; + } + + private void moveToTail(Entry e) { + rearrangePreexistingLinks(e); + rearrangeTailLinks(e); + } + + private void rearrangePreexistingLinks(Entry e) { + if (e.prev != null) { + e.prev.next = e.next; + } + if (e.next != null) { + e.next.prev = e.prev; + } + if (head == e) { + head = e.next; + } + } + + private void rearrangeTailLinks(Entry e) { + if (head == tail) { + head = e; + } + Entry preTail = tail.prev; + if (preTail != null) { + preTail.next = e; + } + e.prev = preTail; + e.next = tail; + tail.prev = e; + } + + public void dump() { + Entry e = head; + System.out.print("N:"); + while (e != null) { + // System.out.print(e+"->"); + System.out.print(e.key + ", "); + e = e.next; + } + System.out.println(); + } + + + + public List> valueList() { + List> result = new LinkedList>(); + Entry e = head; + while (e != tail) { + result.add(e.value); + e = e.next; + } + return result; + } + + // ================================================================ + private class Entry { + Entry next; + Entry prev; + + String key; + Appender value; + long timestamp; + + Entry(String k, Appender v, long timestamp) { + this.key = k; + this.value = v; + this.timestamp = timestamp; + } + +// public long getTimestamp() { +// return timestamp; +// } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((key == null) ? 0 : key.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Entry other = (Entry) obj; + if (key == null) { + if (other.key != null) + return false; + } else if (!key.equals(other.key)) + return false; + if (value == null) { + if (other.value != null) + return false; + } else if (!value.equals(other.value)) + return false; + return true; + } + + @Override + public String toString() { + return "(" + key + ", " + value + ")"; + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java b/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java index 1b049c80dc4c6f3176c4a3daa3b168b84e14f217..5bf0c716910a0f2681bfa1ea10e6b992ef853562 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java +++ b/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java @@ -1,44 +1,44 @@ -/** - * 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.sift; - -import ch.qos.logback.core.spi.LifeCycle; - -/** - * Implement this interface in order to compute a discriminating value for a - * given event of type <E>. - * - *

The returned value can depend on any data available at the time of the - * call, including data contained within the currently running thread. - * - * @author Ceki Gülcü - * - * @param - */ -public interface Discriminator extends LifeCycle { - - /** - * Given event 'e' return a discriminating value. - * - * @param e - * @return - */ - String getDiscriminatingValue(E e); - - /** - * - * @return - */ - String getKey(); -} +/** + * 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.sift; + +import ch.qos.logback.core.spi.LifeCycle; + +/** + * Implement this interface in order to compute a discriminating value for a + * given event of type <E>. + * + *

The returned value can depend on any data available at the time of the + * call, including data contained within the currently running thread. + * + * @author Ceki Gülcü + * + * @param + */ +public interface Discriminator extends LifeCycle { + + /** + * Given event 'e' return a discriminating value. + * + * @param e + * @return + */ + String getDiscriminatingValue(E e); + + /** + * + * @return + */ + String getKey(); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java index e117b5ae798db6fa9af2dd4032ecf7d7fe077e83..82c15e0c860b67649631dbaab554d910f7b91bc8 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java @@ -1,108 +1,108 @@ -/** - * 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.sift; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.UnsynchronizedAppenderBase; -import ch.qos.logback.core.joran.spi.JoranException; - -/** - * This appender serves as the base class for actual SiftingAppenders - * implemented by the logback-classic and logback-access modules. In a nutshell, - * a SiftingAppender contains other appenders which it can build dynamically - * depending on discriminating values supplied by event currently being - * processed. The built appender is specified as part of a configuration file. - * - * @author Ceki Gulcu - */ -public abstract class SiftingAppenderBase extends - UnsynchronizedAppenderBase { - - protected AppenderTracker appenderTracker = new AppenderTrackerImpl(); - AppenderFactoryBase appenderFactory; - - Discriminator discriminator; - - public void setAppenderFactory(AppenderFactoryBase appenderFactory) { - this.appenderFactory = appenderFactory; - } - - @Override - public void start() { - int errors = 0; - if (discriminator == null) { - addError("Missing discriminator. Aborting"); - errors++; - } - if (!discriminator.isStarted()) { - addError("Discriminator has not started successfully. Aborting"); - errors++; - } - if (errors == 0) { - super.start(); - } - } - - @Override - public void stop() { - for (Appender appender : appenderTracker.valueList()) { - appender.stop(); - } - } - - abstract protected long getTimestamp(E event); - - @Override - protected void append(E event) { - if (!isStarted()) { - return; - } - - String discriminatingValue = discriminator.getDiscriminatingValue(event); - long timestamp = getTimestamp(event); - - Appender appender = appenderTracker.get(discriminatingValue, timestamp); - - if (appender == null) { - try { - appender = appenderFactory.buildAppender(context, discriminatingValue); - if (appender != null) { - appenderTracker.put(discriminatingValue, appender, timestamp); - } - } catch (JoranException e) { - addError("Failed to build appender for [" + discriminatingValue + "]", e); - return; - } - } - appenderTracker.stopStaleAppenders(timestamp); - appender.doAppend(event); - } - - public Discriminator getDiscriminator() { - return discriminator; - } - - public void setDiscriminator(Discriminator discriminator) { - this.discriminator = discriminator; - } - - - public String getDiscriminatorKey() { - if(discriminator != null) { - return discriminator.getKey(); - } else { - return null; - } - } -} +/** + * 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.sift; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.UnsynchronizedAppenderBase; +import ch.qos.logback.core.joran.spi.JoranException; + +/** + * This appender serves as the base class for actual SiftingAppenders + * implemented by the logback-classic and logback-access modules. In a nutshell, + * a SiftingAppender contains other appenders which it can build dynamically + * depending on discriminating values supplied by event currently being + * processed. The built appender is specified as part of a configuration file. + * + * @author Ceki Gulcu + */ +public abstract class SiftingAppenderBase extends + UnsynchronizedAppenderBase { + + protected AppenderTracker appenderTracker = new AppenderTrackerImpl(); + AppenderFactoryBase appenderFactory; + + Discriminator discriminator; + + public void setAppenderFactory(AppenderFactoryBase appenderFactory) { + this.appenderFactory = appenderFactory; + } + + @Override + public void start() { + int errors = 0; + if (discriminator == null) { + addError("Missing discriminator. Aborting"); + errors++; + } + if (!discriminator.isStarted()) { + addError("Discriminator has not started successfully. Aborting"); + errors++; + } + if (errors == 0) { + super.start(); + } + } + + @Override + public void stop() { + for (Appender appender : appenderTracker.valueList()) { + appender.stop(); + } + } + + abstract protected long getTimestamp(E event); + + @Override + protected void append(E event) { + if (!isStarted()) { + return; + } + + String discriminatingValue = discriminator.getDiscriminatingValue(event); + long timestamp = getTimestamp(event); + + Appender appender = appenderTracker.get(discriminatingValue, timestamp); + + if (appender == null) { + try { + appender = appenderFactory.buildAppender(context, discriminatingValue); + if (appender != null) { + appenderTracker.put(discriminatingValue, appender, timestamp); + } + } catch (JoranException e) { + addError("Failed to build appender for [" + discriminatingValue + "]", e); + return; + } + } + appenderTracker.stopStaleAppenders(timestamp); + appender.doAppend(event); + } + + public Discriminator getDiscriminator() { + return discriminator; + } + + public void setDiscriminator(Discriminator discriminator) { + this.discriminator = discriminator; + } + + + public String getDiscriminatorKey() { + if(discriminator != null) { + return discriminator.getKey(); + } else { + return null; + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfiguratorBase.java b/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfiguratorBase.java index fad947667a85fd0d751db410337ed66e9ebfaad2..0524f3378b47303aa38a513ff449647878f5032c 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfiguratorBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfiguratorBase.java @@ -1,36 +1,36 @@ -/** - * 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.sift; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.joran.GenericConfigurator; -import ch.qos.logback.core.joran.action.NestedBasicPropertyIA; -import ch.qos.logback.core.joran.action.NestedComplexPropertyIA; -import ch.qos.logback.core.joran.spi.Interpreter; - -public abstract class SiftingJoranConfiguratorBase extends GenericConfigurator { - - @Override - protected void addImplicitRules(Interpreter interpreter) { - NestedComplexPropertyIA nestedComplexIA = new NestedComplexPropertyIA(); - nestedComplexIA.setContext(context); - interpreter.addImplicitAction(nestedComplexIA); - - NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA(); - nestedSimpleIA.setContext(context); - interpreter.addImplicitAction(nestedSimpleIA); - } - - abstract public Appender getAppender(); -} +/** + * 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.sift; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.joran.GenericConfigurator; +import ch.qos.logback.core.joran.action.NestedBasicPropertyIA; +import ch.qos.logback.core.joran.action.NestedComplexPropertyIA; +import ch.qos.logback.core.joran.spi.Interpreter; + +public abstract class SiftingJoranConfiguratorBase extends GenericConfigurator { + + @Override + protected void addImplicitRules(Interpreter interpreter) { + NestedComplexPropertyIA nestedComplexIA = new NestedComplexPropertyIA(); + nestedComplexIA.setContext(context); + interpreter.addImplicitAction(nestedComplexIA); + + NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA(); + nestedSimpleIA.setContext(context); + interpreter.addImplicitAction(nestedSimpleIA); + } + + abstract public Appender getAppender(); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachable.java b/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachable.java index ebdf97b62e871f51649b435e67e33d162523f6b8..fb453f94f96bcee05cf3e0b9c62cab0de5071b9a 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachable.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachable.java @@ -1,62 +1,62 @@ -/** - * 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.spi; - -import java.util.Iterator; - -import ch.qos.logback.core.Appender; - -/** - * Interface for attaching appenders to objects. - * - * @author Ceki Gülcü - */ -public interface AppenderAttachable { - /** - * Add an appender. - */ - public void addAppender(Appender newAppender); - - /** - * Get an iterator for appenders contained in the parent object. - */ - public Iterator> iteratorForAppenders(); - - /** - * Get an appender by name. - */ - public Appender getAppender(String name); - - /** - * Returns true if the specified appender is in list of - * attached attached, false otherwise. - */ - public boolean isAttached(Appender appender); - - /** - * Detach and stop all previously added appenders. - */ - void detachAndStopAllAppenders(); - - /** - * Detach the appender passed as parameter from the list of appenders. - */ - boolean detachAppender(Appender appender); - - /** - * Detach the appender with the name passed as parameter from the list of - * appenders. - */ - boolean detachAppender(String name); -} +/** + * 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.spi; + +import java.util.Iterator; + +import ch.qos.logback.core.Appender; + +/** + * Interface for attaching appenders to objects. + * + * @author Ceki Gülcü + */ +public interface AppenderAttachable { + /** + * Add an appender. + */ + public void addAppender(Appender newAppender); + + /** + * Get an iterator for appenders contained in the parent object. + */ + public Iterator> iteratorForAppenders(); + + /** + * Get an appender by name. + */ + public Appender getAppender(String name); + + /** + * Returns true if the specified appender is in list of + * attached attached, false otherwise. + */ + public boolean isAttached(Appender appender); + + /** + * Detach and stop all previously added appenders. + */ + void detachAndStopAllAppenders(); + + /** + * Detach the appender passed as parameter from the list of appenders. + */ + boolean detachAppender(Appender appender); + + /** + * Detach the appender with the name passed as parameter from the list of + * appenders. + */ + boolean detachAppender(String name); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachableImpl.java b/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachableImpl.java index f4b20cb8f9ca4dacb0559bed055ff0b5cbb24f2c..e8870995e288c824339d69e1908df3b580bcb8f5 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachableImpl.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachableImpl.java @@ -1,197 +1,197 @@ -/** - * 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.spi; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import ch.qos.logback.core.Appender; - -/** - * A ReentrantReadWriteLock based implementation of the - * {@link AppenderAttachable} interface. - * - * @author Ceki Gülcü - */ -public class AppenderAttachableImpl implements AppenderAttachable { - - final private List> appenderList = new ArrayList>(); - final private ReadWriteLock rwLock = new ReentrantReadWriteLock(); - private final Lock r = rwLock.readLock(); - private final Lock w = rwLock.writeLock(); - - /** - * Attach an appender. If the appender is already in the list in won't be - * added again. - */ - public void addAppender(Appender newAppender) { - if (newAppender == null) { - throw new IllegalArgumentException("Null argument disallowed"); - } - w.lock(); - try { - if (!appenderList.contains(newAppender)) { - appenderList.add(newAppender); - } - } finally { - w.unlock(); - } - } - - /** - * Call the doAppend method on all attached appenders. - */ - public int appendLoopOnAppenders(E e) { - int size = 0; - r.lock(); - try { - for (Appender appender : appenderList) { - appender.doAppend(e); - size++; - } - } finally { - r.unlock(); - } - return size; - } - - /** - * Get all attached appenders as an Enumeration. If there are no attached - * appenders null is returned. - * - * @return Iterator An iterator of attached appenders. - */ - public Iterator> iteratorForAppenders() { - List> copy; - r.lock(); - try { - copy = new ArrayList>(appenderList); - } finally { - r.unlock(); - } - return copy.iterator(); - } - - /** - * Look for an attached appender named as name. - * - *

Return the appender with that name if in the list. Return null - * otherwise. - * - */ - public Appender getAppender(String name) { - if (name == null) { - return null; - } - Appender found = null; - - r.lock(); - try { - for (Appender appender : appenderList) { - if (name.equals(appender.getName())) { - found = appender; - break; - } - } - } finally { - r.unlock(); - } - return found; - } - - /** - * Returns true if the specified appender is in the list of - * attached appenders, false otherwise. - * - * @since 1.2 - */ - public boolean isAttached(Appender appender) { - if (appender == null) { - return false; - } - boolean attached = false; - r.lock(); - try { - for (Appender a : appenderList) { - if (a == appender) { - attached = true; - break; - } - } - } finally { - r.unlock(); - } - return attached; - } - - /** - * Remove and stop all previously attached appenders. - */ - public void detachAndStopAllAppenders() { - w.lock(); - try { - for (Appender a : appenderList) { - a.stop(); - } - appenderList.clear(); - } finally { - w.unlock(); - } - } - - /** - * Remove the appender passed as parameter form the list of attached - * appenders. - */ - public boolean detachAppender(Appender appender) { - if (appender == null) { - return false; - } - boolean result; - w.lock(); - try { - result = appenderList.remove(appender); - } finally { - w.unlock(); - } - return result; - } - - /** - * Remove the appender with the name passed as parameter form the list of - * appenders. - */ - public boolean detachAppender(String name) { - if (name == null) { - return false; - } - boolean removed = false; - w.lock(); - try { - for (Appender a : appenderList) { - if (name.equals((a).getName())) { - removed = appenderList.remove(a); - break; - } - } - } finally { - w.unlock(); - } - return removed; - } -} +/** + * 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.spi; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import ch.qos.logback.core.Appender; + +/** + * A ReentrantReadWriteLock based implementation of the + * {@link AppenderAttachable} interface. + * + * @author Ceki Gülcü + */ +public class AppenderAttachableImpl implements AppenderAttachable { + + final private List> appenderList = new ArrayList>(); + final private ReadWriteLock rwLock = new ReentrantReadWriteLock(); + private final Lock r = rwLock.readLock(); + private final Lock w = rwLock.writeLock(); + + /** + * Attach an appender. If the appender is already in the list in won't be + * added again. + */ + public void addAppender(Appender newAppender) { + if (newAppender == null) { + throw new IllegalArgumentException("Null argument disallowed"); + } + w.lock(); + try { + if (!appenderList.contains(newAppender)) { + appenderList.add(newAppender); + } + } finally { + w.unlock(); + } + } + + /** + * Call the doAppend method on all attached appenders. + */ + public int appendLoopOnAppenders(E e) { + int size = 0; + r.lock(); + try { + for (Appender appender : appenderList) { + appender.doAppend(e); + size++; + } + } finally { + r.unlock(); + } + return size; + } + + /** + * Get all attached appenders as an Enumeration. If there are no attached + * appenders null is returned. + * + * @return Iterator An iterator of attached appenders. + */ + public Iterator> iteratorForAppenders() { + List> copy; + r.lock(); + try { + copy = new ArrayList>(appenderList); + } finally { + r.unlock(); + } + return copy.iterator(); + } + + /** + * Look for an attached appender named as name. + * + *

Return the appender with that name if in the list. Return null + * otherwise. + * + */ + public Appender getAppender(String name) { + if (name == null) { + return null; + } + Appender found = null; + + r.lock(); + try { + for (Appender appender : appenderList) { + if (name.equals(appender.getName())) { + found = appender; + break; + } + } + } finally { + r.unlock(); + } + return found; + } + + /** + * Returns true if the specified appender is in the list of + * attached appenders, false otherwise. + * + * @since 1.2 + */ + public boolean isAttached(Appender appender) { + if (appender == null) { + return false; + } + boolean attached = false; + r.lock(); + try { + for (Appender a : appenderList) { + if (a == appender) { + attached = true; + break; + } + } + } finally { + r.unlock(); + } + return attached; + } + + /** + * Remove and stop all previously attached appenders. + */ + public void detachAndStopAllAppenders() { + w.lock(); + try { + for (Appender a : appenderList) { + a.stop(); + } + appenderList.clear(); + } finally { + w.unlock(); + } + } + + /** + * Remove the appender passed as parameter form the list of attached + * appenders. + */ + public boolean detachAppender(Appender appender) { + if (appender == null) { + return false; + } + boolean result; + w.lock(); + try { + result = appenderList.remove(appender); + } finally { + w.unlock(); + } + return result; + } + + /** + * Remove the appender with the name passed as parameter form the list of + * appenders. + */ + public boolean detachAppender(String name) { + if (name == null) { + return false; + } + boolean removed = false; + w.lock(); + try { + for (Appender a : appenderList) { + if (name.equals((a).getName())) { + removed = appenderList.remove(a); + break; + } + } + } finally { + w.unlock(); + } + return removed; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAware.java b/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAware.java index f6fbb52330c94d481cada9fa711684ca5279b3c9..fa13a0c571ebac31b6b74f0a58540a416d20e1b1 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAware.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAware.java @@ -1,38 +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.spi; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.status.Status; - - -public interface ContextAware { - - public void setContext(Context context); - public Context getContext(); - - public void addStatus(Status status); - public void addInfo(String msg); - - public void addInfo(String msg, Throwable ex); - - public void addWarn(String msg); - - public void addWarn(String msg, Throwable ex); - - public void addError(String msg); - - public void addError(String msg, Throwable ex); - -} +/** + * 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.spi; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.status.Status; + + +public interface ContextAware { + + public void setContext(Context context); + public Context getContext(); + + public void addStatus(Status status); + public void addInfo(String msg); + + public void addInfo(String msg, Throwable ex); + + public void addWarn(String msg); + + public void addWarn(String msg, Throwable ex); + + public void addError(String msg); + + public void addError(String msg, Throwable ex); + +} 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 72e31f6f607a944d3d17d753de37a7e08726f1a6..133bbbf7ed00e8e27eec83ca61dabfadb270bada 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 @@ -1,98 +1,98 @@ -/** - * 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.spi; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.status.ErrorStatus; -import ch.qos.logback.core.status.InfoStatus; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.status.WarnStatus; - -/** - * A helper class that implements ContextAware methods. A class can implement - * the ContextAware interface by deriving from this class. - * - * @author Ceki Gülcü - */ -public class ContextAwareBase implements ContextAware { - private int noContextWarning = 0; - protected Context context; - - public void setContext(Context context) { - if (this.context == null) { - this.context = context; - } else if (this.context != context) { - throw new IllegalStateException("Context has been already set"); - } - } - - public Context getContext() { - return this.context; - } - - public StatusManager getStatusManager() { - if (context == null) { - return null; - } - return context.getStatusManager(); - } - - /** - * The declared origin of status messages. By default 'this'. Derived classes may override this - * method to declare other origin. - * - * @return the declared origin, by default 'this' - */ - protected Object getDeclaredOrigin() { - return this; - } - - public void addStatus(Status status) { - if (context == null) { - if (noContextWarning++ == 0) { - System.out.println("LOGBACK: No context given for " + this); - } - return; - } - StatusManager sm = context.getStatusManager(); - if (sm != null) { - sm.add(status); - } - } - - public void addInfo(String msg) { - addStatus(new InfoStatus(msg, getDeclaredOrigin())); - } - - public void addInfo(String msg, Throwable ex) { - addStatus(new InfoStatus(msg, getDeclaredOrigin(), ex)); - } - - public void addWarn(String msg) { - addStatus(new WarnStatus(msg, getDeclaredOrigin())); - } - - public void addWarn(String msg, Throwable ex) { - addStatus(new WarnStatus(msg, getDeclaredOrigin(), ex)); - } - - public void addError(String msg) { - addStatus(new ErrorStatus(msg, getDeclaredOrigin())); - } - - public void addError(String msg, Throwable ex) { - addStatus(new ErrorStatus(msg, getDeclaredOrigin(), ex)); - } -} +/** + * 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.spi; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.WarnStatus; + +/** + * A helper class that implements ContextAware methods. A class can implement + * the ContextAware interface by deriving from this class. + * + * @author Ceki Gülcü + */ +public class ContextAwareBase implements ContextAware { + private int noContextWarning = 0; + protected Context context; + + public void setContext(Context context) { + if (this.context == null) { + this.context = context; + } else if (this.context != context) { + throw new IllegalStateException("Context has been already set"); + } + } + + public Context getContext() { + return this.context; + } + + public StatusManager getStatusManager() { + if (context == null) { + return null; + } + return context.getStatusManager(); + } + + /** + * The declared origin of status messages. By default 'this'. Derived classes may override this + * method to declare other origin. + * + * @return the declared origin, by default 'this' + */ + protected Object getDeclaredOrigin() { + return this; + } + + public void addStatus(Status status) { + if (context == null) { + if (noContextWarning++ == 0) { + System.out.println("LOGBACK: No context given for " + this); + } + return; + } + StatusManager sm = context.getStatusManager(); + if (sm != null) { + sm.add(status); + } + } + + public void addInfo(String msg) { + addStatus(new InfoStatus(msg, getDeclaredOrigin())); + } + + public void addInfo(String msg, Throwable ex) { + addStatus(new InfoStatus(msg, getDeclaredOrigin(), ex)); + } + + public void addWarn(String msg) { + addStatus(new WarnStatus(msg, getDeclaredOrigin())); + } + + public void addWarn(String msg, Throwable ex) { + addStatus(new WarnStatus(msg, getDeclaredOrigin(), ex)); + } + + public void addError(String msg) { + addStatus(new ErrorStatus(msg, getDeclaredOrigin())); + } + + public void addError(String msg, Throwable ex) { + addStatus(new ErrorStatus(msg, getDeclaredOrigin(), ex)); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareImpl.java b/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareImpl.java index 9fc09821993e4f6162fe00f9b3afd8cd41cd1918..9512dd1494f9320fa07ab125b7231ea5e60bdd68 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareImpl.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareImpl.java @@ -1,100 +1,100 @@ -/** - * 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.spi; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.status.ErrorStatus; -import ch.qos.logback.core.status.InfoStatus; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.status.WarnStatus; - - -/** - * A helper class that implements ContextAware methods. Use this class to - * implement the ContextAware interface by composition. - * - * @author Ceki Gülcü - */ -public class ContextAwareImpl implements ContextAware { - - private int noContextWarning = 0; - protected Context context; - final Object origin; - - public ContextAwareImpl(Object origin) { - this.origin = origin; - } - - protected Object getOrigin() { - return origin; - } - - public void setContext(Context context) { - if (this.context == null) { - this.context = context; - } else if (this.context != context) { - throw new IllegalStateException("Context has been already set"); - } - } - - public Context getContext() { - return this.context; - } - - public StatusManager getStatusManager() { - if (context == null) { - return null; - } - return context.getStatusManager(); - } - - public void addStatus(Status status) { - if (context == null) { - if (noContextWarning++ == 0) { - System.out.println("LOGBACK: No context given for " + this); - } - return; - } - StatusManager sm = context.getStatusManager(); - if (sm != null) { - sm.add(status); - } - } - - public void addInfo(String msg) { - addStatus(new InfoStatus(msg, getOrigin())); - } - - public void addInfo(String msg, Throwable ex) { - addStatus(new InfoStatus(msg, getOrigin(), ex)); - } - - public void addWarn(String msg) { - addStatus(new WarnStatus(msg, getOrigin())); - } - - public void addWarn(String msg, Throwable ex) { - addStatus(new WarnStatus(msg, getOrigin(), ex)); - } - - public void addError(String msg) { - addStatus(new ErrorStatus(msg, getOrigin())); - } - - public void addError(String msg, Throwable ex) { - addStatus(new ErrorStatus(msg, getOrigin(), ex)); - } - -} +/** + * 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.spi; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.WarnStatus; + + +/** + * A helper class that implements ContextAware methods. Use this class to + * implement the ContextAware interface by composition. + * + * @author Ceki Gülcü + */ +public class ContextAwareImpl implements ContextAware { + + private int noContextWarning = 0; + protected Context context; + final Object origin; + + public ContextAwareImpl(Object origin) { + this.origin = origin; + } + + protected Object getOrigin() { + return origin; + } + + public void setContext(Context context) { + if (this.context == null) { + this.context = context; + } else if (this.context != context) { + throw new IllegalStateException("Context has been already set"); + } + } + + public Context getContext() { + return this.context; + } + + public StatusManager getStatusManager() { + if (context == null) { + return null; + } + return context.getStatusManager(); + } + + public void addStatus(Status status) { + if (context == null) { + if (noContextWarning++ == 0) { + System.out.println("LOGBACK: No context given for " + this); + } + return; + } + StatusManager sm = context.getStatusManager(); + if (sm != null) { + sm.add(status); + } + } + + public void addInfo(String msg) { + addStatus(new InfoStatus(msg, getOrigin())); + } + + public void addInfo(String msg, Throwable ex) { + addStatus(new InfoStatus(msg, getOrigin(), ex)); + } + + public void addWarn(String msg) { + addStatus(new WarnStatus(msg, getOrigin())); + } + + public void addWarn(String msg, Throwable ex) { + addStatus(new WarnStatus(msg, getOrigin(), ex)); + } + + public void addError(String msg) { + addStatus(new ErrorStatus(msg, getOrigin())); + } + + public void addError(String msg, Throwable ex) { + addStatus(new ErrorStatus(msg, getOrigin(), ex)); + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/FilterAttachable.java b/logback-core/src/main/java/ch/qos/logback/core/spi/FilterAttachable.java index 5ca9f5690b4e79a5c67e990ec03072c1d8af73bf..72eda36e973f299001c346bcadbd1768514f959d 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/FilterAttachable.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/FilterAttachable.java @@ -1,55 +1,55 @@ -/** - * 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.spi; - -import java.util.List; - -import ch.qos.logback.core.filter.Filter; - -/** - * Interface for attaching filters to objects. - * - * @author Ceki Gülcü - */ -public interface FilterAttachable { - /** - * Add a filter. - */ - public void addFilter(Filter newFilter); - - /** - * Get first filter in the chain. - * - * @deprecated This method will be removed in future versions. Please use - * {@link #getCopyOfAttachedFiltersList()} method instead. - */ - public Filter getFirstFilter(); - - public void clearAllFilters(); - - /** - * Get a copy of all the filters contained within this FilterAttachable - * object. - * - * @return all attached filters as a list - */ - public List> getCopyOfAttachedFiltersList(); - - /** - * Loop through the filters in the chain. As soon as a filter decides on - * ACCEPT or DENY, then that value is returned. If all of the filters return - * NEUTRAL, then NEUTRAL is returned. - */ - public FilterReply getFilterChainDecision(E event); -} +/** + * 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.spi; + +import java.util.List; + +import ch.qos.logback.core.filter.Filter; + +/** + * Interface for attaching filters to objects. + * + * @author Ceki Gülcü + */ +public interface FilterAttachable { + /** + * Add a filter. + */ + public void addFilter(Filter newFilter); + + /** + * Get first filter in the chain. + * + * @deprecated This method will be removed in future versions. Please use + * {@link #getCopyOfAttachedFiltersList()} method instead. + */ + public Filter getFirstFilter(); + + public void clearAllFilters(); + + /** + * Get a copy of all the filters contained within this FilterAttachable + * object. + * + * @return all attached filters as a list + */ + public List> getCopyOfAttachedFiltersList(); + + /** + * Loop through the filters in the chain. As soon as a filter decides on + * ACCEPT or DENY, then that value is returned. If all of the filters return + * NEUTRAL, then NEUTRAL is returned. + */ + public FilterReply getFilterChainDecision(E event); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/FilterAttachableImpl.java b/logback-core/src/main/java/ch/qos/logback/core/spi/FilterAttachableImpl.java index b4af814506c3f52ce48a0b59b1fca4538dc1ea31..2b72bd45495bba5e66f98d415a7844040b136b06 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/FilterAttachableImpl.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/FilterAttachableImpl.java @@ -1,74 +1,74 @@ -/** - * 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.spi; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -import ch.qos.logback.core.filter.Filter; - -/** - * Implementation of FilterAttachable. - * - * @author Ceki Gülcü - */ -final public class FilterAttachableImpl implements FilterAttachable { - - CopyOnWriteArrayList> filterList = new CopyOnWriteArrayList>(); - - /** - * Add a filter to end of the filter list. - */ - public void addFilter(Filter newFilter) { - filterList.add(newFilter); - } - - /** - * Get first filter in the chain. - */ - public Filter getFirstFilter() { - if (filterList.size() > 0) { - return filterList.get(0); - } else { - return null; - } - } - - /** - * Clear the filter chain - */ - public void clearAllFilters() { - filterList.clear(); - } - - /** - * Loop through the filters in the list. As soon as a filter decides on - * ACCEPT or DENY, then that value is returned. If all of the filters return - * NEUTRAL, then NEUTRAL is returned. - */ - public FilterReply getFilterChainDecision(E event) { - for (Filter f : filterList) { - final FilterReply r = f.decide(event); - if (r == FilterReply.DENY || r == FilterReply.ACCEPT) { - return r; - } - } - return FilterReply.NEUTRAL; - } - - public List> getCopyOfAttachedFiltersList() { - return new ArrayList>(filterList); - } -} +/** + * 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.spi; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import ch.qos.logback.core.filter.Filter; + +/** + * Implementation of FilterAttachable. + * + * @author Ceki Gülcü + */ +final public class FilterAttachableImpl implements FilterAttachable { + + CopyOnWriteArrayList> filterList = new CopyOnWriteArrayList>(); + + /** + * Add a filter to end of the filter list. + */ + public void addFilter(Filter newFilter) { + filterList.add(newFilter); + } + + /** + * Get first filter in the chain. + */ + public Filter getFirstFilter() { + if (filterList.size() > 0) { + return filterList.get(0); + } else { + return null; + } + } + + /** + * Clear the filter chain + */ + public void clearAllFilters() { + filterList.clear(); + } + + /** + * Loop through the filters in the list. As soon as a filter decides on + * ACCEPT or DENY, then that value is returned. If all of the filters return + * NEUTRAL, then NEUTRAL is returned. + */ + public FilterReply getFilterChainDecision(E event) { + for (Filter f : filterList) { + final FilterReply r = f.decide(event); + if (r == FilterReply.DENY || r == FilterReply.ACCEPT) { + return r; + } + } + return FilterReply.NEUTRAL; + } + + public List> getCopyOfAttachedFiltersList() { + return new ArrayList>(filterList); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/FilterReply.java b/logback-core/src/main/java/ch/qos/logback/core/spi/FilterReply.java index 3278536baba75c9a54056cba7c6a7a22f97d6acc..602eabb07cabfa6a41a622c09f2210455840c0c8 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/FilterReply.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/FilterReply.java @@ -1,34 +1,34 @@ -/** - * 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.spi; - - -/** - * - * This enum represents the possible replies that a filtering component - * in logback can return. It is used by implementations of both - * {@link ch.qos.logback.core.filter.Filter} and - * {@link ch.qos.logback.classic.turbo.TurboFilter} abstract classes. - * - * Based on the order that the FilterReply values are declared, - * FilterReply.ACCEPT.compareTo(FilterReply.DENY) will return - * a positive value. - * - * @author Sébastien Pennec - */ -public enum FilterReply { - DENY, - NEUTRAL, - ACCEPT; -} +/** + * 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.spi; + + +/** + * + * This enum represents the possible replies that a filtering component + * in logback can return. It is used by implementations of both + * {@link ch.qos.logback.core.filter.Filter} and + * {@link ch.qos.logback.classic.turbo.TurboFilter} abstract classes. + * + * Based on the order that the FilterReply values are declared, + * FilterReply.ACCEPT.compareTo(FilterReply.DENY) will return + * a positive value. + * + * @author Sébastien Pennec + */ +public enum FilterReply { + DENY, + NEUTRAL, + ACCEPT; +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/LifeCycle.java b/logback-core/src/main/java/ch/qos/logback/core/spi/LifeCycle.java index 935f14e3918f473a78c70cc9be4400a9d57038d1..bdd772b2ec2278a5b5c1dd584e84e592ae4c281b 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/LifeCycle.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/LifeCycle.java @@ -1,22 +1,22 @@ -/** - * 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.spi; - -public interface LifeCycle { - - public void start(); - public void stop(); - public boolean isStarted(); - -} +/** + * 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.spi; + +public interface LifeCycle { + + public void start(); + public void stop(); + public boolean isStarted(); + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/PreSerializationTransformer.java b/logback-core/src/main/java/ch/qos/logback/core/spi/PreSerializationTransformer.java index 50dc5639eeeb0c4c2370ec987e478bae2e790863..3fd9ad57d2d23f0d983e671c67c61669bd8cd772 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/PreSerializationTransformer.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/PreSerializationTransformer.java @@ -1,28 +1,28 @@ -/** - * 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.spi; - -import java.io.Serializable; - -/** - * PreSerializationTransformer instances have the responsibility to transform - * object into a presumably equivalent serializable representation. - * - * @author Ceki Gülcü - * - * @param - */ -public interface PreSerializationTransformer { - Serializable transform(E event); -} +/** + * 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.spi; + +import java.io.Serializable; + +/** + * PreSerializationTransformer instances have the responsibility to transform + * object into a presumably equivalent serializable representation. + * + * @author Ceki Gülcü + * + * @param + */ +public interface PreSerializationTransformer { + Serializable transform(E event); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/PropertyContainer.java b/logback-core/src/main/java/ch/qos/logback/core/spi/PropertyContainer.java index e6723ee0aa5f5d560e45a6e585d619c543f9f75b..10c2993c308aba3f67cdee1bee431bc03f342aac 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/PropertyContainer.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/PropertyContainer.java @@ -1,19 +1,19 @@ -/** - * 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.spi; - -public interface PropertyContainer { - - public String getProperty(String key); -} +/** + * 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.spi; + +public interface PropertyContainer { + + public String getProperty(String key); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/package.html b/logback-core/src/main/java/ch/qos/logback/core/spi/package.html index bc2f7508e492de7f6ba14a5474f5fa4429572730..8e655fc9db1f129e66ace97926f359227110ed02 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/package.html @@ -1,15 +1,15 @@ - - - - - - - - - -

Contains core functionnalities of logback, such as -@link{ch.qos.logback.core.spi.AppenderAttachable} and -@link{ch.qos.logback.core.spi.LifeCycle}.

- - - + + + + + + + + + +

Contains core functionnalities of logback, such as +@link{ch.qos.logback.core.spi.AppenderAttachable} and +@link{ch.qos.logback.core.spi.LifeCycle}.

+ + + diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/ErrorStatus.java b/logback-core/src/main/java/ch/qos/logback/core/status/ErrorStatus.java index 2ebb117f717c7a3e8a503a5b3f358d3f9d3765fd..ec32261b9c281106fd5e3e0ee44a490b5ed1fea3 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/ErrorStatus.java +++ b/logback-core/src/main/java/ch/qos/logback/core/status/ErrorStatus.java @@ -1,28 +1,28 @@ -/** - * 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.status; - - - -public class ErrorStatus extends StatusBase { - - public ErrorStatus(String msg, Object origin) { - super(Status.ERROR, msg, origin); - } - - public ErrorStatus(String msg, Object origin, Throwable t) { - super(Status.ERROR, msg, origin, t); - } - - } +/** + * 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.status; + + + +public class ErrorStatus extends StatusBase { + + public ErrorStatus(String msg, Object origin) { + super(Status.ERROR, msg, origin); + } + + public ErrorStatus(String msg, Object origin, Throwable t) { + super(Status.ERROR, msg, origin, t); + } + + } diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/InfoStatus.java b/logback-core/src/main/java/ch/qos/logback/core/status/InfoStatus.java index 017dcb1210be7bb110de84048261134cc1b52550..5365b4e12bd0e62f3e0f61f796bfa097526c1372 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/InfoStatus.java +++ b/logback-core/src/main/java/ch/qos/logback/core/status/InfoStatus.java @@ -1,27 +1,27 @@ -/** - * 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.status; - - - -public class InfoStatus extends StatusBase { - public InfoStatus(String msg, Object origin) { - super(Status.INFO, msg, origin); - } - - public InfoStatus(String msg, Object origin, Throwable t) { - super(Status.INFO, msg, origin, t); - } - - } +/** + * 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.status; + + + +public class InfoStatus extends StatusBase { + public InfoStatus(String msg, Object origin) { + super(Status.INFO, msg, origin); + } + + public InfoStatus(String msg, Object origin, Throwable t) { + super(Status.INFO, msg, origin, t); + } + + } diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/OnConsoleStatusListener.java b/logback-core/src/main/java/ch/qos/logback/core/status/OnConsoleStatusListener.java index ae617da9178fb55b09f1d751f1e8b1ccec70136f..9b6ea49406cae48650a1fe57b5f4dff9a964c65c 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/OnConsoleStatusListener.java +++ b/logback-core/src/main/java/ch/qos/logback/core/status/OnConsoleStatusListener.java @@ -1,32 +1,32 @@ -/** - * 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.status; - -import ch.qos.logback.core.util.StatusPrinter; - -/** - * Print all new incoming status messages on the console. - * - * @author Ceki Gülcü - * - */ -public class OnConsoleStatusListener implements StatusListener { - - - public void addStatusEvent(Status status) { - StringBuilder sb = new StringBuilder(); - StatusPrinter.buildStr(sb, "", status); - System.out.print(sb); - } -} +/** + * 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.status; + +import ch.qos.logback.core.util.StatusPrinter; + +/** + * Print all new incoming status messages on the console. + * + * @author Ceki Gülcü + * + */ +public class OnConsoleStatusListener implements StatusListener { + + + public void addStatusEvent(Status status) { + StringBuilder sb = new StringBuilder(); + StatusPrinter.buildStr(sb, "", status); + System.out.print(sb); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/Status.java b/logback-core/src/main/java/ch/qos/logback/core/status/Status.java index 152d97daff066143f48faa857d887468950a0039..68c6bf670e5403b782fb287abd330cea68526f99 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/Status.java +++ b/logback-core/src/main/java/ch/qos/logback/core/status/Status.java @@ -1,37 +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.status; - -import java.util.Iterator; - - -public interface Status { - - public final int INFO = 0; - public final int WARN = 1; - public final int ERROR = 2; - - int getLevel(); - int getEffectiveLevel(); - Object getOrigin(); - String getMessage(); - Throwable getThrowable(); - Long getDate(); - - public boolean hasChildren(); - public void add(Status child); - public boolean remove(Status child); - public Iterator iterator(); - -} +/** + * 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.status; + +import java.util.Iterator; + + +public interface Status { + + public final int INFO = 0; + public final int WARN = 1; + public final int ERROR = 2; + + int getLevel(); + int getEffectiveLevel(); + Object getOrigin(); + String getMessage(); + Throwable getThrowable(); + Long getDate(); + + public boolean hasChildren(); + public void add(Status child); + public boolean remove(Status child); + public Iterator iterator(); + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java b/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java index b715c116d34dafbb102558246e5d6249e2fb22c2..c10e92600129b1e55ee4f863afbb8112b379d1da 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java @@ -1,175 +1,175 @@ -/** - * 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.status; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -abstract public class StatusBase implements Status { - - static private final List EMPTY_LIST = new ArrayList(0); - - int level; - final String message; - final Object origin; - List childrenList; - Throwable throwable; - long date; - - StatusBase(int level, String msg, Object origin) { - this(level, msg, origin, null); - } - - StatusBase(int level, String msg, Object origin, Throwable t) { - this.level = level; - this.message = msg; - this.origin = origin; - this.throwable = t; - this.date = System.currentTimeMillis(); - } - - public synchronized void add(Status child) { - if (child == null) { - throw new NullPointerException("Null values are not valid Status."); - } - if (childrenList == null) { - childrenList = new ArrayList(); - } - childrenList.add(child); - } - - public synchronized boolean hasChildren() { - return ((childrenList != null) && (childrenList.size() > 0)); - } - - public synchronized Iterator iterator() { - if (childrenList != null) { - return childrenList.iterator(); - } else { - return EMPTY_LIST.iterator(); - } - } - - public synchronized boolean remove(Status statusToRemove) { - if (childrenList == null) { - return false; - } - // TODO also search in childrens' children - return childrenList.remove(statusToRemove); - } - - public int getLevel() { - return level; - } - - // status messages are not supposed to contains cycles. - // cyclic status arrangements are like to cause deadlocks - // when this method is called from different thread on - // different status objects lying on the same cycle - public synchronized int getEffectiveLevel() { - int result = level; - int effLevel; - - Iterator it = iterator(); - Status s; - while (it.hasNext()) { - s = (Status) it.next(); - effLevel = s.getEffectiveLevel(); - if (effLevel > result) { - result = effLevel; - } - } - return result; - } - - public String getMessage() { - return message; - } - - public Object getOrigin() { - return origin; - } - - public Throwable getThrowable() { - return throwable; - } - - public Long getDate() { - return date; - } - - /** - * @Override - */ - public String toString() { - StringBuffer buf = new StringBuffer(); - switch (getEffectiveLevel()) { - case INFO: - buf.append("INFO"); - break; - case WARN: - buf.append("WARN"); - break; - case ERROR: - buf.append("ERROR"); - break; - } - if (origin != null) { - buf.append(" in "); - buf.append(origin); - buf.append(" -"); - } - - buf.append(" "); - buf.append(message); - - if (throwable != null) { - buf.append(" "); - buf.append(throwable); - } - - return buf.toString(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + level; - result = prime * result + ((message == null) ? 0 : message.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final StatusBase other = (StatusBase) obj; - if (level != other.level) - return false; - if (message == null) { - if (other.message != null) - return false; - } else if (!message.equals(other.message)) - return false; - return true; - } - - -} +/** + * 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.status; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +abstract public class StatusBase implements Status { + + static private final List EMPTY_LIST = new ArrayList(0); + + int level; + final String message; + final Object origin; + List childrenList; + Throwable throwable; + long date; + + StatusBase(int level, String msg, Object origin) { + this(level, msg, origin, null); + } + + StatusBase(int level, String msg, Object origin, Throwable t) { + this.level = level; + this.message = msg; + this.origin = origin; + this.throwable = t; + this.date = System.currentTimeMillis(); + } + + public synchronized void add(Status child) { + if (child == null) { + throw new NullPointerException("Null values are not valid Status."); + } + if (childrenList == null) { + childrenList = new ArrayList(); + } + childrenList.add(child); + } + + public synchronized boolean hasChildren() { + return ((childrenList != null) && (childrenList.size() > 0)); + } + + public synchronized Iterator iterator() { + if (childrenList != null) { + return childrenList.iterator(); + } else { + return EMPTY_LIST.iterator(); + } + } + + public synchronized boolean remove(Status statusToRemove) { + if (childrenList == null) { + return false; + } + // TODO also search in childrens' children + return childrenList.remove(statusToRemove); + } + + public int getLevel() { + return level; + } + + // status messages are not supposed to contains cycles. + // cyclic status arrangements are like to cause deadlocks + // when this method is called from different thread on + // different status objects lying on the same cycle + public synchronized int getEffectiveLevel() { + int result = level; + int effLevel; + + Iterator it = iterator(); + Status s; + while (it.hasNext()) { + s = (Status) it.next(); + effLevel = s.getEffectiveLevel(); + if (effLevel > result) { + result = effLevel; + } + } + return result; + } + + public String getMessage() { + return message; + } + + public Object getOrigin() { + return origin; + } + + public Throwable getThrowable() { + return throwable; + } + + public Long getDate() { + return date; + } + + /** + * @Override + */ + public String toString() { + StringBuffer buf = new StringBuffer(); + switch (getEffectiveLevel()) { + case INFO: + buf.append("INFO"); + break; + case WARN: + buf.append("WARN"); + break; + case ERROR: + buf.append("ERROR"); + break; + } + if (origin != null) { + buf.append(" in "); + buf.append(origin); + buf.append(" -"); + } + + buf.append(" "); + buf.append(message); + + if (throwable != null) { + buf.append(" "); + buf.append(throwable); + } + + return buf.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + level; + result = prime * result + ((message == null) ? 0 : message.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final StatusBase other = (StatusBase) obj; + if (level != other.level) + return false; + if (message == null) { + if (other.message != null) + return false; + } else if (!message.equals(other.message)) + return false; + return true; + } + + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/StatusListener.java b/logback-core/src/main/java/ch/qos/logback/core/status/StatusListener.java index 7870cdbd08655b709f6a6b52837c53a8b11bb04c..099b324461f6d251b4139d88803896ebf9206482 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/StatusListener.java +++ b/logback-core/src/main/java/ch/qos/logback/core/status/StatusListener.java @@ -1,24 +1,24 @@ -/** - * 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.status; - -/** - * A StatusListener registered with logback context's {@link StatusManager} will - * receive notification of every incoming {@link Status status} message. - * - * @author Ceki Gülcü - */ -public interface StatusListener { - void addStatusEvent(Status status); -} +/** + * 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.status; + +/** + * A StatusListener registered with logback context's {@link StatusManager} will + * receive notification of every incoming {@link Status status} message. + * + * @author Ceki Gülcü + */ +public interface StatusListener { + void addStatusEvent(Status status); +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/StatusListenerAsList.java b/logback-core/src/main/java/ch/qos/logback/core/status/StatusListenerAsList.java index 35eb19cf456bec786e5ae9457f18cf33d3264082..6979fcb3c184cb9aee2fa6cf4451ab02af111923 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/StatusListenerAsList.java +++ b/logback-core/src/main/java/ch/qos/logback/core/status/StatusListenerAsList.java @@ -1,38 +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.status; - -import java.util.ArrayList; -import java.util.List; - -/** - * Collect all incoming events in a list. - * - * @author Ceki Gülcü - * - */ -public class StatusListenerAsList implements StatusListener { - - List statusList = new ArrayList(); - - public void addStatusEvent(Status status) { - statusList.add(status); - } - - public List getStatusList() { - return statusList; - } - - -} +/** + * 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.status; + +import java.util.ArrayList; +import java.util.List; + +/** + * Collect all incoming events in a list. + * + * @author Ceki Gülcü + * + */ +public class StatusListenerAsList implements StatusListener { + + List statusList = new ArrayList(); + + public void addStatusEvent(Status status) { + statusList.add(status); + } + + public List getStatusList() { + return statusList; + } + + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/StatusManager.java b/logback-core/src/main/java/ch/qos/logback/core/status/StatusManager.java index c3bce918b97117d0e3fe118cb59feadc4a33caf1..eb466f6edd9db33f29488a377dde68c10d175383 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/StatusManager.java +++ b/logback-core/src/main/java/ch/qos/logback/core/status/StatusManager.java @@ -1,80 +1,80 @@ -/** - * 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.status; - -import java.util.List; - -/** - * Internal error messages (statii) are managed by instances of this interface. - * - * @author Ceki Gulcu - */ -public interface StatusManager { - - /** - * Add a new status message. - * - * @param status - */ - public void add(Status status); - - /** - * Obtain a copy of the status list maintained by this StatusManager. - * - * @return - */ - public List getCopyOfStatusList(); - - /** - * Return the highest level of all the statii. - * - * @return - */ - public int getLevel(); - - /** - * Return the number of status entries. - * - * @return - */ - public int getCount(); - - /** - * Add a status listener. - * @param listener - */ - public void add(StatusListener listener); - - /** - * Remove a status listener. - * - * @param listener - */ - public void remove(StatusListener listener); - - - /** - * Clear the list of status messages. - */ - public void clear(); - - - /** - * Obtain a copy of the status listener list maintained by this StatusManager - * - * @return - */ - public List getCopyOfStatusListenerList(); - -} +/** + * 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.status; + +import java.util.List; + +/** + * Internal error messages (statii) are managed by instances of this interface. + * + * @author Ceki Gulcu + */ +public interface StatusManager { + + /** + * Add a new status message. + * + * @param status + */ + public void add(Status status); + + /** + * Obtain a copy of the status list maintained by this StatusManager. + * + * @return + */ + public List getCopyOfStatusList(); + + /** + * Return the highest level of all the statii. + * + * @return + */ + public int getLevel(); + + /** + * Return the number of status entries. + * + * @return + */ + public int getCount(); + + /** + * Add a status listener. + * @param listener + */ + public void add(StatusListener listener); + + /** + * Remove a status listener. + * + * @param listener + */ + public void remove(StatusListener listener); + + + /** + * Clear the list of status messages. + */ + public void clear(); + + + /** + * Obtain a copy of the status listener list maintained by this StatusManager + * + * @return + */ + public List getCopyOfStatusListenerList(); + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/StatusUtil.java b/logback-core/src/main/java/ch/qos/logback/core/status/StatusUtil.java index 49191791fe0f9386cac5ce2c01e8cb5b3f6dbf5a..b7ac40ffa670c02cd7877daf7ff0b497a1e72bcf 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/StatusUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/status/StatusUtil.java @@ -1,42 +1,42 @@ -/** - * 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.status; - -import ch.qos.logback.core.Context; - -public class StatusUtil { - - static public void addStatus(Context context, Status status) { - if (context == null) { - return; - } - StatusManager sm = context.getStatusManager(); - if (sm != null) { - sm.add(status); - } - } - - static public void addInfo(Context context, Object caller, String msg) { - addStatus(context, new InfoStatus(msg, caller)); - } - - static public void addWarn(Context context, Object caller, String msg) { - addStatus(context, new WarnStatus(msg, caller)); - } - - static public void addError(Context context, Object caller, String msg, - Throwable t) { - addStatus(context, new ErrorStatus(msg, caller, t)); - } -} +/** + * 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.status; + +import ch.qos.logback.core.Context; + +public class StatusUtil { + + static public void addStatus(Context context, Status status) { + if (context == null) { + return; + } + StatusManager sm = context.getStatusManager(); + if (sm != null) { + sm.add(status); + } + } + + static public void addInfo(Context context, Object caller, String msg) { + addStatus(context, new InfoStatus(msg, caller)); + } + + static public void addWarn(Context context, Object caller, String msg) { + addStatus(context, new WarnStatus(msg, caller)); + } + + static public void addError(Context context, Object caller, String msg, + Throwable t) { + addStatus(context, new ErrorStatus(msg, caller, t)); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/ViewStatusMessagesServletBase.java b/logback-core/src/main/java/ch/qos/logback/core/status/ViewStatusMessagesServletBase.java index 4f178b43d2e214978a8598bbe751aa7091dc8e08..53216d2375985616ccdb8030ff075e31f5b886ea 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/ViewStatusMessagesServletBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/status/ViewStatusMessagesServletBase.java @@ -1,182 +1,182 @@ -/** - * 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.status; - -import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.text.SimpleDateFormat; -import java.util.List; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.helpers.Transform; - -abstract public class ViewStatusMessagesServletBase extends HttpServlet { - - private static final long serialVersionUID = -3551928133801157219L; - private static SimpleDateFormat SDF = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - - protected abstract StatusManager getStatusManager(HttpServletRequest req, HttpServletResponse resp); - - protected abstract String getPageTitle(HttpServletRequest req, HttpServletResponse resp); - - int count; - - protected void service(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - - System.out.println("service called"); - count = 0; - StatusManager sm = getStatusManager(req, resp); - - resp.setContentType("text/html"); - PrintWriter output = resp.getWriter(); - - output.append("\r\n"); - output.append("\r\n"); - printCSS(req.getContextPath(), output); - output.append("\r\n"); - output.append("\r\n"); - output.append(getPageTitle(req, resp)); - - output.append("

"); - StringBuilder buf = new StringBuilder(); - if(sm != null) { - printList(buf, sm); - } else { - output.append("Could not find status manager"); - } - output.append(buf); - output.append("
"); - output.append("\r\n"); - output.append("\r\n"); - output.flush(); - output.close(); - } - - public void printCSS(String localRef, PrintWriter output) { - output.append(" \r\n"); - - } - - public void printList(StringBuilder buf, StatusManager sm) { - buf.append("\r\n"); - printHeader(buf); - List statusList = sm.getCopyOfStatusList(); - for (Status s : statusList) { - count++; - printStatus(buf, s); - } - buf.append("
\r\n"); - } - - public void printHeader(StringBuilder buf) { - buf.append(" \r\n"); - buf.append(" Date \r\n"); - buf.append(" Level\r\n"); - buf.append(" Origin\r\n"); - buf.append(" Message\r\n"); - buf.append(" \r\n"); - - } - - String statusLevelAsString(Status s) { - switch (s.getEffectiveLevel()) { - case Status.INFO: - return "INFO"; - case Status.WARN: - return "WARN"; - case Status.ERROR: - return "ERROR"; - } - return null; - } - - String abbreviatedOrigin(Status s) { - Object o = s.getOrigin(); - if (o == null) { - return null; - } - String fqClassName = o.getClass().getName(); - int lastIndex = fqClassName.lastIndexOf(CoreConstants.DOT); - if (lastIndex != -1) { - return fqClassName.substring(lastIndex + 1, fqClassName.length()); - } else { - return fqClassName; - } - } - - private void printStatus(StringBuilder buf, Status s) { - String trClass; - if (count % 2 == 0) { - trClass = "even"; - } else { - trClass = "odd"; - } - buf.append(" \r\n"); - String dateStr = SDF.format(s.getDate()); - buf.append(" ").append(dateStr).append("\r\n"); - buf.append(" ").append(statusLevelAsString(s)) - .append("\r\n"); - buf.append(" ").append(abbreviatedOrigin(s)).append("\r\n"); - buf.append(" ").append(s.getMessage()).append("\r\n"); - buf.append(" \r\n"); - if (s.getThrowable() != null) { - printThrowable(buf, s.getThrowable()); - } - } - - private void printThrowable(StringBuilder buf, Throwable t) { - buf.append(" \r\n"); - buf.append("
");
-    StringWriter sw = new StringWriter();
-    PrintWriter pw = new PrintWriter(sw);
-    t.printStackTrace(pw);
-    buf.append(Transform.escapeTags(sw.getBuffer()));
-    buf.append("    
\r\n"); - buf.append(" \r\n"); - - } -} +/** + * 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.status; + +import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.helpers.Transform; + +abstract public class ViewStatusMessagesServletBase extends HttpServlet { + + private static final long serialVersionUID = -3551928133801157219L; + private static SimpleDateFormat SDF = new SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss"); + + protected abstract StatusManager getStatusManager(HttpServletRequest req, HttpServletResponse resp); + + protected abstract String getPageTitle(HttpServletRequest req, HttpServletResponse resp); + + int count; + + protected void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + + System.out.println("service called"); + count = 0; + StatusManager sm = getStatusManager(req, resp); + + resp.setContentType("text/html"); + PrintWriter output = resp.getWriter(); + + output.append("\r\n"); + output.append("\r\n"); + printCSS(req.getContextPath(), output); + output.append("\r\n"); + output.append("\r\n"); + output.append(getPageTitle(req, resp)); + + output.append(""); + StringBuilder buf = new StringBuilder(); + if(sm != null) { + printList(buf, sm); + } else { + output.append("Could not find status manager"); + } + output.append(buf); + output.append("
"); + output.append("\r\n"); + output.append("\r\n"); + output.flush(); + output.close(); + } + + public void printCSS(String localRef, PrintWriter output) { + output.append(" \r\n"); + + } + + public void printList(StringBuilder buf, StatusManager sm) { + buf.append("\r\n"); + printHeader(buf); + List statusList = sm.getCopyOfStatusList(); + for (Status s : statusList) { + count++; + printStatus(buf, s); + } + buf.append("
\r\n"); + } + + public void printHeader(StringBuilder buf) { + buf.append(" \r\n"); + buf.append(" Date \r\n"); + buf.append(" Level\r\n"); + buf.append(" Origin\r\n"); + buf.append(" Message\r\n"); + buf.append(" \r\n"); + + } + + String statusLevelAsString(Status s) { + switch (s.getEffectiveLevel()) { + case Status.INFO: + return "INFO"; + case Status.WARN: + return "WARN"; + case Status.ERROR: + return "ERROR"; + } + return null; + } + + String abbreviatedOrigin(Status s) { + Object o = s.getOrigin(); + if (o == null) { + return null; + } + String fqClassName = o.getClass().getName(); + int lastIndex = fqClassName.lastIndexOf(CoreConstants.DOT); + if (lastIndex != -1) { + return fqClassName.substring(lastIndex + 1, fqClassName.length()); + } else { + return fqClassName; + } + } + + private void printStatus(StringBuilder buf, Status s) { + String trClass; + if (count % 2 == 0) { + trClass = "even"; + } else { + trClass = "odd"; + } + buf.append(" \r\n"); + String dateStr = SDF.format(s.getDate()); + buf.append(" ").append(dateStr).append("\r\n"); + buf.append(" ").append(statusLevelAsString(s)) + .append("\r\n"); + buf.append(" ").append(abbreviatedOrigin(s)).append("\r\n"); + buf.append(" ").append(s.getMessage()).append("\r\n"); + buf.append(" \r\n"); + if (s.getThrowable() != null) { + printThrowable(buf, s.getThrowable()); + } + } + + private void printThrowable(StringBuilder buf, Throwable t) { + buf.append(" \r\n"); + buf.append("
");
+    StringWriter sw = new StringWriter();
+    PrintWriter pw = new PrintWriter(sw);
+    t.printStackTrace(pw);
+    buf.append(Transform.escapeTags(sw.getBuffer()));
+    buf.append("    
\r\n"); + buf.append(" \r\n"); + + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/WarnStatus.java b/logback-core/src/main/java/ch/qos/logback/core/status/WarnStatus.java index 3be35ee49a5306ff0d5bbdbb9535e9197df407a2..8e037c08d825632934f2158fb9b17f9c49d5177c 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/WarnStatus.java +++ b/logback-core/src/main/java/ch/qos/logback/core/status/WarnStatus.java @@ -1,29 +1,29 @@ -/** - * 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.status; - - - -public class WarnStatus extends StatusBase { - - - public WarnStatus(String msg, Object origin) { - super(Status.WARN, msg, origin); - } - - public WarnStatus( String msg, Object origin, Throwable t) { - super(Status.WARN, msg, origin, t); - } - - } +/** + * 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.status; + + + +public class WarnStatus extends StatusBase { + + + public WarnStatus(String msg, Object origin) { + super(Status.WARN, msg, origin); + } + + public WarnStatus( String msg, Object origin, Throwable t) { + super(Status.WARN, msg, origin, t); + } + + } diff --git a/logback-core/src/main/java/ch/qos/logback/core/status/package.html b/logback-core/src/main/java/ch/qos/logback/core/status/package.html index 27fb689ff1299b0dc13f1955497a406f9c430147..cf1c5c5c8998f27f3ae4986e281ec1155611d8d8 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/status/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/status/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains logback's internal error reporting system.

- - - + + + + + + + + + +

Contains logback's internal error reporting system.

+ + + diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/AggregationType.java b/logback-core/src/main/java/ch/qos/logback/core/util/AggregationType.java index e5438eabf942fa4d49c0dea2358f0dd14c0a9944..8e483600558219c22b8472cc49a30c7e2e330b57 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/AggregationType.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/AggregationType.java @@ -1,36 +1,36 @@ -/** - * 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.util; - -/** - * AggregationType classifies how one object is contained within - * another object. - * - * - * - * See also http://en.wikipedia.org/wiki/Class_diagram - * and http://en.wikipedia.org/wiki/Object_composition - * - * @author Ceki Gulcu - */ -public enum AggregationType { - NOT_FOUND, - AS_BASIC_PROPERTY, // Long, Integer, Double,..., java primitive, String, - // Duration or FileSize - AS_COMPLEX_PROPERTY, // a complex property, a.k.a. attribute, is any attribute - // not covered by basic attributes, i.e. - // object types defined by the user - AS_BASIC_PROPERTY_COLLECTION, // a collection of basic attributes - AS_COMPLEX_PROPERTY_COLLECTION; // a collection of complex attributes -} +/** + * 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.util; + +/** + * AggregationType classifies how one object is contained within + * another object. + * + * + * + * See also http://en.wikipedia.org/wiki/Class_diagram + * and http://en.wikipedia.org/wiki/Object_composition + * + * @author Ceki Gulcu + */ +public enum AggregationType { + NOT_FOUND, + AS_BASIC_PROPERTY, // Long, Integer, Double,..., java primitive, String, + // Duration or FileSize + AS_COMPLEX_PROPERTY, // a complex property, a.k.a. attribute, is any attribute + // not covered by basic attributes, i.e. + // object types defined by the user + AS_BASIC_PROPERTY_COLLECTION, // a collection of basic attributes + AS_COMPLEX_PROPERTY_COLLECTION; // a collection of complex attributes +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/ContentTypeUtil.java b/logback-core/src/main/java/ch/qos/logback/core/util/ContentTypeUtil.java index 626656bd036970cd307b9e3eb82d42eb2e8abfc9..29d1c677db07cb9f89baa1a102f2997ef03d36f0 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/ContentTypeUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/ContentTypeUtil.java @@ -1,47 +1,47 @@ -/** - * 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.util; - -/** - * Various utility methods for processing strings representing context types. - * - * @author Ceki Gulcu - * - */ -public class ContentTypeUtil { - - public static boolean isTextual(String contextType) { - if (contextType == null) { - return false; - } - return contextType.startsWith("text"); - } - - public static String getSubType(String contextType) { - if (contextType == null) { - return null; - } - int index = contextType.indexOf('/'); - if (index == -1) { - return null; - } else { - int subTypeStartIndex = index + 1; - if (subTypeStartIndex < contextType.length()) { - return contextType.substring(subTypeStartIndex); - } else { - return null; - } - } - } -} +/** + * 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.util; + +/** + * Various utility methods for processing strings representing context types. + * + * @author Ceki Gulcu + * + */ +public class ContentTypeUtil { + + public static boolean isTextual(String contextType) { + if (contextType == null) { + return false; + } + return contextType.startsWith("text"); + } + + public static String getSubType(String contextType) { + if (contextType == null) { + return null; + } + int index = contextType.indexOf('/'); + if (index == -1) { + return null; + } else { + int subTypeStartIndex = index + 1; + if (subTypeStartIndex < contextType.length()) { + return contextType.substring(subTypeStartIndex); + } else { + return null; + } + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/Duration.java b/logback-core/src/main/java/ch/qos/logback/core/util/Duration.java index be879a8cf0bf92acac3ef27048b95919acfbd589..130c8128fdaf4555411e13c100928f3072a80072 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/Duration.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/Duration.java @@ -1,125 +1,125 @@ -/** - * 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.util; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Duration instances represent a lapse of time. Internally, the duration is - * stored in milliseconds. - *

- * - * The {@link #valueOf} method can convert strings such as "3.5 minutes", "5 - * hours", into Duration instances. The recognized units of time are the - * "millisecond", "second", "minute" "hour" and "day". The unit name may be - * followed by an "s". Thus, "2 day" and "2 days" are equivalent. In the absence - * of a time unit specification, milliseconds are assumed. - * - * - * @author Ceki Gulcu - */ -public class Duration { - - private final static String DOUBLE_PART = "([0-9]*(.[0-9]+)?)"; - private final static int DOUBLE_GROUP = 1; - - private final static String UNIT_PART = "(|milli(second)?|second(e)?|minute|hour|day)s?"; - private final static int UNIT_GROUP = 3; - - private static final Pattern DURATION_PATTERN = Pattern.compile(DOUBLE_PART - + "\\s*" + UNIT_PART, Pattern.CASE_INSENSITIVE); - - static final long SECONDS_COEFFICIENT = 1000; - static final long MINUTES_COEFFICIENT = 60 * SECONDS_COEFFICIENT; - static final long HOURS_COEFFICIENT = 60 * MINUTES_COEFFICIENT; - static final long DAYS_COEFFICIENT = 24 * HOURS_COEFFICIENT; - - final long millis; - - public Duration(long millis) { - this.millis = millis; - } - - public static Duration buildByMilliseconds(double value) { - return new Duration((long) (value)); - } - - public static Duration buildBySeconds(double value) { - return new Duration((long) (SECONDS_COEFFICIENT * value)); - } - - public static Duration buildByMinutes(double value) { - return new Duration((long) (MINUTES_COEFFICIENT * value)); - } - - public static Duration buildByHours(double value) { - return new Duration((long) (HOURS_COEFFICIENT * value)); - } - - public static Duration buildByDays(double value) { - return new Duration((long) (DAYS_COEFFICIENT * value)); - } - - public static Duration buildUnbounded() { - return new Duration(Long.MAX_VALUE); - } - - public long getMilliseconds() { - return millis; - } - - public static Duration valueOf(String durationStr) { - Matcher matcher = DURATION_PATTERN.matcher(durationStr); - - if (matcher.matches()) { - String doubleStr = matcher.group(DOUBLE_GROUP); - String unitStr = matcher.group(UNIT_GROUP); - - double doubleValue = Double.valueOf(doubleStr); - if (unitStr.equalsIgnoreCase("milli") - || unitStr.equalsIgnoreCase("millisecond") || unitStr.length() == 0) { - return buildByMilliseconds(doubleValue); - } else if (unitStr.equalsIgnoreCase("second") - || unitStr.equalsIgnoreCase("seconde")) { - return buildBySeconds(doubleValue); - } else if (unitStr.equalsIgnoreCase("minute")) { - return buildByMinutes(doubleValue); - } else if (unitStr.equalsIgnoreCase("hour")) { - return buildByHours(doubleValue); - } else if (unitStr.equalsIgnoreCase("day")) { - return buildByDays(doubleValue); - } else { - throw new IllegalStateException("Unexpected " + unitStr); - } - } else { - throw new IllegalArgumentException("String value [" + durationStr - + "] is not in the expected format."); - } - } - - @Override - public String toString() { - if (millis < SECONDS_COEFFICIENT) { - return millis + " milliseconds"; - } else if (millis < MINUTES_COEFFICIENT) { - return millis / SECONDS_COEFFICIENT + " seconds"; - } else if (millis < HOURS_COEFFICIENT) { - return millis / MINUTES_COEFFICIENT + " minutes"; - } else { - return millis / HOURS_COEFFICIENT + " hours"; - } - - } -} +/** + * 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.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Duration instances represent a lapse of time. Internally, the duration is + * stored in milliseconds. + *

+ * + * The {@link #valueOf} method can convert strings such as "3.5 minutes", "5 + * hours", into Duration instances. The recognized units of time are the + * "millisecond", "second", "minute" "hour" and "day". The unit name may be + * followed by an "s". Thus, "2 day" and "2 days" are equivalent. In the absence + * of a time unit specification, milliseconds are assumed. + * + * + * @author Ceki Gulcu + */ +public class Duration { + + private final static String DOUBLE_PART = "([0-9]*(.[0-9]+)?)"; + private final static int DOUBLE_GROUP = 1; + + private final static String UNIT_PART = "(|milli(second)?|second(e)?|minute|hour|day)s?"; + private final static int UNIT_GROUP = 3; + + private static final Pattern DURATION_PATTERN = Pattern.compile(DOUBLE_PART + + "\\s*" + UNIT_PART, Pattern.CASE_INSENSITIVE); + + static final long SECONDS_COEFFICIENT = 1000; + static final long MINUTES_COEFFICIENT = 60 * SECONDS_COEFFICIENT; + static final long HOURS_COEFFICIENT = 60 * MINUTES_COEFFICIENT; + static final long DAYS_COEFFICIENT = 24 * HOURS_COEFFICIENT; + + final long millis; + + public Duration(long millis) { + this.millis = millis; + } + + public static Duration buildByMilliseconds(double value) { + return new Duration((long) (value)); + } + + public static Duration buildBySeconds(double value) { + return new Duration((long) (SECONDS_COEFFICIENT * value)); + } + + public static Duration buildByMinutes(double value) { + return new Duration((long) (MINUTES_COEFFICIENT * value)); + } + + public static Duration buildByHours(double value) { + return new Duration((long) (HOURS_COEFFICIENT * value)); + } + + public static Duration buildByDays(double value) { + return new Duration((long) (DAYS_COEFFICIENT * value)); + } + + public static Duration buildUnbounded() { + return new Duration(Long.MAX_VALUE); + } + + public long getMilliseconds() { + return millis; + } + + public static Duration valueOf(String durationStr) { + Matcher matcher = DURATION_PATTERN.matcher(durationStr); + + if (matcher.matches()) { + String doubleStr = matcher.group(DOUBLE_GROUP); + String unitStr = matcher.group(UNIT_GROUP); + + double doubleValue = Double.valueOf(doubleStr); + if (unitStr.equalsIgnoreCase("milli") + || unitStr.equalsIgnoreCase("millisecond") || unitStr.length() == 0) { + return buildByMilliseconds(doubleValue); + } else if (unitStr.equalsIgnoreCase("second") + || unitStr.equalsIgnoreCase("seconde")) { + return buildBySeconds(doubleValue); + } else if (unitStr.equalsIgnoreCase("minute")) { + return buildByMinutes(doubleValue); + } else if (unitStr.equalsIgnoreCase("hour")) { + return buildByHours(doubleValue); + } else if (unitStr.equalsIgnoreCase("day")) { + return buildByDays(doubleValue); + } else { + throw new IllegalStateException("Unexpected " + unitStr); + } + } else { + throw new IllegalArgumentException("String value [" + durationStr + + "] is not in the expected format."); + } + } + + @Override + public String toString() { + if (millis < SECONDS_COEFFICIENT) { + return millis + " milliseconds"; + } else if (millis < MINUTES_COEFFICIENT) { + return millis / SECONDS_COEFFICIENT + " seconds"; + } else if (millis < HOURS_COEFFICIENT) { + return millis / MINUTES_COEFFICIENT + " minutes"; + } else { + return millis / HOURS_COEFFICIENT + " hours"; + } + + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/DynamicClassLoadingException.java b/logback-core/src/main/java/ch/qos/logback/core/util/DynamicClassLoadingException.java index 83c37a94d6f13b652d2aec52cb3269bb4dbe2b93..f13168d97c240612032c492366ff0e1ff50a4fc1 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/DynamicClassLoadingException.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/DynamicClassLoadingException.java @@ -1,23 +1,23 @@ -/** - * 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.util; - -public class DynamicClassLoadingException extends Exception { - - private static final long serialVersionUID = 4962278449162476114L; - - public DynamicClassLoadingException(String desc, Throwable root ) { - super(desc, root); - } -} +/** + * 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.util; + +public class DynamicClassLoadingException extends Exception { + + private static final long serialVersionUID = 4962278449162476114L; + + public DynamicClassLoadingException(String desc, Throwable root ) { + super(desc, root); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/FileSize.java b/logback-core/src/main/java/ch/qos/logback/core/util/FileSize.java index 24061402767ea83edcc98151a145099c2bd679f1..68c1e0fb80e47b512e80834f1cce8259583a488a 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/FileSize.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/FileSize.java @@ -1,84 +1,84 @@ -/** - * 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.util; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Instances of this class represent the size of a file. Internally, the size is - * stored as long.> - * - *

The {@link #valueOf} method can convert strings such as "3 kb", "5 mb", into - * FileSize instances. The recognized unit specifications for file size are the - * "kb", "mb", and "gb". The unit name may be followed by an "s". Thus, "2 kbs" - * and "2 kb" are equivalent. In the absence of a time unit specification, byte - * is assumed. - * - * @author Ceki Gülcü - * - */ -public class FileSize { - - private final static String LENGTH_PART = "([0-9]+)"; - private final static int DOUBLE_GROUP = 1; - - private final static String UNIT_PART = "(|kb|mb|gb)s?"; - private final static int UNIT_GROUP = 2; - - private static final Pattern FILE_SIZE_PATTERN = Pattern.compile(LENGTH_PART - + "\\s*" + UNIT_PART, Pattern.CASE_INSENSITIVE); - - static final long KB_COEFFICIENT = 1024; - static final long MB_COEFFICIENT = 1024 * KB_COEFFICIENT; - static final long GB_COEFFICIENT = 1024 * MB_COEFFICIENT; - - final long size; - - FileSize(long size) { - this.size = size; - } - - public long getSize() { - return size; - } - - static public FileSize valueOf(String fileSizeStr) { - Matcher matcher = FILE_SIZE_PATTERN.matcher(fileSizeStr); - - long coefficient; - if (matcher.matches()) { - String lenStr = matcher.group(DOUBLE_GROUP); - String unitStr = matcher.group(UNIT_GROUP); - - long lenValue = Long.valueOf(lenStr); - if (unitStr.equalsIgnoreCase("")) { - coefficient = 1; - } else if (unitStr.equalsIgnoreCase("kb")) { - coefficient = KB_COEFFICIENT; - } else if (unitStr.equalsIgnoreCase("mb")) { - coefficient = MB_COEFFICIENT; - } else if (unitStr.equalsIgnoreCase("gb")) { - coefficient = GB_COEFFICIENT; - } else { - throw new IllegalStateException("Unexpected " + unitStr); - } - return new FileSize(lenValue * coefficient); - } else { - throw new IllegalArgumentException("String value [" + fileSizeStr - + "] is not in the expected format."); - } - - } -} +/** + * 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.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Instances of this class represent the size of a file. Internally, the size is + * stored as long.> + * + *

The {@link #valueOf} method can convert strings such as "3 kb", "5 mb", into + * FileSize instances. The recognized unit specifications for file size are the + * "kb", "mb", and "gb". The unit name may be followed by an "s". Thus, "2 kbs" + * and "2 kb" are equivalent. In the absence of a time unit specification, byte + * is assumed. + * + * @author Ceki Gülcü + * + */ +public class FileSize { + + private final static String LENGTH_PART = "([0-9]+)"; + private final static int DOUBLE_GROUP = 1; + + private final static String UNIT_PART = "(|kb|mb|gb)s?"; + private final static int UNIT_GROUP = 2; + + private static final Pattern FILE_SIZE_PATTERN = Pattern.compile(LENGTH_PART + + "\\s*" + UNIT_PART, Pattern.CASE_INSENSITIVE); + + static final long KB_COEFFICIENT = 1024; + static final long MB_COEFFICIENT = 1024 * KB_COEFFICIENT; + static final long GB_COEFFICIENT = 1024 * MB_COEFFICIENT; + + final long size; + + FileSize(long size) { + this.size = size; + } + + public long getSize() { + return size; + } + + static public FileSize valueOf(String fileSizeStr) { + Matcher matcher = FILE_SIZE_PATTERN.matcher(fileSizeStr); + + long coefficient; + if (matcher.matches()) { + String lenStr = matcher.group(DOUBLE_GROUP); + String unitStr = matcher.group(UNIT_GROUP); + + long lenValue = Long.valueOf(lenStr); + if (unitStr.equalsIgnoreCase("")) { + coefficient = 1; + } else if (unitStr.equalsIgnoreCase("kb")) { + coefficient = KB_COEFFICIENT; + } else if (unitStr.equalsIgnoreCase("mb")) { + coefficient = MB_COEFFICIENT; + } else if (unitStr.equalsIgnoreCase("gb")) { + coefficient = GB_COEFFICIENT; + } else { + throw new IllegalStateException("Unexpected " + unitStr); + } + return new FileSize(lenValue * coefficient); + } else { + throw new IllegalArgumentException("String value [" + fileSizeStr + + "] is not in the expected format."); + } + + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/FileUtil.java b/logback-core/src/main/java/ch/qos/logback/core/util/FileUtil.java index b74789cfeec0a3c275cdb2220df1cb64e71325fe..80fe0c74e3d61cca84c46cc1df8df63b4d65092d 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/FileUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/FileUtil.java @@ -1,40 +1,40 @@ -/** - * 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.util; - -import java.io.File; - -public class FileUtil { - - - public static boolean mustCreateParentDirectories(File file) { - File parent = file.getParentFile(); - if(parent != null && !parent.exists()) { - return true; - } else { - return false; - } - } - - public static boolean createMissingParentDirectories(File file) { - File parent = file.getParentFile(); - if(parent == null || parent.exists()) { - throw new IllegalStateException(file + " should not have a null parent"); - } - if(parent.exists()) { - throw new IllegalStateException(file + " should not have existing parent directory"); - } - return parent.mkdirs(); - } -} +/** + * 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.util; + +import java.io.File; + +public class FileUtil { + + + public static boolean mustCreateParentDirectories(File file) { + File parent = file.getParentFile(); + if(parent != null && !parent.exists()) { + return true; + } else { + return false; + } + } + + public static boolean createMissingParentDirectories(File file) { + File parent = file.getParentFile(); + if(parent == null || parent.exists()) { + throw new IllegalStateException(file + " should not have a null parent"); + } + if(parent.exists()) { + throw new IllegalStateException(file + " should not have existing parent directory"); + } + return parent.mkdirs(); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/IncompatibleClassException.java b/logback-core/src/main/java/ch/qos/logback/core/util/IncompatibleClassException.java index a72998f59a0464318602f53ec69bcb117757176c..e7da6a269a30c062997838c3ff53ad1f3374ada2 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/IncompatibleClassException.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/IncompatibleClassException.java @@ -1,28 +1,28 @@ -/** - * 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.util; - -public class IncompatibleClassException extends Exception { - - private static final long serialVersionUID = -5823372159561159549L; - - Class requestedClass; - Class obtainedClass; - - IncompatibleClassException(Class requestedClass, Class obtainedClass) { - super(); - this.requestedClass =requestedClass; - this.obtainedClass = obtainedClass; - } -} +/** + * 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.util; + +public class IncompatibleClassException extends Exception { + + private static final long serialVersionUID = -5823372159561159549L; + + Class requestedClass; + Class obtainedClass; + + IncompatibleClassException(Class requestedClass, Class obtainedClass) { + super(); + this.requestedClass =requestedClass; + this.obtainedClass = obtainedClass; + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/Loader.java b/logback-core/src/main/java/ch/qos/logback/core/util/Loader.java index daad303a97ae2d0aef01e0c196e6a1c3f137c305..e5d51d595e4127e1c2fd43607c81a2b1716eb6ab 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/Loader.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/Loader.java @@ -1,165 +1,165 @@ -/** - * 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.util; - -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; - -import ch.qos.logback.core.Context; - -/** - * Load resources (or images) from various sources. - * - * @author Ceki Gülcü - */ -public class Loader { - static final String TSTR = "Caught Exception while in Loader.getResource. This may be innocuous."; - - private static boolean ignoreTCL = false; - public static final String IGNORE_TCL_PROPERTY_NAME = "logback.ignoreTCL"; - - static { - - String ignoreTCLProp = OptionHelper.getSystemProperty( - IGNORE_TCL_PROPERTY_NAME, null); - - if (ignoreTCLProp != null) { - ignoreTCL = OptionHelper.toBoolean(ignoreTCLProp, true); - } - } - - /** - * Compute the number of occurrences a resource can be found by a class - * loader. - * - * @param resource - * @param classLoader - * @return - * @throws IOException - */ - public static List getResourceOccurenceCount(String resource, - ClassLoader classLoader) throws IOException { - List urlList = new ArrayList(); - Enumeration urlEnum = classLoader.getResources(resource); - while (urlEnum.hasMoreElements()) { - URL url = urlEnum.nextElement(); - urlList.add(url); - } - - return urlList; - } - - /** - * Search for a resource using the classloader passed as parameter. - * - * @param resource - * the resource name to look for - * @param classLoader - * the classloader used for the search - */ - public static URL getResource(String resource, ClassLoader classLoader) { - try { - return classLoader.getResource(resource); - } catch (Throwable t) { - return null; - } - } - - /** - * Attempt to find a resource by using the classloader that loaded this class, - * namely Loader.class. - * - * @param resource - * @return - */ - public static URL getResourceBySelfClassLoader(String resource) { - return getResource(resource, getClassLoaderOfClass(Loader.class)); - } - - // private static URL getResourceByTCL(String resource) { - // return getResource(resource, getTCL()); - // } - - /** - * Get the Thread Context Loader which is a JDK 1.2 feature. If we are running - * under JDK 1.1 or anything else goes wrong the method returns - * null. - * - */ - public static ClassLoader getTCL() { - return Thread.currentThread().getContextClassLoader(); - } - - public static Class loadClass(String clazz, Context context) - throws ClassNotFoundException { - ClassLoader cl = getClassLoaderOfObject(context); - return cl.loadClass(clazz); - } - - /** - * Get the class loader of the object passed as argument. Return the system - * class loader if appropriate. - * - * @param o - * @return - */ - public static ClassLoader getClassLoaderOfObject(Object o) { - if (o == null) { - throw new NullPointerException("Argument cannot be null"); - } - return getClassLoaderOfClass(o.getClass()); - } - - /** - * Return the class loader which loaded the class passed as argument. Return - * the system class loader if appropriate. - * - * @param clazz - * @return - */ - public static ClassLoader getClassLoaderOfClass(Class clazz) { - ClassLoader cl = clazz.getClassLoader(); - if (cl == null) { - return ClassLoader.getSystemClassLoader(); - } else { - return cl; - } - } - - /** - * If running under JDK 1.2 load the specified class using the - * Thread contextClassLoader if that fails try - * Class.forname. Under JDK 1.1 only Class.forName is used. - * - */ - public static Class loadClass(String clazz) throws ClassNotFoundException { - // Just call Class.forName(clazz) if we are running under JDK 1.1 - // or if we are instructed to ignore the TCL. - if (ignoreTCL) { - return Class.forName(clazz); - } else { - try { - return getTCL().loadClass(clazz); - } catch (Throwable e) { - // we reached here because tcl was null or because of a - // security exception, or because clazz could not be loaded... - // In any case we now try one more time - return Class.forName(clazz); - } - } - } -} +/** + * 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.util; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import ch.qos.logback.core.Context; + +/** + * Load resources (or images) from various sources. + * + * @author Ceki Gülcü + */ +public class Loader { + static final String TSTR = "Caught Exception while in Loader.getResource. This may be innocuous."; + + private static boolean ignoreTCL = false; + public static final String IGNORE_TCL_PROPERTY_NAME = "logback.ignoreTCL"; + + static { + + String ignoreTCLProp = OptionHelper.getSystemProperty( + IGNORE_TCL_PROPERTY_NAME, null); + + if (ignoreTCLProp != null) { + ignoreTCL = OptionHelper.toBoolean(ignoreTCLProp, true); + } + } + + /** + * Compute the number of occurrences a resource can be found by a class + * loader. + * + * @param resource + * @param classLoader + * @return + * @throws IOException + */ + public static List getResourceOccurenceCount(String resource, + ClassLoader classLoader) throws IOException { + List urlList = new ArrayList(); + Enumeration urlEnum = classLoader.getResources(resource); + while (urlEnum.hasMoreElements()) { + URL url = urlEnum.nextElement(); + urlList.add(url); + } + + return urlList; + } + + /** + * Search for a resource using the classloader passed as parameter. + * + * @param resource + * the resource name to look for + * @param classLoader + * the classloader used for the search + */ + public static URL getResource(String resource, ClassLoader classLoader) { + try { + return classLoader.getResource(resource); + } catch (Throwable t) { + return null; + } + } + + /** + * Attempt to find a resource by using the classloader that loaded this class, + * namely Loader.class. + * + * @param resource + * @return + */ + public static URL getResourceBySelfClassLoader(String resource) { + return getResource(resource, getClassLoaderOfClass(Loader.class)); + } + + // private static URL getResourceByTCL(String resource) { + // return getResource(resource, getTCL()); + // } + + /** + * Get the Thread Context Loader which is a JDK 1.2 feature. If we are running + * under JDK 1.1 or anything else goes wrong the method returns + * null. + * + */ + public static ClassLoader getTCL() { + return Thread.currentThread().getContextClassLoader(); + } + + public static Class loadClass(String clazz, Context context) + throws ClassNotFoundException { + ClassLoader cl = getClassLoaderOfObject(context); + return cl.loadClass(clazz); + } + + /** + * Get the class loader of the object passed as argument. Return the system + * class loader if appropriate. + * + * @param o + * @return + */ + public static ClassLoader getClassLoaderOfObject(Object o) { + if (o == null) { + throw new NullPointerException("Argument cannot be null"); + } + return getClassLoaderOfClass(o.getClass()); + } + + /** + * Return the class loader which loaded the class passed as argument. Return + * the system class loader if appropriate. + * + * @param clazz + * @return + */ + public static ClassLoader getClassLoaderOfClass(Class clazz) { + ClassLoader cl = clazz.getClassLoader(); + if (cl == null) { + return ClassLoader.getSystemClassLoader(); + } else { + return cl; + } + } + + /** + * If running under JDK 1.2 load the specified class using the + * Thread contextClassLoader if that fails try + * Class.forname. Under JDK 1.1 only Class.forName is used. + * + */ + public static Class loadClass(String clazz) throws ClassNotFoundException { + // Just call Class.forName(clazz) if we are running under JDK 1.1 + // or if we are instructed to ignore the TCL. + if (ignoreTCL) { + return Class.forName(clazz); + } else { + try { + return getTCL().loadClass(clazz); + } catch (Throwable e) { + // we reached here because tcl was null or because of a + // security exception, or because clazz could not be loaded... + // In any case we now try one more time + return Class.forName(clazz); + } + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/OptionHelper.java b/logback-core/src/main/java/ch/qos/logback/core/util/OptionHelper.java index 947ffefb23bf3131c4e150f7dcf1d5c20166fd0d..5d081291febac377044e4399a7a6405da64334bf 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/OptionHelper.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/OptionHelper.java @@ -1,294 +1,294 @@ -/** - * 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.util; - -import java.util.Properties; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.spi.PropertyContainer; - -/** - * @author Ceki Gulcu - */ -public class OptionHelper { - - public static Object instantiateByClassName(String className, - Class superClass, Context context) throws IncompatibleClassException, - DynamicClassLoadingException { - ClassLoader classLoader = Loader.getClassLoaderOfObject(context); - return instantiateByClassName(className, superClass, classLoader); - } - - @SuppressWarnings("unchecked") - public static Object instantiateByClassName(String className, - Class superClass, ClassLoader classLoader) - throws IncompatibleClassException, DynamicClassLoadingException { - - if (className == null) { - throw new NullPointerException(); - } - - try { - Class classObj = null; - classObj = classLoader.loadClass(className); - if (!superClass.isAssignableFrom(classObj)) { - throw new IncompatibleClassException(superClass, classObj); - } - return classObj.newInstance(); - } catch (IncompatibleClassException ice) { - throw ice; - } catch (Throwable t) { - throw new DynamicClassLoadingException("Failed to instantiate type " - + className, t); - } - } - - /** - * Find the value corresponding to key in props. - * Then perform variable substitution on the found value. - * - */ - // public static String findAndSubst(String key, Properties props) { - // String value = props.getProperty(key); - // - // if (value == null) { - // return null; - // } - // - // try { - // return substVars(value, props); - // } catch (IllegalArgumentException e) { - // return value; - // } - // } - final static String DELIM_START = "${"; - final static char DELIM_STOP = '}'; - final static int DELIM_START_LEN = 2; - final static int DELIM_STOP_LEN = 1; - final static String _IS_UNDEFINED = "_IS_UNDEFINED"; - - /** - * Perform variable substitution in string val from the values - * of keys found in context property map, and if that fails, then in the - * system properties. - * - *

The variable substitution delimeters are ${ and }. - * - *

For example, if the context property map contains a property "key1" set - * as "value1", then the call - * - *

-   * String s = OptionConverter.substituteVars("Value of key is ${key1}.", context);
- * - * will set the variable s to "Value of key is value1.". - * - *

If no value could be found for the specified key in the context map, - * then the system properties are searched, if that fails, then substitution - * defaults to appending "_IS_UNDEFINED" to the key name. - * - *

For example, if not the context not the system properties contains no - * value for the key "inexistentKey", then the call - * - *

-   * String s = OptionConverter.subsVars(
-   *     "Value of inexistentKey is [${inexistentKey}]", context);
- * - * will set s to "Value of inexistentKey is - * [inexistentKey_IS_UNDEFINED]". - * - *

Nevertheless, it is possible to specify a default substitution value - * using the ":-" operator. For example, the call - * - *

-   * String s = OptionConverter.subsVars("Value of key is [${key2:-val2}]", context);
- * - * will set s to "Value of key is [val2]" even if the "key2" - * property is not set. - * - *

An {@link java.lang.IllegalArgumentException} is thrown if - * val contains a start delimeter "${" which is not balanced by - * a stop delimeter "}".

- * - * - * @param val - * The string on which variable substitution is performed. - * @throws IllegalArgumentException - * if val is malformed. - */ - public static String substVars(String val, PropertyContainer pc) { - - StringBuffer sbuf = new StringBuffer(); - - int i = 0; - int j; - int k; - - while (true) { - j = val.indexOf(DELIM_START, i); - - if (j == -1) { - // no more variables - if (i == 0) { // this is a simple string - - return val; - } else { // add the tail string which contails no variables and return - // the result. - sbuf.append(val.substring(i, val.length())); - - return sbuf.toString(); - } - } else { - sbuf.append(val.substring(i, j)); - k = val.indexOf(DELIM_STOP, j); - - if (k == -1) { - throw new IllegalArgumentException('"' + val - + "\" has no closing brace. Opening brace at position " + j + '.'); - } else { - j += DELIM_START_LEN; - - String rawKey = val.substring(j, k); - - // Massage the key to extract a default replacement if there is one - String[] extracted = extractDefaultReplacement(rawKey); - String key = extracted[0]; - String defaultReplacement = extracted[1]; // can be null - - String replacement = null; - - // first try the props passed as parameter - replacement = pc.getProperty(key); - - // then try in System properties - if (replacement == null) { - replacement = getSystemProperty(key, null); - } - - // if replacement is still null, use the defaultReplacement which - // can be null as well - if (replacement == null) { - replacement = defaultReplacement; - } - - if (replacement != null) { - // Do variable substitution on the replacement string - // such that we can solve "Hello ${x2}" as "Hello p1" - // where the properties are - // x1=p1 - // x2=${x1} - String recursiveReplacement = substVars(replacement, pc); - sbuf.append(recursiveReplacement); - } else { - // if we could not find a replacement, then signal the error - sbuf.append(key + "_IS_UNDEFINED"); - } - - i = k + DELIM_STOP_LEN; - } - } - } - } - - /** - * Very similar to System.getProperty except that the - * {@link SecurityException} is absorbed. - * - * @param key - * The key to search for. - * @param def - * The default value to return. - * @return the string value of the system property, or the default value if - * there is no property with that key. - */ - public static String getSystemProperty(String key, String def) { - try { - return System.getProperty(key, def); - } catch (SecurityException e) { - return def; - } - } - - /** - * Very similar to System.getProperty except that the - * {@link SecurityException} is absorbed. - * - * @param key - * The key to search for. - * - * @return the string value of the system property. - */ - public static String getSystemProperty(String key) { - try { - return System.getProperty(key); - } catch (SecurityException e) { - return null; - } - } - - /** - * Very similar to {@link System#getProperties()} except that the - * {@link SecurityException} is absorbed. - * - * @return the system properties - */ - public static Properties getSystemProperties() { - try { - return System.getProperties(); - } catch (SecurityException e) { - return new Properties(); - } - } - - static public String[] extractDefaultReplacement(String key) { - String[] result = new String[2]; - result[0] = key; - int d = key.indexOf(":-"); - if (d != -1) { - result[0] = key.substring(0, d); - result[1] = key.substring(d + 2); - } - return result; - } - - /** - * If value is "true", then true is returned. If - * value is "false", then true is returned. - * Otherwise, default is returned. - * - *

Case of value is unimportant. - */ - public static boolean toBoolean(String value, boolean dEfault) { - if (value == null) { - return dEfault; - } - - String trimmedVal = value.trim(); - - if ("true".equalsIgnoreCase(trimmedVal)) { - return true; - } - - if ("false".equalsIgnoreCase(trimmedVal)) { - return false; - } - - return dEfault; - } - - public static boolean isEmpty(String val) { - return ((val == null) || CoreConstants.EMPTY_STRING.equals(val)); - } - -} +/** + * 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.util; + +import java.util.Properties; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.spi.PropertyContainer; + +/** + * @author Ceki Gulcu + */ +public class OptionHelper { + + public static Object instantiateByClassName(String className, + Class superClass, Context context) throws IncompatibleClassException, + DynamicClassLoadingException { + ClassLoader classLoader = Loader.getClassLoaderOfObject(context); + return instantiateByClassName(className, superClass, classLoader); + } + + @SuppressWarnings("unchecked") + public static Object instantiateByClassName(String className, + Class superClass, ClassLoader classLoader) + throws IncompatibleClassException, DynamicClassLoadingException { + + if (className == null) { + throw new NullPointerException(); + } + + try { + Class classObj = null; + classObj = classLoader.loadClass(className); + if (!superClass.isAssignableFrom(classObj)) { + throw new IncompatibleClassException(superClass, classObj); + } + return classObj.newInstance(); + } catch (IncompatibleClassException ice) { + throw ice; + } catch (Throwable t) { + throw new DynamicClassLoadingException("Failed to instantiate type " + + className, t); + } + } + + /** + * Find the value corresponding to key in props. + * Then perform variable substitution on the found value. + * + */ + // public static String findAndSubst(String key, Properties props) { + // String value = props.getProperty(key); + // + // if (value == null) { + // return null; + // } + // + // try { + // return substVars(value, props); + // } catch (IllegalArgumentException e) { + // return value; + // } + // } + final static String DELIM_START = "${"; + final static char DELIM_STOP = '}'; + final static int DELIM_START_LEN = 2; + final static int DELIM_STOP_LEN = 1; + final static String _IS_UNDEFINED = "_IS_UNDEFINED"; + + /** + * Perform variable substitution in string val from the values + * of keys found in context property map, and if that fails, then in the + * system properties. + * + *

The variable substitution delimeters are ${ and }. + * + *

For example, if the context property map contains a property "key1" set + * as "value1", then the call + * + *

+   * String s = OptionConverter.substituteVars("Value of key is ${key1}.", context);
+ * + * will set the variable s to "Value of key is value1.". + * + *

If no value could be found for the specified key in the context map, + * then the system properties are searched, if that fails, then substitution + * defaults to appending "_IS_UNDEFINED" to the key name. + * + *

For example, if not the context not the system properties contains no + * value for the key "inexistentKey", then the call + * + *

+   * String s = OptionConverter.subsVars(
+   *     "Value of inexistentKey is [${inexistentKey}]", context);
+ * + * will set s to "Value of inexistentKey is + * [inexistentKey_IS_UNDEFINED]". + * + *

Nevertheless, it is possible to specify a default substitution value + * using the ":-" operator. For example, the call + * + *

+   * String s = OptionConverter.subsVars("Value of key is [${key2:-val2}]", context);
+ * + * will set s to "Value of key is [val2]" even if the "key2" + * property is not set. + * + *

An {@link java.lang.IllegalArgumentException} is thrown if + * val contains a start delimeter "${" which is not balanced by + * a stop delimeter "}".

+ * + * + * @param val + * The string on which variable substitution is performed. + * @throws IllegalArgumentException + * if val is malformed. + */ + public static String substVars(String val, PropertyContainer pc) { + + StringBuffer sbuf = new StringBuffer(); + + int i = 0; + int j; + int k; + + while (true) { + j = val.indexOf(DELIM_START, i); + + if (j == -1) { + // no more variables + if (i == 0) { // this is a simple string + + return val; + } else { // add the tail string which contails no variables and return + // the result. + sbuf.append(val.substring(i, val.length())); + + return sbuf.toString(); + } + } else { + sbuf.append(val.substring(i, j)); + k = val.indexOf(DELIM_STOP, j); + + if (k == -1) { + throw new IllegalArgumentException('"' + val + + "\" has no closing brace. Opening brace at position " + j + '.'); + } else { + j += DELIM_START_LEN; + + String rawKey = val.substring(j, k); + + // Massage the key to extract a default replacement if there is one + String[] extracted = extractDefaultReplacement(rawKey); + String key = extracted[0]; + String defaultReplacement = extracted[1]; // can be null + + String replacement = null; + + // first try the props passed as parameter + replacement = pc.getProperty(key); + + // then try in System properties + if (replacement == null) { + replacement = getSystemProperty(key, null); + } + + // if replacement is still null, use the defaultReplacement which + // can be null as well + if (replacement == null) { + replacement = defaultReplacement; + } + + if (replacement != null) { + // Do variable substitution on the replacement string + // such that we can solve "Hello ${x2}" as "Hello p1" + // where the properties are + // x1=p1 + // x2=${x1} + String recursiveReplacement = substVars(replacement, pc); + sbuf.append(recursiveReplacement); + } else { + // if we could not find a replacement, then signal the error + sbuf.append(key + "_IS_UNDEFINED"); + } + + i = k + DELIM_STOP_LEN; + } + } + } + } + + /** + * Very similar to System.getProperty except that the + * {@link SecurityException} is absorbed. + * + * @param key + * The key to search for. + * @param def + * The default value to return. + * @return the string value of the system property, or the default value if + * there is no property with that key. + */ + public static String getSystemProperty(String key, String def) { + try { + return System.getProperty(key, def); + } catch (SecurityException e) { + return def; + } + } + + /** + * Very similar to System.getProperty except that the + * {@link SecurityException} is absorbed. + * + * @param key + * The key to search for. + * + * @return the string value of the system property. + */ + public static String getSystemProperty(String key) { + try { + return System.getProperty(key); + } catch (SecurityException e) { + return null; + } + } + + /** + * Very similar to {@link System#getProperties()} except that the + * {@link SecurityException} is absorbed. + * + * @return the system properties + */ + public static Properties getSystemProperties() { + try { + return System.getProperties(); + } catch (SecurityException e) { + return new Properties(); + } + } + + static public String[] extractDefaultReplacement(String key) { + String[] result = new String[2]; + result[0] = key; + int d = key.indexOf(":-"); + if (d != -1) { + result[0] = key.substring(0, d); + result[1] = key.substring(d + 2); + } + return result; + } + + /** + * If value is "true", then true is returned. If + * value is "false", then true is returned. + * Otherwise, default is returned. + * + *

Case of value is unimportant. + */ + public static boolean toBoolean(String value, boolean dEfault) { + if (value == null) { + return dEfault; + } + + String trimmedVal = value.trim(); + + if ("true".equalsIgnoreCase(trimmedVal)) { + return true; + } + + if ("false".equalsIgnoreCase(trimmedVal)) { + return false; + } + + return dEfault; + } + + public static boolean isEmpty(String val) { + return ((val == null) || CoreConstants.EMPTY_STRING.equals(val)); + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetterException.java b/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetterException.java index c57d85bd3d062e4cdb227770e31d6abf1e9a027c..d1977c25a34faa9b50705e0845af8cbe1056458f 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetterException.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetterException.java @@ -1,37 +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.util; - -/** - * Thrown when an error is encountered whilst attempting to set a property - * using the {@link PropertySetter} utility class. - * - * @author Anders Kristensen - */ -public class PropertySetterException extends Exception { - - private static final long serialVersionUID = -2771077768281663949L; - - public PropertySetterException(String msg) { - super(msg); - } - - public PropertySetterException(Throwable rootCause) { - super(rootCause); - } - - public PropertySetterException(String message, Throwable cause) { - super(message, cause); - } -} +/** + * 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.util; + +/** + * Thrown when an error is encountered whilst attempting to set a property + * using the {@link PropertySetter} utility class. + * + * @author Anders Kristensen + */ +public class PropertySetterException extends Exception { + + private static final long serialVersionUID = -2771077768281663949L; + + public PropertySetterException(String msg) { + super(msg); + } + + public PropertySetterException(Throwable rootCause) { + super(rootCause); + } + + public PropertySetterException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java b/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java index 2e07ff624d708e9df8b3b90424ee6560f837696b..79afa8d568b3d788b3e0a5b2f076dc4154921637 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java @@ -1,173 +1,173 @@ -/** - * 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.util; - -import java.io.PrintStream; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.helpers.ThrowableToStringArray; -import ch.qos.logback.core.status.ErrorStatus; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusManager; - -public class StatusPrinter { - - private static PrintStream ps = System.out; - - static SimpleDateFormat simpleDateFormat = new SimpleDateFormat( - "HH:mm:ss,SSS"); - - public static void setPrintStream(PrintStream printStream) { - ps = printStream; - } - - /** - * Print the contents of the context statuses, but only if they contain - * warnings or errors. - * - * @param context - */ - public static void printInCaseOfErrorsOrWarnings(Context context) { - if (context == null) { - throw new IllegalArgumentException("Context argument cannot be null"); - } - - StatusManager sm = context.getStatusManager(); - if (sm == null) { - ps.println("WARN: Context named \"" + context.getName() - + "\" has no status manager"); - } else { - if (sm.getLevel() == ErrorStatus.WARN || (sm.getLevel() == ErrorStatus.ERROR) ) { - print(sm); - } - } - } - - /** - * Print the contents of the context statuses, but only if they contain - * errors. - * - * @param context - */ - public static void printIfErrorsOccured(Context context) { - if (context == null) { - throw new IllegalArgumentException("Context argument cannot be null"); - } - - StatusManager sm = context.getStatusManager(); - if (sm == null) { - ps.println("WARN: Context named \"" + context.getName() - + "\" has no status manager"); - } else { - if (sm.getLevel() == ErrorStatus.ERROR) { - print(sm); - } - } - } - - /** - * Print the contents of the context's status data. - * - * @param context - */ - public static void print(Context context) { - if (context == null) { - throw new IllegalArgumentException("Context argument cannot be null"); - } - - StatusManager sm = context.getStatusManager(); - if (sm == null) { - ps.println("WARN: Context named \"" + context.getName() - + "\" has no status manager"); - } else { - print(sm); - } - - } - - public static void print(StatusManager sm) { - StringBuilder sb = new StringBuilder(); - buildStrFromStatusManager(sb, sm); - ps.println(sb.toString()); - } - - public static void print(List statusList) { - StringBuilder sb = new StringBuilder(); - buildStrFromStatusList(sb, statusList); - ps.println(sb.toString()); - } - - - private static void buildStrFromStatusList(StringBuilder sb, List statusList) { - if(statusList == null) - return; - for(Status s : statusList) { - buildStr(sb, "", s); - } - } - - private static void buildStrFromStatusManager(StringBuilder sb, StatusManager sm) { - buildStrFromStatusList(sb, sm.getCopyOfStatusList()); - } - - private static void appendThrowable(StringBuilder sb, Throwable t) { - String[] stringRep = ThrowableToStringArray.convert(t); - - for (String s : stringRep) { - if (s.startsWith(CoreConstants.CAUSED_BY)) { - // nothing - } else if (Character.isDigit(s.charAt(0))) { - // if line resembles "48 common frames omitted" - sb.append("\t... "); - } else { - // most of the time. just add a tab+"at" - sb.append("\tat "); - } - sb.append(s).append(CoreConstants.LINE_SEPARATOR); - } - } - - public static void buildStr(StringBuilder sb, String indentation, Status s) { - String prefix; - if (s.hasChildren()) { - prefix = indentation + "+ "; - } else { - prefix = indentation + "|-"; - } - - if (simpleDateFormat != null) { - Date date = new Date(s.getDate()); - String dateStr = simpleDateFormat.format(date); - sb.append(dateStr).append(" "); - } - sb.append(prefix).append(s).append(CoreConstants.LINE_SEPARATOR); - - if (s.getThrowable() != null) { - appendThrowable(sb, s.getThrowable()); - } - if (s.hasChildren()) { - Iterator ite = s.iterator(); - while (ite.hasNext()) { - Status child = ite.next(); - buildStr(sb, indentation + " ", child); - } - } - } - -} +/** + * 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.util; + +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.helpers.ThrowableToStringArray; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; + +public class StatusPrinter { + + private static PrintStream ps = System.out; + + static SimpleDateFormat simpleDateFormat = new SimpleDateFormat( + "HH:mm:ss,SSS"); + + public static void setPrintStream(PrintStream printStream) { + ps = printStream; + } + + /** + * Print the contents of the context statuses, but only if they contain + * warnings or errors. + * + * @param context + */ + public static void printInCaseOfErrorsOrWarnings(Context context) { + if (context == null) { + throw new IllegalArgumentException("Context argument cannot be null"); + } + + StatusManager sm = context.getStatusManager(); + if (sm == null) { + ps.println("WARN: Context named \"" + context.getName() + + "\" has no status manager"); + } else { + if (sm.getLevel() == ErrorStatus.WARN || (sm.getLevel() == ErrorStatus.ERROR) ) { + print(sm); + } + } + } + + /** + * Print the contents of the context statuses, but only if they contain + * errors. + * + * @param context + */ + public static void printIfErrorsOccured(Context context) { + if (context == null) { + throw new IllegalArgumentException("Context argument cannot be null"); + } + + StatusManager sm = context.getStatusManager(); + if (sm == null) { + ps.println("WARN: Context named \"" + context.getName() + + "\" has no status manager"); + } else { + if (sm.getLevel() == ErrorStatus.ERROR) { + print(sm); + } + } + } + + /** + * Print the contents of the context's status data. + * + * @param context + */ + public static void print(Context context) { + if (context == null) { + throw new IllegalArgumentException("Context argument cannot be null"); + } + + StatusManager sm = context.getStatusManager(); + if (sm == null) { + ps.println("WARN: Context named \"" + context.getName() + + "\" has no status manager"); + } else { + print(sm); + } + + } + + public static void print(StatusManager sm) { + StringBuilder sb = new StringBuilder(); + buildStrFromStatusManager(sb, sm); + ps.println(sb.toString()); + } + + public static void print(List statusList) { + StringBuilder sb = new StringBuilder(); + buildStrFromStatusList(sb, statusList); + ps.println(sb.toString()); + } + + + private static void buildStrFromStatusList(StringBuilder sb, List statusList) { + if(statusList == null) + return; + for(Status s : statusList) { + buildStr(sb, "", s); + } + } + + private static void buildStrFromStatusManager(StringBuilder sb, StatusManager sm) { + buildStrFromStatusList(sb, sm.getCopyOfStatusList()); + } + + private static void appendThrowable(StringBuilder sb, Throwable t) { + String[] stringRep = ThrowableToStringArray.convert(t); + + for (String s : stringRep) { + if (s.startsWith(CoreConstants.CAUSED_BY)) { + // nothing + } else if (Character.isDigit(s.charAt(0))) { + // if line resembles "48 common frames omitted" + sb.append("\t... "); + } else { + // most of the time. just add a tab+"at" + sb.append("\tat "); + } + sb.append(s).append(CoreConstants.LINE_SEPARATOR); + } + } + + public static void buildStr(StringBuilder sb, String indentation, Status s) { + String prefix; + if (s.hasChildren()) { + prefix = indentation + "+ "; + } else { + prefix = indentation + "|-"; + } + + if (simpleDateFormat != null) { + Date date = new Date(s.getDate()); + String dateStr = simpleDateFormat.format(date); + sb.append(dateStr).append(" "); + } + sb.append(prefix).append(s).append(CoreConstants.LINE_SEPARATOR); + + if (s.getThrowable() != null) { + appendThrowable(sb, s.getThrowable()); + } + if (s.hasChildren()) { + Iterator ite = s.iterator(); + while (ite.hasNext()) { + Status child = ite.next(); + buildStr(sb, indentation + " ", child); + } + } + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/SystemInfo.java b/logback-core/src/main/java/ch/qos/logback/core/util/SystemInfo.java index d0fe1fc6d1746119ac3142578c2a0c9dabc3a254..e2d701f3fb726a3ced6c3f99a9b2ded317e80c49 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/SystemInfo.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/SystemInfo.java @@ -1,22 +1,22 @@ -/** - * 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.util; - -public class SystemInfo { - - - public static String getJavaVendor() { - return OptionHelper.getSystemProperty("java.vendor", null); - } -} +/** + * 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.util; + +public class SystemInfo { + + + public static String getJavaVendor() { + return OptionHelper.getSystemProperty("java.vendor", null); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/TimeUtil.java b/logback-core/src/main/java/ch/qos/logback/core/util/TimeUtil.java index 7deeef261d9cda12715e29ca609f7ed5b6404aca..f50e01813488c2efd91ca89a36d74a1643634d98 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/TimeUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/util/TimeUtil.java @@ -1,89 +1,89 @@ -/** - * 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.util; - -import java.util.Calendar; -import java.util.Date; - -public class TimeUtil { - - - public static long computeStartOfNextSecond(long now) { - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(now)); - cal.set(Calendar.MILLISECOND, 0); - cal.add(Calendar.SECOND, 1); - return cal.getTime().getTime(); - } - - public static long computeStartOfNextMinute(long now) { - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(now)); - cal.set(Calendar.MILLISECOND, 0); - cal.set(Calendar.SECOND, 0); - cal.add(Calendar.MINUTE, 1); - return cal.getTime().getTime(); - } - - public static long computeStartOfNextHour(long now) { - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(now)); - cal.set(Calendar.MILLISECOND, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MINUTE, 0); - cal.add(Calendar.HOUR, 1); - return cal.getTime().getTime(); - } - - public static long computeStartOfNextDay(long now) { - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(now)); - - cal.add(Calendar.DAY_OF_MONTH, 1); - cal.set(Calendar.MILLISECOND, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.HOUR_OF_DAY, 0); - return cal.getTime().getTime(); - } - - public static long computeStartOfNextWeek(long now) { - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(now)); - - cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - cal.add(Calendar.WEEK_OF_YEAR, 1); - return cal.getTime().getTime(); - } - - public static long computeStartOfNextMonth(long now) { - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(now)); - - cal.set(Calendar.DATE, 1); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - cal.add(Calendar.MONTH, 1); - return cal.getTime().getTime(); - } - - - -} +/** + * 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.util; + +import java.util.Calendar; +import java.util.Date; + +public class TimeUtil { + + + public static long computeStartOfNextSecond(long now) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + cal.set(Calendar.MILLISECOND, 0); + cal.add(Calendar.SECOND, 1); + return cal.getTime().getTime(); + } + + public static long computeStartOfNextMinute(long now) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + cal.set(Calendar.MILLISECOND, 0); + cal.set(Calendar.SECOND, 0); + cal.add(Calendar.MINUTE, 1); + return cal.getTime().getTime(); + } + + public static long computeStartOfNextHour(long now) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + cal.set(Calendar.MILLISECOND, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MINUTE, 0); + cal.add(Calendar.HOUR, 1); + return cal.getTime().getTime(); + } + + public static long computeStartOfNextDay(long now) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + + cal.add(Calendar.DAY_OF_MONTH, 1); + cal.set(Calendar.MILLISECOND, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.HOUR_OF_DAY, 0); + return cal.getTime().getTime(); + } + + public static long computeStartOfNextWeek(long now) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + + cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + cal.add(Calendar.WEEK_OF_YEAR, 1); + return cal.getTime().getTime(); + } + + public static long computeStartOfNextMonth(long now) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + + cal.set(Calendar.DATE, 1); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + cal.add(Calendar.MONTH, 1); + return cal.getTime().getTime(); + } + + + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/package.html b/logback-core/src/main/java/ch/qos/logback/core/util/package.html index 55658ef79610abb0c038b5c2317d1a0fb8f67cf9..311d89f0b05cf67e2e8481b27bf8e2c9855a9a3e 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/util/package.html +++ b/logback-core/src/main/java/ch/qos/logback/core/util/package.html @@ -1,13 +1,13 @@ - - - - - - - - - -

Contains various utility classes.

- - - + + + + + + + + + +

Contains various utility classes.

+ + + diff --git a/logback-core/src/test/build.xml b/logback-core/src/test/build.xml index 018f3ed490a09d898d6cad963c1e795d42cae7c0..ff824eccfe16a8b13952f82fae8f7eb05b8e800b 100644 --- a/logback-core/src/test/build.xml +++ b/logback-core/src/test/build.xml @@ -1,175 +1,175 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - These are the targets supported by this ANT build scpript: - - build - compile all project files, if a certain library is missing, - then the compilation of its dependents are skipped. - - all - run all available tests - - - - - - - - - - - - - - - - - - - - - - Could not find junit classes. Is the file junit.jar missing? - See the documentation for the junit task in the Apache Ant Manual. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + These are the targets supported by this ANT build scpript: + + build - compile all project files, if a certain library is missing, + then the compilation of its dependents are skipped. + + all - run all available tests + + + + + + + + + + + + + + + + + + + + + + Could not find junit classes. Is the file junit.jar missing? + See the documentation for the junit task in the Apache Ant Manual. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/logback-core/src/test/input/compress1.copy b/logback-core/src/test/input/compress1.copy index fd9dc54a0e17836bcafd7191edd614e43f96b6a5..6ec9d8e577d9c910cedfb0769bd3c221c8a88720 100644 --- a/logback-core/src/test/input/compress1.copy +++ b/logback-core/src/test/input/compress1.copy @@ -1,8 +1,8 @@ - - LOGBack: the generic, reliable, fast and flexible logging framework. - - Copyright (C) 1999-2006, QOS.ch - - This library is free software, you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by the Free - Software Foundation. + + LOGBack: the generic, reliable, fast and flexible logging framework. + + Copyright (C) 1999-2006, QOS.ch + + This library is free software, you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation. diff --git a/logback-core/src/test/input/compress3.copy b/logback-core/src/test/input/compress3.copy index 9d2c1ef36e9cb766969187bc4d2a4d7a0291e601..87087da0cc9d389bfb80ae0fac9c3cfaa02bf0c9 100644 --- a/logback-core/src/test/input/compress3.copy +++ b/logback-core/src/test/input/compress3.copy @@ -1,11 +1,11 @@ - - LOGBack: the generic, reliable, fast and flexible logging framework. - - Copyright (C) 1999-2006, QOS.ch - - This library is free software, you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by the Free - Software Foundation. + + LOGBack: the generic, reliable, fast and flexible logging framework. + + Copyright (C) 1999-2006, QOS.ch + + This library is free software, you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation. diff --git a/logback-core/src/test/input/joran/ampEvent.xml b/logback-core/src/test/input/joran/ampEvent.xml index 641d00ef79643f0a8ccf5b99535bfbae0f2b84d8..04a278b860f4c66175bb5549a2bfb64b1b6921d5 100644 --- a/logback-core/src/test/input/joran/ampEvent.xml +++ b/logback-core/src/test/input/joran/ampEvent.xml @@ -1,3 +1,3 @@ - - -xxx & yyy + + +xxx & yyy diff --git a/logback-core/src/test/input/joran/attributesEvent.xml b/logback-core/src/test/input/joran/attributesEvent.xml index 9447e816cbec4b69c32f219522fd6ce4ab0e5324..93de0bc18655c5240ee141ca03ed91872496de82 100644 --- a/logback-core/src/test/input/joran/attributesEvent.xml +++ b/logback-core/src/test/input/joran/attributesEvent.xml @@ -1,3 +1,3 @@ - - - + + + diff --git a/logback-core/src/test/input/joran/event1.xml b/logback-core/src/test/input/joran/event1.xml index 40f159e7e3c408578990243a2adf495f6b4397d8..ccc1584063a2632d49f9ed5ff9a83957233f1cc1 100644 --- a/logback-core/src/test/input/joran/event1.xml +++ b/logback-core/src/test/input/joran/event1.xml @@ -1,14 +1,14 @@ - - - - - - - - - - - - XXX& - + + + + + + + + + + + + XXX& + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/fire1.xml b/logback-core/src/test/input/joran/fire1.xml index 2b099f3e193fd425a366343006d3f5bb1ddca24d..a9722ce8335132f433778a887b1e33386ec291c0 100644 --- a/logback-core/src/test/input/joran/fire1.xml +++ b/logback-core/src/test/input/joran/fire1.xml @@ -1,5 +1,5 @@ - - - - abc - + + + + abc + diff --git a/logback-core/src/test/input/joran/illformed.xml b/logback-core/src/test/input/joran/illformed.xml index 1394b14b81e9e2b0cd27c9fa3ccbeba837c2d86d..8e8cd50efcbe6ff82d7856d05631a12eef28b6fc 100644 --- a/logback-core/src/test/input/joran/illformed.xml +++ b/logback-core/src/test/input/joran/illformed.xml @@ -1,5 +1,5 @@ - - - - - + + + + + diff --git a/logback-core/src/test/input/joran/implicitAction/nestedComplex.xml b/logback-core/src/test/input/joran/implicitAction/nestedComplex.xml index 11aa2b458b809d13b38d5a523fd8441ba6ec7bfb..ce8d17bddd9459efa473fb0650f97b61636293fa 100644 --- a/logback-core/src/test/input/joran/implicitAction/nestedComplex.xml +++ b/logback-core/src/test/input/joran/implicitAction/nestedComplex.xml @@ -1,9 +1,9 @@ - - - - - blue - hello - world - + + + + + blue + hello + world + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/implicitAction/nestedComplexCollection.xml b/logback-core/src/test/input/joran/implicitAction/nestedComplexCollection.xml index d35e28160b3330ed604a27a029298dd139fea685..93f8a9f851b8ccfc09f0a3ee5341bbbeed12c769 100644 --- a/logback-core/src/test/input/joran/implicitAction/nestedComplexCollection.xml +++ b/logback-core/src/test/input/joran/implicitAction/nestedComplexCollection.xml @@ -1,17 +1,17 @@ - - - - - blue - hello - world - - A - 1 - - - B - 2 - - + + + + + blue + hello + world + + A + 1 + + + B + 2 + + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/implicitAction/nestedComplexCollectionWithoutClassAtrribute.xml b/logback-core/src/test/input/joran/implicitAction/nestedComplexCollectionWithoutClassAtrribute.xml index cff6895d9e88dcc2d81550394acd93cce8ec2209..b23ffa04f340cbd82b86f17cb67b74af8aa3c887 100644 --- a/logback-core/src/test/input/joran/implicitAction/nestedComplexCollectionWithoutClassAtrribute.xml +++ b/logback-core/src/test/input/joran/implicitAction/nestedComplexCollectionWithoutClassAtrribute.xml @@ -1,17 +1,17 @@ - - - - - blue - hello - world - - A - 1 - - - B - 2 - - + + + + + blue + hello + world + + A + 1 + + + B + 2 + + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/implicitAction/nestedComplexWithoutClassAtrribute.xml b/logback-core/src/test/input/joran/implicitAction/nestedComplexWithoutClassAtrribute.xml index 0f9fc056621a5830b5550c51a4e993ac1914ea14..716ba793af43da7861bfe71683096f775a6e8af4 100644 --- a/logback-core/src/test/input/joran/implicitAction/nestedComplexWithoutClassAtrribute.xml +++ b/logback-core/src/test/input/joran/implicitAction/nestedComplexWithoutClassAtrribute.xml @@ -1,9 +1,9 @@ - - - - - blue - hello - world - + + + + + blue + hello + world + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/inc.xml b/logback-core/src/test/input/joran/inc.xml index bcccae05936515fc261c4bc97261aca2c1dcefa0..7df847d63910387b06c2878ada459caf2bef3ba7 100644 --- a/logback-core/src/test/input/joran/inc.xml +++ b/logback-core/src/test/input/joran/inc.xml @@ -1,5 +1,5 @@ - - - - - + + + + + diff --git a/logback-core/src/test/input/joran/inclusion/included.xml b/logback-core/src/test/input/joran/inclusion/included.xml index 25664729ccbcca63941c0b2c302021e476f7ee9e..7dfb5fe6e8a0a23f30d2596cb6c6a32e17ab2756 100644 --- a/logback-core/src/test/input/joran/inclusion/included.xml +++ b/logback-core/src/test/input/joran/inclusion/included.xml @@ -1,9 +1,9 @@ - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/inclusion/multiIncludeByFile.xml b/logback-core/src/test/input/joran/inclusion/multiIncludeByFile.xml index 0a133f72ee867ace61270a78896e372c313487e3..dd1d158db121ff84f13345a3655d67c2f3e58ee4 100644 --- a/logback-core/src/test/input/joran/inclusion/multiIncludeByFile.xml +++ b/logback-core/src/test/input/joran/inclusion/multiIncludeByFile.xml @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/logback-core/src/test/input/joran/inclusion/second.xml b/logback-core/src/test/input/joran/inclusion/second.xml index e7a706d2ca4a51451928cdced3b074f913b801d5..33518574d9290806bdbb3e4985083b519c4a2aba 100644 --- a/logback-core/src/test/input/joran/inclusion/second.xml +++ b/logback-core/src/test/input/joran/inclusion/second.xml @@ -1,8 +1,8 @@ - - - - - - - + + + + + + + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/inclusion/subByFile.xml b/logback-core/src/test/input/joran/inclusion/subByFile.xml index 4f60762a39bfc1d384fb46325b52c13db6081ce1..5f82d776de81c4011e137d29940343a19b1cefe0 100644 --- a/logback-core/src/test/input/joran/inclusion/subByFile.xml +++ b/logback-core/src/test/input/joran/inclusion/subByFile.xml @@ -1,6 +1,6 @@ - - - - - - + + + + + + diff --git a/logback-core/src/test/input/joran/inclusion/topByFile.xml b/logback-core/src/test/input/joran/inclusion/topByFile.xml index e23cfc4ca9d8209ff9e01e41d6b2597b0eb5efc7..4dc521c26125b99cd1dea30bb7def51e7ad51421 100644 --- a/logback-core/src/test/input/joran/inclusion/topByFile.xml +++ b/logback-core/src/test/input/joran/inclusion/topByFile.xml @@ -1,6 +1,6 @@ - - - - - - + + + + + + diff --git a/logback-core/src/test/input/joran/inclusion/topByResource.xml b/logback-core/src/test/input/joran/inclusion/topByResource.xml index ea91a30d5c493c80c2d1b08363ca772343ea5093..63e02db68fed7f056c608f2d6a50504328dd9a6e 100644 --- a/logback-core/src/test/input/joran/inclusion/topByResource.xml +++ b/logback-core/src/test/input/joran/inclusion/topByResource.xml @@ -1,8 +1,8 @@ - - - - - - - - + + + + + + + + diff --git a/logback-core/src/test/input/joran/inclusion/topByUrl.xml b/logback-core/src/test/input/joran/inclusion/topByUrl.xml index 10558b170f75b4d2ac5333b991e7181210294976..f49cd974dee35316645b7a388769a399b3a04cb0 100644 --- a/logback-core/src/test/input/joran/inclusion/topByUrl.xml +++ b/logback-core/src/test/input/joran/inclusion/topByUrl.xml @@ -1,6 +1,6 @@ - - - - - - + + + + + + diff --git a/logback-core/src/test/input/joran/propertyActionTest.properties b/logback-core/src/test/input/joran/propertyActionTest.properties index 19f14e661c667cffce84fe1c6133f0ae667a8d54..eb63f10daf43594d30e95f549482f190a0e0e2cd 100644 --- a/logback-core/src/test/input/joran/propertyActionTest.properties +++ b/logback-core/src/test/input/joran/propertyActionTest.properties @@ -1,2 +1,2 @@ -v1=tata +v1=tata v2=toto \ No newline at end of file diff --git a/logback-core/src/test/input/joran/replay/fruit1.xml b/logback-core/src/test/input/joran/replay/fruit1.xml index 6bd51253b5024991505ecf8809496dd212e490ab..499c6f9bf8ea01980c98059aced7e2210247ed0f 100644 --- a/logback-core/src/test/input/joran/replay/fruit1.xml +++ b/logback-core/src/test/input/joran/replay/fruit1.xml @@ -1,9 +1,9 @@ - - - - - - blue - - + + + + + + blue + + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/replay/fruit2.xml b/logback-core/src/test/input/joran/replay/fruit2.xml index 4818d37bac4f70e2055ca336802f3d953c8a6fad..efafe7c7ea50d35a9bc64ad2ce07e9236cf03080 100644 --- a/logback-core/src/test/input/joran/replay/fruit2.xml +++ b/logback-core/src/test/input/joran/replay/fruit2.xml @@ -1,16 +1,16 @@ - - - - - - blue - - - - - - orange - 1.2 - - + + + + + + blue + + + + + + orange + 1.2 + + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/replay/fruitWithSubst.xml b/logback-core/src/test/input/joran/replay/fruitWithSubst.xml index 3d332d395495b60984bbe0abbec1c37532b11ac7..ff921eb2d46d5bde19ef964f987489f42d12bd63 100644 --- a/logback-core/src/test/input/joran/replay/fruitWithSubst.xml +++ b/logback-core/src/test/input/joran/replay/fruitWithSubst.xml @@ -1,10 +1,10 @@ - - - - - - ${fruitKey} - 1.2 - - + + + + + + ${fruitKey} + 1.2 + + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/skip/badBegin1.xml b/logback-core/src/test/input/joran/skip/badBegin1.xml index f8a8ac3568523b1e9ba21ad185b60d075fec1a90..c3f068bb2517db4a46ecaa096ac4a7c427d56cac 100644 --- a/logback-core/src/test/input/joran/skip/badBegin1.xml +++ b/logback-core/src/test/input/joran/skip/badBegin1.xml @@ -1,14 +1,14 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/skip/badBegin2.xml b/logback-core/src/test/input/joran/skip/badBegin2.xml index 3149503dc2588cfb78629f8f4ef77ed98cedf998..33ed4e75196f9527458fd9092cd9276945827732 100644 --- a/logback-core/src/test/input/joran/skip/badBegin2.xml +++ b/logback-core/src/test/input/joran/skip/badBegin2.xml @@ -1,14 +1,14 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/skip/badEnd1.xml b/logback-core/src/test/input/joran/skip/badEnd1.xml index 73ecb524353c7c541c04ddf91bf4347ef3021c31..f81500d90f5732cad68e5f41860fc14719660680 100644 --- a/logback-core/src/test/input/joran/skip/badEnd1.xml +++ b/logback-core/src/test/input/joran/skip/badEnd1.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/logback-core/src/test/input/joran/skip/badEnd2.xml b/logback-core/src/test/input/joran/skip/badEnd2.xml index 8315983dd42dd2823ab51f5b8ecf954add576d55..0d65b11648eddedc0d9fdd410b7f9197bf1dcbab 100644 --- a/logback-core/src/test/input/joran/skip/badEnd2.xml +++ b/logback-core/src/test/input/joran/skip/badEnd2.xml @@ -1,17 +1,17 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + \ No newline at end of file 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 5521967023e624ae9c6ddd1b460966c1cf9f82eb..a3af565b6a127058bbfd15ae47a748738413654c 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 @@ -1,33 +1,33 @@ -/** - * 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; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({BasicStatusManagerTest.class, - ch.qos.logback.core.util.PackageTest.class, - ch.qos.logback.core.helpers.PackageTest.class, - ch.qos.logback.core.pattern.PackageTest.class, - ch.qos.logback.core.PackageTest.class, - ch.qos.logback.core.joran.PackageTest.class, - ch.qos.logback.core.appender.PackageTest.class, - ch.qos.logback.core.spi.PackageTest.class, - ch.qos.logback.core.rolling.PackageTest.class, - ch.qos.logback.core.sift.PackageTest.class}) -public class AllCoreTest { - -} +/** + * 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; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({BasicStatusManagerTest.class, + ch.qos.logback.core.util.PackageTest.class, + ch.qos.logback.core.helpers.PackageTest.class, + ch.qos.logback.core.pattern.PackageTest.class, + ch.qos.logback.core.PackageTest.class, + ch.qos.logback.core.joran.PackageTest.class, + ch.qos.logback.core.appender.PackageTest.class, + ch.qos.logback.core.spi.PackageTest.class, + ch.qos.logback.core.rolling.PackageTest.class, + ch.qos.logback.core.sift.PackageTest.class}) +public class AllCoreTest { + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/BasicStatusManagerTest.java b/logback-core/src/test/java/ch/qos/logback/core/BasicStatusManagerTest.java index 27a645e34489828dce1af701fd15ab78b1778427..0153cfde6cfed4023d364860f2f878ceb4ffcd97 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/BasicStatusManagerTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/BasicStatusManagerTest.java @@ -1,66 +1,66 @@ -/** - * 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; - -import static ch.qos.logback.core.BasicStatusManager.MAX_HEADER_COUNT; -import static ch.qos.logback.core.BasicStatusManager.TAIL_SIZE; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import ch.qos.logback.core.status.ErrorStatus; -import ch.qos.logback.core.status.Status; - - -public class BasicStatusManagerTest { - - - BasicStatusManager bsm = new BasicStatusManager(); - - @Test - public void smoke() { - bsm.add(new ErrorStatus("hello", this)); - assertEquals(Status.ERROR, bsm.getLevel()); - - List statusList = bsm.getCopyOfStatusList(); - assertNotNull(statusList); - assertEquals(1, statusList.size()); - assertEquals("hello", statusList.get(0).getMessage()); - } - - @Test - public void many() { - int margin = 300; - int len = MAX_HEADER_COUNT+TAIL_SIZE+margin; - for(int i = 0; i < len; i++) { - bsm.add(new ErrorStatus(""+i, this)); - } - - List statusList = bsm.getCopyOfStatusList(); - assertNotNull(statusList); - assertEquals(MAX_HEADER_COUNT+TAIL_SIZE, statusList.size()); - List witness = new ArrayList(); - for(int i = 0; i < MAX_HEADER_COUNT; i++) { - witness.add(new ErrorStatus(""+i, this)); - } - for(int i = 0; i < TAIL_SIZE; i++) { - witness.add(new ErrorStatus(""+(MAX_HEADER_COUNT+margin+i), this)); - } - assertEquals(witness, statusList); - } -} +/** + * 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; + +import static ch.qos.logback.core.BasicStatusManager.MAX_HEADER_COUNT; +import static ch.qos.logback.core.BasicStatusManager.TAIL_SIZE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.Status; + + +public class BasicStatusManagerTest { + + + BasicStatusManager bsm = new BasicStatusManager(); + + @Test + public void smoke() { + bsm.add(new ErrorStatus("hello", this)); + assertEquals(Status.ERROR, bsm.getLevel()); + + List statusList = bsm.getCopyOfStatusList(); + assertNotNull(statusList); + assertEquals(1, statusList.size()); + assertEquals("hello", statusList.get(0).getMessage()); + } + + @Test + public void many() { + int margin = 300; + int len = MAX_HEADER_COUNT+TAIL_SIZE+margin; + for(int i = 0; i < len; i++) { + bsm.add(new ErrorStatus(""+i, this)); + } + + List statusList = bsm.getCopyOfStatusList(); + assertNotNull(statusList); + assertEquals(MAX_HEADER_COUNT+TAIL_SIZE, statusList.size()); + List witness = new ArrayList(); + for(int i = 0; i < MAX_HEADER_COUNT; i++) { + witness.add(new ErrorStatus(""+i, this)); + } + for(int i = 0; i < TAIL_SIZE; i++) { + witness.add(new ErrorStatus(""+(MAX_HEADER_COUNT+margin+i), this)); + } + assertEquals(witness, statusList); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/ContextBaseTest.java b/logback-core/src/test/java/ch/qos/logback/core/ContextBaseTest.java index ec581e42217f3a1422354be375289eb616d8341b..823ccec6cf58e98b2db22a4cbdb2415c4215b701 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/ContextBaseTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/ContextBaseTest.java @@ -1,60 +1,60 @@ -/** - * 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; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -import org.junit.Test; - -public class ContextBaseTest { - - ContextBase context = new ContextBase(); - - @Test - public void renameDefault() { - context.setName(CoreConstants.DEFAULT_CONTEXT_NAME); - context.setName("hello"); - } - - - @Test - public void idempotentNameTest() { - context.setName("hello"); - context.setName("hello"); - } - - @Test - public void renameTest() { - context.setName("hello"); - try { - context.setName("x"); - fail("renaming is not allowed"); - } catch (IllegalStateException ise) { - } - } - - @Test - public void resetTest() { - context.setName("hello"); - context.putProperty("keyA", "valA"); - context.putObject("keyA", "valA"); - assertEquals("valA", context.getProperty("keyA")); - assertEquals("valA", context.getObject("keyA")); - context.reset(); - assertNull(context.getProperty("keyA")); - assertNull(context.getObject("keyA")); - } -} +/** + * 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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import org.junit.Test; + +public class ContextBaseTest { + + ContextBase context = new ContextBase(); + + @Test + public void renameDefault() { + context.setName(CoreConstants.DEFAULT_CONTEXT_NAME); + context.setName("hello"); + } + + + @Test + public void idempotentNameTest() { + context.setName("hello"); + context.setName("hello"); + } + + @Test + public void renameTest() { + context.setName("hello"); + try { + context.setName("x"); + fail("renaming is not allowed"); + } catch (IllegalStateException ise) { + } + } + + @Test + public void resetTest() { + context.setName("hello"); + context.putProperty("keyA", "valA"); + context.putObject("keyA", "valA"); + assertEquals("valA", context.getProperty("keyA")); + assertEquals("valA", context.getObject("keyA")); + context.reset(); + assertNull(context.getProperty("keyA")); + assertNull(context.getObject("keyA")); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/PackageTest.java index 2bb23170c3c6b2b0dcc4efe2980b6cae9dd392d7..190f370a97b641d7005689be9c85a09a38a2eb5f 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/PackageTest.java @@ -1,23 +1,23 @@ -/** - * 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; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses( { ContextBaseTest.class, WriterAppenderTest.class }) -public class PackageTest { -} +/** + * 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; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses( { ContextBaseTest.class, WriterAppenderTest.class }) +public class PackageTest { +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/WriterAppenderTest.java b/logback-core/src/test/java/ch/qos/logback/core/WriterAppenderTest.java index b360cb939c3611225239418425b46f5a2ee912ba..c560a279ac016fbf59af0ffbb60563b75eb85b22 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/WriterAppenderTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/WriterAppenderTest.java @@ -1,117 +1,117 @@ -/** - * 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; - - -import static org.junit.Assert.*; - -import java.io.StringWriter; -import java.io.Writer; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.pattern.parser.SamplePatternLayout; - -public class WriterAppenderTest { - - Context context = new ContextBase(); - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void smoke() { - String FILE_HEADER = "FILE_HEADER "; - String PRESENTATION_HEADER = "PRESENTATION_HEADER"; - String PRESENTATION_FOOTER = "PRESENTATION_FOOTER "; - String FILE_FOOTER = "FILE_FOOTER"; - headerFooterCheck(FILE_HEADER, PRESENTATION_HEADER, PRESENTATION_FOOTER, FILE_FOOTER); - } - - @Test - public void nullFileHeader() { - String FILE_HEADER = null; - String PRESENTATION_HEADER = "PRESENTATION_HEADER"; - String PRESENTATION_FOOTER = "PRESENTATION_FOOTER "; - String FILE_FOOTER = "FILE_FOOTER"; - headerFooterCheck(FILE_HEADER, PRESENTATION_HEADER, PRESENTATION_FOOTER, FILE_FOOTER); - } - - @Test - public void nullPresentationHeader() { - String FILE_HEADER = "FILE_HEADER "; - String PRESENTATION_HEADER = null; - String PRESENTATION_FOOTER = "PRESENTATION_FOOTER "; - String FILE_FOOTER = "FILE_FOOTER"; - headerFooterCheck(FILE_HEADER, PRESENTATION_HEADER, PRESENTATION_FOOTER, FILE_FOOTER); - } - - @Test - public void nullPresentationFooter() { - String FILE_HEADER = "FILE_HEADER "; - String PRESENTATION_HEADER = "PRESENTATION_HEADER"; - String PRESENTATION_FOOTER = null; - String FILE_FOOTER = "FILE_FOOTER"; - headerFooterCheck(FILE_HEADER, PRESENTATION_HEADER, PRESENTATION_FOOTER, FILE_FOOTER); - } - - @Test - public void nullFileFooter() { - String FILE_HEADER = "FILE_HEADER "; - String PRESENTATION_HEADER = "PRESENTATION_HEADER"; - String PRESENTATION_FOOTER = "PRESENTATION_FOOTER "; - String FILE_FOOTER = null; - headerFooterCheck(FILE_HEADER, PRESENTATION_HEADER, PRESENTATION_FOOTER, FILE_FOOTER); - } - - public void headerFooterCheck(String fileHeader, String presentationHeader, String presentationFooter, String fileFooter) { - WriterAppender wa = new WriterAppender(); - wa.setContext(context); - Writer sw = new StringWriter(); - - SamplePatternLayout spl = new SamplePatternLayout(); - spl.setContext(context); - - spl.setFileHeader(fileHeader); - spl.setPresentationHeader(presentationHeader); - spl.setPresentationFooter(presentationFooter); - spl.setFileFooter(fileFooter); - - spl.start(); - - wa.setLayout(spl); - wa.setWriter(sw); - wa.start(); - - wa.stop(); - String result = sw.toString(); - - String expectedHeader = emtptyIfNull(fileHeader) + emtptyIfNull(presentationHeader); - assertTrue(result, result.startsWith(expectedHeader)); - - String expectedFooter = emtptyIfNull(presentationFooter) + emtptyIfNull(fileFooter); - assertTrue(result, result.endsWith(expectedFooter)); - } - - String emtptyIfNull(String s) { - return s == null ? "" : s; - } -} +/** + * 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; + + +import static org.junit.Assert.*; + +import java.io.StringWriter; +import java.io.Writer; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.pattern.parser.SamplePatternLayout; + +public class WriterAppenderTest { + + Context context = new ContextBase(); + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void smoke() { + String FILE_HEADER = "FILE_HEADER "; + String PRESENTATION_HEADER = "PRESENTATION_HEADER"; + String PRESENTATION_FOOTER = "PRESENTATION_FOOTER "; + String FILE_FOOTER = "FILE_FOOTER"; + headerFooterCheck(FILE_HEADER, PRESENTATION_HEADER, PRESENTATION_FOOTER, FILE_FOOTER); + } + + @Test + public void nullFileHeader() { + String FILE_HEADER = null; + String PRESENTATION_HEADER = "PRESENTATION_HEADER"; + String PRESENTATION_FOOTER = "PRESENTATION_FOOTER "; + String FILE_FOOTER = "FILE_FOOTER"; + headerFooterCheck(FILE_HEADER, PRESENTATION_HEADER, PRESENTATION_FOOTER, FILE_FOOTER); + } + + @Test + public void nullPresentationHeader() { + String FILE_HEADER = "FILE_HEADER "; + String PRESENTATION_HEADER = null; + String PRESENTATION_FOOTER = "PRESENTATION_FOOTER "; + String FILE_FOOTER = "FILE_FOOTER"; + headerFooterCheck(FILE_HEADER, PRESENTATION_HEADER, PRESENTATION_FOOTER, FILE_FOOTER); + } + + @Test + public void nullPresentationFooter() { + String FILE_HEADER = "FILE_HEADER "; + String PRESENTATION_HEADER = "PRESENTATION_HEADER"; + String PRESENTATION_FOOTER = null; + String FILE_FOOTER = "FILE_FOOTER"; + headerFooterCheck(FILE_HEADER, PRESENTATION_HEADER, PRESENTATION_FOOTER, FILE_FOOTER); + } + + @Test + public void nullFileFooter() { + String FILE_HEADER = "FILE_HEADER "; + String PRESENTATION_HEADER = "PRESENTATION_HEADER"; + String PRESENTATION_FOOTER = "PRESENTATION_FOOTER "; + String FILE_FOOTER = null; + headerFooterCheck(FILE_HEADER, PRESENTATION_HEADER, PRESENTATION_FOOTER, FILE_FOOTER); + } + + public void headerFooterCheck(String fileHeader, String presentationHeader, String presentationFooter, String fileFooter) { + WriterAppender wa = new WriterAppender(); + wa.setContext(context); + Writer sw = new StringWriter(); + + SamplePatternLayout spl = new SamplePatternLayout(); + spl.setContext(context); + + spl.setFileHeader(fileHeader); + spl.setPresentationHeader(presentationHeader); + spl.setPresentationFooter(presentationFooter); + spl.setFileFooter(fileFooter); + + spl.start(); + + wa.setLayout(spl); + wa.setWriter(sw); + wa.start(); + + wa.stop(); + String result = sw.toString(); + + String expectedHeader = emtptyIfNull(fileHeader) + emtptyIfNull(presentationHeader); + assertTrue(result, result.startsWith(expectedHeader)); + + String expectedFooter = emtptyIfNull(presentationFooter) + emtptyIfNull(fileFooter); + assertTrue(result, result.endsWith(expectedFooter)); + } + + String emtptyIfNull(String s) { + return s == null ? "" : s; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/appender/AbstractAppenderTest.java b/logback-core/src/test/java/ch/qos/logback/core/appender/AbstractAppenderTest.java index 001121f11a7e172e0625f8e945fb8cae120410cb..61b0826f7ad37905ec64afed949d464fc3952d96 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/appender/AbstractAppenderTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/appender/AbstractAppenderTest.java @@ -1,67 +1,67 @@ -/** - * 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.appender; - - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.status.StatusChecker; - - - -abstract public class AbstractAppenderTest { - - - abstract protected Appender getAppender(); - abstract protected Appender getConfiguredAppender(); - - @Test - public void testNewAppender() { - // new appenders should be inactive - Appender appender = getAppender(); - assertFalse( appender.isStarted()); - } - - @Test - public void testConfiguredAppender() { - Appender appender = getConfiguredAppender(); - appender.start(); - assertTrue(appender.isStarted()); - - appender.stop(); - assertFalse(appender.isStarted()); - - } - - @Test - public void testNoStart() { - Appender appender = getAppender(); - Context context = new ContextBase(); - appender.setContext(context); - appender.setName("doh"); - // is null OK? - appender.doAppend(null); - StatusChecker checker = new StatusChecker(context.getStatusManager()); - //StatusPrinter.print(context.getStatusManager()); - assertTrue(checker.containsMatch("Attempted to append to non started appender \\[doh\\].")); - } -} - - +/** + * 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.appender; + + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.status.StatusChecker; + + + +abstract public class AbstractAppenderTest { + + + abstract protected Appender getAppender(); + abstract protected Appender getConfiguredAppender(); + + @Test + public void testNewAppender() { + // new appenders should be inactive + Appender appender = getAppender(); + assertFalse( appender.isStarted()); + } + + @Test + public void testConfiguredAppender() { + Appender appender = getConfiguredAppender(); + appender.start(); + assertTrue(appender.isStarted()); + + appender.stop(); + assertFalse(appender.isStarted()); + + } + + @Test + public void testNoStart() { + Appender appender = getAppender(); + Context context = new ContextBase(); + appender.setContext(context); + appender.setName("doh"); + // is null OK? + appender.doAppend(null); + StatusChecker checker = new StatusChecker(context.getStatusManager()); + //StatusPrinter.print(context.getStatusManager()); + assertTrue(checker.containsMatch("Attempted to append to non started appender \\[doh\\].")); + } +} + + diff --git a/logback-core/src/test/java/ch/qos/logback/core/appender/ConsoleAppenderTest.java b/logback-core/src/test/java/ch/qos/logback/core/appender/ConsoleAppenderTest.java index afb858e68b475dc35ff70a3f50d186252701c539..e10888f290c8d65fa93f4d34e30c2f3953c7119e 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/appender/ConsoleAppenderTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/appender/ConsoleAppenderTest.java @@ -1,119 +1,119 @@ -/** - * 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.appender; - -import static org.junit.Assert.assertEquals; - -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.ConsoleAppender; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.layout.DummyLayout; -import ch.qos.logback.core.layout.NopLayout; -import ch.qos.logback.core.util.TeeOutputStream; - - -public class ConsoleAppenderTest extends AbstractAppenderTest { - - TeeOutputStream tee; - PrintStream original; - - - @Before - public void setUp() throws Exception { - original = System.out; - // tee will output bytes on System out but it will also - // collect them so that the output can be compared against - // some expected output data - // tee = new TeeOutputStream(original); - - // keep the console quiet - tee = new TeeOutputStream(null); - - // redirect System.out to tee - System.setOut(new PrintStream(tee)); - } - - @After - public void tearDown() throws Exception { - System.setOut(original); - } - - @Override - public Appender getAppender() { - return new ConsoleAppender(); - } - - protected Appender getConfiguredAppender() { - ConsoleAppender ca = new ConsoleAppender(); - ca.setLayout(new NopLayout()); - ca.start(); - return ca; - } - - @org.junit.Test - public void testBasic() { - ConsoleAppender ca = (ConsoleAppender) getAppender(); - ca.setLayout(new DummyLayout()); - ca.start(); - ca.doAppend(new Object()); - assertEquals(DummyLayout.DUMMY, tee.toString()); - } - - @org.junit.Test - public void testOpen() { - ConsoleAppender ca = (ConsoleAppender) getAppender(); - DummyLayout dummyLayout = new DummyLayout(); - dummyLayout.setFileHeader("open"); - ca.setLayout(dummyLayout); - ca.start(); - ca.doAppend(new Object()); - ca.stop(); - assertEquals("open"+CoreConstants.LINE_SEPARATOR+DummyLayout.DUMMY, tee.toString()); - } - - @Test - public void testClose() { - ConsoleAppender ca = (ConsoleAppender) getAppender(); - DummyLayout dummyLayout = new DummyLayout(); - dummyLayout.setFileFooter("CLOSED"); - ca.setLayout(dummyLayout); - ca.start(); - ca.doAppend(new Object()); - ca.stop(); - assertEquals(DummyLayout.DUMMY + "CLOSED", tee.toString()); - } - - - - @Test - public void testUTF16BE() throws UnsupportedEncodingException { - ConsoleAppender ca = (ConsoleAppender) getAppender(); - ca.setLayout(new DummyLayout()); - String encodingName = "UTF-16BE"; - ca.setEncoding(encodingName); - ca.start(); - ca.doAppend(new Object()); - - assertEquals(DummyLayout.DUMMY, new String(tee.toByteArray(), encodingName)); - } - - -} +/** + * 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.appender; + +import static org.junit.Assert.assertEquals; + +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.ConsoleAppender; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.layout.DummyLayout; +import ch.qos.logback.core.layout.NopLayout; +import ch.qos.logback.core.util.TeeOutputStream; + + +public class ConsoleAppenderTest extends AbstractAppenderTest { + + TeeOutputStream tee; + PrintStream original; + + + @Before + public void setUp() throws Exception { + original = System.out; + // tee will output bytes on System out but it will also + // collect them so that the output can be compared against + // some expected output data + // tee = new TeeOutputStream(original); + + // keep the console quiet + tee = new TeeOutputStream(null); + + // redirect System.out to tee + System.setOut(new PrintStream(tee)); + } + + @After + public void tearDown() throws Exception { + System.setOut(original); + } + + @Override + public Appender getAppender() { + return new ConsoleAppender(); + } + + protected Appender getConfiguredAppender() { + ConsoleAppender ca = new ConsoleAppender(); + ca.setLayout(new NopLayout()); + ca.start(); + return ca; + } + + @org.junit.Test + public void testBasic() { + ConsoleAppender ca = (ConsoleAppender) getAppender(); + ca.setLayout(new DummyLayout()); + ca.start(); + ca.doAppend(new Object()); + assertEquals(DummyLayout.DUMMY, tee.toString()); + } + + @org.junit.Test + public void testOpen() { + ConsoleAppender ca = (ConsoleAppender) getAppender(); + DummyLayout dummyLayout = new DummyLayout(); + dummyLayout.setFileHeader("open"); + ca.setLayout(dummyLayout); + ca.start(); + ca.doAppend(new Object()); + ca.stop(); + assertEquals("open"+CoreConstants.LINE_SEPARATOR+DummyLayout.DUMMY, tee.toString()); + } + + @Test + public void testClose() { + ConsoleAppender ca = (ConsoleAppender) getAppender(); + DummyLayout dummyLayout = new DummyLayout(); + dummyLayout.setFileFooter("CLOSED"); + ca.setLayout(dummyLayout); + ca.start(); + ca.doAppend(new Object()); + ca.stop(); + assertEquals(DummyLayout.DUMMY + "CLOSED", tee.toString()); + } + + + + @Test + public void testUTF16BE() throws UnsupportedEncodingException { + ConsoleAppender ca = (ConsoleAppender) getAppender(); + ca.setLayout(new DummyLayout()); + String encodingName = "UTF-16BE"; + ca.setEncoding(encodingName); + ca.start(); + ca.doAppend(new Object()); + + assertEquals(DummyLayout.DUMMY, new String(tee.toByteArray(), encodingName)); + } + + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/appender/DummyAppender.java b/logback-core/src/test/java/ch/qos/logback/core/appender/DummyAppender.java index 47b826fcb8c5ef79d1365c9f325c7f8f30851596..8e1d504db53f896ee93932c278705c708b9328b1 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/appender/DummyAppender.java +++ b/logback-core/src/test/java/ch/qos/logback/core/appender/DummyAppender.java @@ -1,26 +1,26 @@ -/** - * 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.appender; - -import java.io.Writer; - -import ch.qos.logback.core.WriterAppender; - -public class DummyAppender extends WriterAppender { - - DummyAppender(Writer writer) { - this.setWriter(writer); - } - -} +/** + * 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.appender; + +import java.io.Writer; + +import ch.qos.logback.core.WriterAppender; + +public class DummyAppender extends WriterAppender { + + DummyAppender(Writer writer) { + this.setWriter(writer); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/appender/DummyAppenderTest.java b/logback-core/src/test/java/ch/qos/logback/core/appender/DummyAppenderTest.java index f2ed5b7034ac57f695a977890e426f73fbaaf108..fafc4cfdf2addd10e12dc1d0b5e77a8dbca64243 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/appender/DummyAppenderTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/appender/DummyAppenderTest.java @@ -1,51 +1,51 @@ -/** - * 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.appender; - -import static org.junit.Assert.assertEquals; - -import java.io.StringWriter; - -import org.junit.Test; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.layout.DummyLayout; -import ch.qos.logback.core.layout.NopLayout; - - -public class DummyAppenderTest { - - - protected Appender getAppender() { - return new DummyAppender(new StringWriter()); - } - - protected Appender getConfiguredAppender() { - DummyAppender da = new DummyAppender(new StringWriter()); - da.setLayout(new NopLayout()); - da.start(); - return da; - } - - @Test - public void testBasic() { - StringWriter sw = new StringWriter(); - DummyAppender da = new DummyAppender(sw); - da.setLayout(new DummyLayout()); - da.start(); - da.doAppend(new Object()); - assertEquals(DummyLayout.DUMMY, sw.getBuffer().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.appender; + +import static org.junit.Assert.assertEquals; + +import java.io.StringWriter; + +import org.junit.Test; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.layout.DummyLayout; +import ch.qos.logback.core.layout.NopLayout; + + +public class DummyAppenderTest { + + + protected Appender getAppender() { + return new DummyAppender(new StringWriter()); + } + + protected Appender getConfiguredAppender() { + DummyAppender da = new DummyAppender(new StringWriter()); + da.setLayout(new NopLayout()); + da.start(); + return da; + } + + @Test + public void testBasic() { + StringWriter sw = new StringWriter(); + DummyAppender da = new DummyAppender(sw); + da.setLayout(new DummyLayout()); + da.start(); + da.doAppend(new Object()); + assertEquals(DummyLayout.DUMMY, sw.getBuffer().toString()); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/appender/FileAppenderTest.java b/logback-core/src/test/java/ch/qos/logback/core/appender/FileAppenderTest.java index 56e033bdd66304f4853c9ee86e9a0822ad785121..38ef9dd40fae61ad19ae020b6e25cf2b7c357028 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/appender/FileAppenderTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/appender/FileAppenderTest.java @@ -1,133 +1,133 @@ -/** - * 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.appender; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.util.List; -import java.util.Random; - -import org.junit.Test; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.FileAppender; -import ch.qos.logback.core.layout.DummyLayout; -import ch.qos.logback.core.layout.NopLayout; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.util.CoreTestConstants; -import ch.qos.logback.core.util.FileUtil; - -public class FileAppenderTest extends AbstractAppenderTest { - - int diff = new Random().nextInt(100); - Context context = new ContextBase(); - - protected Appender getAppender() { - return new FileAppender(); - } - - protected Appender getConfiguredAppender() { - FileAppender appender = new FileAppender(); - appender.setLayout(new NopLayout()); - appender.setFile(CoreTestConstants.OUTPUT_DIR_PREFIX+"temp.log"); - appender.setName("test"); - appender.setContext(context); - appender.start(); - return appender; - } - - @Test - public void smoke() { - String filename = CoreTestConstants.OUTPUT_DIR_PREFIX + "temp.log"; - - FileAppender appender = new FileAppender(); - appender.setLayout(new DummyLayout()); - appender.setAppend(false); - appender.setFile(filename); - appender.setName("smoke"); - appender.setContext(context); - appender.start(); - appender.doAppend(new Object()); - appender.stop(); - - File file = new File(filename); - assertTrue(file.exists()); - assertTrue("failed to delete " + file.getAbsolutePath(), file.delete()); - } - - @Test - public void testCreateParentFolders() { - String filename = CoreTestConstants.OUTPUT_DIR_PREFIX + "/fat" + diff - + "/testing.txt"; - File file = new File(filename); - FileAppender appender = new FileAppender(); - appender.setLayout(new DummyLayout()); - appender.setAppend(false); - appender.setFile(filename); - appender.setName("testCreateParentFolders"); - appender.setContext(context); - appender.start(); - appender.doAppend(new Object()); - appender.stop(); - assertFalse(FileUtil.mustCreateParentDirectories(file)); - assertTrue(file.exists()); - - // cleanup - assertTrue("failed to delete " + file.getAbsolutePath(), file.delete()); - File parent = file.getParentFile(); - assertTrue("failed to delete " + parent.getAbsolutePath(), parent.delete()); - } - - @Test - public void testPrudentModeLogicalImplications() { - String filename = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + "testing.txt"; - File file = new File(filename); - FileAppender appender = new FileAppender(); - appender.setLayout(new DummyLayout()); - appender.setFile(filename); - appender.setName("testPrudentMode"); - appender.setContext(context); - - appender.setAppend(false); - appender.setImmediateFlush(false); - appender.setBufferedIO(true); - appender.setPrudent(true); - appender.start(); - - assertTrue(appender.getImmediateFlush()); - assertTrue(appender.isAppend()); - assertFalse(appender.isBufferedIO()); - - StatusManager sm = context.getStatusManager(); - assertEquals(Status.WARN, sm.getLevel()); - List statusList = sm.getCopyOfStatusList(); - assertTrue("Expecting status list size to be larger than 3, but was " - + statusList.size(), statusList.size() > 3); - String msg1 = statusList.get(1).getMessage(); - - assertTrue("Got message [" + msg1 + "]", msg1 - .startsWith("Setting \"Append\" property")); - - appender.doAppend(new Object()); - appender.stop(); - assertTrue(file.exists()); - assertTrue("failed to delete " + file.getAbsolutePath(), file.delete()); - } -} +/** + * 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.appender; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.List; +import java.util.Random; + +import org.junit.Test; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.layout.DummyLayout; +import ch.qos.logback.core.layout.NopLayout; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.CoreTestConstants; +import ch.qos.logback.core.util.FileUtil; + +public class FileAppenderTest extends AbstractAppenderTest { + + int diff = new Random().nextInt(100); + Context context = new ContextBase(); + + protected Appender getAppender() { + return new FileAppender(); + } + + protected Appender getConfiguredAppender() { + FileAppender appender = new FileAppender(); + appender.setLayout(new NopLayout()); + appender.setFile(CoreTestConstants.OUTPUT_DIR_PREFIX+"temp.log"); + appender.setName("test"); + appender.setContext(context); + appender.start(); + return appender; + } + + @Test + public void smoke() { + String filename = CoreTestConstants.OUTPUT_DIR_PREFIX + "temp.log"; + + FileAppender appender = new FileAppender(); + appender.setLayout(new DummyLayout()); + appender.setAppend(false); + appender.setFile(filename); + appender.setName("smoke"); + appender.setContext(context); + appender.start(); + appender.doAppend(new Object()); + appender.stop(); + + File file = new File(filename); + assertTrue(file.exists()); + assertTrue("failed to delete " + file.getAbsolutePath(), file.delete()); + } + + @Test + public void testCreateParentFolders() { + String filename = CoreTestConstants.OUTPUT_DIR_PREFIX + "/fat" + diff + + "/testing.txt"; + File file = new File(filename); + FileAppender appender = new FileAppender(); + appender.setLayout(new DummyLayout()); + appender.setAppend(false); + appender.setFile(filename); + appender.setName("testCreateParentFolders"); + appender.setContext(context); + appender.start(); + appender.doAppend(new Object()); + appender.stop(); + assertFalse(FileUtil.mustCreateParentDirectories(file)); + assertTrue(file.exists()); + + // cleanup + assertTrue("failed to delete " + file.getAbsolutePath(), file.delete()); + File parent = file.getParentFile(); + assertTrue("failed to delete " + parent.getAbsolutePath(), parent.delete()); + } + + @Test + public void testPrudentModeLogicalImplications() { + String filename = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + "testing.txt"; + File file = new File(filename); + FileAppender appender = new FileAppender(); + appender.setLayout(new DummyLayout()); + appender.setFile(filename); + appender.setName("testPrudentMode"); + appender.setContext(context); + + appender.setAppend(false); + appender.setImmediateFlush(false); + appender.setBufferedIO(true); + appender.setPrudent(true); + appender.start(); + + assertTrue(appender.getImmediateFlush()); + assertTrue(appender.isAppend()); + assertFalse(appender.isBufferedIO()); + + StatusManager sm = context.getStatusManager(); + assertEquals(Status.WARN, sm.getLevel()); + List statusList = sm.getCopyOfStatusList(); + assertTrue("Expecting status list size to be larger than 3, but was " + + statusList.size(), statusList.size() > 3); + String msg1 = statusList.get(1).getMessage(); + + assertTrue("Got message [" + msg1 + "]", msg1 + .startsWith("Setting \"Append\" property")); + + appender.doAppend(new Object()); + appender.stop(); + assertTrue(file.exists()); + assertTrue("failed to delete " + file.getAbsolutePath(), file.delete()); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/appender/NOPAppender.java b/logback-core/src/test/java/ch/qos/logback/core/appender/NOPAppender.java index 13da929a64807a7169e6d2947be08ea34f7d49a4..52b40036eec90ff4ddd35f62b84483f93f0edcd1 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/appender/NOPAppender.java +++ b/logback-core/src/test/java/ch/qos/logback/core/appender/NOPAppender.java @@ -1,24 +1,24 @@ -/** - * 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.appender; - -import ch.qos.logback.core.AppenderBase; - -final public class NOPAppender extends AppenderBase { - - @Override - final protected void append(E eventObject) { - } -} +/** + * 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.appender; + +import ch.qos.logback.core.AppenderBase; + +final public class NOPAppender extends AppenderBase { + + @Override + final protected void append(E eventObject) { + } +} \ No newline at end of file diff --git a/logback-core/src/test/java/ch/qos/logback/core/appender/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/appender/PackageTest.java index 7f7993cc514637e17455c3d25181b5c2793059b5..b6618193d1e05cc3312fbc349ecc11e41401f2e5 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/appender/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/appender/PackageTest.java @@ -1,26 +1,26 @@ -/** - * 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.appender; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - - - -@RunWith(Suite.class) -@Suite.SuiteClasses( { DummyAppenderTest.class, ConsoleAppenderTest.class, - FileAppenderTest.class}) - -public class PackageTest { -} +/** + * 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.appender; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + + + +@RunWith(Suite.class) +@Suite.SuiteClasses( { DummyAppenderTest.class, ConsoleAppenderTest.class, + FileAppenderTest.class}) + +public class PackageTest { +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/boolex/MatcherTest.java b/logback-core/src/test/java/ch/qos/logback/core/boolex/MatcherTest.java index 196cfe2b9535875df6df48090e913b30a7e045fb..0028921aaa1388467aedee2356af9b14e56df525 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/boolex/MatcherTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/boolex/MatcherTest.java @@ -1,77 +1,77 @@ -/** - * 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.boolex; - -import junit.framework.TestCase; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; - -public class MatcherTest extends TestCase { - - Context context; - Matcher matcher; - - public void setUp() throws Exception { - context = new ContextBase(); - matcher = new Matcher(); - matcher.setContext(context); - matcher.setName("testMatcher"); - super.setUp(); - } - - public void tearDown() throws Exception { - matcher = null; - super.tearDown(); - } - - public void testFullRegion() throws Exception { - matcher.setRegex(".*test.*"); - matcher.start(); - assertTrue(matcher.matches("test")); - assertTrue(matcher.matches("xxxxtest")); - assertTrue(matcher.matches("testxxxx")); - assertTrue(matcher.matches("xxxxtestxxxx")); - } - - public void testPartRegion() throws Exception { - matcher.setRegex("test"); - matcher.start(); - assertTrue(matcher.matches("test")); - assertTrue(matcher.matches("xxxxtest")); - assertTrue(matcher.matches("testxxxx")); - assertTrue(matcher.matches("xxxxtestxxxx")); - } - - public void testCaseInsensitive() throws Exception { - matcher.setRegex("test"); - matcher.setCaseSensitive(false); - matcher.start(); - - assertTrue(matcher.matches("TEST")); - assertTrue(matcher.matches("tEst")); - assertTrue(matcher.matches("tESt")); - assertTrue(matcher.matches("TesT")); - } - - public void testCaseSensitive() throws Exception { - matcher.setRegex("test"); - matcher.setCaseSensitive(true); - matcher.start(); - - assertFalse(matcher.matches("TEST")); - assertFalse(matcher.matches("tEst")); - assertFalse(matcher.matches("tESt")); - assertFalse(matcher.matches("TesT")); - } -} +/** + * 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.boolex; + +import junit.framework.TestCase; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; + +public class MatcherTest extends TestCase { + + Context context; + Matcher matcher; + + public void setUp() throws Exception { + context = new ContextBase(); + matcher = new Matcher(); + matcher.setContext(context); + matcher.setName("testMatcher"); + super.setUp(); + } + + public void tearDown() throws Exception { + matcher = null; + super.tearDown(); + } + + public void testFullRegion() throws Exception { + matcher.setRegex(".*test.*"); + matcher.start(); + assertTrue(matcher.matches("test")); + assertTrue(matcher.matches("xxxxtest")); + assertTrue(matcher.matches("testxxxx")); + assertTrue(matcher.matches("xxxxtestxxxx")); + } + + public void testPartRegion() throws Exception { + matcher.setRegex("test"); + matcher.start(); + assertTrue(matcher.matches("test")); + assertTrue(matcher.matches("xxxxtest")); + assertTrue(matcher.matches("testxxxx")); + assertTrue(matcher.matches("xxxxtestxxxx")); + } + + public void testCaseInsensitive() throws Exception { + matcher.setRegex("test"); + matcher.setCaseSensitive(false); + matcher.start(); + + assertTrue(matcher.matches("TEST")); + assertTrue(matcher.matches("tEst")); + assertTrue(matcher.matches("tESt")); + assertTrue(matcher.matches("TesT")); + } + + public void testCaseSensitive() throws Exception { + matcher.setRegex("test"); + matcher.setCaseSensitive(true); + matcher.start(); + + assertFalse(matcher.matches("TEST")); + assertFalse(matcher.matches("tEst")); + assertFalse(matcher.matches("tESt")); + assertFalse(matcher.matches("TesT")); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/contention/MultiThreadedHarness.java b/logback-core/src/test/java/ch/qos/logback/core/contention/MultiThreadedHarness.java index 570446789c0604ab288c8937ddc9bf5a459cb328..8940b45960940d80bbee894ae965d871d8036665 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/contention/MultiThreadedHarness.java +++ b/logback-core/src/test/java/ch/qos/logback/core/contention/MultiThreadedHarness.java @@ -1,69 +1,69 @@ -/** - * 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.contention; - - -/** - * Useful scaffolding/harness to start and stop multiple threads. - * - * @author Joern Huxhorn - * @author Ralph Goers - * @author Ceki Gulcu - */ -public class MultiThreadedHarness { - - RunnableWithCounterAndDone[] runnableArray; - Thread[] threadArray; - final long overallDurationInMillis; - - public MultiThreadedHarness(long overallDurationInMillis) { - this.overallDurationInMillis = overallDurationInMillis; - } - - public void printEnvironmentInfo(String msg) { - System.out.println("=== " + msg + " ==="); - System.out.println("java.runtime.version = " - + System.getProperty("java.runtime.version")); - System.out.println("java.vendor = " - + System.getProperty("java.vendor")); - System.out.println("java.version = " - + System.getProperty("java.version")); - System.out.println("os.name = " - + System.getProperty("os.name")); - System.out.println("os.version = " - + System.getProperty("os.version")); - } - - public void execute(RunnableWithCounterAndDone[] runnableArray) - throws InterruptedException { - this.runnableArray = runnableArray; - Thread[] threadArray = new Thread[runnableArray.length]; - - for (int i = 0; i < runnableArray.length; i++) { - threadArray[i] = new Thread(runnableArray[i], "Harness["+i+"]"); - } - for (Thread t : threadArray) { - t.start(); - } - // let the threads run for a while - Thread.sleep(overallDurationInMillis); - - for (RunnableWithCounterAndDone r : runnableArray) { - r.setDone(true); - } - for (Thread t : threadArray) { - t.join(); - } - } -} +/** + * 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.contention; + + +/** + * Useful scaffolding/harness to start and stop multiple threads. + * + * @author Joern Huxhorn + * @author Ralph Goers + * @author Ceki Gulcu + */ +public class MultiThreadedHarness { + + RunnableWithCounterAndDone[] runnableArray; + Thread[] threadArray; + final long overallDurationInMillis; + + public MultiThreadedHarness(long overallDurationInMillis) { + this.overallDurationInMillis = overallDurationInMillis; + } + + public void printEnvironmentInfo(String msg) { + System.out.println("=== " + msg + " ==="); + System.out.println("java.runtime.version = " + + System.getProperty("java.runtime.version")); + System.out.println("java.vendor = " + + System.getProperty("java.vendor")); + System.out.println("java.version = " + + System.getProperty("java.version")); + System.out.println("os.name = " + + System.getProperty("os.name")); + System.out.println("os.version = " + + System.getProperty("os.version")); + } + + public void execute(RunnableWithCounterAndDone[] runnableArray) + throws InterruptedException { + this.runnableArray = runnableArray; + Thread[] threadArray = new Thread[runnableArray.length]; + + for (int i = 0; i < runnableArray.length; i++) { + threadArray[i] = new Thread(runnableArray[i], "Harness["+i+"]"); + } + for (Thread t : threadArray) { + t.start(); + } + // let the threads run for a while + Thread.sleep(overallDurationInMillis); + + for (RunnableWithCounterAndDone r : runnableArray) { + r.setDone(true); + } + for (Thread t : threadArray) { + t.join(); + } + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/contention/RunnableWithCounterAndDone.java b/logback-core/src/test/java/ch/qos/logback/core/contention/RunnableWithCounterAndDone.java index 8cffdb4aa912d31622fb03cf9e711c80d08fdbda..ffe0f3a38c82667999d280969b396703206394c6 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/contention/RunnableWithCounterAndDone.java +++ b/logback-core/src/test/java/ch/qos/logback/core/contention/RunnableWithCounterAndDone.java @@ -1,39 +1,39 @@ -/** - * 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.contention; - -/** - * A runnable with 'done' and 'counter' fields. - * - * @author ceki - * - */ -abstract public class RunnableWithCounterAndDone implements Runnable { - - protected boolean done = false; - protected long counter = 0; - - public long getCounter() { - return counter; - } - - public void setDone(boolean done) { - this.done = done; - } - - public boolean isDone() { - return done; - } - -} +/** + * 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.contention; + +/** + * A runnable with 'done' and 'counter' fields. + * + * @author ceki + * + */ +abstract public class RunnableWithCounterAndDone implements Runnable { + + protected boolean done = false; + protected long counter = 0; + + public long getCounter() { + return counter; + } + + public void setDone(boolean done) { + this.done = done; + } + + public boolean isDone() { + return done; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/contention/ThreadedThroughputCalculator.java b/logback-core/src/test/java/ch/qos/logback/core/contention/ThreadedThroughputCalculator.java index 32f0a89ee2abc5938bdea7e3fd744f3b3f718d65..63c009872e4a0a09b84cfdb75d418cc58ef1d5d7 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/contention/ThreadedThroughputCalculator.java +++ b/logback-core/src/test/java/ch/qos/logback/core/contention/ThreadedThroughputCalculator.java @@ -1,48 +1,48 @@ -/** - * 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.contention; - - -/** - * Useful scaffolding to measure the throughput of certain operations when - * invoked by multiple threads. - * - * @author Joern Huxhorn - * @author Ralph Goers - * @author Ceki Gulcu - */ -public class ThreadedThroughputCalculator extends MultiThreadedHarness { - - - public ThreadedThroughputCalculator(long overallDurationInMillis) { - super(overallDurationInMillis); - } - - public void printThroughput(String msg) throws InterruptedException { - printThroughput(msg, false); - } - - public void printThroughput(String msg, boolean detailed) throws InterruptedException { - long sum = 0; - for (RunnableWithCounterAndDone r : runnableArray) { - if(detailed) { - System.out.println(r +" count="+r.getCounter()); - } - sum += r.getCounter(); - } - - System.out.println(msg + "total of " + sum + " operations, or " - + ((sum) / overallDurationInMillis) + " operations per millisecond"); - } -} +/** + * 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.contention; + + +/** + * Useful scaffolding to measure the throughput of certain operations when + * invoked by multiple threads. + * + * @author Joern Huxhorn + * @author Ralph Goers + * @author Ceki Gulcu + */ +public class ThreadedThroughputCalculator extends MultiThreadedHarness { + + + public ThreadedThroughputCalculator(long overallDurationInMillis) { + super(overallDurationInMillis); + } + + public void printThroughput(String msg) throws InterruptedException { + printThroughput(msg, false); + } + + public void printThroughput(String msg, boolean detailed) throws InterruptedException { + long sum = 0; + for (RunnableWithCounterAndDone r : runnableArray) { + if(detailed) { + System.out.println(r +" count="+r.getCounter()); + } + sum += r.getCounter(); + } + + System.out.println(msg + "total of " + sum + " operations, or " + + ((sum) / overallDurationInMillis) + " operations per millisecond"); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/helpers/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/helpers/PackageTest.java index 03dc681c8da83b1165229867109643459a288cda..f840c787ad1865c54c1463b15f0fc14ae33c1dab 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/helpers/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/helpers/PackageTest.java @@ -1,24 +1,24 @@ -/** - * 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.helpers; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({ThrowableToStringArrayTest.class}) -public class PackageTest { - -} +/** + * 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.helpers; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ThrowableToStringArrayTest.class}) +public class PackageTest { + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/helpers/ThrowableToStringArrayTest.java b/logback-core/src/test/java/ch/qos/logback/core/helpers/ThrowableToStringArrayTest.java index 12a4790ae6a30a83a5965f2c62bd445e164e3a00..05b5d18bf6163d01a0a80708787daccf1d46bd1e 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/helpers/ThrowableToStringArrayTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/helpers/ThrowableToStringArrayTest.java @@ -1,93 +1,93 @@ -/** - * 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.helpers; - -import static org.junit.Assert.assertEquals; - -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.CoreConstants; - -public class ThrowableToStringArrayTest { - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - public void verify(Throwable t) { - t.printStackTrace(pw); - - String[] sa = ThrowableToStringArray.convert(t); - StringBuilder sb = new StringBuilder(); - for (String tdp : sa) { - sb.append(tdp.toString()); - sb.append(CoreConstants.LINE_SEPARATOR); - } - String expected = sw.toString(); - String result = sb.toString().replace("common frames omitted", "more"); - assertEquals(expected, result); - } - - @Test - public void smoke() { - Exception e = new Exception("smoke"); - verify(e); - } - - @Test - public void nested() { - Exception w = null; - try { - someMethod(); - } catch (Exception e) { - w = new Exception("wrapping", e); - } - verify(w); - } - - @Test - public void multiNested() { - Exception w = null; - try { - someOtherMethod(); - } catch (Exception e) { - w = new Exception("wrapping", e); - } - verify(w); - } - - void someMethod() throws Exception { - throw new Exception("someMethod"); - } - - void someOtherMethod() throws Exception { - try { - someMethod(); - } catch (Exception e) { - throw new Exception("someOtherMethod", e); - } - } -} +/** + * 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.helpers; + +import static org.junit.Assert.assertEquals; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.CoreConstants; + +public class ThrowableToStringArrayTest { + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + public void verify(Throwable t) { + t.printStackTrace(pw); + + String[] sa = ThrowableToStringArray.convert(t); + StringBuilder sb = new StringBuilder(); + for (String tdp : sa) { + sb.append(tdp.toString()); + sb.append(CoreConstants.LINE_SEPARATOR); + } + String expected = sw.toString(); + String result = sb.toString().replace("common frames omitted", "more"); + assertEquals(expected, result); + } + + @Test + public void smoke() { + Exception e = new Exception("smoke"); + verify(e); + } + + @Test + public void nested() { + Exception w = null; + try { + someMethod(); + } catch (Exception e) { + w = new Exception("wrapping", e); + } + verify(w); + } + + @Test + public void multiNested() { + Exception w = null; + try { + someOtherMethod(); + } catch (Exception e) { + w = new Exception("wrapping", e); + } + verify(w); + } + + void someMethod() throws Exception { + throw new Exception("someMethod"); + } + + void someOtherMethod() throws Exception { + try { + someMethod(); + } catch (Exception e) { + throw new Exception("someOtherMethod", e); + } + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/issue/LBCORE97.java b/logback-core/src/test/java/ch/qos/logback/core/issue/LBCORE97.java index 12ebb7b319e0bfcd622ee806e05e1a852902f4ed..af4533d6e77dbdcb910d791ef5d8276f7880fdae 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/issue/LBCORE97.java +++ b/logback-core/src/test/java/ch/qos/logback/core/issue/LBCORE97.java @@ -1,191 +1,191 @@ -/** - * 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.issue; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Example code illustrating locking policies in the JDK. - * See http://jira.qos.ch/browse/LBCORE-97 for a discussion. - * - * @author Joern Huxhorn - */ -public class LBCORE97 { - - static int THREAD_COUNT = 10; - - public static void main(String args[]) throws InterruptedException { - - System.out.println("Environment:"); - System.out.println("java.runtime.name = " - + System.getProperty("java.runtime.name")); - System.out.println("java.runtime.version = " - + System.getProperty("java.runtime.version")); - System.out.println("java.vendor = " - + System.getProperty("java.vendor")); - System.out.println("java.version = " - + System.getProperty("java.version")); - System.out.println("java.vm.name = " - + System.getProperty("java.vm.name")); - System.out.println("java.vm.info = " - + System.getProperty("java.vm.info")); - - System.out.println("os.name = " - + System.getProperty("os.name")); - System.out.println("os.version = " - + System.getProperty("os.version")); - System.out.println("os.arch = " - + System.getProperty("os.arch")); - System.out.println("##########################################"); - - usingSynchronized(THREAD_COUNT); - usingUnfairLock(THREAD_COUNT); - usingFairLock(THREAD_COUNT); - } - - public static void execute(String text, Thread[] threads) - throws InterruptedException { - System.out.println("About to execute " + text + "..."); - int threadCount = threads.length; - for (int i = 0; i < threadCount; i++) { - threads[i].start(); - } - - Thread.sleep(10000); - - for (int i = 0; i < threadCount; i++) { - threads[i].interrupt(); - } - Thread.sleep(1000); // wait a moment for termination, to lazy for join ;) - } - - public static void print(String text, Runnable[] runnables) { - System.out.println("Results for " + text + ":"); - for (int i = 0; i < runnables.length; i++) { - System.out.println("runnables[" + i + "]: " + runnables[i]); - } - System.out.println("##########################################"); - } - - public static void usingSynchronized(int threadCount) - throws InterruptedException { - Object lockObject = new Object(); - Runnable[] runnables = new Runnable[threadCount]; - Thread[] threads = new Thread[threadCount]; - - for (int i = 0; i < threadCount; i++) { - runnables[i] = new SynchronizedRunnable(lockObject); - threads[i] = new Thread(runnables[i]); - } - String text = "usingSynchronized"; - execute(text, threads); - print(text, runnables); - } - - public static void usingUnfairLock(int threadCount) - throws InterruptedException { - Lock lock = new ReentrantLock(); - Runnable[] runnables = new Runnable[threadCount]; - Thread[] threads = new Thread[threadCount]; - - for (int i = 0; i < threadCount; i++) { - runnables[i] = new LockRunnable(lock); - threads[i] = new Thread(runnables[i]); - } - - String text = "usingUnfairLock"; - execute(text, threads); - print(text, runnables); - } - - public static void usingFairLock(int threadCount) throws InterruptedException { - Lock lock = new ReentrantLock(true); - Runnable[] runnables = new Runnable[threadCount]; - Thread[] threads = new Thread[threadCount]; - - for (int i = 0; i < threadCount; i++) { - runnables[i] = new LockRunnable(lock); - threads[i] = new Thread(runnables[i]); - } - - String text = "usingFairLock"; - execute(text, threads); - print(text, runnables); - } - - public static class SynchronizedRunnable implements Runnable { - private final Object lockObject; - private int counter; - private boolean running; - - public SynchronizedRunnable(Object lockObject) { - this.lockObject = lockObject; - this.counter = 0; - this.running = false; - } - - public void run() { - running = true; - for (;;) { - synchronized (lockObject) { - counter++; - try { - Thread.sleep(10); - } catch (InterruptedException ex) { - break; - } - } - } - running = false; - } - - public String toString() { - return "SynchronizedRunnable[counter=" + counter + ", running=" + running - + "]"; - } - } - - public static class LockRunnable implements Runnable { - private final Lock lock; - private int counter; - private boolean running; - - public LockRunnable(Lock lock) { - this.lock = lock; - this.counter = 0; - this.running = false; - } - - public void run() { - running = true; - for (;;) { - lock.lock(); - try { - counter++; - Thread.sleep(10); - } catch (InterruptedException ex) { - break; - } finally { - lock.unlock(); - } - } - running = false; - } - - public String toString() { - return "LockRunnable[counter=" + counter + ", running=" + running + "]"; - } - } -} +/** + * 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.issue; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Example code illustrating locking policies in the JDK. + * See http://jira.qos.ch/browse/LBCORE-97 for a discussion. + * + * @author Joern Huxhorn + */ +public class LBCORE97 { + + static int THREAD_COUNT = 10; + + public static void main(String args[]) throws InterruptedException { + + System.out.println("Environment:"); + System.out.println("java.runtime.name = " + + System.getProperty("java.runtime.name")); + System.out.println("java.runtime.version = " + + System.getProperty("java.runtime.version")); + System.out.println("java.vendor = " + + System.getProperty("java.vendor")); + System.out.println("java.version = " + + System.getProperty("java.version")); + System.out.println("java.vm.name = " + + System.getProperty("java.vm.name")); + System.out.println("java.vm.info = " + + System.getProperty("java.vm.info")); + + System.out.println("os.name = " + + System.getProperty("os.name")); + System.out.println("os.version = " + + System.getProperty("os.version")); + System.out.println("os.arch = " + + System.getProperty("os.arch")); + System.out.println("##########################################"); + + usingSynchronized(THREAD_COUNT); + usingUnfairLock(THREAD_COUNT); + usingFairLock(THREAD_COUNT); + } + + public static void execute(String text, Thread[] threads) + throws InterruptedException { + System.out.println("About to execute " + text + "..."); + int threadCount = threads.length; + for (int i = 0; i < threadCount; i++) { + threads[i].start(); + } + + Thread.sleep(10000); + + for (int i = 0; i < threadCount; i++) { + threads[i].interrupt(); + } + Thread.sleep(1000); // wait a moment for termination, to lazy for join ;) + } + + public static void print(String text, Runnable[] runnables) { + System.out.println("Results for " + text + ":"); + for (int i = 0; i < runnables.length; i++) { + System.out.println("runnables[" + i + "]: " + runnables[i]); + } + System.out.println("##########################################"); + } + + public static void usingSynchronized(int threadCount) + throws InterruptedException { + Object lockObject = new Object(); + Runnable[] runnables = new Runnable[threadCount]; + Thread[] threads = new Thread[threadCount]; + + for (int i = 0; i < threadCount; i++) { + runnables[i] = new SynchronizedRunnable(lockObject); + threads[i] = new Thread(runnables[i]); + } + String text = "usingSynchronized"; + execute(text, threads); + print(text, runnables); + } + + public static void usingUnfairLock(int threadCount) + throws InterruptedException { + Lock lock = new ReentrantLock(); + Runnable[] runnables = new Runnable[threadCount]; + Thread[] threads = new Thread[threadCount]; + + for (int i = 0; i < threadCount; i++) { + runnables[i] = new LockRunnable(lock); + threads[i] = new Thread(runnables[i]); + } + + String text = "usingUnfairLock"; + execute(text, threads); + print(text, runnables); + } + + public static void usingFairLock(int threadCount) throws InterruptedException { + Lock lock = new ReentrantLock(true); + Runnable[] runnables = new Runnable[threadCount]; + Thread[] threads = new Thread[threadCount]; + + for (int i = 0; i < threadCount; i++) { + runnables[i] = new LockRunnable(lock); + threads[i] = new Thread(runnables[i]); + } + + String text = "usingFairLock"; + execute(text, threads); + print(text, runnables); + } + + public static class SynchronizedRunnable implements Runnable { + private final Object lockObject; + private int counter; + private boolean running; + + public SynchronizedRunnable(Object lockObject) { + this.lockObject = lockObject; + this.counter = 0; + this.running = false; + } + + public void run() { + running = true; + for (;;) { + synchronized (lockObject) { + counter++; + try { + Thread.sleep(10); + } catch (InterruptedException ex) { + break; + } + } + } + running = false; + } + + public String toString() { + return "SynchronizedRunnable[counter=" + counter + ", running=" + running + + "]"; + } + } + + public static class LockRunnable implements Runnable { + private final Lock lock; + private int counter; + private boolean running; + + public LockRunnable(Lock lock) { + this.lock = lock; + this.counter = 0; + this.running = false; + } + + public void run() { + running = true; + for (;;) { + lock.lock(); + try { + counter++; + Thread.sleep(10); + } catch (InterruptedException ex) { + break; + } finally { + lock.unlock(); + } + } + running = false; + } + + public String toString() { + return "LockRunnable[counter=" + counter + ", running=" + running + "]"; + } + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/issue/LockThroughput.java b/logback-core/src/test/java/ch/qos/logback/core/issue/LockThroughput.java index 444f7b7fa5b305422f9cb78a14751190c71ad357..e9cc60546564d46b2b941d7cc6094dd80101f0fd 100755 --- a/logback-core/src/test/java/ch/qos/logback/core/issue/LockThroughput.java +++ b/logback-core/src/test/java/ch/qos/logback/core/issue/LockThroughput.java @@ -1,60 +1,60 @@ -/** - * 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.issue; - -import ch.qos.logback.core.contention.ThreadedThroughputCalculator; -import ch.qos.logback.core.issue.SelectiveLockRunnable.LockingModel; - -/** - * Short sample code testing the throughput of a fair lock. - * - * @author Joern Huxhorn - * @author Ceki Gulcu - */ -public class LockThroughput { - - static int THREAD_COUNT = 10; - static long OVERALL_DURATION_IN_MILLIS = 5000; - - public static void main(String args[]) throws InterruptedException { - - ThreadedThroughputCalculator tp = new ThreadedThroughputCalculator( - OVERALL_DURATION_IN_MILLIS); - tp.printEnvironmentInfo("LockThroughput"); - - for (int i = 0; i < 2; i++) { - tp.execute(buildArray(LockingModel.SYNC)); - tp.execute(buildArray(LockingModel.UNFAIR)); - tp.execute(buildArray(LockingModel.FAIR)); - } - - tp.execute(buildArray(LockingModel.SYNC)); - tp.printThroughput("Sync: "); - - tp.execute(buildArray(LockingModel.UNFAIR)); - tp.printThroughput("Unfair: "); - - tp.execute(buildArray(LockingModel.FAIR)); - tp.printThroughput("Fair: "); - } - - static SelectiveLockRunnable[] buildArray(LockingModel model) { - SelectiveLockRunnable[] array = new SelectiveLockRunnable[THREAD_COUNT]; - for (int i = 0; i < THREAD_COUNT; i++) { - array[i] = new SelectiveLockRunnable(model); - } - return array; - } - -} +/** + * 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.issue; + +import ch.qos.logback.core.contention.ThreadedThroughputCalculator; +import ch.qos.logback.core.issue.SelectiveLockRunnable.LockingModel; + +/** + * Short sample code testing the throughput of a fair lock. + * + * @author Joern Huxhorn + * @author Ceki Gulcu + */ +public class LockThroughput { + + static int THREAD_COUNT = 10; + static long OVERALL_DURATION_IN_MILLIS = 5000; + + public static void main(String args[]) throws InterruptedException { + + ThreadedThroughputCalculator tp = new ThreadedThroughputCalculator( + OVERALL_DURATION_IN_MILLIS); + tp.printEnvironmentInfo("LockThroughput"); + + for (int i = 0; i < 2; i++) { + tp.execute(buildArray(LockingModel.SYNC)); + tp.execute(buildArray(LockingModel.UNFAIR)); + tp.execute(buildArray(LockingModel.FAIR)); + } + + tp.execute(buildArray(LockingModel.SYNC)); + tp.printThroughput("Sync: "); + + tp.execute(buildArray(LockingModel.UNFAIR)); + tp.printThroughput("Unfair: "); + + tp.execute(buildArray(LockingModel.FAIR)); + tp.printThroughput("Fair: "); + } + + static SelectiveLockRunnable[] buildArray(LockingModel model) { + SelectiveLockRunnable[] array = new SelectiveLockRunnable[THREAD_COUNT]; + for (int i = 0; i < THREAD_COUNT; i++) { + array[i] = new SelectiveLockRunnable(model); + } + return array; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/issue/LockingInJava.java b/logback-core/src/test/java/ch/qos/logback/core/issue/LockingInJava.java index 8b4f60c9ae96c352c5d8e028108c97672ad9a43c..5356b4589aed7dedcbfb7bbba806af08472407c9 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/issue/LockingInJava.java +++ b/logback-core/src/test/java/ch/qos/logback/core/issue/LockingInJava.java @@ -1,94 +1,94 @@ -/** - * 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.issue; - -/** - * Short sample code illustrating locking policies in the JDK. See - * http://jira.qos.ch/browse/LBCORE-97 for a discussion. - * - * @author Joern Huxhorn - * @author Ceki Gulcu - */ -public class LockingInJava implements Runnable { - - static int THREAD_COUNT = 5; - static Object LOCK = new Object(); - static LockingInJava[] RUNNABLE_ARRAY = new LockingInJava[THREAD_COUNT]; - static Thread[] THREAD_ARRAY = new Thread[THREAD_COUNT]; - - private int counter = 0; - private boolean done = false; - - public static void main(String args[]) throws InterruptedException { - printEnvironmentInfo(); - execute(); - printResults(); - } - - public static void printEnvironmentInfo() { - System.out.println("java.runtime.version = " - + System.getProperty("java.runtime.version")); - System.out.println("java.vendor = " - + System.getProperty("java.vendor")); - System.out.println("java.version = " - + System.getProperty("java.version")); - System.out.println("os.name = " - + System.getProperty("os.name")); - System.out.println("os.version = " - + System.getProperty("os.version")); - } - - public static void execute() throws InterruptedException { - for (int i = 0; i < THREAD_COUNT; i++) { - RUNNABLE_ARRAY[i] = new LockingInJava(); - THREAD_ARRAY[i] = new Thread(RUNNABLE_ARRAY[i]); - } - for (Thread t : THREAD_ARRAY) { - t.start(); - } - // let the threads run for a while - Thread.sleep(10000); - - for (int i = THREAD_COUNT - 1; i <= 0; i--) { - RUNNABLE_ARRAY[i].done = true; - } - - } - - public static void printResults() { - for (int i = 0; i < RUNNABLE_ARRAY.length; i++) { - System.out.println("runnable[" + i + "]: " + RUNNABLE_ARRAY[i]); - } - } - - public void run() { - for (;;) { - synchronized (LOCK) { - counter++; - try { - Thread.sleep(10); - } catch (InterruptedException ex) { - } - if(done) { - return; - } - } - } - } - - public String toString() { - return "counter=" + counter; - } - -} +/** + * 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.issue; + +/** + * Short sample code illustrating locking policies in the JDK. See + * http://jira.qos.ch/browse/LBCORE-97 for a discussion. + * + * @author Joern Huxhorn + * @author Ceki Gulcu + */ +public class LockingInJava implements Runnable { + + static int THREAD_COUNT = 5; + static Object LOCK = new Object(); + static LockingInJava[] RUNNABLE_ARRAY = new LockingInJava[THREAD_COUNT]; + static Thread[] THREAD_ARRAY = new Thread[THREAD_COUNT]; + + private int counter = 0; + private boolean done = false; + + public static void main(String args[]) throws InterruptedException { + printEnvironmentInfo(); + execute(); + printResults(); + } + + public static void printEnvironmentInfo() { + System.out.println("java.runtime.version = " + + System.getProperty("java.runtime.version")); + System.out.println("java.vendor = " + + System.getProperty("java.vendor")); + System.out.println("java.version = " + + System.getProperty("java.version")); + System.out.println("os.name = " + + System.getProperty("os.name")); + System.out.println("os.version = " + + System.getProperty("os.version")); + } + + public static void execute() throws InterruptedException { + for (int i = 0; i < THREAD_COUNT; i++) { + RUNNABLE_ARRAY[i] = new LockingInJava(); + THREAD_ARRAY[i] = new Thread(RUNNABLE_ARRAY[i]); + } + for (Thread t : THREAD_ARRAY) { + t.start(); + } + // let the threads run for a while + Thread.sleep(10000); + + for (int i = THREAD_COUNT - 1; i <= 0; i--) { + RUNNABLE_ARRAY[i].done = true; + } + + } + + public static void printResults() { + for (int i = 0; i < RUNNABLE_ARRAY.length; i++) { + System.out.println("runnable[" + i + "]: " + RUNNABLE_ARRAY[i]); + } + } + + public void run() { + for (;;) { + synchronized (LOCK) { + counter++; + try { + Thread.sleep(10); + } catch (InterruptedException ex) { + } + if(done) { + return; + } + } + } + } + + public String toString() { + return "counter=" + counter; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockThroughput.java b/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockThroughput.java index 0a59dc11c1fc93e84f7bb6a3efa714b008499e8c..d7278e3d6114ce92a190d0b0d5fcb0a631d1b085 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockThroughput.java +++ b/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockThroughput.java @@ -1,52 +1,52 @@ -/** - * 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.issue; - -import ch.qos.logback.core.contention.ThreadedThroughputCalculator; -import ch.qos.logback.core.issue.SelectiveLockRunnable.LockingModel; - -/** - * Short sample code testing the throughput of a fair lock. - * - * @author Joern Huxhorn - * @author Ceki Gulcu - */ -public class NoLockThroughput { - - static int THREAD_COUNT = 3; - static long OVERALL_DURATION_IN_MILLIS = 2000; - - public static void main(String args[]) throws InterruptedException { - - ThreadedThroughputCalculator tp = new ThreadedThroughputCalculator( - OVERALL_DURATION_IN_MILLIS); - tp.printEnvironmentInfo("NoLockThroughput"); - - for (int i = 0; i < 2; i++) { - tp.execute(buildArray(LockingModel.NOLOCK)); - } - - tp.execute(buildArray(LockingModel.NOLOCK)); - tp.printThroughput("No lock: ", true); - } - - static SelectiveLockRunnable[] buildArray(LockingModel model) { - SelectiveLockRunnable[] array = new SelectiveLockRunnable[THREAD_COUNT]; - for (int i = 0; i < THREAD_COUNT; i++) { - array[i] = new SelectiveLockRunnable(model); - } - return array; - } - -} +/** + * 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.issue; + +import ch.qos.logback.core.contention.ThreadedThroughputCalculator; +import ch.qos.logback.core.issue.SelectiveLockRunnable.LockingModel; + +/** + * Short sample code testing the throughput of a fair lock. + * + * @author Joern Huxhorn + * @author Ceki Gulcu + */ +public class NoLockThroughput { + + static int THREAD_COUNT = 3; + static long OVERALL_DURATION_IN_MILLIS = 2000; + + public static void main(String args[]) throws InterruptedException { + + ThreadedThroughputCalculator tp = new ThreadedThroughputCalculator( + OVERALL_DURATION_IN_MILLIS); + tp.printEnvironmentInfo("NoLockThroughput"); + + for (int i = 0; i < 2; i++) { + tp.execute(buildArray(LockingModel.NOLOCK)); + } + + tp.execute(buildArray(LockingModel.NOLOCK)); + tp.printThroughput("No lock: ", true); + } + + static SelectiveLockRunnable[] buildArray(LockingModel model) { + SelectiveLockRunnable[] array = new SelectiveLockRunnable[THREAD_COUNT]; + for (int i = 0; i < THREAD_COUNT; i++) { + array[i] = new SelectiveLockRunnable(model); + } + return array; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockingInJava.java b/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockingInJava.java index 57c4538982020e60bc1bc30ce49e83c1402257d6..94482196a4b7def57abebc95ed79ecca6db8c02f 100755 --- a/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockingInJava.java +++ b/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockingInJava.java @@ -1,87 +1,87 @@ -/** - * 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.issue; - -/** - * Measure throughput without any locking policy - * - * @author Joern Huxhorn - * @author Ceki Gulcu - */ -public class NoLockingInJava implements Runnable { - - static int THREAD_COUNT = 5; - static Object LOCK = new Object(); - static NoLockingInJava[] RUNNABLE_ARRAY = new NoLockingInJava[THREAD_COUNT]; - static Thread[] THREAD_ARRAY = new Thread[THREAD_COUNT]; - - private int counter = 0; - private boolean done = false; - - public static void main(String args[]) throws InterruptedException { - printEnvironmentInfo(); - execute(); - printResults(); - } - - public static void printEnvironmentInfo() { - System.out.println("java.runtime.version = " - + System.getProperty("java.runtime.version")); - System.out.println("java.vendor = " - + System.getProperty("java.vendor")); - System.out.println("java.version = " - + System.getProperty("java.version")); - System.out.println("os.name = " - + System.getProperty("os.name")); - System.out.println("os.version = " - + System.getProperty("os.version")); - } - - public static void execute() throws InterruptedException { - for (int i = 0; i < THREAD_COUNT; i++) { - RUNNABLE_ARRAY[i] = new NoLockingInJava(); - THREAD_ARRAY[i] = new Thread(RUNNABLE_ARRAY[i]); - } - for (Thread t : THREAD_ARRAY) { - t.start(); - } - // let the threads run for a while - Thread.sleep(10000); - - for (int i = THREAD_COUNT - 1; i <= 0; i--) { - RUNNABLE_ARRAY[i].done = true; - } - - } - - public static void printResults() { - for (int i = 0; i < RUNNABLE_ARRAY.length; i++) { - System.out.println("runnable[" + i + "]: " + RUNNABLE_ARRAY[i]); - } - } - - public void run() { - for (;;) { - counter++; - if (done) { - return; - } - } - } - - public String toString() { - return "counter=" + counter; - } - -} +/** + * 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.issue; + +/** + * Measure throughput without any locking policy + * + * @author Joern Huxhorn + * @author Ceki Gulcu + */ +public class NoLockingInJava implements Runnable { + + static int THREAD_COUNT = 5; + static Object LOCK = new Object(); + static NoLockingInJava[] RUNNABLE_ARRAY = new NoLockingInJava[THREAD_COUNT]; + static Thread[] THREAD_ARRAY = new Thread[THREAD_COUNT]; + + private int counter = 0; + private boolean done = false; + + public static void main(String args[]) throws InterruptedException { + printEnvironmentInfo(); + execute(); + printResults(); + } + + public static void printEnvironmentInfo() { + System.out.println("java.runtime.version = " + + System.getProperty("java.runtime.version")); + System.out.println("java.vendor = " + + System.getProperty("java.vendor")); + System.out.println("java.version = " + + System.getProperty("java.version")); + System.out.println("os.name = " + + System.getProperty("os.name")); + System.out.println("os.version = " + + System.getProperty("os.version")); + } + + public static void execute() throws InterruptedException { + for (int i = 0; i < THREAD_COUNT; i++) { + RUNNABLE_ARRAY[i] = new NoLockingInJava(); + THREAD_ARRAY[i] = new Thread(RUNNABLE_ARRAY[i]); + } + for (Thread t : THREAD_ARRAY) { + t.start(); + } + // let the threads run for a while + Thread.sleep(10000); + + for (int i = THREAD_COUNT - 1; i <= 0; i--) { + RUNNABLE_ARRAY[i].done = true; + } + + } + + public static void printResults() { + for (int i = 0; i < RUNNABLE_ARRAY.length; i++) { + System.out.println("runnable[" + i + "]: " + RUNNABLE_ARRAY[i]); + } + } + + public void run() { + for (;;) { + counter++; + if (done) { + return; + } + } + } + + public String toString() { + return "counter=" + counter; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/issue/SelectiveLockRunnable.java b/logback-core/src/test/java/ch/qos/logback/core/issue/SelectiveLockRunnable.java index 56575caae9c0d4e2f5d951352ba0aba6d4d53313..bf7d946972edec668abfc4932ead59a1ab923dfb 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/issue/SelectiveLockRunnable.java +++ b/logback-core/src/test/java/ch/qos/logback/core/issue/SelectiveLockRunnable.java @@ -1,106 +1,106 @@ -/** - * 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.issue; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; - -/** - * A runnable which behaves differently depending on the desired locking model. - * - * @author Joern Huxhorn - * @author Ceki Gulcu - */ -public class SelectiveLockRunnable extends RunnableWithCounterAndDone { - - enum LockingModel { - NOLOCK, SYNC, FAIR, UNFAIR; - } - - static Object LOCK = new Object(); - static Lock FAIR_LOCK = new ReentrantLock(true); - static Lock UNFAIR_LOCK = new ReentrantLock(false); - - LockingModel model; - - SelectiveLockRunnable(LockingModel model) { - this.model = model; - } - - public void run() { - switch (model) { - case NOLOCK: - nolockRun(); - break; - case SYNC: - synchronizedRun(); - break; - case FAIR: - fairLockRun(); - break; - case UNFAIR: - unfairLockRun(); - break; - } - } - - void fairLockRun() { - for (;;) { - FAIR_LOCK.lock(); - counter++; - FAIR_LOCK.unlock(); - if (done) { - return; - } - } - } - - void unfairLockRun() { - for (;;) { - UNFAIR_LOCK.lock(); - counter++; - UNFAIR_LOCK.unlock(); - if (done) { - return; - } - } - } - - void nolockRun() { - for (;;) { - counter++; - if (done) { - return; - } - } - } - - void synchronizedRun() { - for (;;) { - synchronized (LOCK) { - counter++; - } - if (done) { - return; - } - } - } - - @Override - public String toString() { - return "SelectiveLockRunnable "+model; - } -} +/** + * 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.issue; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import ch.qos.logback.core.contention.RunnableWithCounterAndDone; + +/** + * A runnable which behaves differently depending on the desired locking model. + * + * @author Joern Huxhorn + * @author Ceki Gulcu + */ +public class SelectiveLockRunnable extends RunnableWithCounterAndDone { + + enum LockingModel { + NOLOCK, SYNC, FAIR, UNFAIR; + } + + static Object LOCK = new Object(); + static Lock FAIR_LOCK = new ReentrantLock(true); + static Lock UNFAIR_LOCK = new ReentrantLock(false); + + LockingModel model; + + SelectiveLockRunnable(LockingModel model) { + this.model = model; + } + + public void run() { + switch (model) { + case NOLOCK: + nolockRun(); + break; + case SYNC: + synchronizedRun(); + break; + case FAIR: + fairLockRun(); + break; + case UNFAIR: + unfairLockRun(); + break; + } + } + + void fairLockRun() { + for (;;) { + FAIR_LOCK.lock(); + counter++; + FAIR_LOCK.unlock(); + if (done) { + return; + } + } + } + + void unfairLockRun() { + for (;;) { + UNFAIR_LOCK.lock(); + counter++; + UNFAIR_LOCK.unlock(); + if (done) { + return; + } + } + } + + void nolockRun() { + for (;;) { + counter++; + if (done) { + return; + } + } + } + + void synchronizedRun() { + for (;;) { + synchronized (LOCK) { + counter++; + } + if (done) { + return; + } + } + } + + @Override + public String toString() { + return "SelectiveLockRunnable "+model; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/PackageTest.java index 0de461356d844a96f2113bc91f95073778bb3cd6..a4d00d5c6c605b8ca3864ac844c7806b725bfa11 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/PackageTest.java @@ -1,29 +1,29 @@ -/** - * 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.joran; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({SkippingInInterpreterTest.class, TrivialConfiguratorTest.class, ch.qos.logback.core.joran.action.PackageTest.class, - ch.qos.logback.core.joran.event.PackageTest.class, - ch.qos.logback.core.joran.spi.PackageTest.class, - ch.qos.logback.core.joran.replay.PackageTest.class, - ch.qos.logback.core.joran.implicitAction.PackageTest.class - }) -public class PackageTest { - -} +/** + * 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.joran; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({SkippingInInterpreterTest.class, TrivialConfiguratorTest.class, ch.qos.logback.core.joran.action.PackageTest.class, + ch.qos.logback.core.joran.event.PackageTest.class, + ch.qos.logback.core.joran.spi.PackageTest.class, + ch.qos.logback.core.joran.replay.PackageTest.class, + ch.qos.logback.core.joran.implicitAction.PackageTest.class + }) +public class PackageTest { + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/SimpleConfigurator.java b/logback-core/src/test/java/ch/qos/logback/core/joran/SimpleConfigurator.java index 6ecfbc228d69f4b3016212c71d277cc10f65ad46..e551646edf50df285dafe4ad9a35c85801e55eb8 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/SimpleConfigurator.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/SimpleConfigurator.java @@ -1,53 +1,53 @@ -/** - * 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.joran; - -import java.util.HashMap; - -import ch.qos.logback.core.joran.GenericConfigurator; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.action.NestedComplexPropertyIA; -import ch.qos.logback.core.joran.action.NestedBasicPropertyIA; -import ch.qos.logback.core.joran.spi.Interpreter; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.joran.spi.RuleStore; - -public class SimpleConfigurator extends GenericConfigurator { - - HashMap rulesMap; - - public SimpleConfigurator(HashMap rules) { - this.rulesMap = rules; - } - - @Override - protected void addImplicitRules(Interpreter interpreter) { - NestedComplexPropertyIA nestedIA = new NestedComplexPropertyIA(); - nestedIA.setContext(context); - interpreter.addImplicitAction(nestedIA); - - NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA(); - nestedSimpleIA.setContext(context); - interpreter.addImplicitAction(nestedSimpleIA); - } - - @Override - protected void addInstanceRules(RuleStore rs) { - for(Pattern pattern : rulesMap.keySet()) { - Action action = rulesMap.get(pattern); - rs.addRule(pattern, action); - } - } - -} +/** + * 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.joran; + +import java.util.HashMap; + +import ch.qos.logback.core.joran.GenericConfigurator; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.action.NestedComplexPropertyIA; +import ch.qos.logback.core.joran.action.NestedBasicPropertyIA; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.joran.spi.RuleStore; + +public class SimpleConfigurator extends GenericConfigurator { + + HashMap rulesMap; + + public SimpleConfigurator(HashMap rules) { + this.rulesMap = rules; + } + + @Override + protected void addImplicitRules(Interpreter interpreter) { + NestedComplexPropertyIA nestedIA = new NestedComplexPropertyIA(); + nestedIA.setContext(context); + interpreter.addImplicitAction(nestedIA); + + NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA(); + nestedSimpleIA.setContext(context); + interpreter.addImplicitAction(nestedSimpleIA); + } + + @Override + protected void addInstanceRules(RuleStore rs) { + for(Pattern pattern : rulesMap.keySet()) { + Action action = rulesMap.get(pattern); + rs.addRule(pattern, action); + } + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/SkippingInInterpreterTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/SkippingInInterpreterTest.java index 713a0e5732a187e57eac73abc6fa0bf890d978be..57ceda5adf1afdab040ba832a46135a70bf2e09f 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/SkippingInInterpreterTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/SkippingInInterpreterTest.java @@ -1,115 +1,115 @@ -/** - * 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.joran; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.util.HashMap; -import java.util.List; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.action.NOPAction; -import ch.qos.logback.core.joran.action.ext.BadBeginAction; -import ch.qos.logback.core.joran.action.ext.BadEndAction; -import ch.qos.logback.core.joran.action.ext.HelloAction; -import ch.qos.logback.core.joran.action.ext.TouchAction; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.util.CoreTestConstants; - -/** - * Test the way Interpreter skips child elements in case of exceptions thrown by - * Actions. It also tests addition of status messages in case of exceptions. - * - * @author Ceki Gulcu - */ -public class SkippingInInterpreterTest { - - HashMap rulesMap = new HashMap(); - Context context = new ContextBase(); - StatusManager sm = context.getStatusManager(); - - SAXParser createParser() throws Exception { - SAXParserFactory spf = SAXParserFactory.newInstance(); - return spf.newSAXParser(); - } - - void doTest(String filename, Integer expectedInt, Class exceptionClass) - throws Exception { - - rulesMap.put(new Pattern("test"), new NOPAction()); - rulesMap.put(new Pattern("test/badBegin"), new BadBeginAction()); - rulesMap.put(new Pattern("test/badBegin/touch"), new TouchAction()); - rulesMap.put(new Pattern("test/badEnd"), new BadEndAction()); - rulesMap.put(new Pattern("test/badEnd/touch"), new TouchAction()); - rulesMap.put(new Pattern("test/hello"), new HelloAction()); - - rulesMap.put(new Pattern("test/isolate"), new NOPAction()); - rulesMap.put(new Pattern("test/isolate/badEnd"), new BadEndAction()); - rulesMap.put(new Pattern("test/isolate/badEnd/touch"), new TouchAction()); - rulesMap.put(new Pattern("test/isolate/touch"), new TouchAction()); - rulesMap.put(new Pattern("test/hello"), new HelloAction()); - - TrivialConfigurator tc = new TrivialConfigurator(rulesMap); - tc.setContext(context); - tc.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + "input/joran/skip/" + filename); - - String str = context.getProperty(HelloAction.PROPERTY_KEY); - assertEquals("Hello John Doe.", str); - - Integer i = (Integer) context.getObject(TouchAction.KEY); - if (expectedInt == null) { - assertNull(i); - } else { - assertEquals(expectedInt, i); - } - - // check the existence of an ERROR status - List statusList = sm.getCopyOfStatusList(); - Status s0 = statusList.get(0); - assertEquals(Status.ERROR, s0.getLevel()); - assertTrue(s0.getThrowable().getClass() == exceptionClass); - } - - @Test - public void testSkippingRuntimeExInBadBegin() throws Exception { - doTest("badBegin1.xml", null, IllegalStateException.class); - } - - @Test - public void testSkippingActionExInBadBegin() throws Exception { - doTest("badBegin2.xml", null, ActionException.class); - } - - @Test - public void testSkippingRuntimeExInBadEnd() throws Exception { - doTest("badEnd1.xml", new Integer(2), IllegalStateException.class); - } - - @Test - public void testSkippingActionExInBadEnd() throws Exception { - doTest("badEnd2.xml", new Integer(2), ActionException.class); - } -} +/** + * 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.joran; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.List; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.action.NOPAction; +import ch.qos.logback.core.joran.action.ext.BadBeginAction; +import ch.qos.logback.core.joran.action.ext.BadEndAction; +import ch.qos.logback.core.joran.action.ext.HelloAction; +import ch.qos.logback.core.joran.action.ext.TouchAction; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.CoreTestConstants; + +/** + * Test the way Interpreter skips child elements in case of exceptions thrown by + * Actions. It also tests addition of status messages in case of exceptions. + * + * @author Ceki Gulcu + */ +public class SkippingInInterpreterTest { + + HashMap rulesMap = new HashMap(); + Context context = new ContextBase(); + StatusManager sm = context.getStatusManager(); + + SAXParser createParser() throws Exception { + SAXParserFactory spf = SAXParserFactory.newInstance(); + return spf.newSAXParser(); + } + + void doTest(String filename, Integer expectedInt, Class exceptionClass) + throws Exception { + + rulesMap.put(new Pattern("test"), new NOPAction()); + rulesMap.put(new Pattern("test/badBegin"), new BadBeginAction()); + rulesMap.put(new Pattern("test/badBegin/touch"), new TouchAction()); + rulesMap.put(new Pattern("test/badEnd"), new BadEndAction()); + rulesMap.put(new Pattern("test/badEnd/touch"), new TouchAction()); + rulesMap.put(new Pattern("test/hello"), new HelloAction()); + + rulesMap.put(new Pattern("test/isolate"), new NOPAction()); + rulesMap.put(new Pattern("test/isolate/badEnd"), new BadEndAction()); + rulesMap.put(new Pattern("test/isolate/badEnd/touch"), new TouchAction()); + rulesMap.put(new Pattern("test/isolate/touch"), new TouchAction()); + rulesMap.put(new Pattern("test/hello"), new HelloAction()); + + TrivialConfigurator tc = new TrivialConfigurator(rulesMap); + tc.setContext(context); + tc.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + "input/joran/skip/" + filename); + + String str = context.getProperty(HelloAction.PROPERTY_KEY); + assertEquals("Hello John Doe.", str); + + Integer i = (Integer) context.getObject(TouchAction.KEY); + if (expectedInt == null) { + assertNull(i); + } else { + assertEquals(expectedInt, i); + } + + // check the existence of an ERROR status + List statusList = sm.getCopyOfStatusList(); + Status s0 = statusList.get(0); + assertEquals(Status.ERROR, s0.getLevel()); + assertTrue(s0.getThrowable().getClass() == exceptionClass); + } + + @Test + public void testSkippingRuntimeExInBadBegin() throws Exception { + doTest("badBegin1.xml", null, IllegalStateException.class); + } + + @Test + public void testSkippingActionExInBadBegin() throws Exception { + doTest("badBegin2.xml", null, ActionException.class); + } + + @Test + public void testSkippingRuntimeExInBadEnd() throws Exception { + doTest("badEnd1.xml", new Integer(2), IllegalStateException.class); + } + + @Test + public void testSkippingActionExInBadEnd() throws Exception { + doTest("badEnd2.xml", new Integer(2), ActionException.class); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfigurator.java b/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfigurator.java index 6542744e9958e5e7e118c1e1f59af455b4f9ccfc..aece18724d357ea77fe589d16e79ab38f9f28fc8 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfigurator.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfigurator.java @@ -1,43 +1,43 @@ -/** - * 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.joran; - -import java.util.HashMap; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.Interpreter; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.joran.spi.RuleStore; - -public class TrivialConfigurator extends GenericConfigurator { - - HashMap rulesMap; - - public TrivialConfigurator(HashMap rules) { - this.rulesMap = rules; - } - - @Override - protected void addImplicitRules(Interpreter interpreter) { - } - - @Override - protected void addInstanceRules(RuleStore rs) { - for(Pattern pattern : rulesMap.keySet()) { - Action action = rulesMap.get(pattern); - rs.addRule(pattern, action); - } - } - -} +/** + * 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.joran; + +import java.util.HashMap; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.joran.spi.RuleStore; + +public class TrivialConfigurator extends GenericConfigurator { + + HashMap rulesMap; + + public TrivialConfigurator(HashMap rules) { + this.rulesMap = rules; + } + + @Override + protected void addImplicitRules(Interpreter interpreter) { + } + + @Override + protected void addInstanceRules(RuleStore rs) { + for(Pattern pattern : rulesMap.keySet()) { + Action action = rulesMap.get(pattern); + rs.addRule(pattern, action); + } + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java index d35f1068b1046b00f235b3906a24993a0687cb38..8d61c2ad2886b9beaab3c20a92818684233afe05 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java @@ -1,179 +1,179 @@ -/** - * 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.joran; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.util.HashMap; -import java.util.jar.JarOutputStream; -import java.util.zip.ZipEntry; - -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.action.ext.IncAction; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.TrivialStatusListener; -import ch.qos.logback.core.testUtil.RandomUtil; -import ch.qos.logback.core.util.CoreTestConstants; - -public class TrivialConfiguratorTest { - - Context context = new ContextBase(); - HashMap rulesMap = new HashMap(); - - public void doTest(String filename) throws Exception { - - // rule store is case insensitve - rulesMap.put(new Pattern("x/inc"), new IncAction()); - - TrivialConfigurator trivialConfigurator = new TrivialConfigurator(rulesMap); - - trivialConfigurator.setContext(context); - trivialConfigurator.doConfigure(CoreTestConstants.TEST_DIR_PREFIX - + "input/joran/" + filename); - } - - @Test - public void smoke() throws Exception { - int oldBeginCount = IncAction.beginCount; - int oldEndCount = IncAction.endCount; - int oldErrorCount = IncAction.errorCount; - doTest("inc.xml"); - assertEquals(oldErrorCount, IncAction.errorCount); - assertEquals(oldBeginCount + 1, IncAction.beginCount); - assertEquals(oldEndCount + 1, IncAction.endCount); - } - - @Test - public void inexistentFile() { - TrivialStatusListener tsl = new TrivialStatusListener(); - String filename = "nothereBLAH.xml"; - context.getStatusManager().add(tsl); - try { - doTest(filename); - } catch (Exception e) { - } - assertTrue(tsl.list.size() + " should be greater than or equal to 1", - tsl.list.size() >= 1); - Status s0 = tsl.list.get(0); - assertTrue(s0.getMessage().startsWith("Could not open [" + filename + "]")); - } - - @Test - public void illFormedXML() { - TrivialStatusListener tsl = new TrivialStatusListener(); - String filename = "illformed.xml"; - context.getStatusManager().add(tsl); - try { - doTest(filename); - } catch (Exception e) { - } - assertEquals(2, tsl.list.size()); - Status s0 = tsl.list.get(0); - assertTrue(s0.getMessage().startsWith( - "Parsing fatal error on line 5 and column 3")); - Status s1 = tsl.list.get(1); - assertTrue(s1 - .getMessage() - .startsWith( - "Problem parsing XML document. See previously reported errors. Abandoning all further processing.")); - } - - @Test - public void lbcore105() throws IOException, JoranException { - String jarEntry = "buzz.xml"; - File jarFile = makeRandomJarFile(); - fillInJarFile(jarFile, jarEntry); - URL url = asURL(jarFile, jarEntry); - TrivialConfigurator tc = new TrivialConfigurator(rulesMap); - tc.setContext(context); - tc.doConfigure(url); - // deleting an open file fails - assertTrue(jarFile.delete()); - assertFalse(jarFile.exists()); - } - - @Test - public void lbcore127() throws IOException, JoranException { - String jarEntry = "buzz.xml"; - String jarEntry2 = "lightyear.xml"; - - File jarFile = makeRandomJarFile(); - fillInJarFile(jarFile, jarEntry, jarEntry2); - - URL url1 = asURL(jarFile, jarEntry); - URL url2 = asURL(jarFile, jarEntry2); - - URLConnection urlConnection2 = url2.openConnection(); - urlConnection2.setUseCaches(false); - InputStream is = urlConnection2.getInputStream(); - - TrivialConfigurator tc = new TrivialConfigurator(rulesMap); - tc.setContext(context); - tc.doConfigure(url1); - - is.read(); - is.close(); - - // deleting an open file fails - assertTrue(jarFile.delete()); - assertFalse(jarFile.exists()); - } - - File makeRandomJarFile() { - File outputDir = new File(CoreTestConstants.OUTPUT_DIR_PREFIX); - outputDir.mkdirs(); - int randomPart = RandomUtil.getPositiveInt(); - return new File(CoreTestConstants.OUTPUT_DIR_PREFIX + "foo-" + randomPart - + ".jar"); - } - - private void fillInJarFile(File jarFile, String jarEntryName) - throws IOException { - fillInJarFile(jarFile, jarEntryName, null); - } - - private void fillInJarFile(File jarFile, String jarEntryName1, - String jarEntryName2) throws IOException { - JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile)); - jos.putNextEntry(new ZipEntry(jarEntryName1)); - jos.write("".getBytes()); - jos.closeEntry(); - if (jarEntryName2 != null) { - jos.putNextEntry(new ZipEntry(jarEntryName2)); - jos.write("".getBytes()); - jos.closeEntry(); - } - jos.close(); - } - - URL asURL(File jarFile, String jarEntryName) throws IOException { - URL innerURL = jarFile.toURI().toURL(); - return new URL("jar:" + innerURL + "!/" + jarEntryName); - } - -} +/** + * 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.joran; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashMap; +import java.util.jar.JarOutputStream; +import java.util.zip.ZipEntry; + +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.action.ext.IncAction; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.TrivialStatusListener; +import ch.qos.logback.core.testUtil.RandomUtil; +import ch.qos.logback.core.util.CoreTestConstants; + +public class TrivialConfiguratorTest { + + Context context = new ContextBase(); + HashMap rulesMap = new HashMap(); + + public void doTest(String filename) throws Exception { + + // rule store is case insensitve + rulesMap.put(new Pattern("x/inc"), new IncAction()); + + TrivialConfigurator trivialConfigurator = new TrivialConfigurator(rulesMap); + + trivialConfigurator.setContext(context); + trivialConfigurator.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + + "input/joran/" + filename); + } + + @Test + public void smoke() throws Exception { + int oldBeginCount = IncAction.beginCount; + int oldEndCount = IncAction.endCount; + int oldErrorCount = IncAction.errorCount; + doTest("inc.xml"); + assertEquals(oldErrorCount, IncAction.errorCount); + assertEquals(oldBeginCount + 1, IncAction.beginCount); + assertEquals(oldEndCount + 1, IncAction.endCount); + } + + @Test + public void inexistentFile() { + TrivialStatusListener tsl = new TrivialStatusListener(); + String filename = "nothereBLAH.xml"; + context.getStatusManager().add(tsl); + try { + doTest(filename); + } catch (Exception e) { + } + assertTrue(tsl.list.size() + " should be greater than or equal to 1", + tsl.list.size() >= 1); + Status s0 = tsl.list.get(0); + assertTrue(s0.getMessage().startsWith("Could not open [" + filename + "]")); + } + + @Test + public void illFormedXML() { + TrivialStatusListener tsl = new TrivialStatusListener(); + String filename = "illformed.xml"; + context.getStatusManager().add(tsl); + try { + doTest(filename); + } catch (Exception e) { + } + assertEquals(2, tsl.list.size()); + Status s0 = tsl.list.get(0); + assertTrue(s0.getMessage().startsWith( + "Parsing fatal error on line 5 and column 3")); + Status s1 = tsl.list.get(1); + assertTrue(s1 + .getMessage() + .startsWith( + "Problem parsing XML document. See previously reported errors. Abandoning all further processing.")); + } + + @Test + public void lbcore105() throws IOException, JoranException { + String jarEntry = "buzz.xml"; + File jarFile = makeRandomJarFile(); + fillInJarFile(jarFile, jarEntry); + URL url = asURL(jarFile, jarEntry); + TrivialConfigurator tc = new TrivialConfigurator(rulesMap); + tc.setContext(context); + tc.doConfigure(url); + // deleting an open file fails + assertTrue(jarFile.delete()); + assertFalse(jarFile.exists()); + } + + @Test + public void lbcore127() throws IOException, JoranException { + String jarEntry = "buzz.xml"; + String jarEntry2 = "lightyear.xml"; + + File jarFile = makeRandomJarFile(); + fillInJarFile(jarFile, jarEntry, jarEntry2); + + URL url1 = asURL(jarFile, jarEntry); + URL url2 = asURL(jarFile, jarEntry2); + + URLConnection urlConnection2 = url2.openConnection(); + urlConnection2.setUseCaches(false); + InputStream is = urlConnection2.getInputStream(); + + TrivialConfigurator tc = new TrivialConfigurator(rulesMap); + tc.setContext(context); + tc.doConfigure(url1); + + is.read(); + is.close(); + + // deleting an open file fails + assertTrue(jarFile.delete()); + assertFalse(jarFile.exists()); + } + + File makeRandomJarFile() { + File outputDir = new File(CoreTestConstants.OUTPUT_DIR_PREFIX); + outputDir.mkdirs(); + int randomPart = RandomUtil.getPositiveInt(); + return new File(CoreTestConstants.OUTPUT_DIR_PREFIX + "foo-" + randomPart + + ".jar"); + } + + private void fillInJarFile(File jarFile, String jarEntryName) + throws IOException { + fillInJarFile(jarFile, jarEntryName, null); + } + + private void fillInJarFile(File jarFile, String jarEntryName1, + String jarEntryName2) throws IOException { + JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile)); + jos.putNextEntry(new ZipEntry(jarEntryName1)); + jos.write("".getBytes()); + jos.closeEntry(); + if (jarEntryName2 != null) { + jos.putNextEntry(new ZipEntry(jarEntryName2)); + jos.write("".getBytes()); + jos.closeEntry(); + } + jos.close(); + } + + URL asURL(File jarFile, String jarEntryName) throws IOException { + URL innerURL = jarFile.toURI().toURL(); + return new URL("jar:" + innerURL + "!/" + jarEntryName); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/DummyAttributes.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/DummyAttributes.java index 98eab4a953262816a3c97617ba1b91c81417a352..4167602a94d6ca90de45f16396f45071d2526abd 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/DummyAttributes.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/DummyAttributes.java @@ -1,76 +1,76 @@ -/** - * 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.joran.action; - -import java.util.HashMap; - -import org.xml.sax.Attributes; - -public class DummyAttributes implements Attributes { - - HashMap atts = new HashMap(); - - public int getIndex(String qName) { - return 0; - } - - public int getIndex(String uri, String localName) { - return 0; - } - - public int getLength() { - return 0; - } - - public String getLocalName(int index) { - return null; - } - - public String getQName(int index) { - return null; - } - - public String getType(int index) { - return null; - } - - public String getType(String qName) { - return null; - } - - public String getType(String uri, String localName) { - return null; - } - - public String getURI(int index) { - return null; - } - - public String getValue(int index) { - return null; - } - - public String getValue(String qName) { - return atts.get(qName); - } - - public void setValue(String key, String value) { - atts.put(key, value); - } - - public String getValue(String uri, String localName) { - return null; - } - -} +/** + * 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.joran.action; + +import java.util.HashMap; + +import org.xml.sax.Attributes; + +public class DummyAttributes implements Attributes { + + HashMap atts = new HashMap(); + + public int getIndex(String qName) { + return 0; + } + + public int getIndex(String uri, String localName) { + return 0; + } + + public int getLength() { + return 0; + } + + public String getLocalName(int index) { + return null; + } + + public String getQName(int index) { + return null; + } + + public String getType(int index) { + return null; + } + + public String getType(String qName) { + return null; + } + + public String getType(String uri, String localName) { + return null; + } + + public String getURI(int index) { + return null; + } + + public String getValue(int index) { + return null; + } + + public String getValue(String qName) { + return atts.get(qName); + } + + public void setValue(String key, String value) { + atts.put(key, value); + } + + public String getValue(String uri, String localName) { + return null; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/IncludeActionTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/IncludeActionTest.java index c4e1cdf1a965506897df1e8a2ff8cd3bc2fedc1e..d7d621c83e9aba402308445a1fdc06d6094dea38 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/IncludeActionTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/IncludeActionTest.java @@ -1,217 +1,217 @@ -/** - * 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.joran.action; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.UnknownHostException; -import java.util.HashMap; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.xml.sax.SAXParseException; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.joran.TrivialConfigurator; -import ch.qos.logback.core.joran.action.ext.IncAction; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusChecker; -import ch.qos.logback.core.testUtil.RandomUtil; -import ch.qos.logback.core.util.CoreTestConstants; -import ch.qos.logback.core.util.StatusPrinter; - -public class IncludeActionTest { - - final static String INCLUDE_KEY = "includeKey"; - final static String SUB_FILE_KEY = "subFileKey"; - final static String SECOND_FILE_KEY = "secondFileKey"; - - Context context = new ContextBase(); - TrivialConfigurator tc; - - static final String INCLUSION_DIR_PREFIX = "src/test/input/joran/inclusion/"; - - static final String TOP_BY_FILE = INCLUSION_DIR_PREFIX + "topByFile.xml"; - - static final String SUB_FILE = INCLUSION_DIR_PREFIX + "subByFile.xml"; - - static final String MULTI_INCLUDE_BY_FILE = INCLUSION_DIR_PREFIX - + "multiIncludeByFile.xml"; - - static final String SECOND_FILE = INCLUSION_DIR_PREFIX + "second.xml"; - - static final String TOP_BY_URL = INCLUSION_DIR_PREFIX + "topByUrl.xml"; - - static final String INCLUDE_BY_RESOURCE = INCLUSION_DIR_PREFIX - + "topByResource.xml"; - - static final String INCLUDED_FILE = INCLUSION_DIR_PREFIX + "included.xml"; - static final String URL_TO_INCLUDE = "file:./" + INCLUDED_FILE; - - static final String INVALID = INCLUSION_DIR_PREFIX + "invalid.xml"; - - static final String INCLUDED_AS_RESOURCE = "asResource/joran/inclusion/includedAsResource.xml"; - - int diff = RandomUtil.getPositiveInt(); - - public IncludeActionTest() { - HashMap rulesMap = new HashMap(); - rulesMap.put(new Pattern("x"), new NOPAction()); - rulesMap.put(new Pattern("x/inc"), new IncAction()); - rulesMap.put(new Pattern("x/include"), new IncludeAction()); - - tc = new TrivialConfigurator(rulesMap); - tc.setContext(context); - } - - @Before - public void setUp() throws Exception { - IncAction.reset(); - } - - @After - public void tearDown() throws Exception { - context = null; - System.clearProperty(INCLUDE_KEY); - System.clearProperty(SECOND_FILE_KEY); - System.clearProperty(SUB_FILE_KEY); - } - - @Test - public void basicFile() throws JoranException { - System.setProperty(INCLUDE_KEY, INCLUDED_FILE); - tc.doConfigure(TOP_BY_FILE); - verifyConfig(2); - } - - @Test - public void basicResource() throws JoranException { - System.setProperty(INCLUDE_KEY, INCLUDED_AS_RESOURCE); - tc.doConfigure(INCLUDE_BY_RESOURCE); - StatusPrinter.print(context); - verifyConfig(2); - } - - @Test - public void basicURL() throws JoranException { - System.setProperty(INCLUDE_KEY, URL_TO_INCLUDE); - tc.doConfigure(TOP_BY_URL); - StatusPrinter.print(context); - verifyConfig(2); - } - - @Test - public void noFileFound() throws JoranException { - System.setProperty(INCLUDE_KEY, "toto"); - tc.doConfigure(TOP_BY_FILE); - assertEquals(Status.ERROR, context.getStatusManager().getLevel()); - StatusChecker sc = new StatusChecker(context.getStatusManager()); - assertTrue(sc.containsException(FileNotFoundException.class)); - } - - @Test - public void withCorruptFile() throws JoranException, IOException { - String tmpOut = copyToTemp(INVALID); - System.setProperty(INCLUDE_KEY, tmpOut); - tc.doConfigure(TOP_BY_FILE); - assertEquals(Status.ERROR, context.getStatusManager().getLevel()); - StatusChecker sc = new StatusChecker(context.getStatusManager()); - assertTrue(sc.containsException(SAXParseException.class)); - - // we like to erase the temp file in order to see - // if http://jira.qos.ch/browse/LBCORE-122 was fixed - File f = new File(tmpOut); - assertTrue(f.exists()); - assertTrue(f.delete()); - - } - - String copyToTemp(String in) throws IOException { - FileInputStream fis = new FileInputStream(in); - String out = CoreTestConstants.OUTPUT_DIR_PREFIX+"out"+diff; - FileOutputStream fos = new FileOutputStream(out); - int b; - while((b=fis.read()) != -1) { - fos.write(b); - } - fis.close(); - fos.close(); - return out; - } - - @Test - public void malformedURL() throws JoranException { - System.setProperty(INCLUDE_KEY, "htp://logback.qos.ch"); - tc.doConfigure(TOP_BY_URL); - assertEquals(Status.ERROR, context.getStatusManager().getLevel()); - StatusChecker sc = new StatusChecker(context.getStatusManager()); - assertTrue(sc.containsException(MalformedURLException.class)); - } - - @Test - public void unknownURL() throws JoranException { - System.setProperty(INCLUDE_KEY, "http://logback2345.qos.ch"); - tc.doConfigure(TOP_BY_URL); - assertEquals(Status.ERROR, context.getStatusManager().getLevel()); - StatusChecker sc = new StatusChecker(context.getStatusManager()); - assertTrue(sc.containsException(UnknownHostException.class)); - } - - @Test - public void nestedInclude() throws JoranException { - System.setProperty(SUB_FILE_KEY, INCLUDED_FILE); - System.setProperty(INCLUDE_KEY, SECOND_FILE); - tc.doConfigure(TOP_BY_FILE); - StatusPrinter.print(context); - verifyConfig(1); - - } - - @Test - public void multiInclude() throws JoranException { - System.setProperty(INCLUDE_KEY, INCLUDED_FILE); - System.setProperty(SECOND_FILE_KEY, SECOND_FILE); - tc.doConfigure(MULTI_INCLUDE_BY_FILE); - verifyConfig(3); - } - - @Test - public void saxParseException() throws JoranException { - System.setProperty(INCLUDE_KEY, INCLUDED_FILE); - System.setProperty(SECOND_FILE_KEY, SECOND_FILE); - tc.doConfigure(MULTI_INCLUDE_BY_FILE); - verifyConfig(3); - } - - @Test - public void errorInDoBegin() { - - } - - void verifyConfig(int expected) { - assertEquals(expected, IncAction.beginCount); - assertEquals(expected, IncAction.endCount); - } -} +/** + * 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.joran.action; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.UnknownHostException; +import java.util.HashMap; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.xml.sax.SAXParseException; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.joran.TrivialConfigurator; +import ch.qos.logback.core.joran.action.ext.IncAction; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusChecker; +import ch.qos.logback.core.testUtil.RandomUtil; +import ch.qos.logback.core.util.CoreTestConstants; +import ch.qos.logback.core.util.StatusPrinter; + +public class IncludeActionTest { + + final static String INCLUDE_KEY = "includeKey"; + final static String SUB_FILE_KEY = "subFileKey"; + final static String SECOND_FILE_KEY = "secondFileKey"; + + Context context = new ContextBase(); + TrivialConfigurator tc; + + static final String INCLUSION_DIR_PREFIX = "src/test/input/joran/inclusion/"; + + static final String TOP_BY_FILE = INCLUSION_DIR_PREFIX + "topByFile.xml"; + + static final String SUB_FILE = INCLUSION_DIR_PREFIX + "subByFile.xml"; + + static final String MULTI_INCLUDE_BY_FILE = INCLUSION_DIR_PREFIX + + "multiIncludeByFile.xml"; + + static final String SECOND_FILE = INCLUSION_DIR_PREFIX + "second.xml"; + + static final String TOP_BY_URL = INCLUSION_DIR_PREFIX + "topByUrl.xml"; + + static final String INCLUDE_BY_RESOURCE = INCLUSION_DIR_PREFIX + + "topByResource.xml"; + + static final String INCLUDED_FILE = INCLUSION_DIR_PREFIX + "included.xml"; + static final String URL_TO_INCLUDE = "file:./" + INCLUDED_FILE; + + static final String INVALID = INCLUSION_DIR_PREFIX + "invalid.xml"; + + static final String INCLUDED_AS_RESOURCE = "asResource/joran/inclusion/includedAsResource.xml"; + + int diff = RandomUtil.getPositiveInt(); + + public IncludeActionTest() { + HashMap rulesMap = new HashMap(); + rulesMap.put(new Pattern("x"), new NOPAction()); + rulesMap.put(new Pattern("x/inc"), new IncAction()); + rulesMap.put(new Pattern("x/include"), new IncludeAction()); + + tc = new TrivialConfigurator(rulesMap); + tc.setContext(context); + } + + @Before + public void setUp() throws Exception { + IncAction.reset(); + } + + @After + public void tearDown() throws Exception { + context = null; + System.clearProperty(INCLUDE_KEY); + System.clearProperty(SECOND_FILE_KEY); + System.clearProperty(SUB_FILE_KEY); + } + + @Test + public void basicFile() throws JoranException { + System.setProperty(INCLUDE_KEY, INCLUDED_FILE); + tc.doConfigure(TOP_BY_FILE); + verifyConfig(2); + } + + @Test + public void basicResource() throws JoranException { + System.setProperty(INCLUDE_KEY, INCLUDED_AS_RESOURCE); + tc.doConfigure(INCLUDE_BY_RESOURCE); + StatusPrinter.print(context); + verifyConfig(2); + } + + @Test + public void basicURL() throws JoranException { + System.setProperty(INCLUDE_KEY, URL_TO_INCLUDE); + tc.doConfigure(TOP_BY_URL); + StatusPrinter.print(context); + verifyConfig(2); + } + + @Test + public void noFileFound() throws JoranException { + System.setProperty(INCLUDE_KEY, "toto"); + tc.doConfigure(TOP_BY_FILE); + assertEquals(Status.ERROR, context.getStatusManager().getLevel()); + StatusChecker sc = new StatusChecker(context.getStatusManager()); + assertTrue(sc.containsException(FileNotFoundException.class)); + } + + @Test + public void withCorruptFile() throws JoranException, IOException { + String tmpOut = copyToTemp(INVALID); + System.setProperty(INCLUDE_KEY, tmpOut); + tc.doConfigure(TOP_BY_FILE); + assertEquals(Status.ERROR, context.getStatusManager().getLevel()); + StatusChecker sc = new StatusChecker(context.getStatusManager()); + assertTrue(sc.containsException(SAXParseException.class)); + + // we like to erase the temp file in order to see + // if http://jira.qos.ch/browse/LBCORE-122 was fixed + File f = new File(tmpOut); + assertTrue(f.exists()); + assertTrue(f.delete()); + + } + + String copyToTemp(String in) throws IOException { + FileInputStream fis = new FileInputStream(in); + String out = CoreTestConstants.OUTPUT_DIR_PREFIX+"out"+diff; + FileOutputStream fos = new FileOutputStream(out); + int b; + while((b=fis.read()) != -1) { + fos.write(b); + } + fis.close(); + fos.close(); + return out; + } + + @Test + public void malformedURL() throws JoranException { + System.setProperty(INCLUDE_KEY, "htp://logback.qos.ch"); + tc.doConfigure(TOP_BY_URL); + assertEquals(Status.ERROR, context.getStatusManager().getLevel()); + StatusChecker sc = new StatusChecker(context.getStatusManager()); + assertTrue(sc.containsException(MalformedURLException.class)); + } + + @Test + public void unknownURL() throws JoranException { + System.setProperty(INCLUDE_KEY, "http://logback2345.qos.ch"); + tc.doConfigure(TOP_BY_URL); + assertEquals(Status.ERROR, context.getStatusManager().getLevel()); + StatusChecker sc = new StatusChecker(context.getStatusManager()); + assertTrue(sc.containsException(UnknownHostException.class)); + } + + @Test + public void nestedInclude() throws JoranException { + System.setProperty(SUB_FILE_KEY, INCLUDED_FILE); + System.setProperty(INCLUDE_KEY, SECOND_FILE); + tc.doConfigure(TOP_BY_FILE); + StatusPrinter.print(context); + verifyConfig(1); + + } + + @Test + public void multiInclude() throws JoranException { + System.setProperty(INCLUDE_KEY, INCLUDED_FILE); + System.setProperty(SECOND_FILE_KEY, SECOND_FILE); + tc.doConfigure(MULTI_INCLUDE_BY_FILE); + verifyConfig(3); + } + + @Test + public void saxParseException() throws JoranException { + System.setProperty(INCLUDE_KEY, INCLUDED_FILE); + System.setProperty(SECOND_FILE_KEY, SECOND_FILE); + tc.doConfigure(MULTI_INCLUDE_BY_FILE); + verifyConfig(3); + } + + @Test + public void errorInDoBegin() { + + } + + void verifyConfig(int expected) { + assertEquals(expected, IncAction.beginCount); + assertEquals(expected, IncAction.endCount); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/PackageTest.java index 5b7ef4d6a4af64904ad18e7208856fab27597808..2f68d11ebafbf37b3a1ea133db1cb20f6895c1a7 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/PackageTest.java @@ -1,23 +1,23 @@ -/** - * 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.joran.action; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({PropertyActionTest.class, IncludeActionTest.class}) -public class PackageTest { -} +/** + * 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.joran.action; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({PropertyActionTest.class, IncludeActionTest.class}) +public class PackageTest { +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java index 483de0accb14f666fa1c03321a8bac74d98d3d7d..362f8f57bcaf0e200239aa29ac8f4c18bc03d720 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java @@ -1,161 +1,161 @@ -/** - * 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.joran.action; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Iterator; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.status.ErrorStatus; -import ch.qos.logback.core.util.CoreTestConstants; -import ch.qos.logback.core.util.StatusPrinter; - -/** - * Test {@link PropertyAction}. - * @author Ceki Gülcü - */ -public class PropertyActionTest { - - Context context; - InterpretationContext ec; - PropertyAction propertyAction; - DummyAttributes atts = new DummyAttributes(); - - @Before - public void setUp() throws Exception { - context = new ContextBase(); - ec = new InterpretationContext(context, null); - propertyAction = new PropertyAction(); - propertyAction.setContext(context); - } - - @After - public void tearDown() throws Exception { - context = null; - propertyAction = null; - atts = null; - } - - @Test - public void nameValuePair() { - atts.setValue("name", "v1"); - atts.setValue("value", "work"); - propertyAction.begin(ec, null, atts); - assertEquals("work", ec.getProperty("v1")); - } - - @Test - public void nameValuePairWithPrerequisiteSubsitution() { - context.putProperty("w", "wor"); - atts.setValue("name", "v1"); - atts.setValue("value", "${w}k"); - propertyAction.begin(ec, null, atts); - assertEquals("work", ec.getProperty("v1")); - } - - @Test - public void noValue() { - atts.setValue("name", "v1"); - propertyAction.begin(ec, null, atts); - assertEquals(1, context.getStatusManager().getCount()); - assertTrue(checkError()); - } - - @Test - public void noName() { - atts.setValue("value", "v1"); - propertyAction.begin(ec, null, atts); - assertEquals(1, context.getStatusManager().getCount()); - assertTrue(checkError()); - } - - @Test - public void noAttributes() { - propertyAction.begin(ec, null, atts); - assertEquals(1, context.getStatusManager().getCount()); - assertTrue(checkError()); - StatusPrinter.print(context); - } - - @Test - public void testFileNotLoaded() { - atts.setValue("file", "toto"); - atts.setValue("value", "work"); - propertyAction.begin(ec, null, atts); - assertEquals(1, context.getStatusManager().getCount()); - assertTrue(checkError()); - } - - @Test - public void testLoadFileWithPrerequisiteSubsitution() { - context.putProperty("STEM", CoreTestConstants.TEST_DIR_PREFIX + "input/joran"); - atts.setValue("file", "${STEM}/propertyActionTest.properties"); - propertyAction.begin(ec, null, atts); - assertEquals("tata", ec.getProperty("v1")); - assertEquals("toto", ec.getProperty("v2")); - } - - @Test - public void testLoadFile() { - atts.setValue("file", CoreTestConstants.TEST_DIR_PREFIX + "input/joran/propertyActionTest.properties"); - propertyAction.begin(ec, null, atts); - assertEquals("tata", ec.getProperty("v1")); - assertEquals("toto", ec.getProperty("v2")); - } - - @Test - public void testLoadResource() { - atts.setValue("resource", "asResource/joran/propertyActionTest.properties"); - propertyAction.begin(ec, null, atts); - assertEquals("tata", ec.getProperty("r1")); - assertEquals("toto", ec.getProperty("r2")); - } - - @Test - public void testLoadResourceWithPrerequisiteSubsitution() { - context.putProperty("STEM", "asResource/joran"); - atts.setValue("resource", "${STEM}/propertyActionTest.properties"); - propertyAction.begin(ec, null, atts); - assertEquals("tata", ec.getProperty("r1")); - assertEquals("toto", ec.getProperty("r2")); - } - - @Test - public void testLoadNotPossible() { - atts.setValue("file", "toto"); - propertyAction.begin(ec, null, atts); - assertEquals(1, context.getStatusManager().getCount()); - assertTrue(checkFileErrors()); - } - - private boolean checkError() { - Iterator it = context.getStatusManager().getCopyOfStatusList().iterator(); - ErrorStatus es = (ErrorStatus)it.next(); - return PropertyAction.INVALID_ATTRIBUTES.equals(es.getMessage()); - } - - private boolean checkFileErrors() { - Iterator it = context.getStatusManager().getCopyOfStatusList().iterator(); - ErrorStatus es1 = (ErrorStatus)it.next(); - return "Could not read properties file [toto].".equals(es1.getMessage()); - } -} +/** + * 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.joran.action; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Iterator; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.util.CoreTestConstants; +import ch.qos.logback.core.util.StatusPrinter; + +/** + * Test {@link PropertyAction}. + * @author Ceki Gülcü + */ +public class PropertyActionTest { + + Context context; + InterpretationContext ec; + PropertyAction propertyAction; + DummyAttributes atts = new DummyAttributes(); + + @Before + public void setUp() throws Exception { + context = new ContextBase(); + ec = new InterpretationContext(context, null); + propertyAction = new PropertyAction(); + propertyAction.setContext(context); + } + + @After + public void tearDown() throws Exception { + context = null; + propertyAction = null; + atts = null; + } + + @Test + public void nameValuePair() { + atts.setValue("name", "v1"); + atts.setValue("value", "work"); + propertyAction.begin(ec, null, atts); + assertEquals("work", ec.getProperty("v1")); + } + + @Test + public void nameValuePairWithPrerequisiteSubsitution() { + context.putProperty("w", "wor"); + atts.setValue("name", "v1"); + atts.setValue("value", "${w}k"); + propertyAction.begin(ec, null, atts); + assertEquals("work", ec.getProperty("v1")); + } + + @Test + public void noValue() { + atts.setValue("name", "v1"); + propertyAction.begin(ec, null, atts); + assertEquals(1, context.getStatusManager().getCount()); + assertTrue(checkError()); + } + + @Test + public void noName() { + atts.setValue("value", "v1"); + propertyAction.begin(ec, null, atts); + assertEquals(1, context.getStatusManager().getCount()); + assertTrue(checkError()); + } + + @Test + public void noAttributes() { + propertyAction.begin(ec, null, atts); + assertEquals(1, context.getStatusManager().getCount()); + assertTrue(checkError()); + StatusPrinter.print(context); + } + + @Test + public void testFileNotLoaded() { + atts.setValue("file", "toto"); + atts.setValue("value", "work"); + propertyAction.begin(ec, null, atts); + assertEquals(1, context.getStatusManager().getCount()); + assertTrue(checkError()); + } + + @Test + public void testLoadFileWithPrerequisiteSubsitution() { + context.putProperty("STEM", CoreTestConstants.TEST_DIR_PREFIX + "input/joran"); + atts.setValue("file", "${STEM}/propertyActionTest.properties"); + propertyAction.begin(ec, null, atts); + assertEquals("tata", ec.getProperty("v1")); + assertEquals("toto", ec.getProperty("v2")); + } + + @Test + public void testLoadFile() { + atts.setValue("file", CoreTestConstants.TEST_DIR_PREFIX + "input/joran/propertyActionTest.properties"); + propertyAction.begin(ec, null, atts); + assertEquals("tata", ec.getProperty("v1")); + assertEquals("toto", ec.getProperty("v2")); + } + + @Test + public void testLoadResource() { + atts.setValue("resource", "asResource/joran/propertyActionTest.properties"); + propertyAction.begin(ec, null, atts); + assertEquals("tata", ec.getProperty("r1")); + assertEquals("toto", ec.getProperty("r2")); + } + + @Test + public void testLoadResourceWithPrerequisiteSubsitution() { + context.putProperty("STEM", "asResource/joran"); + atts.setValue("resource", "${STEM}/propertyActionTest.properties"); + propertyAction.begin(ec, null, atts); + assertEquals("tata", ec.getProperty("r1")); + assertEquals("toto", ec.getProperty("r2")); + } + + @Test + public void testLoadNotPossible() { + atts.setValue("file", "toto"); + propertyAction.begin(ec, null, atts); + assertEquals(1, context.getStatusManager().getCount()); + assertTrue(checkFileErrors()); + } + + private boolean checkError() { + Iterator it = context.getStatusManager().getCopyOfStatusList().iterator(); + ErrorStatus es = (ErrorStatus)it.next(); + return PropertyAction.INVALID_ATTRIBUTES.equals(es.getMessage()); + } + + private boolean checkFileErrors() { + Iterator it = context.getStatusManager().getCopyOfStatusList().iterator(); + ErrorStatus es1 = (ErrorStatus)it.next(); + return "Could not read properties file [toto].".equals(es1.getMessage()); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/BadBeginAction.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/BadBeginAction.java index 85ce9440cc4b5377c0cdad1873e646d0fcabbbff..b65a292ce8ff244d7004f44b53aaa8493119a2ee 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/BadBeginAction.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/BadBeginAction.java @@ -1,55 +1,55 @@ -/** - * 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.joran.action.ext; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; - - - -public class BadBeginAction extends Action { - - - static String EXCEPTION_TYPE = "type"; - static final int RUNTIME_EDXCEPTION = 0; - static final int ACTION_EXCEPTION = 1; - - int type; - - public BadBeginAction() { - } - - public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException { - - String exType = attributes.getValue(EXCEPTION_TYPE); - type = RUNTIME_EDXCEPTION; - if("ActionException".equals(exType)) { - type = ACTION_EXCEPTION; - } - - switch(type) { - case ACTION_EXCEPTION: - throw new ActionException(); - default: - throw new IllegalStateException("bad begin"); - } - - } - - public void end(InterpretationContext ec, String name) { - } -} +/** + * 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.joran.action.ext; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; + + + +public class BadBeginAction extends Action { + + + static String EXCEPTION_TYPE = "type"; + static final int RUNTIME_EDXCEPTION = 0; + static final int ACTION_EXCEPTION = 1; + + int type; + + public BadBeginAction() { + } + + public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException { + + String exType = attributes.getValue(EXCEPTION_TYPE); + type = RUNTIME_EDXCEPTION; + if("ActionException".equals(exType)) { + type = ACTION_EXCEPTION; + } + + switch(type) { + case ACTION_EXCEPTION: + throw new ActionException(); + default: + throw new IllegalStateException("bad begin"); + } + + } + + public void end(InterpretationContext ec, String name) { + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/BadEndAction.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/BadEndAction.java index f345e8409281aeac0fb74fbc8ffa6ea087e89e97..c0644ec773fb8eca4732824ebc454031c1127894 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/BadEndAction.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/BadEndAction.java @@ -1,51 +1,51 @@ -/** - * 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.joran.action.ext; - - - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; - - - -public class BadEndAction extends Action { - - static String EXCEPTION_TYPE = "type"; - static final int RUNTIME_EXCEPTION = 0; - static final int ACTION_EXCEPTION = 1; - - int type; - - - public void begin(InterpretationContext ec, String name, Attributes attributes) { - String exType = attributes.getValue(EXCEPTION_TYPE); - type = RUNTIME_EXCEPTION; - if("ActionException".equals(exType)) { - type = ACTION_EXCEPTION; - } - } - - public void end(InterpretationContext ec, String name) throws ActionException { - switch(type) { - case ACTION_EXCEPTION: - throw new ActionException(); - default: - throw new IllegalStateException("bad end"); - } - } -} +/** + * 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.joran.action.ext; + + + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; + + + +public class BadEndAction extends Action { + + static String EXCEPTION_TYPE = "type"; + static final int RUNTIME_EXCEPTION = 0; + static final int ACTION_EXCEPTION = 1; + + int type; + + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + String exType = attributes.getValue(EXCEPTION_TYPE); + type = RUNTIME_EXCEPTION; + if("ActionException".equals(exType)) { + type = ACTION_EXCEPTION; + } + } + + public void end(InterpretationContext ec, String name) throws ActionException { + switch(type) { + case ACTION_EXCEPTION: + throw new ActionException(); + default: + throw new IllegalStateException("bad end"); + } + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/HelloAction.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/HelloAction.java index bcce09015c3ba53e4a3d3ed1b0612c5b9d609126..603a81de8de272393187fe8862c19386f99adf5e 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/HelloAction.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/HelloAction.java @@ -1,45 +1,45 @@ -/** - * 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.joran.action.ext; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.InterpretationContext; - - - -public class HelloAction extends Action { - - - static final public String PROPERTY_KEY = "name"; - - public HelloAction() { - } - /** - * Instantiates an layout of the given class and sets its name. - * - */ - public void begin(InterpretationContext ec, String name, Attributes attributes) { - String str = "Hello "+attributes.getValue("name")+"."; - ec.getContext().putProperty(PROPERTY_KEY, str); - } - - /** - * Once the children elements are also parsed, now is the time to activate - * the appender options. - */ - public void end(InterpretationContext ec, String name) { - } -} +/** + * 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.joran.action.ext; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; + + + +public class HelloAction extends Action { + + + static final public String PROPERTY_KEY = "name"; + + public HelloAction() { + } + /** + * Instantiates an layout of the given class and sets its name. + * + */ + public void begin(InterpretationContext ec, String name, Attributes attributes) { + String str = "Hello "+attributes.getValue("name")+"."; + ec.getContext().putProperty(PROPERTY_KEY, str); + } + + /** + * Once the children elements are also parsed, now is the time to activate + * the appender options. + */ + public void end(InterpretationContext ec, String name) { + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/IncAction.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/IncAction.java index 618fce347e63a3b7051b70886d84b5bb98077deb..30859b7ae54f13f8298aa4bcb37b9bcb5fe6ac78 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/IncAction.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/IncAction.java @@ -1,56 +1,56 @@ -/** - * 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.joran.action.ext; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; - - - -public class IncAction extends Action { - - static public int beginCount; - static public int endCount; - static public int errorCount; - - static public void reset() { - beginCount = 0; - endCount = 0; - errorCount = 0; - } - /** - * Instantiates an layout of the given class and sets its name. - * - */ - public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException { - //System.out.println("IncAction Begin called"); - beginCount++; - String val = attributes.getValue("increment"); - if(!"1".equals(val)) { - errorCount++; - throw new ActionException(); - } - } - - /** - * Once the children elements are also parsed, now is the time to activate - * the appender options. - */ - public void end(InterpretationContext ec, String name) { - endCount++; - } -} +/** + * 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.joran.action.ext; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; + + + +public class IncAction extends Action { + + static public int beginCount; + static public int endCount; + static public int errorCount; + + static public void reset() { + beginCount = 0; + endCount = 0; + errorCount = 0; + } + /** + * Instantiates an layout of the given class and sets its name. + * + */ + public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException { + //System.out.println("IncAction Begin called"); + beginCount++; + String val = attributes.getValue("increment"); + if(!"1".equals(val)) { + errorCount++; + throw new ActionException(); + } + } + + /** + * Once the children elements are also parsed, now is the time to activate + * the appender options. + */ + public void end(InterpretationContext ec, String name) { + endCount++; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/StackCounterAction.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/StackCounterAction.java index 631385b25f20d5a8f2a4f56c7c8cad2ee4e5b638..48beaff4d3a5429033c6e1ac66dee6ed993990b2 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/StackCounterAction.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/StackCounterAction.java @@ -1,43 +1,43 @@ -/** - * 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.joran.action.ext; - - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.Layout; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.InterpretationContext; - - - -public class StackCounterAction extends Action { - Layout layout; - - - public StackCounterAction() { - } - - public void begin(InterpretationContext ec, String name, Attributes attributes) { - //String str = "Pushing "+name+"-begin"; - ec.pushObject(name+"-begin"); - } - - public void end(InterpretationContext ec, String name) { - ec.pushObject(name+"-end"); - } - - public void finish(InterpretationContext ec) { - } -} +/** + * 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.joran.action.ext; + + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; + + + +public class StackCounterAction extends Action { + Layout layout; + + + public StackCounterAction() { + } + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + //String str = "Pushing "+name+"-begin"; + ec.pushObject(name+"-begin"); + } + + public void end(InterpretationContext ec, String name) { + ec.pushObject(name+"-end"); + } + + public void finish(InterpretationContext ec) { + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/TouchAction.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/TouchAction.java index 9be7f41b101ae19e93dd70987f7c0a4f3f710d92..bf8225fff01d2ddc197ae60a3c1786c0305f19b5 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/TouchAction.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/TouchAction.java @@ -1,49 +1,49 @@ -/** - * 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.joran.action.ext; - - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.InterpretationContext; - - - -public class TouchAction extends Action { - - public static final String KEY = "touched"; - - public TouchAction() { - } - /** - * Instantiates an layout of the given class and sets its name. - * - */ - public void begin(InterpretationContext ec, String name, Attributes attributes) { - Integer i = (Integer) ec.getContext().getObject(KEY); - if(i == null) { - ec.getContext().putObject(KEY, new Integer(1)); - } else { - ec.getContext().putObject(KEY, new Integer(i.intValue()+1)); - } - } - - /** - * Once the children elements are also parsed, now is the time to activate - * the appender options. - */ - public void end(InterpretationContext ec, String name) { - } -} +/** + * 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.joran.action.ext; + + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; + + + +public class TouchAction extends Action { + + public static final String KEY = "touched"; + + public TouchAction() { + } + /** + * Instantiates an layout of the given class and sets its name. + * + */ + public void begin(InterpretationContext ec, String name, Attributes attributes) { + Integer i = (Integer) ec.getContext().getObject(KEY); + if(i == null) { + ec.getContext().putObject(KEY, new Integer(1)); + } else { + ec.getContext().putObject(KEY, new Integer(i.intValue()+1)); + } + } + + /** + * Once the children elements are also parsed, now is the time to activate + * the appender options. + */ + public void end(InterpretationContext ec, String name) { + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/event/EventRecorderTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/event/EventRecorderTest.java index 351f9f790cf6d017984e7c76de5ad3ef191ac4d0..a45d2f20ffadb919546769a255c35f3b9639d9e5 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/event/EventRecorderTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/event/EventRecorderTest.java @@ -1,106 +1,106 @@ -/** - * 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.joran.event; - -import static org.junit.Assert.*; - -import java.io.FileInputStream; -import java.util.List; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.junit.Test; -import org.xml.sax.Attributes; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.util.CoreTestConstants; - -/** - * Test whether SaxEventRecorder does a good job. - * - * @author Ceki Gulcu - */ -public class EventRecorderTest { - - Context context = new ContextBase(); - - - SAXParser createParser() throws Exception { - SAXParserFactory spf = SAXParserFactory.newInstance(); - return spf.newSAXParser(); - } - - public List doTest(String filename) throws Exception { - SaxEventRecorder recorder = new SaxEventRecorder(); - recorder.setContext(context); - FileInputStream fis = new FileInputStream(CoreTestConstants.TEST_DIR_PREFIX - + "input/joran/"+ filename); - recorder.recordEvents(fis); - return recorder.getSaxEventList(); - - - } - - public void dump(List seList) { - for (SaxEvent se : seList) { - System.out.println(se); - } - } - /** - * Tests that whenever an action throws an exception, processing of child - * elements is skipped. - * - * @throws Exception - */ - @Test - public void test1() throws Exception { - List seList = doTest("event1.xml"); - StatusManager sm = context.getStatusManager(); - assertTrue(sm.getLevel() == Status.INFO); - //dump(seList); - assertEquals(11, seList.size()); - - } - - @Test - public void test2() throws Exception { - List seList = doTest("ampEvent.xml"); - StatusManager sm = context.getStatusManager(); - assertTrue(sm.getLevel() == Status.INFO); - //dump(seList); - assertEquals(3, seList.size()); - - BodyEvent be = (BodyEvent) seList.get(1); - assertEquals("xxx & yyy", be.getText()); - } - - @Test - public void test3() throws Exception { - List seList = doTest("inc.xml"); - StatusManager sm = context.getStatusManager(); - assertTrue(sm.getLevel() == Status.INFO); - //dump(seList); - assertEquals(4, seList.size()); - - StartEvent se = (StartEvent) seList.get(1); - Attributes attr = se.getAttributes(); - assertNotNull(attr); - assertEquals("1", attr.getValue("increment")); - } - -} +/** + * 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.joran.event; + +import static org.junit.Assert.*; + +import java.io.FileInputStream; +import java.util.List; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.junit.Test; +import org.xml.sax.Attributes; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.CoreTestConstants; + +/** + * Test whether SaxEventRecorder does a good job. + * + * @author Ceki Gulcu + */ +public class EventRecorderTest { + + Context context = new ContextBase(); + + + SAXParser createParser() throws Exception { + SAXParserFactory spf = SAXParserFactory.newInstance(); + return spf.newSAXParser(); + } + + public List doTest(String filename) throws Exception { + SaxEventRecorder recorder = new SaxEventRecorder(); + recorder.setContext(context); + FileInputStream fis = new FileInputStream(CoreTestConstants.TEST_DIR_PREFIX + + "input/joran/"+ filename); + recorder.recordEvents(fis); + return recorder.getSaxEventList(); + + + } + + public void dump(List seList) { + for (SaxEvent se : seList) { + System.out.println(se); + } + } + /** + * Tests that whenever an action throws an exception, processing of child + * elements is skipped. + * + * @throws Exception + */ + @Test + public void test1() throws Exception { + List seList = doTest("event1.xml"); + StatusManager sm = context.getStatusManager(); + assertTrue(sm.getLevel() == Status.INFO); + //dump(seList); + assertEquals(11, seList.size()); + + } + + @Test + public void test2() throws Exception { + List seList = doTest("ampEvent.xml"); + StatusManager sm = context.getStatusManager(); + assertTrue(sm.getLevel() == Status.INFO); + //dump(seList); + assertEquals(3, seList.size()); + + BodyEvent be = (BodyEvent) seList.get(1); + assertEquals("xxx & yyy", be.getText()); + } + + @Test + public void test3() throws Exception { + List seList = doTest("inc.xml"); + StatusManager sm = context.getStatusManager(); + assertTrue(sm.getLevel() == Status.INFO); + //dump(seList); + assertEquals(4, seList.size()); + + StartEvent se = (StartEvent) seList.get(1); + Attributes attr = se.getAttributes(); + assertNotNull(attr); + assertEquals("1", attr.getValue("increment")); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/event/InPlayFireTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/event/InPlayFireTest.java index a3862c143f30a5a266a3befc5a4332010ffcc439..448e9987b0f625f08fc9080b680b7ba2c5b85f09 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/event/InPlayFireTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/event/InPlayFireTest.java @@ -1,78 +1,78 @@ -/** - * 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.joran.event; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.HashMap; - -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.joran.TrivialConfigurator; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.util.CoreTestConstants; - -public class InPlayFireTest { - - Context context = new ContextBase(); - HashMap rulesMap = new HashMap(); - - @Test - public void testBasic() throws JoranException { - ListenAction listenAction = new ListenAction(); - - rulesMap.put(new Pattern("fire"), listenAction); - TrivialConfigurator gc = new TrivialConfigurator(rulesMap); - - gc.setContext(context); - gc.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + "input/joran/fire1.xml"); - - //for(SaxEvent se: listenAction.getSeList()) { - // System.out.println(se); - //} - assertEquals(5, listenAction.getSeList().size()); - assertTrue(listenAction.getSeList().get(0) instanceof StartEvent); - assertTrue(listenAction.getSeList().get(1) instanceof StartEvent); - assertTrue(listenAction.getSeList().get(2) instanceof BodyEvent); - assertTrue(listenAction.getSeList().get(3) instanceof EndEvent); - } - - @Test - public void testReplay() throws JoranException { - ListenAction listenAction = new ListenAction(); - - rulesMap.put(new Pattern("fire"), listenAction); - TrivialConfigurator gc = new TrivialConfigurator(rulesMap); - - gc.setContext(context); - gc.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + "input/joran/fire1.xml"); - -// for(SaxEvent se: listenAction.getSeList()) { -// System.out.println(se); -// } - assertEquals(5, listenAction.getSeList().size()); - assertTrue(listenAction.getSeList().get(0) instanceof StartEvent); - assertTrue(listenAction.getSeList().get(1) instanceof StartEvent); - assertTrue(listenAction.getSeList().get(2) instanceof BodyEvent); - assertTrue(listenAction.getSeList().get(3) instanceof EndEvent); - } - - - -} +/** + * 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.joran.event; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; + +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.joran.TrivialConfigurator; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.util.CoreTestConstants; + +public class InPlayFireTest { + + Context context = new ContextBase(); + HashMap rulesMap = new HashMap(); + + @Test + public void testBasic() throws JoranException { + ListenAction listenAction = new ListenAction(); + + rulesMap.put(new Pattern("fire"), listenAction); + TrivialConfigurator gc = new TrivialConfigurator(rulesMap); + + gc.setContext(context); + gc.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + "input/joran/fire1.xml"); + + //for(SaxEvent se: listenAction.getSeList()) { + // System.out.println(se); + //} + assertEquals(5, listenAction.getSeList().size()); + assertTrue(listenAction.getSeList().get(0) instanceof StartEvent); + assertTrue(listenAction.getSeList().get(1) instanceof StartEvent); + assertTrue(listenAction.getSeList().get(2) instanceof BodyEvent); + assertTrue(listenAction.getSeList().get(3) instanceof EndEvent); + } + + @Test + public void testReplay() throws JoranException { + ListenAction listenAction = new ListenAction(); + + rulesMap.put(new Pattern("fire"), listenAction); + TrivialConfigurator gc = new TrivialConfigurator(rulesMap); + + gc.setContext(context); + gc.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + "input/joran/fire1.xml"); + +// for(SaxEvent se: listenAction.getSeList()) { +// System.out.println(se); +// } + assertEquals(5, listenAction.getSeList().size()); + assertTrue(listenAction.getSeList().get(0) instanceof StartEvent); + assertTrue(listenAction.getSeList().get(1) instanceof StartEvent); + assertTrue(listenAction.getSeList().get(2) instanceof BodyEvent); + assertTrue(listenAction.getSeList().get(3) instanceof EndEvent); + } + + + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/event/ListenAction.java b/logback-core/src/test/java/ch/qos/logback/core/joran/event/ListenAction.java index 94bc079725d1b7b402caabb8134a5dd35e4d4ba2..5763bb8cce6432bd565a52a085c669382d234278 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/event/ListenAction.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/event/ListenAction.java @@ -1,49 +1,49 @@ -/** - * 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.joran.event; - -import java.util.ArrayList; -import java.util.List; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; - -public class ListenAction extends Action implements InPlayListener { - - List seList = new ArrayList(); - - @Override - public void begin(InterpretationContext ec, String name, Attributes attributes) - throws ActionException { - ec.addInPlayListener(this); - } - - @Override - public void end(InterpretationContext ec, String name) throws ActionException { - ec.removeInPlayListener(this); - - } - - public void inPlay(SaxEvent event) { - seList.add(event); - } - - public List getSeList() { - return seList; - } - -} +/** + * 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.joran.event; + +import java.util.ArrayList; +import java.util.List; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; + +public class ListenAction extends Action implements InPlayListener { + + List seList = new ArrayList(); + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + ec.addInPlayListener(this); + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + ec.removeInPlayListener(this); + + } + + public void inPlay(SaxEvent event) { + seList.add(event); + } + + public List getSeList() { + return seList; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/event/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/event/PackageTest.java index 0f016c9a713180aa6443fe8b85f505440924bba3..260c5c4ccf4b7bd0d43f07101395f3d41186e859 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/event/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/event/PackageTest.java @@ -1,23 +1,23 @@ -/** - * 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.joran.event; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({EventRecorderTest.class, InPlayFireTest.class}) -public class PackageTest { -} +/** + * 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.joran.event; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({EventRecorderTest.class, InPlayFireTest.class}) +public class PackageTest { +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/Cake.java b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/Cake.java index 6a22470492177e6a92ee143b0e8f6e3806da28f3..4c6c24f310c15134dd9440b571c0df3dcbca7479 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/Cake.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/Cake.java @@ -1,35 +1,35 @@ -/** - * 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.joran.implicitAction; - -public class Cake { - - String type; - int code; - - public String getType() { - return type; - } - public void setType(String type) { - this.type = type; - } - public int getCode() { - return code; - } - public void setCode(int code) { - this.code = code; - } - - -} +/** + * 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.joran.implicitAction; + +public class Cake { + + String type; + int code; + + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + public int getCode() { + return code; + } + public void setCode(int code) { + this.code = code; + } + + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/Fruit.java b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/Fruit.java index e8bd9b0b23d4d3511784a831c53d0012bbcab0a0..ebe311befbb422f54a3ba806e2c30f07dca37fb4 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/Fruit.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/Fruit.java @@ -1,43 +1,43 @@ -/** - * 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.joran.implicitAction; - -import java.util.ArrayList; -import java.util.List; - -public class Fruit { - - String name; - List textList = new ArrayList(); - List cakeList = new ArrayList(); - - public Fruit() { - } - - public void setName(String n) { - this.name = n; - } - - public String getName() { - return name; - } - - public void addText(String s) { - textList.add(s); - } - - public void addCake(Cake c) { - cakeList.add(c); - } -} +/** + * 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.joran.implicitAction; + +import java.util.ArrayList; +import java.util.List; + +public class Fruit { + + String name; + List textList = new ArrayList(); + List cakeList = new ArrayList(); + + public Fruit() { + } + + public void setName(String n) { + this.name = n; + } + + public String getName() { + return name; + } + + public void addText(String s) { + textList.add(s); + } + + public void addCake(Cake c) { + cakeList.add(c); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/FruitContext.java b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/FruitContext.java index 2f72fb0b2fbab6eb2e4d7c693649fc6504496200..0a0390aa12953f9072b9cfaf67f1e7a33d1b9896 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/FruitContext.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/FruitContext.java @@ -1,36 +1,36 @@ -/** - * 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.joran.implicitAction; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.core.ContextBase; - -public class FruitContext extends ContextBase { - - List fruitList = new ArrayList(); - - public void addFruit(Fruit fs) { - fruitList.add(fs); - } - - public List getFruitList() { - return fruitList; - } - - public void setFruitShellList(List fruitList) { - this.fruitList = fruitList; - } -} +/** + * 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.joran.implicitAction; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.core.ContextBase; + +public class FruitContext extends ContextBase { + + List fruitList = new ArrayList(); + + public void addFruit(Fruit fs) { + fruitList.add(fs); + } + + public List getFruitList() { + return fruitList; + } + + public void setFruitShellList(List fruitList) { + this.fruitList = fruitList; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/FruitContextAction.java b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/FruitContextAction.java index 0e6f4d684749da28aba95d6c7a784534dccf60c5..e775647e40a8498919995f19f1b253d2a7318745 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/FruitContextAction.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/FruitContextAction.java @@ -1,64 +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.joran.implicitAction; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; - -public class FruitContextAction extends Action { - - private boolean inError = false; - - - @Override - public void begin(InterpretationContext ec, String name, Attributes attributes) - throws ActionException { - - inError = false; - - try { - ec.pushObject(context); - } catch (Exception oops) { - inError = true; - addError( - "Could not push context", oops); - throw new ActionException(oops); - } - } - - @Override - public void end(InterpretationContext ec, String name) throws ActionException { - if (inError) { - return; - } - - Object o = ec.peekObject(); - - if (o != context) { - addWarn( - "The object at the of the stack is not the context named [" - + context.getName() + "] pushed earlier."); - } else { - addInfo( - "Popping context named [" + context.getName() - + "] from the object stack"); - ec.popObject(); - } - } - - -} +/** + * 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.joran.implicitAction; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; + +public class FruitContextAction extends Action { + + private boolean inError = false; + + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + + inError = false; + + try { + ec.pushObject(context); + } catch (Exception oops) { + inError = true; + addError( + "Could not push context", oops); + throw new ActionException(oops); + } + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + if (inError) { + return; + } + + Object o = ec.peekObject(); + + if (o != context) { + addWarn( + "The object at the of the stack is not the context named [" + + context.getName() + "] pushed earlier."); + } else { + addInfo( + "Popping context named [" + context.getName() + + "] from the object stack"); + ec.popObject(); + } + } + + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/ImplicitActionTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/ImplicitActionTest.java index ab77db22ee702d44a1f8868ee3891757490691f1..a0407370b5153971dcb15f49c155501b44610f69 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/ImplicitActionTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/ImplicitActionTest.java @@ -1,129 +1,129 @@ -/** - * 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.joran.implicitAction; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.util.HashMap; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.joran.SimpleConfigurator; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.util.CoreTestConstants; -import ch.qos.logback.core.util.StatusPrinter; - -public class ImplicitActionTest { - - static final String IMPLCIT_DIR = CoreTestConstants.TEST_DIR_PREFIX - + "input/joran/implicitAction/"; - - FruitContext fruitContext = new FruitContext(); - SimpleConfigurator simpleConfigurator; - - public ImplicitActionTest() { - } - - @Before - public void setUp() throws Exception { - fruitContext.setName("fruits"); - HashMap rulesMap = new HashMap(); - rulesMap.put(new Pattern("/context/"), new FruitContextAction()); - simpleConfigurator = new SimpleConfigurator(rulesMap); - simpleConfigurator.setContext(fruitContext); - } - - void verifyFruit() { - List fList = fruitContext.getFruitList(); - assertNotNull(fList); - assertEquals(1, fList.size()); - - Fruit f0 = fList.get(0); - assertEquals("blue", f0.getName()); - assertEquals(2, f0.textList.size()); - assertEquals("hello", f0.textList.get(0)); - assertEquals("world", f0.textList.get(1)); - } - - @Test - public void nestedComplex() throws Exception { - try { - simpleConfigurator.doConfigure(IMPLCIT_DIR + "nestedComplex.xml"); - verifyFruit(); - - } catch (Exception je) { - StatusPrinter.print(fruitContext); - throw je; - } - } - - @Test - public void nestedComplexWithoutClassAtrribute() throws Exception { - try { - simpleConfigurator.doConfigure(IMPLCIT_DIR - + "nestedComplexWithoutClassAtrribute.xml"); - - verifyFruit(); - - } catch (Exception je) { - StatusPrinter.print(fruitContext); - throw je; - } - } - - - void verifyFruitList() { - List fList = fruitContext.getFruitList(); - assertNotNull(fList); - assertEquals(1, fList.size()); - - Fruit f0 = fList.get(0); - assertEquals(2, f0.cakeList.size()); - - Cake cakeA = f0.cakeList.get(0); - assertEquals("A", cakeA.getType()); - - Cake cakeB = f0.cakeList.get(1); - assertEquals("B", cakeB.getType()); - } - @Test - public void nestedComplexCollection() throws Exception { - try { - simpleConfigurator.doConfigure(IMPLCIT_DIR - + "nestedComplexCollection.xml"); - verifyFruitList(); - } catch (Exception je) { - StatusPrinter.print(fruitContext); - throw je; - } - } - - - @Test - public void nestedComplexCollectionWithoutClassAtrribute() throws Exception { - try { - simpleConfigurator.doConfigure(IMPLCIT_DIR - + "nestedComplexCollectionWithoutClassAtrribute.xml"); - verifyFruitList(); - } catch (Exception je) { - StatusPrinter.print(fruitContext); - throw je; - } - } - -} +/** + * 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.joran.implicitAction; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.HashMap; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.joran.SimpleConfigurator; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.util.CoreTestConstants; +import ch.qos.logback.core.util.StatusPrinter; + +public class ImplicitActionTest { + + static final String IMPLCIT_DIR = CoreTestConstants.TEST_DIR_PREFIX + + "input/joran/implicitAction/"; + + FruitContext fruitContext = new FruitContext(); + SimpleConfigurator simpleConfigurator; + + public ImplicitActionTest() { + } + + @Before + public void setUp() throws Exception { + fruitContext.setName("fruits"); + HashMap rulesMap = new HashMap(); + rulesMap.put(new Pattern("/context/"), new FruitContextAction()); + simpleConfigurator = new SimpleConfigurator(rulesMap); + simpleConfigurator.setContext(fruitContext); + } + + void verifyFruit() { + List fList = fruitContext.getFruitList(); + assertNotNull(fList); + assertEquals(1, fList.size()); + + Fruit f0 = fList.get(0); + assertEquals("blue", f0.getName()); + assertEquals(2, f0.textList.size()); + assertEquals("hello", f0.textList.get(0)); + assertEquals("world", f0.textList.get(1)); + } + + @Test + public void nestedComplex() throws Exception { + try { + simpleConfigurator.doConfigure(IMPLCIT_DIR + "nestedComplex.xml"); + verifyFruit(); + + } catch (Exception je) { + StatusPrinter.print(fruitContext); + throw je; + } + } + + @Test + public void nestedComplexWithoutClassAtrribute() throws Exception { + try { + simpleConfigurator.doConfigure(IMPLCIT_DIR + + "nestedComplexWithoutClassAtrribute.xml"); + + verifyFruit(); + + } catch (Exception je) { + StatusPrinter.print(fruitContext); + throw je; + } + } + + + void verifyFruitList() { + List fList = fruitContext.getFruitList(); + assertNotNull(fList); + assertEquals(1, fList.size()); + + Fruit f0 = fList.get(0); + assertEquals(2, f0.cakeList.size()); + + Cake cakeA = f0.cakeList.get(0); + assertEquals("A", cakeA.getType()); + + Cake cakeB = f0.cakeList.get(1); + assertEquals("B", cakeB.getType()); + } + @Test + public void nestedComplexCollection() throws Exception { + try { + simpleConfigurator.doConfigure(IMPLCIT_DIR + + "nestedComplexCollection.xml"); + verifyFruitList(); + } catch (Exception je) { + StatusPrinter.print(fruitContext); + throw je; + } + } + + + @Test + public void nestedComplexCollectionWithoutClassAtrribute() throws Exception { + try { + simpleConfigurator.doConfigure(IMPLCIT_DIR + + "nestedComplexCollectionWithoutClassAtrribute.xml"); + verifyFruitList(); + } catch (Exception je) { + StatusPrinter.print(fruitContext); + throw je; + } + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/PackageTest.java index 5f52f4d692eeb79f08d711864ee126e783dc805f..f31ec29997b82a78982c5137c997c7bfd26693fd 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/PackageTest.java @@ -1,23 +1,23 @@ -/** - * 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.joran.implicitAction; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({ImplicitActionTest.class}) -public class PackageTest { -} +/** + * 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.joran.implicitAction; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ImplicitActionTest.class}) +public class PackageTest { +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/Fruit.java b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/Fruit.java index 28069b8899ae68a239feda3b070a99f289bc0424..8ba620952686a36791d2a091de272126a9be4b38 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/Fruit.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/Fruit.java @@ -1,50 +1,50 @@ -/** - * 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.joran.replay; - -import java.util.ArrayList; -import java.util.List; - -public class Fruit { - - String name; - List textList = new ArrayList(); - - public Fruit() { - // System.out.println("Fruit constructor called"); - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public String toString() { - final String TAB = " "; - - StringBuilder retValue = new StringBuilder(); - - retValue.append("xFruit ( ").append("name = ").append(this.name).append(TAB).append(" )"); - - return retValue.toString(); - } - - public void addText(String s) { - textList.add(s); - } - -} +/** + * 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.joran.replay; + +import java.util.ArrayList; +import java.util.List; + +public class Fruit { + + String name; + List textList = new ArrayList(); + + public Fruit() { + // System.out.println("Fruit constructor called"); + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public String toString() { + final String TAB = " "; + + StringBuilder retValue = new StringBuilder(); + + retValue.append("xFruit ( ").append("name = ").append(this.name).append(TAB).append(" )"); + + return retValue.toString(); + } + + public void addText(String s) { + textList.add(s); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurationTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurationTest.java index 55e9e5d85d9a664ac0fb6cabedca8fde53b97445..74cb7b88e591f3d929ae939ee27662ab48d6cc60 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurationTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurationTest.java @@ -1,114 +1,114 @@ -/** - * 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.joran.replay; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.HashMap; -import java.util.List; - -import org.junit.Test; - -import ch.qos.logback.core.joran.SimpleConfigurator; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.action.NOPAction; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.util.CoreTestConstants; -import ch.qos.logback.core.util.StatusPrinter; - -/** - * The Fruit* code is intended to test Joran's replay capability - * */ -public class FruitConfigurationTest { - - FruitContext fruitContext = new FruitContext(); - - public List doFirstPart(String filename) throws Exception { - - try { - HashMap rulesMap = new HashMap(); - rulesMap.put(new Pattern("group/fruitShell"), new FruitShellAction()); - rulesMap.put(new Pattern("group/fruitShell/fruit"), - new FruitFactoryAction()); - rulesMap.put(new Pattern("group/fruitShell/fruit/*"), new NOPAction()); - SimpleConfigurator simpleConfigurator = new SimpleConfigurator(rulesMap); - - simpleConfigurator.setContext(fruitContext); - - simpleConfigurator.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + "input/joran/replay/" - + filename); - - return fruitContext.getFruitShellList(); - } catch (Exception je) { - StatusPrinter.print(fruitContext); - throw je; - } - } - - @Test - public void fruit1() throws Exception { - List fsList = doFirstPart("fruit1.xml"); - assertNotNull(fsList); - assertEquals(1, fsList.size()); - - FruitShell fs0 = fsList.get(0); - assertNotNull(fs0); - assertEquals("fs0", fs0.getName()); - Fruit fruit0 = fs0.fruitFactory.buildFruit(); - assertTrue(fruit0 instanceof Fruit); - assertEquals("blue", fruit0.getName()); - } - - - @Test - public void fruit2() throws Exception { - List fsList = doFirstPart("fruit2.xml"); - assertNotNull(fsList); - assertEquals(2, fsList.size()); - - FruitShell fs0 = fsList.get(0); - assertNotNull(fs0); - assertEquals("fs0", fs0.getName()); - Fruit fruit0 = fs0.fruitFactory.buildFruit(); - assertTrue(fruit0 instanceof Fruit); - assertEquals("blue", fruit0.getName()); - - FruitShell fs1 = fsList.get(1); - assertNotNull(fs1); - assertEquals("fs1", fs1.getName()); - Fruit fruit1 = fs1.fruitFactory.buildFruit(); - assertTrue(fruit1 instanceof WeightytFruit); - assertEquals("orange", fruit1.getName()); - assertEquals(1.2, ((WeightytFruit) fruit1).getWeight(), 0.01); - } - - @Test - public void withSubst() throws Exception { - List fsList = doFirstPart("fruitWithSubst.xml"); - assertNotNull(fsList); - assertEquals(1, fsList.size()); - - FruitShell fs0 = fsList.get(0); - assertNotNull(fs0); - assertEquals("fs0", fs0.getName()); - int oldCount = FruitFactory.count; - Fruit fruit0 = fs0.fruitFactory.buildFruit(); - assertTrue(fruit0 instanceof WeightytFruit); - assertEquals("orange-" + oldCount, fruit0.getName()); - assertEquals(1.2, ((WeightytFruit) fruit0).getWeight(), 0.01); - } - -} +/** + * 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.joran.replay; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.List; + +import org.junit.Test; + +import ch.qos.logback.core.joran.SimpleConfigurator; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.action.NOPAction; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.util.CoreTestConstants; +import ch.qos.logback.core.util.StatusPrinter; + +/** + * The Fruit* code is intended to test Joran's replay capability + * */ +public class FruitConfigurationTest { + + FruitContext fruitContext = new FruitContext(); + + public List doFirstPart(String filename) throws Exception { + + try { + HashMap rulesMap = new HashMap(); + rulesMap.put(new Pattern("group/fruitShell"), new FruitShellAction()); + rulesMap.put(new Pattern("group/fruitShell/fruit"), + new FruitFactoryAction()); + rulesMap.put(new Pattern("group/fruitShell/fruit/*"), new NOPAction()); + SimpleConfigurator simpleConfigurator = new SimpleConfigurator(rulesMap); + + simpleConfigurator.setContext(fruitContext); + + simpleConfigurator.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + "input/joran/replay/" + + filename); + + return fruitContext.getFruitShellList(); + } catch (Exception je) { + StatusPrinter.print(fruitContext); + throw je; + } + } + + @Test + public void fruit1() throws Exception { + List fsList = doFirstPart("fruit1.xml"); + assertNotNull(fsList); + assertEquals(1, fsList.size()); + + FruitShell fs0 = fsList.get(0); + assertNotNull(fs0); + assertEquals("fs0", fs0.getName()); + Fruit fruit0 = fs0.fruitFactory.buildFruit(); + assertTrue(fruit0 instanceof Fruit); + assertEquals("blue", fruit0.getName()); + } + + + @Test + public void fruit2() throws Exception { + List fsList = doFirstPart("fruit2.xml"); + assertNotNull(fsList); + assertEquals(2, fsList.size()); + + FruitShell fs0 = fsList.get(0); + assertNotNull(fs0); + assertEquals("fs0", fs0.getName()); + Fruit fruit0 = fs0.fruitFactory.buildFruit(); + assertTrue(fruit0 instanceof Fruit); + assertEquals("blue", fruit0.getName()); + + FruitShell fs1 = fsList.get(1); + assertNotNull(fs1); + assertEquals("fs1", fs1.getName()); + Fruit fruit1 = fs1.fruitFactory.buildFruit(); + assertTrue(fruit1 instanceof WeightytFruit); + assertEquals("orange", fruit1.getName()); + assertEquals(1.2, ((WeightytFruit) fruit1).getWeight(), 0.01); + } + + @Test + public void withSubst() throws Exception { + List fsList = doFirstPart("fruitWithSubst.xml"); + assertNotNull(fsList); + assertEquals(1, fsList.size()); + + FruitShell fs0 = fsList.get(0); + assertNotNull(fs0); + assertEquals("fs0", fs0.getName()); + int oldCount = FruitFactory.count; + Fruit fruit0 = fs0.fruitFactory.buildFruit(); + assertTrue(fruit0 instanceof WeightytFruit); + assertEquals("orange-" + oldCount, fruit0.getName()); + assertEquals(1.2, ((WeightytFruit) fruit0).getWeight(), 0.01); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurator.java b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurator.java index 652874ccc6cde81b0afae370382fb9c9b1f4c26f..dd9efefd4c8c4717891b19c3f8cf6cb116abd7eb 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurator.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurator.java @@ -1,62 +1,62 @@ -/** - * 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.joran.replay; - -import java.util.List; - -import ch.qos.logback.core.joran.GenericConfigurator; -import ch.qos.logback.core.joran.action.NOPAction; -import ch.qos.logback.core.joran.action.NestedComplexPropertyIA; -import ch.qos.logback.core.joran.action.NestedBasicPropertyIA; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.joran.spi.EventPlayer; -import ch.qos.logback.core.joran.spi.Interpreter; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.joran.spi.RuleStore; - -public class FruitConfigurator extends GenericConfigurator { - - FruitFactory ff; - public FruitConfigurator(FruitFactory ff) { - this.ff = ff; - } - - @Override - final public void doConfigure(final List eventList) - throws JoranException { - buildInterpreter(); - interpreter.getInterpretationContext().pushObject(ff); - EventPlayer player = new EventPlayer(interpreter); - player.play(eventList); - } - - @Override - protected void addImplicitRules(Interpreter interpreter) { - NestedComplexPropertyIA nestedIA = new NestedComplexPropertyIA(); - nestedIA.setContext(context); - interpreter.addImplicitAction(nestedIA); - - NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA(); - nestedIA.setContext(context); - interpreter.addImplicitAction(nestedSimpleIA); - } - - - @Override - protected void addInstanceRules(RuleStore rs) { - rs.addRule(new Pattern("fruitShell"), new NOPAction()); - } - -} +/** + * 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.joran.replay; + +import java.util.List; + +import ch.qos.logback.core.joran.GenericConfigurator; +import ch.qos.logback.core.joran.action.NOPAction; +import ch.qos.logback.core.joran.action.NestedComplexPropertyIA; +import ch.qos.logback.core.joran.action.NestedBasicPropertyIA; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.EventPlayer; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.joran.spi.RuleStore; + +public class FruitConfigurator extends GenericConfigurator { + + FruitFactory ff; + public FruitConfigurator(FruitFactory ff) { + this.ff = ff; + } + + @Override + final public void doConfigure(final List eventList) + throws JoranException { + buildInterpreter(); + interpreter.getInterpretationContext().pushObject(ff); + EventPlayer player = new EventPlayer(interpreter); + player.play(eventList); + } + + @Override + protected void addImplicitRules(Interpreter interpreter) { + NestedComplexPropertyIA nestedIA = new NestedComplexPropertyIA(); + nestedIA.setContext(context); + interpreter.addImplicitAction(nestedIA); + + NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA(); + nestedIA.setContext(context); + interpreter.addImplicitAction(nestedSimpleIA); + } + + + @Override + protected void addInstanceRules(RuleStore rs) { + rs.addRule(new Pattern("fruitShell"), new NOPAction()); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitContext.java b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitContext.java index 5eda80d209f8c8850b13ba5e278e8195b334489e..80a33ad7b3c4fef3359f5f5a98fcb63eabfdc152 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitContext.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitContext.java @@ -1,36 +1,36 @@ -/** - * 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.joran.replay; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.core.ContextBase; - -public class FruitContext extends ContextBase { - - List fruitShellList = new ArrayList(); - - public void addFruitShell(FruitShell fs) { - fruitShellList.add(fs); - } - - public List getFruitShellList() { - return fruitShellList; - } - - public void setFruitShellList(List fruitShellList) { - this.fruitShellList = fruitShellList; - } -} +/** + * 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.joran.replay; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.core.ContextBase; + +public class FruitContext extends ContextBase { + + List fruitShellList = new ArrayList(); + + public void addFruitShell(FruitShell fs) { + fruitShellList.add(fs); + } + + public List getFruitShellList() { + return fruitShellList; + } + + public void setFruitShellList(List fruitShellList) { + this.fruitShellList = fruitShellList; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitFactory.java b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitFactory.java index 5fc955948a6eafb76b4f4d850e934e4f79c17373..edbbba6582746faa8a930fe39cd6915f3afe76a0 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitFactory.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitFactory.java @@ -1,69 +1,69 @@ -/** - * 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.joran.replay; - -import java.util.List; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.joran.spi.JoranException; - -public class FruitFactory { - - static int count = 0; - - private List eventList; - Fruit fruit; - - public void setFruit(Fruit fruit) { - this.fruit = fruit; - } - - public Fruit buildFruit() { - - Context context = new ContextBase(); - this.fruit = null; - context.putProperty("fruitKey", "orange-"+count); - // for next round - count++; - FruitConfigurator fruitConfigurator = new FruitConfigurator(this); - fruitConfigurator.setContext(context); - try { - fruitConfigurator.doConfigure(eventList); - } catch(JoranException je) { - je.printStackTrace(); - } - return fruit; - } - - public String toString() { - final String TAB = " "; - - StringBuilder retValue = new StringBuilder(); - - retValue.append("FruitFactory ( "); - if (eventList != null && eventList.size() > 0) { - retValue.append("event1 = ").append(eventList.get(0)).append(TAB); - } - retValue.append(" )"); - - return retValue.toString(); - } - - public void setEventList(List eventList) { - this.eventList = eventList; - } - -} +/** + * 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.joran.replay; + +import java.util.List; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.JoranException; + +public class FruitFactory { + + static int count = 0; + + private List eventList; + Fruit fruit; + + public void setFruit(Fruit fruit) { + this.fruit = fruit; + } + + public Fruit buildFruit() { + + Context context = new ContextBase(); + this.fruit = null; + context.putProperty("fruitKey", "orange-"+count); + // for next round + count++; + FruitConfigurator fruitConfigurator = new FruitConfigurator(this); + fruitConfigurator.setContext(context); + try { + fruitConfigurator.doConfigure(eventList); + } catch(JoranException je) { + je.printStackTrace(); + } + return fruit; + } + + public String toString() { + final String TAB = " "; + + StringBuilder retValue = new StringBuilder(); + + retValue.append("FruitFactory ( "); + if (eventList != null && eventList.size() > 0) { + retValue.append("event1 = ").append(eventList.get(0)).append(TAB); + } + retValue.append(" )"); + + return retValue.toString(); + } + + public void setEventList(List eventList) { + this.eventList = eventList; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitFactoryAction.java b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitFactoryAction.java index 745106bbba848bd41d512d51e59ba2e85076e4d1..d42195c9d7adac66536ea36b07f6b0dcc1e936d3 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitFactoryAction.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitFactoryAction.java @@ -1,58 +1,58 @@ -/** - * 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.joran.replay; - -import java.util.ArrayList; -import java.util.List; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.event.InPlayListener; -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; - -public class FruitFactoryAction extends Action implements InPlayListener { - - List seList = new ArrayList(); - - @Override - public void begin(InterpretationContext ec, String name, Attributes attributes) - throws ActionException { - ec.addInPlayListener(this); - } - - @Override - public void end(InterpretationContext ec, String name) throws ActionException { - ec.removeInPlayListener(this); - - Object o = ec.peekObject(); - if(o instanceof FruitShell) { - FruitShell fs = (FruitShell) o; - FruitFactory fruitFactory = new FruitFactory(); - fruitFactory.setEventList(new ArrayList(seList)); - fs.setFruitFactory(fruitFactory); - } - } - - public void inPlay(SaxEvent event) { - seList.add(event); - } - - public List getSeList() { - return seList; - } - -} +/** + * 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.joran.replay; + +import java.util.ArrayList; +import java.util.List; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.event.InPlayListener; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; + +public class FruitFactoryAction extends Action implements InPlayListener { + + List seList = new ArrayList(); + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + ec.addInPlayListener(this); + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + ec.removeInPlayListener(this); + + Object o = ec.peekObject(); + if(o instanceof FruitShell) { + FruitShell fs = (FruitShell) o; + FruitFactory fruitFactory = new FruitFactory(); + fruitFactory.setEventList(new ArrayList(seList)); + fs.setFruitFactory(fruitFactory); + } + } + + public void inPlay(SaxEvent event) { + seList.add(event); + } + + public List getSeList() { + return seList; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitShell.java b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitShell.java index 399c52e527e9ce25ac0f8a8c4a75bc79e4edcc5d..49bcb768f2295a8c23ffe3f2eba64bdb80cb2fef 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitShell.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitShell.java @@ -1,62 +1,62 @@ -/** - * 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.joran.replay; - -import ch.qos.logback.core.spi.ContextAwareBase; - -public class FruitShell extends ContextAwareBase { - - FruitFactory fruitFactory; - String name; - - public void setFruitFactory(FruitFactory fruitFactory) { - this.fruitFactory = fruitFactory; - } - - void testFruit() { - - Fruit fruit = fruitFactory.buildFruit(); - System.out.println(fruit); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - /** - * Constructs a String with all attributes - * in name = value format. - * - * @return a String representation - * of this object. - */ - public String toString() - { - final String TAB = " "; - - String retValue = ""; - - retValue = "FruitShell ( " - + "fruitFactory = " + this.fruitFactory + TAB - + "name = " + this.name + TAB - + " )"; - - return retValue; - } - -} +/** + * 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.joran.replay; + +import ch.qos.logback.core.spi.ContextAwareBase; + +public class FruitShell extends ContextAwareBase { + + FruitFactory fruitFactory; + String name; + + public void setFruitFactory(FruitFactory fruitFactory) { + this.fruitFactory = fruitFactory; + } + + void testFruit() { + + Fruit fruit = fruitFactory.buildFruit(); + System.out.println(fruit); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + /** + * Constructs a String with all attributes + * in name = value format. + * + * @return a String representation + * of this object. + */ + public String toString() + { + final String TAB = " "; + + String retValue = ""; + + retValue = "FruitShell ( " + + "fruitFactory = " + this.fruitFactory + TAB + + "name = " + this.name + TAB + + " )"; + + return retValue; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitShellAction.java b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitShellAction.java index ace9c6debb169237504a2d836e1256b818b5ff82..aaa9fc5cb5e541718a4057d62cd8e5280d3be356 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitShellAction.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitShellAction.java @@ -1,87 +1,87 @@ -/** - * 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.joran.replay; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.InterpretationContext; -import ch.qos.logback.core.util.OptionHelper; - -/** - * The Fruit* code is intended to test Joran's replay capability - * */ -public class FruitShellAction extends Action { - - FruitShell fruitShell; - private boolean inError = false; - - - @Override - public void begin(InterpretationContext ec, String name, Attributes attributes) - throws ActionException { - - // We are just beginning, reset variables - fruitShell = new FruitShell(); - inError = false; - - try { - - - fruitShell.setContext(context); - - String shellName = attributes.getValue(NAME_ATTRIBUTE); - - if (OptionHelper.isEmpty(shellName)) { - addWarn( - "No appender name given for fruitShell]."); - } else { - fruitShell.setName(shellName); - addInfo("FruitShell named as [" + shellName + "]"); - } - - ec.pushObject(fruitShell); - } catch (Exception oops) { - inError = true; - addError( - "Could not create an FruitShell", oops); - throw new ActionException(oops); - } - } - - @Override - public void end(InterpretationContext ec, String name) throws ActionException { - if (inError) { - return; - } - - Object o = ec.peekObject(); - - if (o != fruitShell) { - addWarn( - "The object at the of the stack is not the fruitShell named [" - + fruitShell.getName() + "] pushed earlier."); - } else { - addInfo( - "Popping fruitSHell named [" + fruitShell.getName() - + "] from the object stack"); - ec.popObject(); - FruitContext fruitContext = (FruitContext) ec.getContext(); - fruitContext.addFruitShell(fruitShell); - } - } - - -} +/** + * 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.joran.replay; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; + +/** + * The Fruit* code is intended to test Joran's replay capability + * */ +public class FruitShellAction extends Action { + + FruitShell fruitShell; + private boolean inError = false; + + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + + // We are just beginning, reset variables + fruitShell = new FruitShell(); + inError = false; + + try { + + + fruitShell.setContext(context); + + String shellName = attributes.getValue(NAME_ATTRIBUTE); + + if (OptionHelper.isEmpty(shellName)) { + addWarn( + "No appender name given for fruitShell]."); + } else { + fruitShell.setName(shellName); + addInfo("FruitShell named as [" + shellName + "]"); + } + + ec.pushObject(fruitShell); + } catch (Exception oops) { + inError = true; + addError( + "Could not create an FruitShell", oops); + throw new ActionException(oops); + } + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + if (inError) { + return; + } + + Object o = ec.peekObject(); + + if (o != fruitShell) { + addWarn( + "The object at the of the stack is not the fruitShell named [" + + fruitShell.getName() + "] pushed earlier."); + } else { + addInfo( + "Popping fruitSHell named [" + fruitShell.getName() + + "] from the object stack"); + ec.popObject(); + FruitContext fruitContext = (FruitContext) ec.getContext(); + fruitContext.addFruitShell(fruitShell); + } + } + + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/PackageTest.java index cdf9ef355e52b572f5fedc43f155e1837a8d46d1..e61740f11b9f87de8bb5c6d282fd59c9762d9593 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/PackageTest.java @@ -1,24 +1,24 @@ -/** - * 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.joran.replay; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({FruitConfigurationTest.class}) -public class PackageTest { - -} +/** + * 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.joran.replay; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({FruitConfigurationTest.class}) +public class PackageTest { + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/WeightytFruit.java b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/WeightytFruit.java index cd97b829ce8a9c1c71ac05caf9e7e7ca21ef4d60..3bc4eac8f01e83569452f822be5d58a0cc3d9c88 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/replay/WeightytFruit.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/replay/WeightytFruit.java @@ -1,29 +1,29 @@ -/** - * 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.joran.replay; - -public class WeightytFruit extends Fruit { - - double weight; - - public double getWeight() { - return weight; - } - - public void setWeight(double weight) { - this.weight = weight; - } - - -} +/** + * 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.joran.replay; + +public class WeightytFruit extends Fruit { + + double weight; + + public double getWeight() { + return weight; + } + + public void setWeight(double weight) { + this.weight = weight; + } + + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinator.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinator.java index 0cb13d30e3327628f5e5131a5e39ba53298694b4..519422ee816a0559691311cfa8d7dd6990da691e 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinator.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinator.java @@ -1,103 +1,103 @@ -/** - * 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.joran.spi; - -import java.util.ArrayList; -import java.util.List; - -public class CaseCombinator { - - - List combinations(String in) { - int length = in.length(); - List permutationsList = new ArrayList(); - - int totalCombinations = computeTotalNumerOfCombinations(in, length); - - for (int j = 0; j < totalCombinations; j++) { - StringBuilder newCombination = new StringBuilder(); - int pos = 0; - for (int i = 0; i < length; i++) { - char c = in.charAt(i); - if (isEnglishLetter(c)) { - c = permute(c, j, pos); - pos++; - } - newCombination.append(c); - } - permutationsList.add(newCombination.toString()); - } - return permutationsList; - - } - - private char permute(char c, int permutation, int position) { - int mask = 1 << position; - boolean shouldBeInUpperCase = (permutation & mask) != 0; - boolean isEffectivelyUpperCase = isUpperCase(c); - if (shouldBeInUpperCase && !isEffectivelyUpperCase) - return toUpperCase(c); - if (!shouldBeInUpperCase && isEffectivelyUpperCase) - return toLowerCase(c); - return c; - } - - private int computeTotalNumerOfCombinations(String in, int length) { - int count = 0; - for (int i = 0; i < length; i++) { - char c = in.charAt(i); - if (isEnglishLetter(c)) - count++; - } - // return 2^count (2 to the power of count) - return (1 << count); - } - - private char toUpperCase(char c) { - if ('A' <= c && c <= 'Z') { - return c; - } - if ('a' <= c && c <= 'z') { - int ci = c; - return (char) (ci + 'A' - 'a'); - } - // code should never reach this point - return c; - } - - private char toLowerCase(char c) { - if ('a' <= c && c <= 'z') { - return c; - } - if ('A' <= c && c <= 'Z') { - int ci = c; - return (char) (ci + 'a' - 'A'); - } - // code should never reach this point - return c; - } - - private boolean isEnglishLetter(char c) { - if ('a' <= c && c <= 'z') - return true; - - if ('A' <= c && c <= 'Z') - return true; - return false; - } - - private boolean isUpperCase(char c) { - return ('A' <= c && c <= 'Z'); - } -} +/** + * 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.joran.spi; + +import java.util.ArrayList; +import java.util.List; + +public class CaseCombinator { + + + List combinations(String in) { + int length = in.length(); + List permutationsList = new ArrayList(); + + int totalCombinations = computeTotalNumerOfCombinations(in, length); + + for (int j = 0; j < totalCombinations; j++) { + StringBuilder newCombination = new StringBuilder(); + int pos = 0; + for (int i = 0; i < length; i++) { + char c = in.charAt(i); + if (isEnglishLetter(c)) { + c = permute(c, j, pos); + pos++; + } + newCombination.append(c); + } + permutationsList.add(newCombination.toString()); + } + return permutationsList; + + } + + private char permute(char c, int permutation, int position) { + int mask = 1 << position; + boolean shouldBeInUpperCase = (permutation & mask) != 0; + boolean isEffectivelyUpperCase = isUpperCase(c); + if (shouldBeInUpperCase && !isEffectivelyUpperCase) + return toUpperCase(c); + if (!shouldBeInUpperCase && isEffectivelyUpperCase) + return toLowerCase(c); + return c; + } + + private int computeTotalNumerOfCombinations(String in, int length) { + int count = 0; + for (int i = 0; i < length; i++) { + char c = in.charAt(i); + if (isEnglishLetter(c)) + count++; + } + // return 2^count (2 to the power of count) + return (1 << count); + } + + private char toUpperCase(char c) { + if ('A' <= c && c <= 'Z') { + return c; + } + if ('a' <= c && c <= 'z') { + int ci = c; + return (char) (ci + 'A' - 'a'); + } + // code should never reach this point + return c; + } + + private char toLowerCase(char c) { + if ('a' <= c && c <= 'z') { + return c; + } + if ('A' <= c && c <= 'Z') { + int ci = c; + return (char) (ci + 'a' - 'A'); + } + // code should never reach this point + return c; + } + + private boolean isEnglishLetter(char c) { + if ('a' <= c && c <= 'z') + return true; + + if ('A' <= c && c <= 'Z') + return true; + return false; + } + + private boolean isUpperCase(char c) { + return ('A' <= c && c <= 'Z'); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinatorTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinatorTest.java index 5947a6d27ad00cffb3c288709e8134719da7d061..b3ebb0eb32fe585e3bc390dfcf16f0a35954fdd4 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinatorTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinatorTest.java @@ -1,53 +1,53 @@ -/** - * 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.joran.spi; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.junit.Test; - - -public class CaseCombinatorTest { - - CaseCombinator p = new CaseCombinator(); - - - @Test - public void smoke() { - CaseCombinator p = new CaseCombinator(); - - List result = p.combinations("a-B="); - - List witness = new ArrayList(); - witness.add("a-b="); - witness.add("A-b="); - witness.add("a-B="); - witness.add("A-B="); - assertEquals(witness, result); - } - - @Test - public void other() { - List result = p.combinations("aBCd"); - assertEquals(16, result.size()); - Set witness = new HashSet(result); - // check that there are no duplicates - assertEquals(16, witness.size()); - } -} +/** + * 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.joran.spi; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.Test; + + +public class CaseCombinatorTest { + + CaseCombinator p = new CaseCombinator(); + + + @Test + public void smoke() { + CaseCombinator p = new CaseCombinator(); + + List result = p.combinations("a-B="); + + List witness = new ArrayList(); + witness.add("a-b="); + witness.add("A-b="); + witness.add("a-B="); + witness.add("A-B="); + assertEquals(witness, result); + } + + @Test + public void other() { + List result = p.combinations("aBCd"); + assertEquals(16, result.size()); + Set witness = new HashSet(result); + // check that there are no duplicates + assertEquals(16, witness.size()); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/DefaultNestedComponentRegistryTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/DefaultNestedComponentRegistryTest.java index 0ab67e0518394bf1905640fc854c5c6e27e61e58..fca70f474aebfccbc31b4bf8d4e25f0789d36be9 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/DefaultNestedComponentRegistryTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/DefaultNestedComponentRegistryTest.java @@ -1,50 +1,50 @@ -/** - * 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.joran.spi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class DefaultNestedComponentRegistryTest { - - DefaultNestedComponentRegistry registry = new DefaultNestedComponentRegistry(); - - @Before - public void setUp() throws Exception { - - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void smoke() { - String propertyName = "window"; - registry.add(House.class, propertyName, Window.class); - Class result = registry.findDefaultComponentType(House.class, propertyName); - assertEquals(Window.class, result); - } - - @Test - public void absent() { - registry.add(House.class, "a", Window.class); - Class result = registry.findDefaultComponentType(House.class, "other"); - assertNull(result); - } -} +/** + * 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.joran.spi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class DefaultNestedComponentRegistryTest { + + DefaultNestedComponentRegistry registry = new DefaultNestedComponentRegistry(); + + @Before + public void setUp() throws Exception { + + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void smoke() { + String propertyName = "window"; + registry.add(House.class, propertyName, Window.class); + Class result = registry.findDefaultComponentType(House.class, propertyName); + assertEquals(Window.class, result); + } + + @Test + public void absent() { + registry.add(House.class, "a", Window.class); + Class result = registry.findDefaultComponentType(House.class, "other"); + assertNull(result); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/DoNotAutoStart.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/DoNotAutoStart.java index 35aaa5f1f9b7d2de0c9e75f3256136c06ac38839..cd9189e6e8fdc99564af644a50df21e2a5b6efdb 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/DoNotAutoStart.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/DoNotAutoStart.java @@ -1,34 +1,34 @@ -/** - * 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.joran.spi; - -import ch.qos.logback.core.spi.LifeCycle; - -@NoAutoStart -public class DoNotAutoStart implements LifeCycle { - - boolean started = false; - public boolean isStarted() { - return started; - } - - public void start() { - started = true; - } - - public void stop() { - started = false; - } - -} +/** + * 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.joran.spi; + +import ch.qos.logback.core.spi.LifeCycle; + +@NoAutoStart +public class DoNotAutoStart implements LifeCycle { + + boolean started = false; + public boolean isStarted() { + return started; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/NoAutoStartUtilTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/NoAutoStartUtilTest.java index 5421b7ff6a05a5af81a074311c083ff3daf90a04..d0de088c46c6125ee145e0a902f3bf2c68eee6e1 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/NoAutoStartUtilTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/NoAutoStartUtilTest.java @@ -1,36 +1,36 @@ -/** - * 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.joran.spi; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - - -public class NoAutoStartUtilTest { - - - @Test - public void commonObject() { - Object o = new Object(); - assertTrue(NoAutoStartUtil.notMarkedWithNoAutoStart(o)); - } - - @Test - public void markedWithNoAutoStart() { - DoNotAutoStart o = new DoNotAutoStart(); - assertFalse(NoAutoStartUtil.notMarkedWithNoAutoStart(o)); - } -} +/** + * 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.joran.spi; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + + +public class NoAutoStartUtilTest { + + + @Test + public void commonObject() { + Object o = new Object(); + assertTrue(NoAutoStartUtil.notMarkedWithNoAutoStart(o)); + } + + @Test + public void markedWithNoAutoStart() { + DoNotAutoStart o = new DoNotAutoStart(); + assertFalse(NoAutoStartUtil.notMarkedWithNoAutoStart(o)); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java index 17c91568edba8a8c02e17cc4b8acd483e4f98e76..07c691c5c16ab492be63e4a8432c8cd2cfe62d01 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java @@ -1,25 +1,25 @@ -/** - * 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.joran.spi; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses( { PatternTest.class, SimpleRuleStoreTest.class, - PropertySetterTest.class, NoAutoStartUtilTest.class, - DefaultNestedComponentRegistryTest.class, CaseCombinatorTest.class }) -public class PackageTest { -} +/** + * 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.joran.spi; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses( { PatternTest.class, SimpleRuleStoreTest.class, + PropertySetterTest.class, NoAutoStartUtilTest.class, + DefaultNestedComponentRegistryTest.class, CaseCombinatorTest.class }) +public class PackageTest { +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java index acf57def3ca820b9ba18ab252d9b3b8a621ff565..27198786f929f4f71302daff5d1c1bc50ad776af 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java @@ -1,179 +1,179 @@ -/** - * 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.joran.spi; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -/** - * Test pattern manipulation code. - * - * @author Ceki Gulcu - */ -public class PatternTest { - - @Test - public void test1() { - Pattern p = new Pattern("a"); - assertEquals(1, p.size()); - assertEquals("a", p.peekLast()); - assertEquals("a", p.get(0)); - } - - @Test - public void testSuffix() { - Pattern p = new Pattern("a/"); - assertEquals(1, p.size()); - assertEquals("a", p.peekLast()); - assertEquals("a", p.get(0)); - } - - @Test - public void test2() { - Pattern p = new Pattern("a/b"); - assertEquals(2, p.size()); - assertEquals("b", p.peekLast()); - assertEquals("a", p.get(0)); - assertEquals("b", p.get(1)); - } - - @Test - public void test3() { - Pattern p = new Pattern("a123/b1234/cvvsdf"); - assertEquals(3, p.size()); - assertEquals("a123", p.get(0)); - assertEquals("b1234", p.get(1)); - assertEquals("cvvsdf", p.get(2)); - } - - @Test - public void test4() { - Pattern p = new Pattern("/a123/b1234/cvvsdf"); - assertEquals(3, p.size()); - assertEquals("a123", p.get(0)); - assertEquals("b1234", p.get(1)); - assertEquals("cvvsdf", p.get(2)); - } - - @Test - public void test5() { - Pattern p = new Pattern("//a"); - assertEquals(1, p.size()); - assertEquals("a", p.get(0)); - } - - @Test - public void test6() { - Pattern p = new Pattern("//a//b"); - assertEquals(2, p.size()); - assertEquals("a", p.get(0)); - assertEquals("b", p.get(1)); - } - - - // test tail matching - @Test - public void testTailMatch() { - { - Pattern p = new Pattern("/a/b"); - Pattern rulePattern = new Pattern("*"); - assertEquals(0, p.getTailMatchLength(rulePattern)); - } - - { - Pattern p = new Pattern("/a"); - Pattern rulePattern = new Pattern("*/a"); - assertEquals(1, p.getTailMatchLength(rulePattern)); - } - - { - Pattern p = new Pattern("/A"); - Pattern rulePattern = new Pattern("*/a"); - assertEquals(1, p.getTailMatchLength(rulePattern)); - } - - { - Pattern p = new Pattern("/a"); - Pattern rulePattern = new Pattern("*/A"); - assertEquals(1, p.getTailMatchLength(rulePattern)); - } - - - { - Pattern p = new Pattern("/a/b"); - Pattern rulePattern = new Pattern("*/b"); - assertEquals(1, p.getTailMatchLength(rulePattern)); - } - - { - Pattern p = new Pattern("/a/B"); - Pattern rulePattern = new Pattern("*/b"); - assertEquals(1, p.getTailMatchLength(rulePattern)); - } - - { - Pattern p = new Pattern("/a/b/c"); - Pattern rulePattern = new Pattern("*/b/c"); - assertEquals(2, p.getTailMatchLength(rulePattern)); - } - } - - // test prefix matching - @Test - public void testPrefixMatch() { - { - Pattern p = new Pattern("/a/b"); - Pattern rulePattern = new Pattern("/x/*"); - assertEquals(0, p.getPrefixMatchLength(rulePattern)); - } - - { - Pattern p = new Pattern("/a"); - Pattern rulePattern = new Pattern("/x/*"); - assertEquals(0, p.getPrefixMatchLength(rulePattern)); - } - - { - Pattern p = new Pattern("/a/b"); - Pattern rulePattern = new Pattern("/a/*"); - assertEquals(1, p.getPrefixMatchLength(rulePattern)); - } - - { - Pattern p = new Pattern("/a/b"); - Pattern rulePattern = new Pattern("/A/*"); - assertEquals(1, p.getPrefixMatchLength(rulePattern)); - } - - { - Pattern p = new Pattern("/A/b"); - Pattern rulePattern = new Pattern("/a/*"); - assertEquals(1, p.getPrefixMatchLength(rulePattern)); - } - - { - Pattern p = new Pattern("/a/b"); - Pattern rulePattern = new Pattern("/a/b/*"); - assertEquals(2, p.getPrefixMatchLength(rulePattern)); - } - - { - Pattern p = new Pattern("/a/b"); - Pattern rulePattern = new Pattern("/*"); - assertEquals(0, p.getPrefixMatchLength(rulePattern)); - } - } - -} +/** + * 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.joran.spi; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +/** + * Test pattern manipulation code. + * + * @author Ceki Gulcu + */ +public class PatternTest { + + @Test + public void test1() { + Pattern p = new Pattern("a"); + assertEquals(1, p.size()); + assertEquals("a", p.peekLast()); + assertEquals("a", p.get(0)); + } + + @Test + public void testSuffix() { + Pattern p = new Pattern("a/"); + assertEquals(1, p.size()); + assertEquals("a", p.peekLast()); + assertEquals("a", p.get(0)); + } + + @Test + public void test2() { + Pattern p = new Pattern("a/b"); + assertEquals(2, p.size()); + assertEquals("b", p.peekLast()); + assertEquals("a", p.get(0)); + assertEquals("b", p.get(1)); + } + + @Test + public void test3() { + Pattern p = new Pattern("a123/b1234/cvvsdf"); + assertEquals(3, p.size()); + assertEquals("a123", p.get(0)); + assertEquals("b1234", p.get(1)); + assertEquals("cvvsdf", p.get(2)); + } + + @Test + public void test4() { + Pattern p = new Pattern("/a123/b1234/cvvsdf"); + assertEquals(3, p.size()); + assertEquals("a123", p.get(0)); + assertEquals("b1234", p.get(1)); + assertEquals("cvvsdf", p.get(2)); + } + + @Test + public void test5() { + Pattern p = new Pattern("//a"); + assertEquals(1, p.size()); + assertEquals("a", p.get(0)); + } + + @Test + public void test6() { + Pattern p = new Pattern("//a//b"); + assertEquals(2, p.size()); + assertEquals("a", p.get(0)); + assertEquals("b", p.get(1)); + } + + + // test tail matching + @Test + public void testTailMatch() { + { + Pattern p = new Pattern("/a/b"); + Pattern rulePattern = new Pattern("*"); + assertEquals(0, p.getTailMatchLength(rulePattern)); + } + + { + Pattern p = new Pattern("/a"); + Pattern rulePattern = new Pattern("*/a"); + assertEquals(1, p.getTailMatchLength(rulePattern)); + } + + { + Pattern p = new Pattern("/A"); + Pattern rulePattern = new Pattern("*/a"); + assertEquals(1, p.getTailMatchLength(rulePattern)); + } + + { + Pattern p = new Pattern("/a"); + Pattern rulePattern = new Pattern("*/A"); + assertEquals(1, p.getTailMatchLength(rulePattern)); + } + + + { + Pattern p = new Pattern("/a/b"); + Pattern rulePattern = new Pattern("*/b"); + assertEquals(1, p.getTailMatchLength(rulePattern)); + } + + { + Pattern p = new Pattern("/a/B"); + Pattern rulePattern = new Pattern("*/b"); + assertEquals(1, p.getTailMatchLength(rulePattern)); + } + + { + Pattern p = new Pattern("/a/b/c"); + Pattern rulePattern = new Pattern("*/b/c"); + assertEquals(2, p.getTailMatchLength(rulePattern)); + } + } + + // test prefix matching + @Test + public void testPrefixMatch() { + { + Pattern p = new Pattern("/a/b"); + Pattern rulePattern = new Pattern("/x/*"); + assertEquals(0, p.getPrefixMatchLength(rulePattern)); + } + + { + Pattern p = new Pattern("/a"); + Pattern rulePattern = new Pattern("/x/*"); + assertEquals(0, p.getPrefixMatchLength(rulePattern)); + } + + { + Pattern p = new Pattern("/a/b"); + Pattern rulePattern = new Pattern("/a/*"); + assertEquals(1, p.getPrefixMatchLength(rulePattern)); + } + + { + Pattern p = new Pattern("/a/b"); + Pattern rulePattern = new Pattern("/A/*"); + assertEquals(1, p.getPrefixMatchLength(rulePattern)); + } + + { + Pattern p = new Pattern("/A/b"); + Pattern rulePattern = new Pattern("/a/*"); + assertEquals(1, p.getPrefixMatchLength(rulePattern)); + } + + { + Pattern p = new Pattern("/a/b"); + Pattern rulePattern = new Pattern("/a/b/*"); + assertEquals(2, p.getPrefixMatchLength(rulePattern)); + } + + { + Pattern p = new Pattern("/a/b"); + Pattern rulePattern = new Pattern("/*"); + assertEquals(0, p.getPrefixMatchLength(rulePattern)); + } + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PropertySetterTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PropertySetterTest.java index 8219ff21294ca3ef31a710af003ff1fb204ef3a3..9436b870bc458ca94d73fe0e3b72e2a407e53106 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PropertySetterTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PropertySetterTest.java @@ -1,389 +1,389 @@ -/** - * 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.joran.spi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.spi.FilterReply; -import ch.qos.logback.core.util.AggregationType; -import ch.qos.logback.core.util.Duration; -import ch.qos.logback.core.util.FileSize; - -public class PropertySetterTest { - - DefaultNestedComponentRegistry defaultComponentRegistry = new DefaultNestedComponentRegistry(); - - @Test - public void testCanAggregateComponent() { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - assertEquals(AggregationType.AS_COMPLEX_PROPERTY, setter - .computeAggregationType("door")); - - assertEquals(AggregationType.AS_BASIC_PROPERTY, setter - .computeAggregationType("count")); - assertEquals(AggregationType.AS_BASIC_PROPERTY, setter - .computeAggregationType("Count")); - - assertEquals(AggregationType.AS_BASIC_PROPERTY, setter - .computeAggregationType("name")); - assertEquals(AggregationType.AS_BASIC_PROPERTY, setter - .computeAggregationType("Name")); - - assertEquals(AggregationType.AS_BASIC_PROPERTY, setter - .computeAggregationType("Duration")); - assertEquals(AggregationType.AS_BASIC_PROPERTY, setter - .computeAggregationType("fs")); - - assertEquals(AggregationType.AS_BASIC_PROPERTY, setter - .computeAggregationType("open")); - assertEquals(AggregationType.AS_BASIC_PROPERTY, setter - .computeAggregationType("Open")); - - assertEquals(AggregationType.AS_COMPLEX_PROPERTY_COLLECTION, setter - .computeAggregationType("Window")); - assertEquals(AggregationType.AS_BASIC_PROPERTY_COLLECTION, setter - .computeAggregationType("adjective")); - - assertEquals(AggregationType.AS_BASIC_PROPERTY, setter - .computeAggregationType("filterReply")); - assertEquals(AggregationType.AS_BASIC_PROPERTY, setter - .computeAggregationType("houseColor")); - - System.out.println(); - } - - @Test - public void testSetProperty() { - { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - setter.setProperty("count", "10"); - setter.setProperty("name", "jack"); - setter.setProperty("open", "true"); - - assertEquals(10, house.getCount()); - assertEquals("jack", house.getName()); - assertTrue(house.isOpen()); - } - - { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - setter.setProperty("Count", "10"); - setter.setProperty("Name", "jack"); - setter.setProperty("Open", "true"); - - assertEquals(10, house.getCount()); - assertEquals("jack", house.getName()); - assertTrue(house.isOpen()); - } - } - - @Test - public void testSetCamelProperty() { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - - setter.setProperty("camelCase", "trot"); - assertEquals("trot", house.getCamelCase()); - - setter.setProperty("camelCase", "gh"); - assertEquals("gh", house.getCamelCase()); - } - - @Test - public void testSetComplexProperty() { - House house = new House(); - Door door = new Door(); - PropertySetter setter = new PropertySetter(house); - setter.setComplexProperty("door", door); - assertEquals(door, house.getDoor()); - } - - @Test - public void testgetClassNameViaImplicitRules() { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - Class compClass = setter.getClassNameViaImplicitRules("door", - AggregationType.AS_COMPLEX_PROPERTY, defaultComponentRegistry); - assertEquals(Door.class, compClass); - } - - @Test - public void testgetComplexPropertyColleClassNameViaImplicitRules() { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - Class compClass = setter.getClassNameViaImplicitRules("window", - AggregationType.AS_COMPLEX_PROPERTY_COLLECTION, - defaultComponentRegistry); - assertEquals(Window.class, compClass); - } - - @Test - public void testPropertyCollection() { - House house = new House(); - Context context = new ContextBase(); - PropertySetter setter = new PropertySetter(house); - setter.setContext(context); - setter.addBasicProperty("adjective", "nice"); - setter.addBasicProperty("adjective", "big"); - - assertEquals(2, house.adjectiveList.size()); - assertEquals("nice", house.adjectiveList.get(0)); - assertEquals("big", house.adjectiveList.get(1)); - } - - @Test - public void testComplexCollection() { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - Window w1 = new Window(); - w1.handle = 10; - Window w2 = new Window(); - w2.handle = 20; - - setter.addComplexProperty("window", w1); - setter.addComplexProperty("window", w2); - assertEquals(2, house.windowList.size()); - assertEquals(10, house.windowList.get(0).handle); - assertEquals(20, house.windowList.get(1).handle); - } - - @Test - public void testSetComplexWithCamelCaseName() { - House house = new House(); - SwimmingPool pool = new SwimmingPoolImpl(); - PropertySetter setter = new PropertySetter(house); - setter.setComplexProperty("swimmingPool", pool); - assertEquals(pool, house.getSwimmingPool()); - } - - @Test - public void testDuration() { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - setter.setProperty("duration", "1.4 seconds"); - assertEquals(1400, house.getDuration().getMilliseconds()); - } - - @Test - public void testFileSize() { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - setter.setProperty("fs", "2 kb"); - assertEquals(2 * 1024, house.getFs().getSize()); - } - - @Test - public void testFilterReply() { - // test case reproducing bug #52 - House house = new House(); - PropertySetter setter = new PropertySetter(house); - setter.setProperty("filterReply", "ACCEPT"); - assertEquals(FilterReply.ACCEPT, house.getFilterReply()); - } - - @Test - public void testEnum() { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - setter.setProperty("houseColor", "BLUE"); - assertEquals(HouseColor.BLUE, house.getHouseColor()); - } - - @Test - public void testDefaultClassAnnonation() { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - Method relevantMethod = setter.getRelevantMethod("SwimmingPool", - AggregationType.AS_COMPLEX_PROPERTY); - assertNotNull(relevantMethod); - Class spClass = setter.getDefaultClassNameByAnnonation("SwimmingPool", - relevantMethod); - assertEquals(SwimmingPoolImpl.class, spClass); - - Class classViaImplicitRules = setter.getClassNameViaImplicitRules( - "SwimmingPool", AggregationType.AS_COMPLEX_PROPERTY, - defaultComponentRegistry); - assertEquals(SwimmingPoolImpl.class, classViaImplicitRules); - } - - @Test - public void testDefaultClassAnnotationForLists() { - House house = new House(); - PropertySetter setter = new PropertySetter(house); - Method relevantMethod = setter.getRelevantMethod("LargeSwimmingPool", - AggregationType.AS_COMPLEX_PROPERTY_COLLECTION); - assertNotNull(relevantMethod); - Class spClass = setter.getDefaultClassNameByAnnonation("LargeSwimmingPool", - relevantMethod); - assertEquals(LargeSwimmingPoolImpl.class, spClass); - - Class classViaImplicitRules = setter.getClassNameViaImplicitRules( - "LargeSwimmingPool", AggregationType.AS_COMPLEX_PROPERTY_COLLECTION, - defaultComponentRegistry); - assertEquals(LargeSwimmingPoolImpl.class, classViaImplicitRules); - - } -} - -class House { - Door mainDoor; - int count; - boolean open; - String name; - String camelCase; - SwimmingPool pool; - Duration duration; - FileSize fs; - HouseColor houseColor; - FilterReply reply; - - List adjectiveList = new ArrayList(); - List windowList = new ArrayList(); - List largePoolList = new ArrayList(); - - public String getCamelCase() { - return camelCase; - } - - public void setCamelCase(String camelCase) { - this.camelCase = camelCase; - } - - public int getCount() { - return count; - } - - public void setCount(int c) { - this.count = c; - } - - public Door getDoor() { - return mainDoor; - } - - public void setDoor(Door door) { - this.mainDoor = door; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public boolean isOpen() { - return open; - } - - public void setOpen(boolean open) { - this.open = open; - } - - @DefaultClass(LargeSwimmingPoolImpl.class) - public void addLargeSwimmingPool(SwimmingPool pool) { - this.pool = pool; - } - - @DefaultClass(SwimmingPoolImpl.class) - public void setSwimmingPool(SwimmingPool pool) { - this.pool = pool; - } - - public SwimmingPool getSwimmingPool() { - return pool; - } - - public void addWindow(Window w) { - windowList.add(w); - } - - public void addAdjective(String s) { - adjectiveList.add(s); - } - - public Duration getDuration() { - return duration; - } - - public void setDuration(Duration duration) { - this.duration = duration; - } - - public FileSize getFs() { - return fs; - } - - public void setFs(FileSize fs) { - this.fs = fs; - } - - public void setHouseColor(HouseColor color) { - this.houseColor = color; - } - - public HouseColor getHouseColor() { - return houseColor; - } - - public void setFilterReply(FilterReply reply) { - this.reply = reply; - } - - public FilterReply getFilterReply() { - return reply; - } - -} - -class Door { - int handle; -} - -class Window { - int handle; -} - -interface SwimmingPool { -} - -class SwimmingPoolImpl implements SwimmingPool { - int length; - int width; - int depth; -} - -class LargeSwimmingPoolImpl implements SwimmingPool { - int length; - int width; - int depth; -} - -enum HouseColor { - WHITE, BLUE -} +/** + * 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.joran.spi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.util.AggregationType; +import ch.qos.logback.core.util.Duration; +import ch.qos.logback.core.util.FileSize; + +public class PropertySetterTest { + + DefaultNestedComponentRegistry defaultComponentRegistry = new DefaultNestedComponentRegistry(); + + @Test + public void testCanAggregateComponent() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + assertEquals(AggregationType.AS_COMPLEX_PROPERTY, setter + .computeAggregationType("door")); + + assertEquals(AggregationType.AS_BASIC_PROPERTY, setter + .computeAggregationType("count")); + assertEquals(AggregationType.AS_BASIC_PROPERTY, setter + .computeAggregationType("Count")); + + assertEquals(AggregationType.AS_BASIC_PROPERTY, setter + .computeAggregationType("name")); + assertEquals(AggregationType.AS_BASIC_PROPERTY, setter + .computeAggregationType("Name")); + + assertEquals(AggregationType.AS_BASIC_PROPERTY, setter + .computeAggregationType("Duration")); + assertEquals(AggregationType.AS_BASIC_PROPERTY, setter + .computeAggregationType("fs")); + + assertEquals(AggregationType.AS_BASIC_PROPERTY, setter + .computeAggregationType("open")); + assertEquals(AggregationType.AS_BASIC_PROPERTY, setter + .computeAggregationType("Open")); + + assertEquals(AggregationType.AS_COMPLEX_PROPERTY_COLLECTION, setter + .computeAggregationType("Window")); + assertEquals(AggregationType.AS_BASIC_PROPERTY_COLLECTION, setter + .computeAggregationType("adjective")); + + assertEquals(AggregationType.AS_BASIC_PROPERTY, setter + .computeAggregationType("filterReply")); + assertEquals(AggregationType.AS_BASIC_PROPERTY, setter + .computeAggregationType("houseColor")); + + System.out.println(); + } + + @Test + public void testSetProperty() { + { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + setter.setProperty("count", "10"); + setter.setProperty("name", "jack"); + setter.setProperty("open", "true"); + + assertEquals(10, house.getCount()); + assertEquals("jack", house.getName()); + assertTrue(house.isOpen()); + } + + { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + setter.setProperty("Count", "10"); + setter.setProperty("Name", "jack"); + setter.setProperty("Open", "true"); + + assertEquals(10, house.getCount()); + assertEquals("jack", house.getName()); + assertTrue(house.isOpen()); + } + } + + @Test + public void testSetCamelProperty() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + + setter.setProperty("camelCase", "trot"); + assertEquals("trot", house.getCamelCase()); + + setter.setProperty("camelCase", "gh"); + assertEquals("gh", house.getCamelCase()); + } + + @Test + public void testSetComplexProperty() { + House house = new House(); + Door door = new Door(); + PropertySetter setter = new PropertySetter(house); + setter.setComplexProperty("door", door); + assertEquals(door, house.getDoor()); + } + + @Test + public void testgetClassNameViaImplicitRules() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + Class compClass = setter.getClassNameViaImplicitRules("door", + AggregationType.AS_COMPLEX_PROPERTY, defaultComponentRegistry); + assertEquals(Door.class, compClass); + } + + @Test + public void testgetComplexPropertyColleClassNameViaImplicitRules() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + Class compClass = setter.getClassNameViaImplicitRules("window", + AggregationType.AS_COMPLEX_PROPERTY_COLLECTION, + defaultComponentRegistry); + assertEquals(Window.class, compClass); + } + + @Test + public void testPropertyCollection() { + House house = new House(); + Context context = new ContextBase(); + PropertySetter setter = new PropertySetter(house); + setter.setContext(context); + setter.addBasicProperty("adjective", "nice"); + setter.addBasicProperty("adjective", "big"); + + assertEquals(2, house.adjectiveList.size()); + assertEquals("nice", house.adjectiveList.get(0)); + assertEquals("big", house.adjectiveList.get(1)); + } + + @Test + public void testComplexCollection() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + Window w1 = new Window(); + w1.handle = 10; + Window w2 = new Window(); + w2.handle = 20; + + setter.addComplexProperty("window", w1); + setter.addComplexProperty("window", w2); + assertEquals(2, house.windowList.size()); + assertEquals(10, house.windowList.get(0).handle); + assertEquals(20, house.windowList.get(1).handle); + } + + @Test + public void testSetComplexWithCamelCaseName() { + House house = new House(); + SwimmingPool pool = new SwimmingPoolImpl(); + PropertySetter setter = new PropertySetter(house); + setter.setComplexProperty("swimmingPool", pool); + assertEquals(pool, house.getSwimmingPool()); + } + + @Test + public void testDuration() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + setter.setProperty("duration", "1.4 seconds"); + assertEquals(1400, house.getDuration().getMilliseconds()); + } + + @Test + public void testFileSize() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + setter.setProperty("fs", "2 kb"); + assertEquals(2 * 1024, house.getFs().getSize()); + } + + @Test + public void testFilterReply() { + // test case reproducing bug #52 + House house = new House(); + PropertySetter setter = new PropertySetter(house); + setter.setProperty("filterReply", "ACCEPT"); + assertEquals(FilterReply.ACCEPT, house.getFilterReply()); + } + + @Test + public void testEnum() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + setter.setProperty("houseColor", "BLUE"); + assertEquals(HouseColor.BLUE, house.getHouseColor()); + } + + @Test + public void testDefaultClassAnnonation() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + Method relevantMethod = setter.getRelevantMethod("SwimmingPool", + AggregationType.AS_COMPLEX_PROPERTY); + assertNotNull(relevantMethod); + Class spClass = setter.getDefaultClassNameByAnnonation("SwimmingPool", + relevantMethod); + assertEquals(SwimmingPoolImpl.class, spClass); + + Class classViaImplicitRules = setter.getClassNameViaImplicitRules( + "SwimmingPool", AggregationType.AS_COMPLEX_PROPERTY, + defaultComponentRegistry); + assertEquals(SwimmingPoolImpl.class, classViaImplicitRules); + } + + @Test + public void testDefaultClassAnnotationForLists() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + Method relevantMethod = setter.getRelevantMethod("LargeSwimmingPool", + AggregationType.AS_COMPLEX_PROPERTY_COLLECTION); + assertNotNull(relevantMethod); + Class spClass = setter.getDefaultClassNameByAnnonation("LargeSwimmingPool", + relevantMethod); + assertEquals(LargeSwimmingPoolImpl.class, spClass); + + Class classViaImplicitRules = setter.getClassNameViaImplicitRules( + "LargeSwimmingPool", AggregationType.AS_COMPLEX_PROPERTY_COLLECTION, + defaultComponentRegistry); + assertEquals(LargeSwimmingPoolImpl.class, classViaImplicitRules); + + } +} + +class House { + Door mainDoor; + int count; + boolean open; + String name; + String camelCase; + SwimmingPool pool; + Duration duration; + FileSize fs; + HouseColor houseColor; + FilterReply reply; + + List adjectiveList = new ArrayList(); + List windowList = new ArrayList(); + List largePoolList = new ArrayList(); + + public String getCamelCase() { + return camelCase; + } + + public void setCamelCase(String camelCase) { + this.camelCase = camelCase; + } + + public int getCount() { + return count; + } + + public void setCount(int c) { + this.count = c; + } + + public Door getDoor() { + return mainDoor; + } + + public void setDoor(Door door) { + this.mainDoor = door; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isOpen() { + return open; + } + + public void setOpen(boolean open) { + this.open = open; + } + + @DefaultClass(LargeSwimmingPoolImpl.class) + public void addLargeSwimmingPool(SwimmingPool pool) { + this.pool = pool; + } + + @DefaultClass(SwimmingPoolImpl.class) + public void setSwimmingPool(SwimmingPool pool) { + this.pool = pool; + } + + public SwimmingPool getSwimmingPool() { + return pool; + } + + public void addWindow(Window w) { + windowList.add(w); + } + + public void addAdjective(String s) { + adjectiveList.add(s); + } + + public Duration getDuration() { + return duration; + } + + public void setDuration(Duration duration) { + this.duration = duration; + } + + public FileSize getFs() { + return fs; + } + + public void setFs(FileSize fs) { + this.fs = fs; + } + + public void setHouseColor(HouseColor color) { + this.houseColor = color; + } + + public HouseColor getHouseColor() { + return houseColor; + } + + public void setFilterReply(FilterReply reply) { + this.reply = reply; + } + + public FilterReply getFilterReply() { + return reply; + } + +} + +class Door { + int handle; +} + +class Window { + int handle; +} + +interface SwimmingPool { +} + +class SwimmingPoolImpl implements SwimmingPool { + int length; + int width; + int depth; +} + +class LargeSwimmingPoolImpl implements SwimmingPool { + int length; + int width; + int depth; +} + +enum HouseColor { + WHITE, BLUE +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleRuleStoreTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleRuleStoreTest.java index 3a5e04faa6ec9fc65742337984d117d96b39db38..d95cf11d1fbd6f36b86e09df5aa027c7f2ef18f1 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleRuleStoreTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleRuleStoreTest.java @@ -1,265 +1,265 @@ -/** - * 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.joran.spi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.List; - -import org.junit.Test; -import org.xml.sax.Attributes; - -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.joran.action.Action; - -/** - * Test SimpleRuleStore for various explicit rule combinations. - * - * We also test that explicit patterns are case sensitive. - * - * @author Ceki Gülcü - */ -public class SimpleRuleStoreTest { - - SimpleRuleStore srs = new SimpleRuleStore(new ContextBase()); - CaseCombinator cc = new CaseCombinator(); - - @Test - public void smoke() throws Exception { - srs.addRule(new Pattern("a/b"), new XAction()); - - // test for all possible case combinations of "a/b" - for (String s : cc.combinations("a/b")) { - List r = srs.matchActions(new Pattern(s)); - assertNotNull(r); - assertEquals(1, r.size()); - - if (!(r.get(0) instanceof XAction)) { - fail("Wrong type"); - } - } - } - - @Test - public void smokeII() throws Exception { - srs.addRule(new Pattern("a/b"), new XAction()); - srs.addRule(new Pattern("a/b"), new YAction()); - - for (String s : cc.combinations("a/b")) { - List r = srs.matchActions(new Pattern(s)); - assertNotNull(r); - assertEquals(2, r.size()); - - if (!(r.get(0) instanceof XAction)) { - fail("Wrong type"); - } - - if (!(r.get(1) instanceof YAction)) { - fail("Wrong type"); - } - } - } - - @Test - public void testSlashSuffix() throws Exception { - Pattern pa = new Pattern("a/"); - srs.addRule(pa, new XAction()); - - for (String s : cc.combinations("a")) { - List r = srs.matchActions(new Pattern(s)); - assertNotNull(r); - assertEquals(1, r.size()); - - if (!(r.get(0) instanceof XAction)) { - fail("Wrong type"); - } - } - - } - - @Test - public void testTail1() throws Exception { - srs.addRule(new Pattern("*/b"), new XAction()); - - for (String s : cc.combinations("a/b")) { - List r = srs.matchActions(new Pattern(s)); - assertNotNull(r); - - assertEquals(1, r.size()); - - if (!(r.get(0) instanceof XAction)) { - fail("Wrong type"); - } - } - } - - @Test - public void testTail2() throws Exception { - SimpleRuleStore srs = new SimpleRuleStore(new ContextBase()); - srs.addRule(new Pattern("*/c"), new XAction()); - - for (String s : cc.combinations("a/b/c")) { - List r = srs.matchActions(new Pattern(s)); - assertNotNull(r); - - assertEquals(1, r.size()); - - if (!(r.get(0) instanceof XAction)) { - fail("Wrong type"); - } - } - } - - @Test - public void testTail3() throws Exception { - srs.addRule(new Pattern("*/b"), new XAction()); - srs.addRule(new Pattern("*/a/b"), new YAction()); - - for (String s : cc.combinations("a/b")) { - List r = srs.matchActions(new Pattern(s)); - assertNotNull(r); - assertEquals(1, r.size()); - - if (!(r.get(0) instanceof YAction)) { - fail("Wrong type"); - } - } - } - - @Test - public void testTail4() throws Exception { - srs.addRule(new Pattern("*/b"), new XAction()); - srs.addRule(new Pattern("*/a/b"), new YAction()); - srs.addRule(new Pattern("a/b"), new ZAction()); - - for (String s : cc.combinations("a/b")) { - List r = srs.matchActions(new Pattern(s)); - assertNotNull(r); - assertEquals(1, r.size()); - - if (!(r.get(0) instanceof ZAction)) { - fail("Wrong type"); - } - } - } - - @Test - public void testSuffix() throws Exception { - srs.addRule(new Pattern("a"), new XAction()); - srs.addRule(new Pattern("a/*"), new YAction()); - - for (String s : cc.combinations("a/b")) { - List r = srs.matchActions(new Pattern(s)); - assertNotNull(r); - assertEquals(1, r.size()); - assertTrue(r.get(0) instanceof YAction); - } - } - - @Test - public void testDeepSuffix() throws Exception { - srs.addRule(new Pattern("a"), new XAction(1)); - srs.addRule(new Pattern("a/b/*"), new XAction(2)); - - for (String s : cc.combinations("a/other")) { - List r = srs.matchActions(new Pattern(s)); - assertNull(r); - } - } - - @Test - public void testPrefixSuffixInteraction1() throws Exception { - srs.addRule(new Pattern("a"), new ZAction()); - srs.addRule(new Pattern("a/*"), new YAction()); - srs.addRule(new Pattern("*/a/b"), new XAction(3)); - - for (String s : cc.combinations("a/b")) { - List r = srs.matchActions(new Pattern(s)); - assertNotNull(r); - - assertEquals(1, r.size()); - - assertTrue(r.get(0) instanceof XAction); - XAction xaction = (XAction) r.get(0); - assertEquals(3, xaction.id); - } - } - - @Test - public void testPrefixSuffixInteraction2() throws Exception { - srs.addRule(new Pattern("tG"), new XAction()); - srs.addRule(new Pattern("tG/tS"), new YAction()); - srs.addRule(new Pattern("tG/tS/test"), new ZAction()); - srs.addRule(new Pattern("tG/tS/test/*"), new XAction(9)); - - for (String s : cc.combinations("tG/tS/toto")) { - List r = srs.matchActions(new Pattern(s)); - assertNull(r); - } - } - - class XAction extends Action { - int id = 0; - - XAction() { - } - - XAction(int id) { - this.id = id; - } - - public void begin(InterpretationContext ec, String name, - Attributes attributes) { - } - - public void end(InterpretationContext ec, String name) { - } - - public void finish(InterpretationContext ec) { - } - - public String toString() { - return "XAction(" + id + ")"; - } - } - - class YAction extends Action { - public void begin(InterpretationContext ec, String name, - Attributes attributes) { - } - - public void end(InterpretationContext ec, String name) { - } - - public void finish(InterpretationContext ec) { - } - } - - class ZAction extends Action { - public void begin(InterpretationContext ec, String name, - Attributes attributes) { - } - - public void end(InterpretationContext ec, String name) { - } - - public void finish(InterpretationContext ec) { - } - } - -} +/** + * 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.joran.spi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.List; + +import org.junit.Test; +import org.xml.sax.Attributes; + +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.joran.action.Action; + +/** + * Test SimpleRuleStore for various explicit rule combinations. + * + * We also test that explicit patterns are case sensitive. + * + * @author Ceki Gülcü + */ +public class SimpleRuleStoreTest { + + SimpleRuleStore srs = new SimpleRuleStore(new ContextBase()); + CaseCombinator cc = new CaseCombinator(); + + @Test + public void smoke() throws Exception { + srs.addRule(new Pattern("a/b"), new XAction()); + + // test for all possible case combinations of "a/b" + for (String s : cc.combinations("a/b")) { + List r = srs.matchActions(new Pattern(s)); + assertNotNull(r); + assertEquals(1, r.size()); + + if (!(r.get(0) instanceof XAction)) { + fail("Wrong type"); + } + } + } + + @Test + public void smokeII() throws Exception { + srs.addRule(new Pattern("a/b"), new XAction()); + srs.addRule(new Pattern("a/b"), new YAction()); + + for (String s : cc.combinations("a/b")) { + List r = srs.matchActions(new Pattern(s)); + assertNotNull(r); + assertEquals(2, r.size()); + + if (!(r.get(0) instanceof XAction)) { + fail("Wrong type"); + } + + if (!(r.get(1) instanceof YAction)) { + fail("Wrong type"); + } + } + } + + @Test + public void testSlashSuffix() throws Exception { + Pattern pa = new Pattern("a/"); + srs.addRule(pa, new XAction()); + + for (String s : cc.combinations("a")) { + List r = srs.matchActions(new Pattern(s)); + assertNotNull(r); + assertEquals(1, r.size()); + + if (!(r.get(0) instanceof XAction)) { + fail("Wrong type"); + } + } + + } + + @Test + public void testTail1() throws Exception { + srs.addRule(new Pattern("*/b"), new XAction()); + + for (String s : cc.combinations("a/b")) { + List r = srs.matchActions(new Pattern(s)); + assertNotNull(r); + + assertEquals(1, r.size()); + + if (!(r.get(0) instanceof XAction)) { + fail("Wrong type"); + } + } + } + + @Test + public void testTail2() throws Exception { + SimpleRuleStore srs = new SimpleRuleStore(new ContextBase()); + srs.addRule(new Pattern("*/c"), new XAction()); + + for (String s : cc.combinations("a/b/c")) { + List r = srs.matchActions(new Pattern(s)); + assertNotNull(r); + + assertEquals(1, r.size()); + + if (!(r.get(0) instanceof XAction)) { + fail("Wrong type"); + } + } + } + + @Test + public void testTail3() throws Exception { + srs.addRule(new Pattern("*/b"), new XAction()); + srs.addRule(new Pattern("*/a/b"), new YAction()); + + for (String s : cc.combinations("a/b")) { + List r = srs.matchActions(new Pattern(s)); + assertNotNull(r); + assertEquals(1, r.size()); + + if (!(r.get(0) instanceof YAction)) { + fail("Wrong type"); + } + } + } + + @Test + public void testTail4() throws Exception { + srs.addRule(new Pattern("*/b"), new XAction()); + srs.addRule(new Pattern("*/a/b"), new YAction()); + srs.addRule(new Pattern("a/b"), new ZAction()); + + for (String s : cc.combinations("a/b")) { + List r = srs.matchActions(new Pattern(s)); + assertNotNull(r); + assertEquals(1, r.size()); + + if (!(r.get(0) instanceof ZAction)) { + fail("Wrong type"); + } + } + } + + @Test + public void testSuffix() throws Exception { + srs.addRule(new Pattern("a"), new XAction()); + srs.addRule(new Pattern("a/*"), new YAction()); + + for (String s : cc.combinations("a/b")) { + List r = srs.matchActions(new Pattern(s)); + assertNotNull(r); + assertEquals(1, r.size()); + assertTrue(r.get(0) instanceof YAction); + } + } + + @Test + public void testDeepSuffix() throws Exception { + srs.addRule(new Pattern("a"), new XAction(1)); + srs.addRule(new Pattern("a/b/*"), new XAction(2)); + + for (String s : cc.combinations("a/other")) { + List r = srs.matchActions(new Pattern(s)); + assertNull(r); + } + } + + @Test + public void testPrefixSuffixInteraction1() throws Exception { + srs.addRule(new Pattern("a"), new ZAction()); + srs.addRule(new Pattern("a/*"), new YAction()); + srs.addRule(new Pattern("*/a/b"), new XAction(3)); + + for (String s : cc.combinations("a/b")) { + List r = srs.matchActions(new Pattern(s)); + assertNotNull(r); + + assertEquals(1, r.size()); + + assertTrue(r.get(0) instanceof XAction); + XAction xaction = (XAction) r.get(0); + assertEquals(3, xaction.id); + } + } + + @Test + public void testPrefixSuffixInteraction2() throws Exception { + srs.addRule(new Pattern("tG"), new XAction()); + srs.addRule(new Pattern("tG/tS"), new YAction()); + srs.addRule(new Pattern("tG/tS/test"), new ZAction()); + srs.addRule(new Pattern("tG/tS/test/*"), new XAction(9)); + + for (String s : cc.combinations("tG/tS/toto")) { + List r = srs.matchActions(new Pattern(s)); + assertNull(r); + } + } + + class XAction extends Action { + int id = 0; + + XAction() { + } + + XAction(int id) { + this.id = id; + } + + public void begin(InterpretationContext ec, String name, + Attributes attributes) { + } + + public void end(InterpretationContext ec, String name) { + } + + public void finish(InterpretationContext ec) { + } + + public String toString() { + return "XAction(" + id + ")"; + } + } + + class YAction extends Action { + public void begin(InterpretationContext ec, String name, + Attributes attributes) { + } + + public void end(InterpretationContext ec, String name) { + } + + public void finish(InterpretationContext ec) { + } + } + + class ZAction extends Action { + public void begin(InterpretationContext ec, String name, + Attributes attributes) { + } + + public void end(InterpretationContext ec, String name) { + } + + public void finish(InterpretationContext ec) { + } + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/layout/DummyLayout.java b/logback-core/src/test/java/ch/qos/logback/core/layout/DummyLayout.java index e016ec308e506be444c22f023a78dcc0ff0bff12..9d2f362d610c10c4eb383b914ae94c5ab50cf586 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/layout/DummyLayout.java +++ b/logback-core/src/test/java/ch/qos/logback/core/layout/DummyLayout.java @@ -1,36 +1,36 @@ -/** - * 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.layout; - -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.LayoutBase; - -public class DummyLayout extends LayoutBase { - - public static final String DUMMY = "dummy"+CoreConstants.LINE_SEPARATOR; - String val = DUMMY; - - public DummyLayout() { - } - - public DummyLayout(String val) { - this.val = val; - } - - public String doLayout(E event) { - return val; - } - - -} +/** + * 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.layout; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.LayoutBase; + +public class DummyLayout extends LayoutBase { + + public static final String DUMMY = "dummy"+CoreConstants.LINE_SEPARATOR; + String val = DUMMY; + + public DummyLayout() { + } + + public DummyLayout(String val) { + this.val = val; + } + + public String doLayout(E event) { + return val; + } + + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/layout/NopLayout.java b/logback-core/src/test/java/ch/qos/logback/core/layout/NopLayout.java index e1e347df26cf5b1058214d3b7241d51f93655cf5..61b6af093ba8561ab0704393e8059f5e262a291f 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/layout/NopLayout.java +++ b/logback-core/src/test/java/ch/qos/logback/core/layout/NopLayout.java @@ -1,23 +1,23 @@ -/** - * 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.layout; - -import ch.qos.logback.core.LayoutBase; - -public class NopLayout extends LayoutBase { - - public String doLayout(E event) { - return ""; - } -} +/** + * 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.layout; + +import ch.qos.logback.core.LayoutBase; + +public class NopLayout extends LayoutBase { + + public String doLayout(E event) { + return ""; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/Converter123.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/Converter123.java index a35dea1b1fbcac0dbedd5f4296dea883dc30abff..e57455d4c41c73eaae6ae421db9798fefd22430c 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/Converter123.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/Converter123.java @@ -1,24 +1,24 @@ -/** - * 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; - -import ch.qos.logback.core.pattern.DynamicConverter; - -public class Converter123 extends DynamicConverter { - - public String convert(Object event) { - return "123"; - } - -} +/** + * 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; + +import ch.qos.logback.core.pattern.DynamicConverter; + +public class Converter123 extends DynamicConverter { + + public String convert(Object event) { + return "123"; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/ConverterHello.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/ConverterHello.java index 613b76427d95b0684327e78b157a66ee77a5b18b..627011eb87c8305aeebaae177e3492bb956f1f35 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/ConverterHello.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/ConverterHello.java @@ -1,24 +1,24 @@ -/** - * 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; - -import ch.qos.logback.core.pattern.DynamicConverter; - -public class ConverterHello extends DynamicConverter { - - public String convert(Object event) { - return "Hello"; - } - -} +/** + * 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; + +import ch.qos.logback.core.pattern.DynamicConverter; + +public class ConverterHello extends DynamicConverter { + + public String convert(Object event) { + return "Hello"; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/ExceptionalConverter.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/ExceptionalConverter.java index 49efbffb12840d01310ae2563849cbf39292a01a..756ef31a9abb0232d596048dd6509c7a5cdf0fb1 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/ExceptionalConverter.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/ExceptionalConverter.java @@ -1,27 +1,27 @@ -/** - * 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; - -import ch.qos.logback.core.pattern.DynamicConverter; - -public class ExceptionalConverter extends DynamicConverter { - - public String convert(Object event) { - if(!isStarted()) { - throw new IllegalStateException("this converter must be started before use"); - } - return ""; - } - -} +/** + * 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; + +import ch.qos.logback.core.pattern.DynamicConverter; + +public class ExceptionalConverter extends DynamicConverter { + + public String convert(Object event) { + if(!isStarted()) { + throw new IllegalStateException("this converter must be started before use"); + } + return ""; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/PackageTest.java index 0935477312fe443a98d08cc3ed765000727e3b45..94b502955fe8ade34c01e893a03d5eb756547652 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/PackageTest.java @@ -1,23 +1,23 @@ -/** - * 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; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({SpacePadderTest.class, ch.qos.logback.core.pattern.parser.PackageTest.class}) -public class PackageTest { -} +/** + * 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; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({SpacePadderTest.class, ch.qos.logback.core.pattern.parser.PackageTest.class}) +public class PackageTest { +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/SpacePadderTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/SpacePadderTest.java index 9937bc5f7b1a7004d57b8319f0de02a160ccf0ef..97866a6684ff767d0bb7915d12ceaa3b8e612670 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/SpacePadderTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/SpacePadderTest.java @@ -1,107 +1,107 @@ -/** - * 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; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -public class SpacePadderTest { - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - } - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void smoke() { - { - StringBuffer buf = new StringBuffer(); - String s = "a"; - SpacePadder.leftPad(buf, s, 4); - assertEquals(" a", buf.toString()); - } - { - StringBuffer buf = new StringBuffer(); - String s = "a"; - SpacePadder.rightPad(buf, s, 4); - assertEquals("a ", buf.toString()); - } - } - - @Test - public void nullString() { - String s = null; - { - StringBuffer buf = new StringBuffer(); - SpacePadder.leftPad(buf, s, 2); - assertEquals(" ", buf.toString()); - } - { - StringBuffer buf = new StringBuffer(); - SpacePadder.rightPad(buf, s, 2); - assertEquals(" ", buf.toString()); - } - } - - @Test - public void longString() { - { - StringBuffer buf = new StringBuffer(); - String s = "abc"; - SpacePadder.leftPad(buf, s, 2); - assertEquals(s, buf.toString()); - } - - { - StringBuffer buf = new StringBuffer(); - String s = "abc"; - SpacePadder.rightPad(buf, s, 2); - assertEquals(s, buf.toString()); - } - } - - @Test - public void lengthyPad() { - { - StringBuffer buf = new StringBuffer(); - String s = "abc"; - SpacePadder.leftPad(buf, s, 33); - assertEquals(" abc", buf.toString()); - } - { - StringBuffer buf = new StringBuffer(); - String s = "abc"; - SpacePadder.rightPad(buf, s, 33); - assertEquals("abc ", 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; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class SpacePadderTest { + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void smoke() { + { + StringBuffer buf = new StringBuffer(); + String s = "a"; + SpacePadder.leftPad(buf, s, 4); + assertEquals(" a", buf.toString()); + } + { + StringBuffer buf = new StringBuffer(); + String s = "a"; + SpacePadder.rightPad(buf, s, 4); + assertEquals("a ", buf.toString()); + } + } + + @Test + public void nullString() { + String s = null; + { + StringBuffer buf = new StringBuffer(); + SpacePadder.leftPad(buf, s, 2); + assertEquals(" ", buf.toString()); + } + { + StringBuffer buf = new StringBuffer(); + SpacePadder.rightPad(buf, s, 2); + assertEquals(" ", buf.toString()); + } + } + + @Test + public void longString() { + { + StringBuffer buf = new StringBuffer(); + String s = "abc"; + SpacePadder.leftPad(buf, s, 2); + assertEquals(s, buf.toString()); + } + + { + StringBuffer buf = new StringBuffer(); + String s = "abc"; + SpacePadder.rightPad(buf, s, 2); + assertEquals(s, buf.toString()); + } + } + + @Test + public void lengthyPad() { + { + StringBuffer buf = new StringBuffer(); + String s = "abc"; + SpacePadder.leftPad(buf, s, 33); + assertEquals(" abc", buf.toString()); + } + { + StringBuffer buf = new StringBuffer(); + String s = "abc"; + SpacePadder.rightPad(buf, s, 33); + assertEquals("abc ", buf.toString()); + } + + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/AbstractPatternLayoutBaseTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/AbstractPatternLayoutBaseTest.java index ad132919fb1f62eabb837c4e7c902a8ff0d630e1..8236b9cdefefc7f30bc53c9f0b1761ad72262f72 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/AbstractPatternLayoutBaseTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/AbstractPatternLayoutBaseTest.java @@ -1,90 +1,90 @@ -/** - * 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 static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.pattern.ExceptionalConverter; -import ch.qos.logback.core.pattern.PatternLayoutBase; -import ch.qos.logback.core.status.StatusChecker; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.util.StatusPrinter; - - -abstract public class AbstractPatternLayoutBaseTest { - - abstract public PatternLayoutBase getPatternLayoutBase(); - abstract public E getEventObject(); - abstract public Context getContext(); - - @Test - public void testUnStarted() { - PatternLayoutBase plb = getPatternLayoutBase(); - Context context = new ContextBase(); - plb.setContext(context); - String s = plb.doLayout(getEventObject()); - assertEquals("", s); - StatusManager sm = context.getStatusManager(); - StatusPrinter.print(sm); - } - - /** - * This test checks that the pattern layout implementation starts its - * converters. ExceptionalConverter throws an exception if it's convert - * method is called before being started. - */ - @Test - public void testConverterStart() { - PatternLayoutBase plb = getPatternLayoutBase(); - plb.setContext(getContext()); - plb.getInstanceConverterMap().put("EX", ExceptionalConverter.class.getName()); - plb.setPattern("%EX"); - plb.start(); - String result = plb.doLayout(getEventObject()); - assertFalse(result.contains("%PARSER_ERROR_EX")); - //System.out.println("========="+result); - } - - @Test - public void testStarted() { - PatternLayoutBase plb = getPatternLayoutBase(); - Context context = new ContextBase(); - plb.setContext(context); - String s = plb.doLayout(getEventObject()); - assertEquals("", s); - StatusManager sm = context.getStatusManager(); - StatusPrinter.print(sm); - } - - @Test - public void testNullPattern() { - //System.out.println("testNullPattern"); - PatternLayoutBase plb = getPatternLayoutBase(); - Context context = new ContextBase(); - plb.setContext(context); - plb.start(); - String s = plb.doLayout(getEventObject()); - assertEquals("", s); - StatusChecker checker = new StatusChecker(context.getStatusManager()); - //StatusPrinter.print(context.getStatusManager()); - assertTrue(checker.containsMatch("Failed to parse pattern \"null\"")); - } - -} +/** + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.pattern.ExceptionalConverter; +import ch.qos.logback.core.pattern.PatternLayoutBase; +import ch.qos.logback.core.status.StatusChecker; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.StatusPrinter; + + +abstract public class AbstractPatternLayoutBaseTest { + + abstract public PatternLayoutBase getPatternLayoutBase(); + abstract public E getEventObject(); + abstract public Context getContext(); + + @Test + public void testUnStarted() { + PatternLayoutBase plb = getPatternLayoutBase(); + Context context = new ContextBase(); + plb.setContext(context); + String s = plb.doLayout(getEventObject()); + assertEquals("", s); + StatusManager sm = context.getStatusManager(); + StatusPrinter.print(sm); + } + + /** + * This test checks that the pattern layout implementation starts its + * converters. ExceptionalConverter throws an exception if it's convert + * method is called before being started. + */ + @Test + public void testConverterStart() { + PatternLayoutBase plb = getPatternLayoutBase(); + plb.setContext(getContext()); + plb.getInstanceConverterMap().put("EX", ExceptionalConverter.class.getName()); + plb.setPattern("%EX"); + plb.start(); + String result = plb.doLayout(getEventObject()); + assertFalse(result.contains("%PARSER_ERROR_EX")); + //System.out.println("========="+result); + } + + @Test + public void testStarted() { + PatternLayoutBase plb = getPatternLayoutBase(); + Context context = new ContextBase(); + plb.setContext(context); + String s = plb.doLayout(getEventObject()); + assertEquals("", s); + StatusManager sm = context.getStatusManager(); + StatusPrinter.print(sm); + } + + @Test + public void testNullPattern() { + //System.out.println("testNullPattern"); + PatternLayoutBase plb = getPatternLayoutBase(); + Context context = new ContextBase(); + plb.setContext(context); + plb.start(); + String s = plb.doLayout(getEventObject()); + assertEquals("", s); + StatusChecker checker = new StatusChecker(context.getStatusManager()); + //StatusPrinter.print(context.getStatusManager()); + assertTrue(checker.containsMatch("Failed to parse pattern \"null\"")); + } + +} 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 cfe8464e462dd9261e1a046359e911eac7ce91da..76848bc0a86016d0e5332da63058ba69e0257365 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 @@ -1,257 +1,257 @@ -/** - * 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 static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.pattern.Converter; -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; - - -public class CompilerTest { - - Map converterMap = new HashMap(); - Context context = new ContextBase(); - - @Before public void setUp() { - converterMap.put("OTT", Converter123.class.getName()); - converterMap.put("hello", ConverterHello.class.getName()); - } - - - String write(final Converter head, Object event) { - StringBuffer buf = new StringBuffer(); - Converter c = head; - while (c != null) { - c.write(buf, event); - c = c.getNext(); - } - return buf.toString(); - } - - @Test - public void testLiteral() throws Exception { - Parser p = new Parser("hello"); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("hello", result); - } - - @Test - public void testBasic() throws Exception { - { - Parser p = new Parser("abc %hello"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("abc Hello", result); - } - { - Parser p = new Parser("abc %hello %OTT"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("abc Hello 123", result); - } - } - - @Test - public void testFormat() throws Exception { - { - Parser p = new Parser("abc %7hello"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("abc Hello", result); - } - - { - Parser p = new Parser("abc %-7hello"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("abc Hello ", result); - } - - { - Parser p = new Parser("abc %.3hello"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("abc llo", result); - } - - { - Parser p = new Parser("abc %.-3hello"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("abc Hel", result); - } - - { - Parser p = new Parser("abc %4.5OTT"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("abc 123", result); - } - { - Parser p = new Parser("abc %-4.5OTT"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("abc 123 ", result); - } - { - Parser p = new Parser("abc %3.4hello"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("abc ello", result); - } - { - Parser p = new Parser("abc %-3.-4hello"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("abc Hell", result); - } - } - - @Test - public void testComposite() throws Exception { -// { -// Parser p = new Parser("%(ABC)"); -// p.setContext(context); -// Node t = p.parse(); -// Converter head = p.compile(t, converterMap); -// String result = write(head, new Object()); -// assertEquals("ABC", result); -// } - { - Context c = new ContextBase(); - Parser p = new Parser("%(ABC %hello)"); - p.setContext(c); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - StatusPrinter.print(c); - assertEquals("ABC Hello", result); - } - { - Parser p = new Parser("%(ABC %hello)"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("ABC Hello", result); - } - } - - @Test - public void testCompositeFormatting() throws Exception { - { - Parser p = new Parser("xyz %4.10(ABC)"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("xyz ABC", result); - } - - { - Parser p = new Parser("xyz %-4.10(ABC)"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("xyz ABC ", result); - } - - { - Parser p = new Parser("xyz %.2(ABC %hello)"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("xyz lo", result); - } - - { - Parser p = new Parser("xyz %.-2(ABC)"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("xyz AB", result); - } - - { - Parser p = new Parser("xyz %30.30(ABC %20hello)"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("xyz ABC Hello", result); - } - } - - @Test - public void testUnknownWord() throws Exception { - Parser p = new Parser("%unknown"); - p.setContext(context); - Node t = p.parse(); - p.compile(t, converterMap); - StatusChecker chercker = new StatusChecker(context.getStatusManager()); - assertTrue(chercker - .containsMatch("\\[unknown] is not a valid conversion word")); - } - - @Test - public void testWithNopEscape() throws Exception { - { - Parser p = new Parser("xyz %hello\\_world"); - p.setContext(context); - Node t = p.parse(); - Converter head = p.compile(t, converterMap); - String result = write(head, new Object()); - assertEquals("xyz Helloworld", result); - } - } - -} +/** + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.pattern.Converter; +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; + + +public class CompilerTest { + + Map converterMap = new HashMap(); + Context context = new ContextBase(); + + @Before public void setUp() { + converterMap.put("OTT", Converter123.class.getName()); + converterMap.put("hello", ConverterHello.class.getName()); + } + + + String write(final Converter head, Object event) { + StringBuffer buf = new StringBuffer(); + Converter c = head; + while (c != null) { + c.write(buf, event); + c = c.getNext(); + } + return buf.toString(); + } + + @Test + public void testLiteral() throws Exception { + Parser p = new Parser("hello"); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("hello", result); + } + + @Test + public void testBasic() throws Exception { + { + Parser p = new Parser("abc %hello"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("abc Hello", result); + } + { + Parser p = new Parser("abc %hello %OTT"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("abc Hello 123", result); + } + } + + @Test + public void testFormat() throws Exception { + { + Parser p = new Parser("abc %7hello"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("abc Hello", result); + } + + { + Parser p = new Parser("abc %-7hello"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("abc Hello ", result); + } + + { + Parser p = new Parser("abc %.3hello"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("abc llo", result); + } + + { + Parser p = new Parser("abc %.-3hello"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("abc Hel", result); + } + + { + Parser p = new Parser("abc %4.5OTT"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("abc 123", result); + } + { + Parser p = new Parser("abc %-4.5OTT"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("abc 123 ", result); + } + { + Parser p = new Parser("abc %3.4hello"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("abc ello", result); + } + { + Parser p = new Parser("abc %-3.-4hello"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("abc Hell", result); + } + } + + @Test + public void testComposite() throws Exception { +// { +// Parser p = new Parser("%(ABC)"); +// p.setContext(context); +// Node t = p.parse(); +// Converter head = p.compile(t, converterMap); +// String result = write(head, new Object()); +// assertEquals("ABC", result); +// } + { + Context c = new ContextBase(); + Parser p = new Parser("%(ABC %hello)"); + p.setContext(c); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + StatusPrinter.print(c); + assertEquals("ABC Hello", result); + } + { + Parser p = new Parser("%(ABC %hello)"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("ABC Hello", result); + } + } + + @Test + public void testCompositeFormatting() throws Exception { + { + Parser p = new Parser("xyz %4.10(ABC)"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("xyz ABC", result); + } + + { + Parser p = new Parser("xyz %-4.10(ABC)"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("xyz ABC ", result); + } + + { + Parser p = new Parser("xyz %.2(ABC %hello)"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("xyz lo", result); + } + + { + Parser p = new Parser("xyz %.-2(ABC)"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("xyz AB", result); + } + + { + Parser p = new Parser("xyz %30.30(ABC %20hello)"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("xyz ABC Hello", result); + } + } + + @Test + public void testUnknownWord() throws Exception { + Parser p = new Parser("%unknown"); + p.setContext(context); + Node t = p.parse(); + p.compile(t, converterMap); + StatusChecker chercker = new StatusChecker(context.getStatusManager()); + assertTrue(chercker + .containsMatch("\\[unknown] is not a valid conversion word")); + } + + @Test + public void testWithNopEscape() throws Exception { + { + Parser p = new Parser("xyz %hello\\_world"); + p.setContext(context); + Node t = p.parse(); + Converter head = p.compile(t, converterMap); + String result = write(head, new Object()); + assertEquals("xyz Helloworld", result); + } + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/FormatInfoTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/FormatInfoTest.java index 61d4e3e33e072214dbba2f77cb8b3a3229c03774..33565afaa86ab34e04232c12c3f6a67f88f7a318 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/FormatInfoTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/FormatInfoTest.java @@ -1,120 +1,120 @@ -/** - * 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 static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import org.junit.Test; - -import ch.qos.logback.core.pattern.FormatInfo; - - -public class FormatInfoTest { - - @Test - public void testEndingInDot() { - try { - FormatInfo.valueOf("45."); - fail("45. is not a valid format info string"); - } catch (IllegalArgumentException iae) { - // OK - } - } - - @Test - public void testBasic() { - { - FormatInfo fi = FormatInfo.valueOf("45"); - FormatInfo witness = new FormatInfo(); - witness.setMin(45); - assertEquals(witness, fi); - } - - { - FormatInfo fi = FormatInfo.valueOf("4.5"); - FormatInfo witness = new FormatInfo(); - witness.setMin(4); - witness.setMax(5); - assertEquals(witness, fi); - } - } - - @Test - public void testRightPad() { - { - FormatInfo fi = FormatInfo.valueOf("-40"); - FormatInfo witness = new FormatInfo(); - witness.setMin(40); - witness.setLeftPad(false); - assertEquals(witness, fi); - } - - { - FormatInfo fi = FormatInfo.valueOf("-12.5"); - FormatInfo witness = new FormatInfo(); - witness.setMin(12); - witness.setMax(5); - witness.setLeftPad(false); - assertEquals(witness, fi); - } - - { - FormatInfo fi = FormatInfo.valueOf("-14.-5"); - FormatInfo witness = new FormatInfo(); - witness.setMin(14); - witness.setMax(5); - witness.setLeftPad(false); - witness.setLeftTruncate(false); - assertEquals(witness, fi); - } - } - - @Test - public void testMinOnly() { - { - FormatInfo fi = FormatInfo.valueOf("49"); - FormatInfo witness = new FormatInfo(); - witness.setMin(49); - assertEquals(witness, fi); - } - - { - FormatInfo fi = FormatInfo.valueOf("-587"); - FormatInfo witness = new FormatInfo(); - witness.setMin(587); - witness.setLeftPad(false); - assertEquals(witness, fi); - } - - } - - @Test - public void testMaxOnly() { - { - FormatInfo fi = FormatInfo.valueOf(".49"); - FormatInfo witness = new FormatInfo(); - witness.setMax(49); - assertEquals(witness, fi); - } - - { - FormatInfo fi = FormatInfo.valueOf(".-5"); - FormatInfo witness = new FormatInfo(); - witness.setMax(5); - witness.setLeftTruncate(false); - assertEquals(witness, fi); - } - } +/** + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import org.junit.Test; + +import ch.qos.logback.core.pattern.FormatInfo; + + +public class FormatInfoTest { + + @Test + public void testEndingInDot() { + try { + FormatInfo.valueOf("45."); + fail("45. is not a valid format info string"); + } catch (IllegalArgumentException iae) { + // OK + } + } + + @Test + public void testBasic() { + { + FormatInfo fi = FormatInfo.valueOf("45"); + FormatInfo witness = new FormatInfo(); + witness.setMin(45); + assertEquals(witness, fi); + } + + { + FormatInfo fi = FormatInfo.valueOf("4.5"); + FormatInfo witness = new FormatInfo(); + witness.setMin(4); + witness.setMax(5); + assertEquals(witness, fi); + } + } + + @Test + public void testRightPad() { + { + FormatInfo fi = FormatInfo.valueOf("-40"); + FormatInfo witness = new FormatInfo(); + witness.setMin(40); + witness.setLeftPad(false); + assertEquals(witness, fi); + } + + { + FormatInfo fi = FormatInfo.valueOf("-12.5"); + FormatInfo witness = new FormatInfo(); + witness.setMin(12); + witness.setMax(5); + witness.setLeftPad(false); + assertEquals(witness, fi); + } + + { + FormatInfo fi = FormatInfo.valueOf("-14.-5"); + FormatInfo witness = new FormatInfo(); + witness.setMin(14); + witness.setMax(5); + witness.setLeftPad(false); + witness.setLeftTruncate(false); + assertEquals(witness, fi); + } + } + + @Test + public void testMinOnly() { + { + FormatInfo fi = FormatInfo.valueOf("49"); + FormatInfo witness = new FormatInfo(); + witness.setMin(49); + assertEquals(witness, fi); + } + + { + FormatInfo fi = FormatInfo.valueOf("-587"); + FormatInfo witness = new FormatInfo(); + witness.setMin(587); + witness.setLeftPad(false); + assertEquals(witness, fi); + } + + } + + @Test + public void testMaxOnly() { + { + FormatInfo fi = FormatInfo.valueOf(".49"); + FormatInfo witness = new FormatInfo(); + witness.setMax(49); + assertEquals(witness, fi); + } + + { + FormatInfo fi = FormatInfo.valueOf(".-5"); + FormatInfo witness = new FormatInfo(); + witness.setMax(5); + witness.setLeftTruncate(false); + assertEquals(witness, fi); + } + } } \ No newline at end of file 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 7ec9078d7588d90612ab8711d349215f9cb19e4f..e1a3d532c762bbcc4b3b85afe582683c985b2d70 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 @@ -1,123 +1,123 @@ -/** - * 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 static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -public class OptionTokenizerTest { - - @Test - public void testEmpty() throws ScanException { - { - List ol = new OptionTokenizer("").tokenize(); - List witness = new ArrayList(); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer(" ").tokenize(); - List witness = new ArrayList(); - assertEquals(witness, ol); - } - } - - @Test - public void testSimple() throws ScanException { - { - List ol = new OptionTokenizer("abc").tokenize(); - List witness = new ArrayList(); - witness.add("abc"); - assertEquals(witness, ol); - } - } - - @Test - public void testSingleQuote() throws ScanException { - { - List ol = new OptionTokenizer("' '").tokenize(); - List witness = new ArrayList(); - witness.add(" "); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("' x\t'").tokenize(); - List witness = new ArrayList(); - witness.add(" x\t"); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("' x\\t'").tokenize(); - List witness = new ArrayList(); - witness.add(" x\t"); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("' x\\''").tokenize(); - List witness = new ArrayList(); - witness.add(" x\'"); - assertEquals(witness, ol); - } - } - - @Test - public void testDoubleQuote() throws ScanException { - { - List ol = new OptionTokenizer("\" \"").tokenize(); - List witness = new ArrayList(); - witness.add(" "); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("\" x\t\"").tokenize(); - List witness = new ArrayList(); - witness.add(" x\t"); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("\" x\\t\"").tokenize(); - List witness = new ArrayList(); - witness.add(" x\t"); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("\" x\\\"\"").tokenize(); - List witness = new ArrayList(); - witness.add(" x\""); - assertEquals(witness, ol); - } - } - - @Test - public void testMultiple() throws ScanException { - { - List ol = new OptionTokenizer("a, b").tokenize(); - List witness = new ArrayList(); - witness.add("a"); - witness.add("b"); - assertEquals(witness, ol); - } - } - +/** + * 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 static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +public class OptionTokenizerTest { + + @Test + public void testEmpty() throws ScanException { + { + List ol = new OptionTokenizer("").tokenize(); + List witness = new ArrayList(); + assertEquals(witness, ol); + } + + { + List ol = new OptionTokenizer(" ").tokenize(); + List witness = new ArrayList(); + assertEquals(witness, ol); + } + } + + @Test + public void testSimple() throws ScanException { + { + List ol = new OptionTokenizer("abc").tokenize(); + List witness = new ArrayList(); + witness.add("abc"); + assertEquals(witness, ol); + } + } + + @Test + public void testSingleQuote() throws ScanException { + { + List ol = new OptionTokenizer("' '").tokenize(); + List witness = new ArrayList(); + witness.add(" "); + assertEquals(witness, ol); + } + + { + List ol = new OptionTokenizer("' x\t'").tokenize(); + List witness = new ArrayList(); + witness.add(" x\t"); + assertEquals(witness, ol); + } + + { + List ol = new OptionTokenizer("' x\\t'").tokenize(); + List witness = new ArrayList(); + witness.add(" x\t"); + assertEquals(witness, ol); + } + + { + List ol = new OptionTokenizer("' x\\''").tokenize(); + List witness = new ArrayList(); + witness.add(" x\'"); + assertEquals(witness, ol); + } + } + + @Test + public void testDoubleQuote() throws ScanException { + { + List ol = new OptionTokenizer("\" \"").tokenize(); + List witness = new ArrayList(); + witness.add(" "); + assertEquals(witness, ol); + } + + { + List ol = new OptionTokenizer("\" x\t\"").tokenize(); + List witness = new ArrayList(); + witness.add(" x\t"); + assertEquals(witness, ol); + } + + { + List ol = new OptionTokenizer("\" x\\t\"").tokenize(); + List witness = new ArrayList(); + witness.add(" x\t"); + assertEquals(witness, ol); + } + + { + List ol = new OptionTokenizer("\" x\\\"\"").tokenize(); + List witness = new ArrayList(); + witness.add(" x\""); + assertEquals(witness, ol); + } + } + + @Test + public void testMultiple() throws ScanException { + { + List ol = new OptionTokenizer("a, b").tokenize(); + List witness = new ArrayList(); + witness.add("a"); + 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/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/PackageTest.java index 0ac5169cf62f8572ff913dcacd2469f268cd1299..97d8501ca6038581871fc8bced544459cda489db 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/PackageTest.java @@ -1,28 +1,28 @@ -/** - * 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 org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({TokenStreamTest.class, - OptionTokenizerTest.class, - ParserTest.class, - FormatInfoTest.class, - CompilerTest.class, - SamplePatternLayoutTest.class}) -public class PackageTest { -} +/** + * 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 org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({TokenStreamTest.class, + OptionTokenizerTest.class, + ParserTest.class, + FormatInfoTest.class, + CompilerTest.class, + SamplePatternLayoutTest.class}) +public class PackageTest { +} 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 4144fc5b1c38c97764b8818181d8c3e8c1b2bede..e9d01e94d0b15a334cfc6b3f425b835a7413db66 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 @@ -1,245 +1,245 @@ -/** - * 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 static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import ch.qos.logback.core.pattern.FormatInfo; - -public class ParserTest { - - @Test - public void testBasic() throws Exception { - Parser p = new Parser("hello"); - Node t = p.parse(); - assertEquals(Node.LITERAL, t.getType()); - assertEquals("hello", t.getValue()); - } - - @Test - public void testKeyword() throws Exception { - - { - Parser p = new Parser("hello%xyz"); - Node t = p.parse(); - Node witness = new Node(Node.LITERAL, "hello"); - witness.next = new KeywordNode("xyz"); - assertEquals(witness, t); - } - - { - Parser p = new Parser("hello%xyz{x}"); - Node t = p.parse(); - Node witness = new Node(Node.LITERAL, "hello"); - KeywordNode n = new KeywordNode("xyz"); - List optionList = new ArrayList(); - optionList.add("x"); - n.setOptions(optionList); - witness.next = n; - assertEquals(witness, t); - } - } - - @Test - public void testComposite() throws Exception { - { - Parser p = new Parser("hello%(%child)"); - Node t = p.parse(); - - Node witness = new Node(Node.LITERAL, "hello"); - CompositeNode composite = new CompositeNode(); - Node child = new KeywordNode("child"); - composite.setChildNode(child); - witness.next = composite; - - // System.out.println("w:" + witness); - // System.out.println(t); - - assertEquals(witness, t); - } - - // System.out.println("testRecursive part 2"); - { - Parser p = new Parser("hello%(%child )"); - Node t = p.parse(); - - Node witness = new Node(Node.LITERAL, "hello"); - CompositeNode composite = new CompositeNode(); - Node child = new KeywordNode("child"); - composite.setChildNode(child); - witness.next = composite; - child.next = new Node(Node.LITERAL, " "); - assertEquals(witness, t); - } - - { - 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"); - composite.setChildNode(child); - child.next = new Node(Node.LITERAL, " "); - child.next.next = new KeywordNode("h"); - witness.next = composite; - assertEquals(witness, t); - } - - { - 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"); - composite.setChildNode(child); - child.next = new Node(Node.LITERAL, " "); - child.next.next = new KeywordNode("h"); - witness.next = composite; - composite.next = new Node(Node.LITERAL, " "); - composite.next.next = new KeywordNode("m"); - assertEquals(witness, t); - } - - { - 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 Node(Node.LITERAL, " "); - composite.setChildNode(child); - Node c = child; - c = c.next = new KeywordNode("child"); - c = c.next = new Node(Node.LITERAL, " ("); - c = c.next = new KeywordNode("h"); - c = c.next = new Node(Node.LITERAL, ") "); - witness.next = composite; - composite.next = new Node(Node.LITERAL, " "); - composite.next.next = new KeywordNode("m"); - assertEquals(witness, t); - - } - } - - @Test - public void testNested() throws Exception { - { - Parser p = new Parser("%top %(%child%(%h))"); - Node t = p.parse(); - Node witness = new KeywordNode("top"); - Node w = witness.next = new Node(Node.LITERAL, " "); - CompositeNode composite = new CompositeNode(); - w = w.next = composite; - Node child = new KeywordNode("child"); - composite.setChildNode(child); - composite = new CompositeNode(); - child.next = composite; - composite.setChildNode(new KeywordNode("h")); - - assertEquals(witness, t); - } - } - - @Test - public void testFormattingInfo() throws Exception { - { - Parser p = new Parser("%45x"); - Node t = p.parse(); - FormattingNode witness = new KeywordNode("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"); - witness.setFormatInfo(new FormatInfo(4, 5)); - assertEquals(witness, t); - } - - { - Parser p = new Parser("%-4.5x"); - Node t = p.parse(); - FormattingNode witness = new KeywordNode("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"); - witness.setFormatInfo(new FormatInfo(4, 5, false, false)); - assertEquals(witness, t); - } - - { - Parser p = new Parser("%-4.5x %12y"); - Node t = p.parse(); - FormattingNode witness = new KeywordNode("x"); - witness.setFormatInfo(new FormatInfo(4, 5, false, true)); - Node n = witness.next = new Node(Node.LITERAL, " "); - n = n.next = new KeywordNode("y"); - ((FormattingNode) n).setFormatInfo(new FormatInfo(12, Integer.MAX_VALUE)); - assertEquals(witness, t); - } - } - - @Test - public void testOptions() throws Exception { - { - Parser p = new Parser("%45x{'test '}"); - Node t = p.parse(); - KeywordNode witness = new KeywordNode("x"); - witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE)); - List ol = new ArrayList(); - ol.add("test "); - witness.setOptions(ol); - assertEquals(witness, t); - } - - { - Parser p = new Parser("%45x{a, b}"); - Node t = p.parse(); - KeywordNode witness = new KeywordNode("x"); - witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE)); - List ol = new ArrayList(); - ol.add("a"); - ol.add("b"); - witness.setOptions(ol); - assertEquals(witness, t); - } - } - - @Test - public void testCompositeFormatting() throws Exception { - - { - Parser p = new Parser("hello%5(XYZ)"); - Node t = p.parse(); - - Node witness = new Node(Node.LITERAL, "hello"); - CompositeNode composite = new CompositeNode(); - composite.setFormatInfo(new FormatInfo(5, Integer.MAX_VALUE)); - Node child = new Node(Node.LITERAL, "XYZ"); - composite.setChildNode(child); - witness.next = composite; - - assertEquals(witness, t); - } - } +/** + * 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 static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import ch.qos.logback.core.pattern.FormatInfo; + +public class ParserTest { + + @Test + public void testBasic() throws Exception { + Parser p = new Parser("hello"); + Node t = p.parse(); + assertEquals(Node.LITERAL, t.getType()); + assertEquals("hello", t.getValue()); + } + + @Test + public void testKeyword() throws Exception { + + { + Parser p = new Parser("hello%xyz"); + Node t = p.parse(); + Node witness = new Node(Node.LITERAL, "hello"); + witness.next = new KeywordNode("xyz"); + assertEquals(witness, t); + } + + { + Parser p = new Parser("hello%xyz{x}"); + Node t = p.parse(); + Node witness = new Node(Node.LITERAL, "hello"); + KeywordNode n = new KeywordNode("xyz"); + List optionList = new ArrayList(); + optionList.add("x"); + n.setOptions(optionList); + witness.next = n; + assertEquals(witness, t); + } + } + + @Test + public void testComposite() throws Exception { + { + Parser p = new Parser("hello%(%child)"); + Node t = p.parse(); + + Node witness = new Node(Node.LITERAL, "hello"); + CompositeNode composite = new CompositeNode(); + Node child = new KeywordNode("child"); + composite.setChildNode(child); + witness.next = composite; + + // System.out.println("w:" + witness); + // System.out.println(t); + + assertEquals(witness, t); + } + + // System.out.println("testRecursive part 2"); + { + Parser p = new Parser("hello%(%child )"); + Node t = p.parse(); + + Node witness = new Node(Node.LITERAL, "hello"); + CompositeNode composite = new CompositeNode(); + Node child = new KeywordNode("child"); + composite.setChildNode(child); + witness.next = composite; + child.next = new Node(Node.LITERAL, " "); + assertEquals(witness, t); + } + + { + 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"); + composite.setChildNode(child); + child.next = new Node(Node.LITERAL, " "); + child.next.next = new KeywordNode("h"); + witness.next = composite; + assertEquals(witness, t); + } + + { + 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"); + composite.setChildNode(child); + child.next = new Node(Node.LITERAL, " "); + child.next.next = new KeywordNode("h"); + witness.next = composite; + composite.next = new Node(Node.LITERAL, " "); + composite.next.next = new KeywordNode("m"); + assertEquals(witness, t); + } + + { + 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 Node(Node.LITERAL, " "); + composite.setChildNode(child); + Node c = child; + c = c.next = new KeywordNode("child"); + c = c.next = new Node(Node.LITERAL, " ("); + c = c.next = new KeywordNode("h"); + c = c.next = new Node(Node.LITERAL, ") "); + witness.next = composite; + composite.next = new Node(Node.LITERAL, " "); + composite.next.next = new KeywordNode("m"); + assertEquals(witness, t); + + } + } + + @Test + public void testNested() throws Exception { + { + Parser p = new Parser("%top %(%child%(%h))"); + Node t = p.parse(); + Node witness = new KeywordNode("top"); + Node w = witness.next = new Node(Node.LITERAL, " "); + CompositeNode composite = new CompositeNode(); + w = w.next = composite; + Node child = new KeywordNode("child"); + composite.setChildNode(child); + composite = new CompositeNode(); + child.next = composite; + composite.setChildNode(new KeywordNode("h")); + + assertEquals(witness, t); + } + } + + @Test + public void testFormattingInfo() throws Exception { + { + Parser p = new Parser("%45x"); + Node t = p.parse(); + FormattingNode witness = new KeywordNode("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"); + witness.setFormatInfo(new FormatInfo(4, 5)); + assertEquals(witness, t); + } + + { + Parser p = new Parser("%-4.5x"); + Node t = p.parse(); + FormattingNode witness = new KeywordNode("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"); + witness.setFormatInfo(new FormatInfo(4, 5, false, false)); + assertEquals(witness, t); + } + + { + Parser p = new Parser("%-4.5x %12y"); + Node t = p.parse(); + FormattingNode witness = new KeywordNode("x"); + witness.setFormatInfo(new FormatInfo(4, 5, false, true)); + Node n = witness.next = new Node(Node.LITERAL, " "); + n = n.next = new KeywordNode("y"); + ((FormattingNode) n).setFormatInfo(new FormatInfo(12, Integer.MAX_VALUE)); + assertEquals(witness, t); + } + } + + @Test + public void testOptions() throws Exception { + { + Parser p = new Parser("%45x{'test '}"); + Node t = p.parse(); + KeywordNode witness = new KeywordNode("x"); + witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE)); + List ol = new ArrayList(); + ol.add("test "); + witness.setOptions(ol); + assertEquals(witness, t); + } + + { + Parser p = new Parser("%45x{a, b}"); + Node t = p.parse(); + KeywordNode witness = new KeywordNode("x"); + witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE)); + List ol = new ArrayList(); + ol.add("a"); + ol.add("b"); + witness.setOptions(ol); + assertEquals(witness, t); + } + } + + @Test + public void testCompositeFormatting() throws Exception { + + { + Parser p = new Parser("hello%5(XYZ)"); + Node t = p.parse(); + + Node witness = new Node(Node.LITERAL, "hello"); + CompositeNode composite = new CompositeNode(); + composite.setFormatInfo(new FormatInfo(5, Integer.MAX_VALUE)); + Node child = new Node(Node.LITERAL, "XYZ"); + composite.setChildNode(child); + witness.next = composite; + + assertEquals(witness, t); + } + } } \ No newline at end of file diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/SamplePatternLayout.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/SamplePatternLayout.java index 33ad012b106419ec2e9fa42fcac30da974533706..a549a4496f90e1747c6eac637fe151ef4120d96b 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/SamplePatternLayout.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/SamplePatternLayout.java @@ -1,42 +1,42 @@ -/** - * 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.HashMap; -import java.util.Map; - -import ch.qos.logback.core.pattern.Converter123; -import ch.qos.logback.core.pattern.ConverterHello; -import ch.qos.logback.core.pattern.PatternLayoutBase; - - - -public class SamplePatternLayout extends PatternLayoutBase { - - Map converterMap = new HashMap(); - - public SamplePatternLayout() { - converterMap.put("OTT", Converter123.class.getName()); - converterMap.put("hello", ConverterHello.class.getName()); - } - - public Map getDefaultConverterMap() { - return converterMap; - } - - public String doLayout(E event) { - return writeLoopOnConverters(event); - } - -} +/** + * 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.HashMap; +import java.util.Map; + +import ch.qos.logback.core.pattern.Converter123; +import ch.qos.logback.core.pattern.ConverterHello; +import ch.qos.logback.core.pattern.PatternLayoutBase; + + + +public class SamplePatternLayout extends PatternLayoutBase { + + Map converterMap = new HashMap(); + + public SamplePatternLayout() { + converterMap.put("OTT", Converter123.class.getName()); + converterMap.put("hello", ConverterHello.class.getName()); + } + + public Map getDefaultConverterMap() { + return converterMap; + } + + public String doLayout(E event) { + return writeLoopOnConverters(event); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/SamplePatternLayoutTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/SamplePatternLayoutTest.java index 1e797461bc72f71f6c6829a65536a2d3e3a522f7..befeef39e93627589d586a28cb0dddff4e20b37c 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/SamplePatternLayoutTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/SamplePatternLayoutTest.java @@ -1,92 +1,92 @@ -/** - * 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 static org.junit.Assert.*; - -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.pattern.PatternLayoutBase; - - -public class SamplePatternLayoutTest extends AbstractPatternLayoutBaseTest { - - Context context = new ContextBase(); - - public PatternLayoutBase getPatternLayoutBase() { - return new SamplePatternLayout(); - } - - public Object getEventObject() { - return new Object(); - } - - @Test - public void testOK() { - PatternLayoutBase plb = getPatternLayoutBase(); - Context context = new ContextBase(); - plb.setContext(context); - plb.setPattern("x%OTT"); - plb.start(); - String s = plb.doLayout(new Object()); - //System.out.println(s); - - //StatusManager sm = context.getStatusManager(); - //StatusPrinter.print(sm); - assertEquals("x123", s); - } - - - - @Test - public void testEscapeClosingParentheses() { - PatternLayoutBase plb = getPatternLayoutBase(); - Context context = new ContextBase(); - plb.setContext(context); - plb.setPattern("x(%OTT\\)y"); - plb.start(); - String s = plb.doLayout(new Object()); - assertEquals("x(123)y", s); - } - - @Test - public void testEscapeBothParentheses() { - PatternLayoutBase plb = getPatternLayoutBase(); - Context context = new ContextBase(); - plb.setContext(context); - plb.setPattern("x\\(%OTT\\)y"); - plb.start(); - String s = plb.doLayout(new Object()); - assertEquals("x(123)y", s); - } - - @Test - public void testPercentAsLiteral() { - PatternLayoutBase plb = getPatternLayoutBase(); - Context context = new ContextBase(); - plb.setContext(context); - plb.setPattern("hello \\% world"); - plb.start(); - String s = plb.doLayout(new Object()); - assertEquals("hello % world", s); - } - - - @Override - public Context getContext() { - return context; - } -} +/** + * 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 static org.junit.Assert.*; + +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.pattern.PatternLayoutBase; + + +public class SamplePatternLayoutTest extends AbstractPatternLayoutBaseTest { + + Context context = new ContextBase(); + + public PatternLayoutBase getPatternLayoutBase() { + return new SamplePatternLayout(); + } + + public Object getEventObject() { + return new Object(); + } + + @Test + public void testOK() { + PatternLayoutBase plb = getPatternLayoutBase(); + Context context = new ContextBase(); + plb.setContext(context); + plb.setPattern("x%OTT"); + plb.start(); + String s = plb.doLayout(new Object()); + //System.out.println(s); + + //StatusManager sm = context.getStatusManager(); + //StatusPrinter.print(sm); + assertEquals("x123", s); + } + + + + @Test + public void testEscapeClosingParentheses() { + PatternLayoutBase plb = getPatternLayoutBase(); + Context context = new ContextBase(); + plb.setContext(context); + plb.setPattern("x(%OTT\\)y"); + plb.start(); + String s = plb.doLayout(new Object()); + assertEquals("x(123)y", s); + } + + @Test + public void testEscapeBothParentheses() { + PatternLayoutBase plb = getPatternLayoutBase(); + Context context = new ContextBase(); + plb.setContext(context); + plb.setPattern("x\\(%OTT\\)y"); + plb.start(); + String s = plb.doLayout(new Object()); + assertEquals("x(123)y", s); + } + + @Test + public void testPercentAsLiteral() { + PatternLayoutBase plb = getPatternLayoutBase(); + Context context = new ContextBase(); + plb.setContext(context); + plb.setPattern("hello \\% world"); + plb.start(); + String s = plb.doLayout(new Object()); + assertEquals("hello % world", s); + } + + + @Override + public Context getContext() { + return context; + } +} 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 0e08186d52091a1756a8504ddc8660ddc8f11605..4ce47ceddd8c83cdaa62d24be5675385db37c23d 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 @@ -1,343 +1,343 @@ -/** - * 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 static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import ch.qos.logback.core.pattern.util.AlmostAsIsEscapeUtil; - -public class TokenStreamTest { - - - @Test - public void testEmpty() throws ScanException { - List tl = new TokenStream("").tokenize(); - List witness = new ArrayList(); - assertEquals(witness, tl); - } - - @Test - public void testSingleLiteral() throws ScanException { - List tl = new TokenStream("hello").tokenize(); - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "hello")); - assertEquals(witness, tl); - } - - @Test - public void testLiteralWithPercent() throws ScanException { - { - List tl = new TokenStream("hello\\%world").tokenize(); - - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "hello%world")); - assertEquals(witness, tl); - } - { - List tl = new TokenStream("hello\\%").tokenize(); - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "hello%")); - assertEquals(witness, tl); - } - - { - List tl = new TokenStream("\\%").tokenize(); - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "%")); - assertEquals(witness, tl); - } - } - - @Test - public void testBasic() throws ScanException { - - // test "%c" - { - List tl = new TokenStream("%c").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "c")); - assertEquals(witness, tl); - } - - { - // test "xyz%-34c" - List tl = new TokenStream("%a%b").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "a")); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "b")); - assertEquals(witness, tl); - } - - { - // test "xyz%-34c" - List tl = new TokenStream("xyz%-34c").tokenize(); - List witness = new ArrayList(); - 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")); - assertEquals(witness, tl); - } - } - - @Test - public void testComplexNR() throws ScanException { - List tl = new TokenStream("%d{1234} [%34.-67toto] %n").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.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.LITERAL, "] ")); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "n")); - assertEquals(witness, tl); - } - - @Test - public void testEmptyP() throws ScanException { - List tl = new TokenStream("()").tokenize(); - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "(")); - witness.add(Token.RIGHT_PARENTHESIS_TOKEN); - assertEquals(witness, tl); - } - - @Test - public void testEmptyP2() throws ScanException { - List tl = new TokenStream("%()").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(Token.LEFT_PARENTHESIS_TOKEN); - witness.add(Token.RIGHT_PARENTHESIS_TOKEN); - assertEquals(witness, tl); - } - - @Test - public void testEscape() throws ScanException { - { - List tl = new TokenStream("\\%").tokenize(); - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "%")); - assertEquals(witness, tl); - } - - { - List tl = new TokenStream("\\%\\(\\t\\)\\r\\n").tokenize(); - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "%(\t)\r\n")); - assertEquals(witness, tl); - } - - { - List tl = new TokenStream("\\\\%x").tokenize(); - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "\\")); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); - assertEquals(witness, tl); - } - - { - List tl = new TokenStream("%x\\)").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); - witness.add(new Token(Token.LITERAL, ")")); - assertEquals(witness, tl); - } - - { - List tl = new TokenStream("%x\\_a").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); - witness.add(new Token(Token.LITERAL, "a")); - assertEquals(witness, tl); - } - { - List tl = new TokenStream("%x\\_%b").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "b")); - assertEquals(witness, tl); - } - } - - @Test - public void testOptions() throws ScanException { - { - List tl = new TokenStream("%x{t}").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); - witness.add(new Token(Token.OPTION, "t")); - assertEquals(witness, tl); - } - - { - List tl = new TokenStream("%x{t,y}").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); - witness.add(new Token(Token.OPTION, "t,y")); - assertEquals(witness, tl); - } - - { - List tl = new TokenStream("%x{\"hello world.\", \"12y \"}").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); - witness.add(new Token(Token.OPTION, "\"hello world.\", \"12y \"")); - assertEquals(witness, tl); - } - - { - List tl = new TokenStream("%x{opt\\}}").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); - witness.add(new Token(Token.OPTION, "opt}")); - assertEquals(witness, tl); - } - } - - @Test - public void testSimpleP() throws ScanException { - List tl = new TokenStream("%(hello %class{.4?})").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(Token.LEFT_PARENTHESIS_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.OPTION, ".4?")); - witness.add(Token.RIGHT_PARENTHESIS_TOKEN); - assertEquals(witness, tl); - } - - @Test - public void testSimpleP2() throws ScanException { - List tl = new TokenStream("X %a %-12.550(hello %class{.4?})").tokenize(); - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "X ")); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.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(new Token(Token.LITERAL, "hello ")); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "class")); - witness.add(new Token(Token.OPTION, ".4?")); - witness.add(Token.RIGHT_PARENTHESIS_TOKEN); - assertEquals(witness, tl); - } - - @Test - public void testMultipleRecursion() throws ScanException { - List tl = new TokenStream("%-1(%d %45(%class %file))").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.FORMAT_MODIFIER, "-1")); - witness.add(Token.LEFT_PARENTHESIS_TOKEN); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.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.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "class")); - witness.add(new Token(Token.LITERAL, " ")); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "file")); - witness.add(Token.RIGHT_PARENTHESIS_TOKEN); - witness.add(Token.RIGHT_PARENTHESIS_TOKEN); - - assertEquals(witness, tl); - } - - @Test - public void testNested() throws ScanException { - List tl = new TokenStream("%(%a%(%b))").tokenize(); - List witness = new ArrayList(); - witness.add(Token.PERCENT_TOKEN); - witness.add(Token.LEFT_PARENTHESIS_TOKEN); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "a")); - witness.add(Token.PERCENT_TOKEN); - witness.add(Token.LEFT_PARENTHESIS_TOKEN); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "b")); - witness.add(Token.RIGHT_PARENTHESIS_TOKEN); - witness.add(Token.RIGHT_PARENTHESIS_TOKEN); - - assertEquals(witness, tl); - - } - - @Test - public void testEscapedParanteheses() throws ScanException { - { - List tl = new TokenStream("\\(%h\\)").tokenize(); - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "(")); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "h")); - witness.add(new Token(Token.LITERAL, ")")); - assertEquals(witness, tl); - } - { - List tl = new TokenStream("(%h\\)").tokenize(); - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "(")); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "h")); - witness.add(new Token(Token.LITERAL, ")")); - assertEquals(witness, tl); - } - } - - @Test - public void testWindowsLikeBackSlashes() throws ScanException { - { - List tl = new TokenStream("c:\\hello\\world.%i", new AlmostAsIsEscapeUtil()) - .tokenize(); - - List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "c:\\hello\\world.")); - witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "i")); - assertEquals(witness, tl); - } - } +/** + * 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 static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import ch.qos.logback.core.pattern.util.AlmostAsIsEscapeUtil; + +public class TokenStreamTest { + + + @Test + public void testEmpty() throws ScanException { + List tl = new TokenStream("").tokenize(); + List witness = new ArrayList(); + assertEquals(witness, tl); + } + + @Test + public void testSingleLiteral() throws ScanException { + List tl = new TokenStream("hello").tokenize(); + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "hello")); + assertEquals(witness, tl); + } + + @Test + public void testLiteralWithPercent() throws ScanException { + { + List tl = new TokenStream("hello\\%world").tokenize(); + + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "hello%world")); + assertEquals(witness, tl); + } + { + List tl = new TokenStream("hello\\%").tokenize(); + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "hello%")); + assertEquals(witness, tl); + } + + { + List tl = new TokenStream("\\%").tokenize(); + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "%")); + assertEquals(witness, tl); + } + } + + @Test + public void testBasic() throws ScanException { + + // test "%c" + { + List tl = new TokenStream("%c").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "c")); + assertEquals(witness, tl); + } + + { + // test "xyz%-34c" + List tl = new TokenStream("%a%b").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "a")); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "b")); + assertEquals(witness, tl); + } + + { + // test "xyz%-34c" + List tl = new TokenStream("xyz%-34c").tokenize(); + List witness = new ArrayList(); + 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")); + assertEquals(witness, tl); + } + } + + @Test + public void testComplexNR() throws ScanException { + List tl = new TokenStream("%d{1234} [%34.-67toto] %n").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.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.LITERAL, "] ")); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "n")); + assertEquals(witness, tl); + } + + @Test + public void testEmptyP() throws ScanException { + List tl = new TokenStream("()").tokenize(); + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "(")); + witness.add(Token.RIGHT_PARENTHESIS_TOKEN); + assertEquals(witness, tl); + } + + @Test + public void testEmptyP2() throws ScanException { + List tl = new TokenStream("%()").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(Token.LEFT_PARENTHESIS_TOKEN); + witness.add(Token.RIGHT_PARENTHESIS_TOKEN); + assertEquals(witness, tl); + } + + @Test + public void testEscape() throws ScanException { + { + List tl = new TokenStream("\\%").tokenize(); + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "%")); + assertEquals(witness, tl); + } + + { + List tl = new TokenStream("\\%\\(\\t\\)\\r\\n").tokenize(); + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "%(\t)\r\n")); + assertEquals(witness, tl); + } + + { + List tl = new TokenStream("\\\\%x").tokenize(); + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "\\")); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "x")); + assertEquals(witness, tl); + } + + { + List tl = new TokenStream("%x\\)").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.LITERAL, ")")); + assertEquals(witness, tl); + } + + { + List tl = new TokenStream("%x\\_a").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.LITERAL, "a")); + assertEquals(witness, tl); + } + { + List tl = new TokenStream("%x\\_%b").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "x")); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "b")); + assertEquals(witness, tl); + } + } + + @Test + public void testOptions() throws ScanException { + { + List tl = new TokenStream("%x{t}").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.OPTION, "t")); + assertEquals(witness, tl); + } + + { + List tl = new TokenStream("%x{t,y}").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.OPTION, "t,y")); + assertEquals(witness, tl); + } + + { + List tl = new TokenStream("%x{\"hello world.\", \"12y \"}").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.OPTION, "\"hello world.\", \"12y \"")); + assertEquals(witness, tl); + } + + { + List tl = new TokenStream("%x{opt\\}}").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.OPTION, "opt}")); + assertEquals(witness, tl); + } + } + + @Test + public void testSimpleP() throws ScanException { + List tl = new TokenStream("%(hello %class{.4?})").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(Token.LEFT_PARENTHESIS_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.OPTION, ".4?")); + witness.add(Token.RIGHT_PARENTHESIS_TOKEN); + assertEquals(witness, tl); + } + + @Test + public void testSimpleP2() throws ScanException { + List tl = new TokenStream("X %a %-12.550(hello %class{.4?})").tokenize(); + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "X ")); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.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(new Token(Token.LITERAL, "hello ")); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "class")); + witness.add(new Token(Token.OPTION, ".4?")); + witness.add(Token.RIGHT_PARENTHESIS_TOKEN); + assertEquals(witness, tl); + } + + @Test + public void testMultipleRecursion() throws ScanException { + List tl = new TokenStream("%-1(%d %45(%class %file))").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.FORMAT_MODIFIER, "-1")); + witness.add(Token.LEFT_PARENTHESIS_TOKEN); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.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.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "class")); + witness.add(new Token(Token.LITERAL, " ")); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "file")); + witness.add(Token.RIGHT_PARENTHESIS_TOKEN); + witness.add(Token.RIGHT_PARENTHESIS_TOKEN); + + assertEquals(witness, tl); + } + + @Test + public void testNested() throws ScanException { + List tl = new TokenStream("%(%a%(%b))").tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(Token.LEFT_PARENTHESIS_TOKEN); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "a")); + witness.add(Token.PERCENT_TOKEN); + witness.add(Token.LEFT_PARENTHESIS_TOKEN); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "b")); + witness.add(Token.RIGHT_PARENTHESIS_TOKEN); + witness.add(Token.RIGHT_PARENTHESIS_TOKEN); + + assertEquals(witness, tl); + + } + + @Test + public void testEscapedParanteheses() throws ScanException { + { + List tl = new TokenStream("\\(%h\\)").tokenize(); + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "(")); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "h")); + witness.add(new Token(Token.LITERAL, ")")); + assertEquals(witness, tl); + } + { + List tl = new TokenStream("(%h\\)").tokenize(); + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "(")); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.KEYWORD, "h")); + witness.add(new Token(Token.LITERAL, ")")); + assertEquals(witness, tl); + } + } + + @Test + public void testWindowsLikeBackSlashes() throws ScanException { + { + List tl = new TokenStream("c:\\hello\\world.%i", new AlmostAsIsEscapeUtil()) + .tokenize(); + + List witness = new ArrayList(); + 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 diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/DelayerUtil.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/DelayerUtil.java index 58f9844cfb1e642b3d528033d87bed180c0fefb3..995c7682a22e4cc8785332b6e4f088c46eb457a9 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/DelayerUtil.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/DelayerUtil.java @@ -1,53 +1,53 @@ -/** - * 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.rolling; - -import java.util.Calendar; -import java.util.Date; - -public class DelayerUtil { - - // delay until millis in the next second - static void delayUntilNextSecond(int millis) { - long now = System.currentTimeMillis(); - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(now)); - - cal.set(Calendar.MILLISECOND, millis); - cal.add(Calendar.SECOND, 1); - - long next = cal.getTime().getTime(); - - try { - Thread.sleep(next - now); - } catch (Exception e) { - } - } - - static void delayUntilNextMinute(int seconds) { - long now = System.currentTimeMillis(); - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(now)); - - cal.set(Calendar.SECOND, seconds); - cal.add(Calendar.MINUTE, 1); - - long next = cal.getTime().getTime(); - - try { - Thread.sleep(next - now); - } catch (Exception e) { - } - } -} +/** + * 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.rolling; + +import java.util.Calendar; +import java.util.Date; + +public class DelayerUtil { + + // delay until millis in the next second + static void delayUntilNextSecond(int millis) { + long now = System.currentTimeMillis(); + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + + cal.set(Calendar.MILLISECOND, millis); + cal.add(Calendar.SECOND, 1); + + long next = cal.getTime().getTime(); + + try { + Thread.sleep(next - now); + } catch (Exception e) { + } + } + + static void delayUntilNextMinute(int seconds) { + long now = System.currentTimeMillis(); + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + + cal.set(Calendar.SECOND, seconds); + cal.add(Calendar.MINUTE, 1); + + long next = cal.getTime().getTime(); + + try { + Thread.sleep(next - now); + } catch (Exception e) { + } + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/FileOpener.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/FileOpener.java index 91dfd8ce2a5e781dda8414c40ec43554223ba36c..66f83130ecb5ffb820b2bc236ac2f1ba753b07ae 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/FileOpener.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/FileOpener.java @@ -1,33 +1,33 @@ -/** - * 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.rolling; - -import java.io.FileInputStream; -import java.io.InputStream; - - -/** - * Keep the file "output/test.log open for 10 seconds so that we can test - * RollingFileAppender's ability to roll file open by another process. - * @author Ceki Gülcü - */ -public class FileOpener { - public static void main(String[] args) throws Exception { - InputStream is = new FileInputStream("output/test.log"); - is.read(); - Thread.sleep(10000); - is.close(); - System.out.println("Exiting FileOpener"); - } -} +/** + * 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.rolling; + +import java.io.FileInputStream; +import java.io.InputStream; + + +/** + * Keep the file "output/test.log open for 10 seconds so that we can test + * RollingFileAppender's ability to roll file open by another process. + * @author Ceki Gülcü + */ +public class FileOpener { + public static void main(String[] args) throws Exception { + InputStream is = new FileInputStream("output/test.log"); + is.read(); + Thread.sleep(10000); + is.close(); + System.out.println("Exiting FileOpener"); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/MultiThreadedRollingTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/MultiThreadedRollingTest.java index 399cf809a637efbeed9e8ef89188af8a854b892a..c1b21e2933ef1b290479946c72af3ccb6f9f9eac 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/MultiThreadedRollingTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/MultiThreadedRollingTest.java @@ -1,215 +1,215 @@ -/** - * 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.rolling; - -import static org.junit.Assert.fail; - -import java.io.File; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.Layout; -import ch.qos.logback.core.contention.MultiThreadedHarness; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; -import ch.qos.logback.core.layout.EchoLayout; -import ch.qos.logback.core.status.StatusChecker; -import ch.qos.logback.core.testUtil.RandomUtil; -import ch.qos.logback.core.util.CoreTestConstants; -import ch.qos.logback.core.util.StatusPrinter; - -public class MultiThreadedRollingTest { - - final static int NUM_THREADS = 10; - final static int TOTAL_DURATION = 2000; - RunnableWithCounterAndDone[] runnableArray; - - Layout layout; - Context context = new ContextBase(); - - int diff = RandomUtil.getPositiveInt(); - String outputDirStr = CoreTestConstants.OUTPUT_DIR_PREFIX + "multi-" + diff - + "/"; - - RollingFileAppender rfa = new RollingFileAppender(); - - @Before - public void setUp() throws Exception { - layout = new EchoLayout(); - File outputDir = new File(outputDirStr); - outputDir.mkdirs(); - - rfa.setName("rolling"); - rfa.setLayout(layout); - rfa.setContext(context); - rfa.setFile(outputDirStr + "output.log"); - - } - - @After - public void tearDown() throws Exception { - rfa.stop(); - } - - public void setUpTImeBasedTriggeringPolicy(RollingFileAppender rfa) { - String datePattern = "yyyy-MM-dd'T'HH_mm_ss_SSS"; - TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy(); - tbrp.setFileNamePattern(outputDirStr + "test-%d{" + datePattern + "}"); - tbrp.setContext(context); - tbrp.setParent(rfa); - tbrp.start(); - - rfa.setRollingPolicy(tbrp); - rfa.start(); - } - - public void setUpSizeBasedTriggeringPolicy(RollingFileAppender rfa) { - SizeBasedTriggeringPolicy zbtp = new SizeBasedTriggeringPolicy(); - zbtp.setContext(context); - zbtp.setMaxFileSize("100KB"); - - zbtp.start(); - rfa.setTriggeringPolicy(zbtp); - - FixedWindowRollingPolicy fwrp = new FixedWindowRollingPolicy(); - fwrp.setContext(context); - fwrp.setFileNamePattern(outputDirStr + "test-%i.log"); - fwrp.setMaxIndex(10); - fwrp.setMinIndex(0); - fwrp.setParent(rfa); - fwrp.start(); - rfa.setRollingPolicy(fwrp); - rfa.start(); - } - - RunnableWithCounterAndDone[] buildRunnableArray() { - RunnableWithCounterAndDone[] runnableArray = new RunnableWithCounterAndDone[NUM_THREADS]; - for (int i = 0; i < NUM_THREADS; i++) { - runnableArray[i] = new RFARunnable(i, rfa); - } - return runnableArray; - } - - @Test - public void multiThreadedTimedBased() throws InterruptedException { - setUpTImeBasedTriggeringPolicy(rfa); - executeHarness(); - printScriptForTimeBased(); - } - - @Test - public void multiThreadedSizeBased() throws InterruptedException { - setUpSizeBasedTriggeringPolicy(rfa); - executeHarness(); - printScriptForSizeBased(); - } - - private void printScriptHeader(String type) { - out("# ===================================================="); - out("# Adapt this scipt to check the exactness of the output "); - out("# produced by "+type+" test"); - out("# ===================================================="); - out("# "); - out("# cd to "+outputDirStr); - - } - - private void printCommonScriptCore() { - out(""); - out("for t in $(seq 0 1 " + (NUM_THREADS - 1) + ")"); - out("do"); - out(" echo \"Testing results of thread $t\""); - out(" grep \"$t \" aggregated | cut -d ' ' -f 2 > ${t}-sample"); - out(" for j in $(seq 1 1 ${end[$t]}); do echo $j; done > ${t}-witness"); - out(" diff -q -w ${t}-sample ${t}-witness;"); - out(" res=$?"); - out(" if [ $res != \"0\" ]; then"); - out(" echo \"FAILED for $t\""); - out(" exit 1"); - out(" fi"); - out("done"); - out(""); - out("echo SUCCESS"); - } - - private void printScriptForTimeBased() { - printScriptHeader("TimeBased"); - for (int i = 0; i < NUM_THREADS; i++) { - out("end[" + i + "]=" + this.runnableArray[i].getCounter()); - } - out(""); - out("rm aggregated"); - out("cat test* output.log >> aggregated"); - printCommonScriptCore(); - - } - - private void printScriptForSizeBased() { - printScriptHeader("SizeBased"); - - for (int i = 0; i < NUM_THREADS; i++) { - out("end[" + i + "]=" + this.runnableArray[i].getCounter()); - } - out(""); - out("rm aggregated"); - out("Modify the integer set to include all test-* files"); - out("for i in 3 2 1 0; do cat test-$i.log >> aggregated; done"); - out("cat output.log >> aggregated"); - out(""); - printCommonScriptCore(); - } - - private void out(String msg) { - System.out.println(msg); - } - - private void executeHarness() throws InterruptedException { - MultiThreadedHarness multiThreadedHarness = new MultiThreadedHarness( - TOTAL_DURATION); - this.runnableArray = buildRunnableArray(); - multiThreadedHarness.execute(runnableArray); - - StatusChecker checker = new StatusChecker(context.getStatusManager()); - if (!checker.isErrorFree()) { - fail("errors reported"); - StatusPrinter.print(context); - } - } - - long diff(long start) { - return System.currentTimeMillis() - start; - } - - static class RFARunnable extends RunnableWithCounterAndDone { - RollingFileAppender rfa; - int id; - - RFARunnable(int id, RollingFileAppender rfa) { - this.id = id; - this.rfa = rfa; - } - - public void run() { - while (!isDone()) { - counter++; - rfa.doAppend(id + " " + counter); - } - } - - } - -} +/** + * 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.rolling; + +import static org.junit.Assert.fail; + +import java.io.File; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.contention.MultiThreadedHarness; +import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.layout.EchoLayout; +import ch.qos.logback.core.status.StatusChecker; +import ch.qos.logback.core.testUtil.RandomUtil; +import ch.qos.logback.core.util.CoreTestConstants; +import ch.qos.logback.core.util.StatusPrinter; + +public class MultiThreadedRollingTest { + + final static int NUM_THREADS = 10; + final static int TOTAL_DURATION = 2000; + RunnableWithCounterAndDone[] runnableArray; + + Layout layout; + Context context = new ContextBase(); + + int diff = RandomUtil.getPositiveInt(); + String outputDirStr = CoreTestConstants.OUTPUT_DIR_PREFIX + "multi-" + diff + + "/"; + + RollingFileAppender rfa = new RollingFileAppender(); + + @Before + public void setUp() throws Exception { + layout = new EchoLayout(); + File outputDir = new File(outputDirStr); + outputDir.mkdirs(); + + rfa.setName("rolling"); + rfa.setLayout(layout); + rfa.setContext(context); + rfa.setFile(outputDirStr + "output.log"); + + } + + @After + public void tearDown() throws Exception { + rfa.stop(); + } + + public void setUpTImeBasedTriggeringPolicy(RollingFileAppender rfa) { + String datePattern = "yyyy-MM-dd'T'HH_mm_ss_SSS"; + TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy(); + tbrp.setFileNamePattern(outputDirStr + "test-%d{" + datePattern + "}"); + tbrp.setContext(context); + tbrp.setParent(rfa); + tbrp.start(); + + rfa.setRollingPolicy(tbrp); + rfa.start(); + } + + public void setUpSizeBasedTriggeringPolicy(RollingFileAppender rfa) { + SizeBasedTriggeringPolicy zbtp = new SizeBasedTriggeringPolicy(); + zbtp.setContext(context); + zbtp.setMaxFileSize("100KB"); + + zbtp.start(); + rfa.setTriggeringPolicy(zbtp); + + FixedWindowRollingPolicy fwrp = new FixedWindowRollingPolicy(); + fwrp.setContext(context); + fwrp.setFileNamePattern(outputDirStr + "test-%i.log"); + fwrp.setMaxIndex(10); + fwrp.setMinIndex(0); + fwrp.setParent(rfa); + fwrp.start(); + rfa.setRollingPolicy(fwrp); + rfa.start(); + } + + RunnableWithCounterAndDone[] buildRunnableArray() { + RunnableWithCounterAndDone[] runnableArray = new RunnableWithCounterAndDone[NUM_THREADS]; + for (int i = 0; i < NUM_THREADS; i++) { + runnableArray[i] = new RFARunnable(i, rfa); + } + return runnableArray; + } + + @Test + public void multiThreadedTimedBased() throws InterruptedException { + setUpTImeBasedTriggeringPolicy(rfa); + executeHarness(); + printScriptForTimeBased(); + } + + @Test + public void multiThreadedSizeBased() throws InterruptedException { + setUpSizeBasedTriggeringPolicy(rfa); + executeHarness(); + printScriptForSizeBased(); + } + + private void printScriptHeader(String type) { + out("# ===================================================="); + out("# Adapt this scipt to check the exactness of the output "); + out("# produced by "+type+" test"); + out("# ===================================================="); + out("# "); + out("# cd to "+outputDirStr); + + } + + private void printCommonScriptCore() { + out(""); + out("for t in $(seq 0 1 " + (NUM_THREADS - 1) + ")"); + out("do"); + out(" echo \"Testing results of thread $t\""); + out(" grep \"$t \" aggregated | cut -d ' ' -f 2 > ${t}-sample"); + out(" for j in $(seq 1 1 ${end[$t]}); do echo $j; done > ${t}-witness"); + out(" diff -q -w ${t}-sample ${t}-witness;"); + out(" res=$?"); + out(" if [ $res != \"0\" ]; then"); + out(" echo \"FAILED for $t\""); + out(" exit 1"); + out(" fi"); + out("done"); + out(""); + out("echo SUCCESS"); + } + + private void printScriptForTimeBased() { + printScriptHeader("TimeBased"); + for (int i = 0; i < NUM_THREADS; i++) { + out("end[" + i + "]=" + this.runnableArray[i].getCounter()); + } + out(""); + out("rm aggregated"); + out("cat test* output.log >> aggregated"); + printCommonScriptCore(); + + } + + private void printScriptForSizeBased() { + printScriptHeader("SizeBased"); + + for (int i = 0; i < NUM_THREADS; i++) { + out("end[" + i + "]=" + this.runnableArray[i].getCounter()); + } + out(""); + out("rm aggregated"); + out("Modify the integer set to include all test-* files"); + out("for i in 3 2 1 0; do cat test-$i.log >> aggregated; done"); + out("cat output.log >> aggregated"); + out(""); + printCommonScriptCore(); + } + + private void out(String msg) { + System.out.println(msg); + } + + private void executeHarness() throws InterruptedException { + MultiThreadedHarness multiThreadedHarness = new MultiThreadedHarness( + TOTAL_DURATION); + this.runnableArray = buildRunnableArray(); + multiThreadedHarness.execute(runnableArray); + + StatusChecker checker = new StatusChecker(context.getStatusManager()); + if (!checker.isErrorFree()) { + fail("errors reported"); + StatusPrinter.print(context); + } + } + + long diff(long start) { + return System.currentTimeMillis() - start; + } + + static class RFARunnable extends RunnableWithCounterAndDone { + RollingFileAppender rfa; + int id; + + RFARunnable(int id, RollingFileAppender rfa) { + this.id = id; + this.rfa = rfa; + } + + public void run() { + while (!isDone()) { + counter++; + rfa.doAppend(id + " " + counter); + } + } + + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java index 6e74c20615a970250035db29f12547127a8062a4..ecc934b5bbf684780c4f902b9df98905ae71814e 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java @@ -1,26 +1,26 @@ -/** - * 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.rolling; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses( { RenamingTest.class, SizeBasedRollingTest.class, - TimeBasedRollingTest.class, TimeBasedRollingWithArchiveRemovalTest.class, - MultiThreadedRollingTest.class, - SizeAndTimeBasedFNATP_Test.class, - ch.qos.logback.core.rolling.helper.PackageTest.class }) -public class PackageTest { -} +/** + * 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.rolling; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses( { RenamingTest.class, SizeBasedRollingTest.class, + TimeBasedRollingTest.class, TimeBasedRollingWithArchiveRemovalTest.class, + MultiThreadedRollingTest.class, + SizeAndTimeBasedFNATP_Test.class, + ch.qos.logback.core.rolling.helper.PackageTest.class }) +public class PackageTest { +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/RenamingTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/RenamingTest.java index b335f2f04ce4574e4400ca4785eca302ae5f17c3..34660d41c727b9cc1f313ae418903a1b3ddcddbd 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/RenamingTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/RenamingTest.java @@ -1,96 +1,96 @@ -/** - * 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.rolling; - -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Calendar; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.Layout; -import ch.qos.logback.core.layout.EchoLayout; -import ch.qos.logback.core.util.Compare; -import ch.qos.logback.core.util.CoreTestConstants; - -/** - * - * This test case aims to unit test/reproduce problems encountered while - * renaming the log file under windows. - * - * @author Ceki - * - */ -public class RenamingTest { - - Layout layout; - Context context = new ContextBase(); - - @Before - public void setUp() throws Exception { - layout = new EchoLayout(); - - File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX + "test.log"); - target.mkdirs(); - target.delete(); - } - - @Test - public void testRename() throws Exception { - - RollingFileAppender rfa = new RollingFileAppender(); - rfa.setLayout(layout); - rfa.setContext(context); - - // rollover by the second - String datePattern = "yyyy-MM-dd_HH_mm_ss"; - SimpleDateFormat sdf = new SimpleDateFormat(datePattern); - String[] filenames = new String[2]; - - TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy(); - tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "test-%d{" - + datePattern + "}"); - tbrp.setContext(context); - tbrp.setParent(rfa); - tbrp.start(); - - rfa.setRollingPolicy(tbrp); - rfa.start(); - - - Calendar cal0 = Calendar.getInstance(); - rfa.doAppend("Hello 0"); - - DelayerUtil.delayUntilNextSecond(50); - - Calendar cal1 = Calendar.getInstance(); - rfa.doAppend("Hello 1"); - - filenames[0] = CoreTestConstants.OUTPUT_DIR_PREFIX + "test-" - + sdf.format(cal0.getTime()); - filenames[1] = CoreTestConstants.OUTPUT_DIR_PREFIX + "test-" - + sdf.format(cal1.getTime()); - - - for (int i = 0; i < filenames.length; i++) { - assertTrue(Compare.compare(filenames[i], CoreTestConstants.TEST_DIR_PREFIX - + "witness/rolling/renaming." + i)); - } - } -} +/** + * 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.rolling; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Calendar; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.layout.EchoLayout; +import ch.qos.logback.core.util.Compare; +import ch.qos.logback.core.util.CoreTestConstants; + +/** + * + * This test case aims to unit test/reproduce problems encountered while + * renaming the log file under windows. + * + * @author Ceki + * + */ +public class RenamingTest { + + Layout layout; + Context context = new ContextBase(); + + @Before + public void setUp() throws Exception { + layout = new EchoLayout(); + + File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX + "test.log"); + target.mkdirs(); + target.delete(); + } + + @Test + public void testRename() throws Exception { + + RollingFileAppender rfa = new RollingFileAppender(); + rfa.setLayout(layout); + rfa.setContext(context); + + // rollover by the second + String datePattern = "yyyy-MM-dd_HH_mm_ss"; + SimpleDateFormat sdf = new SimpleDateFormat(datePattern); + String[] filenames = new String[2]; + + TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy(); + tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "test-%d{" + + datePattern + "}"); + tbrp.setContext(context); + tbrp.setParent(rfa); + tbrp.start(); + + rfa.setRollingPolicy(tbrp); + rfa.start(); + + + Calendar cal0 = Calendar.getInstance(); + rfa.doAppend("Hello 0"); + + DelayerUtil.delayUntilNextSecond(50); + + Calendar cal1 = Calendar.getInstance(); + rfa.doAppend("Hello 1"); + + filenames[0] = CoreTestConstants.OUTPUT_DIR_PREFIX + "test-" + + sdf.format(cal0.getTime()); + filenames[1] = CoreTestConstants.OUTPUT_DIR_PREFIX + "test-" + + sdf.format(cal1.getTime()); + + + for (int i = 0; i < filenames.length; i++) { + assertTrue(Compare.compare(filenames[i], CoreTestConstants.TEST_DIR_PREFIX + + "witness/rolling/renaming." + i)); + } + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/RollingFileAppenderTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/RollingFileAppenderTest.java index cabceaa890ecad9c6bd041bc9efb4aa4e3dc861c..93a029d594b4ada676e088efac0d5fb3672b9b3f 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/RollingFileAppenderTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/RollingFileAppenderTest.java @@ -1,136 +1,136 @@ -/** - * 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.rolling; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.appender.AbstractAppenderTest; -import ch.qos.logback.core.layout.DummyLayout; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusChecker; -import ch.qos.logback.core.status.StatusManager; -import ch.qos.logback.core.util.CoreTestConstants; -import ch.qos.logback.core.util.StatusPrinter; - -public class RollingFileAppenderTest extends AbstractAppenderTest { - - RollingFileAppender rfa = new RollingFileAppender(); - Context context = new ContextBase(); - - TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy(); - - @Before - public void setUp() throws Exception { - // noStartTest fails if the context is set in setUp - // rfa.setContext(context); - - rfa.setLayout(new DummyLayout()); - rfa.setName("test"); - tbrp.setContext(context); - tbrp.setParent(rfa); - } - - @After - public void tearDown() throws Exception { - } - - @Override - protected Appender getAppender() { - return rfa; - } - - @Override - protected Appender getConfiguredAppender() { - rfa.setContext(context); - tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX+"toto-%d.log"); - tbrp.start(); - rfa.setRollingPolicy(tbrp); - - rfa.start(); - return rfa; - } - - @Test - public void testPrudentModeLogicalImplications() { - rfa.setContext(context); - // prudent mode will force "file" property to be null - rfa.setFile("some non null value"); - rfa.setAppend(false); - rfa.setImmediateFlush(false); - rfa.setBufferedIO(true); - rfa.setPrudent(true); - - tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX+"toto-%d.log"); - tbrp.start(); - rfa.setRollingPolicy(tbrp); - - rfa.start(); - - assertTrue(rfa.getImmediateFlush()); - assertTrue(rfa.isAppend()); - assertFalse(rfa.isBufferedIO()); - assertNull(rfa.rawFileProperty()); - assertTrue(rfa.isStarted()); - } - - @Test - public void testPrudentModeLogicalImplicationsOnCompression() { - rfa.setContext(context); - rfa.setAppend(false); - rfa.setImmediateFlush(false); - rfa.setBufferedIO(true); - rfa.setPrudent(true); - - tbrp.setFileNamePattern("toto-%d.log.zip"); - tbrp.start(); - rfa.setRollingPolicy(tbrp); - - rfa.start(); - - StatusManager sm = context.getStatusManager(); - assertFalse(rfa.isStarted()); - assertEquals(Status.ERROR, sm.getLevel()); - } - - @Test - public void testFilePropertyAfterRollingPolicy() { - rfa.setContext(context); - rfa.setRollingPolicy(tbrp); - rfa.setFile("x"); - StatusPrinter.print(context); - StatusChecker statusChecker = new StatusChecker(context.getStatusManager()); - statusChecker.containsMatch(Status.ERROR, - "File property must be set before any triggeringPolicy "); - } - - @Test - public void testFilePropertyAfterTriggeringPolicy() { - rfa.setContext(context); - rfa.setTriggeringPolicy(new SizeBasedTriggeringPolicy()); - rfa.setFile("x"); - StatusChecker statusChecker = new StatusChecker(context.getStatusManager()); - statusChecker.containsMatch(Status.ERROR, - "File property must be set before any triggeringPolicy "); - } -} +/** + * 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.rolling; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.appender.AbstractAppenderTest; +import ch.qos.logback.core.layout.DummyLayout; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusChecker; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.CoreTestConstants; +import ch.qos.logback.core.util.StatusPrinter; + +public class RollingFileAppenderTest extends AbstractAppenderTest { + + RollingFileAppender rfa = new RollingFileAppender(); + Context context = new ContextBase(); + + TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy(); + + @Before + public void setUp() throws Exception { + // noStartTest fails if the context is set in setUp + // rfa.setContext(context); + + rfa.setLayout(new DummyLayout()); + rfa.setName("test"); + tbrp.setContext(context); + tbrp.setParent(rfa); + } + + @After + public void tearDown() throws Exception { + } + + @Override + protected Appender getAppender() { + return rfa; + } + + @Override + protected Appender getConfiguredAppender() { + rfa.setContext(context); + tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX+"toto-%d.log"); + tbrp.start(); + rfa.setRollingPolicy(tbrp); + + rfa.start(); + return rfa; + } + + @Test + public void testPrudentModeLogicalImplications() { + rfa.setContext(context); + // prudent mode will force "file" property to be null + rfa.setFile("some non null value"); + rfa.setAppend(false); + rfa.setImmediateFlush(false); + rfa.setBufferedIO(true); + rfa.setPrudent(true); + + tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX+"toto-%d.log"); + tbrp.start(); + rfa.setRollingPolicy(tbrp); + + rfa.start(); + + assertTrue(rfa.getImmediateFlush()); + assertTrue(rfa.isAppend()); + assertFalse(rfa.isBufferedIO()); + assertNull(rfa.rawFileProperty()); + assertTrue(rfa.isStarted()); + } + + @Test + public void testPrudentModeLogicalImplicationsOnCompression() { + rfa.setContext(context); + rfa.setAppend(false); + rfa.setImmediateFlush(false); + rfa.setBufferedIO(true); + rfa.setPrudent(true); + + tbrp.setFileNamePattern("toto-%d.log.zip"); + tbrp.start(); + rfa.setRollingPolicy(tbrp); + + rfa.start(); + + StatusManager sm = context.getStatusManager(); + assertFalse(rfa.isStarted()); + assertEquals(Status.ERROR, sm.getLevel()); + } + + @Test + public void testFilePropertyAfterRollingPolicy() { + rfa.setContext(context); + rfa.setRollingPolicy(tbrp); + rfa.setFile("x"); + StatusPrinter.print(context); + StatusChecker statusChecker = new StatusChecker(context.getStatusManager()); + statusChecker.containsMatch(Status.ERROR, + "File property must be set before any triggeringPolicy "); + } + + @Test + public void testFilePropertyAfterTriggeringPolicy() { + rfa.setContext(context); + rfa.setTriggeringPolicy(new SizeBasedTriggeringPolicy()); + rfa.setFile("x"); + StatusChecker statusChecker = new StatusChecker(context.getStatusManager()); + statusChecker.containsMatch(Status.ERROR, + "File property must be set before any triggeringPolicy "); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/ScaffoldingForRollingTests.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/ScaffoldingForRollingTests.java index 561dc55217e7d56304e1ea1d97b5f1606937056b..8b2fbca11c35394c7df083f9eb92dea5e8a193fa 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/ScaffoldingForRollingTests.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/ScaffoldingForRollingTests.java @@ -1,187 +1,187 @@ -/** - * 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.rolling; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.IOException; -import java.sql.Date; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.layout.EchoLayout; -import ch.qos.logback.core.rolling.helper.FileFilterUtil; -import ch.qos.logback.core.testUtil.FileToBufferUtil; -import ch.qos.logback.core.testUtil.RandomUtil; -import ch.qos.logback.core.util.CoreTestConstants; - -/** - * Scaffolding for various rolling tests. Some assumptions are made: - rollover - * periodicity is 1 second (without precluding size based roll-over) - * - * @author Ceki Gülcü - * - */ -public class ScaffoldingForRollingTests { - - static public final String DATE_PATTERN_WITH_SECONDS = "yyyy-MM-dd_HH_mm_ss"; - static public final SimpleDateFormat SDF = new SimpleDateFormat( - DATE_PATTERN_WITH_SECONDS); - - int diff = RandomUtil.getPositiveInt(); - protected String randomOutputDir = CoreTestConstants.OUTPUT_DIR_PREFIX + diff - + "/"; - EchoLayout layout = new EchoLayout(); - Context context = new ContextBase(); - protected List expectedFilenameList = new ArrayList(); - - protected long nextRolloverThreshold; // initialized in setUp() - protected long currentTime; // initialized in setUp() - Calendar cal = Calendar.getInstance(); - - public void setUp() { - context.setName("test"); - cal.set(Calendar.MILLISECOND, 333); - currentTime = cal.getTimeInMillis(); - recomputeRolloverThreshold(currentTime); - } - - public static void existenceCheck(String filename) { - assertTrue("File " + filename + " does not exist", new File(filename) - .exists()); - } - - public static File[] getFilesInDirectory(String outputDirStr) { - File outputDir = new File(outputDirStr); - return outputDir.listFiles(); - } - - public static void fileContentCheck(File[] fileArray, int runLength, - String prefix) throws IOException { - List stringList = new ArrayList(); - for (File file : fileArray) { - FileToBufferUtil.readIntoList(file, stringList); - } - - List witnessList = new ArrayList(); - - for (int i = 0; i < runLength; i++) { - witnessList.add(prefix + i); - } - assertEquals(witnessList, stringList); - } - - public static void sortedContentCheck(String outputDirStr, int runLength, - String prefix) throws IOException { - File[] fileArray = getFilesInDirectory(outputDirStr); - FileFilterUtil.sortFileArrayByName(fileArray); - fileContentCheck(fileArray, runLength, prefix); - } - - public static void reverseSortedContentCheck(String outputDirStr, - int runLength, String prefix) throws IOException { - File[] fileArray = getFilesInDirectory(outputDirStr); - FileFilterUtil.reverseSortFileArrayByName(fileArray); - fileContentCheck(fileArray, runLength, prefix); - } - - public static void existenceCheck(List filenameList) { - for (String filename : filenameList) { - assertTrue("File " + filename + " does not exist", new File(filename) - .exists()); - } - } - - public static int existenceCount(List filenameList) { - int existenceCounter = 0; - for (String filename : filenameList) { - if (new File(filename).exists()) { - existenceCounter++; - } - } - return existenceCounter; - } - - String testId2FileName(String testId) { - return randomOutputDir + testId + ".log"; - } - - // assuming rollover every second - protected void recomputeRolloverThreshold(long ct) { - long delta = ct % 1000; - nextRolloverThreshold = (ct - delta) + 1000; - } - - protected boolean passThresholdTime(long nextRolloverThreshold) { - return currentTime >= nextRolloverThreshold; - } - - protected void incCurrentTime(long increment) { - currentTime += increment; - } - - protected Date getDateOfCurrentPeriodsStart() { - long delta = currentTime % 1000; - return new Date(currentTime - delta); - } - - protected Date getDateOfPreviousPeriodsStart() { - long delta = currentTime % 1000; - return new Date(currentTime - delta - 1000); - } - - static void waitForCompression(TimeBasedRollingPolicy tbrp) - throws InterruptedException, ExecutionException, TimeoutException { - if (tbrp.future != null && !tbrp.future.isDone()) { - tbrp.future.get(200, TimeUnit.MILLISECONDS); - } - } - - protected void addExpectedFileName_ByDate(String testId, Date date, - boolean gzExtension) { - - String fn = randomOutputDir + testId + "-" + SDF.format(date); - if (gzExtension) { - fn += ".gz"; - } - expectedFilenameList.add(fn); - } - - protected void addExpectedFileNamedIfItsTime_ByDate(String testId, - boolean gzExtension) { - if (passThresholdTime(nextRolloverThreshold)) { - addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), - gzExtension); - recomputeRolloverThreshold(currentTime); - } - } - - String addGZIfNotLast(int i) { - int lastIndex = expectedFilenameList.size() - 1; - if (i != lastIndex) { - return ".gz"; - } else { - return ""; - } - } -} +/** + * 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.rolling; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.sql.Date; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.layout.EchoLayout; +import ch.qos.logback.core.rolling.helper.FileFilterUtil; +import ch.qos.logback.core.testUtil.FileToBufferUtil; +import ch.qos.logback.core.testUtil.RandomUtil; +import ch.qos.logback.core.util.CoreTestConstants; + +/** + * Scaffolding for various rolling tests. Some assumptions are made: - rollover + * periodicity is 1 second (without precluding size based roll-over) + * + * @author Ceki Gülcü + * + */ +public class ScaffoldingForRollingTests { + + static public final String DATE_PATTERN_WITH_SECONDS = "yyyy-MM-dd_HH_mm_ss"; + static public final SimpleDateFormat SDF = new SimpleDateFormat( + DATE_PATTERN_WITH_SECONDS); + + int diff = RandomUtil.getPositiveInt(); + protected String randomOutputDir = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + + "/"; + EchoLayout layout = new EchoLayout(); + Context context = new ContextBase(); + protected List expectedFilenameList = new ArrayList(); + + protected long nextRolloverThreshold; // initialized in setUp() + protected long currentTime; // initialized in setUp() + Calendar cal = Calendar.getInstance(); + + public void setUp() { + context.setName("test"); + cal.set(Calendar.MILLISECOND, 333); + currentTime = cal.getTimeInMillis(); + recomputeRolloverThreshold(currentTime); + } + + public static void existenceCheck(String filename) { + assertTrue("File " + filename + " does not exist", new File(filename) + .exists()); + } + + public static File[] getFilesInDirectory(String outputDirStr) { + File outputDir = new File(outputDirStr); + return outputDir.listFiles(); + } + + public static void fileContentCheck(File[] fileArray, int runLength, + String prefix) throws IOException { + List stringList = new ArrayList(); + for (File file : fileArray) { + FileToBufferUtil.readIntoList(file, stringList); + } + + List witnessList = new ArrayList(); + + for (int i = 0; i < runLength; i++) { + witnessList.add(prefix + i); + } + assertEquals(witnessList, stringList); + } + + public static void sortedContentCheck(String outputDirStr, int runLength, + String prefix) throws IOException { + File[] fileArray = getFilesInDirectory(outputDirStr); + FileFilterUtil.sortFileArrayByName(fileArray); + fileContentCheck(fileArray, runLength, prefix); + } + + public static void reverseSortedContentCheck(String outputDirStr, + int runLength, String prefix) throws IOException { + File[] fileArray = getFilesInDirectory(outputDirStr); + FileFilterUtil.reverseSortFileArrayByName(fileArray); + fileContentCheck(fileArray, runLength, prefix); + } + + public static void existenceCheck(List filenameList) { + for (String filename : filenameList) { + assertTrue("File " + filename + " does not exist", new File(filename) + .exists()); + } + } + + public static int existenceCount(List filenameList) { + int existenceCounter = 0; + for (String filename : filenameList) { + if (new File(filename).exists()) { + existenceCounter++; + } + } + return existenceCounter; + } + + String testId2FileName(String testId) { + return randomOutputDir + testId + ".log"; + } + + // assuming rollover every second + protected void recomputeRolloverThreshold(long ct) { + long delta = ct % 1000; + nextRolloverThreshold = (ct - delta) + 1000; + } + + protected boolean passThresholdTime(long nextRolloverThreshold) { + return currentTime >= nextRolloverThreshold; + } + + protected void incCurrentTime(long increment) { + currentTime += increment; + } + + protected Date getDateOfCurrentPeriodsStart() { + long delta = currentTime % 1000; + return new Date(currentTime - delta); + } + + protected Date getDateOfPreviousPeriodsStart() { + long delta = currentTime % 1000; + return new Date(currentTime - delta - 1000); + } + + static void waitForCompression(TimeBasedRollingPolicy tbrp) + throws InterruptedException, ExecutionException, TimeoutException { + if (tbrp.future != null && !tbrp.future.isDone()) { + tbrp.future.get(200, TimeUnit.MILLISECONDS); + } + } + + protected void addExpectedFileName_ByDate(String testId, Date date, + boolean gzExtension) { + + String fn = randomOutputDir + testId + "-" + SDF.format(date); + if (gzExtension) { + fn += ".gz"; + } + expectedFilenameList.add(fn); + } + + protected void addExpectedFileNamedIfItsTime_ByDate(String testId, + boolean gzExtension) { + if (passThresholdTime(nextRolloverThreshold)) { + addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), + gzExtension); + recomputeRolloverThreshold(currentTime); + } + } + + String addGZIfNotLast(int i) { + int lastIndex = expectedFilenameList.size() - 1; + if (i != lastIndex) { + return ".gz"; + } else { + return ""; + } + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP_Test.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP_Test.java index ee228d4816b0bdc4e9267fc888af8fc0c2516b8d..cfc1841a6d8facdf75c7776034f8c43616880108 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP_Test.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP_Test.java @@ -1,216 +1,216 @@ -/** - * 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.rolling; - - -import java.util.Date; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.util.StatusPrinter; - -public class SizeAndTimeBasedFNATP_Test extends - ScaffoldingForRollingTests { - - SizeAndTimeBasedFNATP sizeAndTimeBasedFNATP; - RollingFileAppender rfa1 = new RollingFileAppender(); - TimeBasedRollingPolicy tbrp1 = new TimeBasedRollingPolicy(); - - RollingFileAppender rfa2 = new RollingFileAppender(); - TimeBasedRollingPolicy tbrp2 = new TimeBasedRollingPolicy(); - - int fileSize = 0; - int fileIndexCounter = 0; - int sizeThreshold; - - @Before - @Override - public void setUp() { - super.setUp(); - } - - void initRFA(RollingFileAppender rfa, String filename) { - rfa.setContext(context); - rfa.setLayout(layout); - if (filename != null) { - rfa.setFile(filename); - } - } - - void initTRBP(RollingFileAppender rfa, - TimeBasedRollingPolicy tbrp, String filenamePattern, - int sizeThreshold, long givenTime, long lastCheck) { - - sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP(); - tbrp.setContext(context); - sizeAndTimeBasedFNATP.setMaxFileSize("" + sizeThreshold); - tbrp.setTimeBasedFileNamingAndTriggeringPolicy(sizeAndTimeBasedFNATP); - tbrp.setFileNamePattern(filenamePattern); - tbrp.setParent(rfa); - tbrp.timeBasedTriggering.setCurrentTime(givenTime); -// if (lastCheck != 0) { -// tbrp.timeBasedTriggering.setDateInCurrentPeriod(new Date(lastCheck)); -// } - rfa.setRollingPolicy(tbrp); - tbrp.start(); - rfa.start(); - } - - @Test - public void noCompression_FileSet_NoRestart_1() throws Exception { - String testId = "test1"; - String file = randomOutputDir + "toto.log"; - initRFA(rfa1, file); - sizeThreshold = 300; - initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}-%i.txt", sizeThreshold, currentTime, 0); - - addExpectedFileName(testId, getDateOfCurrentPeriodsStart(), - fileIndexCounter, false); - - incCurrentTime(100); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - - int runLength = 100; - String prefix = "Hello -----------------"; - - for (int i = 0; i < runLength; i++) { - String msg = prefix + i; - rfa1.doAppend(msg); - addExpectedFileNamedIfItsTime(testId, msg, false); - incCurrentTime(20); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - } - - massageExpectedFilesToCorresponToCurrentTarget(file); - existenceCheck(expectedFilenameList); - sortedContentCheck(randomOutputDir, runLength, prefix); - } - - @Test - public void noCompression_FileBlank_NoRestart_2() throws Exception { - String testId = "test1"; - initRFA(rfa1, null); - sizeThreshold = 300; - initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}-%i.txt", sizeThreshold, currentTime, 0); - - addExpectedFileName(testId, getDateOfCurrentPeriodsStart(), - fileIndexCounter, false); - - incCurrentTime(100); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - - int runLength = 100; - String prefix = "Hello -----------------"; - - for (int i = 0; i < runLength; i++) { - String msg = prefix + i; - rfa1.doAppend(msg); - addExpectedFileNamedIfItsTime(testId, msg, false); - incCurrentTime(20); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - } - existenceCheck(expectedFilenameList); - sortedContentCheck(randomOutputDir, runLength, prefix); - } - - @Test - public void noCompression_FileBlank_WithStopStart_3() throws Exception { - String testId = "test3"; - initRFA(rfa1, null); - sizeThreshold = 300; - initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}-%i.txt", sizeThreshold, currentTime, 0); - - addExpectedFileName(testId, getDateOfCurrentPeriodsStart(), - fileIndexCounter, false); - - incCurrentTime(100); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - - int runLength = 100; - String prefix = "Hello -----------------"; - - int i = 0; - - for (; i < runLength; i++) { - String msg = prefix + i; - rfa1.doAppend(msg); - addExpectedFileNamedIfItsTime(testId, msg, false); - incCurrentTime(20); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - } - rfa1.stop(); - initRFA(rfa2, null); - initTRBP(rfa2, tbrp2, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}-%i.txt", sizeThreshold, currentTime, 0); - - runLength *= 2; - for (; i < runLength; i++) { - String msg = prefix + i; - addExpectedFileNamedIfItsTime(testId, msg, false); - rfa2.doAppend(msg); - incCurrentTime(100); - tbrp2.timeBasedTriggering.setCurrentTime(currentTime); - } - StatusPrinter.print(context); - existenceCheck(expectedFilenameList); - sortedContentCheck(randomOutputDir, runLength, prefix); - } - - - - void massageExpectedFilesToCorresponToCurrentTarget(String file) { - // we added one too many files by date - expectedFilenameList.remove(expectedFilenameList.size() - 1); - expectedFilenameList.add(file); - } - - void addExpectedFileNamedIfItsTime(String testId, String msg, - boolean gzExtension) { - fileSize += msg.getBytes().length; - - if (passThresholdTime(nextRolloverThreshold)) { - fileIndexCounter = 0; - fileSize = 0; - addExpectedFileName(testId, getDateOfCurrentPeriodsStart(), - fileIndexCounter, gzExtension); - recomputeRolloverThreshold(currentTime); - return; - } - - // windows can delay file size changes, so we only allow for - // fileIndexCounter 0 and 1 - if ((fileIndexCounter < 1) && fileSize > sizeThreshold) { - addExpectedFileName(testId, getDateOfCurrentPeriodsStart(), - ++fileIndexCounter, gzExtension); - fileSize = 0; - return; - } - } - - void addExpectedFileName(String testId, Date date, int fileIndexCounter, - boolean gzExtension) { - - String fn = randomOutputDir + testId + "-" + SDF.format(date) + "-" - + fileIndexCounter + ".txt"; - if (gzExtension) { - fn += ".gz"; - } - expectedFilenameList.add(fn); - } - -} +/** + * 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.rolling; + + +import java.util.Date; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.util.StatusPrinter; + +public class SizeAndTimeBasedFNATP_Test extends + ScaffoldingForRollingTests { + + SizeAndTimeBasedFNATP sizeAndTimeBasedFNATP; + RollingFileAppender rfa1 = new RollingFileAppender(); + TimeBasedRollingPolicy tbrp1 = new TimeBasedRollingPolicy(); + + RollingFileAppender rfa2 = new RollingFileAppender(); + TimeBasedRollingPolicy tbrp2 = new TimeBasedRollingPolicy(); + + int fileSize = 0; + int fileIndexCounter = 0; + int sizeThreshold; + + @Before + @Override + public void setUp() { + super.setUp(); + } + + void initRFA(RollingFileAppender rfa, String filename) { + rfa.setContext(context); + rfa.setLayout(layout); + if (filename != null) { + rfa.setFile(filename); + } + } + + void initTRBP(RollingFileAppender rfa, + TimeBasedRollingPolicy tbrp, String filenamePattern, + int sizeThreshold, long givenTime, long lastCheck) { + + sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP(); + tbrp.setContext(context); + sizeAndTimeBasedFNATP.setMaxFileSize("" + sizeThreshold); + tbrp.setTimeBasedFileNamingAndTriggeringPolicy(sizeAndTimeBasedFNATP); + tbrp.setFileNamePattern(filenamePattern); + tbrp.setParent(rfa); + tbrp.timeBasedTriggering.setCurrentTime(givenTime); +// if (lastCheck != 0) { +// tbrp.timeBasedTriggering.setDateInCurrentPeriod(new Date(lastCheck)); +// } + rfa.setRollingPolicy(tbrp); + tbrp.start(); + rfa.start(); + } + + @Test + public void noCompression_FileSet_NoRestart_1() throws Exception { + String testId = "test1"; + String file = randomOutputDir + "toto.log"; + initRFA(rfa1, file); + sizeThreshold = 300; + initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}-%i.txt", sizeThreshold, currentTime, 0); + + addExpectedFileName(testId, getDateOfCurrentPeriodsStart(), + fileIndexCounter, false); + + incCurrentTime(100); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + + int runLength = 100; + String prefix = "Hello -----------------"; + + for (int i = 0; i < runLength; i++) { + String msg = prefix + i; + rfa1.doAppend(msg); + addExpectedFileNamedIfItsTime(testId, msg, false); + incCurrentTime(20); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + } + + massageExpectedFilesToCorresponToCurrentTarget(file); + existenceCheck(expectedFilenameList); + sortedContentCheck(randomOutputDir, runLength, prefix); + } + + @Test + public void noCompression_FileBlank_NoRestart_2() throws Exception { + String testId = "test1"; + initRFA(rfa1, null); + sizeThreshold = 300; + initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}-%i.txt", sizeThreshold, currentTime, 0); + + addExpectedFileName(testId, getDateOfCurrentPeriodsStart(), + fileIndexCounter, false); + + incCurrentTime(100); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + + int runLength = 100; + String prefix = "Hello -----------------"; + + for (int i = 0; i < runLength; i++) { + String msg = prefix + i; + rfa1.doAppend(msg); + addExpectedFileNamedIfItsTime(testId, msg, false); + incCurrentTime(20); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + } + existenceCheck(expectedFilenameList); + sortedContentCheck(randomOutputDir, runLength, prefix); + } + + @Test + public void noCompression_FileBlank_WithStopStart_3() throws Exception { + String testId = "test3"; + initRFA(rfa1, null); + sizeThreshold = 300; + initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}-%i.txt", sizeThreshold, currentTime, 0); + + addExpectedFileName(testId, getDateOfCurrentPeriodsStart(), + fileIndexCounter, false); + + incCurrentTime(100); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + + int runLength = 100; + String prefix = "Hello -----------------"; + + int i = 0; + + for (; i < runLength; i++) { + String msg = prefix + i; + rfa1.doAppend(msg); + addExpectedFileNamedIfItsTime(testId, msg, false); + incCurrentTime(20); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + } + rfa1.stop(); + initRFA(rfa2, null); + initTRBP(rfa2, tbrp2, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}-%i.txt", sizeThreshold, currentTime, 0); + + runLength *= 2; + for (; i < runLength; i++) { + String msg = prefix + i; + addExpectedFileNamedIfItsTime(testId, msg, false); + rfa2.doAppend(msg); + incCurrentTime(100); + tbrp2.timeBasedTriggering.setCurrentTime(currentTime); + } + StatusPrinter.print(context); + existenceCheck(expectedFilenameList); + sortedContentCheck(randomOutputDir, runLength, prefix); + } + + + + void massageExpectedFilesToCorresponToCurrentTarget(String file) { + // we added one too many files by date + expectedFilenameList.remove(expectedFilenameList.size() - 1); + expectedFilenameList.add(file); + } + + void addExpectedFileNamedIfItsTime(String testId, String msg, + boolean gzExtension) { + fileSize += msg.getBytes().length; + + if (passThresholdTime(nextRolloverThreshold)) { + fileIndexCounter = 0; + fileSize = 0; + addExpectedFileName(testId, getDateOfCurrentPeriodsStart(), + fileIndexCounter, gzExtension); + recomputeRolloverThreshold(currentTime); + return; + } + + // windows can delay file size changes, so we only allow for + // fileIndexCounter 0 and 1 + if ((fileIndexCounter < 1) && fileSize > sizeThreshold) { + addExpectedFileName(testId, getDateOfCurrentPeriodsStart(), + ++fileIndexCounter, gzExtension); + fileSize = 0; + return; + } + } + + void addExpectedFileName(String testId, Date date, int fileIndexCounter, + boolean gzExtension) { + + String fn = randomOutputDir + testId + "-" + SDF.format(date) + "-" + + fileIndexCounter + ".txt"; + if (gzExtension) { + fn += ".gz"; + } + expectedFilenameList.add(fn); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeBasedRollingTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeBasedRollingTest.java index e1ecff6765a16d8c4312a612094a5cf99bb276fc..453123a399dd301c446255dcf5188b905c841b7e 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeBasedRollingTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeBasedRollingTest.java @@ -1,184 +1,184 @@ -/** - * 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.rolling; - -import static org.junit.Assert.fail; - -import java.io.File; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.Layout; -import ch.qos.logback.core.layout.DummyLayout; -import ch.qos.logback.core.layout.EchoLayout; -import ch.qos.logback.core.util.CoreTestConstants; - -/** - * - * Do not forget to call start() when configuring programatically. - * - * @author Ceki Gülcü - * @author Sébastien Pennec - * - */ -public class SizeBasedRollingTest extends ScaffoldingForRollingTests { - - @Before - @Override - public void setUp() { - super.setUp(); - { - File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX - + "sizeBased-smoke.log"); - target.mkdirs(); - target.delete(); - } - { - File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX - + "sbr-test3.log"); - target.mkdirs(); - target.delete(); - } - } - - @After - public void tearDown() { - } - - /** - * Test whether FixedWindowRollingPolicy throws an exception when the - * ActiveFileName is not set. - */ - @Test - public void activeFileNameNotSet() throws Exception { - // We purposefully use the \n as the line separator. - // This makes the regression test system independent. - Context context = new ContextBase(); - Layout layout = new DummyLayout(); - RollingFileAppender rfa = new RollingFileAppender(); - rfa.setLayout(layout); - rfa.setContext(new ContextBase()); - - FixedWindowRollingPolicy fwrp = new FixedWindowRollingPolicy(); - fwrp.setContext(context); - fwrp.setParent(rfa); - SizeBasedTriggeringPolicy sbtp = new SizeBasedTriggeringPolicy(); - sbtp.setContext(context); - - sbtp.setMaxFileSize("100"); - sbtp.start(); - fwrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX - + "sizeBased-test1.%i"); - try { - fwrp.start(); - fail("The absence of activeFileName option should have caused an exception."); - } catch (IllegalStateException e) { - return; - } - } - - /** - * Test basic rolling functionality. - */ - @Test - public void smoke() throws Exception { - Context context = new ContextBase(); - - EchoLayout layout = new EchoLayout(); - RollingFileAppender rfa = new RollingFileAppender(); - rfa.setName("ROLLING"); - rfa.setLayout(layout); - rfa.setContext(context); - // make the .log show first - rfa.setFile(randomOutputDir + "a-sizeBased-smoke.log"); - - FixedWindowRollingPolicy swrp = new FixedWindowRollingPolicy(); - swrp.setContext(context); - SizeBasedTriggeringPolicy sbtp = new SizeBasedTriggeringPolicy(); - sbtp.setContext(context); - - sbtp.setMaxFileSize("100"); - swrp.setMinIndex(0); - swrp.setFileNamePattern(randomOutputDir + "sizeBased-smoke.%i"); - swrp.setParent(rfa); - swrp.start(); - - rfa.setRollingPolicy(swrp); - rfa.setTriggeringPolicy(sbtp); - rfa.start(); - - int runLength = 45; - String prefix = "hello"; - for (int i = 0; i < runLength; i++) { - Thread.sleep(10); - rfa.doAppend(prefix+i); - } - - expectedFilenameList.add(randomOutputDir + "a-sizeBased-smoke.log"); - expectedFilenameList.add(randomOutputDir + "sizeBased-smoke.0"); - expectedFilenameList.add(randomOutputDir + "sizeBased-smoke.1"); - existenceCheck(expectedFilenameList); - - reverseSortedContentCheck(randomOutputDir, runLength, prefix); - } - - /** - * Same as testBasic but also with GZ compression. - */ - @Test - public void test3() throws Exception { - Context context = new ContextBase(); - EchoLayout layout = new EchoLayout(); - RollingFileAppender rfa = new RollingFileAppender(); - rfa.setLayout(layout); - rfa.setContext(context); - rfa.setFile(randomOutputDir + "a-sbr-test3.log"); - - FixedWindowRollingPolicy fwrp = new FixedWindowRollingPolicy(); - fwrp.setContext(context); - SizeBasedTriggeringPolicy sbtp = new SizeBasedTriggeringPolicy(); - sbtp.setContext(context); - - sbtp.setMaxFileSize("100"); - fwrp.setMinIndex(0); - // fwrp.setActiveFileName(Constants.TEST_DIR_PREFIX + - // "output/sbr-test3.log"); - fwrp.setFileNamePattern(randomOutputDir + "sbr-test3.%i.gz"); - fwrp.setParent(rfa); - fwrp.start(); - rfa.setRollingPolicy(fwrp); - rfa.setTriggeringPolicy(sbtp); - rfa.start(); - - int runLength = 40; - String prefix = "hello"; - for (int i = 0; i < runLength; i++) { - Thread.sleep(10); - rfa.doAppend("hello"+i); - } - - expectedFilenameList.add(randomOutputDir + "a-sbr-test3.log"); - expectedFilenameList.add(randomOutputDir + "sbr-test3.0.gz"); - expectedFilenameList.add(randomOutputDir + "sbr-test3.1.gz"); - - existenceCheck(expectedFilenameList); - reverseSortedContentCheck(randomOutputDir, runLength, prefix); - - } - -} +/** + * 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.rolling; + +import static org.junit.Assert.fail; + +import java.io.File; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.layout.DummyLayout; +import ch.qos.logback.core.layout.EchoLayout; +import ch.qos.logback.core.util.CoreTestConstants; + +/** + * + * Do not forget to call start() when configuring programatically. + * + * @author Ceki Gülcü + * @author Sébastien Pennec + * + */ +public class SizeBasedRollingTest extends ScaffoldingForRollingTests { + + @Before + @Override + public void setUp() { + super.setUp(); + { + File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX + + "sizeBased-smoke.log"); + target.mkdirs(); + target.delete(); + } + { + File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX + + "sbr-test3.log"); + target.mkdirs(); + target.delete(); + } + } + + @After + public void tearDown() { + } + + /** + * Test whether FixedWindowRollingPolicy throws an exception when the + * ActiveFileName is not set. + */ + @Test + public void activeFileNameNotSet() throws Exception { + // We purposefully use the \n as the line separator. + // This makes the regression test system independent. + Context context = new ContextBase(); + Layout layout = new DummyLayout(); + RollingFileAppender rfa = new RollingFileAppender(); + rfa.setLayout(layout); + rfa.setContext(new ContextBase()); + + FixedWindowRollingPolicy fwrp = new FixedWindowRollingPolicy(); + fwrp.setContext(context); + fwrp.setParent(rfa); + SizeBasedTriggeringPolicy sbtp = new SizeBasedTriggeringPolicy(); + sbtp.setContext(context); + + sbtp.setMaxFileSize("100"); + sbtp.start(); + fwrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + + "sizeBased-test1.%i"); + try { + fwrp.start(); + fail("The absence of activeFileName option should have caused an exception."); + } catch (IllegalStateException e) { + return; + } + } + + /** + * Test basic rolling functionality. + */ + @Test + public void smoke() throws Exception { + Context context = new ContextBase(); + + EchoLayout layout = new EchoLayout(); + RollingFileAppender rfa = new RollingFileAppender(); + rfa.setName("ROLLING"); + rfa.setLayout(layout); + rfa.setContext(context); + // make the .log show first + rfa.setFile(randomOutputDir + "a-sizeBased-smoke.log"); + + FixedWindowRollingPolicy swrp = new FixedWindowRollingPolicy(); + swrp.setContext(context); + SizeBasedTriggeringPolicy sbtp = new SizeBasedTriggeringPolicy(); + sbtp.setContext(context); + + sbtp.setMaxFileSize("100"); + swrp.setMinIndex(0); + swrp.setFileNamePattern(randomOutputDir + "sizeBased-smoke.%i"); + swrp.setParent(rfa); + swrp.start(); + + rfa.setRollingPolicy(swrp); + rfa.setTriggeringPolicy(sbtp); + rfa.start(); + + int runLength = 45; + String prefix = "hello"; + for (int i = 0; i < runLength; i++) { + Thread.sleep(10); + rfa.doAppend(prefix+i); + } + + expectedFilenameList.add(randomOutputDir + "a-sizeBased-smoke.log"); + expectedFilenameList.add(randomOutputDir + "sizeBased-smoke.0"); + expectedFilenameList.add(randomOutputDir + "sizeBased-smoke.1"); + existenceCheck(expectedFilenameList); + + reverseSortedContentCheck(randomOutputDir, runLength, prefix); + } + + /** + * Same as testBasic but also with GZ compression. + */ + @Test + public void test3() throws Exception { + Context context = new ContextBase(); + EchoLayout layout = new EchoLayout(); + RollingFileAppender rfa = new RollingFileAppender(); + rfa.setLayout(layout); + rfa.setContext(context); + rfa.setFile(randomOutputDir + "a-sbr-test3.log"); + + FixedWindowRollingPolicy fwrp = new FixedWindowRollingPolicy(); + fwrp.setContext(context); + SizeBasedTriggeringPolicy sbtp = new SizeBasedTriggeringPolicy(); + sbtp.setContext(context); + + sbtp.setMaxFileSize("100"); + fwrp.setMinIndex(0); + // fwrp.setActiveFileName(Constants.TEST_DIR_PREFIX + + // "output/sbr-test3.log"); + fwrp.setFileNamePattern(randomOutputDir + "sbr-test3.%i.gz"); + fwrp.setParent(rfa); + fwrp.start(); + rfa.setRollingPolicy(fwrp); + rfa.setTriggeringPolicy(sbtp); + rfa.start(); + + int runLength = 40; + String prefix = "hello"; + for (int i = 0; i < runLength; i++) { + Thread.sleep(10); + rfa.doAppend("hello"+i); + } + + expectedFilenameList.add(randomOutputDir + "a-sbr-test3.log"); + expectedFilenameList.add(randomOutputDir + "sbr-test3.0.gz"); + expectedFilenameList.add(randomOutputDir + "sbr-test3.1.gz"); + + existenceCheck(expectedFilenameList); + reverseSortedContentCheck(randomOutputDir, runLength, prefix); + + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicyTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicyTest.java index feb83e1c6005d0fa50979fe753c8662cc79fa980..34cd1a9c0393ac84f08d999beef71795a78cd499 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicyTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicyTest.java @@ -1,58 +1,58 @@ -/** - * 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.rolling; - -import junit.framework.TestCase; -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; - -public class SizeBasedTriggeringPolicyTest extends TestCase { - - public void testStringToLong() { - Context context = new ContextBase(); - SizeBasedTriggeringPolicy policy = new SizeBasedTriggeringPolicy(); - policy.setContext(context); - - Long result; - - { - result = policy.toFileSize("123"); - assertEquals(new Long("123"), result); - } - { - result = policy.toFileSize("123KB"); - // = 123 * 1024 - assertEquals(new Long("125952"), result); - } - { - result = policy.toFileSize("123MB"); - // = 123 * 1024 * 1024 - assertEquals(new Long("128974848"), result); - } - { - result = policy.toFileSize("123GB"); - // = 123 * 1024 * 1024 * 1024 - assertEquals(new Long("132070244352"), result); - } - - { - result = policy.toFileSize("123xxxx"); - // = 123 * 1024 * 1024 * 1024 - assertEquals(new Long(SizeBasedTriggeringPolicy.DEFAULT_MAX_FILE_SIZE), - result); - assertEquals(2, context.getStatusManager().getCount()); - } - - } -} +/** + * 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.rolling; + +import junit.framework.TestCase; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; + +public class SizeBasedTriggeringPolicyTest extends TestCase { + + public void testStringToLong() { + Context context = new ContextBase(); + SizeBasedTriggeringPolicy policy = new SizeBasedTriggeringPolicy(); + policy.setContext(context); + + Long result; + + { + result = policy.toFileSize("123"); + assertEquals(new Long("123"), result); + } + { + result = policy.toFileSize("123KB"); + // = 123 * 1024 + assertEquals(new Long("125952"), result); + } + { + result = policy.toFileSize("123MB"); + // = 123 * 1024 * 1024 + assertEquals(new Long("128974848"), result); + } + { + result = policy.toFileSize("123GB"); + // = 123 * 1024 * 1024 * 1024 + assertEquals(new Long("132070244352"), result); + } + + { + result = policy.toFileSize("123xxxx"); + // = 123 * 1024 * 1024 * 1024 + assertEquals(new Long(SizeBasedTriggeringPolicy.DEFAULT_MAX_FILE_SIZE), + result); + assertEquals(2, context.getStatusManager().getCount()); + } + + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingTest.java index 46b3c2c2d11f09b78e29ec1d8c0739c1b2660b10..4c5b87bc551db6cf4a49069977adb37ccf9c280b 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingTest.java @@ -1,372 +1,372 @@ -/** - * 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.rolling; - -import static org.junit.Assert.assertTrue; - -import java.io.File; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.util.Compare; -import ch.qos.logback.core.util.CoreTestConstants; - -/** - * A rather exhaustive set of tests. Tests include leaving the file option - * blank, or setting it, with and without compression, and tests with or without - * stopping/restarting the RollingFileAppender. - * - * The regression tests log a few times using a RollingFileAppender. Then, they - * predict the names of the files which should be generated and compare them - * with witness files. - * - *
- *                Compression     file option    Stop/Restart 
- *     Test1      NO              BLANK           NO
- *     Test2      YES             BLANK           NO
- *     Test3      NO              BLANK           YES
- *     Test4      NO              SET             YES 
- *     Test5      NO              SET             NO
- *     Test6      YES             SET             NO
- * 
- * - * @author Ceki Gülcü - */ -public class TimeBasedRollingTest extends ScaffoldingForRollingTests { - - RollingFileAppender rfa1 = new RollingFileAppender(); - TimeBasedRollingPolicy tbrp1 = new TimeBasedRollingPolicy(); - - RollingFileAppender rfa2 = new RollingFileAppender(); - TimeBasedRollingPolicy tbrp2 = new TimeBasedRollingPolicy(); - - @Before - @Override - public void setUp() { - super.setUp(); - } - - @After - public void tearDown() { - } - - void initRFA(RollingFileAppender rfa, String filename) { - rfa.setContext(context); - rfa.setLayout(layout); - if (filename != null) { - rfa.setFile(filename); - } - } - - void initTRBP(RollingFileAppender rfa, - TimeBasedRollingPolicy tbrp, String filenamePattern, - long givenTime) { - tbrp.setContext(context); - tbrp.setFileNamePattern(filenamePattern); - tbrp.setParent(rfa); - tbrp.timeBasedTriggering = new DefaultTimeBasedFileNamingAndTriggeringPolicy(); - tbrp.timeBasedTriggering.setCurrentTime(givenTime); - rfa.setRollingPolicy(tbrp); - tbrp.start(); - rfa.start(); - } - - /** - * Test rolling without compression, file option left blank, no stop/start - */ - @Test - public void noCompression_FileBlank_NoRestart_1() throws Exception { - String testId = "test1"; - initRFA(rfa1, null); - initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}", currentTime); - - // compute the current filename - addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), false); - - incCurrentTime(1100); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - - for (int i = 0; i < 3; i++) { - rfa1.doAppend("Hello---" + i); - addExpectedFileNamedIfItsTime_ByDate(testId, false); - incCurrentTime(500); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - } - - int i = 0; - for (String fn : expectedFilenameList) { - assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX - + "witness/rolling/tbr-" + testId + "." + i++)); - } - } - - /** - * With compression, file option left blank, no stop/restart - */ - @Test - public void withCompression_FileBlank_NoRestart_2() throws Exception { - String testId = "test2"; - initRFA(rfa1, null); - initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}.gz", currentTime); - - addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), true); - incCurrentTime(1100); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - - for (int i = 0; i < 3; i++) { - // when i == 2, file name should not have .gz extension - addExpectedFileNamedIfItsTime_ByDate(testId, i != 2); - rfa1.doAppend("Hello---" + i); - incCurrentTime(500); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - waitForCompression(tbrp1); - } - - int i = 0; - for (String fn : expectedFilenameList) { - assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX - + "witness/rolling/tbr-" + testId + "." + i + addGZIfNotLast(i))); - i++; - } - } - - /** - * No compression, file option left blank, with stop/restart, - */ - @Test - public void noCompression_FileBlank_StopRestart_3() throws Exception { - String testId = "test3"; - - initRFA(rfa1, null); - initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}", currentTime); - - // a new file is created by virtue of rfa.start(); - addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), false); - - incCurrentTime(1100); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - - for (int i = 0; i <= 2; i++) { - rfa1.doAppend("Hello---" + i); - addExpectedFileNamedIfItsTime_ByDate(testId, false); - incCurrentTime(500); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - } - - rfa1.stop(); - - initRFA(rfa2, null); - initTRBP(rfa2, tbrp2, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}", tbrp1.timeBasedTriggering - .getCurrentTime()); - - for (int i = 0; i <= 2; i++) { - addExpectedFileNamedIfItsTime_ByDate(testId, false); - rfa2.doAppend("World---" + i); - incCurrentTime(100); - tbrp2.timeBasedTriggering.setCurrentTime(currentTime); - } - - int i = 0; - for (String fn : expectedFilenameList) { - assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX - + "witness/rolling/tbr-" + testId + "." + i++)); - } - } - - /** - * Without compression, file option set, with stop/restart - */ - @Test - public void noCompression_FileSet_StopRestart_4() throws Exception { - String testId = "test4"; - initRFA(rfa1, testId2FileName(testId)); - initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}", currentTime); - - addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), false); - - incCurrentTime(1100); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - - for (int i = 0; i <= 2; i++) { - rfa1.doAppend("Hello---" + i); - addExpectedFileNamedIfItsTime_ByDate(testId, false); - incCurrentTime(500); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - } - - rfa1.stop(); - - // change the timestamp of the currently actively file - File activeFile = new File(rfa1.getFile()); - activeFile.setLastModified(currentTime); - - initRFA(rfa2, testId2FileName(testId)); - initTRBP(rfa2, tbrp2, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}", currentTime); - - for (int i = 0; i <= 2; i++) { - rfa2.doAppend("World---" + i); - addExpectedFileNamedIfItsTime_ByDate(testId, false); - incCurrentTime(100); - tbrp2.timeBasedTriggering.setCurrentTime(currentTime); - } - - massageExpectedFilesToCorresponToCurrentTarget("test4.log"); - - int i = 0; - for (String fn : expectedFilenameList) { - assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX - + "witness/rolling/tbr-" + testId + "." + i++)); - } - } - - @Test - public void noCompression_FileSet_StopRestart_WithLongWait_4B() - throws Exception { - String testId = "test4B"; - initRFA(rfa1, testId2FileName(testId)); - initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}", currentTime); - - addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), false); - - incCurrentTime(1100); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - - for (int i = 0; i <= 2; i++) { - rfa1.doAppend("Hello---" + i); - addExpectedFileNamedIfItsTime_ByDate(testId, false); - incCurrentTime(500); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - } - - rfa1.stop(); - - // change the timestamp of the currently actively file - File activeFile = new File(rfa1.getFile()); - activeFile.setLastModified(currentTime); - - incCurrentTime(2000); - - initRFA(rfa2, randomOutputDir + "test4B.log"); - initTRBP(rfa2, tbrp2, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}", currentTime); - - for (int i = 0; i <= 2; i++) { - rfa2.doAppend("World---" + i); - addExpectedFileNamedIfItsTime_ByDate(testId, false); - incCurrentTime(100); - tbrp2.timeBasedTriggering.setCurrentTime(currentTime); - } - - massageExpectedFilesToCorresponToCurrentTarget("test4B.log"); - - int i = 0; - for (String fn : expectedFilenameList) { - assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX - + "witness/rolling/tbr-test4B." + i++)); - } - - } - - /** - * No compression, file option set, without stop/restart - */ - @Test - public void noCompression_FileSet_NoRestart_5() throws Exception { - String testId = "test5"; - - initRFA(rfa1, testId2FileName(testId)); - initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}", currentTime); - - addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), false); - - incCurrentTime(1100); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - - for (int i = 0; i < 3; i++) { - rfa1.doAppend("Hello---" + i); - addExpectedFileNamedIfItsTime_ByDate(testId, false); - incCurrentTime(500); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - } - - massageExpectedFilesToCorresponToCurrentTarget("test5.log"); - - int i = 0; - for (String fn : expectedFilenameList) { - assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX - + "witness/rolling/tbr-test5." + i++)); - } - } - - /** - * With compression, file option set, no stop/restart, - */ - @Test - public void withCompression_FileSet_NoRestart_6() throws Exception { - - String testId = "test6"; - - initRFA(rfa1, testId2FileName(testId)); - initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}.gz", currentTime); - - addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), true); - - incCurrentTime(1100); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - - for (int i = 0; i < 3; i++) { - rfa1.doAppend("Hello---" + i); - addExpectedFileNamedIfItsTime_ByDate(testId, true); - incCurrentTime(500); - tbrp1.timeBasedTriggering.setCurrentTime(currentTime); - waitForCompression(tbrp1); - } - - massageExpectedFilesToCorresponToCurrentTarget("test6.log"); - - int i = 0; - for (String fn : expectedFilenameList) { - assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX - + "witness/rolling/tbr-" + testId + "." + i + addGZIfNotLast(i))); - i++; - } - } - - // ========================================================================= - // utility methods - // ========================================================================= - - void massageExpectedFilesToCorresponToCurrentTarget(String file) { - // we added one too many files by date - expectedFilenameList.remove(expectedFilenameList.size() - 1); - // since file is set, we have to add it - addExpectedFileName_ByFile(file); - } - - void addExpectedFileName_ByFile(String filenameSuffix) { - String fn = randomOutputDir + filenameSuffix; - expectedFilenameList.add(fn); - } -} +/** + * 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.rolling; + +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.util.Compare; +import ch.qos.logback.core.util.CoreTestConstants; + +/** + * A rather exhaustive set of tests. Tests include leaving the file option + * blank, or setting it, with and without compression, and tests with or without + * stopping/restarting the RollingFileAppender. + * + * The regression tests log a few times using a RollingFileAppender. Then, they + * predict the names of the files which should be generated and compare them + * with witness files. + * + *
+ *                Compression     file option    Stop/Restart 
+ *     Test1      NO              BLANK           NO
+ *     Test2      YES             BLANK           NO
+ *     Test3      NO              BLANK           YES
+ *     Test4      NO              SET             YES 
+ *     Test5      NO              SET             NO
+ *     Test6      YES             SET             NO
+ * 
+ * + * @author Ceki Gülcü + */ +public class TimeBasedRollingTest extends ScaffoldingForRollingTests { + + RollingFileAppender rfa1 = new RollingFileAppender(); + TimeBasedRollingPolicy tbrp1 = new TimeBasedRollingPolicy(); + + RollingFileAppender rfa2 = new RollingFileAppender(); + TimeBasedRollingPolicy tbrp2 = new TimeBasedRollingPolicy(); + + @Before + @Override + public void setUp() { + super.setUp(); + } + + @After + public void tearDown() { + } + + void initRFA(RollingFileAppender rfa, String filename) { + rfa.setContext(context); + rfa.setLayout(layout); + if (filename != null) { + rfa.setFile(filename); + } + } + + void initTRBP(RollingFileAppender rfa, + TimeBasedRollingPolicy tbrp, String filenamePattern, + long givenTime) { + tbrp.setContext(context); + tbrp.setFileNamePattern(filenamePattern); + tbrp.setParent(rfa); + tbrp.timeBasedTriggering = new DefaultTimeBasedFileNamingAndTriggeringPolicy(); + tbrp.timeBasedTriggering.setCurrentTime(givenTime); + rfa.setRollingPolicy(tbrp); + tbrp.start(); + rfa.start(); + } + + /** + * Test rolling without compression, file option left blank, no stop/start + */ + @Test + public void noCompression_FileBlank_NoRestart_1() throws Exception { + String testId = "test1"; + initRFA(rfa1, null); + initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}", currentTime); + + // compute the current filename + addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), false); + + incCurrentTime(1100); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + + for (int i = 0; i < 3; i++) { + rfa1.doAppend("Hello---" + i); + addExpectedFileNamedIfItsTime_ByDate(testId, false); + incCurrentTime(500); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + } + + int i = 0; + for (String fn : expectedFilenameList) { + assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX + + "witness/rolling/tbr-" + testId + "." + i++)); + } + } + + /** + * With compression, file option left blank, no stop/restart + */ + @Test + public void withCompression_FileBlank_NoRestart_2() throws Exception { + String testId = "test2"; + initRFA(rfa1, null); + initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}.gz", currentTime); + + addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), true); + incCurrentTime(1100); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + + for (int i = 0; i < 3; i++) { + // when i == 2, file name should not have .gz extension + addExpectedFileNamedIfItsTime_ByDate(testId, i != 2); + rfa1.doAppend("Hello---" + i); + incCurrentTime(500); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + waitForCompression(tbrp1); + } + + int i = 0; + for (String fn : expectedFilenameList) { + assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX + + "witness/rolling/tbr-" + testId + "." + i + addGZIfNotLast(i))); + i++; + } + } + + /** + * No compression, file option left blank, with stop/restart, + */ + @Test + public void noCompression_FileBlank_StopRestart_3() throws Exception { + String testId = "test3"; + + initRFA(rfa1, null); + initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}", currentTime); + + // a new file is created by virtue of rfa.start(); + addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), false); + + incCurrentTime(1100); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + + for (int i = 0; i <= 2; i++) { + rfa1.doAppend("Hello---" + i); + addExpectedFileNamedIfItsTime_ByDate(testId, false); + incCurrentTime(500); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + } + + rfa1.stop(); + + initRFA(rfa2, null); + initTRBP(rfa2, tbrp2, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}", tbrp1.timeBasedTriggering + .getCurrentTime()); + + for (int i = 0; i <= 2; i++) { + addExpectedFileNamedIfItsTime_ByDate(testId, false); + rfa2.doAppend("World---" + i); + incCurrentTime(100); + tbrp2.timeBasedTriggering.setCurrentTime(currentTime); + } + + int i = 0; + for (String fn : expectedFilenameList) { + assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX + + "witness/rolling/tbr-" + testId + "." + i++)); + } + } + + /** + * Without compression, file option set, with stop/restart + */ + @Test + public void noCompression_FileSet_StopRestart_4() throws Exception { + String testId = "test4"; + initRFA(rfa1, testId2FileName(testId)); + initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}", currentTime); + + addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), false); + + incCurrentTime(1100); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + + for (int i = 0; i <= 2; i++) { + rfa1.doAppend("Hello---" + i); + addExpectedFileNamedIfItsTime_ByDate(testId, false); + incCurrentTime(500); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + } + + rfa1.stop(); + + // change the timestamp of the currently actively file + File activeFile = new File(rfa1.getFile()); + activeFile.setLastModified(currentTime); + + initRFA(rfa2, testId2FileName(testId)); + initTRBP(rfa2, tbrp2, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}", currentTime); + + for (int i = 0; i <= 2; i++) { + rfa2.doAppend("World---" + i); + addExpectedFileNamedIfItsTime_ByDate(testId, false); + incCurrentTime(100); + tbrp2.timeBasedTriggering.setCurrentTime(currentTime); + } + + massageExpectedFilesToCorresponToCurrentTarget("test4.log"); + + int i = 0; + for (String fn : expectedFilenameList) { + assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX + + "witness/rolling/tbr-" + testId + "." + i++)); + } + } + + @Test + public void noCompression_FileSet_StopRestart_WithLongWait_4B() + throws Exception { + String testId = "test4B"; + initRFA(rfa1, testId2FileName(testId)); + initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}", currentTime); + + addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), false); + + incCurrentTime(1100); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + + for (int i = 0; i <= 2; i++) { + rfa1.doAppend("Hello---" + i); + addExpectedFileNamedIfItsTime_ByDate(testId, false); + incCurrentTime(500); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + } + + rfa1.stop(); + + // change the timestamp of the currently actively file + File activeFile = new File(rfa1.getFile()); + activeFile.setLastModified(currentTime); + + incCurrentTime(2000); + + initRFA(rfa2, randomOutputDir + "test4B.log"); + initTRBP(rfa2, tbrp2, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}", currentTime); + + for (int i = 0; i <= 2; i++) { + rfa2.doAppend("World---" + i); + addExpectedFileNamedIfItsTime_ByDate(testId, false); + incCurrentTime(100); + tbrp2.timeBasedTriggering.setCurrentTime(currentTime); + } + + massageExpectedFilesToCorresponToCurrentTarget("test4B.log"); + + int i = 0; + for (String fn : expectedFilenameList) { + assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX + + "witness/rolling/tbr-test4B." + i++)); + } + + } + + /** + * No compression, file option set, without stop/restart + */ + @Test + public void noCompression_FileSet_NoRestart_5() throws Exception { + String testId = "test5"; + + initRFA(rfa1, testId2FileName(testId)); + initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}", currentTime); + + addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), false); + + incCurrentTime(1100); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + + for (int i = 0; i < 3; i++) { + rfa1.doAppend("Hello---" + i); + addExpectedFileNamedIfItsTime_ByDate(testId, false); + incCurrentTime(500); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + } + + massageExpectedFilesToCorresponToCurrentTarget("test5.log"); + + int i = 0; + for (String fn : expectedFilenameList) { + assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX + + "witness/rolling/tbr-test5." + i++)); + } + } + + /** + * With compression, file option set, no stop/restart, + */ + @Test + public void withCompression_FileSet_NoRestart_6() throws Exception { + + String testId = "test6"; + + initRFA(rfa1, testId2FileName(testId)); + initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}.gz", currentTime); + + addExpectedFileName_ByDate(testId, getDateOfCurrentPeriodsStart(), true); + + incCurrentTime(1100); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + + for (int i = 0; i < 3; i++) { + rfa1.doAppend("Hello---" + i); + addExpectedFileNamedIfItsTime_ByDate(testId, true); + incCurrentTime(500); + tbrp1.timeBasedTriggering.setCurrentTime(currentTime); + waitForCompression(tbrp1); + } + + massageExpectedFilesToCorresponToCurrentTarget("test6.log"); + + int i = 0; + for (String fn : expectedFilenameList) { + assertTrue(Compare.compare(fn, CoreTestConstants.TEST_DIR_PREFIX + + "witness/rolling/tbr-" + testId + "." + i + addGZIfNotLast(i))); + i++; + } + } + + // ========================================================================= + // utility methods + // ========================================================================= + + void massageExpectedFilesToCorresponToCurrentTarget(String file) { + // we added one too many files by date + expectedFilenameList.remove(expectedFilenameList.size() - 1); + // since file is set, we have to add it + addExpectedFileName_ByFile(file); + } + + void addExpectedFileName_ByFile(String filenameSuffix) { + String fn = randomOutputDir + filenameSuffix; + expectedFilenameList.add(fn); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java index ce708d576dece812f7926d48c4bef4938550485a..f4335232e56abb858ab7616c675ea82b13bf1e66 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java @@ -1,371 +1,371 @@ -/** - * 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.rolling; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.FileFilter; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.layout.EchoLayout; -import ch.qos.logback.core.testUtil.RandomUtil; -import ch.qos.logback.core.util.CoreTestConstants; - -public class TimeBasedRollingWithArchiveRemovalTest { - - Context context = new ContextBase(); - EchoLayout layout = new EchoLayout(); - - static final String MONTHLY_DATE_PATTERN = "yyyy-MM"; - static final String MONTHLY_CROLOLOG_DATE_PATTERN = "yyyy/MM"; - - static final String DAILY_DATE_PATTERN = "yyyy-MM-dd"; - static final String DAILY_CROLOLOG_DATE_PATTERN = "yyyy/MM/dd"; - - static final long MILLIS_IN_MINUTE = 60 * 1000; - static final long MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE; - static final long MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR; - static final long MILLIS_IN_MONTH = 30 * MILLIS_IN_DAY; - - int diff = RandomUtil.getPositiveInt(); - protected String randomOutputDir = CoreTestConstants.OUTPUT_DIR_PREFIX + diff - + "/"; - int slashCount; - - // by default tbfnatp is an instance of - // DefaultTimeBasedFileNamingAndTriggeringPolicy - TimeBasedFileNamingAndTriggeringPolicy tbfnatp = new DefaultTimeBasedFileNamingAndTriggeringPolicy(); - - @Before - public void setUp() { - context.setName("test"); - } - - @After - public void tearDown() throws Exception { - } - - int computeSlashCount(String datePattern) { - int fromIndex = 0; - int count = 0; - while (true) { - int i = datePattern.indexOf('/', fromIndex); - if (i == -1) { - break; - } else { - count++; - fromIndex = i + 1; - if (fromIndex >= datePattern.length()) { - break; - } - } - } - return count; - } - - @Test - public void montlyRollover() throws Exception { - slashCount = computeSlashCount(MONTHLY_DATE_PATTERN); - // large maxPeriod, a 3 times as many number of periods to simulate - doRollover(randomOutputDir + "clean-%d{" + MONTHLY_DATE_PATTERN + "}.txt", - MILLIS_IN_MONTH, 20, 20 * 3); - check(expectedCountWithoutFolders(20)); - } - - @Test - public void montlyRolloverOverManyPeriods() throws Exception { - System.out.println("randomOutputDir=" + randomOutputDir); - // small maxHistory, many periods - slashCount = computeSlashCount(MONTHLY_CROLOLOG_DATE_PATTERN); - int numPeriods = 40; - int maxHistory = 2; - - doRollover(randomOutputDir + "/%d{" + MONTHLY_CROLOLOG_DATE_PATTERN - + "}/clean.txt.zip", MILLIS_IN_MONTH, maxHistory, numPeriods); - int beginPeriod = Calendar.getInstance().get(Calendar.MONTH); - boolean extraFolder = extraFolder(numPeriods, 12, beginPeriod, maxHistory); - check(expectedCountWithFolders(2, extraFolder)); - } - - @Test - public void dailyRollover() throws Exception { - slashCount = computeSlashCount(DAILY_DATE_PATTERN); - doRollover( - randomOutputDir + "clean-%d{" + DAILY_DATE_PATTERN + "}.txt.zip", - MILLIS_IN_DAY, 5, 5 * 3); - check(expectedCountWithoutFolders(5)); - } - - @Test - public void dailyCronologRollover() throws Exception { - slashCount = computeSlashCount(DAILY_CROLOLOG_DATE_PATTERN); - doRollover(randomOutputDir + "/%d{" + DAILY_CROLOLOG_DATE_PATTERN - + "}/clean.txt.zip", MILLIS_IN_DAY, 8, 8 * 3); - int expectedDirMin = 9 + slashCount; - int expectDirMax = expectedDirMin + 1 + 1; // plus 1 of stepping into a - // new month, and another 1 into - // a new year - expectedFileAndDirCount(9, expectedDirMin, expectDirMax); - } - - @Test - public void dailySizeBasedRollover() throws Exception { - SizeAndTimeBasedFNATP sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP(); - sizeAndTimeBasedFNATP.setMaxFileSize("10000"); - tbfnatp = sizeAndTimeBasedFNATP; - - slashCount = computeSlashCount(DAILY_DATE_PATTERN); - doRollover( - randomOutputDir + "/%d{" + DAILY_DATE_PATTERN + "}-clean.%i.zip", - MILLIS_IN_DAY, 5, 5 * 4); - - // make .zip optional so that if for one reason or another, no size-based - // rollover occurs on the last period, that the last period is still - // accounted - // for - checkPatternCompliance(5 + 1 + slashCount, - "\\d{4}-\\d{2}-\\d{2}-clean(\\.\\d)(.zip)?"); - } - - @Test - public void dailyChronologSizeBasedRollover() throws Exception { - SizeAndTimeBasedFNATP sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP(); - sizeAndTimeBasedFNATP.setMaxFileSize("10000"); - tbfnatp = sizeAndTimeBasedFNATP; - - slashCount = 1; - doRollover( - randomOutputDir + "/%d{" + DAILY_DATE_PATTERN + "}/clean.%i.zip", - MILLIS_IN_DAY, 5, 5 * 4); - checkDirPatternCompliance(6); - } - - void doRollover(String fileNamePattern, long periodDurationInMillis, - int maxHistory, int simulatedNumberOfPeriods) throws Exception { - long currentTime = System.currentTimeMillis(); - - RollingFileAppender rfa = new RollingFileAppender(); - rfa.setContext(context); - rfa.setLayout(layout); - // rfa.setFile(Constants.OUTPUT_DIR_PREFIX + "clean.txt"); - TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy(); - tbrp.setContext(context); - tbrp.setFileNamePattern(fileNamePattern); - - tbrp.setMaxHistory(maxHistory); - tbrp.setParent(rfa); - tbrp.timeBasedTriggering = tbfnatp; - tbrp.timeBasedTriggering.setCurrentTime(currentTime); - tbrp.start(); - rfa.setRollingPolicy(tbrp); - rfa.start(); - - // lots of ticks per period - int ticksPerPeriod = 512; - long runLength = simulatedNumberOfPeriods * ticksPerPeriod; - - for (long i = 0; i < runLength; i++) { - rfa - .doAppend("Hello ----------------------------------------------------------" - + i); - tbrp.timeBasedTriggering.setCurrentTime(addTime(tbrp.timeBasedTriggering - .getCurrentTime(), periodDurationInMillis / ticksPerPeriod)); - - // wait every now and then for the compression job - // otherwise, we might rollover a file for a given period before a previous - // period's compressor had a chance to run - if(i % (ticksPerPeriod/2) == 0) { - waitForCompression(tbrp); - } - } - waitForCompression(tbrp); - rfa.stop(); - } - - void waitForCompression(TimeBasedRollingPolicy tbrp) - throws InterruptedException, ExecutionException, TimeoutException { - if (tbrp.future != null && !tbrp.future.isDone()) { - tbrp.future.get(200, TimeUnit.MILLISECONDS); - } - } - - void findAllFoldersRecursively(File dir, List fileList) { - if (dir.isDirectory()) { - File[] match = dir.listFiles(new FileFilter() { - public boolean accept(File f) { - return (f.isDirectory()); - } - }); - for (File f : match) { - fileList.add(f); - findAllFoldersRecursively(f, fileList); - } - } - } - - void findAllInFolderRecursivelyByStringContains(File dir, - List fileList, final String pattern) { - if (dir.isDirectory()) { - File[] match = dir.listFiles(new FileFilter() { - public boolean accept(File f) { - return (f.isDirectory() || f.getName().contains(pattern)); - } - }); - for (File f : match) { - fileList.add(f); - if (f.isDirectory()) { - findAllInFolderRecursivelyByStringContains(f, fileList, pattern); - } - } - } - } - - void findFilesInFolderRecursivelyByPatterMatch(File dir, List fileList, - final String pattern) { - if (dir.isDirectory()) { - File[] match = dir.listFiles(new FileFilter() { - public boolean accept(File f) { - return (f.isDirectory() || f.getName().matches(pattern)); - } - }); - for (File f : match) { - if (f.isDirectory()) { - findFilesInFolderRecursivelyByPatterMatch(f, fileList, pattern); - } else { - fileList.add(f); - } - } - } - } - - void findFoldersInFolderRecursively(File dir, List fileList) { - if (dir.isDirectory()) { - File[] match = dir.listFiles(new FileFilter() { - public boolean accept(File f) { - return f.isDirectory(); - } - }); - for (File f : match) { - fileList.add(f); - findFoldersInFolderRecursively(f, fileList); - } - } - } - - int expectedCountWithoutFolders(int maxHistory) { - // maxHistory plus the currently active file - return maxHistory + 1; - } - - // sometimes, after a number of periods, there is an extra folder - // from the previous "era" because the latest period - maxHistory, enters the - // bound of the previous era. For example, with a maxHistory of 2, on 2009-09, - // after 40 periods, the current period is 2013-01. Going back two months, the - // year is 2012, and not 2013 (the current year). - boolean extraFolder(int numPeriods, int periodsPerEra, int beginPeriod, - int maxHistory) { - int adjustedBegin = beginPeriod + 1; - int remainder = ((adjustedBegin) + numPeriods) % periodsPerEra; - return (remainder < maxHistory + 1); - } - - int expectedCountWithFolders(int maxHistory, boolean extraFolder) { - // each slash adds a new directory - // + one file and one directory per archived log file - int result = (maxHistory + 1) * 2 + slashCount; - if (extraFolder) - result++; - return result; - } - - void check(int expectedCount) { - File dir = new File(randomOutputDir); - List fileList = new ArrayList(); - findAllInFolderRecursivelyByStringContains(dir, fileList, "clean"); - assertEquals(expectedCount, fileList.size()); - } - - void expectedFileAndDirCount(int expectedFileAndDirCount, - int expectedDirCountMin, int expectedDirCountMax) { - File dir = new File(randomOutputDir); - List fileList = new ArrayList(); - findFilesInFolderRecursivelyByPatterMatch(dir, fileList, "clean"); - - List dirList = new ArrayList(); - findAllFoldersRecursively(dir, dirList); - assertTrue("expectedDirCountMin=" + expectedDirCountMin - + ", expectedDirCountMax=" + expectedDirCountMax + " actual value=" - + dirList.size(), expectedDirCountMin <= dirList.size() - && dirList.size() <= expectedDirCountMax); - } - - void checkPatternCompliance(int expectedClassCount, String regex) { - File dir = new File(randomOutputDir); - List fileList = new ArrayList(); - findFilesInFolderRecursivelyByPatterMatch(dir, fileList, regex); - Set set = groupByClass(fileList, regex); - assertEquals(expectedClassCount, set.size()); - } - - void checkDirPatternCompliance(int expectedClassCount) { - File dir = new File(randomOutputDir); - List fileList = new ArrayList(); - findFoldersInFolderRecursively(dir, fileList); - for (File f : fileList) { - assertTrue(f.list().length >= 1); - } - assertEquals(expectedClassCount, fileList.size()); - } - - // reduce file names differing by index number into the same group - // for example, 2009-11-01-clean.0.zip, 2009-11-01-clean.1.zip and - // 2009-11-01-clean-2 are reduced into the same string (group) - // 2009-11-01-clean - Set groupByClass(List fileList, String regex) { - Pattern p = Pattern.compile(regex); - Set set = new HashSet(); - for (File f : fileList) { - String n = f.getName(); - Matcher m = p.matcher(n); - m.matches(); - int begin = m.start(1); - String reduced = n.substring(0, begin); - set.add(reduced); - } - System.out.println(set); - return set; - } - - static long addTime(long currentTime, long timeToWait) { - return currentTime + timeToWait; - } - -} +/** + * 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.rolling; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileFilter; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.layout.EchoLayout; +import ch.qos.logback.core.testUtil.RandomUtil; +import ch.qos.logback.core.util.CoreTestConstants; + +public class TimeBasedRollingWithArchiveRemovalTest { + + Context context = new ContextBase(); + EchoLayout layout = new EchoLayout(); + + static final String MONTHLY_DATE_PATTERN = "yyyy-MM"; + static final String MONTHLY_CROLOLOG_DATE_PATTERN = "yyyy/MM"; + + static final String DAILY_DATE_PATTERN = "yyyy-MM-dd"; + static final String DAILY_CROLOLOG_DATE_PATTERN = "yyyy/MM/dd"; + + static final long MILLIS_IN_MINUTE = 60 * 1000; + static final long MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE; + static final long MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR; + static final long MILLIS_IN_MONTH = 30 * MILLIS_IN_DAY; + + int diff = RandomUtil.getPositiveInt(); + protected String randomOutputDir = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + + "/"; + int slashCount; + + // by default tbfnatp is an instance of + // DefaultTimeBasedFileNamingAndTriggeringPolicy + TimeBasedFileNamingAndTriggeringPolicy tbfnatp = new DefaultTimeBasedFileNamingAndTriggeringPolicy(); + + @Before + public void setUp() { + context.setName("test"); + } + + @After + public void tearDown() throws Exception { + } + + int computeSlashCount(String datePattern) { + int fromIndex = 0; + int count = 0; + while (true) { + int i = datePattern.indexOf('/', fromIndex); + if (i == -1) { + break; + } else { + count++; + fromIndex = i + 1; + if (fromIndex >= datePattern.length()) { + break; + } + } + } + return count; + } + + @Test + public void montlyRollover() throws Exception { + slashCount = computeSlashCount(MONTHLY_DATE_PATTERN); + // large maxPeriod, a 3 times as many number of periods to simulate + doRollover(randomOutputDir + "clean-%d{" + MONTHLY_DATE_PATTERN + "}.txt", + MILLIS_IN_MONTH, 20, 20 * 3); + check(expectedCountWithoutFolders(20)); + } + + @Test + public void montlyRolloverOverManyPeriods() throws Exception { + System.out.println("randomOutputDir=" + randomOutputDir); + // small maxHistory, many periods + slashCount = computeSlashCount(MONTHLY_CROLOLOG_DATE_PATTERN); + int numPeriods = 40; + int maxHistory = 2; + + doRollover(randomOutputDir + "/%d{" + MONTHLY_CROLOLOG_DATE_PATTERN + + "}/clean.txt.zip", MILLIS_IN_MONTH, maxHistory, numPeriods); + int beginPeriod = Calendar.getInstance().get(Calendar.MONTH); + boolean extraFolder = extraFolder(numPeriods, 12, beginPeriod, maxHistory); + check(expectedCountWithFolders(2, extraFolder)); + } + + @Test + public void dailyRollover() throws Exception { + slashCount = computeSlashCount(DAILY_DATE_PATTERN); + doRollover( + randomOutputDir + "clean-%d{" + DAILY_DATE_PATTERN + "}.txt.zip", + MILLIS_IN_DAY, 5, 5 * 3); + check(expectedCountWithoutFolders(5)); + } + + @Test + public void dailyCronologRollover() throws Exception { + slashCount = computeSlashCount(DAILY_CROLOLOG_DATE_PATTERN); + doRollover(randomOutputDir + "/%d{" + DAILY_CROLOLOG_DATE_PATTERN + + "}/clean.txt.zip", MILLIS_IN_DAY, 8, 8 * 3); + int expectedDirMin = 9 + slashCount; + int expectDirMax = expectedDirMin + 1 + 1; // plus 1 of stepping into a + // new month, and another 1 into + // a new year + expectedFileAndDirCount(9, expectedDirMin, expectDirMax); + } + + @Test + public void dailySizeBasedRollover() throws Exception { + SizeAndTimeBasedFNATP sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP(); + sizeAndTimeBasedFNATP.setMaxFileSize("10000"); + tbfnatp = sizeAndTimeBasedFNATP; + + slashCount = computeSlashCount(DAILY_DATE_PATTERN); + doRollover( + randomOutputDir + "/%d{" + DAILY_DATE_PATTERN + "}-clean.%i.zip", + MILLIS_IN_DAY, 5, 5 * 4); + + // make .zip optional so that if for one reason or another, no size-based + // rollover occurs on the last period, that the last period is still + // accounted + // for + checkPatternCompliance(5 + 1 + slashCount, + "\\d{4}-\\d{2}-\\d{2}-clean(\\.\\d)(.zip)?"); + } + + @Test + public void dailyChronologSizeBasedRollover() throws Exception { + SizeAndTimeBasedFNATP sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP(); + sizeAndTimeBasedFNATP.setMaxFileSize("10000"); + tbfnatp = sizeAndTimeBasedFNATP; + + slashCount = 1; + doRollover( + randomOutputDir + "/%d{" + DAILY_DATE_PATTERN + "}/clean.%i.zip", + MILLIS_IN_DAY, 5, 5 * 4); + checkDirPatternCompliance(6); + } + + void doRollover(String fileNamePattern, long periodDurationInMillis, + int maxHistory, int simulatedNumberOfPeriods) throws Exception { + long currentTime = System.currentTimeMillis(); + + RollingFileAppender rfa = new RollingFileAppender(); + rfa.setContext(context); + rfa.setLayout(layout); + // rfa.setFile(Constants.OUTPUT_DIR_PREFIX + "clean.txt"); + TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy(); + tbrp.setContext(context); + tbrp.setFileNamePattern(fileNamePattern); + + tbrp.setMaxHistory(maxHistory); + tbrp.setParent(rfa); + tbrp.timeBasedTriggering = tbfnatp; + tbrp.timeBasedTriggering.setCurrentTime(currentTime); + tbrp.start(); + rfa.setRollingPolicy(tbrp); + rfa.start(); + + // lots of ticks per period + int ticksPerPeriod = 512; + long runLength = simulatedNumberOfPeriods * ticksPerPeriod; + + for (long i = 0; i < runLength; i++) { + rfa + .doAppend("Hello ----------------------------------------------------------" + + i); + tbrp.timeBasedTriggering.setCurrentTime(addTime(tbrp.timeBasedTriggering + .getCurrentTime(), periodDurationInMillis / ticksPerPeriod)); + + // wait every now and then for the compression job + // otherwise, we might rollover a file for a given period before a previous + // period's compressor had a chance to run + if(i % (ticksPerPeriod/2) == 0) { + waitForCompression(tbrp); + } + } + waitForCompression(tbrp); + rfa.stop(); + } + + void waitForCompression(TimeBasedRollingPolicy tbrp) + throws InterruptedException, ExecutionException, TimeoutException { + if (tbrp.future != null && !tbrp.future.isDone()) { + tbrp.future.get(200, TimeUnit.MILLISECONDS); + } + } + + void findAllFoldersRecursively(File dir, List fileList) { + if (dir.isDirectory()) { + File[] match = dir.listFiles(new FileFilter() { + public boolean accept(File f) { + return (f.isDirectory()); + } + }); + for (File f : match) { + fileList.add(f); + findAllFoldersRecursively(f, fileList); + } + } + } + + void findAllInFolderRecursivelyByStringContains(File dir, + List fileList, final String pattern) { + if (dir.isDirectory()) { + File[] match = dir.listFiles(new FileFilter() { + public boolean accept(File f) { + return (f.isDirectory() || f.getName().contains(pattern)); + } + }); + for (File f : match) { + fileList.add(f); + if (f.isDirectory()) { + findAllInFolderRecursivelyByStringContains(f, fileList, pattern); + } + } + } + } + + void findFilesInFolderRecursivelyByPatterMatch(File dir, List fileList, + final String pattern) { + if (dir.isDirectory()) { + File[] match = dir.listFiles(new FileFilter() { + public boolean accept(File f) { + return (f.isDirectory() || f.getName().matches(pattern)); + } + }); + for (File f : match) { + if (f.isDirectory()) { + findFilesInFolderRecursivelyByPatterMatch(f, fileList, pattern); + } else { + fileList.add(f); + } + } + } + } + + void findFoldersInFolderRecursively(File dir, List fileList) { + if (dir.isDirectory()) { + File[] match = dir.listFiles(new FileFilter() { + public boolean accept(File f) { + return f.isDirectory(); + } + }); + for (File f : match) { + fileList.add(f); + findFoldersInFolderRecursively(f, fileList); + } + } + } + + int expectedCountWithoutFolders(int maxHistory) { + // maxHistory plus the currently active file + return maxHistory + 1; + } + + // sometimes, after a number of periods, there is an extra folder + // from the previous "era" because the latest period - maxHistory, enters the + // bound of the previous era. For example, with a maxHistory of 2, on 2009-09, + // after 40 periods, the current period is 2013-01. Going back two months, the + // year is 2012, and not 2013 (the current year). + boolean extraFolder(int numPeriods, int periodsPerEra, int beginPeriod, + int maxHistory) { + int adjustedBegin = beginPeriod + 1; + int remainder = ((adjustedBegin) + numPeriods) % periodsPerEra; + return (remainder < maxHistory + 1); + } + + int expectedCountWithFolders(int maxHistory, boolean extraFolder) { + // each slash adds a new directory + // + one file and one directory per archived log file + int result = (maxHistory + 1) * 2 + slashCount; + if (extraFolder) + result++; + return result; + } + + void check(int expectedCount) { + File dir = new File(randomOutputDir); + List fileList = new ArrayList(); + findAllInFolderRecursivelyByStringContains(dir, fileList, "clean"); + assertEquals(expectedCount, fileList.size()); + } + + void expectedFileAndDirCount(int expectedFileAndDirCount, + int expectedDirCountMin, int expectedDirCountMax) { + File dir = new File(randomOutputDir); + List fileList = new ArrayList(); + findFilesInFolderRecursivelyByPatterMatch(dir, fileList, "clean"); + + List dirList = new ArrayList(); + findAllFoldersRecursively(dir, dirList); + assertTrue("expectedDirCountMin=" + expectedDirCountMin + + ", expectedDirCountMax=" + expectedDirCountMax + " actual value=" + + dirList.size(), expectedDirCountMin <= dirList.size() + && dirList.size() <= expectedDirCountMax); + } + + void checkPatternCompliance(int expectedClassCount, String regex) { + File dir = new File(randomOutputDir); + List fileList = new ArrayList(); + findFilesInFolderRecursivelyByPatterMatch(dir, fileList, regex); + Set set = groupByClass(fileList, regex); + assertEquals(expectedClassCount, set.size()); + } + + void checkDirPatternCompliance(int expectedClassCount) { + File dir = new File(randomOutputDir); + List fileList = new ArrayList(); + findFoldersInFolderRecursively(dir, fileList); + for (File f : fileList) { + assertTrue(f.list().length >= 1); + } + assertEquals(expectedClassCount, fileList.size()); + } + + // reduce file names differing by index number into the same group + // for example, 2009-11-01-clean.0.zip, 2009-11-01-clean.1.zip and + // 2009-11-01-clean-2 are reduced into the same string (group) + // 2009-11-01-clean + Set groupByClass(List fileList, String regex) { + Pattern p = Pattern.compile(regex); + Set set = new HashSet(); + for (File f : fileList) { + String n = f.getName(); + Matcher m = p.matcher(n); + m.matches(); + int begin = m.start(1); + String reduced = n.substring(0, begin); + set.add(reduced); + } + System.out.println(set); + return set; + } + + static long addTime(long currentTime, long timeToWait) { + return currentTime + timeToWait; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/CompressTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/CompressTest.java index 785d6e4cd1e183e97e654cacb6de391d1b8a8c30..b69734d91a6710233ce9b4f38c2660369aabd1e5 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/CompressTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/CompressTest.java @@ -1,140 +1,140 @@ -/** - * 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.rolling.helper; - -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.status.StatusChecker; -import ch.qos.logback.core.util.Compare; -import ch.qos.logback.core.util.CoreTestConstants; - -/** - * @author Ceki Gulcu - */ -public class CompressTest { - - Context context = new ContextBase(); - - @Before - public void setUp() throws IOException { - // Copy source files - // Delete output files - { - File source = new File(CoreTestConstants.TEST_DIR_PREFIX - + "input/compress1.copy"); - File dest = new File(CoreTestConstants.TEST_DIR_PREFIX - + "input/compress1.txt"); - - copy(source, dest); - File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX - + "compress1.txt.gz"); - target.mkdirs(); - target.delete(); - } - { - File source = new File(CoreTestConstants.TEST_DIR_PREFIX - + "input/compress2.copy"); - File dest = new File(CoreTestConstants.TEST_DIR_PREFIX - + "input/compress2.txt"); - copy(source, dest); - File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX - + "compress2.txt.gz"); - target.mkdirs(); - target.delete(); - } - { - File source = new File(CoreTestConstants.TEST_DIR_PREFIX - + "input/compress3.copy"); - File dest = new File(CoreTestConstants.TEST_DIR_PREFIX - + "input/compress3.txt"); - copy(source, dest); - File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX - + "compress3.txt.zip"); - target.mkdirs(); - target.delete(); - } - } - - @Test - public void test1() throws Exception { - Compressor compressor = new Compressor(CompressionMode.GZ); - compressor.setContext(context); - compressor.compress(CoreTestConstants.TEST_DIR_PREFIX - + "input/compress1.txt", CoreTestConstants.OUTPUT_DIR_PREFIX - + "compress1.txt.gz"); - - StatusChecker checker = new StatusChecker(context); - assertTrue(checker.isErrorFree()); - assertTrue(Compare.gzCompare(CoreTestConstants.OUTPUT_DIR_PREFIX - + "compress1.txt.gz", CoreTestConstants.TEST_DIR_PREFIX - + "witness/compress1.txt.gz")); - } - - @Test - public void test2() throws Exception { - Compressor compressor = new Compressor(CompressionMode.GZ); - compressor.setContext(context); - compressor.compress(CoreTestConstants.TEST_DIR_PREFIX - + "input/compress2.txt", CoreTestConstants.OUTPUT_DIR_PREFIX - + "compress2.txt"); - - StatusChecker checker = new StatusChecker(context); - assertTrue(checker.isErrorFree()); - - assertTrue(Compare.gzCompare(CoreTestConstants.OUTPUT_DIR_PREFIX - + "compress2.txt.gz", CoreTestConstants.TEST_DIR_PREFIX - + "witness/compress2.txt.gz")); - } - - @Test - public void test3() throws Exception { - Compressor compressor = new Compressor(CompressionMode.ZIP); - compressor.setContext(context); - compressor.compress(CoreTestConstants.TEST_DIR_PREFIX - + "input/compress3.txt", CoreTestConstants.OUTPUT_DIR_PREFIX - + "compress3.txt"); - StatusChecker checker = new StatusChecker(context); - assertTrue(checker.isErrorFree()); - - // we don't know how to compare .zip files - // assertTrue(Compare.compare(CoreTestConstants.OUTPUT_DIR_PREFIX - // + "compress3.txt.zip", CoreTestConstants.TEST_DIR_PREFIX - // + "witness/compress3.txt.zip")); - } - - private void copy(File src, File dst) throws IOException { - InputStream in = new FileInputStream(src); - OutputStream out = new FileOutputStream(dst); - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - in.close(); - out.close(); - } - -} +/** + * 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.rolling.helper; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.status.StatusChecker; +import ch.qos.logback.core.util.Compare; +import ch.qos.logback.core.util.CoreTestConstants; + +/** + * @author Ceki Gulcu + */ +public class CompressTest { + + Context context = new ContextBase(); + + @Before + public void setUp() throws IOException { + // Copy source files + // Delete output files + { + File source = new File(CoreTestConstants.TEST_DIR_PREFIX + + "input/compress1.copy"); + File dest = new File(CoreTestConstants.TEST_DIR_PREFIX + + "input/compress1.txt"); + + copy(source, dest); + File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX + + "compress1.txt.gz"); + target.mkdirs(); + target.delete(); + } + { + File source = new File(CoreTestConstants.TEST_DIR_PREFIX + + "input/compress2.copy"); + File dest = new File(CoreTestConstants.TEST_DIR_PREFIX + + "input/compress2.txt"); + copy(source, dest); + File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX + + "compress2.txt.gz"); + target.mkdirs(); + target.delete(); + } + { + File source = new File(CoreTestConstants.TEST_DIR_PREFIX + + "input/compress3.copy"); + File dest = new File(CoreTestConstants.TEST_DIR_PREFIX + + "input/compress3.txt"); + copy(source, dest); + File target = new File(CoreTestConstants.OUTPUT_DIR_PREFIX + + "compress3.txt.zip"); + target.mkdirs(); + target.delete(); + } + } + + @Test + public void test1() throws Exception { + Compressor compressor = new Compressor(CompressionMode.GZ); + compressor.setContext(context); + compressor.compress(CoreTestConstants.TEST_DIR_PREFIX + + "input/compress1.txt", CoreTestConstants.OUTPUT_DIR_PREFIX + + "compress1.txt.gz"); + + StatusChecker checker = new StatusChecker(context); + assertTrue(checker.isErrorFree()); + assertTrue(Compare.gzCompare(CoreTestConstants.OUTPUT_DIR_PREFIX + + "compress1.txt.gz", CoreTestConstants.TEST_DIR_PREFIX + + "witness/compress1.txt.gz")); + } + + @Test + public void test2() throws Exception { + Compressor compressor = new Compressor(CompressionMode.GZ); + compressor.setContext(context); + compressor.compress(CoreTestConstants.TEST_DIR_PREFIX + + "input/compress2.txt", CoreTestConstants.OUTPUT_DIR_PREFIX + + "compress2.txt"); + + StatusChecker checker = new StatusChecker(context); + assertTrue(checker.isErrorFree()); + + assertTrue(Compare.gzCompare(CoreTestConstants.OUTPUT_DIR_PREFIX + + "compress2.txt.gz", CoreTestConstants.TEST_DIR_PREFIX + + "witness/compress2.txt.gz")); + } + + @Test + public void test3() throws Exception { + Compressor compressor = new Compressor(CompressionMode.ZIP); + compressor.setContext(context); + compressor.compress(CoreTestConstants.TEST_DIR_PREFIX + + "input/compress3.txt", CoreTestConstants.OUTPUT_DIR_PREFIX + + "compress3.txt"); + StatusChecker checker = new StatusChecker(context); + assertTrue(checker.isErrorFree()); + + // we don't know how to compare .zip files + // assertTrue(Compare.compare(CoreTestConstants.OUTPUT_DIR_PREFIX + // + "compress3.txt.zip", CoreTestConstants.TEST_DIR_PREFIX + // + "witness/compress3.txt.zip")); + } + + private void copy(File src, File dst) throws IOException { + InputStream in = new FileInputStream(src); + OutputStream out = new FileOutputStream(dst); + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + in.close(); + out.close(); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexTest.java index 8bc908ce427e64d405b4e5dc625960786af03d1b..876be153f579c1f952e417ab7975a87f28205f1c 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexTest.java @@ -1,110 +1,110 @@ -/** - * 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.rolling.helper; - -import static org.junit.Assert.assertTrue; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; - -import org.junit.BeforeClass; -import org.junit.Test; - -import ch.qos.logback.core.CoreConstants; - -public class DatePatternToRegexTest { - static Calendar CAL_2009_08_3_NIGHT = Calendar.getInstance(); - static Calendar CAL_2009_08_3_MORNING = Calendar.getInstance(); - - @BeforeClass - public static void setUpCalendars() { - CAL_2009_08_3_NIGHT.set(2009, 8, 3, 21, 57, 16); - CAL_2009_08_3_NIGHT.set(Calendar.MILLISECOND, 333); - - CAL_2009_08_3_MORNING.set(2009, 8, 3, 10, 24, 37); - CAL_2009_08_3_MORNING.set(Calendar.MILLISECOND, 333); - } - - @Test - public void ISO8601() { - doTest(CoreConstants.ISO8601_PATTERN, CAL_2009_08_3_NIGHT);; - } - - @Test - public void month() { - doTest("yyyy-MMM-dd", CAL_2009_08_3_NIGHT); - doTest("yyyy-MMMM-dd", CAL_2009_08_3_NIGHT); - } - - - @Test - public void dot() { - doTest("yyyy.MMM.dd", CAL_2009_08_3_NIGHT);; - } - - @Test - public void timeZone() { - doTest("yyyy-MMM-dd HH:mm:ss z", CAL_2009_08_3_NIGHT); - doTest("yyyy-MMM-dd HH:mm:ss Z", CAL_2009_08_3_NIGHT); - } - - - @Test - public void dayInWeek() { - doTest("yyyy-MMM-E", CAL_2009_08_3_NIGHT); - doTest("yyyy-MMM-EE", CAL_2009_08_3_NIGHT); - doTest("yyyy-MMM-EEE", CAL_2009_08_3_NIGHT); - } - - @Test - public void amPm() { - doTest("yyyy-MM-dd a", CAL_2009_08_3_NIGHT); - doTest("yyyy-MM-dd a", CAL_2009_08_3_MORNING); - } - - - void doTest(String datePattern, Calendar calendar, boolean slashified) { - SimpleDateFormat sdf = new SimpleDateFormat(datePattern); - DateTokenConverter dtc = makeDTC(datePattern); - verify(sdf, calendar, dtc, slashified); - } - - void doTest(String datePattern, Calendar calendar) { - doTest(datePattern, calendar, false); - } - - - void verify(SimpleDateFormat sdf, Calendar calendar, DateTokenConverter dtc, boolean slashified) { - String expected = sdf.format(calendar.getTime()); - if(slashified) { - expected = expected.replace('\\', '/'); - } - String regex = dtc.toRegex(); - //System.out.println("expected="+expected); - //System.out.println(regex); - assertTrue("[" + expected + "] does not match regex [" + regex + "]", - expected.matches(regex)); - } - - private DateTokenConverter makeDTC(String datePattern) { - DateTokenConverter dtc = new DateTokenConverter(); - List optionList = new ArrayList(); - optionList.add(datePattern); - dtc.setOptionList(optionList); - dtc.start(); - return dtc; - } -} +/** + * 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.rolling.helper; + +import static org.junit.Assert.assertTrue; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; + +import ch.qos.logback.core.CoreConstants; + +public class DatePatternToRegexTest { + static Calendar CAL_2009_08_3_NIGHT = Calendar.getInstance(); + static Calendar CAL_2009_08_3_MORNING = Calendar.getInstance(); + + @BeforeClass + public static void setUpCalendars() { + CAL_2009_08_3_NIGHT.set(2009, 8, 3, 21, 57, 16); + CAL_2009_08_3_NIGHT.set(Calendar.MILLISECOND, 333); + + CAL_2009_08_3_MORNING.set(2009, 8, 3, 10, 24, 37); + CAL_2009_08_3_MORNING.set(Calendar.MILLISECOND, 333); + } + + @Test + public void ISO8601() { + doTest(CoreConstants.ISO8601_PATTERN, CAL_2009_08_3_NIGHT);; + } + + @Test + public void month() { + doTest("yyyy-MMM-dd", CAL_2009_08_3_NIGHT); + doTest("yyyy-MMMM-dd", CAL_2009_08_3_NIGHT); + } + + + @Test + public void dot() { + doTest("yyyy.MMM.dd", CAL_2009_08_3_NIGHT);; + } + + @Test + public void timeZone() { + doTest("yyyy-MMM-dd HH:mm:ss z", CAL_2009_08_3_NIGHT); + doTest("yyyy-MMM-dd HH:mm:ss Z", CAL_2009_08_3_NIGHT); + } + + + @Test + public void dayInWeek() { + doTest("yyyy-MMM-E", CAL_2009_08_3_NIGHT); + doTest("yyyy-MMM-EE", CAL_2009_08_3_NIGHT); + doTest("yyyy-MMM-EEE", CAL_2009_08_3_NIGHT); + } + + @Test + public void amPm() { + doTest("yyyy-MM-dd a", CAL_2009_08_3_NIGHT); + doTest("yyyy-MM-dd a", CAL_2009_08_3_MORNING); + } + + + void doTest(String datePattern, Calendar calendar, boolean slashified) { + SimpleDateFormat sdf = new SimpleDateFormat(datePattern); + DateTokenConverter dtc = makeDTC(datePattern); + verify(sdf, calendar, dtc, slashified); + } + + void doTest(String datePattern, Calendar calendar) { + doTest(datePattern, calendar, false); + } + + + void verify(SimpleDateFormat sdf, Calendar calendar, DateTokenConverter dtc, boolean slashified) { + String expected = sdf.format(calendar.getTime()); + if(slashified) { + expected = expected.replace('\\', '/'); + } + String regex = dtc.toRegex(); + //System.out.println("expected="+expected); + //System.out.println(regex); + assertTrue("[" + expected + "] does not match regex [" + regex + "]", + expected.matches(regex)); + } + + private DateTokenConverter makeDTC(String datePattern) { + DateTokenConverter dtc = new DateTokenConverter(); + List optionList = new ArrayList(); + optionList.add(datePattern); + dtc.setOptionList(optionList); + dtc.start(); + return dtc; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java index 24f7d4e8ee6a0992be3749b13721c7b99eeba50f..196d8b4198eb8e378d542f7ee351979cd557fa57 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java @@ -1,137 +1,137 @@ -/** - * 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.rolling.helper; - -import static org.junit.Assert.assertEquals; - -import java.util.Calendar; - -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; - -/** - * @author Ceki - * - */ -public class FileNamePatternTest { - - Context context = new ContextBase(); - - @Test - public void testSmoke() { - FileNamePattern pp = new FileNamePattern("t", context); - assertEquals("t", pp.convertInt(3)); - - pp = new FileNamePattern("foo", context); - assertEquals("foo", pp.convertInt(3)); - - pp = new FileNamePattern("%i foo", context); - - assertEquals("3 foo", pp.convertInt(3)); - - pp = new FileNamePattern("foo%i.xixo", context); - assertEquals("foo3.xixo", pp.convertInt(3)); - - pp = new FileNamePattern("foo%i.log", context); - assertEquals("foo3.log", pp.convertInt(3)); - - 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)); - - //pp = new FileNamePattern("\\%foo", context); - //assertEquals("%foo", pp.convertInt(3)); - } - - @Test - // test ways for dealing with flowing i converter, as in "foo%ix" - public void flowingI() { - { - 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)); - } - } - - @Test - public void date() { - Calendar cal = Calendar.getInstance(); - cal.set(2003, 4, 20, 17, 55); - - FileNamePattern pp = new FileNamePattern("foo%d{yyyy.MM.dd}", context); - - assertEquals("foo2003.05.20", pp.convert(cal.getTime())); - - pp = new FileNamePattern("foo%d{yyyy.MM.dd HH:mm}", context); - assertEquals("foo2003.05.20 17:55", pp.convert(cal.getTime())); - - pp = new FileNamePattern("%d{yyyy.MM.dd HH:mm} foo", context); - assertEquals("2003.05.20 17:55 foo", pp.convert(cal.getTime())); - - } - - @Test - public void withBackslash() { - FileNamePattern pp = new FileNamePattern("c:\\foo\\bar.%i", context); - assertEquals("c:/foo/bar.3", pp.convertInt(3)); - } - - @Test - public void objectListConverter() { - Calendar cal = Calendar.getInstance(); - cal.set(2003, 4, 20, 17, 55); - FileNamePattern fnp = new FileNamePattern("foo-%d{yyyy.MM.dd}-%i.txt", - context); - assertEquals("foo-2003.05.20-79.txt", fnp.convertMultipleArguments(cal - .getTime(), 79)); - } - - @Test - public void asRegexByDate() { - - Calendar cal = Calendar.getInstance(); - cal.set(2003, 4, 20, 17, 55); - - { - FileNamePattern fnp = new FileNamePattern("foo-%d{yyyy.MM.dd}-%i.txt", - context); - String regex = fnp.toRegex(cal.getTime()); - assertEquals("foo-2003.05.20-(\\d{1,2}).txt", regex); - } - { - FileNamePattern fnp = new FileNamePattern("\\toto\\foo-%d{yyyy\\MM\\dd}-%i.txt", - context); - String regex = fnp.toRegex(cal.getTime()); - assertEquals("/toto/foo-2003/05/20-(\\d{1,2}).txt", regex); - } - } - - @Test - public void asRegex() { - Calendar cal = Calendar.getInstance(); - cal.set(2003, 4, 20, 17, 55); - FileNamePattern fnp = new FileNamePattern("foo-%d{yyyy.MM.dd}-%i.txt", - context); - String regex = fnp.toRegex(); - assertEquals("foo-\\d{4}\\.\\d{2}\\.\\d{2}-\\d{1,2}.txt", regex); - } - -} +/** + * 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.rolling.helper; + +import static org.junit.Assert.assertEquals; + +import java.util.Calendar; + +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; + +/** + * @author Ceki + * + */ +public class FileNamePatternTest { + + Context context = new ContextBase(); + + @Test + public void testSmoke() { + FileNamePattern pp = new FileNamePattern("t", context); + assertEquals("t", pp.convertInt(3)); + + pp = new FileNamePattern("foo", context); + assertEquals("foo", pp.convertInt(3)); + + pp = new FileNamePattern("%i foo", context); + + assertEquals("3 foo", pp.convertInt(3)); + + pp = new FileNamePattern("foo%i.xixo", context); + assertEquals("foo3.xixo", pp.convertInt(3)); + + pp = new FileNamePattern("foo%i.log", context); + assertEquals("foo3.log", pp.convertInt(3)); + + 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)); + + //pp = new FileNamePattern("\\%foo", context); + //assertEquals("%foo", pp.convertInt(3)); + } + + @Test + // test ways for dealing with flowing i converter, as in "foo%ix" + public void flowingI() { + { + 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)); + } + } + + @Test + public void date() { + Calendar cal = Calendar.getInstance(); + cal.set(2003, 4, 20, 17, 55); + + FileNamePattern pp = new FileNamePattern("foo%d{yyyy.MM.dd}", context); + + assertEquals("foo2003.05.20", pp.convert(cal.getTime())); + + pp = new FileNamePattern("foo%d{yyyy.MM.dd HH:mm}", context); + assertEquals("foo2003.05.20 17:55", pp.convert(cal.getTime())); + + pp = new FileNamePattern("%d{yyyy.MM.dd HH:mm} foo", context); + assertEquals("2003.05.20 17:55 foo", pp.convert(cal.getTime())); + + } + + @Test + public void withBackslash() { + FileNamePattern pp = new FileNamePattern("c:\\foo\\bar.%i", context); + assertEquals("c:/foo/bar.3", pp.convertInt(3)); + } + + @Test + public void objectListConverter() { + Calendar cal = Calendar.getInstance(); + cal.set(2003, 4, 20, 17, 55); + FileNamePattern fnp = new FileNamePattern("foo-%d{yyyy.MM.dd}-%i.txt", + context); + assertEquals("foo-2003.05.20-79.txt", fnp.convertMultipleArguments(cal + .getTime(), 79)); + } + + @Test + public void asRegexByDate() { + + Calendar cal = Calendar.getInstance(); + cal.set(2003, 4, 20, 17, 55); + + { + FileNamePattern fnp = new FileNamePattern("foo-%d{yyyy.MM.dd}-%i.txt", + context); + String regex = fnp.toRegex(cal.getTime()); + assertEquals("foo-2003.05.20-(\\d{1,2}).txt", regex); + } + { + FileNamePattern fnp = new FileNamePattern("\\toto\\foo-%d{yyyy\\MM\\dd}-%i.txt", + context); + String regex = fnp.toRegex(cal.getTime()); + assertEquals("/toto/foo-2003/05/20-(\\d{1,2}).txt", regex); + } + } + + @Test + public void asRegex() { + Calendar cal = Calendar.getInstance(); + cal.set(2003, 4, 20, 17, 55); + FileNamePattern fnp = new FileNamePattern("foo-%d{yyyy.MM.dd}-%i.txt", + context); + String regex = fnp.toRegex(); + assertEquals("foo-\\d{4}\\.\\d{2}\\.\\d{2}-\\d{1,2}.txt", regex); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/PackageTest.java index a5f07602658d259e7651bb238a689d1ad9319408..cfefd3b7395333c9b011a78aa3e6b517dc232a2f 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/PackageTest.java @@ -1,26 +1,26 @@ -/** - * 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.rolling.helper; - -import junit.framework.TestCase; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses( { CompressTest.class, FileNamePatternTest.class, - RollingCalendarTest.class, DatePatternToRegexTest.class }) -public class PackageTest extends TestCase { - -} +/** + * 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.rolling.helper; + +import junit.framework.TestCase; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses( { CompressTest.class, FileNamePatternTest.class, + RollingCalendarTest.class, DatePatternToRegexTest.class }) +public class PackageTest extends TestCase { + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/RollingCalendarTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/RollingCalendarTest.java index 8170ee22c3bac9ede47c356ce586f65cd352f7fd..6023cc1200562a9d7b57b9e08bc12b460520725a 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/RollingCalendarTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/RollingCalendarTest.java @@ -1,95 +1,95 @@ -/** - * 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.rolling.helper; - -import java.util.Date; - -import junit.framework.TestCase; - -public class RollingCalendarTest extends TestCase { - - public RollingCalendarTest(String arg0) { - super(arg0); - } - - protected void setUp() throws Exception { - super.setUp(); - } - - protected void tearDown() throws Exception { - super.tearDown(); - } - - public void testPeriodicity() { - { - RollingCalendar rc = new RollingCalendar(); - assertEquals(PeriodicityType.TOP_OF_SECOND, rc - .computePeriodicity("yyyy-MM-dd_HH_mm_ss")); - } - - { - RollingCalendar rc = new RollingCalendar(); - assertEquals(PeriodicityType.TOP_OF_MINUTE, rc - .computePeriodicity("yyyy-MM-dd_HH_mm")); - } - - { - RollingCalendar rc = new RollingCalendar(); - assertEquals(PeriodicityType.TOP_OF_HOUR, rc - .computePeriodicity("yyyy-MM-dd_HH")); - } - - { - RollingCalendar rc = new RollingCalendar(); - assertEquals(PeriodicityType.TOP_OF_DAY, rc - .computePeriodicity("yyyy-MM-dd")); - } - - { - RollingCalendar rc = new RollingCalendar(); - assertEquals(PeriodicityType.TOP_OF_MONTH, rc - .computePeriodicity("yyyy-MM")); - } - } - - public void testVaryingNumberOfHourlyPeriods() { - RollingCalendar rc = new RollingCalendar(); - rc.init("yyyy-MM-dd_HH"); - long MILLIS_IN_HOUR = 3600*1000; - - for (int p = 100; p > -100; p--) { - long now = 1223325293589L; // Mon Oct 06 22:34:53 CEST 2008 - Date result = rc.getRelativeDate(new Date(now), p); - long expected = now - (now % (MILLIS_IN_HOUR)) + p * MILLIS_IN_HOUR; - assertEquals(expected, result.getTime()); - } - } - - public void testVaryingNumberOfDailyPeriods() { - RollingCalendar rc = new RollingCalendar(); - rc.init("yyyy-MM-dd"); - final long MILLIS_IN_DAY = 24*3600*1000; - - for (int p = 20; p > -100; p--) { - long now = 1223325293589L; // Mon Oct 06 22:34:53 CEST 2008 - Date nowDate = new Date(now); - Date result = rc.getRelativeDate(nowDate, p); - long offset = rc.getTimeZone().getRawOffset()+rc.getTimeZone().getDSTSavings(); - - long origin = now - (now % (MILLIS_IN_DAY)) - offset; - long expected = origin + p * MILLIS_IN_DAY; - assertEquals("p="+p, expected, result.getTime()); - } - } -} +/** + * 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.rolling.helper; + +import java.util.Date; + +import junit.framework.TestCase; + +public class RollingCalendarTest extends TestCase { + + public RollingCalendarTest(String arg0) { + super(arg0); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testPeriodicity() { + { + RollingCalendar rc = new RollingCalendar(); + assertEquals(PeriodicityType.TOP_OF_SECOND, rc + .computePeriodicity("yyyy-MM-dd_HH_mm_ss")); + } + + { + RollingCalendar rc = new RollingCalendar(); + assertEquals(PeriodicityType.TOP_OF_MINUTE, rc + .computePeriodicity("yyyy-MM-dd_HH_mm")); + } + + { + RollingCalendar rc = new RollingCalendar(); + assertEquals(PeriodicityType.TOP_OF_HOUR, rc + .computePeriodicity("yyyy-MM-dd_HH")); + } + + { + RollingCalendar rc = new RollingCalendar(); + assertEquals(PeriodicityType.TOP_OF_DAY, rc + .computePeriodicity("yyyy-MM-dd")); + } + + { + RollingCalendar rc = new RollingCalendar(); + assertEquals(PeriodicityType.TOP_OF_MONTH, rc + .computePeriodicity("yyyy-MM")); + } + } + + public void testVaryingNumberOfHourlyPeriods() { + RollingCalendar rc = new RollingCalendar(); + rc.init("yyyy-MM-dd_HH"); + long MILLIS_IN_HOUR = 3600*1000; + + for (int p = 100; p > -100; p--) { + long now = 1223325293589L; // Mon Oct 06 22:34:53 CEST 2008 + Date result = rc.getRelativeDate(new Date(now), p); + long expected = now - (now % (MILLIS_IN_HOUR)) + p * MILLIS_IN_HOUR; + assertEquals(expected, result.getTime()); + } + } + + public void testVaryingNumberOfDailyPeriods() { + RollingCalendar rc = new RollingCalendar(); + rc.init("yyyy-MM-dd"); + final long MILLIS_IN_DAY = 24*3600*1000; + + for (int p = 20; p > -100; p--) { + long now = 1223325293589L; // Mon Oct 06 22:34:53 CEST 2008 + Date nowDate = new Date(now); + Date result = rc.getRelativeDate(nowDate, p); + long offset = rc.getTimeZone().getRawOffset()+rc.getTimeZone().getDSTSavings(); + + long origin = now - (now % (MILLIS_IN_DAY)) - offset; + long expected = origin + p * MILLIS_IN_DAY; + assertEquals("p="+p, expected, result.getTime()); + } + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java b/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java index d64fa4fd95f0f9747b13acf54377d9656e883610..85af51afa57069c9c4aa54d8a127e65995d573ca 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java @@ -1,74 +1,74 @@ -/** - * 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.sift; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.read.ListAppender; - -public class AppenderTrackerTest { - - - Context context = new ContextBase(); - AppenderTracker appenderTracker = new AppenderTrackerImpl(); - ListAppender la = new ListAppender(); - - @Before - public void setUp() { - la.setContext(context); - la.start(); - } - - - @Test - public void empty0() { - long now = 3000; - appenderTracker.stopStaleAppenders(now); - assertEquals(0, appenderTracker.keyList().size()); - } - - @Test - public void empty1() { - long now = 3000; - assertNull(appenderTracker.get("a", now++)); - now += AppenderTrackerImpl.THRESHOLD+1000; - appenderTracker.stopStaleAppenders(now); - assertNull(appenderTracker.get("a", now++)); - } - - @Test - public void smoke() { - assertTrue(la.isStarted()); - long now = 3000; - appenderTracker.put("a", la, now); - assertEquals(la, appenderTracker.get("a", now++)); - now += AppenderTrackerImpl.THRESHOLD+1000; - appenderTracker.stopStaleAppenders(now); - assertFalse(la.isStarted()); - assertNull(appenderTracker.get("a", now++)); - } - - @Test - public void scenarioBased() { - - } -} +/** + * 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.sift; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.read.ListAppender; + +public class AppenderTrackerTest { + + + Context context = new ContextBase(); + AppenderTracker appenderTracker = new AppenderTrackerImpl(); + ListAppender la = new ListAppender(); + + @Before + public void setUp() { + la.setContext(context); + la.start(); + } + + + @Test + public void empty0() { + long now = 3000; + appenderTracker.stopStaleAppenders(now); + assertEquals(0, appenderTracker.keyList().size()); + } + + @Test + public void empty1() { + long now = 3000; + assertNull(appenderTracker.get("a", now++)); + now += AppenderTrackerImpl.THRESHOLD+1000; + appenderTracker.stopStaleAppenders(now); + assertNull(appenderTracker.get("a", now++)); + } + + @Test + public void smoke() { + assertTrue(la.isStarted()); + long now = 3000; + appenderTracker.put("a", la, now); + assertEquals(la, appenderTracker.get("a", now++)); + now += AppenderTrackerImpl.THRESHOLD+1000; + appenderTracker.stopStaleAppenders(now); + assertFalse(la.isStarted()); + assertNull(appenderTracker.get("a", now++)); + } + + @Test + public void scenarioBased() { + + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/sift/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/sift/PackageTest.java index d6c299b1fc37a390069a4d09a1fafad02d795008..28af86092fb9e62e80afb5f13fd115dd1cfa9a1a 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/sift/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/sift/PackageTest.java @@ -1,23 +1,23 @@ -/** - * 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.sift; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({ScenarioBasedAppenderTrackerTest.class}) -public class PackageTest { +/** + * 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.sift; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ScenarioBasedAppenderTrackerTest.class}) +public class PackageTest { } \ No newline at end of file diff --git a/logback-core/src/test/java/ch/qos/logback/core/sift/ScenarioBasedAppenderTrackerTest.java b/logback-core/src/test/java/ch/qos/logback/core/sift/ScenarioBasedAppenderTrackerTest.java index 2858718f79373e48ecf099181fe58f9cb93b2297..6f21a1e61e0c397274c1f1b7d56ea09f4b7c85b0 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/sift/ScenarioBasedAppenderTrackerTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/sift/ScenarioBasedAppenderTrackerTest.java @@ -1,57 +1,57 @@ -/** - * 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.sift; - -import static org.junit.Assert.assertEquals; - -import org.junit.Ignore; -import org.junit.Test; - -public class ScenarioBasedAppenderTrackerTest { - - Simulator simulator; - - void verify() { - AppenderTracker at = simulator.appenderTracker; - AppenderTracker t_at = simulator.t_appenderTracker; - //List resultKeys = at.keyList(); - //List witnessKeys = t_at.keyList(); - assertEquals(t_at.keyList(), at.keyList()); - } - - @Test - public void shortTest() { - simulator = new Simulator(20, AppenderTracker.THRESHOLD / 2); - simulator.buildScenario(200); - simulator.simulate(); - verify(); - } - - @Test - public void mediumTest() { - simulator = new Simulator(100, AppenderTracker.THRESHOLD / 2); - simulator.buildScenario(20000); - simulator.simulate(); - verify(); - } - - @Test - @Ignore - public void longetTest() { - simulator = new Simulator(100, AppenderTracker.THRESHOLD / 200); - simulator.buildScenario(2000000); - simulator.simulate(); - verify(); - } -} +/** + * 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.sift; + +import static org.junit.Assert.assertEquals; + +import org.junit.Ignore; +import org.junit.Test; + +public class ScenarioBasedAppenderTrackerTest { + + Simulator simulator; + + void verify() { + AppenderTracker at = simulator.appenderTracker; + AppenderTracker t_at = simulator.t_appenderTracker; + //List resultKeys = at.keyList(); + //List witnessKeys = t_at.keyList(); + assertEquals(t_at.keyList(), at.keyList()); + } + + @Test + public void shortTest() { + simulator = new Simulator(20, AppenderTracker.THRESHOLD / 2); + simulator.buildScenario(200); + simulator.simulate(); + verify(); + } + + @Test + public void mediumTest() { + simulator = new Simulator(100, AppenderTracker.THRESHOLD / 2); + simulator.buildScenario(20000); + simulator.simulate(); + verify(); + } + + @Test + @Ignore + public void longetTest() { + simulator = new Simulator(100, AppenderTracker.THRESHOLD / 200); + simulator.buildScenario(2000000); + simulator.simulate(); + verify(); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/sift/Simulator.java b/logback-core/src/test/java/ch/qos/logback/core/sift/Simulator.java index 1d1767e56042e5390cbf0b741b3a25f7ecc363db..16cf0f057950a5eccdbd713f26af8419c176ac9b 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/sift/Simulator.java +++ b/logback-core/src/test/java/ch/qos/logback/core/sift/Simulator.java @@ -1,96 +1,96 @@ -/** - * 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.sift; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.appender.NOPAppender; -import ch.qos.logback.core.sift.tracker.AppenderTrackerTImpl; -import ch.qos.logback.core.sift.tracker.SimulationEvent; - -/** - * Simulate use of AppenderTracker by HoardAppender. - * - * @author ceki - * - */ -public class Simulator { - - AppenderTrackerImpl appenderTracker = new AppenderTrackerImpl(); - AppenderTrackerTImpl t_appenderTracker = new AppenderTrackerTImpl(); - - List keySpace = new ArrayList(); - List scenario = new ArrayList(); - Random randomKeyGen = new Random(100); - - Random random = new Random(11234); - - final int maxTimestampInc; - long timestamp = 30000; - - Simulator(int keySpaceLen, int maxTimestampInc) { - this.maxTimestampInc = maxTimestampInc; - Map checkMap = new HashMap(); - for (int i = 0; i < keySpaceLen; i++) { - String k = getRandomKeyStr(); - if (checkMap.containsKey(k)) { - System.out.println("random key collision occured"); - k += "" + i; - } - keySpace.add(k); - checkMap.put(k, k); - } - - } - - private String getRandomKeyStr() { - int ri = randomKeyGen.nextInt(); - String s = String.format("%X", ri); - return s; - } - - void buildScenario(int simLen) { - int keySpaceLen = keySpace.size(); - for (int i = 0; i < simLen; i++) { - int index = random.nextInt(keySpaceLen); - timestamp += random.nextInt(maxTimestampInc); - String key = keySpace.get(index); - scenario.add(new SimulationEvent(key, timestamp)); - } - } - - public void simulate() { - for (SimulationEvent simeEvent : scenario) { - play(simeEvent, appenderTracker); - play(simeEvent, t_appenderTracker); - } - } - - void play(SimulationEvent simulationEvent, - AppenderTracker appenderTracker) { - String mdcValue = simulationEvent.key; - long timestamp = simulationEvent.timestamp; - Appender appender = appenderTracker.get(mdcValue, timestamp); - if (appender == null) { - appender = new NOPAppender(); - appenderTracker.put(mdcValue, appender, timestamp); - } - appenderTracker.stopStaleAppenders(timestamp); - } -} +/** + * 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.sift; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.appender.NOPAppender; +import ch.qos.logback.core.sift.tracker.AppenderTrackerTImpl; +import ch.qos.logback.core.sift.tracker.SimulationEvent; + +/** + * Simulate use of AppenderTracker by HoardAppender. + * + * @author ceki + * + */ +public class Simulator { + + AppenderTrackerImpl appenderTracker = new AppenderTrackerImpl(); + AppenderTrackerTImpl t_appenderTracker = new AppenderTrackerTImpl(); + + List keySpace = new ArrayList(); + List scenario = new ArrayList(); + Random randomKeyGen = new Random(100); + + Random random = new Random(11234); + + final int maxTimestampInc; + long timestamp = 30000; + + Simulator(int keySpaceLen, int maxTimestampInc) { + this.maxTimestampInc = maxTimestampInc; + Map checkMap = new HashMap(); + for (int i = 0; i < keySpaceLen; i++) { + String k = getRandomKeyStr(); + if (checkMap.containsKey(k)) { + System.out.println("random key collision occured"); + k += "" + i; + } + keySpace.add(k); + checkMap.put(k, k); + } + + } + + private String getRandomKeyStr() { + int ri = randomKeyGen.nextInt(); + String s = String.format("%X", ri); + return s; + } + + void buildScenario(int simLen) { + int keySpaceLen = keySpace.size(); + for (int i = 0; i < simLen; i++) { + int index = random.nextInt(keySpaceLen); + timestamp += random.nextInt(maxTimestampInc); + String key = keySpace.get(index); + scenario.add(new SimulationEvent(key, timestamp)); + } + } + + public void simulate() { + for (SimulationEvent simeEvent : scenario) { + play(simeEvent, appenderTracker); + play(simeEvent, t_appenderTracker); + } + } + + void play(SimulationEvent simulationEvent, + AppenderTracker appenderTracker) { + String mdcValue = simulationEvent.key; + long timestamp = simulationEvent.timestamp; + Appender appender = appenderTracker.get(mdcValue, timestamp); + if (appender == null) { + appender = new NOPAppender(); + appenderTracker.put(mdcValue, appender, timestamp); + } + appenderTracker.stopStaleAppenders(timestamp); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/AppenderTrackerTImpl.java b/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/AppenderTrackerTImpl.java index 92815af33e394e3afdd2b634d5fab3610f642fd5..1a3363716cdffd365c9b94a338dbef7f15533ae9 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/AppenderTrackerTImpl.java +++ b/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/AppenderTrackerTImpl.java @@ -1,102 +1,102 @@ -/** - * 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.sift.tracker; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.sift.AppenderTracker; - -/** - * This is an alternative (slower) implementation of AppenderTracker for testing - * purposes. - * - * @author Ceki Gulcu - */ -public class AppenderTrackerTImpl implements AppenderTracker { - - List entryList = new LinkedList(); - long lastCheck = 0; - - public AppenderTrackerTImpl() { - } - - @SuppressWarnings("unchecked") - synchronized public void put(String k, Appender appender, - long timestamp) { - TEntry te = getEntry(k); - if (te != null) { - te.timestamp = timestamp; - } else { - te = new TEntry(k, appender, timestamp); - entryList.add(te); - } - Collections.sort(entryList); - } - - @SuppressWarnings("unchecked") - synchronized public Appender get(String k, long timestamp) { - TEntry te = getEntry(k); - if (te == null) { - return null; - } else { - te.timestamp = timestamp; - Collections.sort(entryList); - return te.appender; - } - } - - synchronized public void stopStaleAppenders(long timestamp) { - if (lastCheck + MILLIS_IN_ONE_SECOND > timestamp) { - return; - } - lastCheck = timestamp; - while (entryList.size() != 0 && isEntryStale(entryList.get(0), timestamp)) { - entryList.remove(0); - } - } - - final private boolean isEntryStale(TEntry entry, long now) { - return ((entry.timestamp + THRESHOLD) < now); - } - - synchronized public List keyList() { - List keyList = new ArrayList(); - for (TEntry e : entryList) { - keyList.add(e.key); - } - return keyList; - } - - synchronized public List> valueList() { - List> appenderList = new ArrayList>(); - for (TEntry e : entryList) { - appenderList.add(e.appender); - } - return appenderList; - } - - private TEntry getEntry(String k) { - for (int i = 0; i < entryList.size(); i++) { - TEntry te = entryList.get(i); - if (te.key.equals(k)) { - return te; - } - } - return null; - } -} +/** + * 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.sift.tracker; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.sift.AppenderTracker; + +/** + * This is an alternative (slower) implementation of AppenderTracker for testing + * purposes. + * + * @author Ceki Gulcu + */ +public class AppenderTrackerTImpl implements AppenderTracker { + + List entryList = new LinkedList(); + long lastCheck = 0; + + public AppenderTrackerTImpl() { + } + + @SuppressWarnings("unchecked") + synchronized public void put(String k, Appender appender, + long timestamp) { + TEntry te = getEntry(k); + if (te != null) { + te.timestamp = timestamp; + } else { + te = new TEntry(k, appender, timestamp); + entryList.add(te); + } + Collections.sort(entryList); + } + + @SuppressWarnings("unchecked") + synchronized public Appender get(String k, long timestamp) { + TEntry te = getEntry(k); + if (te == null) { + return null; + } else { + te.timestamp = timestamp; + Collections.sort(entryList); + return te.appender; + } + } + + synchronized public void stopStaleAppenders(long timestamp) { + if (lastCheck + MILLIS_IN_ONE_SECOND > timestamp) { + return; + } + lastCheck = timestamp; + while (entryList.size() != 0 && isEntryStale(entryList.get(0), timestamp)) { + entryList.remove(0); + } + } + + final private boolean isEntryStale(TEntry entry, long now) { + return ((entry.timestamp + THRESHOLD) < now); + } + + synchronized public List keyList() { + List keyList = new ArrayList(); + for (TEntry e : entryList) { + keyList.add(e.key); + } + return keyList; + } + + synchronized public List> valueList() { + List> appenderList = new ArrayList>(); + for (TEntry e : entryList) { + appenderList.add(e.appender); + } + return appenderList; + } + + private TEntry getEntry(String k) { + for (int i = 0; i < entryList.size(); i++) { + TEntry te = entryList.get(i); + if (te.key.equals(k)) { + return te; + } + } + return null; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/SimulationEvent.java b/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/SimulationEvent.java index 8371f2c7a3e03e43a54f8f3b91c15b2ef580033e..b04e52f8eca785e590c5135ce8d9e8ce7ea74b79 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/SimulationEvent.java +++ b/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/SimulationEvent.java @@ -1,30 +1,30 @@ -/** - * 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.sift.tracker; - - -public class SimulationEvent { - - public String key; - public long timestamp; - - public SimulationEvent(String key, long timestamp) { - this.key = key; - this.timestamp = timestamp; - } - - public String toString() { - return "Event: k=" + key +", timestamp=" + timestamp; - } -} +/** + * 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.sift.tracker; + + +public class SimulationEvent { + + public String key; + public long timestamp; + + public SimulationEvent(String key, long timestamp) { + this.key = key; + this.timestamp = timestamp; + } + + public String toString() { + return "Event: k=" + key +", timestamp=" + timestamp; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/TEntry.java b/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/TEntry.java index 22c80b04656cb0207c58717eb56c82eee113fc8c..600f41c3101996764cb9edd48d861029130af6e7 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/TEntry.java +++ b/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/TEntry.java @@ -1,49 +1,49 @@ -/** - * 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.sift.tracker; - -import ch.qos.logback.core.Appender; - -public class TEntry implements Comparable { - - String key; - long timestamp; - Appender appender; - - TEntry(String key, Appender appender, long timestamp) { - this.key = key; - this.appender = appender; - this.timestamp = timestamp; - } - - public int compareTo(Object o) { - if(!(o instanceof TEntry)) { - throw new IllegalArgumentException("arguments must be of type "+TEntry.class); - } - - TEntry other = (TEntry) o; - if(timestamp > other.timestamp) { - return 1; - } - if(timestamp == other.timestamp) { - return 0; - } - return -1; - } - - @Override - public String toString() { - return "("+key+","+timestamp+")"; - } -} +/** + * 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.sift.tracker; + +import ch.qos.logback.core.Appender; + +public class TEntry implements Comparable { + + String key; + long timestamp; + Appender appender; + + TEntry(String key, Appender appender, long timestamp) { + this.key = key; + this.appender = appender; + this.timestamp = timestamp; + } + + public int compareTo(Object o) { + if(!(o instanceof TEntry)) { + throw new IllegalArgumentException("arguments must be of type "+TEntry.class); + } + + TEntry other = (TEntry) o; + if(timestamp > other.timestamp) { + return 1; + } + if(timestamp == other.timestamp) { + return 0; + } + return -1; + } + + @Override + public String toString() { + return "("+key+","+timestamp+")"; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/spi/AppenderAttachableImplLockTest.java b/logback-core/src/test/java/ch/qos/logback/core/spi/AppenderAttachableImplLockTest.java index e5efdee4c36f791bfe5c78fdc1342157503240ae..89e4a94f21d8492f62730ed0dca8fcf45c400a22 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/spi/AppenderAttachableImplLockTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/spi/AppenderAttachableImplLockTest.java @@ -1,107 +1,107 @@ -/** - * 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.spi; - -import static org.easymock.EasyMock.createStrictMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.makeThreadSafe; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; - -import org.junit.Test; - -import ch.qos.logback.core.Appender; - -/** - * This test shows the general problem I described in LBCORE-67. - * - * In the two test cases below, an appender that throws an OutOfMemoryError - * while getName is called - but this is just an example to show the general - * problem. - * - * The tests below fail without fixing LBCORE-67 and pass when Joern Huxhorn's - * patch is applied. - * - * Additionally, the following, probably more realistic, situations could - * happen: - * - * -addAppender: appenderList.add() could throw OutOfMemoryError. This could - * only be shown by using an appenderList mock but appenderList does not (and - * should not) have a setter. This would leave the write lock locked. - * - * -iteratorForAppenders: new ArrayList() could throw an OutOfMemoryError, - * leaving the read lock locked. - * - * I can't imagine a bad situation in isAttached, detachAppender(Appender) or - * detachAppender(String) but I'd change the code anyway for consistency. I'm - * also pretty sure that something stupid can happen at any time so it's best to - * just stick to conventions. - * - * @author Joern Huxhorn - */ -public class AppenderAttachableImplLockTest { - private AppenderAttachableImpl aai = new AppenderAttachableImpl(); - - @SuppressWarnings("unchecked") - @Test(timeout = 1000) - public void getAppenderBoom() { - - Appender mockAppender1 = createStrictMock(Appender.class); - expect(mockAppender1.getName()).andThrow(new OutOfMemoryError("oops")); - replay(mockAppender1); - - aai.addAppender(mockAppender1); - try { - // appender.getName called as a result of next statement - aai.getAppender("foo"); - } catch (OutOfMemoryError e) { - // this leaves the read lock locked. - } - - Appender mockAppender2=createStrictMock(Appender.class); - // the next call will lock - aai.addAppender(mockAppender2); - verify(mockAppender1); - } - - @SuppressWarnings("unchecked") - @Test(timeout = 1000) - public void detachAppenderBoom() throws InterruptedException { - Appender mockAppender = createStrictMock(Appender.class); - makeThreadSafe(mockAppender, true); - expect(mockAppender.getName()).andThrow(new OutOfMemoryError("oops")); - mockAppender.doAppend(17); - replay(mockAppender); - - aai.addAppender(mockAppender); - Thread t = new Thread(new Runnable() { - - public void run() { - try { - // appender.getName called as a result of next statement - aai.detachAppender("foo"); - } catch (OutOfMemoryError e) { - // this leaves the write lock locked. - } - } - }); - t.start(); - t.join(); - - // the next call will lock - aai.appendLoopOnAppenders(17); - verify(mockAppender); - } - -} +/** + * 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.spi; + +import static org.easymock.EasyMock.createStrictMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.makeThreadSafe; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import org.junit.Test; + +import ch.qos.logback.core.Appender; + +/** + * This test shows the general problem I described in LBCORE-67. + * + * In the two test cases below, an appender that throws an OutOfMemoryError + * while getName is called - but this is just an example to show the general + * problem. + * + * The tests below fail without fixing LBCORE-67 and pass when Joern Huxhorn's + * patch is applied. + * + * Additionally, the following, probably more realistic, situations could + * happen: + * + * -addAppender: appenderList.add() could throw OutOfMemoryError. This could + * only be shown by using an appenderList mock but appenderList does not (and + * should not) have a setter. This would leave the write lock locked. + * + * -iteratorForAppenders: new ArrayList() could throw an OutOfMemoryError, + * leaving the read lock locked. + * + * I can't imagine a bad situation in isAttached, detachAppender(Appender) or + * detachAppender(String) but I'd change the code anyway for consistency. I'm + * also pretty sure that something stupid can happen at any time so it's best to + * just stick to conventions. + * + * @author Joern Huxhorn + */ +public class AppenderAttachableImplLockTest { + private AppenderAttachableImpl aai = new AppenderAttachableImpl(); + + @SuppressWarnings("unchecked") + @Test(timeout = 1000) + public void getAppenderBoom() { + + Appender mockAppender1 = createStrictMock(Appender.class); + expect(mockAppender1.getName()).andThrow(new OutOfMemoryError("oops")); + replay(mockAppender1); + + aai.addAppender(mockAppender1); + try { + // appender.getName called as a result of next statement + aai.getAppender("foo"); + } catch (OutOfMemoryError e) { + // this leaves the read lock locked. + } + + Appender mockAppender2=createStrictMock(Appender.class); + // the next call will lock + aai.addAppender(mockAppender2); + verify(mockAppender1); + } + + @SuppressWarnings("unchecked") + @Test(timeout = 1000) + public void detachAppenderBoom() throws InterruptedException { + Appender mockAppender = createStrictMock(Appender.class); + makeThreadSafe(mockAppender, true); + expect(mockAppender.getName()).andThrow(new OutOfMemoryError("oops")); + mockAppender.doAppend(17); + replay(mockAppender); + + aai.addAppender(mockAppender); + Thread t = new Thread(new Runnable() { + + public void run() { + try { + // appender.getName called as a result of next statement + aai.detachAppender("foo"); + } catch (OutOfMemoryError e) { + // this leaves the write lock locked. + } + } + }); + t.start(); + t.join(); + + // the next call will lock + aai.appendLoopOnAppenders(17); + verify(mockAppender); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/spi/AppenderAttachableImplTest.java b/logback-core/src/test/java/ch/qos/logback/core/spi/AppenderAttachableImplTest.java index 61c513cb3332ac15e3e443b74160fc999e35e562..dd822ed988cf665d109717722f095a839a9dbc64 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/spi/AppenderAttachableImplTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/spi/AppenderAttachableImplTest.java @@ -1,181 +1,181 @@ -/** - * 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.spi; - - -import static org.junit.Assert.*; -import ch.qos.logback.core.appender.NOPAppender; -import ch.qos.logback.core.Appender; -import ch.qos.logback.core.layout.NopLayout; - -import java.util.Iterator; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * This test case verifies all the methods of AppenderAttableImpl work properly. - * - * @author Ralph Goers - */ -public class AppenderAttachableImplTest { - - - private AppenderAttachableImpl aai; - - @Before - public void setUp() throws Exception { - aai = new AppenderAttachableImpl(); - } - - @After - public void tearDown() throws Exception { - aai = null; - } - - @Test - public void testAddAppender() throws Exception { - TestEvent event = new TestEvent(); - NOPAppender ta = new NOPAppender(); - ta.setLayout(new NopLayout()); - ta.start(); - aai.addAppender(ta); - ta = new NOPAppender(); - ta.setName("test"); - ta.setLayout(new NopLayout()); - ta.start(); - aai.addAppender(ta); - int size = aai.appendLoopOnAppenders(event); - assertTrue("Incorrect number of appenders", size == 2); - } - - @Test - public void testIteratorForAppenders() throws Exception { - NOPAppender ta = new NOPAppender(); - ta.setLayout(new NopLayout()); - ta.start(); - aai.addAppender(ta); - NOPAppender tab = new NOPAppender(); - tab.setName("test"); - tab.setLayout(new NopLayout()); - tab.start(); - aai.addAppender(tab); - Iterator> iter = aai.iteratorForAppenders(); - int size = 0; - while (iter.hasNext()) { - ++size; - Appender app = iter.next(); - assertTrue("Bad Appender", app == ta || app == tab); - } - assertTrue("Incorrect number of appenders", size == 2); - } - - @Test - public void getGetAppender() throws Exception { - NOPAppender test = new NOPAppender(); - test.setLayout(new NopLayout()); - test.setName("test"); - test.start(); - aai.addAppender(test); - - NOPAppender testOther = new NOPAppender(); - testOther.setName("testOther"); - testOther.setLayout(new NopLayout()); - testOther.start(); - aai.addAppender(testOther); - - Appender a = aai.getAppender("testOther"); - assertNotNull("Could not find appender", a); - assertTrue("Wrong appender", a == testOther); - - a = aai.getAppender("test"); - assertNotNull("Could not find appender", a); - assertTrue("Wrong appender", a == test); - a = aai.getAppender("NotThere"); - assertNull("Appender was returned", a); - } - - @Test - public void testIsAttached() throws Exception { - NOPAppender ta = new NOPAppender(); - ta.setLayout(new NopLayout()); - ta.start(); - aai.addAppender(ta); - NOPAppender tab = new NOPAppender(); - tab.setName("test"); - tab.setLayout(new NopLayout()); - tab.start(); - aai.addAppender(tab); - assertTrue("Appender is not attached", aai.isAttached(ta)); - assertTrue("Appender is not attached", aai.isAttached(tab)); - } - - @Test - public void testDetachAndStopAllAppenders() throws Exception { - NOPAppender ta = new NOPAppender(); - ta.setLayout(new NopLayout()); - ta.start(); - aai.addAppender(ta); - NOPAppender tab = new NOPAppender(); - tab.setName("test"); - tab.setLayout(new NopLayout()); - tab.start(); - aai.addAppender(tab); - assertTrue("Appender was not started", tab.isStarted()); - aai.detachAndStopAllAppenders(); - assertNull("Appender was not removed", aai.getAppender("test")); - assertFalse("Appender was not stopped", tab.isStarted()); - } - - @Test - public void testDetachAppender() throws Exception { - NOPAppender ta = new NOPAppender(); - ta.setLayout(new NopLayout()); - ta.start(); - aai.addAppender(ta); - NOPAppender tab = new NOPAppender(); - tab.setName("test"); - tab.setLayout(new NopLayout()); - tab.start(); - aai.addAppender(tab); - assertTrue("Appender not detached", aai.detachAppender(tab)); - assertNull("Appender was not removed", aai.getAppender("test")); - assertFalse("Appender detach error", aai.detachAppender(tab)); - } - - @Test - public void testDetachAppenderByName() throws Exception { - NOPAppender ta = new NOPAppender(); - ta.setName("test1"); - ta.setLayout(new NopLayout()); - ta.start(); - aai.addAppender(ta); - NOPAppender tab = new NOPAppender(); - tab.setName("test"); - tab.setLayout(new NopLayout()); - tab.start(); - aai.addAppender(tab); - - assertTrue(aai.detachAppender("test")); - assertTrue(aai.detachAppender("test1")); - assertFalse( aai.detachAppender("test1")); - } - - private static class TestEvent { - - } - -} - +/** + * 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.spi; + + +import static org.junit.Assert.*; +import ch.qos.logback.core.appender.NOPAppender; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.layout.NopLayout; + +import java.util.Iterator; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * This test case verifies all the methods of AppenderAttableImpl work properly. + * + * @author Ralph Goers + */ +public class AppenderAttachableImplTest { + + + private AppenderAttachableImpl aai; + + @Before + public void setUp() throws Exception { + aai = new AppenderAttachableImpl(); + } + + @After + public void tearDown() throws Exception { + aai = null; + } + + @Test + public void testAddAppender() throws Exception { + TestEvent event = new TestEvent(); + NOPAppender ta = new NOPAppender(); + ta.setLayout(new NopLayout()); + ta.start(); + aai.addAppender(ta); + ta = new NOPAppender(); + ta.setName("test"); + ta.setLayout(new NopLayout()); + ta.start(); + aai.addAppender(ta); + int size = aai.appendLoopOnAppenders(event); + assertTrue("Incorrect number of appenders", size == 2); + } + + @Test + public void testIteratorForAppenders() throws Exception { + NOPAppender ta = new NOPAppender(); + ta.setLayout(new NopLayout()); + ta.start(); + aai.addAppender(ta); + NOPAppender tab = new NOPAppender(); + tab.setName("test"); + tab.setLayout(new NopLayout()); + tab.start(); + aai.addAppender(tab); + Iterator> iter = aai.iteratorForAppenders(); + int size = 0; + while (iter.hasNext()) { + ++size; + Appender app = iter.next(); + assertTrue("Bad Appender", app == ta || app == tab); + } + assertTrue("Incorrect number of appenders", size == 2); + } + + @Test + public void getGetAppender() throws Exception { + NOPAppender test = new NOPAppender(); + test.setLayout(new NopLayout()); + test.setName("test"); + test.start(); + aai.addAppender(test); + + NOPAppender testOther = new NOPAppender(); + testOther.setName("testOther"); + testOther.setLayout(new NopLayout()); + testOther.start(); + aai.addAppender(testOther); + + Appender a = aai.getAppender("testOther"); + assertNotNull("Could not find appender", a); + assertTrue("Wrong appender", a == testOther); + + a = aai.getAppender("test"); + assertNotNull("Could not find appender", a); + assertTrue("Wrong appender", a == test); + a = aai.getAppender("NotThere"); + assertNull("Appender was returned", a); + } + + @Test + public void testIsAttached() throws Exception { + NOPAppender ta = new NOPAppender(); + ta.setLayout(new NopLayout()); + ta.start(); + aai.addAppender(ta); + NOPAppender tab = new NOPAppender(); + tab.setName("test"); + tab.setLayout(new NopLayout()); + tab.start(); + aai.addAppender(tab); + assertTrue("Appender is not attached", aai.isAttached(ta)); + assertTrue("Appender is not attached", aai.isAttached(tab)); + } + + @Test + public void testDetachAndStopAllAppenders() throws Exception { + NOPAppender ta = new NOPAppender(); + ta.setLayout(new NopLayout()); + ta.start(); + aai.addAppender(ta); + NOPAppender tab = new NOPAppender(); + tab.setName("test"); + tab.setLayout(new NopLayout()); + tab.start(); + aai.addAppender(tab); + assertTrue("Appender was not started", tab.isStarted()); + aai.detachAndStopAllAppenders(); + assertNull("Appender was not removed", aai.getAppender("test")); + assertFalse("Appender was not stopped", tab.isStarted()); + } + + @Test + public void testDetachAppender() throws Exception { + NOPAppender ta = new NOPAppender(); + ta.setLayout(new NopLayout()); + ta.start(); + aai.addAppender(ta); + NOPAppender tab = new NOPAppender(); + tab.setName("test"); + tab.setLayout(new NopLayout()); + tab.start(); + aai.addAppender(tab); + assertTrue("Appender not detached", aai.detachAppender(tab)); + assertNull("Appender was not removed", aai.getAppender("test")); + assertFalse("Appender detach error", aai.detachAppender(tab)); + } + + @Test + public void testDetachAppenderByName() throws Exception { + NOPAppender ta = new NOPAppender(); + ta.setName("test1"); + ta.setLayout(new NopLayout()); + ta.start(); + aai.addAppender(ta); + NOPAppender tab = new NOPAppender(); + tab.setName("test"); + tab.setLayout(new NopLayout()); + tab.start(); + aai.addAppender(tab); + + assertTrue(aai.detachAppender("test")); + assertTrue(aai.detachAppender("test1")); + assertFalse( aai.detachAppender("test1")); + } + + private static class TestEvent { + + } + +} + diff --git a/logback-core/src/test/java/ch/qos/logback/core/spi/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/spi/PackageTest.java index 54f15024aef98381b0380ee1419d914dc20c04c0..991ffff1db167b87ac02835f680fa9e1e1438671 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/spi/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/spi/PackageTest.java @@ -1,24 +1,24 @@ -/** - * 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.spi; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - - -@RunWith(Suite.class) -@Suite.SuiteClasses({AppenderAttachableImplTest.class ,AppenderAttachableImplLockTest.class}) - -public class PackageTest { -} +/** + * 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.spi; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + + +@RunWith(Suite.class) +@Suite.SuiteClasses({AppenderAttachableImplTest.class ,AppenderAttachableImplLockTest.class}) + +public class PackageTest { +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/status/StatusBaseTest.java b/logback-core/src/test/java/ch/qos/logback/core/status/StatusBaseTest.java index 9cf9d79b04c5b4d87fed7716176116e631a7db22..d5df1cb7aaa7c7b220741df0cc36156816bc1d1e 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/status/StatusBaseTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/status/StatusBaseTest.java @@ -1,93 +1,93 @@ -/** - * 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.status; - -import java.util.Iterator; - -import junit.framework.TestCase; - -public class StatusBaseTest extends TestCase { - - public void testAddStatus() { - { - InfoStatus status = new InfoStatus("testing", this); - status.add(new ErrorStatus("error", this)); - Iterator it = status.iterator(); - assertTrue("No status was added", it.hasNext()); - assertTrue("hasChilden method reported wrong result", status - .hasChildren()); - } - { - InfoStatus status = new InfoStatus("testing", this); - try { - status.add(null); - fail("method should have thrown an Exception"); - } catch (NullPointerException ex) { - } - } - } - - public void testRemoveStatus() { - { - InfoStatus status = new InfoStatus("testing", this); - ErrorStatus error = new ErrorStatus("error", this); - status.add(error); - boolean result = status.remove(error); - Iterator it = status.iterator(); - assertTrue("Remove failed", result); - assertFalse("No status was removed", it.hasNext()); - assertFalse("hasChilden method reported wrong result", status - .hasChildren()); - } - { - InfoStatus status = new InfoStatus("testing", this); - ErrorStatus error = new ErrorStatus("error", this); - status.add(error); - boolean result = status.remove(null); - assertFalse("Remove result was not false", result); - } - } - - public void testEffectiveLevel() { - { - // effective level = 0 level deep - ErrorStatus status = new ErrorStatus("error", this); - WarnStatus warn = new WarnStatus("warning", this); - status.add(warn); - assertEquals("effective level misevaluated", status.getEffectiveLevel(), - Status.ERROR); - } - - { - // effective level = 1 level deep - InfoStatus status = new InfoStatus("info", this); - WarnStatus warn = new WarnStatus("warning", this); - status.add(warn); - assertEquals("effective level misevaluated", status.getEffectiveLevel(), - Status.WARN); - } - - { - // effective level = 2 levels deep - InfoStatus status = new InfoStatus("info", this); - WarnStatus warn = new WarnStatus("warning", this); - ErrorStatus error = new ErrorStatus("error", this); - status.add(warn); - warn.add(error); - assertEquals("effective level misevaluated", status.getEffectiveLevel(), - Status.ERROR); - } - } - -} +/** + * 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.status; + +import java.util.Iterator; + +import junit.framework.TestCase; + +public class StatusBaseTest extends TestCase { + + public void testAddStatus() { + { + InfoStatus status = new InfoStatus("testing", this); + status.add(new ErrorStatus("error", this)); + Iterator it = status.iterator(); + assertTrue("No status was added", it.hasNext()); + assertTrue("hasChilden method reported wrong result", status + .hasChildren()); + } + { + InfoStatus status = new InfoStatus("testing", this); + try { + status.add(null); + fail("method should have thrown an Exception"); + } catch (NullPointerException ex) { + } + } + } + + public void testRemoveStatus() { + { + InfoStatus status = new InfoStatus("testing", this); + ErrorStatus error = new ErrorStatus("error", this); + status.add(error); + boolean result = status.remove(error); + Iterator it = status.iterator(); + assertTrue("Remove failed", result); + assertFalse("No status was removed", it.hasNext()); + assertFalse("hasChilden method reported wrong result", status + .hasChildren()); + } + { + InfoStatus status = new InfoStatus("testing", this); + ErrorStatus error = new ErrorStatus("error", this); + status.add(error); + boolean result = status.remove(null); + assertFalse("Remove result was not false", result); + } + } + + public void testEffectiveLevel() { + { + // effective level = 0 level deep + ErrorStatus status = new ErrorStatus("error", this); + WarnStatus warn = new WarnStatus("warning", this); + status.add(warn); + assertEquals("effective level misevaluated", status.getEffectiveLevel(), + Status.ERROR); + } + + { + // effective level = 1 level deep + InfoStatus status = new InfoStatus("info", this); + WarnStatus warn = new WarnStatus("warning", this); + status.add(warn); + assertEquals("effective level misevaluated", status.getEffectiveLevel(), + Status.WARN); + } + + { + // effective level = 2 levels deep + InfoStatus status = new InfoStatus("info", this); + WarnStatus warn = new WarnStatus("warning", this); + ErrorStatus error = new ErrorStatus("error", this); + status.add(warn); + warn.add(error); + assertEquals("effective level misevaluated", status.getEffectiveLevel(), + Status.ERROR); + } + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/status/StatusChecker.java b/logback-core/src/test/java/ch/qos/logback/core/status/StatusChecker.java index 1250de8d5a94a34cd7b2a922bf2ec01d8fe59ebb..b40e7cbe03180a6f856ad926a8a069494d99d33f 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/status/StatusChecker.java +++ b/logback-core/src/test/java/ch/qos/logback/core/status/StatusChecker.java @@ -1,93 +1,93 @@ -/** - * 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.status; - -import java.util.Iterator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import ch.qos.logback.core.Context; - -public class StatusChecker { - - StatusManager sm; - - public StatusChecker(StatusManager sm) { - this.sm = sm; - } - - public StatusChecker(Context context) { - this.sm = context.getStatusManager(); - } - - public boolean isErrorFree() { - int level = sm.getLevel(); - return level < Status.ERROR; - } - - public boolean containsMatch(int level, String regex) { - Pattern p = Pattern.compile(regex); - - for(Status status: sm.getCopyOfStatusList()) { - if(level != status.getLevel()) { - continue; - } - String msg = status.getMessage(); - Matcher matcher = p.matcher(msg); - if (matcher.lookingAt()) { - return true; - } - } - return false; - - } - - public boolean containsMatch(String regex) { - Pattern p = Pattern.compile(regex); - for(Status status: sm.getCopyOfStatusList()) { - String msg = status.getMessage(); - Matcher matcher = p.matcher(msg); - if (matcher.lookingAt()) { - return true; - } - } - return false; - } - - public int matchCount(String regex) { - int count = 0; - Pattern p = Pattern.compile(regex); - for(Status status: sm.getCopyOfStatusList()) { - String msg = status.getMessage(); - Matcher matcher = p.matcher(msg); - if (matcher.lookingAt()) { - count++; - } - } - return count; - } - - public boolean containsException(Class exceptionType) { - Iterator stati = sm.getCopyOfStatusList().iterator(); - while (stati.hasNext()) { - Status status = (Status) stati.next(); - Throwable t = status.getThrowable(); - if (t != null && t.getClass().getName().equals(exceptionType.getName())) { - return true; - } - } - return false; - } - -} +/** + * 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.status; + +import java.util.Iterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import ch.qos.logback.core.Context; + +public class StatusChecker { + + StatusManager sm; + + public StatusChecker(StatusManager sm) { + this.sm = sm; + } + + public StatusChecker(Context context) { + this.sm = context.getStatusManager(); + } + + public boolean isErrorFree() { + int level = sm.getLevel(); + return level < Status.ERROR; + } + + public boolean containsMatch(int level, String regex) { + Pattern p = Pattern.compile(regex); + + for(Status status: sm.getCopyOfStatusList()) { + if(level != status.getLevel()) { + continue; + } + String msg = status.getMessage(); + Matcher matcher = p.matcher(msg); + if (matcher.lookingAt()) { + return true; + } + } + return false; + + } + + public boolean containsMatch(String regex) { + Pattern p = Pattern.compile(regex); + for(Status status: sm.getCopyOfStatusList()) { + String msg = status.getMessage(); + Matcher matcher = p.matcher(msg); + if (matcher.lookingAt()) { + return true; + } + } + return false; + } + + public int matchCount(String regex) { + int count = 0; + Pattern p = Pattern.compile(regex); + for(Status status: sm.getCopyOfStatusList()) { + String msg = status.getMessage(); + Matcher matcher = p.matcher(msg); + if (matcher.lookingAt()) { + count++; + } + } + return count; + } + + public boolean containsException(Class exceptionType) { + Iterator stati = sm.getCopyOfStatusList().iterator(); + while (stati.hasNext()) { + Status status = (Status) stati.next(); + Throwable t = status.getThrowable(); + if (t != null && t.getClass().getName().equals(exceptionType.getName())) { + return true; + } + } + return false; + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/status/TrivialStatusListener.java b/logback-core/src/test/java/ch/qos/logback/core/status/TrivialStatusListener.java index d6f5dfd2239deb92b8ed03f252d6cfe9f20e274b..c942255dd1f456b339d806e0290412b3210ff317 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/status/TrivialStatusListener.java +++ b/logback-core/src/test/java/ch/qos/logback/core/status/TrivialStatusListener.java @@ -1,30 +1,30 @@ -/** - * 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.status; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.StatusListener; - -public class TrivialStatusListener implements StatusListener { - - public List list = new ArrayList(); - - public void addStatusEvent(Status status) { - list.add(status); - } - -} +/** + * 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.status; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusListener; + +public class TrivialStatusListener implements StatusListener { + + public List list = new ArrayList(); + + public void addStatusEvent(Status status) { + list.add(status); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/testUtil/Env.java b/logback-core/src/test/java/ch/qos/logback/core/testUtil/Env.java index c29ba43f710d33317dabfbc5d69aa1c0e75d94b9..00bccb9b6ea6531d3cd76436838f5c7e327a8ad9 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/testUtil/Env.java +++ b/logback-core/src/test/java/ch/qos/logback/core/testUtil/Env.java @@ -1,38 +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.testUtil; - -public class Env { - - static public boolean isWindows() { - return System.getProperty("os.name").indexOf("Windows") != -1; - } - - static public boolean isLinux() { - return System.getProperty("os.name").indexOf("Linux") != -1; - } - - static public boolean isJDK6OrHigher() { - String javaVersion = System.getProperty("java.version"); - if (javaVersion == null) { - return false; - } - if (javaVersion.startsWith("1.6") || javaVersion.startsWith("1.7")) { - return true; - } else { - return false; - } - } - -} +/** + * 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.testUtil; + +public class Env { + + static public boolean isWindows() { + return System.getProperty("os.name").indexOf("Windows") != -1; + } + + static public boolean isLinux() { + return System.getProperty("os.name").indexOf("Linux") != -1; + } + + static public boolean isJDK6OrHigher() { + String javaVersion = System.getProperty("java.version"); + if (javaVersion == null) { + return false; + } + if (javaVersion.startsWith("1.6") || javaVersion.startsWith("1.7")) { + return true; + } else { + return false; + } + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/testUtil/FileToBufferUtil.java b/logback-core/src/test/java/ch/qos/logback/core/testUtil/FileToBufferUtil.java index 12aaa14434d6e0693dd77deeb16b4392e883e989..dd4143c6692002b20bed70dce775209d90d2f592 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/testUtil/FileToBufferUtil.java +++ b/logback-core/src/test/java/ch/qos/logback/core/testUtil/FileToBufferUtil.java @@ -1,57 +1,57 @@ -/** - * 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.testUtil; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.List; -import java.util.zip.GZIPInputStream; - -public class FileToBufferUtil { - - static public void readIntoList(File file, List stringList) - throws IOException { - - if(file.getName().endsWith(".gz")) { - gzFileReadIntoList(file, stringList); - } else { - regularReadIntoList(file, stringList); - } - } - - static public void regularReadIntoList(File file, List stringList) throws IOException { - FileInputStream fis = new FileInputStream(file); - BufferedReader in = new BufferedReader(new InputStreamReader(fis)); - String line; - while( (line = in.readLine()) != null) { - stringList.add(line); - } - in.close(); - } - - static public void gzFileReadIntoList(File file, List stringList) throws IOException { - FileInputStream fis = new FileInputStream(file); - GZIPInputStream gzis = new GZIPInputStream(fis); - BufferedReader in = new BufferedReader(new InputStreamReader(gzis)); - String line; - while( (line = in.readLine()) != null) { - stringList.add(line); - } - in.close(); - } - -} +/** + * 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.testUtil; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.List; +import java.util.zip.GZIPInputStream; + +public class FileToBufferUtil { + + static public void readIntoList(File file, List stringList) + throws IOException { + + if(file.getName().endsWith(".gz")) { + gzFileReadIntoList(file, stringList); + } else { + regularReadIntoList(file, stringList); + } + } + + static public void regularReadIntoList(File file, List stringList) throws IOException { + FileInputStream fis = new FileInputStream(file); + BufferedReader in = new BufferedReader(new InputStreamReader(fis)); + String line; + while( (line = in.readLine()) != null) { + stringList.add(line); + } + in.close(); + } + + static public void gzFileReadIntoList(File file, List stringList) throws IOException { + FileInputStream fis = new FileInputStream(file); + GZIPInputStream gzis = new GZIPInputStream(fis); + BufferedReader in = new BufferedReader(new InputStreamReader(gzis)); + String line; + while( (line = in.readLine()) != null) { + stringList.add(line); + } + in.close(); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/testUtil/RandomUtil.java b/logback-core/src/test/java/ch/qos/logback/core/testUtil/RandomUtil.java index 413276cfe8c73961968f753320e23cae2e51b6d8..b1967a579711b865c199bdf4d6403ebe510ae356 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/testUtil/RandomUtil.java +++ b/logback-core/src/test/java/ch/qos/logback/core/testUtil/RandomUtil.java @@ -1,35 +1,35 @@ -/** - * 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.testUtil; - -import java.util.Random; - -public class RandomUtil { - - private static Random random = new Random(); - - public static int getRandomServerPort() { - int r = random.nextInt(20000); - // the first 1024 ports are usually reserved for the OS - return r + 1024; - } - - public static int getPositiveInt() { - int r = random.nextInt(); - if (r < 0) { - r = -r; - } - return r; - } -} +/** + * 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.testUtil; + +import java.util.Random; + +public class RandomUtil { + + private static Random random = new Random(); + + public static int getRandomServerPort() { + int r = random.nextInt(20000); + // the first 1024 ports are usually reserved for the OS + return r + 1024; + } + + public static int getPositiveInt() { + int r = random.nextInt(); + if (r < 0) { + r = -r; + } + return r; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/testUtil/StringListAppender.java b/logback-core/src/test/java/ch/qos/logback/core/testUtil/StringListAppender.java index a6e023aee3211baaf3a01f9682344995ac9c31f5..bd51887fd453a0314ea965aa41c240312317e7a2 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/testUtil/StringListAppender.java +++ b/logback-core/src/test/java/ch/qos/logback/core/testUtil/StringListAppender.java @@ -1,59 +1,59 @@ -/** - * 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.testUtil; - -import java.util.ArrayList; -import java.util.List; - -import ch.qos.logback.core.AppenderBase; -import ch.qos.logback.core.Layout; - -public class StringListAppender extends AppenderBase { - - Layout layout; - public List strList = new ArrayList(); - - public StringListAppender() { - - } - - public void start() { - strList.clear(); - - if (layout == null || !layout.isStarted()) { - return; - } - super.start(); - } - - public void stop() { - super.stop(); - } - - @Override - protected void append(E eventObject) { - String res = layout.doLayout(eventObject); - strList.add(res); - } - - @Override - public Layout getLayout() { - return layout; - } - - @Override - public void setLayout(Layout layout) { - this.layout = layout; - } -} +/** + * 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.testUtil; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.Layout; + +public class StringListAppender extends AppenderBase { + + Layout layout; + public List strList = new ArrayList(); + + public StringListAppender() { + + } + + public void start() { + strList.clear(); + + if (layout == null || !layout.isStarted()) { + return; + } + super.start(); + } + + public void stop() { + super.stop(); + } + + @Override + protected void append(E eventObject) { + String res = layout.doLayout(eventObject); + strList.add(res); + } + + @Override + public Layout getLayout() { + return layout; + } + + @Override + public void setLayout(Layout layout) { + this.layout = layout; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/Compare.java b/logback-core/src/test/java/ch/qos/logback/core/util/Compare.java index 0a623266c472909fbe990c56b55258758cc76d1a..a0cb940f5be7baff30096539644d678dddbc1d58 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/Compare.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/Compare.java @@ -1,164 +1,164 @@ -/** - * 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.util; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.zip.GZIPInputStream; - -public class Compare { - static final int B1_NULL = -1; - static final int B2_NULL = -2; - - public static boolean compare(String file1, String file2) throws FileNotFoundException, IOException { - if (file1.endsWith(".gz")) { - //System.out.println(file1 +" is a gz file"); - return gzFileCompare(file1, file2); - } else { - return regularFileCompare(file1, file2); - } - } - - static BufferedReader gzFileToBufferedReader(String file) throws IOException { - FileInputStream fis = new FileInputStream(file); - GZIPInputStream gzis = new GZIPInputStream(fis); - BufferedReader br = new BufferedReader(new InputStreamReader(gzis)); - return br; - } - - public static boolean gzFileCompare(String file1, String file2) throws IOException { - BufferedReader in1 = gzFileToBufferedReader(file1); - BufferedReader in2 = gzFileToBufferedReader(file2); - return bufferCompare(in1, in2, file1, file2); - } - - public static boolean regularFileCompare(String file1, String file2) - throws FileNotFoundException, IOException { - BufferedReader in1 = new BufferedReader(new FileReader(file1)); - BufferedReader in2 = new BufferedReader(new FileReader(file2)); - return bufferCompare(in1, in2, file1, file2); - } - - public static boolean bufferCompare(BufferedReader in1, BufferedReader in2, - String file1, String file2) throws FileNotFoundException, IOException { - - String s1; - int lineCounter = 0; - - while ((s1 = in1.readLine()) != null) { - lineCounter++; - - String s2 = in2.readLine(); - - if (!s1.equals(s2)) { - System.out.println("Files [" + file1 + "] and [" + file2 - + "] differ on line " + lineCounter); - System.out.println("One reads: [" + s1 + "]."); - System.out.println("Other reads:[" + s2 + "]."); - outputFile(file1); - outputFile(file2); - - return false; - } - } - - // the second file is longer - if (in2.read() != -1) { - System.out.println("File [" + file2 + "] longer than file [" + file1 - + "]."); - outputFile(file1); - outputFile(file2); - - return false; - } - - return true; - } - - /** - * - * Prints file on the console. - * - */ - private static void outputFile(String file) throws FileNotFoundException, - IOException { - BufferedReader in1 = new BufferedReader(new FileReader(file)); - - String s1; - int lineCounter = 0; - System.out.println("--------------------------------"); - System.out.println("Contents of " + file + ":"); - - while ((s1 = in1.readLine()) != null) { - lineCounter++; - System.out.print(lineCounter); - - if (lineCounter < 10) { - System.out.print(" : "); - } else if (lineCounter < 100) { - System.out.print(" : "); - } else if (lineCounter < 1000) { - System.out.print(" : "); - } else { - System.out.print(": "); - } - - System.out.println(s1); - } - } - - public static boolean gzCompare(String file1, String file2) - throws FileNotFoundException, IOException { - BufferedReader in1 = new BufferedReader(new InputStreamReader( - new GZIPInputStream(new FileInputStream(file1)))); - BufferedReader in2 = new BufferedReader(new InputStreamReader( - new GZIPInputStream(new FileInputStream(file2)))); - - String s1; - int lineCounter = 0; - - while ((s1 = in1.readLine()) != null) { - lineCounter++; - - String s2 = in2.readLine(); - - if (!s1.equals(s2)) { - System.out.println("Files [" + file1 + "] and [" + file2 - + "] differ on line " + lineCounter); - System.out.println("One reads: [" + s1 + "]."); - System.out.println("Other reads:[" + s2 + "]."); - outputFile(file1); - outputFile(file2); - - return false; - } - } - - // the second file is longer - if (in2.read() != -1) { - System.out.println("File [" + file2 + "] longer than file [" + file1 - + "]."); - outputFile(file1); - outputFile(file2); - - return false; - } - - return true; - } -} +/** + * 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.util; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.zip.GZIPInputStream; + +public class Compare { + static final int B1_NULL = -1; + static final int B2_NULL = -2; + + public static boolean compare(String file1, String file2) throws FileNotFoundException, IOException { + if (file1.endsWith(".gz")) { + //System.out.println(file1 +" is a gz file"); + return gzFileCompare(file1, file2); + } else { + return regularFileCompare(file1, file2); + } + } + + static BufferedReader gzFileToBufferedReader(String file) throws IOException { + FileInputStream fis = new FileInputStream(file); + GZIPInputStream gzis = new GZIPInputStream(fis); + BufferedReader br = new BufferedReader(new InputStreamReader(gzis)); + return br; + } + + public static boolean gzFileCompare(String file1, String file2) throws IOException { + BufferedReader in1 = gzFileToBufferedReader(file1); + BufferedReader in2 = gzFileToBufferedReader(file2); + return bufferCompare(in1, in2, file1, file2); + } + + public static boolean regularFileCompare(String file1, String file2) + throws FileNotFoundException, IOException { + BufferedReader in1 = new BufferedReader(new FileReader(file1)); + BufferedReader in2 = new BufferedReader(new FileReader(file2)); + return bufferCompare(in1, in2, file1, file2); + } + + public static boolean bufferCompare(BufferedReader in1, BufferedReader in2, + String file1, String file2) throws FileNotFoundException, IOException { + + String s1; + int lineCounter = 0; + + while ((s1 = in1.readLine()) != null) { + lineCounter++; + + String s2 = in2.readLine(); + + if (!s1.equals(s2)) { + System.out.println("Files [" + file1 + "] and [" + file2 + + "] differ on line " + lineCounter); + System.out.println("One reads: [" + s1 + "]."); + System.out.println("Other reads:[" + s2 + "]."); + outputFile(file1); + outputFile(file2); + + return false; + } + } + + // the second file is longer + if (in2.read() != -1) { + System.out.println("File [" + file2 + "] longer than file [" + file1 + + "]."); + outputFile(file1); + outputFile(file2); + + return false; + } + + return true; + } + + /** + * + * Prints file on the console. + * + */ + private static void outputFile(String file) throws FileNotFoundException, + IOException { + BufferedReader in1 = new BufferedReader(new FileReader(file)); + + String s1; + int lineCounter = 0; + System.out.println("--------------------------------"); + System.out.println("Contents of " + file + ":"); + + while ((s1 = in1.readLine()) != null) { + lineCounter++; + System.out.print(lineCounter); + + if (lineCounter < 10) { + System.out.print(" : "); + } else if (lineCounter < 100) { + System.out.print(" : "); + } else if (lineCounter < 1000) { + System.out.print(" : "); + } else { + System.out.print(": "); + } + + System.out.println(s1); + } + } + + public static boolean gzCompare(String file1, String file2) + throws FileNotFoundException, IOException { + BufferedReader in1 = new BufferedReader(new InputStreamReader( + new GZIPInputStream(new FileInputStream(file1)))); + BufferedReader in2 = new BufferedReader(new InputStreamReader( + new GZIPInputStream(new FileInputStream(file2)))); + + String s1; + int lineCounter = 0; + + while ((s1 = in1.readLine()) != null) { + lineCounter++; + + String s2 = in2.readLine(); + + if (!s1.equals(s2)) { + System.out.println("Files [" + file1 + "] and [" + file2 + + "] differ on line " + lineCounter); + System.out.println("One reads: [" + s1 + "]."); + System.out.println("Other reads:[" + s2 + "]."); + outputFile(file1); + outputFile(file2); + + return false; + } + } + + // the second file is longer + if (in2.read() != -1) { + System.out.println("File [" + file2 + "] longer than file [" + file1 + + "]."); + outputFile(file1); + outputFile(file2); + + return false; + } + + return true; + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/ContentTypeUtilTest.java b/logback-core/src/test/java/ch/qos/logback/core/util/ContentTypeUtilTest.java index 49e6e29f4b4590477afc045f2cdcc36ed3bb24b7..8db1d17098b753094d61d7481bbb0533ccdae4d4 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/ContentTypeUtilTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/ContentTypeUtilTest.java @@ -1,44 +1,44 @@ -/** - * 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.util; - -import static org.junit.Assert.*; - -import org.junit.Test; - - -public class ContentTypeUtilTest { - - - @Test - public void smoke() { - String contextType = "text/html"; - assertTrue(ContentTypeUtil.isTextual(contextType)); - assertEquals("html", ContentTypeUtil.getSubType(contextType)); - } - - @Test - public void nullContext() { - String contextType = null; - assertFalse(ContentTypeUtil.isTextual(contextType)); - assertNull(ContentTypeUtil.getSubType(contextType)); - } - - @Test - public void emptySubtype() { - String contextType = "text/"; - assertTrue(ContentTypeUtil.isTextual(contextType)); - assertNull(ContentTypeUtil.getSubType(contextType)); - } -} +/** + * 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.util; + +import static org.junit.Assert.*; + +import org.junit.Test; + + +public class ContentTypeUtilTest { + + + @Test + public void smoke() { + String contextType = "text/html"; + assertTrue(ContentTypeUtil.isTextual(contextType)); + assertEquals("html", ContentTypeUtil.getSubType(contextType)); + } + + @Test + public void nullContext() { + String contextType = null; + assertFalse(ContentTypeUtil.isTextual(contextType)); + assertNull(ContentTypeUtil.getSubType(contextType)); + } + + @Test + public void emptySubtype() { + String contextType = "text/"; + assertTrue(ContentTypeUtil.isTextual(contextType)); + assertNull(ContentTypeUtil.getSubType(contextType)); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/CoreTestConstants.java b/logback-core/src/test/java/ch/qos/logback/core/util/CoreTestConstants.java index 9d9f035a382fe0117c87ec37266e0335d3ab8b5d..e86a0149aefd589b4462777416430731c2fd6c7f 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/CoreTestConstants.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/CoreTestConstants.java @@ -1,22 +1,22 @@ -/** - * 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.util; - - -public class CoreTestConstants { - - public static final String TEST_DIR_PREFIX = "src/test/"; - public static final String OUTPUT_DIR_PREFIX = "target/test-output/"; - -} +/** + * 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.util; + + +public class CoreTestConstants { + + public static final String TEST_DIR_PREFIX = "src/test/"; + public static final String OUTPUT_DIR_PREFIX = "target/test-output/"; + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/DurationTest.java b/logback-core/src/test/java/ch/qos/logback/core/util/DurationTest.java index 2da98a30a4bec3cc81fc868b70179cd106322cb9..2cd354e7c1eb7e09b0562f1aea65ca2c74d91d4b 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/DurationTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/DurationTest.java @@ -1,104 +1,104 @@ -/** - * 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.util; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - - -public class DurationTest { - - static long HOURS_CO = 60*60; - static long DAYS_CO = 24*60*60; - - - @Test - public void test() { - { - Duration d = Duration.valueOf("12"); - assertEquals(12, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("159 milli"); - assertEquals(159, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("15 millis"); - assertEquals(15, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("8 milliseconds"); - assertEquals(8, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("10.7 millisecond"); - assertEquals(10, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("10 SECOnds"); - assertEquals(10 * 1000, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("12seconde"); - assertEquals(12 * 1000, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("14 SECONDES"); - assertEquals(14 * 1000, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("12second"); - assertEquals(12 * 1000, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("10.7 seconds"); - assertEquals(10700, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("1 minute"); - assertEquals(1000*60, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("2.2 minutes"); - assertEquals(2200*60, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("1 hour"); - assertEquals(1000*HOURS_CO, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("4.2 hours"); - assertEquals(4200*HOURS_CO, d.getMilliseconds()); - } - - { - Duration d = Duration.valueOf("5 days"); - assertEquals(5000*DAYS_CO, d.getMilliseconds()); - } - } -} +/** + * 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.util; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + + +public class DurationTest { + + static long HOURS_CO = 60*60; + static long DAYS_CO = 24*60*60; + + + @Test + public void test() { + { + Duration d = Duration.valueOf("12"); + assertEquals(12, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("159 milli"); + assertEquals(159, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("15 millis"); + assertEquals(15, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("8 milliseconds"); + assertEquals(8, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("10.7 millisecond"); + assertEquals(10, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("10 SECOnds"); + assertEquals(10 * 1000, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("12seconde"); + assertEquals(12 * 1000, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("14 SECONDES"); + assertEquals(14 * 1000, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("12second"); + assertEquals(12 * 1000, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("10.7 seconds"); + assertEquals(10700, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("1 minute"); + assertEquals(1000*60, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("2.2 minutes"); + assertEquals(2200*60, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("1 hour"); + assertEquals(1000*HOURS_CO, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("4.2 hours"); + assertEquals(4200*HOURS_CO, d.getMilliseconds()); + } + + { + Duration d = Duration.valueOf("5 days"); + assertEquals(5000*DAYS_CO, d.getMilliseconds()); + } + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/FileSizeTest.java b/logback-core/src/test/java/ch/qos/logback/core/util/FileSizeTest.java index a1c29a2b97f1717bc0c166318a037e57fe6b662f..ab9f7d90897e0243fc6525804d1eab3fca034a6f 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/FileSizeTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/FileSizeTest.java @@ -1,56 +1,56 @@ -/** - * 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.util; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - - -public class FileSizeTest{ - - static long KB_CO = 1024; - static long MB_CO = 1024*1024; - static long GB_CO = 1024*MB_CO; - - - @Test - public void test() { - { - FileSize fs = FileSize.valueOf("8"); - assertEquals(8, fs.getSize()); - } - - { - FileSize fs = FileSize.valueOf("8 kbs"); - assertEquals(8*KB_CO, fs.getSize()); - } - - { - FileSize fs = FileSize.valueOf("8 kb"); - assertEquals(8*KB_CO, fs.getSize()); - } - - { - FileSize fs = FileSize.valueOf("12 mb"); - assertEquals(12*MB_CO, fs.getSize()); - } - - { - FileSize fs = FileSize.valueOf("5 GBs"); - assertEquals(5*GB_CO, fs.getSize()); - } - - } -} +/** + * 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.util; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + + +public class FileSizeTest{ + + static long KB_CO = 1024; + static long MB_CO = 1024*1024; + static long GB_CO = 1024*MB_CO; + + + @Test + public void test() { + { + FileSize fs = FileSize.valueOf("8"); + assertEquals(8, fs.getSize()); + } + + { + FileSize fs = FileSize.valueOf("8 kbs"); + assertEquals(8*KB_CO, fs.getSize()); + } + + { + FileSize fs = FileSize.valueOf("8 kb"); + assertEquals(8*KB_CO, fs.getSize()); + } + + { + FileSize fs = FileSize.valueOf("12 mb"); + assertEquals(12*MB_CO, fs.getSize()); + } + + { + FileSize fs = FileSize.valueOf("5 GBs"); + assertEquals(5*GB_CO, fs.getSize()); + } + + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/FileUtilTest.java b/logback-core/src/test/java/ch/qos/logback/core/util/FileUtilTest.java index 459825e5a78c803bbd6f98b0cfdf3fa5dda992f5..b392c916c2dd346ba2b1fb7b4fcd62e5e59cdd86 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/FileUtilTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/FileUtilTest.java @@ -1,72 +1,72 @@ -/** - * 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.util; - - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class FileUtilTest { - - List cleanupList = new ArrayList(); - - @Before - public void setUp() throws Exception { - - } - - @After - public void tearDown() throws Exception { - for(File f: cleanupList) { - f.delete(); - } - } - - - @Test - public void smoke() { - int diff = new Random().nextInt(100); - File file = new File(CoreTestConstants.OUTPUT_DIR_PREFIX+"/fu"+diff+"/testing.txt"); - // these will be deleted later - cleanupList.add(file); - cleanupList.add(file.getParentFile()); - - assertTrue(FileUtil.mustCreateParentDirectories(file)); - assertTrue(FileUtil.createMissingParentDirectories(file)); - assertFalse(FileUtil.mustCreateParentDirectories(file)); - } - - @Test - public void smokeII() { - int diff = new Random().nextInt(100); - File file = new File(CoreTestConstants.OUTPUT_DIR_PREFIX+"/fu"+diff+"/bla/testing.txt"); - // these will be deleted later - cleanupList.add(file); - cleanupList.add(file.getParentFile()); - cleanupList.add(file.getParentFile().getParentFile()); - - assertTrue(FileUtil.mustCreateParentDirectories(file)); - assertTrue(FileUtil.createMissingParentDirectories(file)); - assertFalse(FileUtil.mustCreateParentDirectories(file)); - } -} +/** + * 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.util; + + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class FileUtilTest { + + List cleanupList = new ArrayList(); + + @Before + public void setUp() throws Exception { + + } + + @After + public void tearDown() throws Exception { + for(File f: cleanupList) { + f.delete(); + } + } + + + @Test + public void smoke() { + int diff = new Random().nextInt(100); + File file = new File(CoreTestConstants.OUTPUT_DIR_PREFIX+"/fu"+diff+"/testing.txt"); + // these will be deleted later + cleanupList.add(file); + cleanupList.add(file.getParentFile()); + + assertTrue(FileUtil.mustCreateParentDirectories(file)); + assertTrue(FileUtil.createMissingParentDirectories(file)); + assertFalse(FileUtil.mustCreateParentDirectories(file)); + } + + @Test + public void smokeII() { + int diff = new Random().nextInt(100); + File file = new File(CoreTestConstants.OUTPUT_DIR_PREFIX+"/fu"+diff+"/bla/testing.txt"); + // these will be deleted later + cleanupList.add(file); + cleanupList.add(file.getParentFile()); + cleanupList.add(file.getParentFile().getParentFile()); + + assertTrue(FileUtil.mustCreateParentDirectories(file)); + assertTrue(FileUtil.createMissingParentDirectories(file)); + assertFalse(FileUtil.mustCreateParentDirectories(file)); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/OptionHelperTest.java b/logback-core/src/test/java/ch/qos/logback/core/util/OptionHelperTest.java index bbb01417364f24e44144250955f653eb4cd6a069..717f96990e5e6acb380fdae08bb743d6cb41038d 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/OptionHelperTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/OptionHelperTest.java @@ -1,111 +1,111 @@ -/** - * 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.util; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; - - -public class OptionHelperTest { - - String text = "Testing ${v1} variable substitution ${v2}"; - String expected = "Testing if variable substitution works"; - Context context = new ContextBase(); - Map secondaryMap; - - - - @Before - public void setUp() throws Exception { - secondaryMap = new HashMap(); - } - - @Test - public void testLiteral() { - String noSubst = "hello world"; - String result = OptionHelper.substVars(noSubst, context); - assertEquals(noSubst, result); - } - - @Test - public void testUndefinedValues() { - String withUndefinedValues = "${axyz}"; - - String result = OptionHelper.substVars(withUndefinedValues, context); - assertEquals("axyz"+OptionHelper._IS_UNDEFINED, result); - } - - @Test - public void testSubstVarsVariableNotClosed() { - String noSubst = "testing if ${v1 works"; - - try { - @SuppressWarnings("unused") - String result = OptionHelper.substVars(noSubst, context); - fail(); - } catch (IllegalArgumentException e) { - //ok - } - } - @Test - public void testSubstVarsContextOnly() { - context.putProperty("v1", "if"); - context.putProperty("v2", "works"); - - String result = OptionHelper.substVars(text, context); - assertEquals(expected, result); - } - - @Test - public void testSubstVarsSystemProperties() { - System.setProperty("v1", "if"); - System.setProperty("v2", "works"); - - String result = OptionHelper.substVars(text, context); - assertEquals(expected, result); - - System.clearProperty("v1"); - System.clearProperty("v2"); - } - - @Test - public void testSubstVarsWithDefault() { - context.putProperty("v1", "if"); - String textWithDefault = "Testing ${v1} variable substitution ${v2:-toto}"; - String resultWithDefault = "Testing if variable substitution toto"; - - String result = OptionHelper.substVars(textWithDefault, context); - assertEquals(resultWithDefault, result); - } - - @Test - public void testSubstVarsRecursive() { - context.putProperty("v1", "if"); - context.putProperty("v2", "${v3}"); - context.putProperty("v3", "works"); - - String result = OptionHelper.substVars(text, context); - assertEquals(expected, result); - } - -} +/** + * 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.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; + + +public class OptionHelperTest { + + String text = "Testing ${v1} variable substitution ${v2}"; + String expected = "Testing if variable substitution works"; + Context context = new ContextBase(); + Map secondaryMap; + + + + @Before + public void setUp() throws Exception { + secondaryMap = new HashMap(); + } + + @Test + public void testLiteral() { + String noSubst = "hello world"; + String result = OptionHelper.substVars(noSubst, context); + assertEquals(noSubst, result); + } + + @Test + public void testUndefinedValues() { + String withUndefinedValues = "${axyz}"; + + String result = OptionHelper.substVars(withUndefinedValues, context); + assertEquals("axyz"+OptionHelper._IS_UNDEFINED, result); + } + + @Test + public void testSubstVarsVariableNotClosed() { + String noSubst = "testing if ${v1 works"; + + try { + @SuppressWarnings("unused") + String result = OptionHelper.substVars(noSubst, context); + fail(); + } catch (IllegalArgumentException e) { + //ok + } + } + @Test + public void testSubstVarsContextOnly() { + context.putProperty("v1", "if"); + context.putProperty("v2", "works"); + + String result = OptionHelper.substVars(text, context); + assertEquals(expected, result); + } + + @Test + public void testSubstVarsSystemProperties() { + System.setProperty("v1", "if"); + System.setProperty("v2", "works"); + + String result = OptionHelper.substVars(text, context); + assertEquals(expected, result); + + System.clearProperty("v1"); + System.clearProperty("v2"); + } + + @Test + public void testSubstVarsWithDefault() { + context.putProperty("v1", "if"); + String textWithDefault = "Testing ${v1} variable substitution ${v2:-toto}"; + String resultWithDefault = "Testing if variable substitution toto"; + + String result = OptionHelper.substVars(textWithDefault, context); + assertEquals(resultWithDefault, result); + } + + @Test + public void testSubstVarsRecursive() { + context.putProperty("v1", "if"); + context.putProperty("v2", "${v3}"); + context.putProperty("v3", "works"); + + String result = OptionHelper.substVars(text, context); + assertEquals(expected, result); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/util/PackageTest.java index cd532cd3bc3b8a2dd93d695dfb291a4008df9679..74630a56f580093f3553e1732c554cefb2a6ec50 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/PackageTest.java @@ -1,30 +1,30 @@ -/** - * 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.util; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({ - DurationTest.class, - FileSizeTest.class, - FileUtilTest.class, - OptionHelperTest.class, - StatusPrinterTest.class, - TimeUtilTest.class, - ContentTypeUtilTest.class}) -public class PackageTest { -} +/** + * 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.util; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ + DurationTest.class, + FileSizeTest.class, + FileUtilTest.class, + OptionHelperTest.class, + StatusPrinterTest.class, + TimeUtilTest.class, + ContentTypeUtilTest.class}) +public class PackageTest { +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/StatusPrinterTest.java b/logback-core/src/test/java/ch/qos/logback/core/util/StatusPrinterTest.java index 16adc3bae4694326c59cfed33b3f9541fdbf2bd2..f79105301ece814567ddae103a1c6fb0935083b0 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/StatusPrinterTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/StatusPrinterTest.java @@ -1,120 +1,120 @@ -/** - * 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.util; - -import static org.junit.Assert.*; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.qos.logback.core.Context; -import ch.qos.logback.core.ContextBase; -import ch.qos.logback.core.status.ErrorStatus; -import ch.qos.logback.core.status.InfoStatus; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.status.WarnStatus; - -public class StatusPrinterTest { - - ByteArrayOutputStream outputStream; - PrintStream ps; - - @Before - public void setUp() throws Exception { - outputStream = new ByteArrayOutputStream(); - ps = new PrintStream(outputStream); - StatusPrinter.setPrintStream(ps); - } - - @After - public void tearDown() throws Exception { - StatusPrinter.setPrintStream(System.out); - ps = null; - outputStream = null; - } - - @Test - public void testBasic() { - Context context = new ContextBase(); - context.getStatusManager().add(new InfoStatus("test", this)); - StatusPrinter.print(context); - String result = outputStream.toString(); - assertTrue(result.contains("|-INFO in "+this.getClass().getName())); - } - - @Test - public void testNested() { - Status s0 = new ErrorStatus("test0", this); - Status s1 = new InfoStatus("test1", this); - Status s11 = new InfoStatus("test11", this); - Status s12 = new InfoStatus("test12", this); - s1.add(s11); - s1.add(s12); - - Status s2 = new InfoStatus("test2", this); - Status s21 = new InfoStatus("test21", this); - Status s211 = new WarnStatus("test211", this); - - Status s22 = new InfoStatus("test22", this); - s2.add(s21); - s2.add(s22); - s21.add(s211); - - - Context context = new ContextBase(); - context.getStatusManager().add(s0); - context.getStatusManager().add(s1); - context.getStatusManager().add(s2); - - StatusPrinter.print(context); - String result = outputStream.toString(); - assertTrue(result.contains("+ INFO in "+this.getClass().getName())); - assertTrue(result.contains("+ WARN in "+this.getClass().getName())); - assertTrue(result.contains(" |-WARN in "+this.getClass().getName())); - } - - @Test - public void testWithException() { - Status s0 = new ErrorStatus("test0", this); - Status s1 = new InfoStatus("test1", this, new Exception("testEx")); - Status s11 = new InfoStatus("test11", this); - Status s12 = new InfoStatus("test12", this); - s1.add(s11); - s1.add(s12); - - Status s2 = new InfoStatus("test2", this); - Status s21 = new InfoStatus("test21", this); - Status s211 = new WarnStatus("test211", this); - - Status s22 = new InfoStatus("test22", this); - s2.add(s21); - s2.add(s22); - s21.add(s211); - - Context context = new ContextBase(); - context.getStatusManager().add(s0); - context.getStatusManager().add(s1); - context.getStatusManager().add(s2); - StatusPrinter.print(context); - String result = outputStream.toString(); - assertTrue(result.contains("|-ERROR in "+this.getClass().getName())); - assertTrue(result.contains("+ INFO in "+this.getClass().getName())); - assertTrue(result.contains("ch.qos.logback.core.util.StatusPrinterTest.testWithException")); - } - -} +/** + * 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.util; + +import static org.junit.Assert.*; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.WarnStatus; + +public class StatusPrinterTest { + + ByteArrayOutputStream outputStream; + PrintStream ps; + + @Before + public void setUp() throws Exception { + outputStream = new ByteArrayOutputStream(); + ps = new PrintStream(outputStream); + StatusPrinter.setPrintStream(ps); + } + + @After + public void tearDown() throws Exception { + StatusPrinter.setPrintStream(System.out); + ps = null; + outputStream = null; + } + + @Test + public void testBasic() { + Context context = new ContextBase(); + context.getStatusManager().add(new InfoStatus("test", this)); + StatusPrinter.print(context); + String result = outputStream.toString(); + assertTrue(result.contains("|-INFO in "+this.getClass().getName())); + } + + @Test + public void testNested() { + Status s0 = new ErrorStatus("test0", this); + Status s1 = new InfoStatus("test1", this); + Status s11 = new InfoStatus("test11", this); + Status s12 = new InfoStatus("test12", this); + s1.add(s11); + s1.add(s12); + + Status s2 = new InfoStatus("test2", this); + Status s21 = new InfoStatus("test21", this); + Status s211 = new WarnStatus("test211", this); + + Status s22 = new InfoStatus("test22", this); + s2.add(s21); + s2.add(s22); + s21.add(s211); + + + Context context = new ContextBase(); + context.getStatusManager().add(s0); + context.getStatusManager().add(s1); + context.getStatusManager().add(s2); + + StatusPrinter.print(context); + String result = outputStream.toString(); + assertTrue(result.contains("+ INFO in "+this.getClass().getName())); + assertTrue(result.contains("+ WARN in "+this.getClass().getName())); + assertTrue(result.contains(" |-WARN in "+this.getClass().getName())); + } + + @Test + public void testWithException() { + Status s0 = new ErrorStatus("test0", this); + Status s1 = new InfoStatus("test1", this, new Exception("testEx")); + Status s11 = new InfoStatus("test11", this); + Status s12 = new InfoStatus("test12", this); + s1.add(s11); + s1.add(s12); + + Status s2 = new InfoStatus("test2", this); + Status s21 = new InfoStatus("test21", this); + Status s211 = new WarnStatus("test211", this); + + Status s22 = new InfoStatus("test22", this); + s2.add(s21); + s2.add(s22); + s21.add(s211); + + Context context = new ContextBase(); + context.getStatusManager().add(s0); + context.getStatusManager().add(s1); + context.getStatusManager().add(s2); + StatusPrinter.print(context); + String result = outputStream.toString(); + assertTrue(result.contains("|-ERROR in "+this.getClass().getName())); + assertTrue(result.contains("+ INFO in "+this.getClass().getName())); + assertTrue(result.contains("ch.qos.logback.core.util.StatusPrinterTest.testWithException")); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/TeeOutputStream.java b/logback-core/src/test/java/ch/qos/logback/core/util/TeeOutputStream.java index 20fb463a6cf1119e11cfaa75bfb26523842f4911..3c18cc2e8a47c6b40176571810bfadd0cec411b6 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/TeeOutputStream.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/TeeOutputStream.java @@ -1,52 +1,52 @@ -/** - * 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.util; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; - -/** - * This stream writes its output to the target PrintStream supplied to its - * constructor. At the same time, all the available bytes are collected and - * returned by the toString() method. - * - * @author Ceki Gulcu - */ -public class TeeOutputStream extends OutputStream { - - final PrintStream targetPS; - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - public TeeOutputStream(PrintStream targetPS) { - // allow for null arguments - this.targetPS = targetPS; - } - - public void write(int b) throws IOException { - baos.write(b); - if(targetPS != null) { - targetPS.write(b); - } - } - - public String toString() { - return baos.toString(); - } - - public byte[] toByteArray() { - return baos.toByteArray(); - } -} +/** + * 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.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; + +/** + * This stream writes its output to the target PrintStream supplied to its + * constructor. At the same time, all the available bytes are collected and + * returned by the toString() method. + * + * @author Ceki Gulcu + */ +public class TeeOutputStream extends OutputStream { + + final PrintStream targetPS; + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + public TeeOutputStream(PrintStream targetPS) { + // allow for null arguments + this.targetPS = targetPS; + } + + public void write(int b) throws IOException { + baos.write(b); + if(targetPS != null) { + targetPS.write(b); + } + } + + public String toString() { + return baos.toString(); + } + + public byte[] toByteArray() { + return baos.toByteArray(); + } +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/TimeUtilTest.java b/logback-core/src/test/java/ch/qos/logback/core/util/TimeUtilTest.java index c4c353d8831fbffa69075a794d340ab3a4e77c23..c88bb3c79928f046c0606da9e415417096851511 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/TimeUtilTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/TimeUtilTest.java @@ -1,123 +1,123 @@ -/** - * 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.util; - -import static org.junit.Assert.assertEquals; - -import java.util.Calendar; -import java.util.Date; -import java.util.TimeZone; - -import org.junit.Test; - -public class TimeUtilTest { - - @Test - public void testSecond() { - // Mon Nov 20 18:05:17,522 CET 2006 - long now = 1164042317522L; - // Mon Nov 20 18:05:18,000 CET 2006 - long expected = 1164042318000L; - long computed = TimeUtil.computeStartOfNextSecond(now); - assertEquals(expected - now, 478); - assertEquals(expected, computed); - } - - @Test - public void testMinute() { - // Mon Nov 20 18:05:17,522 CET 2006 - long now = 1164042317522L; - // Mon Nov 20 18:06:00 CET 2006 - long expected = 1164042360000L; - - long computed = TimeUtil.computeStartOfNextMinute(now); - assertEquals(expected - now, 1000 * 42 + 478); - assertEquals(expected, computed); - } - - @Test - public void testHour() { - // Mon Nov 20 18:05:17,522 GMT 2006 - long now = 1164045917522L; - now = correctBasedOnTimeZone(now); - // Mon Nov 20 19:00:00 GMT 2006 - long expected = 1164049200000L; - expected = correctBasedOnTimeZone(expected); - - long computed = TimeUtil.computeStartOfNextHour(now); - assertEquals(expected - now, 1000 * (42 + 60 * 54) + 478); - assertEquals(expected, computed); - } - - @Test - public void testDay() { - // Mon Nov 20 18:05:17 GMT 2006 - long now = 1164045917522L; - now = correctBasedOnTimeZone(now); - // Tue Nov 21 00:00:00 GMT 2006 - long expected = 1164067200000L; - expected = correctBasedOnTimeZone(expected); - long computed = TimeUtil.computeStartOfNextDay(now); - - assertEquals(expected - now, 1000 * (3600 * 5 + 60 * 54 + 42) + 478); - assertEquals(expected, computed); - } - - @Test - public void testWeek() { - // Mon Nov 20 18:05:17 GMT 2006 - long now = 1164045917522L; - now = correctBasedOnTimeZone(now); - // Sun Nov 26 00:00:00 GMT 2006 - long expected = 1164499200000L; - expected = correctBasedOnTimeZone(expected); - - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(now)); - - int dayOffset = cal.getFirstDayOfWeek() - Calendar.SUNDAY; - if (dayOffset != 0) { - expected += 24L * 3600 * 1000 * (cal.getFirstDayOfWeek() - Calendar.SUNDAY); - } - - long computed = TimeUtil.computeStartOfNextWeek(now); - // System.out.println("now "+new Date(now)); - // System.out.println("computed "+new Date(computed)); - // System.out.println("expected "+new Date(expected)); - assertEquals(expected - now, - 1000 * (3600 * (5 + 24 * (5 + dayOffset)) + 60 * 54 + 42) + 478); - assertEquals(expected, computed); - } - - @Test - public void testMonth() { - // Mon Nov 20 18:05:17 GMT 2006 - long now = 1164045917522L; - now = correctBasedOnTimeZone(now); - // Fri Dec 01 00:00:00 GMT 2006 - long expected = 1164931200000L; - expected = correctBasedOnTimeZone(expected); - - long computed = TimeUtil.computeStartOfNextMonth(now); - assertEquals(expected - now, - 1000 * (3600 * (5 + 24 * 10) + 60 * 54 + 42) + 478); - assertEquals(expected, computed); - } - - private long correctBasedOnTimeZone(long gmtLong) { - int offset = TimeZone.getDefault().getRawOffset(); - return gmtLong - offset; - } - -} +/** + * 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.util; + +import static org.junit.Assert.assertEquals; + +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +import org.junit.Test; + +public class TimeUtilTest { + + @Test + public void testSecond() { + // Mon Nov 20 18:05:17,522 CET 2006 + long now = 1164042317522L; + // Mon Nov 20 18:05:18,000 CET 2006 + long expected = 1164042318000L; + long computed = TimeUtil.computeStartOfNextSecond(now); + assertEquals(expected - now, 478); + assertEquals(expected, computed); + } + + @Test + public void testMinute() { + // Mon Nov 20 18:05:17,522 CET 2006 + long now = 1164042317522L; + // Mon Nov 20 18:06:00 CET 2006 + long expected = 1164042360000L; + + long computed = TimeUtil.computeStartOfNextMinute(now); + assertEquals(expected - now, 1000 * 42 + 478); + assertEquals(expected, computed); + } + + @Test + public void testHour() { + // Mon Nov 20 18:05:17,522 GMT 2006 + long now = 1164045917522L; + now = correctBasedOnTimeZone(now); + // Mon Nov 20 19:00:00 GMT 2006 + long expected = 1164049200000L; + expected = correctBasedOnTimeZone(expected); + + long computed = TimeUtil.computeStartOfNextHour(now); + assertEquals(expected - now, 1000 * (42 + 60 * 54) + 478); + assertEquals(expected, computed); + } + + @Test + public void testDay() { + // Mon Nov 20 18:05:17 GMT 2006 + long now = 1164045917522L; + now = correctBasedOnTimeZone(now); + // Tue Nov 21 00:00:00 GMT 2006 + long expected = 1164067200000L; + expected = correctBasedOnTimeZone(expected); + long computed = TimeUtil.computeStartOfNextDay(now); + + assertEquals(expected - now, 1000 * (3600 * 5 + 60 * 54 + 42) + 478); + assertEquals(expected, computed); + } + + @Test + public void testWeek() { + // Mon Nov 20 18:05:17 GMT 2006 + long now = 1164045917522L; + now = correctBasedOnTimeZone(now); + // Sun Nov 26 00:00:00 GMT 2006 + long expected = 1164499200000L; + expected = correctBasedOnTimeZone(expected); + + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + + int dayOffset = cal.getFirstDayOfWeek() - Calendar.SUNDAY; + if (dayOffset != 0) { + expected += 24L * 3600 * 1000 * (cal.getFirstDayOfWeek() - Calendar.SUNDAY); + } + + long computed = TimeUtil.computeStartOfNextWeek(now); + // System.out.println("now "+new Date(now)); + // System.out.println("computed "+new Date(computed)); + // System.out.println("expected "+new Date(expected)); + assertEquals(expected - now, + 1000 * (3600 * (5 + 24 * (5 + dayOffset)) + 60 * 54 + 42) + 478); + assertEquals(expected, computed); + } + + @Test + public void testMonth() { + // Mon Nov 20 18:05:17 GMT 2006 + long now = 1164045917522L; + now = correctBasedOnTimeZone(now); + // Fri Dec 01 00:00:00 GMT 2006 + long expected = 1164931200000L; + expected = correctBasedOnTimeZone(expected); + + long computed = TimeUtil.computeStartOfNextMonth(now); + assertEquals(expected - now, + 1000 * (3600 * (5 + 24 * 10) + 60 * 54 + 42) + 478); + assertEquals(expected, computed); + } + + private long correctBasedOnTimeZone(long gmtLong) { + int offset = TimeZone.getDefault().getRawOffset(); + return gmtLong - offset; + } + +} diff --git a/logback-core/src/test/resources/asResource/joran/inclusion/includedAsResource.xml b/logback-core/src/test/resources/asResource/joran/inclusion/includedAsResource.xml index 2823b440a22c26574ba693bdb917bf8f27d4b868..1b806871541aaa014b30717e37fa1138e223d6c7 100644 --- a/logback-core/src/test/resources/asResource/joran/inclusion/includedAsResource.xml +++ b/logback-core/src/test/resources/asResource/joran/inclusion/includedAsResource.xml @@ -1,9 +1,9 @@ - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/logback-core/src/test/resources/asResource/joran/propertyActionTest.properties b/logback-core/src/test/resources/asResource/joran/propertyActionTest.properties index 651e05ced391a2af618b242ebd5d3860be2a9471..f0b9e807c482187d9995c98e9fd90e7303ca3c3e 100644 --- a/logback-core/src/test/resources/asResource/joran/propertyActionTest.properties +++ b/logback-core/src/test/resources/asResource/joran/propertyActionTest.properties @@ -1,2 +1,2 @@ -r1=tata +r1=tata r2=toto \ No newline at end of file diff --git a/logback-core/src/test/witness/rolling/renaming.0 b/logback-core/src/test/witness/rolling/renaming.0 index aed561e27b39cf993d5fca6d86a2c61f9ea9f4a7..c6c20fe59b3fac2ef4e925c6a3580d4b8ae963a4 100644 --- a/logback-core/src/test/witness/rolling/renaming.0 +++ b/logback-core/src/test/witness/rolling/renaming.0 @@ -1 +1 @@ -Hello 0 +Hello 0 diff --git a/logback-core/src/test/witness/rolling/renaming.1 b/logback-core/src/test/witness/rolling/renaming.1 index f43170e8c921a6e75b4093b8ca5095f99e0ad425..ed5389e897051d4aeb5c80af91b09cc24ca6b36a 100644 --- a/logback-core/src/test/witness/rolling/renaming.1 +++ b/logback-core/src/test/witness/rolling/renaming.1 @@ -1 +1 @@ -Hello 1 +Hello 1 diff --git a/logback-core/src/test/witness/rolling/tbr-test4B.1 b/logback-core/src/test/witness/rolling/tbr-test4B.1 index 7ec5f321d683f745bfe7b010c46934d9adc557d3..aea23e872e1e590dea6093b86a618ccf18b6b547 100644 --- a/logback-core/src/test/witness/rolling/tbr-test4B.1 +++ b/logback-core/src/test/witness/rolling/tbr-test4B.1 @@ -1,2 +1,2 @@ -Hello---0 +Hello---0 Hello---1 \ No newline at end of file diff --git a/logback-core/src/test/witness/rolling/tbr-test4B.2 b/logback-core/src/test/witness/rolling/tbr-test4B.2 index 85cae8a4db8082e0641116f67bfb4c405a689548..c32a130bb54365c4923e03546456b8e6e9cc13c6 100644 --- a/logback-core/src/test/witness/rolling/tbr-test4B.2 +++ b/logback-core/src/test/witness/rolling/tbr-test4B.2 @@ -1 +1 @@ -Hello---2 +Hello---2 diff --git a/logback-core/src/test/witness/rolling/tbr-test4B.4 b/logback-core/src/test/witness/rolling/tbr-test4B.4 index 478633ac0a5fe9948ec43b9431f4b20a0cf8533a..759f5345f2b42da42560778b1c6ab2e6be7a916f 100644 --- a/logback-core/src/test/witness/rolling/tbr-test4B.4 +++ b/logback-core/src/test/witness/rolling/tbr-test4B.4 @@ -1,2 +1,2 @@ -World---1 +World---1 World---2 \ No newline at end of file diff --git a/logback-examples/pom.xml b/logback-examples/pom.xml index 01ea54cd292fb91f540703c7a3f26af926855442..b6a83d4793a8646b17442bcc7d58ac79d95188db 100644 --- a/logback-examples/pom.xml +++ b/logback-examples/pom.xml @@ -1,114 +1,114 @@ - - - - ch.qos.logback - logback-parent - 0.9.18-SNAPSHOT - - - 4.0.0 - - ch.qos.logback - logback-examples - ${parent.version} - jar - Logback Examples Module - - http://logback.qos.ch - - - - Eclipse Public License - v 1.0 - http://www.eclipse.org/legal/epl-v10.html - - - - GNU Lesser General Public License - http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - - - - - - - ch.qos.logback - logback-core - - - - ch.qos.logback - logback-classic - - - - ch.qos.logback - logback-access - - - - org.slf4j - slf4j-ext - ${slf4j.version} - - - - log4j - log4j - 1.2.14 - - - - - javax.servlet - servlet-api - compile - true - - - - - - - - src/main/resources - true - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - - - - - maven-antrun-plugin - - - package - - - - - Copying ${slf4jJAR} to lib/ - - - - - - - - run - - - - - - + + + + ch.qos.logback + logback-parent + 0.9.18-SNAPSHOT + + + 4.0.0 + + ch.qos.logback + logback-examples + ${parent.version} + jar + Logback Examples Module + + http://logback.qos.ch + + + + Eclipse Public License - v 1.0 + http://www.eclipse.org/legal/epl-v10.html + + + + GNU Lesser General Public License + http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html + + + + + + + ch.qos.logback + logback-core + + + + ch.qos.logback + logback-classic + + + + ch.qos.logback + logback-access + + + + org.slf4j + slf4j-ext + ${slf4j.version} + + + + log4j + log4j + 1.2.14 + + + + + javax.servlet + servlet-api + compile + true + + + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + maven-antrun-plugin + + + package + + + + + Copying ${slf4jJAR} to lib/ + + + + + + + + run + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter1/HelloWorld1.java b/logback-examples/src/main/java/chapter1/HelloWorld1.java index f1ee76dec07001b0a35370e80476f57be83cc2f4..10f2651ea577674b75ca7541eb1732e7e9968cfc 100644 --- a/logback-examples/src/main/java/chapter1/HelloWorld1.java +++ b/logback-examples/src/main/java/chapter1/HelloWorld1.java @@ -1,26 +1,26 @@ -/** - * 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 chapter1; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class HelloWorld1 { - - public static void main(String[] args) { - - Logger logger = LoggerFactory.getLogger("chapter1.HelloWorld1"); - logger.debug("Hello world."); - } -} +/** + * 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 chapter1; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HelloWorld1 { + + public static void main(String[] args) { + + Logger logger = LoggerFactory.getLogger("chapter1.HelloWorld1"); + logger.debug("Hello world."); + } +} diff --git a/logback-examples/src/main/java/chapter1/HelloWorld2.java b/logback-examples/src/main/java/chapter1/HelloWorld2.java index e326b2de464457e8f41fb61dab765423edf2886d..a67018f0579a9b088f7810fa83b858811962ceeb 100644 --- a/logback-examples/src/main/java/chapter1/HelloWorld2.java +++ b/logback-examples/src/main/java/chapter1/HelloWorld2.java @@ -1,31 +1,31 @@ -/** - * 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 chapter1; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.util.StatusPrinter; - -public class HelloWorld2 { - - public static void main(String[] args) { - Logger logger = LoggerFactory.getLogger("chapter1.HelloWorld2"); - logger.debug("Hello world."); - - // print internal state - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - StatusPrinter.print(lc); - } -} +/** + * 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 chapter1; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.util.StatusPrinter; + +public class HelloWorld2 { + + public static void main(String[] args) { + Logger logger = LoggerFactory.getLogger("chapter1.HelloWorld2"); + logger.debug("Hello world."); + + // print internal state + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + StatusPrinter.print(lc); + } +} diff --git a/logback-examples/src/main/java/chapter10/SimpleConfigurator.java b/logback-examples/src/main/java/chapter10/SimpleConfigurator.java index f7a21bae76045cae8cf1f100877c7413dd961569..398d72e2c4351dff9333910879e97e913de89614 100644 --- a/logback-examples/src/main/java/chapter10/SimpleConfigurator.java +++ b/logback-examples/src/main/java/chapter10/SimpleConfigurator.java @@ -1,64 +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 chapter10; - -import java.util.List; -import java.util.Map; - -import ch.qos.logback.core.joran.GenericConfigurator; -import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.action.ImplicitAction; -import ch.qos.logback.core.joran.spi.Interpreter; -import ch.qos.logback.core.joran.spi.Pattern; -import ch.qos.logback.core.joran.spi.RuleStore; - -/** - * A minimal configurator extending GenericConfigurator. - * - * @author Ceki Gücü - * - */ -public class SimpleConfigurator extends GenericConfigurator { - - final Map ruleMap; - final List iaList; - - public SimpleConfigurator(Map ruleMap) { - this(ruleMap, null); - } - - public SimpleConfigurator(Map ruleMap, List iaList) { - this.ruleMap = ruleMap; - this.iaList = iaList; - } - - @Override - protected void addInstanceRules(RuleStore rs) { - for (Pattern pattern : ruleMap.keySet()) { - Action action = ruleMap.get(pattern); - rs.addRule(pattern, action); - } - } - - @Override - protected void addImplicitRules(Interpreter interpreter) { - if(iaList == null) { - return; - } - for (ImplicitAction ia : iaList) { - interpreter.addImplicitAction(ia); - } - } - -} +/** + * 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 chapter10; + +import java.util.List; +import java.util.Map; + +import ch.qos.logback.core.joran.GenericConfigurator; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.action.ImplicitAction; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.joran.spi.RuleStore; + +/** + * A minimal configurator extending GenericConfigurator. + * + * @author Ceki Gücü + * + */ +public class SimpleConfigurator extends GenericConfigurator { + + final Map ruleMap; + final List iaList; + + public SimpleConfigurator(Map ruleMap) { + this(ruleMap, null); + } + + public SimpleConfigurator(Map ruleMap, List iaList) { + this.ruleMap = ruleMap; + this.iaList = iaList; + } + + @Override + protected void addInstanceRules(RuleStore rs) { + for (Pattern pattern : ruleMap.keySet()) { + Action action = ruleMap.get(pattern); + rs.addRule(pattern, action); + } + } + + @Override + protected void addImplicitRules(Interpreter interpreter) { + if(iaList == null) { + return; + } + for (ImplicitAction ia : iaList) { + interpreter.addImplicitAction(ia); + } + } + +} diff --git a/logback-examples/src/main/java/chapter10/calculator/calculator3.xml b/logback-examples/src/main/java/chapter10/calculator/calculator3.xml index f6d1f601a2577e9a26ebaf4a1c7b0cdf9e1d868d..5c19944324b3c5c1bbfa70fe6edad184d44297aa 100644 --- a/logback-examples/src/main/java/chapter10/calculator/calculator3.xml +++ b/logback-examples/src/main/java/chapter10/calculator/calculator3.xml @@ -1,4 +1,4 @@ - + - - - - - + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter3/sample3.xml b/logback-examples/src/main/java/chapter3/sample3.xml index 65d8e7001f3603f4f8ec53b32b432b68ff8618af..874d80f36e9b9fbc501879baba908720e1da4f50 100644 --- a/logback-examples/src/main/java/chapter3/sample3.xml +++ b/logback-examples/src/main/java/chapter3/sample3.xml @@ -1,21 +1,21 @@ - - - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - - - + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter3/sample4.xml b/logback-examples/src/main/java/chapter3/sample4.xml index 74ac7d44825b34339b08f95430cbb95e928fe73b..c9873d56c28cabcb02a9f744f89714006e4db684 100644 --- a/logback-examples/src/main/java/chapter3/sample4.xml +++ b/logback-examples/src/main/java/chapter3/sample4.xml @@ -1,19 +1,19 @@ - - - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter3/scan1.xml b/logback-examples/src/main/java/chapter3/scan1.xml index b3eea319b5ec2e2f4dfd2568f073bcef13353ad7..600b8e098849295da63a462cd1653b9eb3861c3e 100644 --- a/logback-examples/src/main/java/chapter3/scan1.xml +++ b/logback-examples/src/main/java/chapter3/scan1.xml @@ -1,15 +1,15 @@ - - - - - - - %d [%thread] %-5level %logger{36} - %msg%n - - - - - - - + + + + + + + %d [%thread] %-5level %logger{36} - %msg%n + + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter3/scan2.xml b/logback-examples/src/main/java/chapter3/scan2.xml index 25fe67973b89118c3903849e2b7008df9cdc605f..24369f2917bc71c5b42b333d4150844b6e8304d6 100644 --- a/logback-examples/src/main/java/chapter3/scan2.xml +++ b/logback-examples/src/main/java/chapter3/scan2.xml @@ -1,15 +1,15 @@ - - - - - - - %d [%thread] %-5level %logger{36} - %msg%n - - - - - - - + + + + + + + %d [%thread] %-5level %logger{36} - %msg%n + + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter3/variableSubstitution1.xml b/logback-examples/src/main/java/chapter3/variableSubstitution1.xml index 743f070daf5db228e599bdc38c5055c035a98524..ff6b80dad078a6bc8146345e7c626af3114c47ff 100644 --- a/logback-examples/src/main/java/chapter3/variableSubstitution1.xml +++ b/logback-examples/src/main/java/chapter3/variableSubstitution1.xml @@ -1,15 +1,15 @@ - - - - - - ${USER_HOME}/myApp.log - - %msg%n - - - - - - + + + + + + ${USER_HOME}/myApp.log + + %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter3/variableSubstitution2.xml b/logback-examples/src/main/java/chapter3/variableSubstitution2.xml index 86f41ee7b81b1770c00bad7c2fc1e7355138b3be..5faa695baa3a8afeed3f67b652ebe1973a55167d 100644 --- a/logback-examples/src/main/java/chapter3/variableSubstitution2.xml +++ b/logback-examples/src/main/java/chapter3/variableSubstitution2.xml @@ -1,13 +1,13 @@ - - - - ${USER_HOME}/myApp.log - - %msg%n - - - - - - + + + + ${USER_HOME}/myApp.log + + %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter3/variableSubstitution3.xml b/logback-examples/src/main/java/chapter3/variableSubstitution3.xml index c3dbf08c21b4854f831ab4418f2bc291ea1e11c9..481b477a0250639e66064f6362ab6d68c4b30d31 100644 --- a/logback-examples/src/main/java/chapter3/variableSubstitution3.xml +++ b/logback-examples/src/main/java/chapter3/variableSubstitution3.xml @@ -1,15 +1,15 @@ - - - - - - ${USER_HOME}/myApp.log - - %msg%n - - - - - - + + + + + + ${USER_HOME}/myApp.log + + %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter3/variableSubstitution4.xml b/logback-examples/src/main/java/chapter3/variableSubstitution4.xml index 0db3f31ed53e0c6b50ed6448b50d264de56ddfd1..2c056d07f7fff179a2ae2635d2ac7933a03d690d 100644 --- a/logback-examples/src/main/java/chapter3/variableSubstitution4.xml +++ b/logback-examples/src/main/java/chapter3/variableSubstitution4.xml @@ -1,15 +1,15 @@ - - - - - - ${destination}/myApp.log - - %msg%n - - - - - - + + + + + + ${destination}/myApp.log + + %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter3/variables2.properties b/logback-examples/src/main/java/chapter3/variables2.properties index d021f64b54f36fa4369afc66ca59995722bd914d..9c0b5523719ceecaba6e0253dbfe6279e1b063d6 100644 --- a/logback-examples/src/main/java/chapter3/variables2.properties +++ b/logback-examples/src/main/java/chapter3/variables2.properties @@ -1,3 +1,3 @@ -USER_HOME=/home/sebastien -fileName=myApp.log +USER_HOME=/home/sebastien +fileName=myApp.log destination=${USER_HOME}/${fileName} \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/ConfigurationTester.java b/logback-examples/src/main/java/chapter4/ConfigurationTester.java index ccca1dad7a980aa82123925b08d13a8331a20063..7403030a76d6fcb9eba5b122c153729f4b512d01 100644 --- a/logback-examples/src/main/java/chapter4/ConfigurationTester.java +++ b/logback-examples/src/main/java/chapter4/ConfigurationTester.java @@ -1,67 +1,67 @@ -/** - * 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 chapter4; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.util.StatusPrinter; -import chapter4.sub.sample.Bar; - -/** - * - * This class can be used to check the result of a configuration file. - *

- * When all the logback-core, logback-classic, logback-examples and their dependencies have been - * added to the ClassPath, one can launch this class using the following - * command: - *

- * java chapter4.ConfigurationTester - * chapter4/conf/name_of_the_configuration_file.xml - * - * @author Sébastien Pennec - */ -public class ConfigurationTester { - - public static void main(String[] args) throws InterruptedException { - Logger logger = (Logger) LoggerFactory.getLogger(ConfigurationTester.class); - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - - try { - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - lc.reset(); - configurator.doConfigure(args[0]); - } catch (JoranException je) { - je.printStackTrace(); - } - // After we've called Joran, let's print information about the - // internal status of logback - StatusPrinter.print(lc.getStatusManager()); - - logger.debug("**Hello {}", new Bar()); - MDC.put("testKey", "testValueFromMDC"); - MDC.put("testKey2", "value2"); - for (int i = 0; i < 10; i++) { - logger.debug("logging statement " + i); - Thread.sleep(1000); - } - Bar bar = new Bar(); - bar.createLoggingRequest(); - } -} +/** + * 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 chapter4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.StatusPrinter; +import chapter4.sub.sample.Bar; + +/** + * + * This class can be used to check the result of a configuration file. + *

+ * When all the logback-core, logback-classic, logback-examples and their dependencies have been + * added to the ClassPath, one can launch this class using the following + * command: + *

+ * java chapter4.ConfigurationTester + * chapter4/conf/name_of_the_configuration_file.xml + * + * @author Sébastien Pennec + */ +public class ConfigurationTester { + + public static void main(String[] args) throws InterruptedException { + Logger logger = (Logger) LoggerFactory.getLogger(ConfigurationTester.class); + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + + try { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + lc.reset(); + configurator.doConfigure(args[0]); + } catch (JoranException je) { + je.printStackTrace(); + } + // After we've called Joran, let's print information about the + // internal status of logback + StatusPrinter.print(lc.getStatusManager()); + + logger.debug("**Hello {}", new Bar()); + MDC.put("testKey", "testValueFromMDC"); + MDC.put("testKey2", "value2"); + for (int i = 0; i < 10; i++) { + logger.debug("logging statement " + i); + Thread.sleep(1000); + } + Bar bar = new Bar(); + bar.createLoggingRequest(); + } +} diff --git a/logback-examples/src/main/java/chapter4/CountingConsoleAppender.java b/logback-examples/src/main/java/chapter4/CountingConsoleAppender.java index a0308aff721cf337820a9f6b3d186277f7ce7120..fd29e5d2530d746a7d1797a85534471384e3c14c 100644 --- a/logback-examples/src/main/java/chapter4/CountingConsoleAppender.java +++ b/logback-examples/src/main/java/chapter4/CountingConsoleAppender.java @@ -1,56 +1,56 @@ -/** - * 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 chapter4; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; - - -public class CountingConsoleAppender extends AppenderBase { - static int DEFAULT_LIMIT = 10; - int counter = 0; - int limit = DEFAULT_LIMIT; - - public CountingConsoleAppender() { - } - - public void setLimit(int limit) { - this.limit = limit; - } - - public int getLimit() { - return limit; - } - - @Override - public void start() { - if (this.layout == null) { - addError("No layout set for the appender named ["+ name +"]."); - return; - } - - super.start(); - } - - public void append(ILoggingEvent event) { - if (counter >= limit) { - return; - } - // output the events as formatted by our layout - System.out.print(this.layout.doLayout(event)); - - // prepare for next event - counter++; - } -} +/** + * 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 chapter4; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; + + +public class CountingConsoleAppender extends AppenderBase { + static int DEFAULT_LIMIT = 10; + int counter = 0; + int limit = DEFAULT_LIMIT; + + public CountingConsoleAppender() { + } + + public void setLimit(int limit) { + this.limit = limit; + } + + public int getLimit() { + return limit; + } + + @Override + public void start() { + if (this.layout == null) { + addError("No layout set for the appender named ["+ name +"]."); + return; + } + + super.start(); + } + + public void append(ILoggingEvent event) { + if (counter >= limit) { + return; + } + // output the events as formatted by our layout + System.out.print(this.layout.doLayout(event)); + + // prepare for next event + counter++; + } +} diff --git a/logback-examples/src/main/java/chapter4/ExitWoes1.java b/logback-examples/src/main/java/chapter4/ExitWoes1.java index 1df809e8a8201e5daf1d21add8524c28072825bc..ebaf133a4aa686912f8e08902787487a57307d42 100644 --- a/logback-examples/src/main/java/chapter4/ExitWoes1.java +++ b/logback-examples/src/main/java/chapter4/ExitWoes1.java @@ -1,48 +1,48 @@ -/** - * 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 chapter4; - -import java.io.FileOutputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.WriterAppender; -import ch.qos.logback.core.layout.EchoLayout; - -public class ExitWoes1 { - - public static void main(String[] args) throws Exception { - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - lc.reset(); // we want to override the default-config. - WriterAppender writerAppender = new WriterAppender(); - writerAppender.setContext(lc); - writerAppender.setLayout(new EchoLayout()); - - OutputStream os = new FileOutputStream("exitWoes1.log"); - writerAppender.setWriter(new OutputStreamWriter(os)); - writerAppender.setImmediateFlush(false); - writerAppender.start(); - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - root.addAppender(writerAppender); - - Logger logger = lc.getLogger(ExitWoes1.class); - - logger.debug("Hello world."); - } +/** + * 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 chapter4; + +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.WriterAppender; +import ch.qos.logback.core.layout.EchoLayout; + +public class ExitWoes1 { + + public static void main(String[] args) throws Exception { + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + lc.reset(); // we want to override the default-config. + WriterAppender writerAppender = new WriterAppender(); + writerAppender.setContext(lc); + writerAppender.setLayout(new EchoLayout()); + + OutputStream os = new FileOutputStream("exitWoes1.log"); + writerAppender.setWriter(new OutputStreamWriter(os)); + writerAppender.setImmediateFlush(false); + writerAppender.start(); + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + root.addAppender(writerAppender); + + Logger logger = lc.getLogger(ExitWoes1.class); + + logger.debug("Hello world."); + } } \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/ExitWoes2.java b/logback-examples/src/main/java/chapter4/ExitWoes2.java index a853f65a708b7ea4efb244f08550964f993d9b15..a03d0abff269404061e7f9c15eb74f91d6212f2a 100644 --- a/logback-examples/src/main/java/chapter4/ExitWoes2.java +++ b/logback-examples/src/main/java/chapter4/ExitWoes2.java @@ -1,53 +1,53 @@ -/** - * 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 chapter4; - -import java.io.FileOutputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.WriterAppender; -import ch.qos.logback.core.layout.EchoLayout; -import ch.qos.logback.core.util.StatusPrinter; - -public class ExitWoes2 { - - public static void main(String[] args) throws Exception { - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - lc.reset();//this is to cancel default-config. - WriterAppender writerAppender = new WriterAppender(); - writerAppender.setContext(lc); - writerAppender.setLayout(new EchoLayout()); - - OutputStream os = new FileOutputStream("exitWoes2.log"); - writerAppender.setWriter(new OutputStreamWriter(os)); - writerAppender.setImmediateFlush(false); - writerAppender.start(); - Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); - root.addAppender(writerAppender); - - Logger logger = lc.getLogger(ExitWoes2.class); - - logger.debug("Hello world."); - - lc.stop(); - - StatusPrinter.print(lc); - } +/** + * 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 chapter4; + +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.WriterAppender; +import ch.qos.logback.core.layout.EchoLayout; +import ch.qos.logback.core.util.StatusPrinter; + +public class ExitWoes2 { + + public static void main(String[] args) throws Exception { + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + lc.reset();//this is to cancel default-config. + WriterAppender writerAppender = new WriterAppender(); + writerAppender.setContext(lc); + writerAppender.setLayout(new EchoLayout()); + + OutputStream os = new FileOutputStream("exitWoes2.log"); + writerAppender.setWriter(new OutputStreamWriter(os)); + writerAppender.setImmediateFlush(false); + writerAppender.start(); + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); + root.addAppender(writerAppender); + + Logger logger = lc.getLogger(ExitWoes2.class); + + logger.debug("Hello world."); + + lc.stop(); + + StatusPrinter.print(lc); + } } \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/IO.java b/logback-examples/src/main/java/chapter4/IO.java index fc91ecede4cf078415a8106a761b701c7356cc47..9010f7ec97c8427f6638f8d57fabecd6801c785f 100644 --- a/logback-examples/src/main/java/chapter4/IO.java +++ b/logback-examples/src/main/java/chapter4/IO.java @@ -1,178 +1,178 @@ -/** - * 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 chapter4; - -import org.slf4j.Logger; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.FileAppender; -import ch.qos.logback.core.layout.EchoLayout; - -public class IO extends Thread { - static String msgLong = "ABCDEGHIJKLMNOPQRSTUVWXYZabcdeghijklmnopqrstuvwxyz1234567890"; - static String msgShort = "Hello"; - static boolean scarceCPU; - static int numThreads; - static long l; - static boolean longMessage; - long len; - boolean buffered; - boolean immediateFlush; - Logger logger; - LoggerContext context; - double throughput; - - public IO(boolean _buffered, boolean _immediateFlush, long _len) { - this.len = _len; - this.buffered = _buffered; - this.immediateFlush = _immediateFlush; - context = new LoggerContext(); - logger = context.getLogger("logger-" + getName()); - - // A FileAppender is created according to the buffering and - // immediate flush setting of this IO instance. - FileAppender fa = new FileAppender(); - - if (longMessage) { - PatternLayout pa = new PatternLayout(); - pa.setPattern("%r %5p %c [%t] - %m%n"); - fa.setLayout(pa); - } else { - fa.setLayout(new EchoLayout()); - } - - fa.setFile(getName() + ".log"); - fa.setAppend(false); - fa.setImmediateFlush(immediateFlush); - fa.setBufferedIO(buffered); - fa.setContext(context); - fa.start(); - - } - - public static void main(String[] argv) throws Exception { - if (argv.length != 4) { - usage("Wrong number of arguments."); - } - - l = Integer.parseInt(argv[0]); - numThreads = Integer.parseInt(argv[1]); - scarceCPU = "true".equalsIgnoreCase(argv[2]); - longMessage = "long".equalsIgnoreCase(argv[3]); - - // ---------------------------------------------------- - // first test with unbuffered IO and immediate flushing - perfCase(false, true, l); - - // ---------------------------------------------------- - // Second test with unbuffered IO and no immediate flushing - perfCase(false, false, l); - - // ---------------------------------------------------- - // Third test with buffered IO and no immediate flushing - perfCase(true, false, l); - - // There is no fourth test as buffered IO and immediate flushing - // do not make sense. - } - - static void usage(String msg) { - System.err.println(msg); - System.err.println("Usage: java " + IO.class.getName() + - " runLength numThreads scarceCPU (short|long)\n" + - " runLength (integer) the number of logs to generate perthread\n" + - " numThreads (integer) the number of threads.\n" + - " scarceCPU (boolean) if true an additional CPU intensive thread is created\n" + - " (short|long) length of log messages."); - System.exit(1); - } - - static void perfCase(boolean buffered, boolean immediateFlush, long len) - throws Exception { - IO[] threads = new IO[numThreads]; - Counter counterThread = null; - - if (scarceCPU) { - counterThread = new Counter(); - counterThread.start(); - } - - // First create the threads - for (int i = 0; i < numThreads; i++) { - threads[i] = new IO(buffered, immediateFlush, len); - } - - // then start them - for (int i = 0; i < numThreads; i++) { - threads[i].start(); - } - - // wait for them to stop, compute the average throughput - double sum = 0; - - for (int i = 0; i < numThreads; i++) { - threads[i].join(); - sum += threads[i].throughput; - } - - if (scarceCPU) { - // setting the interrupted field will cause counterThread to stop - counterThread.interrupted = true; - counterThread.join(); - } - - System.out.println("On average throughput of " + (sum / numThreads)*1000 + - " logs per microsecond."); - System.out.println("------------------------------------------------"); - } - - public void run() { - String msg = msgShort; - - if (longMessage) { - msg = msgLong; - } - - long before = System.nanoTime(); - - for (int i = 0; i < len; i++) { - logger.debug(msg); - } - - throughput = (len * 1.0) / (System.nanoTime() - before); - System.out.println(getName() + ", buffered: " + buffered + - ", immediateFlush: " + immediateFlush + ", throughput: " + throughput + - " logs per nanosecond."); - } -} - - -class Counter extends Thread { - public boolean interrupted = false; - public double counter = 0; - - public void run() { - long before = System.nanoTime(); - - while (!interrupted) { - counter += 1.0; - } - - double tput = (counter * 1.0) / (System.nanoTime() - before); - System.out.println("Counter thread " + getName() + - " incremented counter by " + tput + " per nanosecond."); - } -} +/** + * 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 chapter4; + +import org.slf4j.Logger; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.layout.EchoLayout; + +public class IO extends Thread { + static String msgLong = "ABCDEGHIJKLMNOPQRSTUVWXYZabcdeghijklmnopqrstuvwxyz1234567890"; + static String msgShort = "Hello"; + static boolean scarceCPU; + static int numThreads; + static long l; + static boolean longMessage; + long len; + boolean buffered; + boolean immediateFlush; + Logger logger; + LoggerContext context; + double throughput; + + public IO(boolean _buffered, boolean _immediateFlush, long _len) { + this.len = _len; + this.buffered = _buffered; + this.immediateFlush = _immediateFlush; + context = new LoggerContext(); + logger = context.getLogger("logger-" + getName()); + + // A FileAppender is created according to the buffering and + // immediate flush setting of this IO instance. + FileAppender fa = new FileAppender(); + + if (longMessage) { + PatternLayout pa = new PatternLayout(); + pa.setPattern("%r %5p %c [%t] - %m%n"); + fa.setLayout(pa); + } else { + fa.setLayout(new EchoLayout()); + } + + fa.setFile(getName() + ".log"); + fa.setAppend(false); + fa.setImmediateFlush(immediateFlush); + fa.setBufferedIO(buffered); + fa.setContext(context); + fa.start(); + + } + + public static void main(String[] argv) throws Exception { + if (argv.length != 4) { + usage("Wrong number of arguments."); + } + + l = Integer.parseInt(argv[0]); + numThreads = Integer.parseInt(argv[1]); + scarceCPU = "true".equalsIgnoreCase(argv[2]); + longMessage = "long".equalsIgnoreCase(argv[3]); + + // ---------------------------------------------------- + // first test with unbuffered IO and immediate flushing + perfCase(false, true, l); + + // ---------------------------------------------------- + // Second test with unbuffered IO and no immediate flushing + perfCase(false, false, l); + + // ---------------------------------------------------- + // Third test with buffered IO and no immediate flushing + perfCase(true, false, l); + + // There is no fourth test as buffered IO and immediate flushing + // do not make sense. + } + + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + IO.class.getName() + + " runLength numThreads scarceCPU (short|long)\n" + + " runLength (integer) the number of logs to generate perthread\n" + + " numThreads (integer) the number of threads.\n" + + " scarceCPU (boolean) if true an additional CPU intensive thread is created\n" + + " (short|long) length of log messages."); + System.exit(1); + } + + static void perfCase(boolean buffered, boolean immediateFlush, long len) + throws Exception { + IO[] threads = new IO[numThreads]; + Counter counterThread = null; + + if (scarceCPU) { + counterThread = new Counter(); + counterThread.start(); + } + + // First create the threads + for (int i = 0; i < numThreads; i++) { + threads[i] = new IO(buffered, immediateFlush, len); + } + + // then start them + for (int i = 0; i < numThreads; i++) { + threads[i].start(); + } + + // wait for them to stop, compute the average throughput + double sum = 0; + + for (int i = 0; i < numThreads; i++) { + threads[i].join(); + sum += threads[i].throughput; + } + + if (scarceCPU) { + // setting the interrupted field will cause counterThread to stop + counterThread.interrupted = true; + counterThread.join(); + } + + System.out.println("On average throughput of " + (sum / numThreads)*1000 + + " logs per microsecond."); + System.out.println("------------------------------------------------"); + } + + public void run() { + String msg = msgShort; + + if (longMessage) { + msg = msgLong; + } + + long before = System.nanoTime(); + + for (int i = 0; i < len; i++) { + logger.debug(msg); + } + + throughput = (len * 1.0) / (System.nanoTime() - before); + System.out.println(getName() + ", buffered: " + buffered + + ", immediateFlush: " + immediateFlush + ", throughput: " + throughput + + " logs per nanosecond."); + } +} + + +class Counter extends Thread { + public boolean interrupted = false; + public double counter = 0; + + public void run() { + long before = System.nanoTime(); + + while (!interrupted) { + counter += 1.0; + } + + double tput = (counter * 1.0) / (System.nanoTime() - before); + System.out.println("Counter thread " + getName() + + " incremented counter by " + tput + " per nanosecond."); + } +} diff --git a/logback-examples/src/main/java/chapter4/conf/access/logback-DB.xml b/logback-examples/src/main/java/chapter4/conf/access/logback-DB.xml index 8fe017fdbb22899dc8d6ac19b29430c325a6ccbb..a3284022a522fb2bc1389b2a5653167b9d9765f2 100644 --- a/logback-examples/src/main/java/chapter4/conf/access/logback-DB.xml +++ b/logback-examples/src/main/java/chapter4/conf/access/logback-DB.xml @@ -1,14 +1,14 @@ - - - com.mysql.jdbc.Driver - jdbc:mysql://localhost:3306/logbackdb - logback - logback - - true - - + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/logbackdb + logback + logback + + true + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/conf/access/logback-SMTP.xml b/logback-examples/src/main/java/chapter4/conf/access/logback-SMTP.xml index ccbd87e239be44779301c7d1c1188dc9e71cd862..c1a6bb9498d4e62ea44295a668398142784bb608 100644 --- a/logback-examples/src/main/java/chapter4/conf/access/logback-SMTP.xml +++ b/logback-examples/src/main/java/chapter4/conf/access/logback-SMTP.xml @@ -1,20 +1,20 @@ - - - %h%l%u%t%r%s%b - - - - - url1.jsp - directory/url2.html - - - sender_email@host.com - mail.domain.com - recipient_email@host.com + + + %h%l%u%t%r%s%b + + + + + url1.jsp + directory/url2.html + + + sender_email@host.com + mail.domain.com + recipient_email@host.com diff --git a/logback-examples/src/main/java/chapter4/conf/logback-Console.xml b/logback-examples/src/main/java/chapter4/conf/logback-Console.xml index 243f5a697517ee932db8782160d6fad9e15efefc..5c2e94d7359d5ee5210d89e84b602b83b8e1c641 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-Console.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-Console.xml @@ -1,14 +1,14 @@ - - - - - %-4relative [%thread] %-5level - %msg %n - - - - - - - - + + + + + %-4relative [%thread] %-5level - %msg %n + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/conf/logback-HtmlToConsole.xml b/logback-examples/src/main/java/chapter4/conf/logback-HtmlToConsole.xml index d008c9ee400179d6d8722113e3b3538d66b9574d..c528bb927b15aa7a041a050317a2dfca322fad34 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-HtmlToConsole.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-HtmlToConsole.xml @@ -1,17 +1,17 @@ - - - - - - path_to_StyleFile.css - - %-4relative [%thread] %-5level - %msg%n - - - - - - - - + + + + + + path_to_StyleFile.css + + %-4relative [%thread] %-5level - %msg%n + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/conf/logback-JMSQueue.xml b/logback-examples/src/main/java/chapter4/conf/logback-JMSQueue.xml index 649ef6a66e922a2d47e79215bff1a455eacdeb9f..cb5be8908bbd5d082c1f281174eb83cd5f394a19 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-JMSQueue.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-JMSQueue.xml @@ -1,18 +1,18 @@ - - - - - org.apache.activemq.jndi.ActiveMQInitialContextFactory - - tcp://localhost:61616 - - ConnectionFactory - - MyQueue - - - - - + + + + + org.apache.activemq.jndi.ActiveMQInitialContextFactory + + tcp://localhost:61616 + + ConnectionFactory + + MyQueue + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/conf/logback-JMSTopic.xml b/logback-examples/src/main/java/chapter4/conf/logback-JMSTopic.xml index 6b5b67a45799457d3ac06c73e722f56141d8b93f..b6bb7782ca108b7c8096afafdd38428bcef1f9bc 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-JMSTopic.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-JMSTopic.xml @@ -1,18 +1,18 @@ - - - - - org.apache.activemq.jndi.ActiveMQInitialContextFactory - - tcp://localhost:61616 - - ConnectionFactory - - MyTopic - - - - - + + + + + org.apache.activemq.jndi.ActiveMQInitialContextFactory + + tcp://localhost:61616 + + ConnectionFactory + + MyTopic + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/conf/logback-MDC.xml b/logback-examples/src/main/java/chapter4/conf/logback-MDC.xml index b26f314bfd9a1715a7ce975f8062cc3a3e69c46c..cd26ef2d3ad69dc666dddbf4a3311994989e98b9 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-MDC.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-MDC.xml @@ -1,14 +1,14 @@ - - - - - %-4relative [%thread] %-5level %X{testKey} - %msg%n - - - - - - - - + + + + + %-4relative [%thread] %-5level %X{testKey} - %msg%n + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/conf/logback-PrudentTimeBasedRolling.xml b/logback-examples/src/main/java/chapter4/conf/logback-PrudentTimeBasedRolling.xml index 22562b2345751ad219dabe637c1c9e30cf071fcb..a8a71ae7cb3f5ee16105f253ea87c9b29bbe2dbe 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-PrudentTimeBasedRolling.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-PrudentTimeBasedRolling.xml @@ -1,19 +1,19 @@ - - - - - true - - logFile.%d{yyyy-MM-dd}.log - 30 - - - - %-4relative [%thread] %-5level %logger{35} - %msg%n - - - - - - + + + + + true + + logFile.%d{yyyy-MM-dd}.log + 30 + + + + %-4relative [%thread] %-5level %logger{35} - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/conf/logback-RollingFixedWindow.xml b/logback-examples/src/main/java/chapter4/conf/logback-RollingFixedWindow.xml index 377eb8a670fc713e5e4281b4419b5f0b4a15f7d5..9be0ce067e90a6ff2905547ac03051dd94ad37b6 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-RollingFixedWindow.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-RollingFixedWindow.xml @@ -1,21 +1,21 @@ - - - testFile.log - - testFile.%i.log.zip - 1 - 3 - - - - 5MB - - - %-4relative [%thread] %-5level %logger{35} - %msg%n - - - - - - + + + testFile.log + + testFile.%i.log.zip + 1 + 3 + + + + 5MB + + + %-4relative [%thread] %-5level %logger{35} - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/conf/logback-RollingSizeBased.xml b/logback-examples/src/main/java/chapter4/conf/logback-RollingSizeBased.xml index 51864e20263027580f86a605805684b916c46ec0..53d061e1218a921a438477e2af6c5d43efc21adc 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-RollingSizeBased.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-RollingSizeBased.xml @@ -1,24 +1,24 @@ - - - - test.log - - tests.%i.log.zip - 1 - 3 - - - - 1KB - - - %-4relative [%thread] %-5level %logger{35} - %msg%n - - - - - - - - + + + + test.log + + tests.%i.log.zip + 1 + 3 + + + + 1KB + + + %-4relative [%thread] %-5level %logger{35} - %msg%n + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/conf/logback-RollingTimeBased.xml b/logback-examples/src/main/java/chapter4/conf/logback-RollingTimeBased.xml index d5920b758f7a0d27d97e0b8157088f9f14f5770d..115575735f899af9909bcc73ec7bd3988a75db79 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-RollingTimeBased.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-RollingTimeBased.xml @@ -1,18 +1,18 @@ - - - logFile.log - - logFile.%d{yyyy-MM-dd}.log - - 30 - - - - %-4relative [%thread] %-5level %logger{35} - %msg%n - - - - - - + + + logFile.log + + logFile.%d{yyyy-MM-dd}.log + + 30 + + + + %-4relative [%thread] %-5level %logger{35} - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/conf/logback-SMTP.xml b/logback-examples/src/main/java/chapter4/conf/logback-SMTP.xml index f138d7fd50fa26f9a1d2320ccd0818ba8e3b8506..f9965e29183278bccfe270cdd913b3294206201a 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-SMTP.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-SMTP.xml @@ -1,20 +1,20 @@ - - - - - %-4relative [%thread] %-5level %class - %msg%n - - sender_email@host.ch - mail.host.ch - - Last Event: %-10logger %nopex - - recipient_email@host.ch - - - - - - - + + + + + %-4relative [%thread] %-5level %class - %msg%n + + sender_email@host.ch + mail.host.ch + + Last Event: %-10logger %nopex + + recipient_email@host.ch + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/conf/logback-SMTPWithHtml.xml b/logback-examples/src/main/java/chapter4/conf/logback-SMTPWithHtml.xml index b08c4c48a995cb0662f797b8a5a308342541d85c..d0718450fb23ddbbdbe291e5eb0e6789850bab4a 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-SMTPWithHtml.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-SMTPWithHtml.xml @@ -1,21 +1,21 @@ - - - - - %relative%thread%mdc%level%class%msg - - - sender_email@host.ch - mail.host.ch - - Last Event: %-10logger %nopex - - recipient_email@host.ch - - - - - - - + + + + + %relative%thread%mdc%level%class%msg + + + sender_email@host.ch + mail.host.ch + + Last Event: %-10logger %nopex + + recipient_email@host.ch + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/conf/logback-fileAppender.xml b/logback-examples/src/main/java/chapter4/conf/logback-fileAppender.xml index 5ff1753aad3180b1c4db03f11b696f5aa5bc1ce7..06d16630533d9f5c680d093e4b1ef26870fadaa1 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-fileAppender.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-fileAppender.xml @@ -1,15 +1,15 @@ - - - - testFile.log - true - - - %-4relative [%thread] %-5level %logger{35} - %msg%n - - - - - - + + + + testFile.log + true + + + %-4relative [%thread] %-5level %logger{35} - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/conf/logback-syslog.xml b/logback-examples/src/main/java/chapter4/conf/logback-syslog.xml index 81ad0e93b44ef286b7fad99e2c8fdbddd0c730c7..04c564a4bb62990bb0b53cfd47548b54fefdc50c 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-syslog.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-syslog.xml @@ -1,14 +1,14 @@ - - - - ${syslogHost} - ${facility} - %-4relative [%thread] %-5level - %msg - - - - - - - + + + + ${syslogHost} + ${facility} + %-4relative [%thread] %-5level - %msg + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/conf/logback-timestamp.xml b/logback-examples/src/main/java/chapter4/conf/logback-timestamp.xml index fc5b7ed31bb348b14e94cf37a7e470f367364ef8..1bcc4219637a2b322020fd00858f2c8b36dde102 100644 --- a/logback-examples/src/main/java/chapter4/conf/logback-timestamp.xml +++ b/logback-examples/src/main/java/chapter4/conf/logback-timestamp.xml @@ -1,20 +1,20 @@ - - - - - - - - log-${bySecond}.txt - - %logger{35} - %msg%n - - - - - - - + + + + + + + + log-${bySecond}.txt + + %logger{35} - %msg%n + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/conf/logbback-sizeAndTime.xml b/logback-examples/src/main/java/chapter4/conf/logbback-sizeAndTime.xml index 15a5d2e13ad7c74804053b31e1bfa89830c2b5d9..8e727090b60af0f505fdd91f7059ba50323ec989 100644 --- a/logback-examples/src/main/java/chapter4/conf/logbback-sizeAndTime.xml +++ b/logback-examples/src/main/java/chapter4/conf/logbback-sizeAndTime.xml @@ -1,26 +1,26 @@ - - - - ${randomOutputDir}z${testId} - - - ${randomOutputDir}${testId}-%d{yyyy-MM-dd_HH_mm_ss}.%i - - - ${sizeThreshold} - - - - %msg%n - - - - - - - - - + + + + ${randomOutputDir}z${testId} + + + ${randomOutputDir}${testId}-%d{yyyy-MM-dd_HH_mm_ss}.%i + + + ${sizeThreshold} + + + + %msg%n + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/countingConsole.xml b/logback-examples/src/main/java/chapter4/countingConsole.xml index 9fa11479ea774f8a80c36644ae6e0e8d1077f0c8..26d31681029f2e0a205842a2f6082cbec1410a7a 100644 --- a/logback-examples/src/main/java/chapter4/countingConsole.xml +++ b/logback-examples/src/main/java/chapter4/countingConsole.xml @@ -1,19 +1,19 @@ - - - - - - - - %date [%thread] %-5level %logger - %msg%n - - 5 - - - - - - - - - + + + + + + + + %date [%thread] %-5level %logger - %msg%n + + 5 + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/db/append-and-share-with-jndi.xml b/logback-examples/src/main/java/chapter4/db/append-and-share-with-jndi.xml index 1086cb89fa83809cc6b88dbae30ca6bf83cecb2c..313ce4260cb4647ac5b7681a25004f8d31305382 100644 --- a/logback-examples/src/main/java/chapter4/db/append-and-share-with-jndi.xml +++ b/logback-examples/src/main/java/chapter4/db/append-and-share-with-jndi.xml @@ -1,36 +1,36 @@ - - - - - - - - - - - - - - - ${serverName} - ${databaseName} - - - ${user} - ${password}> - - - - - - - - - - - + + + + + + + + + + + + + + + ${serverName} + ${databaseName} + + + ${user} + ${password}> + + + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource-and-pooling.xml b/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource-and-pooling.xml index c2dcbacab8914cb3dc450f1658cc6ed5f8e11842..fa262a7b1603cf94d123847208493a3db27d91ad 100644 --- a/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource-and-pooling.xml +++ b/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource-and-pooling.xml @@ -1,19 +1,19 @@ - - - - - - com.mysql.jdbc.Driver - jdbc:mysql://localhost:3306/logbackdb - logback - logback - - - - - - - + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/logbackdb + logback + logback + + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource.xml b/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource.xml index ac428675996cc6f6b71da4ca4bba4b36abcd1f99..db2f114830285453996e8f2c8bb33c18d2eb8064 100644 --- a/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource.xml +++ b/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource.xml @@ -1,21 +1,21 @@ - - - - - - - - ${serverName} - ${port$ - ${dbName} - ${user} - ${pass} - - - - - - - - + + + + + + + + ${serverName} + ${port$ + ${dbName} + ${user} + ${pass} + + + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-driverManager.xml b/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-driverManager.xml index 5e21c368c5204f5902d61fe65796acbafe33b1c4..476fb2bcf9c97060bfbebfdbfd6f39ab963c272a 100644 --- a/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-driverManager.xml +++ b/logback-examples/src/main/java/chapter4/db/append-toMySQL-with-driverManager.xml @@ -1,17 +1,17 @@ - - - - - - - com.mysql.jdbc.Driver - jdbc:mysql://host_name:3306/datebase_name - username - password - - - - - - - + + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://host_name:3306/datebase_name + username + password + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/db/append-with-c3p0.xml b/logback-examples/src/main/java/chapter4/db/append-with-c3p0.xml index 7289b120d428aa55acc9091c83b90c495c05e083..834f4d2bab376c5486da52e24dfc323e611a7ffb 100644 --- a/logback-examples/src/main/java/chapter4/db/append-with-c3p0.xml +++ b/logback-examples/src/main/java/chapter4/db/append-with-c3p0.xml @@ -1,33 +1,33 @@ - - - - - - - - ${driverClass} - ${url} - ${serverName} - ${databaseName} - ${user} - ${password} - - - - - - - - - - - - - + + + + + + + + ${driverClass} + ${url} + ${serverName} + ${databaseName} + ${user} + ${password} + + + + + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/db/append-with-datasource.xml b/logback-examples/src/main/java/chapter4/db/append-with-datasource.xml index dc1aeff7f04ca13f5c8a3d7ae1e550b3b6493e7f..6890ab9c77d8d210e9cf85881ef982adca54e56a 100644 --- a/logback-examples/src/main/java/chapter4/db/append-with-datasource.xml +++ b/logback-examples/src/main/java/chapter4/db/append-with-datasource.xml @@ -1,29 +1,29 @@ - - - - - - - - - - - ${serverName} - ${databaseName} - - - ${user} - ${password} - - - - - - - - - - + + + + + + + + + + + ${serverName} + ${databaseName} + + + ${user} + ${password} + + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/db/append-with-drivermanager.xml b/logback-examples/src/main/java/chapter4/db/append-with-drivermanager.xml index 980f37a230c9f24e19ea87bbe3ffcc30e25b6bc6..9487550eb2fdcf4854c8034dd487fa0c346a0b4a 100644 --- a/logback-examples/src/main/java/chapter4/db/append-with-drivermanager.xml +++ b/logback-examples/src/main/java/chapter4/db/append-with-drivermanager.xml @@ -1,20 +1,20 @@ - - - - - - - ${driverClass} - ${url} - ${user} - ${password} - - - - - - - - - + + + + + + + ${driverClass} + ${url} + ${user} + ${password} + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/db/append-with-pooled-datasource.xml b/logback-examples/src/main/java/chapter4/db/append-with-pooled-datasource.xml index 4eb1a2aef914b999d41a33d27cbada5264ed00d4..eb6fb09e5a4e2cc700ff7b0b28e1b9b278642aa0 100644 --- a/logback-examples/src/main/java/chapter4/db/append-with-pooled-datasource.xml +++ b/logback-examples/src/main/java/chapter4/db/append-with-pooled-datasource.xml @@ -1,32 +1,32 @@ - - - - - - - - - - - ${serverName} - ${databaseName} - ${user} - ${password} - - 10 - 10 - - - - - - - - - - - - + + + + + + + + + + + ${serverName} + ${databaseName} + ${user} + ${password} + + 10 + 10 + + + + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/mail/CounterBasedEvaluator.java b/logback-examples/src/main/java/chapter4/mail/CounterBasedEvaluator.java index 0f546f5d3e3a76b3319cf097b3ce9efd8f5d5bd6..f55aaf8904aa953789821c27a1682ccc8b7697db 100644 --- a/logback-examples/src/main/java/chapter4/mail/CounterBasedEvaluator.java +++ b/logback-examples/src/main/java/chapter4/mail/CounterBasedEvaluator.java @@ -1,63 +1,63 @@ -/** - * 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 chapter4.mail; - -import ch.qos.logback.core.boolex.EvaluationException; -import ch.qos.logback.core.boolex.EventEvaluator; -import ch.qos.logback.core.spi.ContextAwareBase; - -/** - * A simple EventEvaluator implementation that triggers email transmission after - * 1024 events regardless of event level. - */ -public class CounterBasedEvaluator extends ContextAwareBase implements EventEvaluator { - - static int LIMIT = 1024; - int counter = 0; - String name; - boolean started; - - public boolean evaluate(Object event) throws NullPointerException, - EvaluationException { - counter++; - - if (counter == LIMIT) { - counter = 0; - - return true; - } else { - return false; - } - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public boolean isStarted() { - return started; - } - - public void start() { - started = true; - } - - public void stop() { - started = false; - } -} +/** + * 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 chapter4.mail; + +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.spi.ContextAwareBase; + +/** + * A simple EventEvaluator implementation that triggers email transmission after + * 1024 events regardless of event level. + */ +public class CounterBasedEvaluator extends ContextAwareBase implements EventEvaluator { + + static int LIMIT = 1024; + int counter = 0; + String name; + boolean started; + + public boolean evaluate(Object event) throws NullPointerException, + EvaluationException { + counter++; + + if (counter == LIMIT) { + counter = 0; + + return true; + } else { + return false; + } + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isStarted() { + return started; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } +} diff --git a/logback-examples/src/main/java/chapter4/mail/EMail.java b/logback-examples/src/main/java/chapter4/mail/EMail.java index 7a6700d968dbd04882e98dadc73a1affb7ae9687..f2fc78e4f4e2bc8fa74b92263235842ae8a4b328 100644 --- a/logback-examples/src/main/java/chapter4/mail/EMail.java +++ b/logback-examples/src/main/java/chapter4/mail/EMail.java @@ -1,70 +1,70 @@ -/** - * 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 chapter4.mail; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.util.StatusPrinter; - - - -/** - * This application generates log messages in numbers specified by the - * user. See - * also configuration scripts rolling.properties and rolling.xml. - * */ -public class EMail { - static public void main(String[] args) throws Exception { - if (args.length != 2) { - usage("Wrong number of arguments."); - } - - int runLength = Integer.parseInt(args[0]); - String configFile = args[1]; - - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - JoranConfigurator configurator = new JoranConfigurator(); - lc.reset(); - configurator.setContext(lc); - configurator.doConfigure(configFile); - StatusPrinter.printInCaseOfErrorsOrWarnings(lc); - - Logger logger = LoggerFactory.getLogger(EMail.class); - - for (int i = 1; i <= runLength; i++) { - if ((i % 10) < 9) { - logger.debug("This is a debug message. Message number: " + i); - } else { - logger.warn("This is a warning message. Message number: " + i); - } - } - - logger.error("At last an error.", new Exception("Just testing")); - - StatusPrinter.printInCaseOfErrorsOrWarnings(lc); - } - - static void usage(String msg) { - System.err.println(msg); - System.err.println("Usage: java " + EMail.class.getName() + - " runLength configFile\n" + - " runLength (integer) the number of logs to generate\n" + - " configFile a logback configuration file in XML format." + - " XML files must have a '.xml' extension."); - System.exit(1); - } -} +/** + * 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 chapter4.mail; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.util.StatusPrinter; + + + +/** + * This application generates log messages in numbers specified by the + * user. See + * also configuration scripts rolling.properties and rolling.xml. + * */ +public class EMail { + static public void main(String[] args) throws Exception { + if (args.length != 2) { + usage("Wrong number of arguments."); + } + + int runLength = Integer.parseInt(args[0]); + String configFile = args[1]; + + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + JoranConfigurator configurator = new JoranConfigurator(); + lc.reset(); + configurator.setContext(lc); + configurator.doConfigure(configFile); + StatusPrinter.printInCaseOfErrorsOrWarnings(lc); + + Logger logger = LoggerFactory.getLogger(EMail.class); + + for (int i = 1; i <= runLength; i++) { + if ((i % 10) < 9) { + logger.debug("This is a debug message. Message number: " + i); + } else { + logger.warn("This is a warning message. Message number: " + i); + } + } + + logger.error("At last an error.", new Exception("Just testing")); + + StatusPrinter.printInCaseOfErrorsOrWarnings(lc); + } + + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + EMail.class.getName() + + " runLength configFile\n" + + " runLength (integer) the number of logs to generate\n" + + " configFile a logback configuration file in XML format." + + " XML files must have a '.xml' extension."); + System.exit(1); + } +} diff --git a/logback-examples/src/main/java/chapter4/mail/gmailSSL.xml b/logback-examples/src/main/java/chapter4/mail/gmailSSL.xml index 61f68db7d2e9ac8ba3f938cb55ae956f42a59f31..c6ccde166c1356c5ed3536044e18bfeb58073bff 100644 --- a/logback-examples/src/main/java/chapter4/mail/gmailSSL.xml +++ b/logback-examples/src/main/java/chapter4/mail/gmailSSL.xml @@ -1,22 +1,22 @@ - - - - smtp.gmail.com - 465 - true - YOUR_USERNAME@gmail.com - YOUR_GMAIL_PASSWORD - - EMAIL-DESTINATION - ANOTHER_EMAIL_DESTINATION - YOUR_USERNAME@gmail.com - TESTING: %logger{20} - %m - - %date %-5level %logger - %message%n - - - - - - - + + + + smtp.gmail.com + 465 + true + YOUR_USERNAME@gmail.com + YOUR_GMAIL_PASSWORD + + EMAIL-DESTINATION + ANOTHER_EMAIL_DESTINATION + YOUR_USERNAME@gmail.com + TESTING: %logger{20} - %m + + %date %-5level %logger - %message%n + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/mail/gmailSTARTTLS.xml b/logback-examples/src/main/java/chapter4/mail/gmailSTARTTLS.xml index e7520a1efcf8a64487823e3f38db20e94445c495..e1989500d1ee90e79eab84824083926bd702bdc1 100644 --- a/logback-examples/src/main/java/chapter4/mail/gmailSTARTTLS.xml +++ b/logback-examples/src/main/java/chapter4/mail/gmailSTARTTLS.xml @@ -1,21 +1,21 @@ - - - smtp.gmail.com - 587 - true - YOUR_USERNAME@gmail.com - YOUR_GMAIL_PASSWORD - - EMAIL-DESTINATION - ANOTHER_EMAIL_DESTINATION - YOUR_USERNAME@gmail.com - TESTING: %logger{20} - %m - - %date %-5level %logger - %message%n - - - - - - - + + + smtp.gmail.com + 587 + true + YOUR_USERNAME@gmail.com + YOUR_GMAIL_PASSWORD + + EMAIL-DESTINATION + ANOTHER_EMAIL_DESTINATION + YOUR_USERNAME@gmail.com + TESTING: %logger{20} - %m + + %date %-5level %logger - %message%n + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/mail/mail1.xml b/logback-examples/src/main/java/chapter4/mail/mail1.xml index 842a6533c3bef47369ab01059e099cb1f1c84428..dd162cc2065f8aa43fbff49982dfd67bb56e401b 100644 --- a/logback-examples/src/main/java/chapter4/mail/mail1.xml +++ b/logback-examples/src/main/java/chapter4/mail/mail1.xml @@ -1,17 +1,17 @@ - - - - ADDRESS-OF-YOUR-SMTP-HOST - EMAIL-DESTINATION - ANOTHER_EMAIL_DESTINATION - SENDER-EMAIL - TESTING: %logger{20} - %m - - %date %-5level %logger - %message%n - - - - - - - + + + + ADDRESS-OF-YOUR-SMTP-HOST + EMAIL-DESTINATION + ANOTHER_EMAIL_DESTINATION + SENDER-EMAIL + TESTING: %logger{20} - %m + + %date %-5level %logger - %message%n + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/mail/mail2.xml b/logback-examples/src/main/java/chapter4/mail/mail2.xml index 20a524916d9052ce08b907f1428ec61d3177d229..2754181fc27919be3f131ffc00a50c6434779624 100644 --- a/logback-examples/src/main/java/chapter4/mail/mail2.xml +++ b/logback-examples/src/main/java/chapter4/mail/mail2.xml @@ -1,17 +1,17 @@ - - - - - - ${smtpHost} - ${to} - ${from} - - - - - - - - - + + + + + + ${smtpHost} + ${to} + ${from} + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/mail/mail3.xml b/logback-examples/src/main/java/chapter4/mail/mail3.xml index 5d562ff665c639150401dfd5feda50b24aa9dba2..bda5873d676d6b5777100692c281b7b6760d0de5 100644 --- a/logback-examples/src/main/java/chapter4/mail/mail3.xml +++ b/logback-examples/src/main/java/chapter4/mail/mail3.xml @@ -1,24 +1,24 @@ - - - - - - - - - - - 1050 - ${smtpHost} - ${to} - ${from} - - - - - - - - - - + + + + + + + + + + + 1050 + ${smtpHost} + ${to} + ${from} + + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/sift/SiftExample.java b/logback-examples/src/main/java/chapter4/sift/SiftExample.java index 340641f8a56bda6e420079f29ee441906c2a04a4..ec2f3c45cdcce903d434a50bdcaecd14decc9927 100644 --- a/logback-examples/src/main/java/chapter4/sift/SiftExample.java +++ b/logback-examples/src/main/java/chapter4/sift/SiftExample.java @@ -1,55 +1,55 @@ -/** - * 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 chapter4.sift; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; - -public class SiftExample { - - public static void main(String[] args) throws JoranException { - if (args.length != 1) { - usage("Wrong number of arguments."); - } - - String configFile = args[0]; - - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - JoranConfigurator configurator = new JoranConfigurator(); - lc.reset(); - configurator.setContext(lc); - configurator.doConfigure(configFile); - - - Logger logger = LoggerFactory.getLogger(SiftExample.class); - logger.debug("Application started"); - - MDC.put("userid", "Alice"); - logger.debug("Alice says hello"); - - //StatusPrinter.print(lc); - } - - static void usage(String msg) { - System.err.println(msg); - System.err.println("Usage: java " + SiftExample.class.getName() - + " configFile\n" + " configFile a logback configuration file"); - System.exit(1); - } -} +/** + * 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 chapter4.sift; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; + +public class SiftExample { + + public static void main(String[] args) throws JoranException { + if (args.length != 1) { + usage("Wrong number of arguments."); + } + + String configFile = args[0]; + + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + JoranConfigurator configurator = new JoranConfigurator(); + lc.reset(); + configurator.setContext(lc); + configurator.doConfigure(configFile); + + + Logger logger = LoggerFactory.getLogger(SiftExample.class); + logger.debug("Application started"); + + MDC.put("userid", "Alice"); + logger.debug("Alice says hello"); + + //StatusPrinter.print(lc); + } + + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + SiftExample.class.getName() + + " configFile\n" + " configFile a logback configuration file"); + System.exit(1); + } +} diff --git a/logback-examples/src/main/java/chapter4/sift/access-siftingFile.xml b/logback-examples/src/main/java/chapter4/sift/access-siftingFile.xml index f579e3f05068e9c3bc04c1877bcc9efdf4ace752..9b15cdfc068712a09b721f8350fe73647e5099ae 100644 --- a/logback-examples/src/main/java/chapter4/sift/access-siftingFile.xml +++ b/logback-examples/src/main/java/chapter4/sift/access-siftingFile.xml @@ -1,22 +1,22 @@ - - - - - id - SESSION_ATTRIBUTE - username - NA - - - - byUser/${id}.log - - %h %l %u %t \"%r\" %s %b - - - - - - + + + + + id + SESSION_ATTRIBUTE + username + NA + + + + byUser/${id}.log + + %h %l %u %t \"%r\" %s %b + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter4/sift/byUserid.xml b/logback-examples/src/main/java/chapter4/sift/byUserid.xml index 997692c1d62595025d44e60a36285997a341aa06..9e9c9457f8394dbe85ad23aa7a3c7468227918d7 100644 --- a/logback-examples/src/main/java/chapter4/sift/byUserid.xml +++ b/logback-examples/src/main/java/chapter4/sift/byUserid.xml @@ -1,21 +1,21 @@ - - - - userid - unknown - - - - ${userid}.logs - false - - %d [%thread] %level %mdc %logger{35} - %msg%n - - - - - - - - - + + + + userid + unknown + + + + ${userid}.logs + false + + %d [%thread] %level %mdc %logger{35} - %msg%n + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/socket/SocketClient1.java b/logback-examples/src/main/java/chapter4/socket/SocketClient1.java index a3810a01decb2053bbb88fb6a19f32881cfa07b0..d31e120ec0a8451491c4d4e0428aa4dfe097e5ec 100644 --- a/logback-examples/src/main/java/chapter4/socket/SocketClient1.java +++ b/logback-examples/src/main/java/chapter4/socket/SocketClient1.java @@ -1,80 +1,80 @@ -/** - * 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 chapter4.socket; - - -import java.io.BufferedReader; -import java.io.InputStreamReader; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.net.SocketAppender; - - -/** - * This application uses a SocketAppender that log messages to a - * server on a host and port specified by the user. It waits for the - * user to type a message which will be sent to the server. - * */ -public class SocketClient1 { - static void usage(String msg) { - System.err.println(msg); - System.err.println("Usage: java " + SocketClient1.class.getName() + - " hostname port\n" + " hostname the name of the remote log server\n" + - " port (integer) the port number of the server\n"); - System.exit(1); - } - - static public void main(String[] args) throws Exception { - if (args.length != 2) { - usage("Wrong number of arguments."); - } - - String hostName = args[0]; - int port = Integer.parseInt(args[1]); - - // Create a SocketAppender connected to hostname:port with a - // reconnection delay of 10000 seconds. - SocketAppender socketAppender = new SocketAppender(); - socketAppender.setRemoteHost(hostName); - socketAppender.setPort(port); - socketAppender.setReconnectionDelay(10000); - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - socketAppender.setContext(lc); - - // SocketAppender options become active only after the execution - // of the next statement. - socketAppender.start(); - - Logger logger = (Logger) LoggerFactory.getLogger(SocketClient1.class); - logger.addAppender(socketAppender); - - BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); - - while (true) { - System.out.println("Type a message to send to log server at " + hostName + - ":" + port + ". Type 'q' to quit."); - - String s = reader.readLine(); - - if (s.equals("q")) { - break; - } else { - logger.debug(s); - } - } - } -} +/** + * 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 chapter4.socket; + + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.net.SocketAppender; + + +/** + * This application uses a SocketAppender that log messages to a + * server on a host and port specified by the user. It waits for the + * user to type a message which will be sent to the server. + * */ +public class SocketClient1 { + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + SocketClient1.class.getName() + + " hostname port\n" + " hostname the name of the remote log server\n" + + " port (integer) the port number of the server\n"); + System.exit(1); + } + + static public void main(String[] args) throws Exception { + if (args.length != 2) { + usage("Wrong number of arguments."); + } + + String hostName = args[0]; + int port = Integer.parseInt(args[1]); + + // Create a SocketAppender connected to hostname:port with a + // reconnection delay of 10000 seconds. + SocketAppender socketAppender = new SocketAppender(); + socketAppender.setRemoteHost(hostName); + socketAppender.setPort(port); + socketAppender.setReconnectionDelay(10000); + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + socketAppender.setContext(lc); + + // SocketAppender options become active only after the execution + // of the next statement. + socketAppender.start(); + + Logger logger = (Logger) LoggerFactory.getLogger(SocketClient1.class); + logger.addAppender(socketAppender); + + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + + while (true) { + System.out.println("Type a message to send to log server at " + hostName + + ":" + port + ". Type 'q' to quit."); + + String s = reader.readLine(); + + if (s.equals("q")) { + break; + } else { + logger.debug(s); + } + } + } +} diff --git a/logback-examples/src/main/java/chapter4/socket/SocketClient2.java b/logback-examples/src/main/java/chapter4/socket/SocketClient2.java index 3e98953b82d5f0293b80a9ede4b40fae445eda75..afc03787123838272af34867d62ebcc13a5e2e3f 100644 --- a/logback-examples/src/main/java/chapter4/socket/SocketClient2.java +++ b/logback-examples/src/main/java/chapter4/socket/SocketClient2.java @@ -1,73 +1,73 @@ -/** - * 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 chapter4.socket; - -import java.io.BufferedReader; -import java.io.InputStreamReader; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; - - -/** - * This application uses a SocketAppender that log messages to a - * server on a host and port specified by the user. It waits for the - * user to type a message which will be sent to the server. - * */ -public class SocketClient2 { - static void usage(String msg) { - System.err.println(msg); - System.err.println("Usage: java " + SocketClient2.class.getName() + - " configFile\n" + - " configFile a logback configuration file" + - " in XML format."); - System.exit(1); - } - - static public void main(String[] args) throws Exception { - if (args.length != 1) { - usage("Wrong number of arguments."); - } - - String configFile = args[0]; - - if (configFile.endsWith(".xml")) { - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - JoranConfigurator configurator = new JoranConfigurator(); - lc.stop(); - configurator.setContext(lc); - configurator.doConfigure(configFile); - } - - Logger logger = LoggerFactory.getLogger(SocketClient2.class); - - BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); - - while (true) { - System.out.println( - "Type a message to send to log server. Type 'q' to quit."); - - String s = reader.readLine(); - - if (s.equals("q")) { - break; - } else { - logger.debug(s); - } - } - } -} +/** + * 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 chapter4.socket; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; + + +/** + * This application uses a SocketAppender that log messages to a + * server on a host and port specified by the user. It waits for the + * user to type a message which will be sent to the server. + * */ +public class SocketClient2 { + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + SocketClient2.class.getName() + + " configFile\n" + + " configFile a logback configuration file" + + " in XML format."); + System.exit(1); + } + + static public void main(String[] args) throws Exception { + if (args.length != 1) { + usage("Wrong number of arguments."); + } + + String configFile = args[0]; + + if (configFile.endsWith(".xml")) { + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + JoranConfigurator configurator = new JoranConfigurator(); + lc.stop(); + configurator.setContext(lc); + configurator.doConfigure(configFile); + } + + Logger logger = LoggerFactory.getLogger(SocketClient2.class); + + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + + while (true) { + System.out.println( + "Type a message to send to log server. Type 'q' to quit."); + + String s = reader.readLine(); + + if (s.equals("q")) { + break; + } else { + logger.debug(s); + } + } + } +} diff --git a/logback-examples/src/main/java/chapter4/socket/client1.xml b/logback-examples/src/main/java/chapter4/socket/client1.xml index 4c7fefb105ce752d4ad13110a113a7d993b44675..fa29a7a0a233ccb4aab6aaf2ed5f47fb45b2f6d0 100644 --- a/logback-examples/src/main/java/chapter4/socket/client1.xml +++ b/logback-examples/src/main/java/chapter4/socket/client1.xml @@ -1,23 +1,23 @@ - - - - - - - - - - ${host} - ${port} - 10000 - ${includeCallerData} - - - - - - - - - - + + + + + + + + + + ${host} + ${port} + 10000 + ${includeCallerData} + + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/socket/server1.xml b/logback-examples/src/main/java/chapter4/socket/server1.xml index 2cf0587dc87f3eaf84c3b47e916ff4471186bd7b..bb7dbdc869b7ec4b8919f5e2214c48826874b5c4 100644 --- a/logback-examples/src/main/java/chapter4/socket/server1.xml +++ b/logback-examples/src/main/java/chapter4/socket/server1.xml @@ -1,47 +1,47 @@ - - - - - - - - - - - - - - - %date %-5level [%thread] %logger - %message%n - - - - - - rolling.log - - - rolling.%i.log - 1 - 3 - - - - 8KB - - - - %relative %-5level %logger - %message%n - - - - - - - - - - - - + + + + + + + + + + + + + + + %date %-5level [%thread] %logger - %message%n + + + + + + rolling.log + + + rolling.%i.log + 1 + 3 + + + + 8KB + + + + %relative %-5level %logger - %message%n + + + + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/socket/server2.xml b/logback-examples/src/main/java/chapter4/socket/server2.xml index 7c458d882bcb73736c6ed850173a7b2533f2a391..f8f3cff7ebc086496e611f820494fbeec39afe48 100644 --- a/logback-examples/src/main/java/chapter4/socket/server2.xml +++ b/logback-examples/src/main/java/chapter4/socket/server2.xml @@ -1,25 +1,25 @@ - - - - - - - - - - - - - - %date %-5level [%thread] [%file:%line] %logger - %message%n - - - - - - - - - - - + + + + + + + + + + + + + + %date %-5level [%thread] [%file:%line] %logger - %message%n + + + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter4/sub/sample/Bar.java b/logback-examples/src/main/java/chapter4/sub/sample/Bar.java index 1c0953e2adf0ff6a13584cd287440158c0e017e5..6c232332189c7fc3e4e47c216606a82a26fcf325 100644 --- a/logback-examples/src/main/java/chapter4/sub/sample/Bar.java +++ b/logback-examples/src/main/java/chapter4/sub/sample/Bar.java @@ -1,34 +1,34 @@ -/** - * 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 chapter4.sub.sample; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Bar { - Logger logger = LoggerFactory.getLogger(Bar.class); - - public String toString() { - return "test 123"; - } - - public void createLoggingRequest() { - subMethodToCreateRequest(); - } - - //this is done to create a stacktrace of more than one line - private void subMethodToCreateRequest() { - logger.error("error-level request", new Exception("test exception")); - } -} +/** + * 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 chapter4.sub.sample; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Bar { + Logger logger = LoggerFactory.getLogger(Bar.class); + + public String toString() { + return "test 123"; + } + + public void createLoggingRequest() { + subMethodToCreateRequest(); + } + + //this is done to create a stacktrace of more than one line + private void subMethodToCreateRequest() { + logger.error("error-level request", new Exception("test exception")); + } +} diff --git a/logback-examples/src/main/java/chapter5/CallerEvaluatorExample.java b/logback-examples/src/main/java/chapter5/CallerEvaluatorExample.java index c46d6a1923f0b0d1e9ad708aa949dcd8222b8a52..2cd2dd5805eda609c0349e28693a5bcce56db3bf 100644 --- a/logback-examples/src/main/java/chapter5/CallerEvaluatorExample.java +++ b/logback-examples/src/main/java/chapter5/CallerEvaluatorExample.java @@ -1,48 +1,48 @@ -/** - * 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 chapter5; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.util.StatusPrinter; - -public class CallerEvaluatorExample { - - public static void main(String[] args) { - Logger logger = LoggerFactory - .getLogger(CallerEvaluatorExample.class); - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - - try { - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - lc.reset(); - configurator.doConfigure(args[0]); - } catch (JoranException je) { - StatusPrinter.print(lc); - } - - for (int i = 0; i < 5; i++) { - if (i == 3) { - logger.debug("who calls thee?"); - } else { - logger.debug("I know me " + i); - } - } - } +/** + * 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 chapter5; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.StatusPrinter; + +public class CallerEvaluatorExample { + + public static void main(String[] args) { + Logger logger = LoggerFactory + .getLogger(CallerEvaluatorExample.class); + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + + try { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + lc.reset(); + configurator.doConfigure(args[0]); + } catch (JoranException je) { + StatusPrinter.print(lc); + } + + for (int i = 0; i < 5; i++) { + if (i == 3) { + logger.debug("who calls thee?"); + } else { + logger.debug("I know me " + i); + } + } + } } \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter5/ExceptionEvaluatorExample.java b/logback-examples/src/main/java/chapter5/ExceptionEvaluatorExample.java index bd4c1a782dd0ba3ea8a88f2d4a6851538c627c18..6ba79bf4711e57f0f661b7527a6df1d4fa10f0af 100644 --- a/logback-examples/src/main/java/chapter5/ExceptionEvaluatorExample.java +++ b/logback-examples/src/main/java/chapter5/ExceptionEvaluatorExample.java @@ -1,47 +1,47 @@ -/** - * 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 chapter5; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.util.StatusPrinter; - -public class ExceptionEvaluatorExample { - - public static void main(String[] args) { - Logger logger = LoggerFactory.getLogger(ExceptionEvaluatorExample.class); - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - - try { - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - lc.reset(); - configurator.doConfigure(args[0]); - } catch (JoranException je) { - StatusPrinter.print(lc); - } - for (int i = 0; i < 5; i++) { - if (i == 3) { - logger.debug("logging statement " + i, new TestException( - "do not display this")); - } else { - logger.debug("logging statement " + i, new Exception("display")); - } - } - } +/** + * 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 chapter5; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.StatusPrinter; + +public class ExceptionEvaluatorExample { + + public static void main(String[] args) { + Logger logger = LoggerFactory.getLogger(ExceptionEvaluatorExample.class); + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + + try { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + lc.reset(); + configurator.doConfigure(args[0]); + } catch (JoranException je) { + StatusPrinter.print(lc); + } + for (int i = 0; i < 5; i++) { + if (i == 3) { + logger.debug("logging statement " + i, new TestException( + "do not display this")); + } else { + logger.debug("logging statement " + i, new Exception("display")); + } + } + } } \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter5/MySampleConverter.java b/logback-examples/src/main/java/chapter5/MySampleConverter.java index 957e1b4fa79eaafc5d1b3cf46227332fccce694c..ac9198064f7598de71ca5ef1a4dcd6d88226be88 100644 --- a/logback-examples/src/main/java/chapter5/MySampleConverter.java +++ b/logback-examples/src/main/java/chapter5/MySampleConverter.java @@ -1,50 +1,50 @@ -/** - * 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 chapter5; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.pattern.ClassicConverter; -import ch.qos.logback.classic.spi.ILoggingEvent; - -public class MySampleConverter extends ClassicConverter { - - private static final String END_COLOR = "\u001b[m"; - - private static final String ERROR_COLOR = "\u001b[0;31m"; - private static final String WARN_COLOR = "\u001b[0;33m"; - - @Override - public String convert(ILoggingEvent event) { - StringBuffer sbuf = new StringBuffer(); - sbuf.append(getColor(event.getLevel())); - sbuf.append(event.getLevel()); - sbuf.append(END_COLOR); - return sbuf.toString(); - } - - /** - * Returns the appropriate characters to change the color for the specified - * logging level. - */ - private String getColor(Level level) { - switch (level.toInt()) { - case Level.ERROR_INT: - return ERROR_COLOR; - case Level.WARN_INT: - return WARN_COLOR; - default: - return ""; - } - } -} +/** + * 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 chapter5; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.pattern.ClassicConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; + +public class MySampleConverter extends ClassicConverter { + + private static final String END_COLOR = "\u001b[m"; + + private static final String ERROR_COLOR = "\u001b[0;31m"; + private static final String WARN_COLOR = "\u001b[0;33m"; + + @Override + public String convert(ILoggingEvent event) { + StringBuffer sbuf = new StringBuffer(); + sbuf.append(getColor(event.getLevel())); + sbuf.append(event.getLevel()); + sbuf.append(END_COLOR); + return sbuf.toString(); + } + + /** + * Returns the appropriate characters to change the color for the specified + * logging level. + */ + private String getColor(Level level) { + switch (level.toInt()) { + case Level.ERROR_INT: + return ERROR_COLOR; + case Level.WARN_INT: + return WARN_COLOR; + default: + return ""; + } + } +} diff --git a/logback-examples/src/main/java/chapter5/MySampleLayout.java b/logback-examples/src/main/java/chapter5/MySampleLayout.java index 5f09216b00d3b30800d1bbb4382c73e35701bd9a..38caefd1db4862692880c142e705f0d276229954 100644 --- a/logback-examples/src/main/java/chapter5/MySampleLayout.java +++ b/logback-examples/src/main/java/chapter5/MySampleLayout.java @@ -1,36 +1,36 @@ -/** - * 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 chapter5; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.LayoutBase; - -public class MySampleLayout extends LayoutBase { - - public String doLayout(ILoggingEvent event) { - StringBuffer sbuf = new StringBuffer(128); - sbuf.append(event.getTimeStamp() - event.getLoggerContextVO().getBirthTime()); - sbuf.append(" "); - sbuf.append(event.getLevel()); - sbuf.append(" ["); - sbuf.append(event.getThreadName()); - sbuf.append("] "); - sbuf.append(event.getLoggerName()); - sbuf.append(" - "); - sbuf.append(event.getFormattedMessage()); - sbuf.append(CoreConstants.LINE_SEPARATOR); - return sbuf.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 chapter5; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.LayoutBase; + +public class MySampleLayout extends LayoutBase { + + public String doLayout(ILoggingEvent event) { + StringBuffer sbuf = new StringBuffer(128); + sbuf.append(event.getTimeStamp() - event.getLoggerContextVO().getBirthTime()); + sbuf.append(" "); + sbuf.append(event.getLevel()); + sbuf.append(" ["); + sbuf.append(event.getThreadName()); + sbuf.append("] "); + sbuf.append(event.getLoggerName()); + sbuf.append(" - "); + sbuf.append(event.getFormattedMessage()); + sbuf.append(CoreConstants.LINE_SEPARATOR); + return sbuf.toString(); + } } \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter5/MySampleLayout2.java b/logback-examples/src/main/java/chapter5/MySampleLayout2.java index 399fe052ecfe22e2046e8729c1ec7f0ca69e8248..87b1c433c8a840f0cdd9177d74bf2c4ffd1fdc2d 100644 --- a/logback-examples/src/main/java/chapter5/MySampleLayout2.java +++ b/logback-examples/src/main/java/chapter5/MySampleLayout2.java @@ -1,54 +1,54 @@ -/** - * 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 chapter5; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.LayoutBase; - -public class MySampleLayout2 extends LayoutBase { - - String prefix = null; - boolean printThreadName = true; - - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - public void setPrintThreadName(boolean printThreadName) { - this.printThreadName = printThreadName; - } - - public String doLayout(ILoggingEvent event) { - StringBuffer sbuf = new StringBuffer(128); - if (prefix != null) { - sbuf.append(prefix + ": "); - } - sbuf.append(event.getTimeStamp() - event.getLoggerContextVO().getBirthTime()); - sbuf.append(" "); - sbuf.append(event.getLevel()); - if (printThreadName) { - sbuf.append(" ["); - sbuf.append(event.getThreadName()); - sbuf.append("] "); - } else { - sbuf.append(" "); - } - sbuf.append(event.getLoggerName()); - sbuf.append(" - "); - sbuf.append(event.getFormattedMessage()); - sbuf.append(CoreConstants.LINE_SEPARATOR); - return sbuf.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 chapter5; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.LayoutBase; + +public class MySampleLayout2 extends LayoutBase { + + String prefix = null; + boolean printThreadName = true; + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public void setPrintThreadName(boolean printThreadName) { + this.printThreadName = printThreadName; + } + + public String doLayout(ILoggingEvent event) { + StringBuffer sbuf = new StringBuffer(128); + if (prefix != null) { + sbuf.append(prefix + ": "); + } + sbuf.append(event.getTimeStamp() - event.getLoggerContextVO().getBirthTime()); + sbuf.append(" "); + sbuf.append(event.getLevel()); + if (printThreadName) { + sbuf.append(" ["); + sbuf.append(event.getThreadName()); + sbuf.append("] "); + } else { + sbuf.append(" "); + } + sbuf.append(event.getLoggerName()); + sbuf.append(" - "); + sbuf.append(event.getFormattedMessage()); + sbuf.append(CoreConstants.LINE_SEPARATOR); + return sbuf.toString(); + } } \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter5/PatternSample.java b/logback-examples/src/main/java/chapter5/PatternSample.java index bcb8a21cf8ec565cf2a88ccb6bae350630da1681..6ae46b6f9d69d4ae5d9c0667dd63636964a0455d 100644 --- a/logback-examples/src/main/java/chapter5/PatternSample.java +++ b/logback-examples/src/main/java/chapter5/PatternSample.java @@ -1,42 +1,42 @@ -/** - * 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 chapter5; - -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.ConsoleAppender; - -public class PatternSample { - - static public void main(String[] args) throws Exception { - Logger rootLogger = (Logger) LoggerFactory.getLogger("root"); - - PatternLayout layout = new PatternLayout(); - layout.setPattern("%-5level [%thread]: %message%n"); - layout.start(); - - ConsoleAppender appender = new ConsoleAppender(); - appender.setContext(rootLogger.getLoggerContext()); - appender.setLayout(layout); - appender.start(); - - rootLogger.addAppender(appender); - - rootLogger.debug("Message 1"); - rootLogger.warn("Message 2"); - } +/** + * 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 chapter5; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.ConsoleAppender; + +public class PatternSample { + + static public void main(String[] args) throws Exception { + Logger rootLogger = (Logger) LoggerFactory.getLogger("root"); + + PatternLayout layout = new PatternLayout(); + layout.setPattern("%-5level [%thread]: %message%n"); + layout.start(); + + ConsoleAppender appender = new ConsoleAppender(); + appender.setContext(rootLogger.getLoggerContext()); + appender.setLayout(layout); + appender.start(); + + rootLogger.addAppender(appender); + + rootLogger.debug("Message 1"); + rootLogger.warn("Message 2"); + } } \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter5/SampleLogging.java b/logback-examples/src/main/java/chapter5/SampleLogging.java index 3a4a78992eed458dd818f44ea19011f06fabc063..e62cd934a12bb3bd3b7b12dcdc479d19bcc0c8d4 100644 --- a/logback-examples/src/main/java/chapter5/SampleLogging.java +++ b/logback-examples/src/main/java/chapter5/SampleLogging.java @@ -1,44 +1,44 @@ -/** - * 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 chapter5; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.util.StatusPrinter; - -public class SampleLogging { - - public static void main(String[] args) { - - Logger logger = LoggerFactory.getLogger(SampleLogging.class); - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - - try { - JoranConfigurator configurator = new JoranConfigurator(); - lc.reset(); - configurator.setContext(lc); - configurator.doConfigure(args[0]); - } catch (JoranException je) { - StatusPrinter.print(lc); - } - - logger.debug("Everything's going well"); - logger.error("maybe not quite..."); - } - -} +/** + * 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 chapter5; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.StatusPrinter; + +public class SampleLogging { + + public static void main(String[] args) { + + Logger logger = LoggerFactory.getLogger(SampleLogging.class); + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + + try { + JoranConfigurator configurator = new JoranConfigurator(); + lc.reset(); + configurator.setContext(lc); + configurator.doConfigure(args[0]); + } catch (JoranException je) { + StatusPrinter.print(lc); + } + + logger.debug("Everything's going well"); + logger.error("maybe not quite..."); + } + +} diff --git a/logback-examples/src/main/java/chapter5/TestException.java b/logback-examples/src/main/java/chapter5/TestException.java index 026569fb27759a9071df82319c4e2bd08c1343f6..4eb054f32a38776d039005ff8fa765fce44bb648 100644 --- a/logback-examples/src/main/java/chapter5/TestException.java +++ b/logback-examples/src/main/java/chapter5/TestException.java @@ -1,23 +1,23 @@ -/** - * 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 chapter5; - -public class TestException extends Exception { - - private static final long serialVersionUID = 8326547927308399902L; - - public TestException(String message) { - super(message); - } -} +/** + * 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 chapter5; + +public class TestException extends Exception { + + private static final long serialVersionUID = 8326547927308399902L; + + public TestException(String message) { + super(message); + } +} diff --git a/logback-examples/src/main/java/chapter5/callerEvaluatorConfig.xml b/logback-examples/src/main/java/chapter5/callerEvaluatorConfig.xml index 8d3471fba924bb06b5d043a829e43f36c5f247a5..1d84e19df1c63a8716d256183e0143eefe9a8be5 100644 --- a/logback-examples/src/main/java/chapter5/callerEvaluatorConfig.xml +++ b/logback-examples/src/main/java/chapter5/callerEvaluatorConfig.xml @@ -1,18 +1,18 @@ - - - - - logger.getName().contains("chapter5") && message.contains("who calls thee") - - - - - - %-4relative [%thread] %-5level - %msg%n%caller{2, DISPLAY_CALLER_EVAL} - - - - - - + + + + + logger.getName().contains("chapter5") && message.contains("who calls thee") + + + + + + %-4relative [%thread] %-5level - %msg%n%caller{2, DISPLAY_CALLER_EVAL} + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter5/exceptionEvaluatorConfig.xml b/logback-examples/src/main/java/chapter5/exceptionEvaluatorConfig.xml index 57624528bc931a4dbce46e000c9f18fbed8c8288..f9b850289d0a1399b1f1cfad5f23ad3fc3c6e3d4 100644 --- a/logback-examples/src/main/java/chapter5/exceptionEvaluatorConfig.xml +++ b/logback-examples/src/main/java/chapter5/exceptionEvaluatorConfig.xml @@ -1,16 +1,16 @@ - - - - throwable != null && throwable instanceof chapter5.TestException - - - - - %-4relative [%thread] %-5level - %msg%n%ex{full, DISPLAY_EX_EVAL} - - - - - - + + + + throwable != null && throwable instanceof chapter5.TestException + + + + + %-4relative [%thread] %-5level - %msg%n%ex{full, DISPLAY_EX_EVAL} + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter5/mySampleConverterConfig.xml b/logback-examples/src/main/java/chapter5/mySampleConverterConfig.xml index b68f650d1d36224d61a06e536246fcc9128bbba7..c526c1bb3e96d23e475840c773ac6178674fcb36 100644 --- a/logback-examples/src/main/java/chapter5/mySampleConverterConfig.xml +++ b/logback-examples/src/main/java/chapter5/mySampleConverterConfig.xml @@ -1,15 +1,15 @@ - - - - - - - %-4relative [%thread] %sample - %msg%n - - - - - - + + + + + + + %-4relative [%thread] %sample - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter5/sampleLayoutConfig.xml b/logback-examples/src/main/java/chapter5/sampleLayoutConfig.xml index 120d1045d1b60a2dc37361ddeb82f72656eb16c1..4ec1933e30833b4d4a4c329459e1356f3461e93f 100644 --- a/logback-examples/src/main/java/chapter5/sampleLayoutConfig.xml +++ b/logback-examples/src/main/java/chapter5/sampleLayoutConfig.xml @@ -1,11 +1,11 @@ - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter5/sampleLayoutConfig2.xml b/logback-examples/src/main/java/chapter5/sampleLayoutConfig2.xml index 3d454348bf4e0298d250ed6de7126300ef8a7c4c..24ed95dff09bba25c90a86891f87a854eb2a4121 100644 --- a/logback-examples/src/main/java/chapter5/sampleLayoutConfig2.xml +++ b/logback-examples/src/main/java/chapter5/sampleLayoutConfig2.xml @@ -1,14 +1,14 @@ - - - - - MyPrefix - false - - - - - - + + + + + MyPrefix + false + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/FilterEvents.java b/logback-examples/src/main/java/chapter6/FilterEvents.java index 95d22caf5b11165ae877fdeb9fae673c14d4119e..a6658e04a1d1095c4056891972ede880d85452d6 100644 --- a/logback-examples/src/main/java/chapter6/FilterEvents.java +++ b/logback-examples/src/main/java/chapter6/FilterEvents.java @@ -1,59 +1,59 @@ -/** - * 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 chapter6; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; -import org.slf4j.Marker; -import org.slf4j.MarkerFactory; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; - -public class FilterEvents { - - public static void main(String[] args) throws InterruptedException { - if (args.length == 0) { - System.out.println("A configuration file must be passed as a parameter."); - return; - } - - Logger logger = (Logger) LoggerFactory.getLogger(FilterEvents.class); - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - - try { - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - lc.reset(); - configurator.doConfigure(args[0]); - } catch (JoranException je) { - je.printStackTrace(); - } - - for (int i = 0; i < 10; i++) { - if (i == 3) { - MDC.put("username", "sebastien"); - logger.debug("logging statement {}", i); - MDC.remove("username"); - } else if (i == 6) { - Marker billing = MarkerFactory.getMarker("billing"); - logger.error(billing, "billing statement {}", i); - } else { - logger.info("logging statement {}", i); - } - } - } -} +/** + * 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 chapter6; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; + +public class FilterEvents { + + public static void main(String[] args) throws InterruptedException { + if (args.length == 0) { + System.out.println("A configuration file must be passed as a parameter."); + return; + } + + Logger logger = (Logger) LoggerFactory.getLogger(FilterEvents.class); + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + + try { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + lc.reset(); + configurator.doConfigure(args[0]); + } catch (JoranException je) { + je.printStackTrace(); + } + + for (int i = 0; i < 10; i++) { + if (i == 3) { + MDC.put("username", "sebastien"); + logger.debug("logging statement {}", i); + MDC.remove("username"); + } else if (i == 6) { + Marker billing = MarkerFactory.getMarker("billing"); + logger.error(billing, "billing statement {}", i); + } else { + logger.info("logging statement {}", i); + } + } + } +} diff --git a/logback-examples/src/main/java/chapter6/GoMDC.java b/logback-examples/src/main/java/chapter6/GoMDC.java index 75fbe9a8d45bd93274559ad3dcc2f99421d0b598..9ce9a2762fae6aeffb72a774c50e5f7b71d7f9ae 100644 --- a/logback-examples/src/main/java/chapter6/GoMDC.java +++ b/logback-examples/src/main/java/chapter6/GoMDC.java @@ -1,48 +1,48 @@ -/** - * 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 chapter6; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.util.StatusPrinter; - -public class GoMDC { - - public static void main(String[] args) { - Logger logger = LoggerFactory - .getLogger(GoMDC.class); - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - - try { - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - lc.reset(); - configurator.doConfigure("mdcFilter.xml"); - - } catch (JoranException je) { - StatusPrinter.print(lc); - } - - logger.debug("I know me " + 0); - MDC.put("key", "val"); - logger.debug("I know me " + 1); - - StatusPrinter.print(lc); - } +/** + * 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 chapter6; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.StatusPrinter; + +public class GoMDC { + + public static void main(String[] args) { + Logger logger = LoggerFactory + .getLogger(GoMDC.class); + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + + try { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + lc.reset(); + configurator.doConfigure("mdcFilter.xml"); + + } catch (JoranException je) { + StatusPrinter.print(lc); + } + + logger.debug("I know me " + 0); + MDC.put("key", "val"); + logger.debug("I know me " + 1); + + StatusPrinter.print(lc); + } } \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/SampleFilter.java b/logback-examples/src/main/java/chapter6/SampleFilter.java index bf7ee9db2e7eb308db8c102736f002d620c2adb7..d70d280435b3969233a49a41eb465c3cb048973f 100644 --- a/logback-examples/src/main/java/chapter6/SampleFilter.java +++ b/logback-examples/src/main/java/chapter6/SampleFilter.java @@ -1,30 +1,30 @@ -/** - * 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 chapter6; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.filter.Filter; -import ch.qos.logback.core.spi.FilterReply; - -public class SampleFilter extends Filter { - - @Override - public FilterReply decide(ILoggingEvent event) { - if (event.getMessage() != null && event.getMessage().contains("sample")) { - return FilterReply.ACCEPT; - } else { - return FilterReply.NEUTRAL; - } - } -} +/** + * 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 chapter6; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.spi.FilterReply; + +public class SampleFilter extends Filter { + + @Override + public FilterReply decide(ILoggingEvent event) { + if (event.getMessage() != null && event.getMessage().contains("sample")) { + return FilterReply.ACCEPT; + } else { + return FilterReply.NEUTRAL; + } + } +} diff --git a/logback-examples/src/main/java/chapter6/SampleTurboFilter.java b/logback-examples/src/main/java/chapter6/SampleTurboFilter.java index 4d935975409de5f18044b06038ec39e864cd63e2..9406840394c99d8aa7363dc3f27c26f798e44528 100644 --- a/logback-examples/src/main/java/chapter6/SampleTurboFilter.java +++ b/logback-examples/src/main/java/chapter6/SampleTurboFilter.java @@ -1,59 +1,59 @@ -/** - * 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 chapter6; - -import org.slf4j.Marker; -import org.slf4j.MarkerFactory; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.turbo.TurboFilter; -import ch.qos.logback.core.spi.FilterReply; - -public class SampleTurboFilter extends TurboFilter { - - String marker; - Marker markerToAccept; - - @Override - public FilterReply decide(Marker marker, Logger logger, Level level, - String format, Object[] params, Throwable t) { - - if (!isStarted()) { - return FilterReply.NEUTRAL; - } - - if ((markerToAccept.equals(marker))) { - return FilterReply.ACCEPT; - } else { - return FilterReply.NEUTRAL; - } - } - - public String getMarker() { - return marker; - } - - public void setMarker(String markerStr) { - this.marker = markerStr; - } - - @Override - public void start() { - if (marker != null && marker.trim().length() > 0) { - markerToAccept = MarkerFactory.getMarker(marker); - super.start(); - } - } -} +/** + * 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 chapter6; + +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.turbo.TurboFilter; +import ch.qos.logback.core.spi.FilterReply; + +public class SampleTurboFilter extends TurboFilter { + + String marker; + Marker markerToAccept; + + @Override + public FilterReply decide(Marker marker, Logger logger, Level level, + String format, Object[] params, Throwable t) { + + if (!isStarted()) { + return FilterReply.NEUTRAL; + } + + if ((markerToAccept.equals(marker))) { + return FilterReply.ACCEPT; + } else { + return FilterReply.NEUTRAL; + } + } + + public String getMarker() { + return marker; + } + + public void setMarker(String markerStr) { + this.marker = markerStr; + } + + @Override + public void start() { + if (marker != null && marker.trim().length() > 0) { + markerToAccept = MarkerFactory.getMarker(marker); + super.start(); + } + } +} diff --git a/logback-examples/src/main/java/chapter6/accessEventEvaluator.xml b/logback-examples/src/main/java/chapter6/accessEventEvaluator.xml index 60cc3f206b899b03247e4a9aa3355dc06f023c08..513cdd7eb56a0c267cbbf151af81fc30fb5394b5 100644 --- a/logback-examples/src/main/java/chapter6/accessEventEvaluator.xml +++ b/logback-examples/src/main/java/chapter6/accessEventEvaluator.xml @@ -1,20 +1,20 @@ - - - - - - event.getStatusCode() == 404 - - NEUTRAL - ACCEPT - - - - %h %l %u %t %r %s %b - - - - - + + + + + + event.getStatusCode() == 404 + + NEUTRAL + ACCEPT + + + + %h %l %u %t %r %s %b + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/accessEventEvaluator2.xml b/logback-examples/src/main/java/chapter6/accessEventEvaluator2.xml index 7c31d3e73e40902f5b2859c5de9d242040180be4..116061a161417cc4f492e230488106b67de887fd 100644 --- a/logback-examples/src/main/java/chapter6/accessEventEvaluator2.xml +++ b/logback-examples/src/main/java/chapter6/accessEventEvaluator2.xml @@ -1,27 +1,27 @@ - - - - - - event.getStatusCode() == 404 - - NEUTRAL - ACCEPT - - - - event.getRequestURI().contains("css") - - NEUTRAL - DENY - - - - %h %l %u %t %r %s %b - - - - - + + + + + + event.getStatusCode() == 404 + + NEUTRAL + ACCEPT + + + + event.getRequestURI().contains("css") + + NEUTRAL + DENY + + + + %h %l %u %t %r %s %b + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/basicConfiguration.xml b/logback-examples/src/main/java/chapter6/basicConfiguration.xml index 83fd0460e4e6a9fcb6d448c574a37dee7dbcdcb3..c290b30fddd135b38f223838315d1a21344a911f 100644 --- a/logback-examples/src/main/java/chapter6/basicConfiguration.xml +++ b/logback-examples/src/main/java/chapter6/basicConfiguration.xml @@ -1,12 +1,12 @@ - - - - - %-4relative [%thread] %-5level %logger - %msg%n - - - - - - + + + + + %-4relative [%thread] %-5level %logger - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/basicEventEvaluator.xml b/logback-examples/src/main/java/chapter6/basicEventEvaluator.xml index f6a1e3ea9aa9d57323b247fd29eb27f6d3df23bc..dd177803e6cc4a831d72e83422d2404a52ed37c8 100644 --- a/logback-examples/src/main/java/chapter6/basicEventEvaluator.xml +++ b/logback-examples/src/main/java/chapter6/basicEventEvaluator.xml @@ -1,19 +1,19 @@ - - - - - - message.contains("billing") - - NEUTRAL - DENY - - - %-4relative [%thread] %-5level %logger - %msg%n - - - - - - + + + + + + message.contains("billing") + + NEUTRAL + DENY + + + %-4relative [%thread] %-5level %logger - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/duplicateMessage.xml b/logback-examples/src/main/java/chapter6/duplicateMessage.xml index 9637829d4a2f51407b0511f8e53f87ec5f1f928b..b79757c28e4d4ff2915d521f4346f858622e3b10 100644 --- a/logback-examples/src/main/java/chapter6/duplicateMessage.xml +++ b/logback-examples/src/main/java/chapter6/duplicateMessage.xml @@ -1,16 +1,16 @@ - - - - - - - - - %date [%thread] %-5level %logger - %msg%n - - - - - - + + + + + + + + + %date [%thread] %-5level %logger - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/evaluatorWithMatcher.xml b/logback-examples/src/main/java/chapter6/evaluatorWithMatcher.xml index f2aab92abd8a4ac823a0d890ac99266e9314bbf0..0850732e2ee03fbc3446c4db967ec1ba1aac3dee 100644 --- a/logback-examples/src/main/java/chapter6/evaluatorWithMatcher.xml +++ b/logback-examples/src/main/java/chapter6/evaluatorWithMatcher.xml @@ -1,25 +1,25 @@ - - - - - - - - odd - statement [13579] - - - odd.matches(formattedMessage) - - NEUTRAL - DENY - - - %-4relative [%thread] %-5level %logger - %msg%n - - - - - - + + + + + + + + odd + statement [13579] + + + odd.matches(formattedMessage) + + NEUTRAL + DENY + + + %-4relative [%thread] %-5level %logger - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/levelFilterConfig.xml b/logback-examples/src/main/java/chapter6/levelFilterConfig.xml index b1008bb7721aa834e3a14b22499b49c9ac4a1fb1..9b514f96b11d5b401dc2cf2cb9421054ab46209d 100644 --- a/logback-examples/src/main/java/chapter6/levelFilterConfig.xml +++ b/logback-examples/src/main/java/chapter6/levelFilterConfig.xml @@ -1,17 +1,17 @@ - - - - - - INFO - ACCEPT - DENY - - - %-4relative [%thread] %-5level %logger{30} - %msg%n - - - - - + + + + + + INFO + ACCEPT + DENY + + + %-4relative [%thread] %-5level %logger{30} - %msg%n + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/mdcfilter.xml b/logback-examples/src/main/java/chapter6/mdcfilter.xml index 9963e6123b8a437a1cf7b269faab2a895a4b2fd6..feacd8feef4c00d14e5ba9918ddc22ce93bee3da 100644 --- a/logback-examples/src/main/java/chapter6/mdcfilter.xml +++ b/logback-examples/src/main/java/chapter6/mdcfilter.xml @@ -1,23 +1,23 @@ - - - - - %-4relative [%thread] %-5level %X{testKey} - %msg%n" - - - - myFilter - DENY - - mdcEvaluator - mdc!=null && "val".equals(mdc.get("key")) - - - - - - - - - + + + + + %-4relative [%thread] %-5level %X{testKey} - %msg%n" + + + + myFilter + DENY + + mdcEvaluator + mdc!=null && "val".equals(mdc.get("key")) + + + + + + + + + diff --git a/logback-examples/src/main/java/chapter6/sampleFilterConfig.xml b/logback-examples/src/main/java/chapter6/sampleFilterConfig.xml index b206d51d9693b1a31f2f5d47c04b28c23e32e824..1e8a10e744c9bcfb14cce45696d5337f73ecfb9e 100644 --- a/logback-examples/src/main/java/chapter6/sampleFilterConfig.xml +++ b/logback-examples/src/main/java/chapter6/sampleFilterConfig.xml @@ -1,17 +1,17 @@ - - - - - - - - %-4relative [%thread] %-5level %logger - %msg%n - - - - - - - + + + + + + + + %-4relative [%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/sampleTurboFilterConfig.xml b/logback-examples/src/main/java/chapter6/sampleTurboFilterConfig.xml index e6d9f1e1d3a8ec2f08d14b44167758d8ea31817f..6421d5ff578aaf284399d67eb570acc2f8f77497 100644 --- a/logback-examples/src/main/java/chapter6/sampleTurboFilterConfig.xml +++ b/logback-examples/src/main/java/chapter6/sampleTurboFilterConfig.xml @@ -1,16 +1,16 @@ - - - - sample - - - - - %-4relative [%thread] %-5level %logger - %msg%n - - - - - - + + + + sample + + + + + %-4relative [%thread] %-5level %logger - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml b/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml index bcdb27ff7a95ad3d06ad58bcc791fcbcb874ef1c..f7a38b8364381cf7c49c231e5b415c364683d38b 100644 --- a/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml +++ b/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml @@ -1,20 +1,20 @@ - - - - - - - - INFO - - - %-4relative [%thread] %-5level %logger{30} - %msg%n - - - - - - - - + + + + + + + + INFO + + + %-4relative [%thread] %-5level %logger{30} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter6/turboFilters.xml b/logback-examples/src/main/java/chapter6/turboFilters.xml index 6e1b26b5a766c37525b70cba1b90f519de8b611d..df997274872beebf3b987313b9db98d622da5c03 100644 --- a/logback-examples/src/main/java/chapter6/turboFilters.xml +++ b/logback-examples/src/main/java/chapter6/turboFilters.xml @@ -1,25 +1,25 @@ - - - - - - username - sebastien - ACCEPT - - - - billing - DENY - - - - - %date [%thread] %-5level %logger - %msg%n - - - - - - + + + + + + username + sebastien + ACCEPT + + + + billing + DENY + + + + + %date [%thread] %-5level %logger - %msg%n + + + + + + \ No newline at end of file diff --git a/logback-examples/src/main/java/chapter7/NumberCruncher.java b/logback-examples/src/main/java/chapter7/NumberCruncher.java index 3a5a8179c1eabb72c10bc91ecd39d5b372c808a1..4ae415184b27651e62536067b5e4766fa7933720 100644 --- a/logback-examples/src/main/java/chapter7/NumberCruncher.java +++ b/logback-examples/src/main/java/chapter7/NumberCruncher.java @@ -1,29 +1,29 @@ -/** - * 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 chapter7; - -import java.rmi.Remote; -import java.rmi.RemoteException; - - -/** - * NumberCruncher factors positive integers. - */ -public interface NumberCruncher extends Remote { - /** - * Factor a positive integer number and return its - * distinct factor's as an integer array. - * */ - int[] factor(int number) throws RemoteException; -} +/** + * 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 chapter7; + +import java.rmi.Remote; +import java.rmi.RemoteException; + + +/** + * NumberCruncher factors positive integers. + */ +public interface NumberCruncher extends Remote { + /** + * Factor a positive integer number and return its + * distinct factor's as an integer array. + * */ + int[] factor(int number) throws RemoteException; +} diff --git a/logback-examples/src/main/java/chapter7/NumberCruncherClient.java b/logback-examples/src/main/java/chapter7/NumberCruncherClient.java index ad3ed34ca33a1330be8a1370ca29e77281e778b3..2a06829ca1e509d4b45e14fa29323769e07e4cdd 100644 --- a/logback-examples/src/main/java/chapter7/NumberCruncherClient.java +++ b/logback-examples/src/main/java/chapter7/NumberCruncherClient.java @@ -1,86 +1,86 @@ -/** - * 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 chapter7; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.rmi.Naming; -import java.rmi.RemoteException; - - -/** - * NumberCruncherClient is a simple client for factoring integers. A - * remote NumberCruncher is contacted and asked to factor an - * integer. The factors returned by the {@link NumberCruncherServer} - * are displayed on the screen. - * */ -public class NumberCruncherClient { - public static void main(String[] args) { - if (args.length == 1) { - try { - String url = "rmi://" + args[0] + "/Factor"; - NumberCruncher nc = (NumberCruncher) Naming.lookup(url); - loop(nc); - } catch (Exception e) { - e.printStackTrace(); - } - } else { - usage("Wrong number of arguments."); - } - } - - static void usage(String msg) { - System.err.println(msg); - System.err.println("Usage: java chapter7.NumberCruncherClient HOST\n" + - " where HOST is the machine where the NumberCruncherServer is running."); - System.exit(1); - } - - static void loop(NumberCruncher nc) { - BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); - int i = 0; - - while (true) { - System.out.print("Enter a number to factor, '-1' to quit: "); - - try { - i = Integer.parseInt(in.readLine()); - } catch (Exception e) { - e.printStackTrace(); - } - - if (i == -1) { - System.out.print("Exiting loop."); - - return; - } else { - try { - System.out.println("Will attempt to factor " + i); - - int[] factors = nc.factor(i); - System.out.print("The factors of " + i + " are"); - - for (int k = 0; k < factors.length; k++) { - System.out.print(" " + factors[k]); - } - - System.out.println("."); - } catch (RemoteException e) { - System.err.println("Could not factor " + i); - e.printStackTrace(); - } - } - } - } -} +/** + * 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 chapter7; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.rmi.Naming; +import java.rmi.RemoteException; + + +/** + * NumberCruncherClient is a simple client for factoring integers. A + * remote NumberCruncher is contacted and asked to factor an + * integer. The factors returned by the {@link NumberCruncherServer} + * are displayed on the screen. + * */ +public class NumberCruncherClient { + public static void main(String[] args) { + if (args.length == 1) { + try { + String url = "rmi://" + args[0] + "/Factor"; + NumberCruncher nc = (NumberCruncher) Naming.lookup(url); + loop(nc); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + usage("Wrong number of arguments."); + } + } + + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java chapter7.NumberCruncherClient HOST\n" + + " where HOST is the machine where the NumberCruncherServer is running."); + System.exit(1); + } + + static void loop(NumberCruncher nc) { + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + int i = 0; + + while (true) { + System.out.print("Enter a number to factor, '-1' to quit: "); + + try { + i = Integer.parseInt(in.readLine()); + } catch (Exception e) { + e.printStackTrace(); + } + + if (i == -1) { + System.out.print("Exiting loop."); + + return; + } else { + try { + System.out.println("Will attempt to factor " + i); + + int[] factors = nc.factor(i); + System.out.print("The factors of " + i + " are"); + + for (int k = 0; k < factors.length; k++) { + System.out.print(" " + factors[k]); + } + + System.out.println("."); + } catch (RemoteException e) { + System.err.println("Could not factor " + i); + e.printStackTrace(); + } + } + } + } +} diff --git a/logback-examples/src/main/java/chapter7/NumberCruncherServer.java b/logback-examples/src/main/java/chapter7/NumberCruncherServer.java index f952706de3311ebcd3be9840b4f9b709803f51a9..6977152d34931150759fa57b73197da68aa270c4 100644 --- a/logback-examples/src/main/java/chapter7/NumberCruncherServer.java +++ b/logback-examples/src/main/java/chapter7/NumberCruncherServer.java @@ -1,162 +1,162 @@ -/** - * 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 chapter7; - -import java.rmi.RemoteException; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.rmi.server.UnicastRemoteObject; -import java.util.Vector; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; - - -/** - * A simple NumberCruncher implementation that logs its progress when - * factoring numbers. The purpose of the whole exercise is to show the - * use of mapped diagnostic contexts in order to distinguish the log - * output from different client requests. - * */ -public class NumberCruncherServer extends UnicastRemoteObject - implements NumberCruncher { - - private static final long serialVersionUID = 1L; - - static Logger logger = LoggerFactory.getLogger(NumberCruncherServer.class); - - public NumberCruncherServer() throws RemoteException { - } - - public int[] factor(int number) throws RemoteException { - // The client's host is an important source of information. - try { - MDC.put("client", NumberCruncherServer.getClientHost()); - } catch (java.rmi.server.ServerNotActiveException e) { - logger.warn("Caught unexpected ServerNotActiveException.", e); - } - - // The information contained within the request is another source - // of distinctive information. It might reveal the users name, - // date of request, request ID etc. In servlet type environments, - // useful information is contained in the HttpRequest or in the - // HttpSession. - MDC.put("number", String.valueOf(number)); - - logger.info("Beginning to factor."); - - if (number <= 0) { - throw new IllegalArgumentException(number + - " is not a positive integer."); - } else if (number == 1) { - return new int[] { 1 }; - } - - Vector factors = new Vector(); - int n = number; - - for (int i = 2; (i <= n) && ((i * i) <= number); i++) { - // It is bad practice to place log requests within tight loops. - // It is done here to show interleaved log output from - // different requests. - logger.debug("Trying " + i + " as a factor."); - - if ((n % i) == 0) { - logger.info("Found factor " + i); - factors.addElement(new Integer(i)); - - do { - n /= i; - } while ((n % i) == 0); - } - - // Placing artificial delays in tight loops will also lead to - // sub-optimal resuts. :-) - delay(100); - } - - if (n != 1) { - logger.info("Found factor " + n); - factors.addElement(new Integer(n)); - } - - int len = factors.size(); - - int[] result = new int[len]; - - for (int i = 0; i < len; i++) { - result[i] = ((Integer) factors.elementAt(i)).intValue(); - } - - // clean up - MDC.remove("client"); - MDC.remove("number"); - - return result; - } - - static void usage(String msg) { - System.err.println(msg); - System.err.println("Usage: java chapter7.NumberCruncherServer configFile\n" + - " where configFile is a logback configuration file."); - System.exit(1); - } - - public static void delay(int millis) { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - } - } - - public static void main(String[] args) { - if (args.length != 1) { - usage("Wrong number of arguments."); - } - - String configFile = args[0]; - - if (configFile.endsWith(".xml")) { - try { - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - lc.reset(); - configurator.doConfigure(args[0]); - } catch (JoranException je) { - je.printStackTrace(); - } - } - - NumberCruncherServer ncs; - - try { - ncs = new NumberCruncherServer(); - logger.info("Creating registry."); - - Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT); - registry.rebind("Factor", ncs); - logger.info("NumberCruncherServer bound and ready."); - } catch (Exception e) { - logger.error("Could not bind NumberCruncherServer.", e); - - return; - } - } -} +/** + * 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 chapter7; + +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.UnicastRemoteObject; +import java.util.Vector; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; + + +/** + * A simple NumberCruncher implementation that logs its progress when + * factoring numbers. The purpose of the whole exercise is to show the + * use of mapped diagnostic contexts in order to distinguish the log + * output from different client requests. + * */ +public class NumberCruncherServer extends UnicastRemoteObject + implements NumberCruncher { + + private static final long serialVersionUID = 1L; + + static Logger logger = LoggerFactory.getLogger(NumberCruncherServer.class); + + public NumberCruncherServer() throws RemoteException { + } + + public int[] factor(int number) throws RemoteException { + // The client's host is an important source of information. + try { + MDC.put("client", NumberCruncherServer.getClientHost()); + } catch (java.rmi.server.ServerNotActiveException e) { + logger.warn("Caught unexpected ServerNotActiveException.", e); + } + + // The information contained within the request is another source + // of distinctive information. It might reveal the users name, + // date of request, request ID etc. In servlet type environments, + // useful information is contained in the HttpRequest or in the + // HttpSession. + MDC.put("number", String.valueOf(number)); + + logger.info("Beginning to factor."); + + if (number <= 0) { + throw new IllegalArgumentException(number + + " is not a positive integer."); + } else if (number == 1) { + return new int[] { 1 }; + } + + Vector factors = new Vector(); + int n = number; + + for (int i = 2; (i <= n) && ((i * i) <= number); i++) { + // It is bad practice to place log requests within tight loops. + // It is done here to show interleaved log output from + // different requests. + logger.debug("Trying " + i + " as a factor."); + + if ((n % i) == 0) { + logger.info("Found factor " + i); + factors.addElement(new Integer(i)); + + do { + n /= i; + } while ((n % i) == 0); + } + + // Placing artificial delays in tight loops will also lead to + // sub-optimal resuts. :-) + delay(100); + } + + if (n != 1) { + logger.info("Found factor " + n); + factors.addElement(new Integer(n)); + } + + int len = factors.size(); + + int[] result = new int[len]; + + for (int i = 0; i < len; i++) { + result[i] = ((Integer) factors.elementAt(i)).intValue(); + } + + // clean up + MDC.remove("client"); + MDC.remove("number"); + + return result; + } + + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java chapter7.NumberCruncherServer configFile\n" + + " where configFile is a logback configuration file."); + System.exit(1); + } + + public static void delay(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + } + } + + public static void main(String[] args) { + if (args.length != 1) { + usage("Wrong number of arguments."); + } + + String configFile = args[0]; + + if (configFile.endsWith(".xml")) { + try { + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + lc.reset(); + configurator.doConfigure(args[0]); + } catch (JoranException je) { + je.printStackTrace(); + } + } + + NumberCruncherServer ncs; + + try { + ncs = new NumberCruncherServer(); + logger.info("Creating registry."); + + Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT); + registry.rebind("Factor", ncs); + logger.info("NumberCruncherServer bound and ready."); + } catch (Exception e) { + logger.error("Could not bind NumberCruncherServer.", e); + + return; + } + } +} diff --git a/logback-examples/src/main/java/chapter7/SimpleMDC.java b/logback-examples/src/main/java/chapter7/SimpleMDC.java index f804774478563f298d144c5bb3f9e68f7bc1192d..59a56840067d2ad50edcfb6669ac27e62e3ac07a 100644 --- a/logback-examples/src/main/java/chapter7/SimpleMDC.java +++ b/logback-examples/src/main/java/chapter7/SimpleMDC.java @@ -1,94 +1,94 @@ -/** - * 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 chapter7; - -import java.net.URL; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.ConsoleAppender; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.util.Loader; -import ch.qos.logback.core.util.StatusPrinter; - -public class SimpleMDC { - static public void main(String[] args) throws Exception { - // You can put values in the MDC at any time. Before anything else - // we put the first name - MDC.put("first", "Dorothy"); - - // configure via the configuration file "chapter7/simpleMDC.xml" - // which ships with the examples - configureViaXML_File(); - - // For educational purposes, the same configuration can - // be accomplished programmatically. - // - // programmaticConfiguration(); - - Logger logger = LoggerFactory.getLogger(SimpleMDC.class); - // We now put the last name - MDC.put("last", "Parker"); - - // The most beautiful two words in the English language according - // to Dorothy Parker: - logger.info("Check enclosed."); - logger.debug("The most beautiful two words in English."); - - MDC.put("first", "Richard"); - MDC.put("last", "Nixon"); - logger.info("I am not a crook."); - logger.info("Attributed to the former US president. 17 Nov 1973."); - } - - static void programmaticConfiguration() { - // Configure logback - LoggerContext loggerContext = (LoggerContext) LoggerFactory - .getILoggerFactory(); - loggerContext.reset(); - PatternLayout layout = new PatternLayout(); - layout.setContext(loggerContext); - layout.setPattern("%X{first} %X{last} - %m%n"); - layout.start(); - ConsoleAppender appender = new ConsoleAppender(); - appender.setContext(loggerContext); - appender.setLayout(layout); - appender.start(); - // cast root logger to c.q.logback.classic.Logger so that we can attach - // an appender to it - ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory - .getLogger("root"); - root.addAppender(appender); - } - - static void configureViaXML_File() { - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - try { - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - lc.stop(); - URL url = Loader.getResourceBySelfClassLoader("chapter7/simpleMDC.xml"); - configurator.doConfigure(url); - } catch (JoranException je) { - StatusPrinter.print(lc); - } - } - -} +/** + * 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 chapter7; + +import java.net.URL; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.ConsoleAppender; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.StatusPrinter; + +public class SimpleMDC { + static public void main(String[] args) throws Exception { + // You can put values in the MDC at any time. Before anything else + // we put the first name + MDC.put("first", "Dorothy"); + + // configure via the configuration file "chapter7/simpleMDC.xml" + // which ships with the examples + configureViaXML_File(); + + // For educational purposes, the same configuration can + // be accomplished programmatically. + // + // programmaticConfiguration(); + + Logger logger = LoggerFactory.getLogger(SimpleMDC.class); + // We now put the last name + MDC.put("last", "Parker"); + + // The most beautiful two words in the English language according + // to Dorothy Parker: + logger.info("Check enclosed."); + logger.debug("The most beautiful two words in English."); + + MDC.put("first", "Richard"); + MDC.put("last", "Nixon"); + logger.info("I am not a crook."); + logger.info("Attributed to the former US president. 17 Nov 1973."); + } + + static void programmaticConfiguration() { + // Configure logback + LoggerContext loggerContext = (LoggerContext) LoggerFactory + .getILoggerFactory(); + loggerContext.reset(); + PatternLayout layout = new PatternLayout(); + layout.setContext(loggerContext); + layout.setPattern("%X{first} %X{last} - %m%n"); + layout.start(); + ConsoleAppender appender = new ConsoleAppender(); + appender.setContext(loggerContext); + appender.setLayout(layout); + appender.start(); + // cast root logger to c.q.logback.classic.Logger so that we can attach + // an appender to it + ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory + .getLogger("root"); + root.addAppender(appender); + } + + static void configureViaXML_File() { + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + try { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + lc.stop(); + URL url = Loader.getResourceBySelfClassLoader("chapter7/simpleMDC.xml"); + configurator.doConfigure(url); + } catch (JoranException je) { + StatusPrinter.print(lc); + } + } + +} diff --git a/logback-examples/src/main/java/chapter7/UserServletFilter.java b/logback-examples/src/main/java/chapter7/UserServletFilter.java index 228d2e57662a1f0b1e2be8a437317fdaedeba6cc..abd5d1a05c527a04899d15c5dd6f479ea6b9da32 100644 --- a/logback-examples/src/main/java/chapter7/UserServletFilter.java +++ b/logback-examples/src/main/java/chapter7/UserServletFilter.java @@ -1,98 +1,98 @@ -/** - * 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 chapter7; - -import java.io.IOException; -import java.security.Principal; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import org.slf4j.MDC; - -/** - * A simple servlet filter that puts the username - * found either in the Principle or as a session attribute - * in the MDC. - * - * The value is removed from the MDC once the request has been - * fully processed. - * - * To be used, add the following lines to a web.xml file - * - * - * User Servlet Filter - * - * chapter7.UserServletFilter - * - * - * - * User Servlet Filter - * /* - * - * - * @author Sébastien Pennec - */ -public class UserServletFilter implements Filter { - - boolean userRegistered = false; - - private final String userKey = "username"; - - public void destroy() { - } - - public void doFilter(ServletRequest request, ServletResponse response, - FilterChain chain) throws IOException, ServletException { - - HttpServletRequest req = (HttpServletRequest) request; - Principal principal = req.getUserPrincipal(); - // Please note that we could have also used a cookie to - // retreive the user name - - if (principal != null) { - String username = principal.getName(); - registerUsername(username); - } else { - HttpSession session = req.getSession(); - String username = (String)session.getAttribute(userKey); - registerUsername(username); - } - - try { - chain.doFilter(request, response); - } finally { - if (userRegistered) { - MDC.remove(userKey); - } - } - } - - public void init(FilterConfig arg0) throws ServletException { - } - - private void registerUsername(String username) { - if (username != null && username.trim().length() > 0) { - MDC.put(userKey, username); - userRegistered = true; - } - } - -} +/** + * 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 chapter7; + +import java.io.IOException; +import java.security.Principal; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.slf4j.MDC; + +/** + * A simple servlet filter that puts the username + * found either in the Principle or as a session attribute + * in the MDC. + * + * The value is removed from the MDC once the request has been + * fully processed. + * + * To be used, add the following lines to a web.xml file + * + * + * User Servlet Filter + * + * chapter7.UserServletFilter + * + * + * + * User Servlet Filter + * /* + * + * + * @author Sébastien Pennec + */ +public class UserServletFilter implements Filter { + + boolean userRegistered = false; + + private final String userKey = "username"; + + public void destroy() { + } + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + HttpServletRequest req = (HttpServletRequest) request; + Principal principal = req.getUserPrincipal(); + // Please note that we could have also used a cookie to + // retreive the user name + + if (principal != null) { + String username = principal.getName(); + registerUsername(username); + } else { + HttpSession session = req.getSession(); + String username = (String)session.getAttribute(userKey); + registerUsername(username); + } + + try { + chain.doFilter(request, response); + } finally { + if (userRegistered) { + MDC.remove(userKey); + } + } + } + + public void init(FilterConfig arg0) throws ServletException { + } + + private void registerUsername(String username) { + if (username != null && username.trim().length() > 0) { + MDC.put(userKey, username); + userRegistered = true; + } + } + +} diff --git a/logback-examples/src/main/java/chapter7/mdc1.xml b/logback-examples/src/main/java/chapter7/mdc1.xml index 5a97bf9fbab1217893fa06144fdfbd39f5803280..497cc404c8d99f9e1bde7c53cc97706a604972cc 100644 --- a/logback-examples/src/main/java/chapter7/mdc1.xml +++ b/logback-examples/src/main/java/chapter7/mdc1.xml @@ -1,16 +1,16 @@ - - - - - - - %-4r [%thread] %-5level C:%X{client} N:%X{number} - %msg%n - - - - - - - - + + + + + + + %-4r [%thread] %-5level C:%X{client} N:%X{number} - %msg%n + + + + + + + + diff --git a/logback-examples/src/main/java/chapter7/simpleMDC.xml b/logback-examples/src/main/java/chapter7/simpleMDC.xml index 6a4e605955a32c2f744b1cc88bef539a54208002..87c18398ffdc701058126fcc60fa43232ce9e6eb 100644 --- a/logback-examples/src/main/java/chapter7/simpleMDC.xml +++ b/logback-examples/src/main/java/chapter7/simpleMDC.xml @@ -1,15 +1,15 @@ - - - - - - - %X{first} %X{last} - %m%n - - - - - - - + + + + + + + %X{first} %X{last} - %m%n + + + + + + + diff --git a/logback-site/pom.xml b/logback-site/pom.xml index 7f118aefd3fa6c891f2af1c00f93d1387e162a79..17763bcfbb5efb10654a7e098602cab96c47a6aa 100644 --- a/logback-site/pom.xml +++ b/logback-site/pom.xml @@ -1,76 +1,76 @@ - - - - ch.qos.logback - logback-parent - 0.9.18-SNAPSHOT - - - 4.0.0 - - ch.qos.logback - logback-site - jar - ${parent.version} - Logback Site - - http://logback.qos.ch - - - QOS.ch - http://www.qos.ch - - 1999 - - - - Eclipse Public License - v 1.0 - http://www.eclipse.org/legal/epl-v10.html - - - - GNU Lesser General Public License - http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - - - - - - - src/site/pages - - ../../../target/site - true - - - - - - - - - org.apache.maven.plugins - maven-site-plugin - - ${project.parent.basedir}/target/site - - - - org.apache.maven.plugins - - maven-project-info-reports-plugin - - - - - - - - - - - + + + + ch.qos.logback + logback-parent + 0.9.18-SNAPSHOT + + + 4.0.0 + + ch.qos.logback + logback-site + jar + ${parent.version} + Logback Site + + http://logback.qos.ch + + + QOS.ch + http://www.qos.ch + + 1999 + + + + Eclipse Public License - v 1.0 + http://www.eclipse.org/legal/epl-v10.html + + + + GNU Lesser General Public License + http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html + + + + + + + src/site/pages + + ../../../target/site + true + + + + + + + + + org.apache.maven.plugins + maven-site-plugin + + ${project.parent.basedir}/target/site + + + + org.apache.maven.plugins + + maven-project-info-reports-plugin + + + + + + + + + + + \ No newline at end of file diff --git a/logback-site/src/site/pages/.htaccess b/logback-site/src/site/pages/.htaccess index 3e599229308b364684aa782ab84e863242a95f9c..0873005599f61c940a107c92ee46e54af1dc0ddb 100644 --- a/logback-site/src/site/pages/.htaccess +++ b/logback-site/src/site/pages/.htaccess @@ -1,2 +1,2 @@ -Redirect jmxConfig.html http://logback.qos.ch/manual/jmxConfig.html +Redirect jmxConfig.html http://logback.qos.ch/manual/jmxConfig.html Redirect joran.html http://logback.qos.ch/manual/onJoran.html \ No newline at end of file diff --git a/logback-site/src/site/pages/access.html b/logback-site/src/site/pages/access.html index bd3c899f0beb8611e0bf0128b66d0652007a642d..f579138310b62aded9f6d2ef1ccf81bfbc963201 100644 --- a/logback-site/src/site/pages/access.html +++ b/logback-site/src/site/pages/access.html @@ -1,548 +1,548 @@ - - - - - - Logback Access - - - - - - - - - -

- -
-
- -

Access log with logback, Jetty and Tomcat

- -
- Authors: Ceki Gülcü, Sébastien Pennec -
- - - - -

Introduction

- -

The logback-access module integrates with Servlet containers - such as Jetty or Tomcat to provide rich and powerful HTTP-access - log functionality. -

- -

Logback was designed as a modular framework from the - start. Making logback-core reusable under different circumstances - without much recoding was one of our main goals. In accordance - with this strategy, logback-access builds on top of - logback-core.

- - -

Logback-access under Tomcat

- -

To use logback-access with Tomcat, after downlading the logback - distribution, place the files logback-core-VERSION.jar - and logback-access-VERSION.jar under - $TOMCAT_HOME/server/lib/ directory, where $TOMCAT_HOME is - the folder where you have installed Tomcat. We have tested - logback-access module with Tomcat version 5.5.26. -

- -

If you place the logback-core and logback-access jars in - $TOMCAT_HOME/server/lib and your webapps do not use - logback-classic, then everything should be fine. If however your - webapps do indeed use logback-classic, you must make sure to - bundle logback-core.jar under your webapps' - WEB-INF/lib directory. An alternative strategy is to place - logback-core.jar under $TOMCAT_HOME/common/lib. In that case, you - no longer need to place logback-core.jar in your web-apps. -

- -

LogbackValve

- -

The - ch.qos.logback.access.tomcat.LogbackValve class - extends Tomcat's - ValveBase class. Valves are usually associated together - to form a processing pipeline. -

- -

To configure Tomcat in order to use LogbackValve, - add the following lines to the tomcat server configuration file, - namely $TOMCAT_HOME/conf/server.xml: -

-
<Valve className="ch.qos.logback.access.tomcat.LogbackValve"/>
- -

This line is usually nested within an Engine element. -

- -

By default, LogbackValve looks for a configuration - file called logback-access.xml, in the same folder where - server.xml is located, that is in - $TOMCAT_HOME/conf/. This configuration file contains - directives for configuring logback-access components. It is used - to specify appenders where the logging requests will be - sent. Please refer to the logback-access - configuration section further below. -

- -

In order to help with troubleshooting, by default, the - LogbackValve will print its internal status at its - initialization. Typical output would look as: -

- -

21:56:09,921 |-INFO in c.q.lb.access.j.a.ConfigurationAction - Ignoring debug attribute. -21:56:09,921 |-INFO in c.q.lb.core.j.a.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender] -21:56:09,921 |-INFO in c.q.lb.core.j.a.AppenderAction - Naming appender as [STDOUT] -21:56:10,000 |-INFO in c.q.lb.core.j.a.NestedComponentIA - Pushing component [layout] on top of the object stack. -21:56:10,015 |-INFO in c.q.lb.core.j.a.AppenderAction - Popping appender named [STDOUT] from the object stack -21:56:10,015 |-INFO in c.q.lb.core.j.a.AppenderRefAction - Attaching appender named [STDOUT] to ch.qos.logback.access.tomcat.LogbackValve[Catalina] -21:56:10,015 |-INFO in c.q.lb.access.j.a.ConfigurationAction - End of configuration.

- -

It is possible to override default status printing by specifing - the "quiet" attribute in the Valve - element. Similarly, it is also possible to set the filename for - the logback-access configuration file. Here is an example. -

- -

<Valve className="ch.qos.logback.access.tomcat.LogbackValve" - quiet="true" filename="c:/my-logback-access.xml"/>

- -

Viewing status messages

- -

Logback-access ships with a servlet called - ViewStatusMessagesServlet. This servlet prints the - internal status messages of the LogbackValve as an - HTML table. Here is sample output. -

- - - - click to enlarge - - -

To add this servlet to your web-application, add the following - lines to its WEB-INF/web.xml file.

- -

<servlet> - <servlet-name>AccessViewStatusMessages</servlet-name> - <servlet-class>ch.qos.logback.access.ViewStatusMessagesServlet</servlet-class> - </servlet> - - <servlet-mapping> - <servlet-name>AccessViewStatusMessages</servlet-name> - <url-pattern>/lbAccessStatus</url-pattern> - </servlet-mapping>

- -

The ViewStatusMessages servlet will available - under the URL http://host/yourWebapp/lbAccessStatus -

- - -

Logback-access under Jetty

- -

After downlading the logback distribution, place the files - logback-core-VERSION.jar and - logback-access-VERSION.jar under $JETTY_HOME/lib - directory, where $JETTY_HOME is the folder where you have - installed Jetty. We have tested logback-access module with Jetty - version 6.0 as well as 6.1. -

- -

Logback's implementation of - org.mortbay.jetty.RequestLog interface

- -

The - ch.qos.logback.access.jetty.RequestLogImpl class - implements jetty's RequestLog - interface. Jetty delegates the manament of access logging - functionality to implementations of this interface. -

- -

In logback, a logging destination is called an "appender" which - can be directly attached to a - ch.qos.logback.access.jetty.RequestLogImpl instance. -

- - -

In order to configure Jetty to use logback-access's - RequestLogImpl, please add the following lines to - jetty's main configuration file, namely - $JETTY_HOME/etc/jetty.xml: -

-
<Ref id="requestLog">
-  <Set name="requestLog">
-    <New id="requestLogImpl"
-      class="ch.qos.logback.access.jetty.RequestLogImpl">
-    </New>
-  </Set>
-</Ref>
- -

By default, RequestLogImpl looks for a logback - configuration file called logback-access.xml, in the same - folder where jetty.xml is located. This configuration - file contains directives for configuring logback components. Among - others, you can specify the appenders where the logging requests - will be sent, and their format. -

- -

As long the path is specified, you can place the logback - configuration file in any location. Here is another example of - jetty configuration file, including the path to the - logback-access.xml configuration file. -

- -
<Ref id="requestLog">
-  <Set name="requestLog">
-    <New id="requestLogImpl"
-      class="ch.qos.logback.access.jetty.RequestLogImpl">
-    </New>
-    <Set name="fileName">path/to/myaccess.xml</Set>
-  </Set>
-</Ref>
- - -

Logback-access configuration

- -

Altough similar, the logback-access.xml file is slightly - different than its more common counterpart in logback-classic. - Appenders and Layouts are declared the exact same way. However, in - the access module there is no notion of loggers and consequently - logger elements are disallowed in logback-access configuraiton - files. -

- -

Example 1: basic logback-access configuration

-

- Here is a small but fully functional logback-access.xml - configuration file: -

-
<configuration>
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <layout
-      class="ch.qos.logback.access.PatternLayout">
-      <Pattern>%h %l %u %user %date "%r" %s %b</Pattern>
-    </layout>
-  </appender>
-
-  <appender-ref ref="STDOUT" />
-</configuration>
-

- It declares a ConsoleAppender which prints its output - on the console. The ConsoleAppender contains a - PatternLayout object responsible to format this - output. The log format is specied by the "%h %l %u %user %date - "%r" %s %b" pattern which incidentally corresponds to Common Log - Format (CLF). This format is recognized by log analysers such as - Analog or AWStats. -

- -

The words "common" or "clf" are interpreted as shorthands for - the said pattern. Thus, the following are all equivalent: -

- -
<Pattern>%h %l %u %user %date "%r" %s %b</Pattern>
-<Pattern>common</Pattern>
-<Pattern>clf</Pattern>
- -

The so called "combined" format is also widely recognized. It is - defined as the '%h %l %u %t "%r" %s %b "%i{Referer}" - "%i{User-Agent}"' pattern. As a facilitator, you can use the - "combined" as a shorthand. Thus, the following directive -

- -
<layout class="ch.qos.logback.access.PatternLayout">
-  <Pattern>%h %l %u %t "%r" %s %b "%i{Referer}" "%i{User-Agent}"</Pattern>
-</layout>
- -

is equivalent to:

- -
<layout class="ch.qos.logback.access.PatternLayout">
-  <Pattern>combined</Pattern>
-</layout>
- - -

Example 2: RollingFileAppender

- -

The configuration file below configures a daily rolling - RollingFileAppender. Note that due to the - .zip suffix included in the value for FileNamePattern option, the log file are not - only rolled daily, but they are also automatically compressed.

- - -
<configuration>
-  <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>
-
-    <layout class="ch.qos.logback.access.PatternLayout">
-      <Pattern">combined</Pattern">
-    </layout>
-  </appender>
- 
-  <appender-ref ref="FILE" />
-</configuration>
- -

These two examples should give you an idea of the possibilities - offered by logback-access. In principle, most if not all of the - features available in logback-classic are also available in - logback-access. -

- -

PatternLayout

- -

Logback-access ships with an http-specific implementation of - PatternLayout. For detailled instructions on how - to use the PatternLayout, please refer to the corresponding - chapter of the logback manual. -

- -

JMX Components

- -

Logback-access integrates with JMX servers to publish - information about its components. -

- -

Both RequestLogImpl and LogbackValve - expose data and can be updated via JMX. A special filter, covered - further down this document, publishes statistical data on access - logs. -

- - -

Configuring Tomcat for JMX

- -

In order to configure Tomcat for JMX, please add the following - lines to the $TOMCAT_HOME/bin/catalina.sh shell script - (or its MS Windows equivalent): -

- -
CATALINA_OPTS="-Dcom.sun.management.jmxremote"
-CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
-CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
- -

After you launch Tomcat, you can access the MBeans exposed by - Tomcat throught he JConsole application, which can be started with - the following command: -

-
jconsole
- -

If you prefer MX4J to access your components via a web-based - interface, here is a short summary of the steps to follow. After - downloading MX4J, place - the mx4j-impl.jar file in the $TOMCAT_HOME/bin/ - directory, and the mx4j-tools.jar file in the - $TOMCAT_HOME/common/lib/ directory. Once that is done, - add the following lines to the - $TOMCAT_HOME/bin/catalina.sh shell script: -

- -
<!-- at the beginning of the file -->
-CATALINA_OPTS="-Dcom.sun.management.jmxremote"
-CATALINA_OPTS="$CATALINA_OPTS -Djavax.management.builder.initial=mx4j.server.MX4JMBeanServerBuilder"
-
-<!-- in the "Add on extra jar files to CLASSPATH" section -->
-CLASSPATH="$CLASSPATH":"$CATALINA_HOME"/bin/mx4j-impl.jar
- -

- Finally, declare a new Connector in the - $TOMCAT_HOME/conf/server.xml file: -

- -
<Connector port="8050" 
-  handler.list="mx"
-  mx.enabled="true" 
-  mx.httpHost="localhost" 
-  mx.httpPort="8082" 
-  protocol="AJP/1.3" />
- -

- Once Tomcat is started, you should be able to reach your JMX - components by pointing your browser at the following URL: -

- -
http://localhost:8082/
- -

Configuring Jetty

- -

- Configuring Jetty to publish JMX components requires a few modifications to the - $JETTY_HOME/etc/jetty.xml configuration file. Here are the elements that need to be - added: -

- -
<Call id="MBeanServer" class="java.lang.management.ManagementFactory" name="getPlatformMBeanServer"/>
-<!-- initialize the Jetty MBean container -->
-<Get id="Container" name="container">
-  <Call name="addEventListener">
-    <Arg>
-      <New class="org.mortbay.management.MBeanContainer">
-        <Arg><Ref id="MBeanServer"/></Arg>
-        <Set name="managementPort">8082</Set>
-        <Call name="start" />
-      </New>
-    </Arg>
-  </Call>
-</Get>
- -

Once Jetty is started with this configuration, all available - components can be reviewed at: -

-
http://localhost:8082/
- -

Logback-access' RequestLogImpl should be - available, including its start() and - stop() methods. -

- - -

CountingFilter

- -

With the help of CountingFilter - class, logback-access can provide statistical data about access to - the web-server. -

- -

If you wish to make use of CountingFilter, you to - declare it, as any other filter: -

- -
<configuration>
-  <filter class="ch.qos.logback.access.filter.CountingFilter">
-    <name>countingFilter</name>
-  </filter>
-
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.access.PatternLayout">
-      <Pattern>%h %l %u %t \"%r\" %s %b</Pattern>
-    </layout>
-  </appender>
-
-  <appender-ref ref="STDOUT" />
-</configuration>
- -

- This component registers itself to the JMX server and publishes - the statistical data such as averages by minute, by hour, by - day, by week, and by month. Last month's, week's, day's, hour's - and minute's counts as well as the total number of access are - also exposed. -

- - -

TeeFilter

- -

For debugging purposes, it is often handy to capture the client - request as well as the server response as is. The - TeeFilter was desgined precisely for this purpose. -

- -

The TeeFilter is a regular servlet filter. Like other - servlet filters, it needs to be declared in your web-application's - web.xml file: -

- -
<filter> - <filter-name>TeeFilter</filter-name> - <filter-class>ch.qos.logback.access.servlet.TeeFilter</filter-class> -</filter> - -<filter-mapping> - <filter-name>TeeFilter</filter-name> - <url-pattern>/*</url-pattern> -</filter-mapping> -
- -

We have tested TeeFilter to the best of our - ability. However, since it duplicates the input stream of the - request and the output stream of the response, it may interfere with - your application. For large input or output, it will add masurable - latency. Although we have already fixed all currently known bugs, - TeeFilter has broken otherwise correctly behaving - applications. Thus, in case of doubt, do not hesitate to disabl - TeeFilter. - -

- -

Once TeeFilter is installed, the PatternLayout - converters fullRequest and fullResponse - will output the full contents of the request and respectively the - response. -

- -

Here is a sample logback-access.xml configuration file which will - output the full contents of the request and response on the console. -

- -

<configuration> - <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> - <layout class="ch.qos.logback.access.PatternLayout"> - <Pattern>%fullRequest%n%n%fullResponse</Pattern> - </layout> - </appender> - - <appender-ref ref="STDOUT" /> -</configuration>

- -

Few clicks accessing the logback-demo - application configured as outlined above, yeilds:

- -

GET /logback-demo/index.jsp HTTP/1.1 -Host: localhost:8080 -User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.11) Gecko/20070312 Firefox/1.5.0.11 -Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 -Accept-Language: en-us,en;q=0.5 -Accept-Encoding: gzip,deflate -Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 -Keep-Alive: 300 -Connection: keep-alive -Referer: http://localhost:8080/logback-demo/login.jsp -Cookie: JSESSIONID=15c7tqi9ehlwk; OID324nkzcmr=null; OID32862zgoa=null; - - - -HTTP/1.1 200 OK -Content-Type: text/html; charset=iso-8859-1 -Expires: Thu, 01 Jan 1970 00:00:00 GMT -Set-Cookie: JSESSIONID=bgebt99ce9om;path=/logback-demo - - -<html> -<head> - <LINK REL=StyleSheet HREF="css/pk.css" /> -</head> -<body> - -<h2>Logback demo center</h2> - -[snip, so that text is reasonably sized]

- -

 

- - - -
- - - + + + + + + Logback Access + + + + + + + + + +
+ +
+
+ +

Access log with logback, Jetty and Tomcat

+ +
+ Authors: Ceki Gülcü, Sébastien Pennec +
+ + + + +

Introduction

+ +

The logback-access module integrates with Servlet containers + such as Jetty or Tomcat to provide rich and powerful HTTP-access + log functionality. +

+ +

Logback was designed as a modular framework from the + start. Making logback-core reusable under different circumstances + without much recoding was one of our main goals. In accordance + with this strategy, logback-access builds on top of + logback-core.

+ + +

Logback-access under Tomcat

+ +

To use logback-access with Tomcat, after downlading the logback + distribution, place the files logback-core-VERSION.jar + and logback-access-VERSION.jar under + $TOMCAT_HOME/server/lib/ directory, where $TOMCAT_HOME is + the folder where you have installed Tomcat. We have tested + logback-access module with Tomcat version 5.5.26. +

+ +

If you place the logback-core and logback-access jars in + $TOMCAT_HOME/server/lib and your webapps do not use + logback-classic, then everything should be fine. If however your + webapps do indeed use logback-classic, you must make sure to + bundle logback-core.jar under your webapps' + WEB-INF/lib directory. An alternative strategy is to place + logback-core.jar under $TOMCAT_HOME/common/lib. In that case, you + no longer need to place logback-core.jar in your web-apps. +

+ +

LogbackValve

+ +

The + ch.qos.logback.access.tomcat.LogbackValve class + extends Tomcat's + ValveBase class. Valves are usually associated together + to form a processing pipeline. +

+ +

To configure Tomcat in order to use LogbackValve, + add the following lines to the tomcat server configuration file, + namely $TOMCAT_HOME/conf/server.xml: +

+
<Valve className="ch.qos.logback.access.tomcat.LogbackValve"/>
+ +

This line is usually nested within an Engine element. +

+ +

By default, LogbackValve looks for a configuration + file called logback-access.xml, in the same folder where + server.xml is located, that is in + $TOMCAT_HOME/conf/. This configuration file contains + directives for configuring logback-access components. It is used + to specify appenders where the logging requests will be + sent. Please refer to the logback-access + configuration section further below. +

+ +

In order to help with troubleshooting, by default, the + LogbackValve will print its internal status at its + initialization. Typical output would look as: +

+ +

21:56:09,921 |-INFO in c.q.lb.access.j.a.ConfigurationAction - Ignoring debug attribute. +21:56:09,921 |-INFO in c.q.lb.core.j.a.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender] +21:56:09,921 |-INFO in c.q.lb.core.j.a.AppenderAction - Naming appender as [STDOUT] +21:56:10,000 |-INFO in c.q.lb.core.j.a.NestedComponentIA - Pushing component [layout] on top of the object stack. +21:56:10,015 |-INFO in c.q.lb.core.j.a.AppenderAction - Popping appender named [STDOUT] from the object stack +21:56:10,015 |-INFO in c.q.lb.core.j.a.AppenderRefAction - Attaching appender named [STDOUT] to ch.qos.logback.access.tomcat.LogbackValve[Catalina] +21:56:10,015 |-INFO in c.q.lb.access.j.a.ConfigurationAction - End of configuration.

+ +

It is possible to override default status printing by specifing + the "quiet" attribute in the Valve + element. Similarly, it is also possible to set the filename for + the logback-access configuration file. Here is an example. +

+ +

<Valve className="ch.qos.logback.access.tomcat.LogbackValve" + quiet="true" filename="c:/my-logback-access.xml"/>

+ +

Viewing status messages

+ +

Logback-access ships with a servlet called + ViewStatusMessagesServlet. This servlet prints the + internal status messages of the LogbackValve as an + HTML table. Here is sample output. +

+ + + + click to enlarge + + +

To add this servlet to your web-application, add the following + lines to its WEB-INF/web.xml file.

+ +

<servlet> + <servlet-name>AccessViewStatusMessages</servlet-name> + <servlet-class>ch.qos.logback.access.ViewStatusMessagesServlet</servlet-class> + </servlet> + + <servlet-mapping> + <servlet-name>AccessViewStatusMessages</servlet-name> + <url-pattern>/lbAccessStatus</url-pattern> + </servlet-mapping>

+ +

The ViewStatusMessages servlet will available + under the URL http://host/yourWebapp/lbAccessStatus +

+ + +

Logback-access under Jetty

+ +

After downlading the logback distribution, place the files + logback-core-VERSION.jar and + logback-access-VERSION.jar under $JETTY_HOME/lib + directory, where $JETTY_HOME is the folder where you have + installed Jetty. We have tested logback-access module with Jetty + version 6.0 as well as 6.1. +

+ +

Logback's implementation of + org.mortbay.jetty.RequestLog interface

+ +

The + ch.qos.logback.access.jetty.RequestLogImpl class + implements jetty's RequestLog + interface. Jetty delegates the manament of access logging + functionality to implementations of this interface. +

+ +

In logback, a logging destination is called an "appender" which + can be directly attached to a + ch.qos.logback.access.jetty.RequestLogImpl instance. +

+ + +

In order to configure Jetty to use logback-access's + RequestLogImpl, please add the following lines to + jetty's main configuration file, namely + $JETTY_HOME/etc/jetty.xml: +

+
<Ref id="requestLog">
+  <Set name="requestLog">
+    <New id="requestLogImpl"
+      class="ch.qos.logback.access.jetty.RequestLogImpl">
+    </New>
+  </Set>
+</Ref>
+ +

By default, RequestLogImpl looks for a logback + configuration file called logback-access.xml, in the same + folder where jetty.xml is located. This configuration + file contains directives for configuring logback components. Among + others, you can specify the appenders where the logging requests + will be sent, and their format. +

+ +

As long the path is specified, you can place the logback + configuration file in any location. Here is another example of + jetty configuration file, including the path to the + logback-access.xml configuration file. +

+ +
<Ref id="requestLog">
+  <Set name="requestLog">
+    <New id="requestLogImpl"
+      class="ch.qos.logback.access.jetty.RequestLogImpl">
+    </New>
+    <Set name="fileName">path/to/myaccess.xml</Set>
+  </Set>
+</Ref>
+ + +

Logback-access configuration

+ +

Altough similar, the logback-access.xml file is slightly + different than its more common counterpart in logback-classic. + Appenders and Layouts are declared the exact same way. However, in + the access module there is no notion of loggers and consequently + logger elements are disallowed in logback-access configuraiton + files. +

+ +

Example 1: basic logback-access configuration

+

+ Here is a small but fully functional logback-access.xml + configuration file: +

+
<configuration>
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <layout
+      class="ch.qos.logback.access.PatternLayout">
+      <Pattern>%h %l %u %user %date "%r" %s %b</Pattern>
+    </layout>
+  </appender>
+
+  <appender-ref ref="STDOUT" />
+</configuration>
+

+ It declares a ConsoleAppender which prints its output + on the console. The ConsoleAppender contains a + PatternLayout object responsible to format this + output. The log format is specied by the "%h %l %u %user %date + "%r" %s %b" pattern which incidentally corresponds to Common Log + Format (CLF). This format is recognized by log analysers such as + Analog or AWStats. +

+ +

The words "common" or "clf" are interpreted as shorthands for + the said pattern. Thus, the following are all equivalent: +

+ +
<Pattern>%h %l %u %user %date "%r" %s %b</Pattern>
+<Pattern>common</Pattern>
+<Pattern>clf</Pattern>
+ +

The so called "combined" format is also widely recognized. It is + defined as the '%h %l %u %t "%r" %s %b "%i{Referer}" + "%i{User-Agent}"' pattern. As a facilitator, you can use the + "combined" as a shorthand. Thus, the following directive +

+ +
<layout class="ch.qos.logback.access.PatternLayout">
+  <Pattern>%h %l %u %t "%r" %s %b "%i{Referer}" "%i{User-Agent}"</Pattern>
+</layout>
+ +

is equivalent to:

+ +
<layout class="ch.qos.logback.access.PatternLayout">
+  <Pattern>combined</Pattern>
+</layout>
+ + +

Example 2: RollingFileAppender

+ +

The configuration file below configures a daily rolling + RollingFileAppender. Note that due to the + .zip suffix included in the value for FileNamePattern option, the log file are not + only rolled daily, but they are also automatically compressed.

+ + +
<configuration>
+  <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>
+
+    <layout class="ch.qos.logback.access.PatternLayout">
+      <Pattern">combined</Pattern">
+    </layout>
+  </appender>
+ 
+  <appender-ref ref="FILE" />
+</configuration>
+ +

These two examples should give you an idea of the possibilities + offered by logback-access. In principle, most if not all of the + features available in logback-classic are also available in + logback-access. +

+ +

PatternLayout

+ +

Logback-access ships with an http-specific implementation of + PatternLayout. For detailled instructions on how + to use the PatternLayout, please refer to the corresponding + chapter of the logback manual. +

+ +

JMX Components

+ +

Logback-access integrates with JMX servers to publish + information about its components. +

+ +

Both RequestLogImpl and LogbackValve + expose data and can be updated via JMX. A special filter, covered + further down this document, publishes statistical data on access + logs. +

+ + +

Configuring Tomcat for JMX

+ +

In order to configure Tomcat for JMX, please add the following + lines to the $TOMCAT_HOME/bin/catalina.sh shell script + (or its MS Windows equivalent): +

+ +
CATALINA_OPTS="-Dcom.sun.management.jmxremote"
+CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
+CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
+ +

After you launch Tomcat, you can access the MBeans exposed by + Tomcat throught he JConsole application, which can be started with + the following command: +

+
jconsole
+ +

If you prefer MX4J to access your components via a web-based + interface, here is a short summary of the steps to follow. After + downloading MX4J, place + the mx4j-impl.jar file in the $TOMCAT_HOME/bin/ + directory, and the mx4j-tools.jar file in the + $TOMCAT_HOME/common/lib/ directory. Once that is done, + add the following lines to the + $TOMCAT_HOME/bin/catalina.sh shell script: +

+ +
<!-- at the beginning of the file -->
+CATALINA_OPTS="-Dcom.sun.management.jmxremote"
+CATALINA_OPTS="$CATALINA_OPTS -Djavax.management.builder.initial=mx4j.server.MX4JMBeanServerBuilder"
+
+<!-- in the "Add on extra jar files to CLASSPATH" section -->
+CLASSPATH="$CLASSPATH":"$CATALINA_HOME"/bin/mx4j-impl.jar
+ +

+ Finally, declare a new Connector in the + $TOMCAT_HOME/conf/server.xml file: +

+ +
<Connector port="8050" 
+  handler.list="mx"
+  mx.enabled="true" 
+  mx.httpHost="localhost" 
+  mx.httpPort="8082" 
+  protocol="AJP/1.3" />
+ +

+ Once Tomcat is started, you should be able to reach your JMX + components by pointing your browser at the following URL: +

+ +
http://localhost:8082/
+ +

Configuring Jetty

+ +

+ Configuring Jetty to publish JMX components requires a few modifications to the + $JETTY_HOME/etc/jetty.xml configuration file. Here are the elements that need to be + added: +

+ +
<Call id="MBeanServer" class="java.lang.management.ManagementFactory" name="getPlatformMBeanServer"/>
+<!-- initialize the Jetty MBean container -->
+<Get id="Container" name="container">
+  <Call name="addEventListener">
+    <Arg>
+      <New class="org.mortbay.management.MBeanContainer">
+        <Arg><Ref id="MBeanServer"/></Arg>
+        <Set name="managementPort">8082</Set>
+        <Call name="start" />
+      </New>
+    </Arg>
+  </Call>
+</Get>
+ +

Once Jetty is started with this configuration, all available + components can be reviewed at: +

+
http://localhost:8082/
+ +

Logback-access' RequestLogImpl should be + available, including its start() and + stop() methods. +

+ + +

CountingFilter

+ +

With the help of CountingFilter + class, logback-access can provide statistical data about access to + the web-server. +

+ +

If you wish to make use of CountingFilter, you to + declare it, as any other filter: +

+ +
<configuration>
+  <filter class="ch.qos.logback.access.filter.CountingFilter">
+    <name>countingFilter</name>
+  </filter>
+
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.access.PatternLayout">
+      <Pattern>%h %l %u %t \"%r\" %s %b</Pattern>
+    </layout>
+  </appender>
+
+  <appender-ref ref="STDOUT" />
+</configuration>
+ +

+ This component registers itself to the JMX server and publishes + the statistical data such as averages by minute, by hour, by + day, by week, and by month. Last month's, week's, day's, hour's + and minute's counts as well as the total number of access are + also exposed. +

+ + +

TeeFilter

+ +

For debugging purposes, it is often handy to capture the client + request as well as the server response as is. The + TeeFilter was desgined precisely for this purpose. +

+ +

The TeeFilter is a regular servlet filter. Like other + servlet filters, it needs to be declared in your web-application's + web.xml file: +

+ +
<filter> + <filter-name>TeeFilter</filter-name> + <filter-class>ch.qos.logback.access.servlet.TeeFilter</filter-class> +</filter> + +<filter-mapping> + <filter-name>TeeFilter</filter-name> + <url-pattern>/*</url-pattern> +</filter-mapping> +
+ +

We have tested TeeFilter to the best of our + ability. However, since it duplicates the input stream of the + request and the output stream of the response, it may interfere with + your application. For large input or output, it will add masurable + latency. Although we have already fixed all currently known bugs, + TeeFilter has broken otherwise correctly behaving + applications. Thus, in case of doubt, do not hesitate to disabl + TeeFilter. + +

+ +

Once TeeFilter is installed, the PatternLayout + converters fullRequest and fullResponse + will output the full contents of the request and respectively the + response. +

+ +

Here is a sample logback-access.xml configuration file which will + output the full contents of the request and response on the console. +

+ +

<configuration> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <layout class="ch.qos.logback.access.PatternLayout"> + <Pattern>%fullRequest%n%n%fullResponse</Pattern> + </layout> + </appender> + + <appender-ref ref="STDOUT" /> +</configuration>

+ +

Few clicks accessing the logback-demo + application configured as outlined above, yeilds:

+ +

GET /logback-demo/index.jsp HTTP/1.1 +Host: localhost:8080 +User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.11) Gecko/20070312 Firefox/1.5.0.11 +Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 +Accept-Language: en-us,en;q=0.5 +Accept-Encoding: gzip,deflate +Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 +Keep-Alive: 300 +Connection: keep-alive +Referer: http://localhost:8080/logback-demo/login.jsp +Cookie: JSESSIONID=15c7tqi9ehlwk; OID324nkzcmr=null; OID32862zgoa=null; + + + +HTTP/1.1 200 OK +Content-Type: text/html; charset=iso-8859-1 +Expires: Thu, 01 Jan 1970 00:00:00 GMT +Set-Cookie: JSESSIONID=bgebt99ce9om;path=/logback-demo + + +<html> +<head> + <LINK REL=StyleSheet HREF="css/pk.css" /> +</head> +<body> + +<h2>Logback demo center</h2> + +[snip, so that text is reasonably sized]

+ +

 

+ + + +
+ + + diff --git a/logback-site/src/site/pages/bridge.html b/logback-site/src/site/pages/bridge.html index 0c656ae45e322493e6eec321c7b0006cf531560b..104b8500606a510083b2f6ab88e9e323d982e71f 100644 --- a/logback-site/src/site/pages/bridge.html +++ b/logback-site/src/site/pages/bridge.html @@ -1,38 +1,38 @@ - - - - -Log4j Bridge - - - - - - - - - - - -
- -
- -
- -

Log4j bridge

- -

This module has migrated into the SLF4J project, its original - home. It has also been renamed as log4j-over-slf4j. -

- - - -
- - + + + + +Log4j Bridge + + + + + + + + + + + +
+ +
+ +
+ +

Log4j bridge

+ +

This module has migrated into the SLF4J project, its original + home. It has also been renamed as log4j-over-slf4j. +

+ + + +
+ + diff --git a/logback-site/src/site/pages/bugreport.html b/logback-site/src/site/pages/bugreport.html index cea7681aef55ac39f3ac12a5d8b23464305682fa..b22e383983097b69371c56bcbbc42115501de27e 100644 --- a/logback-site/src/site/pages/bugreport.html +++ b/logback-site/src/site/pages/bugreport.html @@ -1,91 +1,91 @@ - - - - - Bug report - - - - - - - - -
- -
-
- - - - -

Before you report a bug

- -

The logback community consists of those who use logback and its - modules, help answer questions on discussions lists, contribute - documentation and patches, and those who develop and maintain its - code. Almost all those who assist on a day to day basis resolving - bug reports do this for a wide variety of reasons, and almost all - of them do this on their own time.

- -

Many bugs reported end up not being a bug in logback, but are - due to misconfiguration, problems caused by installed - applications, the operating system, etc. -

- -

Before reporting a bug please make every effort to resolve the - problem yourself. Just reporting a bug will not fix it. A good - bug report includes a detailed description of the problem and a - succinct test case which can reproduce the problem. -

- -

Review the documentation

- -

Review the documentation for the version of component you are - using. The problem you are having may already be addressed in the - docs. -

- -

Search the mailing list archives

- -

It is very likely you are not the first to run into a problem. - Others may have already found a solution. Our various mailing lists - are likely to have discussed this problem before. -

- -

Search JIRA

- -

Please search the bug database to see if the bug you are seeing - has already been reported. The bug may have already been fixed - and is available in a later version. If someone else has reported - the same bug, you could add supporting information to help - reproduce and resolve the bug. -

- - - -

Reporting a bug

- -

Only after you have exhausted the aforementioned steps, should - you file a formal report in JIRA, our bug tracking system. -

- -

Please make sure you provide as much information as possible. - It is hard to fix a bug if the person looking into the problem - cannot reproduce it. -

- - - - -
- - + + + + + Bug report + + + + + + + + +
+ +
+
+ + + + +

Before you report a bug

+ +

The logback community consists of those who use logback and its + modules, help answer questions on discussions lists, contribute + documentation and patches, and those who develop and maintain its + code. Almost all those who assist on a day to day basis resolving + bug reports do this for a wide variety of reasons, and almost all + of them do this on their own time.

+ +

Many bugs reported end up not being a bug in logback, but are + due to misconfiguration, problems caused by installed + applications, the operating system, etc. +

+ +

Before reporting a bug please make every effort to resolve the + problem yourself. Just reporting a bug will not fix it. A good + bug report includes a detailed description of the problem and a + succinct test case which can reproduce the problem. +

+ +

Review the documentation

+ +

Review the documentation for the version of component you are + using. The problem you are having may already be addressed in the + docs. +

+ +

Search the mailing list archives

+ +

It is very likely you are not the first to run into a problem. + Others may have already found a solution. Our various mailing lists + are likely to have discussed this problem before. +

+ +

Search JIRA

+ +

Please search the bug database to see if the bug you are seeing + has already been reported. The bug may have already been fixed + and is available in a later version. If someone else has reported + the same bug, you could add supporting information to help + reproduce and resolve the bug. +

+ + + +

Reporting a bug

+ +

Only after you have exhausted the aforementioned steps, should + you file a formal report in JIRA, our bug tracking system. +

+ +

Please make sure you provide as much information as possible. + It is hard to fix a bug if the person looking into the problem + cannot reproduce it. +

+ + + + +
+ + diff --git a/logback-site/src/site/pages/cla.txt b/logback-site/src/site/pages/cla.txt index cce3714f93a9db006e950f38f4134ce5056d4507..f13018d7fc6520c23e6f6c8d8965d36641a2114b 100644 --- a/logback-site/src/site/pages/cla.txt +++ b/logback-site/src/site/pages/cla.txt @@ -1,124 +1,124 @@ - QOS.ch - Individual Contributor License Agreement ("Agreement") - -This agreement is an adaptation of the Apache Software Foundation ICL -agreement where references to ASF have been replaced by QOS.ch. We -thank the ASF for allowing QOS.ch to make use of their ICL agreement. - -Thank you for your interest in QOS.ch. In order to clarify the -intellectual property license granted with Contributions from any -person or entity, QOS.ch must have a Contributor License Agreement -("CLA") on file that has been signed by each Contributor, indicating -agreement to the license terms below. This license is for your -protection as a Contributor as well as the protection of QOS.ch and -its users; it does not change your rights to use your own -Contributions for any other purpose. If you have not already done so, -please complete and send an original signed Agreement to QOS.ch, rue -Enning 4, 1003 Lausanne, Switzerland. Please read this document -carefully before signing and keep a copy for your records. - - Full name: ____________________________ E-Mail: ___________________ - - Mailing Address: ______________________ Telephone: ___________________ - - _______________________________________________________________________ - - _______________________________________ Country: ___________________ - - -You accept and agree to the following terms and conditions for Your -present and future Contributions submitted QOS.ch. In return, QOS.ch -shall not use Your Contributions in a way that is contrary to the -public benefit. Except for the license granted herein to QOS.ch and -recipients of software distributed by QOS.ch, You reserve all right, -title, and interest in and to Your Contributions. - -1. Definitions. - - "You" (or "Your") shall mean the copyright owner or legal entity - authorized by the copyright owner that is making this Agreement - with QOS.ch. For legal entities, the entity making a Contribution - and all other entities that control, are controlled by, or are - under common control with that entity are considered to be a single - Contributor. For the purposes of this definition, "control" means - (i) the power, direct or indirect, to cause the direction or - management of such entity, whether by contract or otherwise, or - (ii) ownership of fifty percent (50%) or more of the outstanding - shares, or (iii) beneficial ownership of such entity. - - "Contribution" shall mean any original work of authorship, - including any modifications or additions to an existing work, that - is intentionally submitted by You to QOS.ch for inclusion in, or - documentation of, any of the products owned or managed by QOS.ch - (the "Work"). For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to QOS.ch or its representatives, including but not limited to - communication on electronic mailing lists, source code control - systems, and issue tracking systems that are managed by, or on - behalf of, QOS.ch for the purpose of discussing and improving the - Work, but excluding communication that is conspicuously marked or - otherwise designated in writing by You as "Not a Contribution." - -2. Grant of Copyright License. Subject to the terms and conditions of - this Agreement, You hereby grant to QOS.ch and to recipients of - software distributed by QOS.ch a perpetual, worldwide, - non-exclusive, no-charge, royalty-free, irrevocable copyright - license to reproduce, prepare derivative works of, publicly - display, publicly perform, sublicense, and distribute Your - Contributions and such derivative works. - -3. Grant of Patent License. Subject to the terms and conditions of - this Agreement, You hereby grant to QOS.ch and to recipients of - software distributed by QOS.ch a perpetual, worldwide, - non-exclusive, no-charge, royalty-free, irrevocable (except as - stated in this section) patent license to make, have made, use, - offer to sell, sell, import, and otherwise transfer the Work, where - such license applies only to those patent claims licensable by You - that are necessarily infringed by Your Contribution(s) alone or by - combination of Your Contribution(s) with the Work to which such - Contribution(s) was submitted. If any entity institutes patent - litigation against You or any other entity (including a cross-claim - or counterclaim in a lawsuit) alleging that your Contribution, or - the Work to which you have contributed, constitutes direct or - contributory patent infringement, then any patent licenses granted - to that entity under this Agreement for that Contribution or Work - shall terminate as of the date such litigation is filed. - -4. You represent that you are legally entitled to grant the above - license. If your employer(s) has rights to intellectual property - that you create that includes your Contributions, you represent - that you have received permission to make Contributions on behalf - of that employer, that your employer has waived such rights for - your Contributions to QOS.ch. - -5. You represent that each of Your Contributions is Your original - creation (see section 7 for submissions on behalf of others). You - represent that Your Contribution submissions include complete - details of any third-party license or other restriction (including, - but not limited to, related patents and trademarks) of which you - are personally aware and which are associated with any part of Your - Contributions. - -6. You are not expected to provide support for Your Contributions, - except to the extent You desire to provide support. You may provide - support for free, for a fee, or not at all. Unless required by - applicable law or agreed to in writing, You provide Your - Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS - OF ANY KIND, either express or implied, including, without - limitation, any warranties or conditions of TITLE, NON- - INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. - -7. Should You wish to submit work that is not Your original creation, - You may submit it to QOS.ch separately from any Contribution, - identifying the complete details of its source and of any license - or other restriction (including, but not limited to, related - patents, trademarks, and license agreements) of which you are - personally aware, and conspicuously marking the work as "Submitted - on behalf of a third-party: [named here]". - -8. You agree to notify QOS.ch of any facts or circumstances of which - you become aware that would make these representations inaccurate - in any respect. - - -Please sign: __________________________________ Date: ________________ + QOS.ch + Individual Contributor License Agreement ("Agreement") + +This agreement is an adaptation of the Apache Software Foundation ICL +agreement where references to ASF have been replaced by QOS.ch. We +thank the ASF for allowing QOS.ch to make use of their ICL agreement. + +Thank you for your interest in QOS.ch. In order to clarify the +intellectual property license granted with Contributions from any +person or entity, QOS.ch must have a Contributor License Agreement +("CLA") on file that has been signed by each Contributor, indicating +agreement to the license terms below. This license is for your +protection as a Contributor as well as the protection of QOS.ch and +its users; it does not change your rights to use your own +Contributions for any other purpose. If you have not already done so, +please complete and send an original signed Agreement to QOS.ch, rue +Enning 4, 1003 Lausanne, Switzerland. Please read this document +carefully before signing and keep a copy for your records. + + Full name: ____________________________ E-Mail: ___________________ + + Mailing Address: ______________________ Telephone: ___________________ + + _______________________________________________________________________ + + _______________________________________ Country: ___________________ + + +You accept and agree to the following terms and conditions for Your +present and future Contributions submitted QOS.ch. In return, QOS.ch +shall not use Your Contributions in a way that is contrary to the +public benefit. Except for the license granted herein to QOS.ch and +recipients of software distributed by QOS.ch, You reserve all right, +title, and interest in and to Your Contributions. + +1. Definitions. + + "You" (or "Your") shall mean the copyright owner or legal entity + authorized by the copyright owner that is making this Agreement + with QOS.ch. For legal entities, the entity making a Contribution + and all other entities that control, are controlled by, or are + under common control with that entity are considered to be a single + Contributor. For the purposes of this definition, "control" means + (i) the power, direct or indirect, to cause the direction or + management of such entity, whether by contract or otherwise, or + (ii) ownership of fifty percent (50%) or more of the outstanding + shares, or (iii) beneficial ownership of such entity. + + "Contribution" shall mean any original work of authorship, + including any modifications or additions to an existing work, that + is intentionally submitted by You to QOS.ch for inclusion in, or + documentation of, any of the products owned or managed by QOS.ch + (the "Work"). For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to QOS.ch or its representatives, including but not limited to + communication on electronic mailing lists, source code control + systems, and issue tracking systems that are managed by, or on + behalf of, QOS.ch for the purpose of discussing and improving the + Work, but excluding communication that is conspicuously marked or + otherwise designated in writing by You as "Not a Contribution." + +2. Grant of Copyright License. Subject to the terms and conditions of + this Agreement, You hereby grant to QOS.ch and to recipients of + software distributed by QOS.ch a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable copyright + license to reproduce, prepare derivative works of, publicly + display, publicly perform, sublicense, and distribute Your + Contributions and such derivative works. + +3. Grant of Patent License. Subject to the terms and conditions of + this Agreement, You hereby grant to QOS.ch and to recipients of + software distributed by QOS.ch a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable (except as + stated in this section) patent license to make, have made, use, + offer to sell, sell, import, and otherwise transfer the Work, where + such license applies only to those patent claims licensable by You + that are necessarily infringed by Your Contribution(s) alone or by + combination of Your Contribution(s) with the Work to which such + Contribution(s) was submitted. If any entity institutes patent + litigation against You or any other entity (including a cross-claim + or counterclaim in a lawsuit) alleging that your Contribution, or + the Work to which you have contributed, constitutes direct or + contributory patent infringement, then any patent licenses granted + to that entity under this Agreement for that Contribution or Work + shall terminate as of the date such litigation is filed. + +4. You represent that you are legally entitled to grant the above + license. If your employer(s) has rights to intellectual property + that you create that includes your Contributions, you represent + that you have received permission to make Contributions on behalf + of that employer, that your employer has waived such rights for + your Contributions to QOS.ch. + +5. You represent that each of Your Contributions is Your original + creation (see section 7 for submissions on behalf of others). You + represent that Your Contribution submissions include complete + details of any third-party license or other restriction (including, + but not limited to, related patents and trademarks) of which you + are personally aware and which are associated with any part of Your + Contributions. + +6. You are not expected to provide support for Your Contributions, + except to the extent You desire to provide support. You may provide + support for free, for a fee, or not at all. Unless required by + applicable law or agreed to in writing, You provide Your + Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + OF ANY KIND, either express or implied, including, without + limitation, any warranties or conditions of TITLE, NON- + INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. + +7. Should You wish to submit work that is not Your original creation, + You may submit it to QOS.ch separately from any Contribution, + identifying the complete details of its source and of any license + or other restriction (including, but not limited to, related + patents, trademarks, and license agreements) of which you are + personally aware, and conspicuously marking the work as "Submitted + on behalf of a third-party: [named here]". + +8. You agree to notify QOS.ch of any facts or circumstances of which + you become aware that would make these representations inaccurate + in any respect. + + +Please sign: __________________________________ Date: ________________ diff --git a/logback-site/src/site/pages/codes.html b/logback-site/src/site/pages/codes.html index 17803db428c377ab43d057a54b58fb0b1222e855..c52a936647d94a4d4d5264fc8f86a1a8d020a727 100644 --- a/logback-site/src/site/pages/codes.html +++ b/logback-site/src/site/pages/codes.html @@ -1,307 +1,307 @@ - - - - - Logback Error Codes - - - - - - - - - - - -
- -
-
- -

Logback error messages and their meanings

- - -

The contextSelector cannot be - null in StaticLoggerBinder. - -

- -

An IllegalStateException is thrown when no - ContextSelector could be set for logback's - StaticLoggerBinder. In principle, this error can only - occur when the context selector is expressly specified by the user, - and when that context selector cannot not be instantiated correctly. -

- -

It should not happen when you are using the default or JNDI - context selectors. -

-
- -

- No remote host or - address is set for SocketAppender - -

- -

A remote host or address is mandatory for SocketAppender.

-

You can specify the remote host in the configuration file - as follows. -

- -

<appender name="SOCKET" - class="ch.qos.logback.classic.net.SocketAppender"> - ... - <remoteHost>127.0.0.1</remoteHost> - ... -</appender>

- - -
- -

- No remote port is set for - SocketAppender - -

- -

A remote port is mandatory for SocketAppender.

- -

You can specify the remote port in the configuration file - like this: -

- -

<appender name="SOCKET" class="ch.qos.logback.classic.net.SocketAppender"> - ... - <port>4560</port> - ... -</appender>

- - -
- - -

- - No Layout is set for SMTPAppender -

- -

A Layout is mandatory for - SMTPAppender. It allows SMPTPAppender to format logging - events before sending an email. -

- -

You can specify the Layout in a configuration file - as follows: -

- -

<appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender"> - ... - <layout class="ch.qos.logback.classic.PatternLayout"> - <pattern>%date [%thread] %-5level %logger - %msg%n"></pattern> - </layout> - ... -</appender>

- -

SMTPAppender is known to work well with PatternLayout - and HTMLLayout. -

- - -
- -

- Specified number is not in proper - int form, or not expected format. - -

- -

When you specify the MaxFileSize to be used by the - SizeBasedRollingPolicy, logback expects a rather precise - format: -

- -
    -
  • The number has to be an integer
  • -
  • You can add 'KB', 'MB' or 'GB' after the number. -
  • -
- -

Here are some correct values: 500KB, 15MB, 2GB.

- -
- -

- No - TriggeringPolicy was set for the - RollingFileAppender. - -

- -

The RollingFileAppender must be set up with a - TriggeringPolicy. It permits the Appender to know when - the rollover must be activated. -

- -

To find more information about TriggeringPolicy - objects, please read the following javadocs: -

- - - -

Please note that the TimeBasedRollingPolicy - is a TriggeringPolicy and and - RollingPolicy at the same time. -

- -
- - -

- No RollingPolicy was set - for the RollingFileAppender. - -

- -

The RollingFileAppender must be set up with - a RollingPolicy. It permits the Appender to - know what to do when a rollover is requested. -

- -

To find more information about RollingPolicy - objects, please read the following javadocs: -

- - - -

Please note that the TimeBasedRollingPolicy is a - TriggeringPolicy and and RollingPolicy at - the same time. -

- - -
- -

- - The FileNamePattern property is mandatory for both - TimeBasedRollingPolicy and - FixedWindowRollingPolicy. - -

- - -

The FileNamePattern property for both - TimeBasedRollingPolicy and - FixedWindowRollingPolicy is mandatory. -

- -

Please refer to the documentation of TimeBasedRollingPolicy - and FixedWindowRollingPolicy for - examples. -

- - -
- -

- - The File property must be set before - any rolling policy or triggering policy. - -

- -

The File property, if present, must - be placed before any rolling policy or triggering policy. Thus, in a - configuration file, the File property, - if present, must be declared declared before any rolling policy or - triggering policy declarations. -

- -
- -

- - The File property must be set before - FixedWindowRollingPolicy - -

- -

The File property is mandatory with - FixedWindowRollingPolicy. Moreover, the File option must be set before the - FixedWindowRollingPolicy element. -

- -

Refer to the logback manual on - - FixedWindowRollingPolicy for more information. -

- -
-

- Prudent mode is not supported - with FixedWindowRollingPolicy. -

- -

Given that FixedWindowRollingPolicy performs - multiple file rename operations suring roll over, and that these - operations cannot be guaranteed to be safe in a multi-JVM context, - prudent mode is not allowed in conjuction with a - FixedWindowRollingPolicy. -

- -
- -

SyslogAppender - does not admit a layout. -

- - -

Given that the format of a syslog request follows strict rules, - you cannot freely specify the layout to be used with - SyslogAppender. However, you can use SuffixPattern option instead to influence the - contents of the message sent to the syslog daemon. -

- -

For more information on SyslogAppeder please refer to the its documentation. -

- -
- - - -
- - + + + + + Logback Error Codes + + + + + + + + + + + +
+ +
+
+ +

Logback error messages and their meanings

+ + +

The contextSelector cannot be + null in StaticLoggerBinder. + +

+ +

An IllegalStateException is thrown when no + ContextSelector could be set for logback's + StaticLoggerBinder. In principle, this error can only + occur when the context selector is expressly specified by the user, + and when that context selector cannot not be instantiated correctly. +

+ +

It should not happen when you are using the default or JNDI + context selectors. +

+
+ +

+ No remote host or + address is set for SocketAppender + +

+ +

A remote host or address is mandatory for SocketAppender.

+

You can specify the remote host in the configuration file + as follows. +

+ +

<appender name="SOCKET" + class="ch.qos.logback.classic.net.SocketAppender"> + ... + <remoteHost>127.0.0.1</remoteHost> + ... +</appender>

+ + +
+ +

+ No remote port is set for + SocketAppender + +

+ +

A remote port is mandatory for SocketAppender.

+ +

You can specify the remote port in the configuration file + like this: +

+ +

<appender name="SOCKET" class="ch.qos.logback.classic.net.SocketAppender"> + ... + <port>4560</port> + ... +</appender>

+ + +
+ + +

+ + No Layout is set for SMTPAppender +

+ +

A Layout is mandatory for + SMTPAppender. It allows SMPTPAppender to format logging + events before sending an email. +

+ +

You can specify the Layout in a configuration file + as follows: +

+ +

<appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender"> + ... + <layout class="ch.qos.logback.classic.PatternLayout"> + <pattern>%date [%thread] %-5level %logger - %msg%n"></pattern> + </layout> + ... +</appender>

+ +

SMTPAppender is known to work well with PatternLayout + and HTMLLayout. +

+ + +
+ +

+ Specified number is not in proper + int form, or not expected format. + +

+ +

When you specify the MaxFileSize to be used by the + SizeBasedRollingPolicy, logback expects a rather precise + format: +

+ +
    +
  • The number has to be an integer
  • +
  • You can add 'KB', 'MB' or 'GB' after the number. +
  • +
+ +

Here are some correct values: 500KB, 15MB, 2GB.

+ +
+ +

+ No + TriggeringPolicy was set for the + RollingFileAppender. + +

+ +

The RollingFileAppender must be set up with a + TriggeringPolicy. It permits the Appender to know when + the rollover must be activated. +

+ +

To find more information about TriggeringPolicy + objects, please read the following javadocs: +

+ + + +

Please note that the TimeBasedRollingPolicy + is a TriggeringPolicy and and + RollingPolicy at the same time. +

+ +
+ + +

+ No RollingPolicy was set + for the RollingFileAppender. + +

+ +

The RollingFileAppender must be set up with + a RollingPolicy. It permits the Appender to + know what to do when a rollover is requested. +

+ +

To find more information about RollingPolicy + objects, please read the following javadocs: +

+ + + +

Please note that the TimeBasedRollingPolicy is a + TriggeringPolicy and and RollingPolicy at + the same time. +

+ + +
+ +

+ + The FileNamePattern property is mandatory for both + TimeBasedRollingPolicy and + FixedWindowRollingPolicy. + +

+ + +

The FileNamePattern property for both + TimeBasedRollingPolicy and + FixedWindowRollingPolicy is mandatory. +

+ +

Please refer to the documentation of TimeBasedRollingPolicy + and FixedWindowRollingPolicy for + examples. +

+ + +
+ +

+ + The File property must be set before + any rolling policy or triggering policy. + +

+ +

The File property, if present, must + be placed before any rolling policy or triggering policy. Thus, in a + configuration file, the File property, + if present, must be declared declared before any rolling policy or + triggering policy declarations. +

+ +
+ +

+ + The File property must be set before + FixedWindowRollingPolicy + +

+ +

The File property is mandatory with + FixedWindowRollingPolicy. Moreover, the File option must be set before the + FixedWindowRollingPolicy element. +

+ +

Refer to the logback manual on + + FixedWindowRollingPolicy for more information. +

+ +
+

+ Prudent mode is not supported + with FixedWindowRollingPolicy. +

+ +

Given that FixedWindowRollingPolicy performs + multiple file rename operations suring roll over, and that these + operations cannot be guaranteed to be safe in a multi-JVM context, + prudent mode is not allowed in conjuction with a + FixedWindowRollingPolicy. +

+ +
+ +

SyslogAppender + does not admit a layout. +

+ + +

Given that the format of a syslog request follows strict rules, + you cannot freely specify the layout to be used with + SyslogAppender. However, you can use SuffixPattern option instead to influence the + contents of the message sent to the syslog daemon. +

+ +

For more information on SyslogAppeder please refer to the its documentation. +

+ +
+ + + +
+ + diff --git a/logback-site/src/site/pages/consolePlugin.html b/logback-site/src/site/pages/consolePlugin.html index 2615e4b9877c49500ca4b99bf83ce87d3ff52f25..8079cbb4d5a34587ab90af5a7733b210860bcd03 100644 --- a/logback-site/src/site/pages/consolePlugin.html +++ b/logback-site/src/site/pages/consolePlugin.html @@ -1,329 +1,329 @@ - - - - - - Logback Console Plugin for Eclipse - - - - - - - - - - -
- -
-
- -

Logback Console Plugin for Eclipse

- -

During the development process, it is common for developers to - print log output on the console. Typically, the developer will - also customize the format of the log output by setting properties - of a PatternLayout instance. The Logback Console - Plugin for Eclipse serves the same purpose as the regular console, - but offers several advantages over the plain-old console. Below is - a list of key advantages of our plugin: -

- -
    - -
  • Event of level WARN and ERROR are colored in orange and - respectively in red.
  • - -
  • Go to the java class and line where any given logging request was - issued by double-clicking on its output line. -
  • - -
  • Filter events with logback's powerful filtering mechanism - without changing your logging configuration. -
  • - -
  • Change the output format dynamically whenever you chose to do so.
  • - - -
  • Easy configuration (only one line in your logback.xml file). -
  • - -
- -

Installation

- -

- Installing the plugin requires a few steps. First get the plugin from - our download page. -

- -

- Once the transfert is complete, unzip the file called - ch.qos.logback.eclipse_VERSION.zip. Place the folder - found inside the archive in the following directory: ECLIPSE_INSTALL/plugins/ - where ECLIPSE_INSTALL is the directory where you've installed Eclipse. -

- -

- Relaunching Eclipse should load the plugin. To access the logback plugin, open - the following menu: Window > Show view > Other... . You should see - the Logback View nested in the Logback category. Selecting the - view will add it to your workspace. -

- -

Logging to the logback plugin

- -

- Logging to the logback plugin takes a single line of configuration - in your logback.xml configuration file, as you can see below. -

- -
<?xml version="1.0" encoding="UTF-8"?>
-
-<configuration>
-
-  <consolePlugin />
-  
-</configuration>
- -

- This element will trigger the creation of a SocketAppender that will send - events to the localhost, on port 4321 by default. That's all it takes to run your - software and log to the logback plugin. By default, logging events are not filtered, but please - keep in mind that context-wide filtering in your logging configuration may affect the events - that are recieved by the logback plugin. -

- -

If you already have - a server running on the default port, you can specify the port that will be used - by adding a simple attribute to the xml element: -

- -
<?xml version="1.0" encoding="UTF-8"?>
-
-<configuration>
-
-  <consolePlugin port="4567" />
-  
-</configuration>
- -

- In that case, however, you will need to specify in the plugin preferences on which - port to listen for events. The plugin preferences will be covered in a following section - of this document. -

- -

Using the logback plugin

- -

- Once the Logback View is shown on your workspace, you might want to - configure it to fit your needs. Look at the right side of the plugin view. - You should see two buttons, along with the usual three Eclipse icons: -

- - buttons.gif - -

- The first button on the left clears the console. The second button toggles - the auto-scroll functionnality. When enabled, you will always see the latest - logs that have been recieved by the plugin. If you disable the auto scrolling, - the view will display the current logs, and add the new ones at the bottom of - the list. -

- -

- The third button opens a sub-menu that lets you configure the logback plugin. This - will be covered in a short moment. -

- -

- When your software logs events, they are displayed in the logback view as shown - below: -

- - sampleLogs.gif - -

- All events with the WARN level are displayed in orange. ERROR - level events are displayed in red. -

- -

- Double-clicking on a log entry will open a Java editor and show you the line - where the entry was requested. It is an easy way to be access directly - to the class and method that logged the selected entry. -

- -

- When an icon is shown on the left of the logging event, it means that the - logging event contains a stacktrace. Right-clicking on the line reveals - a sub-menu that lets you open Eclipse's StackTrace Console and display the - stacktrace. You can click on the underlined parts of the stack trace to open - an editor revealing the selected class. -

- - stackTrace.gif - -

Configuring the logback plugin

- -

- On the right of the view, right next to the auto-scroll toggle is - a button that opens a sub menu. -

- -

Preferences

- -

- The first item in this menu opens the plugin's preference window. -

- - prefs.gif - -

- In this window, you can configure the pattern that will be used by the plugin - to display the logs. By default, it is configured to show the following informations: -

- -
    -
  • - Relative time since launch -
  • -
  • - Level of the request -
  • -
  • - The thread name -
  • -
  • - Name of the logger. The name is automatically shortened when longer than - 25 characters -
  • -
  • - The message of the request -
  • -
- -

An important point about this pattern is that, if it is - modified, the changes are immediately reflected on the - current content of the logback view. That means - that if you would like to display an MDC value, or any - other information that the PatternLayout provides, you - can change it even after the logs have been requested. -

- -

- Along with the pattern, you can specify the port on which the plugin will listen - for logging events. You can also choose the font type and size that will be used - to display the logs in the logback view. -

- -

- Finally, you can choose how many logging events should be displayed in the - view before the list is trimmed. By default, the logback plugin will display - 20'000 events. Once this number is reached, the plugin automatically drops - the 30% oldest logs. Please note that changing this value to a too much higher - value might lead to memory issues, or even crashing Eclipse. -

- - -

Filters

- -

- The logback plugin lets you filter logging events when they are - recieved. It uses the powerfull EvaluatorFilterobjects - that are available in logback. For detailled information about these filters, you might want - to check the corresponding documentation - in the logback manual. In this document, we will only - cover some basic points, enough to get you started using the filtering - functionnality of the logback plugin. -

- -

- The second item of the sub-menu on the right of the logback view - opens the filter configuration window: -

- - filterWindow.gif - -

- The upper part of the window lists the filters that are currently - used by the logback plugin. The lower part lets you create, edit - or delete a filter. -

- -

- A filter is composed of three informations. First, a Java expression, - that will be evaluated for each logging event that is recieved by - the logback plugin. This expression can use a set of common variables - such as level, logger, message, - and several others. For a complete list of available variables, please - refer to the chapter - about filters in the logback manual. -

- -

- The second and third informations that compose a filter are the - action that will be taken depending on the result of the evaluation. - Three actions are possible: ACCEPT, DENY - or NEUTRAL. Setting a filter's reply to ACCEPT - or DENY will prevent the plugin from evaluating any - other filter and return a definitive result on the logging event. -

- -

- Let us create a filter that will drop any request that has a level - lower than INFO. A click on the New button creates - a new filter. Enter the following informations in the corresponding - fields: -

- -
    -
  • - Expression: level >= INFO -
  • -
  • - Action on filter match: NEUTRAL -
  • -
  • - Action on filter mismatch: DENY -
  • -
- -

- Here is what the window should look like, once you've - saved the filter. -

- - createFilter.gif - -

- We've just created a filter that will drop any requests whose - level is lower than INFO. Note the use of the NEUTRAL - value as the action to be taken when the filter is matched. Since - we do not know what other filters might want to do, there is not reason - to stop evaluating when the level is higher or equal to INFO. -

- -

- You may have noticed the two buttons on the left side of the filter windows - labelled Up and Down. An important concept ruling the filters - in logback is that filters are called in a chain. As we've seen above, - a filter returning ACCEPT or DENY will stop the chain - and have a direct impact on the logging event. It is sometimes important - to manage the order in which filters are called to achieve a specific - filtering policy. -

- -

- You should now be ready to experience the logback plugin and use its functionnalites. - If you have any question about its use, feel free to use the logback - mailing lists. -

- - - -
- - + + + + + + Logback Console Plugin for Eclipse + + + + + + + + + + +
+ +
+
+ +

Logback Console Plugin for Eclipse

+ +

During the development process, it is common for developers to + print log output on the console. Typically, the developer will + also customize the format of the log output by setting properties + of a PatternLayout instance. The Logback Console + Plugin for Eclipse serves the same purpose as the regular console, + but offers several advantages over the plain-old console. Below is + a list of key advantages of our plugin: +

+ +
    + +
  • Event of level WARN and ERROR are colored in orange and + respectively in red.
  • + +
  • Go to the java class and line where any given logging request was + issued by double-clicking on its output line. +
  • + +
  • Filter events with logback's powerful filtering mechanism + without changing your logging configuration. +
  • + +
  • Change the output format dynamically whenever you chose to do so.
  • + + +
  • Easy configuration (only one line in your logback.xml file). +
  • + +
+ +

Installation

+ +

+ Installing the plugin requires a few steps. First get the plugin from + our download page. +

+ +

+ Once the transfert is complete, unzip the file called + ch.qos.logback.eclipse_VERSION.zip. Place the folder + found inside the archive in the following directory: ECLIPSE_INSTALL/plugins/ + where ECLIPSE_INSTALL is the directory where you've installed Eclipse. +

+ +

+ Relaunching Eclipse should load the plugin. To access the logback plugin, open + the following menu: Window > Show view > Other... . You should see + the Logback View nested in the Logback category. Selecting the + view will add it to your workspace. +

+ +

Logging to the logback plugin

+ +

+ Logging to the logback plugin takes a single line of configuration + in your logback.xml configuration file, as you can see below. +

+ +
<?xml version="1.0" encoding="UTF-8"?>
+
+<configuration>
+
+  <consolePlugin />
+  
+</configuration>
+ +

+ This element will trigger the creation of a SocketAppender that will send + events to the localhost, on port 4321 by default. That's all it takes to run your + software and log to the logback plugin. By default, logging events are not filtered, but please + keep in mind that context-wide filtering in your logging configuration may affect the events + that are recieved by the logback plugin. +

+ +

If you already have + a server running on the default port, you can specify the port that will be used + by adding a simple attribute to the xml element: +

+ +
<?xml version="1.0" encoding="UTF-8"?>
+
+<configuration>
+
+  <consolePlugin port="4567" />
+  
+</configuration>
+ +

+ In that case, however, you will need to specify in the plugin preferences on which + port to listen for events. The plugin preferences will be covered in a following section + of this document. +

+ +

Using the logback plugin

+ +

+ Once the Logback View is shown on your workspace, you might want to + configure it to fit your needs. Look at the right side of the plugin view. + You should see two buttons, along with the usual three Eclipse icons: +

+ + buttons.gif + +

+ The first button on the left clears the console. The second button toggles + the auto-scroll functionnality. When enabled, you will always see the latest + logs that have been recieved by the plugin. If you disable the auto scrolling, + the view will display the current logs, and add the new ones at the bottom of + the list. +

+ +

+ The third button opens a sub-menu that lets you configure the logback plugin. This + will be covered in a short moment. +

+ +

+ When your software logs events, they are displayed in the logback view as shown + below: +

+ + sampleLogs.gif + +

+ All events with the WARN level are displayed in orange. ERROR + level events are displayed in red. +

+ +

+ Double-clicking on a log entry will open a Java editor and show you the line + where the entry was requested. It is an easy way to be access directly + to the class and method that logged the selected entry. +

+ +

+ When an icon is shown on the left of the logging event, it means that the + logging event contains a stacktrace. Right-clicking on the line reveals + a sub-menu that lets you open Eclipse's StackTrace Console and display the + stacktrace. You can click on the underlined parts of the stack trace to open + an editor revealing the selected class. +

+ + stackTrace.gif + +

Configuring the logback plugin

+ +

+ On the right of the view, right next to the auto-scroll toggle is + a button that opens a sub menu. +

+ +

Preferences

+ +

+ The first item in this menu opens the plugin's preference window. +

+ + prefs.gif + +

+ In this window, you can configure the pattern that will be used by the plugin + to display the logs. By default, it is configured to show the following informations: +

+ +
    +
  • + Relative time since launch +
  • +
  • + Level of the request +
  • +
  • + The thread name +
  • +
  • + Name of the logger. The name is automatically shortened when longer than + 25 characters +
  • +
  • + The message of the request +
  • +
+ +

An important point about this pattern is that, if it is + modified, the changes are immediately reflected on the + current content of the logback view. That means + that if you would like to display an MDC value, or any + other information that the PatternLayout provides, you + can change it even after the logs have been requested. +

+ +

+ Along with the pattern, you can specify the port on which the plugin will listen + for logging events. You can also choose the font type and size that will be used + to display the logs in the logback view. +

+ +

+ Finally, you can choose how many logging events should be displayed in the + view before the list is trimmed. By default, the logback plugin will display + 20'000 events. Once this number is reached, the plugin automatically drops + the 30% oldest logs. Please note that changing this value to a too much higher + value might lead to memory issues, or even crashing Eclipse. +

+ + +

Filters

+ +

+ The logback plugin lets you filter logging events when they are + recieved. It uses the powerfull EvaluatorFilterobjects + that are available in logback. For detailled information about these filters, you might want + to check the corresponding documentation + in the logback manual. In this document, we will only + cover some basic points, enough to get you started using the filtering + functionnality of the logback plugin. +

+ +

+ The second item of the sub-menu on the right of the logback view + opens the filter configuration window: +

+ + filterWindow.gif + +

+ The upper part of the window lists the filters that are currently + used by the logback plugin. The lower part lets you create, edit + or delete a filter. +

+ +

+ A filter is composed of three informations. First, a Java expression, + that will be evaluated for each logging event that is recieved by + the logback plugin. This expression can use a set of common variables + such as level, logger, message, + and several others. For a complete list of available variables, please + refer to the chapter + about filters in the logback manual. +

+ +

+ The second and third informations that compose a filter are the + action that will be taken depending on the result of the evaluation. + Three actions are possible: ACCEPT, DENY + or NEUTRAL. Setting a filter's reply to ACCEPT + or DENY will prevent the plugin from evaluating any + other filter and return a definitive result on the logging event. +

+ +

+ Let us create a filter that will drop any request that has a level + lower than INFO. A click on the New button creates + a new filter. Enter the following informations in the corresponding + fields: +

+ +
    +
  • + Expression: level >= INFO +
  • +
  • + Action on filter match: NEUTRAL +
  • +
  • + Action on filter mismatch: DENY +
  • +
+ +

+ Here is what the window should look like, once you've + saved the filter. +

+ + createFilter.gif + +

+ We've just created a filter that will drop any requests whose + level is lower than INFO. Note the use of the NEUTRAL + value as the action to be taken when the filter is matched. Since + we do not know what other filters might want to do, there is not reason + to stop evaluating when the level is higher or equal to INFO. +

+ +

+ You may have noticed the two buttons on the left side of the filter windows + labelled Up and Down. An important concept ruling the filters + in logback is that filters are called in a chain. As we've seen above, + a filter returning ACCEPT or DENY will stop the chain + and have a direct impact on the logging event. It is sometimes important + to manage the order in which filters are called to achieve a specific + filtering policy. +

+ +

+ You should now be ready to experience the logback plugin and use its functionnalites. + If you have any question about its use, feel free to use the logback + mailing lists. +

+ + + +
+ + diff --git a/logback-site/src/site/pages/css/_print.css b/logback-site/src/site/pages/css/_print.css index 243c24a50d15e0402f07580645d08b0aa7e60557..b38577971cb37f47fcfe53530af4b606a04be25c 100644 --- a/logback-site/src/site/pages/css/_print.css +++ b/logback-site/src/site/pages/css/_print.css @@ -1,31 +1,31 @@ - -body { - margin: 0px; - padding: 100px 0px 2px 0px; - line-height: 1.3em; - font-size: 12px; -} - -#left, #right { - width: 0px; - height: 0px; - display: none; - visibility:hidden; -} - -#bodyColumn { - margin-right: 1.5em; - margin-left: 0px; /*was: 197*/ -} - - -table.bodyTable td { - vertical-align: text-top; -} - -table.bodyTable th { - vertical-align: text-top; - text-align:center; -} - - + +body { + margin: 0px; + padding: 100px 0px 2px 0px; + line-height: 1.3em; + font-size: 12px; +} + +#left, #right { + width: 0px; + height: 0px; + display: none; + visibility:hidden; +} + +#bodyColumn { + margin-right: 1.5em; + margin-left: 0px; /*was: 197*/ +} + + +table.bodyTable td { + vertical-align: text-top; +} + +table.bodyTable th { + vertical-align: text-top; + text-align:center; +} + + diff --git a/logback-site/src/site/pages/css/common.css b/logback-site/src/site/pages/css/common.css index 2785f5503a02dedaee17c95282aab1ee1187e21b..e1aa3ca17d4dcdd17c2e5353f50bce1498571978 100644 --- a/logback-site/src/site/pages/css/common.css +++ b/logback-site/src/site/pages/css/common.css @@ -1,260 +1,260 @@ -html { -/* padding:0px; - margin:0px; */ -} - - -a { - color: #0000CC; - background-color:transparent; - text-decoration: none; -} - -#content a:hover { - text-decoration: underline; -} - -div.source { - margin-top: 1em; -} - -.longline { - overflow: scroll; -} - -.source, .command, .console { - border-top: 1px solid #DDDDDD; - border-bottom: 1px solid #DDDDDD; - background:#eee; - font-family: Courier, "MS Courier New", Prestige, monospace; - padding-left: 1ex; - white-space: pre; -} - -.source { - padding-bottom: 0.5ex; - padding-top: 0.5ex; -} - -.command { - padding-bottom: 0ex; - padding-top: 0ex; -} - -.console { -} - -pre { - padding: 0px; - margin: 0px; - background-color:transparent; - font-family: Courier, Monaco, Monospace; -} - -.alignright { - margin-top: 0; - text-align: right; - font-size: 10px; -} - - -h1, h2, h3, h4 { - color: #333; - padding-top: 0ex; - background-color: transparent; -} - -h2 { - font-weight: 900; - font-size: x-large; -} - -h3 { - font-weight: normal; - font-size: large; -} - -h4 { - font-weight: bold; - font-size: medium; -} - -table.footer { - width: 100%; -} - -.footer { - color: #564b47; - background-color: #fff; - padding:0px; - border-top: 1px solid #CCCCCC; - margin-top: 3ex; - font-size: smaller; -} - - -p.menu { - padding-top: 0px; - padding-bottom: 0px; - margin-top: 0px; - margin-bottom: 0px; -} - -.small { - font-size: smaller; -} - -.strong { - /*font-size: 13px;*/ - font-weight: bold; -} - -/* ========== body table ============ */ -table.bodyTable { - padding: 0px; - margin-left: -2px; - margin-right: -2px; -} - -table.bodyTable th { - color: white; - background-color: #bbb; - font-weight: bold; -} - - -table.bodyTable td { - padding-left: 0.5ex; - padding-bottom: 0.5ex; -} - - -/* apply to tr elements of tables which are both bodytable and dark */ -table[class="bodyTable dark"] tr { - background-color: #ddd; -} - -/* apply to tr elements of tables which are both bodytable and dark */ -table[class="bodyTable properties"] tr { - vertical-align: top; -} - -table.bodyTable tr.a { - background-color: #ddd; -} - -table.bodyTable tr.b { - background-color: #eee; -} - -table.bodyTable tr.alt { - background-color: #eee; -} - -/* EOF =============== bodyTable =============== */ - -.author { - text-align: left; - font-weight: bold; -} - -.definition { - padding-left: 5px; - padding-right: 5px; - margin: 5px 50px 5px 50px; - text-align: justify; - background-color: #E6E64C; -} - -.deftitle { - font-weight: bold; -} - - -.big { - font-size: 130%; -} - - -.green { - color: green; -} - -.white_bg { - background-color: #FFFFFF; -} - -.lgray_bg { - background-color: #EEE; -} - - -.blue { - color: blue; -} - -.red { - color: red; -} - -.redBold { - color: red; - font-weight: bold; -} - -.greenBold { - color: green; - font-weight: bold; -} - -code { - font-family: Courier, monospace; -} - -.variable { - font-family: Courier, monospace; - font-style:italic; -} - - - -.attr { - font-family: Courier, monospace; - font-style:italic; - -} - -.option { - border-top: 1px dotted black; - border-bottom: 1px dotted black; - border-left: 1px dotted black; - border-right: 1px dotted black; - padding-left: 2px; - padding-right: 2px; - font-family: Arial, sans-serif; -} - -.highlight { - width: 300px; - float: right; - display: inline; - font-weight: bolder; - border:1px solid #000; - background:#FFCC99; - padding-top: 0px; - padding-left: 1ex; - padding-right: 1ex; - margin-left: 3em; - margin-right: 3em; -} - -.quote { - text-align: right; - padding-left: 12em; -} - -/* --------- numbering --------- */ -.autoEx:before { - counter-increment: example; /* Add 1 to example */ - content: counter(example) +html { +/* padding:0px; + margin:0px; */ +} + + +a { + color: #0000CC; + background-color:transparent; + text-decoration: none; +} + +#content a:hover { + text-decoration: underline; +} + +div.source { + margin-top: 1em; +} + +.longline { + overflow: scroll; +} + +.source, .command, .console { + border-top: 1px solid #DDDDDD; + border-bottom: 1px solid #DDDDDD; + background:#eee; + font-family: Courier, "MS Courier New", Prestige, monospace; + padding-left: 1ex; + white-space: pre; +} + +.source { + padding-bottom: 0.5ex; + padding-top: 0.5ex; +} + +.command { + padding-bottom: 0ex; + padding-top: 0ex; +} + +.console { +} + +pre { + padding: 0px; + margin: 0px; + background-color:transparent; + font-family: Courier, Monaco, Monospace; +} + +.alignright { + margin-top: 0; + text-align: right; + font-size: 10px; +} + + +h1, h2, h3, h4 { + color: #333; + padding-top: 0ex; + background-color: transparent; +} + +h2 { + font-weight: 900; + font-size: x-large; +} + +h3 { + font-weight: normal; + font-size: large; +} + +h4 { + font-weight: bold; + font-size: medium; +} + +table.footer { + width: 100%; +} + +.footer { + color: #564b47; + background-color: #fff; + padding:0px; + border-top: 1px solid #CCCCCC; + margin-top: 3ex; + font-size: smaller; +} + + +p.menu { + padding-top: 0px; + padding-bottom: 0px; + margin-top: 0px; + margin-bottom: 0px; +} + +.small { + font-size: smaller; +} + +.strong { + /*font-size: 13px;*/ + font-weight: bold; +} + +/* ========== body table ============ */ +table.bodyTable { + padding: 0px; + margin-left: -2px; + margin-right: -2px; +} + +table.bodyTable th { + color: white; + background-color: #bbb; + font-weight: bold; +} + + +table.bodyTable td { + padding-left: 0.5ex; + padding-bottom: 0.5ex; +} + + +/* apply to tr elements of tables which are both bodytable and dark */ +table[class="bodyTable dark"] tr { + background-color: #ddd; +} + +/* apply to tr elements of tables which are both bodytable and dark */ +table[class="bodyTable properties"] tr { + vertical-align: top; +} + +table.bodyTable tr.a { + background-color: #ddd; +} + +table.bodyTable tr.b { + background-color: #eee; +} + +table.bodyTable tr.alt { + background-color: #eee; +} + +/* EOF =============== bodyTable =============== */ + +.author { + text-align: left; + font-weight: bold; +} + +.definition { + padding-left: 5px; + padding-right: 5px; + margin: 5px 50px 5px 50px; + text-align: justify; + background-color: #E6E64C; +} + +.deftitle { + font-weight: bold; +} + + +.big { + font-size: 130%; +} + + +.green { + color: green; +} + +.white_bg { + background-color: #FFFFFF; +} + +.lgray_bg { + background-color: #EEE; +} + + +.blue { + color: blue; +} + +.red { + color: red; +} + +.redBold { + color: red; + font-weight: bold; +} + +.greenBold { + color: green; + font-weight: bold; +} + +code { + font-family: Courier, monospace; +} + +.variable { + font-family: Courier, monospace; + font-style:italic; +} + + + +.attr { + font-family: Courier, monospace; + font-style:italic; + +} + +.option { + border-top: 1px dotted black; + border-bottom: 1px dotted black; + border-left: 1px dotted black; + border-right: 1px dotted black; + padding-left: 2px; + padding-right: 2px; + font-family: Arial, sans-serif; +} + +.highlight { + width: 300px; + float: right; + display: inline; + font-weight: bolder; + border:1px solid #000; + background:#FFCC99; + padding-top: 0px; + padding-left: 1ex; + padding-right: 1ex; + margin-left: 3em; + margin-right: 3em; +} + +.quote { + text-align: right; + padding-left: 12em; +} + +/* --------- numbering --------- */ +.autoEx:before { + counter-increment: example; /* Add 1 to example */ + content: counter(example) } \ No newline at end of file diff --git a/logback-site/src/site/pages/css/prettify.css b/logback-site/src/site/pages/css/prettify.css index 35cad27755b234cda15897dcc63e8f78a1a3e45d..65cfc4195df25a171e4637e7632a843d3bfb08ba 100644 --- a/logback-site/src/site/pages/css/prettify.css +++ b/logback-site/src/site/pages/css/prettify.css @@ -1,28 +1,28 @@ -.str{color:#080} -.kwd{color:#008} -.com{color:#800} -.typ{color:#606} -.lit{color:#066} -.pun{color:#660} -.pln{color:#000} -.tag{color:#008} -.atn{color:#606} -.atv{color:#080} -.dec{color:#606} - -pre.prettyprint{ - padding:2px; -} -@media print{.str{color:#060} - -.kwd{ - color:#006;font-weight:bold} - .com{color:#600;font-style:italic -} -.typ{color:#404;font-weight:bold} -.lit{color:#044} -.pun{color:#440} -.pln{color:#000} -.tag{color:#006;font-weight:bold} -.atn{color:#404} +.str{color:#080} +.kwd{color:#008} +.com{color:#800} +.typ{color:#606} +.lit{color:#066} +.pun{color:#660} +.pln{color:#000} +.tag{color:#008} +.atn{color:#606} +.atv{color:#080} +.dec{color:#606} + +pre.prettyprint{ + padding:2px; +} +@media print{.str{color:#060} + +.kwd{ + color:#006;font-weight:bold} + .com{color:#600;font-style:italic +} +.typ{color:#404;font-weight:bold} +.lit{color:#044} +.pun{color:#440} +.pln{color:#000} +.tag{color:#006;font-weight:bold} +.atn{color:#404} .atv{color:#060}} \ No newline at end of file diff --git a/logback-site/src/site/pages/css/screen.css b/logback-site/src/site/pages/css/screen.css index ad369dfedacff8cff3b06bbb08907f1350c11add..5369a7a514221351d7d5f0f27ba1f524d35ccd43 100644 --- a/logback-site/src/site/pages/css/screen.css +++ b/logback-site/src/site/pages/css/screen.css @@ -1,115 +1,115 @@ -html { -/* padding:0px; - margin:0px; */ -} - -body { - background-color: #fff; - font-family: Verdana, Arial, SunSans-Regular, Sans-Serif; - color: #000; - padding: 0px; - margin: 0px; - counter-reset: example; /* Create an example counter scope */ -} - -.footer { - text-align: right; - color: #564b47; - background-color: #fff; - padding:0px; - border-top: 1px solid #CCCCCC; - margin-top: 3ex; - font-size: smaller; -} - - -p.menu { - padding-top: 0px; - padding-bottom: 0px; - margin-top: 0px; - margin-bottom: 0px; -} - - -#left { - position: absolute; - left: 0px; - width: 15em; - color: #564b47; - margin: 4px 0px 0px 4px; - padding: 0px; - border: 1px solid #cccccc; - background-color: #ffffff; - font-size: 80%; -} - -#left a, #right a { - display: block; - width: 95.5%; - margin: 0px; - padding: 2px; - border: solid 1px #FFFFFF; - color: #0066cc; - text-decoration: none; -} - -p.menu_header { - margin: 0px; - padding: 2px; - font-weight: normal; - background-color: #ffd0a0; - border-top: solid 1px #CCCCCC; - border-bottom: solid 1px #CCCCCC; -} - -#left a:hover, #right a:hover { - border: solid 1px #FFFFFF; - background-color: #3333CC; - color: #ffffff; -} - -#left a:hover.x { - background-color: #fff; -} - -#right { - position: absolute; - right: 0px; - width: 12em; - color: #564b47; - margin: 4px 4px 0px 0px; - padding: 0px; - background-color: #ffffff; - border: 1px solid #cccccc; - font-size: 80%; -} - -#left img { - display: block; - margin: 20px 0 20px 17px; - border: none; - width: 90px; - height: 30px; -} - -#headerLine { - background-color:#FFD0A0; - border:1px solid #CCCCCC; - font-size:small; - margin:0 4px; - padding:3px 10px; -} - -#content { - min-width:50em; - margin: 0px 15em 0px 15em; - padding: 0px; - background-color: #ffffff; -} - -#content img { - border:none; - margin-left: auto; - margin-right: auto; - display: block; -} +html { +/* padding:0px; + margin:0px; */ +} + +body { + background-color: #fff; + font-family: Verdana, Arial, SunSans-Regular, Sans-Serif; + color: #000; + padding: 0px; + margin: 0px; + counter-reset: example; /* Create an example counter scope */ +} + +.footer { + text-align: right; + color: #564b47; + background-color: #fff; + padding:0px; + border-top: 1px solid #CCCCCC; + margin-top: 3ex; + font-size: smaller; +} + + +p.menu { + padding-top: 0px; + padding-bottom: 0px; + margin-top: 0px; + margin-bottom: 0px; +} + + +#left { + position: absolute; + left: 0px; + width: 15em; + color: #564b47; + margin: 4px 0px 0px 4px; + padding: 0px; + border: 1px solid #cccccc; + background-color: #ffffff; + font-size: 80%; +} + +#left a, #right a { + display: block; + width: 95.5%; + margin: 0px; + padding: 2px; + border: solid 1px #FFFFFF; + color: #0066cc; + text-decoration: none; +} + +p.menu_header { + margin: 0px; + padding: 2px; + font-weight: normal; + background-color: #ffd0a0; + border-top: solid 1px #CCCCCC; + border-bottom: solid 1px #CCCCCC; +} + +#left a:hover, #right a:hover { + border: solid 1px #FFFFFF; + background-color: #3333CC; + color: #ffffff; +} + +#left a:hover.x { + background-color: #fff; +} + +#right { + position: absolute; + right: 0px; + width: 12em; + color: #564b47; + margin: 4px 4px 0px 0px; + padding: 0px; + background-color: #ffffff; + border: 1px solid #cccccc; + font-size: 80%; +} + +#left img { + display: block; + margin: 20px 0 20px 17px; + border: none; + width: 90px; + height: 30px; +} + +#headerLine { + background-color:#FFD0A0; + border:1px solid #CCCCCC; + font-size:small; + margin:0 4px; + padding:3px 10px; +} + +#content { + min-width:50em; + margin: 0px 15em 0px 15em; + padding: 0px; + background-color: #ffffff; +} + +#content img { + border:none; + margin-left: auto; + margin-right: auto; + display: block; +} diff --git a/logback-site/src/site/pages/deadlock.html b/logback-site/src/site/pages/deadlock.html index 4f768fb1bad4ec34f4ebf34951e9ca996b742d39..c25cd23da5f9870d7449bc3e57917ce04cce63f5 100644 --- a/logback-site/src/site/pages/deadlock.html +++ b/logback-site/src/site/pages/deadlock.html @@ -1,79 +1,79 @@ - - -logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java: - public synchronized void doAppend(E eventObject) - -logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java: - locks: - Object statusListLock - Object statusListenerListLock - exposition: to derived classes - -logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java: - locks: this - lock exposition: this - -logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextJNDISelector.java: - locks: synchronizedContextMap - lock exposition: none - - -logback-classic/src/main/java/ch/qos/logback/classic/Logger.java - locks: synchronizedContextMap - lock exposition: none - -logback-classic/src/main/java/ch/qos/logback/classic/LoggerContext.java - locks: logger, - loggerCache should be syncronzied but is not - lock exposition: - -logback-classic/src/main/java/ch/qos/logback/classic/Logger.java: - * synchronized on 'this' (Logger) protecting against simultaneous - * only within addAppender which is synchronized

3) all the other methods - public synchronized void setLevel(Level newLevel) { - private synchronized void handleParentLevelChange(int newParentLevelInt) { - // this method MUST be synchronized. See comments on 'aai' field for further - public synchronized void addAppender(Appender newAppender) { - - -logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java: - locks: context - lock exposition: none - - - - - * only within addAppender which is synchronized

3) all the other methods - public synchronized void setLevel(Level newLevel) { - private synchronized void handleParentLevelChange(int newParentLevelInt) { - // this method MUST be synchronized. See comments on 'aai' field for further - public synchronized void addAppender(Appender newAppender) { - - - - -logback-core/src/main/java/ch/qos/logback/core/FileAppender.java: public synchronized void openFile(String file_name) throws IOException { - -logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java: synchronized public void stop() { -logback-core/src/main/java/ch/qos/logback/core/net/SocketAppenderBase.java: synchronized (this) { - -logback-core/src/main/java/ch/qos/logback/core/WriterAppender.java: public synchronized void stop() { -logback-core/src/main/java/ch/qos/logback/core/WriterAppender.java: public synchronized void setWriter(Writer writer) { - -logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueAppender.java: public synchronized void stop() { -logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueAppender.java: // The synchronized modifier avoids concurrent append and close operations -logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicAppender.java: public synchronized void stop() { -logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicAppender.java: // The synchronized modifier avoids concurrent append and close operations - - -logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java: public synchronized void add(Status child) { -logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java: public synchronized boolean hasChildren() { -logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java: public synchronized Iterator iterator() { -logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java: public synchronized boolean remove(Status statusToRemove) { - - -logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java: synchronized (socketNodeList) { -logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java: synchronized(this) { -logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java: synchronized (socketNodeList) { -logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java: synchronized (socketNodeList) { -logback-classic/src/main/java/ch/qos/logback/classic/pattern/DateConverter.java: // the AppenderBase.doAppend is synchronized, we are should be + + +logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java: + public synchronized void doAppend(E eventObject) + +logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java: + locks: + Object statusListLock + Object statusListenerListLock + exposition: to derived classes + +logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java: + locks: this + lock exposition: this + +logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextJNDISelector.java: + locks: synchronizedContextMap + lock exposition: none + + +logback-classic/src/main/java/ch/qos/logback/classic/Logger.java + locks: synchronizedContextMap + lock exposition: none + +logback-classic/src/main/java/ch/qos/logback/classic/LoggerContext.java + locks: logger, + loggerCache should be syncronzied but is not + lock exposition: + +logback-classic/src/main/java/ch/qos/logback/classic/Logger.java: + * synchronized on 'this' (Logger) protecting against simultaneous + * only within addAppender which is synchronized

3) all the other methods + public synchronized void setLevel(Level newLevel) { + private synchronized void handleParentLevelChange(int newParentLevelInt) { + // this method MUST be synchronized. See comments on 'aai' field for further + public synchronized void addAppender(Appender newAppender) { + + +logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java: + locks: context + lock exposition: none + + + + + * only within addAppender which is synchronized

3) all the other methods + public synchronized void setLevel(Level newLevel) { + private synchronized void handleParentLevelChange(int newParentLevelInt) { + // this method MUST be synchronized. See comments on 'aai' field for further + public synchronized void addAppender(Appender newAppender) { + + + + +logback-core/src/main/java/ch/qos/logback/core/FileAppender.java: public synchronized void openFile(String file_name) throws IOException { + +logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java: synchronized public void stop() { +logback-core/src/main/java/ch/qos/logback/core/net/SocketAppenderBase.java: synchronized (this) { + +logback-core/src/main/java/ch/qos/logback/core/WriterAppender.java: public synchronized void stop() { +logback-core/src/main/java/ch/qos/logback/core/WriterAppender.java: public synchronized void setWriter(Writer writer) { + +logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueAppender.java: public synchronized void stop() { +logback-classic/src/main/java/ch/qos/logback/classic/net/JMSQueueAppender.java: // The synchronized modifier avoids concurrent append and close operations +logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicAppender.java: public synchronized void stop() { +logback-classic/src/main/java/ch/qos/logback/classic/net/JMSTopicAppender.java: // The synchronized modifier avoids concurrent append and close operations + + +logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java: public synchronized void add(Status child) { +logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java: public synchronized boolean hasChildren() { +logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java: public synchronized Iterator iterator() { +logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java: public synchronized boolean remove(Status statusToRemove) { + + +logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java: synchronized (socketNodeList) { +logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java: synchronized(this) { +logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java: synchronized (socketNodeList) { +logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java: synchronized (socketNodeList) { +logback-classic/src/main/java/ch/qos/logback/classic/pattern/DateConverter.java: // the AppenderBase.doAppend is synchronized, we are should be diff --git a/logback-site/src/site/pages/demo.html b/logback-site/src/site/pages/demo.html index 4cc18b36a11d288f2839706663426120880be226..60565e0d0fc0058c2298676680724e52e6df2559 100644 --- a/logback-site/src/site/pages/demo.html +++ b/logback-site/src/site/pages/demo.html @@ -1,489 +1,489 @@ - - - - - - Logback Demo - - - - - - - - -

- -
-
- - -

Logback Demo

- -

Welcome to the logback demo! This document will take you through - a tour of some of logback's major features. -

- -

Installation

- -

First, please download the logback demo. You will need to - install a Subversion - client and issue the following command on a console: -

- -

svn co http://svn.qos.ch/repos/logback-demo/tags/STABLE logback-demo

- -

This will checkout a copy of the logback demonstration - web-application to a directory called logback-demo. The - logback demo can be packaged as a war file and deployed - to an application server. We strongly recommend the use of Maven2 to accomplish this - task, since it takes a single command in order to compile, package - and run this demo. -

- -

Using Maven, let's package the files and run the demo for the first - time. From the logback-demo directory, issue the following - command: -

- -
mvn package jetty:run
- -

Then, visit http://localhost:8080/logback-demo/ - to view the main page of the logback demo. -

- -

Logback-classic

- -

By default (or as packaged), logback-demo configures - logback-classic with two appenders: a ConsoleAppender - and a RollingFileAppender. The - RollingFileAppender sends logging events to a file - called logFile.log and will rollover the active file every - minute. The old file will be renamed and compressed to zip - file. The ConsoleAppender will output the logging - requests to the console, and shorten the logger names to gain space - on the console window, without loss of legibility. For example, - ch.qos.logback.demo.prime.NumberCruncherImpl will be - abbreviated as c.q.l.d.prime.NumberCruncherImpl. -

- -

We highly encourage you to study the logback.xml - configuratiun file located under the src/main/resources/ - folder. You might want to keep open this file in an editor window, - since we will modify its contents thoughout the demo. -

- -

Let us now visit the ViewStatii page, via the navigation - menu on the left hand side of your browser's window. This page - contains the content of the Status objects that were - created up until now. Status objects are a part of - logback's internal reporting framework. They allow you to see what - is going on inside logback, and check that a configuration file has - been parsed correctly, or that a rollovers occur as expected. -

- -

You should be seeing log messages printed on the console and the - contents of "logFile.log" file rolled over every minute. -

- -

If you visit the View logs page (by clicking on the link - located in the menu on the left), you should see empty contemts. Let - us change that by uncommenting two parts in the - config file.

- -

Remove the comments around

- -

<!-- Basic Cyclic buffer -<appender name="CYCLIC" class="ch.qos.logback.core.read.CyclicBufferAppender"> - <MaxSize>512</MaxSize> -</appender> --->

-

and around

- -

<!-- Part I: Basic Cyclic buffer -<appender-ref ref="CYCLIC" /> --->

- -

The <appender-ref> element element, found at the - end of the configuration file links an appender to a given logger, - in this particular case the root logger. -

- -

A CyclicBuffer keeps track of incoming logging event - stream in a circular - buffer for later display. After having removed the comments - around the two elemetns shown above, reload the logback-demo - web-application by exiting the previous "mvn" command with - CTRL-C and issuing it again: -

- -

mvn package jetty:run

- -

This time View logs page should have contents.

- - view logs - - -

By virtue of CyclicBufferAppender, this page can - fetch the last events and present them through a servlet. We see - that every ten seconds a line is added to the logs. The formatting - of this page is made with a HTMLLayout. This component - creates a table containing logging events, based on a pattern that - describes the information you wish to see in the table. -

- -

Having the logs cluttered with repetitive - Howdydy-diddly-ho messages is wasteful. We can get rid of - them with an appropriate filter. Uncomment the block entitled - Cyclic buffer with Evaluator. You should then comment the - block entitled "Basic Cyclic buffer" that we uncommmented - earlier.

- -

Let's take a look at the filter we've just added:

- -

<filter class="ch.qos.logback.core.filter.EvaluatorFilter"> - <evaluator name="loggingTaskEval"> - <expression> - logger.getName().contains("LoggingTask") &amp;&amp; - message.contains("Howdydy-diddly-ho") &amp;&amp; - (timeStamp - event.getStartTime()) >= 20000 - </expression> - </evaluator> - <OnMatch>DENY</OnMatch> -</filter>

- -

The <expression> element uses the familiar - Java-language syntax. It checks that the name of the logger contains - the String LoggingTask, but also that its message contains - the string Howdydy-diddly-ho. Moreover, in order to be - sure that the Howdydy-diddly-ho task actually works, we add - a last condition which checks that that at least 20 seconds have - elapsed after application launch. The variables references in the - expression, namely (logger, message and - event) are implicitly made available by logback. The - <OnMatch> element lets the user specify the filter's - behaviour once the expression matched (evaluated to true). -

- -

After a restart, the Vew logs page will shows the - Howdydy-diddly-ho logs, but only for the first 20 - seconds. If you wish to see new logging events to be shown on the - "View logs" page, then visit the "Prime number" page. -

- -

Turbo Filters

- -

Logback support with a special category of filters called - TurboFilters. TurboFilter objects are ultra-fast, - context-wide filters. They can be very useful by setting - context-wide (i.e. global) conditions for enabling or disabling - logging events. -

- -

Remove the comments around the block entitled "TurboFilter: MDC - value".

- -

<turboFilter class="ch.qos.logback.classic.turbo.MDCFilter"> - <MDCKey>username</MDCKey> - <Value>sebastien</Value> - <OnMatch>ACCEPT</OnMatch> -</turboFilter>

- - -

This <turboFilter> element adds a - TurboFilter to the logging context which will enable - events if the MDC contains a key named "username" set to the value - "sebastien". The logback-demo application contains a servlet - filter which will set the MDC key "username" with the name of - the currently logged in user.

- - -

For the purpose of this demo, let us disable all logging by - setting the root logger's level to OFF. -

- -

<root> - <level value="OFF"/> - ... -</root>

- -

Now restart the server as previously

- -

Once on the demo main webpage again, perform a number of actions - (e.g. calculate a few prime numbers) and visit the View - logs page. The table should be empty. -

- -

Now log in into the logback-demo web-application with the - username sebastien and perform a few prime - computations. The View logs page should show the logging - events thgat were generated. Moreover, each logging event will have - an MDC field associated with the name of the logged in user, in this - case, sebastien. Please log off before continuing the demo, using - the logout button on the left. -

- - mdc filters - -

Parametrized logging

- -

Parametrized - logging is not a logback feature per se. It is part of - SLF4J. Usually, a logging request is issued as follows: -

- -
logger.debug("Hello, my name is" + username + ", I am " + age + " years old.");
- -

In the above call, the cost of constructing the message of type - String is borne even if the log request is disabled. -

- -

SLF4J offers the following alternative: -

- -
logger.debug("Hello, my name is {}, I am {} years old", username, age);
- -

In this alternative, the final log message will be formatted only - if the log statement is enabled. -

- -

At present, let us see what kind of gain can we expect from this - alternative approach. First, go to the Prime number page - and compute factors for intergers of your choice. Check the time it - takes to compute the results. To see a clearer difference between - the two formatting methods, you might want to try the two big - integers that are listed below the prime number textbox. Jot down - the time it takes to compute the result. -

- -

Now let us edit the NumberCruncherImpl class in - order to use parametrized logging. You will find this class in the - src/main/java/ch/qos/logback/demo/prime/ directory. Comment - line 54 (doing unconditional message concatenation) and uncomment - line 55 (parameterized logging). Restart the server with mvn - package jetty:run and re-run the factorization you tried - beforehand. -

- -

The time required to complete the computation should much lower - this time. Remember that we have turned off all logging in the - previous step of this demo. In the initial version, we were - constructing the message ("Trying "+i+" as a factor.") each - time a factor was tested. With the paramatrized logging, the - construction of the message was postponed and, since logging was - turned off, never done. Thus, parameterized logging can - significantly reduce the cost of disabled log statements. -

- -

Markers

- -

You can color log statements with markers. Markers are - part of the SLF4J API. If you look at the LoggingTask class (part of - logback-demo) which includes the Howdydy-diddly-ho log - statement, you should see that it is bound to a marker named - HOWDY marker. Assume we wish to drop log statements - bearing the HOWDY marker. Here is the - TurboFilter to do just that. -

- -

<turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> - <Name>HOWDY_FILTER</Name> - <Marker>HOWDY</Marker> - <OnMatch>DENY</OnMatch> - </turboFilter>

- -

After you have set the root logger's level back to DEBUG - and uncommented the MarkerFilter block in logback.xml, - restart the server. -

- - -

The logs bearing the Howdydy-diddly-ho message should no - longer appear as they associated with a HOWDY marker. You can check - that by visiting the View Logs page. -

- -

Logback Access

- -

Access logging is another important feature offered by - logback. By default, the logback-demo web-application is configured - so that each time you access it, an access log is printed on the - console. The details of access logs are configured by the - logback-access.xml file located under the src/etc/ - directory. -

- -

Here is a rather minimal configuration for logback-access:

- -
<configuration>
- 
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.access.PatternLayout">
-      <Pattern>%h %l %u %t \"%r\" %s %b</Pattern>
-    </layout>
-  </appender>
-  
-  <appender-ref ref="STDOUT" />
-  
-</configuration>
- -

Note that logback-classic and logback-access are configured via - different files, logback.xml and respectively - logback-acces.xml. At present time, you might want to turn - off logging for logback-classic by setting the level of the root - logger to OFF. Logback-access will be unaffected by this change. -

- -

To see the logs produced by logback access, just visit a few - pages and look at your console. The information contained in each - line has been specified in the configuration file. The - ConsoleAppender named STDOUT contains a - PatternLayout component. This very component that one - uses in logback classic to display either the message, logger name - or level of the request is used in logback access to display the - request method, requested page, status code and many others. -

- -

Here is a sample output for this appender.

- -
127.0.0.1 - - 22/01/2007:14:35:40 +0100 GET /logback-demo/ViewStatii.do HTTP/1.1 200 3660
-127.0.0.1 - - 22/01/2007:14:35:41 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
-127.0.0.1 - - 22/01/2007:14:35:42 +0100 GET /logback-demo/lastLog/ HTTP/1.1 200 948
-127.0.0.1 - - 22/01/2007:14:35:42 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
-127.0.0.1 - - 22/01/2007:14:35:43 +0100 GET /logback-demo/prime.jsp HTTP/1.1 200 1296
-127.0.0.1 - - 22/01/2007:14:35:44 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
-127.0.0.1 - - 22/01/2007:14:35:45 +0100 GET /logback-demo/lottery.jsp HTTP/1.1 200 1209
-127.0.0.1 - - 22/01/2007:14:35:46 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
-127.0.0.1 - - 22/01/2007:14:35:48 +0100 GET /logback-demo/reload.jsp HTTP/1.1 200 1335
-127.0.0.1 - - 22/01/2007:14:35:49 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
-127.0.0.1 - - 22/01/2007:14:35:54 +0100 GET /logback-demo/login.jsp HTTP/1.1 200 1214
-127.0.0.1 - - 22/01/2007:14:35:55 +0100 GET /logback-demo/Logout.do HTTP/1.1 200 1000
- -

Filtering

- -

In this next part, we are going to add some information to the - console. Let us imagine that we want to log the numbers that are - tried on the Lottery page. We will need a second - ConsoleAppender that will only print a given information - (e.g. the guessed number, along with some hints about the player). The - appender will also have to print that information only when a certain - page is accessed. -

- -

The configuration lines that are necessary are listed below. -

- -

<appender name="STDOUT_LOTTERY" - class="ch.qos.logback.core.ConsoleAppender"> - <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> - <evaluator name="lotto_eval"> - <Expression> - url.matches(event.getRequestURL().toString()) - </Expression> - <matcher name="url"> - <regex>Lottery.do</regex> - <caseSensitive>false</caseSensitive> - </matcher> - </evaluator> - <OnMatch>ACCEPT</OnMatch> - <OnMismatch>DENY</OnMismatch> - </filter> - <layout class="ch.qos.logback.access.PatternLayout"> - <Pattern> - LOTTERY: %A [%r] Guess=%reqParameter{guessed_number} - </Pattern> - </layout> -</appender>

- -

This appender will use a PatternLayout to format its - output. The %reqParameter conversion word is used to - extract the guessed number from the request, and print it. -

- -

It also uses an EvaluatorFilter that will prevent - the appender to display anything when the access' request url does - not match the given expression. You can see that it is easy to - specify a RegExp, name it and use it in the expression that will be - evaluated. In that case, we only entered the name of the - lottery.do action. -

- -

Let us uncomment the two elements with the Lottery to - Console comments and restart the server. Now, try to play the - lottery. You will see more lines in the Console that you've seen until - now. At every try, logback will produce a log as shown below: -

- -

LOTTERY: 192.168.1.6 [POST /logback-demo/Lottery.do HTTP/1.1] Guess=321

> - -

Sending emails

- -

Logback access provides several components that are usually used - by the classic module. For example, a SMTPAppender can - be used to send an email when a specific event occurs. Here, we will - contact the lottery administrator each time a winner is detected. To - achieve this, we will add a SMTPAppender to the - existing configuration. Please uncomment the part of - logback-access.xml named Lottery to Email. Do not - forget to uncomment the appender-ref element, at the end of - the configuration file, referencing the appender called - SMTP. In the appender element, notice the use of a - URLEvaluator. This evaluator allows us to only specify - one or more URLs that have to be watched. When one of them are - accessed, an email is sent. -

- -

A reload of the configuration has to be done before we can test - this new component. Once done, try to play the lottery with the - number 99. You should see a congratulation message but, - most importantly, the specified recipients should have a new mail in - their mailbox. The content of the email is a nicely formatted HTML - table with informations about the access that have occured before - the triggering event. -

- -

JMX

- -

Logback publishes several components via JMX. This allows you to - see the status of certain objects, and change several configuration - parameters. Publishing logback's components via JMX is possible - with Jetty and Tomcat. For more information about JMXConfigurator - please refer to the relevant - chapter in the manual. -

- -

Let us test the level setting possibility of the configurator. - The Prime Number page requests two types of logs. When the - calculation checks if a number is a factor, a DEBUG log is - displayed. When the calculation has found a factor, a INFO - log is displayed. -

- -

Let us first set the level of the logger named - ch.qos.logback.demo.prime to DEBUG. Run a prime - calculation directly, without restarting the server. The View - logs page should show the DEBUG and INFO logs. -

- -

Now, if you set the level of the ch.qos.logback.demo.prime - logger to INFO, and run a prime calculation again, you should - not see the DEBUG level logs anymore. -

- -

This demo of logback is now over. Do not hesitate to play around - with the configuration files. You might want to check the logback documentation - page for more information about any component you'd like to test. -

- - -
- - + + + + + + Logback Demo + + + + + + + + +
+ +
+
+ + +

Logback Demo

+ +

Welcome to the logback demo! This document will take you through + a tour of some of logback's major features. +

+ +

Installation

+ +

First, please download the logback demo. You will need to + install a Subversion + client and issue the following command on a console: +

+ +

svn co http://svn.qos.ch/repos/logback-demo/tags/STABLE logback-demo

+ +

This will checkout a copy of the logback demonstration + web-application to a directory called logback-demo. The + logback demo can be packaged as a war file and deployed + to an application server. We strongly recommend the use of Maven2 to accomplish this + task, since it takes a single command in order to compile, package + and run this demo. +

+ +

Using Maven, let's package the files and run the demo for the first + time. From the logback-demo directory, issue the following + command: +

+ +
mvn package jetty:run
+ +

Then, visit http://localhost:8080/logback-demo/ + to view the main page of the logback demo. +

+ +

Logback-classic

+ +

By default (or as packaged), logback-demo configures + logback-classic with two appenders: a ConsoleAppender + and a RollingFileAppender. The + RollingFileAppender sends logging events to a file + called logFile.log and will rollover the active file every + minute. The old file will be renamed and compressed to zip + file. The ConsoleAppender will output the logging + requests to the console, and shorten the logger names to gain space + on the console window, without loss of legibility. For example, + ch.qos.logback.demo.prime.NumberCruncherImpl will be + abbreviated as c.q.l.d.prime.NumberCruncherImpl. +

+ +

We highly encourage you to study the logback.xml + configuratiun file located under the src/main/resources/ + folder. You might want to keep open this file in an editor window, + since we will modify its contents thoughout the demo. +

+ +

Let us now visit the ViewStatii page, via the navigation + menu on the left hand side of your browser's window. This page + contains the content of the Status objects that were + created up until now. Status objects are a part of + logback's internal reporting framework. They allow you to see what + is going on inside logback, and check that a configuration file has + been parsed correctly, or that a rollovers occur as expected. +

+ +

You should be seeing log messages printed on the console and the + contents of "logFile.log" file rolled over every minute. +

+ +

If you visit the View logs page (by clicking on the link + located in the menu on the left), you should see empty contemts. Let + us change that by uncommenting two parts in the + config file.

+ +

Remove the comments around

+ +

<!-- Basic Cyclic buffer +<appender name="CYCLIC" class="ch.qos.logback.core.read.CyclicBufferAppender"> + <MaxSize>512</MaxSize> +</appender> +-->

+

and around

+ +

<!-- Part I: Basic Cyclic buffer +<appender-ref ref="CYCLIC" /> +-->

+ +

The <appender-ref> element element, found at the + end of the configuration file links an appender to a given logger, + in this particular case the root logger. +

+ +

A CyclicBuffer keeps track of incoming logging event + stream in a circular + buffer for later display. After having removed the comments + around the two elemetns shown above, reload the logback-demo + web-application by exiting the previous "mvn" command with + CTRL-C and issuing it again: +

+ +

mvn package jetty:run

+ +

This time View logs page should have contents.

+ + view logs + + +

By virtue of CyclicBufferAppender, this page can + fetch the last events and present them through a servlet. We see + that every ten seconds a line is added to the logs. The formatting + of this page is made with a HTMLLayout. This component + creates a table containing logging events, based on a pattern that + describes the information you wish to see in the table. +

+ +

Having the logs cluttered with repetitive + Howdydy-diddly-ho messages is wasteful. We can get rid of + them with an appropriate filter. Uncomment the block entitled + Cyclic buffer with Evaluator. You should then comment the + block entitled "Basic Cyclic buffer" that we uncommmented + earlier.

+ +

Let's take a look at the filter we've just added:

+ +

<filter class="ch.qos.logback.core.filter.EvaluatorFilter"> + <evaluator name="loggingTaskEval"> + <expression> + logger.getName().contains("LoggingTask") &amp;&amp; + message.contains("Howdydy-diddly-ho") &amp;&amp; + (timeStamp - event.getStartTime()) >= 20000 + </expression> + </evaluator> + <OnMatch>DENY</OnMatch> +</filter>

+ +

The <expression> element uses the familiar + Java-language syntax. It checks that the name of the logger contains + the String LoggingTask, but also that its message contains + the string Howdydy-diddly-ho. Moreover, in order to be + sure that the Howdydy-diddly-ho task actually works, we add + a last condition which checks that that at least 20 seconds have + elapsed after application launch. The variables references in the + expression, namely (logger, message and + event) are implicitly made available by logback. The + <OnMatch> element lets the user specify the filter's + behaviour once the expression matched (evaluated to true). +

+ +

After a restart, the Vew logs page will shows the + Howdydy-diddly-ho logs, but only for the first 20 + seconds. If you wish to see new logging events to be shown on the + "View logs" page, then visit the "Prime number" page. +

+ +

Turbo Filters

+ +

Logback support with a special category of filters called + TurboFilters. TurboFilter objects are ultra-fast, + context-wide filters. They can be very useful by setting + context-wide (i.e. global) conditions for enabling or disabling + logging events. +

+ +

Remove the comments around the block entitled "TurboFilter: MDC + value".

+ +

<turboFilter class="ch.qos.logback.classic.turbo.MDCFilter"> + <MDCKey>username</MDCKey> + <Value>sebastien</Value> + <OnMatch>ACCEPT</OnMatch> +</turboFilter>

+ + +

This <turboFilter> element adds a + TurboFilter to the logging context which will enable + events if the MDC contains a key named "username" set to the value + "sebastien". The logback-demo application contains a servlet + filter which will set the MDC key "username" with the name of + the currently logged in user.

+ + +

For the purpose of this demo, let us disable all logging by + setting the root logger's level to OFF. +

+ +

<root> + <level value="OFF"/> + ... +</root>

+ +

Now restart the server as previously

+ +

Once on the demo main webpage again, perform a number of actions + (e.g. calculate a few prime numbers) and visit the View + logs page. The table should be empty. +

+ +

Now log in into the logback-demo web-application with the + username sebastien and perform a few prime + computations. The View logs page should show the logging + events thgat were generated. Moreover, each logging event will have + an MDC field associated with the name of the logged in user, in this + case, sebastien. Please log off before continuing the demo, using + the logout button on the left. +

+ + mdc filters + +

Parametrized logging

+ +

Parametrized + logging is not a logback feature per se. It is part of + SLF4J. Usually, a logging request is issued as follows: +

+ +
logger.debug("Hello, my name is" + username + ", I am " + age + " years old.");
+ +

In the above call, the cost of constructing the message of type + String is borne even if the log request is disabled. +

+ +

SLF4J offers the following alternative: +

+ +
logger.debug("Hello, my name is {}, I am {} years old", username, age);
+ +

In this alternative, the final log message will be formatted only + if the log statement is enabled. +

+ +

At present, let us see what kind of gain can we expect from this + alternative approach. First, go to the Prime number page + and compute factors for intergers of your choice. Check the time it + takes to compute the results. To see a clearer difference between + the two formatting methods, you might want to try the two big + integers that are listed below the prime number textbox. Jot down + the time it takes to compute the result. +

+ +

Now let us edit the NumberCruncherImpl class in + order to use parametrized logging. You will find this class in the + src/main/java/ch/qos/logback/demo/prime/ directory. Comment + line 54 (doing unconditional message concatenation) and uncomment + line 55 (parameterized logging). Restart the server with mvn + package jetty:run and re-run the factorization you tried + beforehand. +

+ +

The time required to complete the computation should much lower + this time. Remember that we have turned off all logging in the + previous step of this demo. In the initial version, we were + constructing the message ("Trying "+i+" as a factor.") each + time a factor was tested. With the paramatrized logging, the + construction of the message was postponed and, since logging was + turned off, never done. Thus, parameterized logging can + significantly reduce the cost of disabled log statements. +

+ +

Markers

+ +

You can color log statements with markers. Markers are + part of the SLF4J API. If you look at the LoggingTask class (part of + logback-demo) which includes the Howdydy-diddly-ho log + statement, you should see that it is bound to a marker named + HOWDY marker. Assume we wish to drop log statements + bearing the HOWDY marker. Here is the + TurboFilter to do just that. +

+ +

<turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> + <Name>HOWDY_FILTER</Name> + <Marker>HOWDY</Marker> + <OnMatch>DENY</OnMatch> + </turboFilter>

+ +

After you have set the root logger's level back to DEBUG + and uncommented the MarkerFilter block in logback.xml, + restart the server. +

+ + +

The logs bearing the Howdydy-diddly-ho message should no + longer appear as they associated with a HOWDY marker. You can check + that by visiting the View Logs page. +

+ +

Logback Access

+ +

Access logging is another important feature offered by + logback. By default, the logback-demo web-application is configured + so that each time you access it, an access log is printed on the + console. The details of access logs are configured by the + logback-access.xml file located under the src/etc/ + directory. +

+ +

Here is a rather minimal configuration for logback-access:

+ +
<configuration>
+ 
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.access.PatternLayout">
+      <Pattern>%h %l %u %t \"%r\" %s %b</Pattern>
+    </layout>
+  </appender>
+  
+  <appender-ref ref="STDOUT" />
+  
+</configuration>
+ +

Note that logback-classic and logback-access are configured via + different files, logback.xml and respectively + logback-acces.xml. At present time, you might want to turn + off logging for logback-classic by setting the level of the root + logger to OFF. Logback-access will be unaffected by this change. +

+ +

To see the logs produced by logback access, just visit a few + pages and look at your console. The information contained in each + line has been specified in the configuration file. The + ConsoleAppender named STDOUT contains a + PatternLayout component. This very component that one + uses in logback classic to display either the message, logger name + or level of the request is used in logback access to display the + request method, requested page, status code and many others. +

+ +

Here is a sample output for this appender.

+ +
127.0.0.1 - - 22/01/2007:14:35:40 +0100 GET /logback-demo/ViewStatii.do HTTP/1.1 200 3660
+127.0.0.1 - - 22/01/2007:14:35:41 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
+127.0.0.1 - - 22/01/2007:14:35:42 +0100 GET /logback-demo/lastLog/ HTTP/1.1 200 948
+127.0.0.1 - - 22/01/2007:14:35:42 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
+127.0.0.1 - - 22/01/2007:14:35:43 +0100 GET /logback-demo/prime.jsp HTTP/1.1 200 1296
+127.0.0.1 - - 22/01/2007:14:35:44 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
+127.0.0.1 - - 22/01/2007:14:35:45 +0100 GET /logback-demo/lottery.jsp HTTP/1.1 200 1209
+127.0.0.1 - - 22/01/2007:14:35:46 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
+127.0.0.1 - - 22/01/2007:14:35:48 +0100 GET /logback-demo/reload.jsp HTTP/1.1 200 1335
+127.0.0.1 - - 22/01/2007:14:35:49 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
+127.0.0.1 - - 22/01/2007:14:35:54 +0100 GET /logback-demo/login.jsp HTTP/1.1 200 1214
+127.0.0.1 - - 22/01/2007:14:35:55 +0100 GET /logback-demo/Logout.do HTTP/1.1 200 1000
+ +

Filtering

+ +

In this next part, we are going to add some information to the + console. Let us imagine that we want to log the numbers that are + tried on the Lottery page. We will need a second + ConsoleAppender that will only print a given information + (e.g. the guessed number, along with some hints about the player). The + appender will also have to print that information only when a certain + page is accessed. +

+ +

The configuration lines that are necessary are listed below. +

+ +

<appender name="STDOUT_LOTTERY" + class="ch.qos.logback.core.ConsoleAppender"> + <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> + <evaluator name="lotto_eval"> + <Expression> + url.matches(event.getRequestURL().toString()) + </Expression> + <matcher name="url"> + <regex>Lottery.do</regex> + <caseSensitive>false</caseSensitive> + </matcher> + </evaluator> + <OnMatch>ACCEPT</OnMatch> + <OnMismatch>DENY</OnMismatch> + </filter> + <layout class="ch.qos.logback.access.PatternLayout"> + <Pattern> + LOTTERY: %A [%r] Guess=%reqParameter{guessed_number} + </Pattern> + </layout> +</appender>

+ +

This appender will use a PatternLayout to format its + output. The %reqParameter conversion word is used to + extract the guessed number from the request, and print it. +

+ +

It also uses an EvaluatorFilter that will prevent + the appender to display anything when the access' request url does + not match the given expression. You can see that it is easy to + specify a RegExp, name it and use it in the expression that will be + evaluated. In that case, we only entered the name of the + lottery.do action. +

+ +

Let us uncomment the two elements with the Lottery to + Console comments and restart the server. Now, try to play the + lottery. You will see more lines in the Console that you've seen until + now. At every try, logback will produce a log as shown below: +

+ +

LOTTERY: 192.168.1.6 [POST /logback-demo/Lottery.do HTTP/1.1] Guess=321

> + +

Sending emails

+ +

Logback access provides several components that are usually used + by the classic module. For example, a SMTPAppender can + be used to send an email when a specific event occurs. Here, we will + contact the lottery administrator each time a winner is detected. To + achieve this, we will add a SMTPAppender to the + existing configuration. Please uncomment the part of + logback-access.xml named Lottery to Email. Do not + forget to uncomment the appender-ref element, at the end of + the configuration file, referencing the appender called + SMTP. In the appender element, notice the use of a + URLEvaluator. This evaluator allows us to only specify + one or more URLs that have to be watched. When one of them are + accessed, an email is sent. +

+ +

A reload of the configuration has to be done before we can test + this new component. Once done, try to play the lottery with the + number 99. You should see a congratulation message but, + most importantly, the specified recipients should have a new mail in + their mailbox. The content of the email is a nicely formatted HTML + table with informations about the access that have occured before + the triggering event. +

+ +

JMX

+ +

Logback publishes several components via JMX. This allows you to + see the status of certain objects, and change several configuration + parameters. Publishing logback's components via JMX is possible + with Jetty and Tomcat. For more information about JMXConfigurator + please refer to the relevant + chapter in the manual. +

+ +

Let us test the level setting possibility of the configurator. + The Prime Number page requests two types of logs. When the + calculation checks if a number is a factor, a DEBUG log is + displayed. When the calculation has found a factor, a INFO + log is displayed. +

+ +

Let us first set the level of the logger named + ch.qos.logback.demo.prime to DEBUG. Run a prime + calculation directly, without restarting the server. The View + logs page should show the DEBUG and INFO logs. +

+ +

Now, if you set the level of the ch.qos.logback.demo.prime + logger to INFO, and run a prime calculation again, you should + not see the DEBUG level logs anymore. +

+ +

This demo of logback is now over. Do not hesitate to play around + with the configuration files. You might want to check the logback documentation + page for more information about any component you'd like to test. +

+ + +
+ + diff --git a/logback-site/src/site/pages/dependencies.html b/logback-site/src/site/pages/dependencies.html index 22e3fb78631a6bb049b4539fcb0e114225154a02..2d541abf98fc96f9d66f879f3cdae4ca6aba415c 100644 --- a/logback-site/src/site/pages/dependencies.html +++ b/logback-site/src/site/pages/dependencies.html @@ -1,226 +1,226 @@ - - - - - Logback Dependencies - - - - - - - - - - -
- -
-
- - -

Dependencies per module

- -

Each logback module has a different set of dependencies. These - are listed below in a separate table per module.

- -

logback-core

- - - - - - - - - - - - - - - - - - - - - - - - - - -
Componentdependencies
Overall -
    -
  • JDK 1.5 -
  • -
-
JMSAppender - -
JaninoEventEvaluatorBase and derived classes - -
SMTPAppenderBase and derived classes - -
- -

logback-classic

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Componentdependencies
Overall -
    -
  • JDK 1.5 -
  • -
-
Overall -
    -
  • logback-core, and by transitivity logback-core's - dependencies. -
  • -
-
Overall - -
ch.qos.logback.classic.selector.* -
    -
  • servlet-api version 2.5 -
  • -
-
c.q.l.c.boolex.JaninoEventEvaluator -
    -
  • Depends on JaninoEventEvaluatorBase, and by - transitivity on JaninoEventEvaluatorBase's - dependencies. -
  • -
-
SMTPAppender -
    -
  • Depends on SMTPAppenderBase, and by - transitivity on SMTPAppenderBase's - dependencies. -
  • -
-
- -

logback-access

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Componentdependencies
Overall -
    -
  • JDK 1.5 -
  • -
-
Overall -
    -
  • logback-core, and by transitivity logback-core's - dependencies. -
  • -
-
Overall -
    -
  • servlet-api version 2.5 -
  • -
-
ch.qos.logback.access.jetty.* -
    -
  • Jetty version 6.1.1 -
  • -
-
ch.qos.logback.access.tomcat.* - -
- - - -
- - + + + + + Logback Dependencies + + + + + + + + + + +
+ +
+
+ + +

Dependencies per module

+ +

Each logback module has a different set of dependencies. These + are listed below in a separate table per module.

+ +

logback-core

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Componentdependencies
Overall +
    +
  • JDK 1.5 +
  • +
+
JMSAppender + +
JaninoEventEvaluatorBase and derived classes + +
SMTPAppenderBase and derived classes + +
+ +

logback-classic

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Componentdependencies
Overall +
    +
  • JDK 1.5 +
  • +
+
Overall +
    +
  • logback-core, and by transitivity logback-core's + dependencies. +
  • +
+
Overall + +
ch.qos.logback.classic.selector.* +
    +
  • servlet-api version 2.5 +
  • +
+
c.q.l.c.boolex.JaninoEventEvaluator +
    +
  • Depends on JaninoEventEvaluatorBase, and by + transitivity on JaninoEventEvaluatorBase's + dependencies. +
  • +
+
SMTPAppender +
    +
  • Depends on SMTPAppenderBase, and by + transitivity on SMTPAppenderBase's + dependencies. +
  • +
+
+ +

logback-access

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Componentdependencies
Overall +
    +
  • JDK 1.5 +
  • +
+
Overall +
    +
  • logback-core, and by transitivity logback-core's + dependencies. +
  • +
+
Overall +
    +
  • servlet-api version 2.5 +
  • +
+
ch.qos.logback.access.jetty.* +
    +
  • Jetty version 6.1.1 +
  • +
+
ch.qos.logback.access.tomcat.* + +
+ + + +
+ + \ No newline at end of file diff --git a/logback-site/src/site/pages/documentation.html b/logback-site/src/site/pages/documentation.html index 90a9de4a0f46bcc5239843f56a97f32d0d818073..3c226a16b289ffcb0c9aa47644aa55604274722d 100644 --- a/logback-site/src/site/pages/documentation.html +++ b/logback-site/src/site/pages/documentation.html @@ -1,131 +1,131 @@ - - - - - - Documentation - - - - - - - - -
- - -
- -
- -

Logback documentation

- -

Below is a list of logback-related documentaiton currently - available.

- - - -

Source code related documentation:

- - - -

Articles and Presentations

- - - -

In french

- - - - -

Conferences

- - - - - - -
- Jazoon, June 22-25, 2009 Zurich
- - Jazoon 2009 - -
- Devoxx, November 16-20, 2009 Antwerp
- - Devoxx 2009 - -
- - - -
- - + + + + + + Documentation + + + + + + + + +
+ + +
+ +
+ +

Logback documentation

+ +

Below is a list of logback-related documentaiton currently + available.

+ + + +

Source code related documentation:

+ + + +

Articles and Presentations

+ + + +

In french

+ + + + +

Conferences

+ + + + + + +
+ Jazoon, June 22-25, 2009 Zurich
+ + Jazoon 2009 + +
+ Devoxx, November 16-20, 2009 Antwerp
+ + Devoxx 2009 + +
+ + + +
+ + diff --git a/logback-site/src/site/pages/download.html b/logback-site/src/site/pages/download.html index 8004509ae4eab40532480f274a5fd9018a01a11e..25148534c008dbab34534326dc6d5cd47ea8af69 100644 --- a/logback-site/src/site/pages/download.html +++ b/logback-site/src/site/pages/download.html @@ -1,91 +1,91 @@ - - - - - - Download - - - - - - - - -
- - -
-
- -

Download links

- - -

Logback modules are available as downloads including full - source code, class files and documentation. -

- - - - -

If you wish to download an older version of logback, please - refer to the distributions - directory.

- - -

A console plugin for Eclipse is also available. It allows you - to recieve logging events in a convenient Eclipse view, and - offers, among other features, integrates with logbacks filtering - framework. A more precise description can be found in the plugin's - user guide. Unfortunately, the - console plugin is somewhat outdated. It expects logback version - 0.9.9. It will be upgraded in the coming weeks.

- - - - - -
- -

Third-party tools

- -
-
- Configuration - wizard by Dirk Ooms -
- -
-

A nifty web-application to help you configure logback - classic.

-
- - -
- Lilith by Joern Huxhorn -
- -
-

Lilith is a Logging- and AccessEvent viewer for logback. -

-
- -
- - - - - -
- - + + + + + + Download + + + + + + + + +
+ + +
+
+ +

Download links

+ + +

Logback modules are available as downloads including full + source code, class files and documentation. +

+ + + + +

If you wish to download an older version of logback, please + refer to the distributions + directory.

+ + +

A console plugin for Eclipse is also available. It allows you + to recieve logging events in a convenient Eclipse view, and + offers, among other features, integrates with logbacks filtering + framework. A more precise description can be found in the plugin's + user guide. Unfortunately, the + console plugin is somewhat outdated. It expects logback version + 0.9.9. It will be upgraded in the coming weeks.

+ + + + + +
+ +

Third-party tools

+ +
+
+ Configuration + wizard by Dirk Ooms +
+ +
+

A nifty web-application to help you configure logback + classic.

+
+ + +
+ Lilith by Joern Huxhorn +
+ +
+

Lilith is a Logging- and AccessEvent viewer for logback. +

+
+ +
+ + + + + +
+ + diff --git a/logback-site/src/site/pages/faq.html b/logback-site/src/site/pages/faq.html index 7776938134258bc66f0dd2540345611c767ed53c..de185250a70c602fcb502bcfbe28ab00265e1782 100644 --- a/logback-site/src/site/pages/faq.html +++ b/logback-site/src/site/pages/faq.html @@ -1,349 +1,349 @@ - - - - - - Logback FAQ - - - - - - - - - -
- -
-
- -

- Frequently Asked Questions -

- -

Logback project

- -
    -
  1. Why is logback distributed under LGPL and - not the Apache Software License? -
  2. - -
  3. What are logback's dependencies, i.e. - JDK version and third-party libraries? -
  4. -
- - -

Logback Classic

- - -
    -
  1. - Are logback loggers - serializable? -
  2. - -
  3. - How does the automatic configuration - work? -
  4. - -
  5. - Where should the configuration files, - logback-test.xml or logback.xml, be located - on the classpath? -
  6. - -
  7. - Is it possible for multiple JEE - applications to share the same configuration file but without - stepping on each other's toes? - -
  8. - -
  9. - - How can I disable logging from the command line? - -
  10. - -
  11. - How can Jetty be instructed to use - logback-classic as its logging implementataion? - -
  12. -
- - - - - - - -
-

Logback project

- -
-
- Why is logback distributed - under LGPL and not the Apache Software License? -
- -
-

The logback project is distributed under the LGPL license - in order to emphasize the fact that it is a related but - different project than log4j. -

- -

Given that Java v7 will be distributed under GPL, we expect - GPL and LGPL to become even more prevalent in the Java world. -

- -

In short, LGPL is a reasonable and widely-accepted - license. Let well alone. -

-
-
- -
- -
-
What are logback's - dependencies, i.e. JDK version and third-party libraries? -
- -

This question is answered on a separate page dedicated to the - question of dependencies.

-
-
- - -
- -
-

Logback-classic

-
- - - -
- - How does the automatic configuration work? - -
-
-

This question is answered in the relevant - section of the logback manual. -

-
-
- - - - -
- Where - should the configuration files, logback-test.xml or - logback.xml, be located on the classpath? -
- -
-

Configuration files such as logback-test.xml or - logback.xml can be located directly under - any folder declared in the class path. For example, if the - class path reads "c:/java/jdk15/lib/rt.jar;c:/mylibs/" then - the logback.xml file should be located directly - under "c:/mylibs/", that is as - "c:/mylibs/logback.xml". Placing it under a sub-folder of - c:/mylibs/, say, c:/mylibs/other/, will not work.

- -

For web-applications, configuration files can be placed - directly under WEB-INF/classes/.

- -
- -
- - - -
- - Are logback loggers serializable? -
-
-

Yes. A logback logger is an SLF4J logger and SLF4J - loggers are serializable. This means that an object - referencing a logger will be alble to log after its - deserialization. -

- -

The deserialized logger instance will be generated by - org.slf4j.LoggerFactory. Thus, it is possible - for a logback logger to be deserialized as a log4j or j.u.l. - logger, depending on the deserialization environment.

- -
-
- - - - -
- - Is it possible for multiple JEE applications to share the - same configuration file but without stepping on each other's - toes? -
-
-

Yes, it is. Using variable - substitution, it is possible to have a single - configuration file to output logs to different destinations - depending on each JEE application. Here is a sample - configuration file designed for this purpose.

- -

<configuration> - <appender name="FILE" class="ch.qos.logback.core.FileAppender"> - <!-- "application-name" is a variable --> - <File>c:/logs/${application-name}.log</File> - <layout class="ch.qos.logback.classic.PatternLayout"> - <Pattern>%d %p %t %c - %m%n</Pattern> - </layout> - </appender> - <root level="debug"> - <appender-ref ref="FILE"/> - </root> -</configuration>

- -

Assuming each JEE application loads a different copy of - logback classes into memory, if we can somehow inject a - different value for application-name - each time an application starts, logs will be output to - different files. We just need to initialize logback with the - above configuration file while injecting a different value - for application-name variable. Here is - sample code that programmatically configures logback. It - should be invoked during the initialization of your JEE - applications. -

- -

LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); - // inject the name of the current application as "applicaiton-name" - // property of the LoggerContext - context.putProperty("application-name", NAME_OF_CURRENT_APPLICATION); - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(context); - context.reset(); // override default configuration - jc.doConfigure("/path/to/the/above/configuration/file.xml");

- -
-
- - - - -
- - How can I disable logging from the command line? - -
-
-

Logback does not allow disabling logging from the command - line. However, if the configuration file allows it, you can - set the level of logers on the command line via a java - system property. Here is such a configuration file.

- -

<configuration> - <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> - <layout class="ch.qos.logback.classic.PatternLayout"> - <Pattern>%d [%thread] %level %logger - %m%n</Pattern> - </layout> - </appender> - <root level="${root-level:-INFO}"> - <appender-ref ref="CONSOLE"/> - </root> -</configuration>

- - -

Making use of variable - substitution as well as default - values for variables, if the root-level system property is set to - OFF, then all logging will be turned - off. However, if it is not set, it will assume the default - value of INFO. Note that you can set the root-level system property to any - level value of your choice. The value OFF is - just an example. - -

-
-
- - - - -
- - How can Jetty be instructed to use logback-classic as its - logging implementataion? - -
- -
-

The Jetty application server uses SLF4J for its internal - logging. -

- -

Logback jar files must be present on Jetty's class - path. These files are - logback-core-${project.version}.jar and - logback-classic-${project.version}.jar. These files - should be placed under the $JETTY_HOME/lib - directory. -

- - -

Since Jetty's uses an older version of SLF4J internally, - we recommend that the old version be replaced by - slf4j-api-${slf4j.version}.jar. This file can be - downloaded from the SLF4J project. -

- - -

For automaticly configuring logback-classic, you can - place the file logback.xml under the - $JETTY_HOME/resources directory. You can find - sample configuration files in the - logback-examples/src/main/java/chapter4/conf/ - folder shipping within the logback distribution. -

- -
-
- - - - - -
- - -
- - - -
- - - - - - + + + + + + Logback FAQ + + + + + + + + + +
+ +
+
+ +

+ Frequently Asked Questions +

+ +

Logback project

+ +
    +
  1. Why is logback distributed under LGPL and + not the Apache Software License? +
  2. + +
  3. What are logback's dependencies, i.e. + JDK version and third-party libraries? +
  4. +
+ + +

Logback Classic

+ + +
    +
  1. + Are logback loggers + serializable? +
  2. + +
  3. + How does the automatic configuration + work? +
  4. + +
  5. + Where should the configuration files, + logback-test.xml or logback.xml, be located + on the classpath? +
  6. + +
  7. + Is it possible for multiple JEE + applications to share the same configuration file but without + stepping on each other's toes? + +
  8. + +
  9. + + How can I disable logging from the command line? + +
  10. + +
  11. + How can Jetty be instructed to use + logback-classic as its logging implementataion? + +
  12. +
+ + + + + + + +
+

Logback project

+ +
+
+ Why is logback distributed + under LGPL and not the Apache Software License? +
+ +
+

The logback project is distributed under the LGPL license + in order to emphasize the fact that it is a related but + different project than log4j. +

+ +

Given that Java v7 will be distributed under GPL, we expect + GPL and LGPL to become even more prevalent in the Java world. +

+ +

In short, LGPL is a reasonable and widely-accepted + license. Let well alone. +

+
+
+ +
+ +
+
What are logback's + dependencies, i.e. JDK version and third-party libraries? +
+ +

This question is answered on a separate page dedicated to the + question of dependencies.

+
+
+ + +
+ +
+

Logback-classic

+
+ + + +
+ + How does the automatic configuration work? + +
+
+

This question is answered in the relevant + section of the logback manual. +

+
+
+ + + + +
+ Where + should the configuration files, logback-test.xml or + logback.xml, be located on the classpath? +
+ +
+

Configuration files such as logback-test.xml or + logback.xml can be located directly under + any folder declared in the class path. For example, if the + class path reads "c:/java/jdk15/lib/rt.jar;c:/mylibs/" then + the logback.xml file should be located directly + under "c:/mylibs/", that is as + "c:/mylibs/logback.xml". Placing it under a sub-folder of + c:/mylibs/, say, c:/mylibs/other/, will not work.

+ +

For web-applications, configuration files can be placed + directly under WEB-INF/classes/.

+ +
+ +
+ + + +
+ + Are logback loggers serializable? +
+
+

Yes. A logback logger is an SLF4J logger and SLF4J + loggers are serializable. This means that an object + referencing a logger will be alble to log after its + deserialization. +

+ +

The deserialized logger instance will be generated by + org.slf4j.LoggerFactory. Thus, it is possible + for a logback logger to be deserialized as a log4j or j.u.l. + logger, depending on the deserialization environment.

+ +
+
+ + + + +
+ + Is it possible for multiple JEE applications to share the + same configuration file but without stepping on each other's + toes? +
+
+

Yes, it is. Using variable + substitution, it is possible to have a single + configuration file to output logs to different destinations + depending on each JEE application. Here is a sample + configuration file designed for this purpose.

+ +

<configuration> + <appender name="FILE" class="ch.qos.logback.core.FileAppender"> + <!-- "application-name" is a variable --> + <File>c:/logs/${application-name}.log</File> + <layout class="ch.qos.logback.classic.PatternLayout"> + <Pattern>%d %p %t %c - %m%n</Pattern> + </layout> + </appender> + <root level="debug"> + <appender-ref ref="FILE"/> + </root> +</configuration>

+ +

Assuming each JEE application loads a different copy of + logback classes into memory, if we can somehow inject a + different value for application-name + each time an application starts, logs will be output to + different files. We just need to initialize logback with the + above configuration file while injecting a different value + for application-name variable. Here is + sample code that programmatically configures logback. It + should be invoked during the initialization of your JEE + applications. +

+ +

LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + // inject the name of the current application as "applicaiton-name" + // property of the LoggerContext + context.putProperty("application-name", NAME_OF_CURRENT_APPLICATION); + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(context); + context.reset(); // override default configuration + jc.doConfigure("/path/to/the/above/configuration/file.xml");

+ +
+
+ + + + +
+ + How can I disable logging from the command line? + +
+
+

Logback does not allow disabling logging from the command + line. However, if the configuration file allows it, you can + set the level of logers on the command line via a java + system property. Here is such a configuration file.

+ +

<configuration> + <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> + <layout class="ch.qos.logback.classic.PatternLayout"> + <Pattern>%d [%thread] %level %logger - %m%n</Pattern> + </layout> + </appender> + <root level="${root-level:-INFO}"> + <appender-ref ref="CONSOLE"/> + </root> +</configuration>

+ + +

Making use of variable + substitution as well as default + values for variables, if the root-level system property is set to + OFF, then all logging will be turned + off. However, if it is not set, it will assume the default + value of INFO. Note that you can set the root-level system property to any + level value of your choice. The value OFF is + just an example. + +

+
+
+ + + + +
+ + How can Jetty be instructed to use logback-classic as its + logging implementataion? + +
+ +
+

The Jetty application server uses SLF4J for its internal + logging. +

+ +

Logback jar files must be present on Jetty's class + path. These files are + logback-core-${project.version}.jar and + logback-classic-${project.version}.jar. These files + should be placed under the $JETTY_HOME/lib + directory. +

+ + +

Since Jetty's uses an older version of SLF4J internally, + we recommend that the old version be replaced by + slf4j-api-${slf4j.version}.jar. This file can be + downloaded from the SLF4J project. +

+ + +

For automaticly configuring logback-classic, you can + place the file logback.xml under the + $JETTY_HOME/resources directory. You can find + sample configuration files in the + logback-examples/src/main/java/chapter4/conf/ + folder shipping within the logback distribution. +

+ +
+
+ + + + + +
+ + +
+ + + +
+ + + + + + diff --git a/logback-site/src/site/pages/index.html b/logback-site/src/site/pages/index.html index 8120e40bc6870ee7a1500227e241bce925e0779b..5be9939893dcc757848af9e928760419dbe2926d 100644 --- a/logback-site/src/site/pages/index.html +++ b/logback-site/src/site/pages/index.html @@ -1,63 +1,63 @@ - - - - - - Logback Home - - - - - - - - -
- - -
-
- -

Logback Project

- -

Logback is intended as a successor to the popular log4j - project. It was designed, in addition to many individual - contributors, by Ceki Gülcü, the founder of log4j. It - builds upon experience gained in building industrial-strength - logging systems going back as far as 1999. -

- -

Logback's basic architecture is sufficiently generic so as to - apply under different circumstances. At present time, logback is - divided into three modules, logback-core, logback-classic and - logback-access. -

- -

The logback-core module lays the groundwork for the other two - modules. The logback-classic module can be assimilated to a - significantly improved version of log4j. Moreover, logback-classic - natively implements the SLF4J - API so that you can readily switch back and forth between - logback and other logging frameworks such as log4j or - java.util.logging (JUL). -

- -

The logback-access module integrates with Servlet containers, - such as Tomcat and Jetty, to provide HTTP-access log - functionality. Note that you could easily build your own module - on top of logback-core. -

- -

Sister projects

- -

The logback-audit project is - designed for processing logging events having long-term business - significance. Logback-audit is commercial software based on - logback-core. -

- - -
- - + + + + + + Logback Home + + + + + + + + +
+ + +
+
+ +

Logback Project

+ +

Logback is intended as a successor to the popular log4j + project. It was designed, in addition to many individual + contributors, by Ceki Gülcü, the founder of log4j. It + builds upon experience gained in building industrial-strength + logging systems going back as far as 1999. +

+ +

Logback's basic architecture is sufficiently generic so as to + apply under different circumstances. At present time, logback is + divided into three modules, logback-core, logback-classic and + logback-access. +

+ +

The logback-core module lays the groundwork for the other two + modules. The logback-classic module can be assimilated to a + significantly improved version of log4j. Moreover, logback-classic + natively implements the SLF4J + API so that you can readily switch back and forth between + logback and other logging frameworks such as log4j or + java.util.logging (JUL). +

+ +

The logback-access module integrates with Servlet containers, + such as Tomcat and Jetty, to provide HTTP-access log + functionality. Note that you could easily build your own module + on top of logback-core. +

+ +

Sister projects

+ +

The logback-audit project is + designed for processing logging events having long-term business + significance. Logback-audit is commercial software based on + logback-core. +

+ + +
+ + diff --git a/logback-site/src/site/pages/license.html b/logback-site/src/site/pages/license.html index af320a8f95bd52d5df750cdaddb92c41e0c96359..fa5131b462f0f82be7c52559050e65e44f34e4e4 100644 --- a/logback-site/src/site/pages/license.html +++ b/logback-site/src/site/pages/license.html @@ -1,76 +1,76 @@ - - - - - - License - - - - - - - - - -
- -
-
- -
-

Logback License

-
- - -

As of relase 0.9.18, logback source code and binaries are - dual-licensed under EPL v1.0 and the LGPL 2.1, or more - formally:

- -

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.

- - - -

Please note that logback is intended to be used behind the - SLF4J API, which is licensed under the MIT license. -

- -

The EPL/LGPL dual-license serves several purposes. The LGPL - license ensures continuity in terms of licensing of the - logback project. Prior to version 0.9.18, logback was licensed - (exlusively) under the LGPL v2.1. Moreover, since the EPL is - deemed incompatible - by the Free Software Foundation, the LGPL will allow various - licensees, in particular software distributors who may be already - bound by the terms of the GPL or the LGPL, to distribute our - software. -

- -

On the other hand, the EPL license will placate organizations - which refuse certain restrictions imposed by the LGPL. -

- -

If you wish to make a significant contribution to the logback - project, you are invited to file Contributor - License Agreement. The purpose of this agreement is to - formalize the terms of your contribution and to protect the - project in case of litigation. -

- - -
- - + + + + + + License + + + + + + + + + +
+ +
+
+ +
+

Logback License

+
+ + +

As of relase 0.9.18, logback source code and binaries are + dual-licensed under EPL v1.0 and the LGPL 2.1, or more + formally:

+ +

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.

+ + + +

Please note that logback is intended to be used behind the + SLF4J API, which is licensed under the MIT license. +

+ +

The EPL/LGPL dual-license serves several purposes. The LGPL + license ensures continuity in terms of licensing of the + logback project. Prior to version 0.9.18, logback was licensed + (exlusively) under the LGPL v2.1. Moreover, since the EPL is + deemed incompatible + by the Free Software Foundation, the LGPL will allow various + licensees, in particular software distributors who may be already + bound by the terms of the GPL or the LGPL, to distribute our + software. +

+ +

On the other hand, the EPL license will placate organizations + which refuse certain restrictions imposed by the LGPL. +

+ +

If you wish to make a significant contribution to the logback + project, you are invited to file Contributor + License Agreement. The purpose of this agreement is to + formalize the terms of your contribution and to protect the + project in case of litigation. +

+ + +
+ + diff --git a/logback-site/src/site/pages/mailinglist.html b/logback-site/src/site/pages/mailinglist.html index c03f6fef3bbad4f9acdc887becadcceec3259996..e6ee0fc0567242b594ef25d0ea5ddaeb39dd2405 100644 --- a/logback-site/src/site/pages/mailinglist.html +++ b/logback-site/src/site/pages/mailinglist.html @@ -1,162 +1,162 @@ - - - - - - Mailing lists - - - - - - - - - -
- - -
-
- -

Project Mailing Lists

- -

A mailing list is an electronic discussion forum that anyone - can subscribe to. When someone sends an email message to the - mailing list, a copy of that message is broadcast to everyone who - is subscribed to that mailing list. Mailing lists provide a simple - and effective communication mechanism. With potentially thousands - of subscribers, there is a common set of etiquette guidelines that - you should observe. Please keep on reading. -

- -

Respect the mailing list type

- -

The "User" lists where you can send questions and comments - about configuration, setup, usage and other "user" types of - questions. The "Developer" lists where you can send questions and - comments about the actual software source code and other issues - related to development. -

- -

Some questions are appropriate for posting on both the "user" - and the "developer" lists. In this case, pick one and only one. Do - not cross post. -

- -

Please do your best to ensure that you are not sending HTML or - "Stylelized" email to the list. If you are using Outlook or - Outlook Express or Eudora, chances are that you are sending HTML - email by default. There is usually a setting that will allow you - to send "Plain Text" email. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameVolumeSubscribeUnsubscribeArchives
QOS.ch announce ListLow - - Subscribe - - - - Unsubscribe - - - - qos.ch - -
Logback User ListMedium - - Subscribe - - - - Unsubscribe - - - - qos.ch - | - - MARC - | - - - Nabble - -
Logback Dev ListMedium - - Subscribe - - - - Unsubscribe - - - - qos.ch - | - - MARC - | - - Nabble - -
- - -

 

- -

On IRC

- -

We can also be reached by IRC at irc.freenode.net#qos.ch.

- -

 

- - -
- - + + + + + + Mailing lists + + + + + + + + + +
+ + +
+
+ +

Project Mailing Lists

+ +

A mailing list is an electronic discussion forum that anyone + can subscribe to. When someone sends an email message to the + mailing list, a copy of that message is broadcast to everyone who + is subscribed to that mailing list. Mailing lists provide a simple + and effective communication mechanism. With potentially thousands + of subscribers, there is a common set of etiquette guidelines that + you should observe. Please keep on reading. +

+ +

Respect the mailing list type

+ +

The "User" lists where you can send questions and comments + about configuration, setup, usage and other "user" types of + questions. The "Developer" lists where you can send questions and + comments about the actual software source code and other issues + related to development. +

+ +

Some questions are appropriate for posting on both the "user" + and the "developer" lists. In this case, pick one and only one. Do + not cross post. +

+ +

Please do your best to ensure that you are not sending HTML or + "Stylelized" email to the list. If you are using Outlook or + Outlook Express or Eudora, chances are that you are sending HTML + email by default. There is usually a setting that will allow you + to send "Plain Text" email. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameVolumeSubscribeUnsubscribeArchives
QOS.ch announce ListLow + + Subscribe + + + + Unsubscribe + + + + qos.ch + +
Logback User ListMedium + + Subscribe + + + + Unsubscribe + + + + qos.ch + | + + MARC + | + + + Nabble + +
Logback Dev ListMedium + + Subscribe + + + + Unsubscribe + + + + qos.ch + | + + MARC + | + + Nabble + +
+ + +

 

+ +

On IRC

+ +

We can also be reached by IRC at irc.freenode.net#qos.ch.

+ +

 

+ + +
+ + diff --git a/logback-site/src/site/pages/manual/.htaccess b/logback-site/src/site/pages/manual/.htaccess index 9e2395e07720e4379cf822221dee888d5adf6461..ad41956b96d69a76e8744081cc99419c63fa0e81 100644 --- a/logback-site/src/site/pages/manual/.htaccess +++ b/logback-site/src/site/pages/manual/.htaccess @@ -1,2 +1,2 @@ -Redirect contextSelector.html http://logback.qos.ch/manual/loggingSeparation.html +Redirect contextSelector.html http://logback.qos.ch/manual/loggingSeparation.html Redirect joran.html http://logback.qos.ch/manual/configuration.html \ No newline at end of file diff --git a/logback-site/src/site/pages/manual/appenders.html b/logback-site/src/site/pages/manual/appenders.html index debc52e1e61cf5e7d468433ee3ebdd7480acb85b..473bfa3372af2b59ae431f647e60c9b63324bba3 100644 --- a/logback-site/src/site/pages/manual/appenders.html +++ b/logback-site/src/site/pages/manual/appenders.html @@ -1,3809 +1,3809 @@ - - - - - Chapter 4: Appenders - - - - - - - - -
- - -
- - -
- -

Chapter 4: Appenders

- -
- -

There is so much to tell about the Western country in - that day that it is hard to know where to start. One thing sets - off a hundred others. The problem is to decide which one to tell - first.

- -

—JOHN STEINBECK, East of Eden

-
- - - - - -

What is an Appender?

- -

Logback delegates the task of writing a logging event to - components called appenders. Appenders must implement the ch.qos.logback.core.Appender - interface. The salient methods of this interface are summarized - below: -

-
package ch.qos.logback.core;
-  
-import ch.qos.logback.core.spi.ContextAware;
-import ch.qos.logback.core.spi.FilterAttachable;
-import ch.qos.logback.core.spi.LifeCycle;
-  
-
-public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable {
-
-  public String getName();
-  void doAppend(E event);
-  public void setLayout(Layout<E> layout);
-  public Layout<E> getLayout();
-  public void setName(String name);
-  
-}
- -

Most of the methods in the Appender interface are - made of setter and getter methods. A notable exception is the - doAppend() method taking an object instance of type - E as its only parameter. The actual type of E - would vary depending on the logback module. Within the - logback-classic module E would be of type ILoggingEvent - and within the logback-access module it would be of type AccessEvent. - The doAppend() method is perhaps the most important in - the logback framework. It is responsible for outputting the logging - events in a suitable format to the appropriate output device. -

- -

Appenders are named entities. This ensures that they can be - referenced by name, a quality confirmed to be instrumental in - configuration scripts. The Appender interface extends - the FilterAttachable interface. It follows that one or - more filters can be attached to an appender instance. Filters are - discussed in detail in a subsequent chapter. -

- -

Appenders are ultimately responsible for outputting logging - events. However, they may delegate the actual formatting of the - event to a Layout object. Each layout is associated - with one and only one appender, referred to as the owning - appender. Some appenders have a built-in or fixed event - format. Consequently, they do not require nor have a layout. For - example, the SocketAppender simply serializes logging - events before transmitting them over the wire. -

- - -

AppenderBase

- -

The - ch.qos.logback.core.AppenderBase class is an - abstract class implementing the Appender interface. It - provides basic functionality shared by all appenders, such as - methods for getting or setting their name, their activation status, - their layout and their filters. It is the super-class of all - appenders shipped with logback. Although an abstract class, - AppenderBase actually implements the - doAppend() method in the Append interface. - Perhaps the clearest way to discuss AppenderBase class - is by presenting an excerpt of actual source code. -

- -
public synchronized void doAppend(E eventObject) {
-
-  // prevent re-entry.
-  if (guard) {
-    return;
-  }
-
-  try {
-    guard = true;
-
-    if (!this.started) {
-      if (statusRepeatCount++ < ALLOWED_REPEATS) {
-        addStatus(new WarnStatus(
-            "Attempted to append to non started appender [" + name + "].",this));
-      }
-      return;
-    }
-
-    if (getFilterChainDecision(eventObject) == FilterReply.DENY) {
-      return;
-    }
-    
-    // ok, we now invoke derived class' implementation of append
-    this.append(eventObject);
-
-  } finally {
-    guard = false;
-  }
-}
- -

This implementation of the doAppend() method is - synchronized. It follows that logging to the same appender from - different threads is safe. While a thread, say T, is - executing the doAppend() method, subsequent calls by - other threads are queued until T leaves the - doAppend() method, ensuring T's exclusive - access to the appender. -

- -

The first thing the doAppend() method does is to - check whether the guard is set to true. If it is, it immediately - exits. If the guard is not set, it is set to true at the next - statement. The guard ensures that the doAppend() method - will not recursively call itself. Just imagine that a component, - called somewhere beyond the append() method, wants to - log something. Its call could be directed to the very same appender - that just called it. -

- -

In the following statement we check whether the - started field is true. If it is not, - doAppend() will send a warning message and return. In - other words, once an appender is closed, it is impossible to write - to it. Appender objects implement the - LifeCycle interface, which implies that they implement - start(), stop() and - isStarted() methods. After setting all the properties of - an appender, Joran, logback's configuration framework, calls the - start() method to signal the appender to activate its - properties. Depending on its kind, an appender may fail to start if - certain properties are missing or because of interferences between - various properties. For example, given that file creation depends on - truncation mode, FileAppender cannot act on the value - of its File option until the value of the Append option - is also known with certainty. The explicit activation step ensures - that an appender acts on its properties after their values - become known. -

- -

If the appender could not be started or if it has been stopped, a - warning message will be issued through logback's internal status - management system. After several attempts, in order to avoid - flooding the internal status system with copies of the same warning - message, the doAppend() method will stop issuing these - warnings. -

- -

The next if statement checks the result of the - attached filters. Depending on the decision resulting from the - filter chain, events can be denied or alternatively accepted. In - the absence of a decision by the filter chain, events are accepted - by default. -

- -

The doAppend() method then invokes the derived - classes' implementation of the append() method. This - method does the actual work of appending the event to the - appropriate device. -

- -

Finally, the guard is released so as to allow a subsequent - invocation of the doAppend() method. -

- -

For the remainder of this manual, we reserve the term "option" or - alternatively "property" for any attribute that is inferred - dynamically using JavaBeans introspection through setter and getter - methods.

- -

Logback-core

- -

Logback-core lays the foundation upon which the other logback - modules are built. In general, the components in logback-core - require some, albeit minimal, customization. However, in the next - few sections, we describe several appenders which are ready for use - out of the box. -

- - - -

- WriterAppender -

- -

WriterAppender - appends events to a java.io.Writer. This class - provides basic services that other appenders build upon. Users do - not usually instantiate WriterAppender objects - directly. Since java.io.Writer type cannot be mapped - to a string, as there is no way to specify the target - Writer object in a configuration script. Simply put, - you cannot configure a WriterAppender from a script. - However, this does not mean that WriterAppender lacks - configurable properties. These properties are described next. -

- - - - - - - - - - - - - - - - - - - - - -
Property NameTypeDescription
EncodingStringThe encoding specifies the method of conversion between - Java's internal 16-bit Unicode representation of characters into - raw 8-bit bytes. This appender will use the local platform's - default encoding unless you say otherwise by specifying an Encoding value. According to the - java.lang package documentation, acceptable values - are dependent on the VM implementation although all - implementations are required to support at least the following - encodings: US-ASCII, ISO-8859-1, - UTF-8, UTF-16BE, UTF-16LE and - UTF-16. As mentioned previously, by default, the Encoding option is null such - that the platform's default encoding is used. -
ImmediateFlushbooleanIf the ImmediateFlush option is - set to true, then each write of a logging event will be followed - by a flush operation on the underlying Writer - object. Conversely, if the option is set to false, each write - will not be followed by a flush. In general, skipping the flush - operation improves logging throughput by roughly 15%. The - downside is that if the application exits abruptly, the - unwritten characters buffered inside the Writer - might be lost. This can be particularly troublesome as those - unwritten characters may contain crucial information needed in - identifying the reasons behind a crash. By default, the ImmediateFlush option is set to true. -
- -

In general, if you disable immediate flushing, then make sure to - flush any output streams when your application exits. Otherwise, log - messages will be lost as illustrated by the next example. -

- - Example 4.: Exiting an application without flushing (logback-examples/src/main/java/chapter4/ExitWoes1.java) - -
package chapter4;
-
-import java.io.FileOutputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-
-
-import org.slf4j.LoggerFactory;
-
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.WriterAppender;
-import ch.qos.logback.core.layout.EchoLayout;
-
-public class ExitWoes1 {
-
-  public static void main(String[] args) throws Exception {
-    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-    lc.reset(); // we want to override the default-config.
-    WriterAppender<ILoggingEvent> writerAppender = new WriterAppender<ILoggingEvent>();
-    writerAppender.setContext(lc);
-    writerAppender.setLayout(new EchoLayout<ILoggingEvent>());
-
-    OutputStream os = new FileOutputStream("exitWoes1.log");
-    writerAppender.setWriter(new OutputStreamWriter(os));
-    writerAppender.setImmediateFlush(false);
-    writerAppender.start();
-    Logger root = lc.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
-    root.addAppender(writerAppender);
-
-    Logger logger = lc.getLogger(ExitWoes1.class);
-
-    logger.debug("Hello world.");
-  }
-}
- -

This example creates a WriterAppender that uses an - OutputStreamWriter wrapping a - FileOutputStream as its underlying Writer - object, with immediate flushing disabled. It then proceeds to log a - single debug message. According to OutputStreamWriter - javadocs, each invocation of a write() method causes - the encoding converter to be invoked on the given character(s). The - resulting bytes are accumulated in a buffer before being written to - the underlying output stream. As astonishing as this may seem, - running ExitWoes1 will not produce any data in the file - exitWoes1.log because the Java VM does not flush output - streams when it exits. Calling the stop() - method of a LoggerContext ensures that all appenders in - the hierarchy are closed and their buffers are flushed. The ExitWoes2 class - uses this statement and outputs a logging request. -

- -

The WriterAppender is the superclass of three other - appenders, namely ConsoleAppender, - FileAppender which in turn is the super class of - RollingFileAppender. The next figure illustrates the - class diagram for WriterAppender and its subclasses. -

- - A UML diagram showing FileAppender - - -

- ConsoleAppender -

- -

The - ConsoleAppender, as the name indicates, appends on - the console, or more precisely on System.out or - System.err, the former being the default - target. ConsoleAppender formats events with a layout - specified by the user. Layouts will be discussed in the next - chapter. Both System.out and System.err are - java.io.PrintStream objects. Consequently, they are - wrapped inside an OutputStreamWriter which buffers I/O - operations but not character conversions. -

- - - - - - - - - - - - - - - - - - - - - - -
Property NameTypeDescription
EncodingStringSee WriterAppender properties.
ImmediateFlushbooleanSee WriterAppender properties.
TargetString - One of the String values System.out or - System.err. The default target is System.out. -
- -

Here is a sample configuration that uses - ConsoleAppender. -

- - Example 4.: ConsoleAppender configuration (logback-examples/src/main/java/chapter4/conf/logback-Console.xml) -
<configuration>
-
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

After you have set your current path to the - logback-examples directory, you can give the above - configuration file a whirl by issuing the following command: -

- -

java chapter4.ConfigurationTester src/main/java/chapter4/conf/logback-Console.xml

- - -

- FileAppender -

- -

The FileAppender, - a subclass of WriterAppender, appends log events into - a file. The target file is specified by the File option. If the file already exists, it - is either appended to, or truncated depending on the value of the - Append option. - FileAppender uses a FileOutputStream - which is wrapped by an OutputStreamWriter. Note that - OutputStreamWriter buffers I/O operations but not - character conversions. To optimize character conversions one can - set the BufferedIO option to true which - effectively wraps the OutputStreamWriter with a - BufferedWriter. Properties for FileAppender - are summarized below. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Property NameTypeDescription
AppendbooleanIf true, events are appended at the end of an existing - file. Otherwise, if Append is - false, any existing file is truncated. The Append option is set to true by - default. -
EncodingStringSee WriterAppender properties.
BufferedIObooleanThe BufferedIO option is set to - false by default. If set to true, the underlying - OutputStreamWriter is wrapped by a - BufferedWriter object. Setting BufferedIO to true automatically sets the - ImmediateFlush option to false. - The name BufferedIO is slightly - misleading because buffered I/O is already supported by - OutputStreamWriter. Setting BufferedIO to true has the effect of - buffering I/O as well as character to raw byte conversions, - saving a few CPU cycles in the process. -
BufferSizeintSize of BufferedWriter buffer. The default value is 8192.
FileStringThe name of the file to write to. If the file does not - exist, it is created. On the MS Windows platform users - frequently forget to escape back slashes. For example, the - value c:\temp\test.log is not likely to be interpreted - properly as '\t' is an escape sequence interpreted as - a single tab character (\u0009). Correct values can - be specified as c:/temp/test.log or alternatively as - c:\\temp\\test.log. The File option has no default value. - -

If the parent directory of the file does now exist, the - FileAppender will automatically create it, including any - necessary but nonexistent parent directories. -

-
ImmediateFlushbooleanSee WriterAppender properties.
Prudentboolean -

In prudent mode, FileAppeder will safely - write to the specified file, even in the presence of other - FileAppender instances running in different - JVMs, potentially running on different hosts. The default - value for prudent mode is false. -

- -

Prudent mode implies that Append and ImmediateFlush properties are - automatically set to true and the BufferedIO set to false. -

- -

Prudent mode will approximately triple (x3) the cost of - writing a logging event. On an "average" PC writing to a file - located on a local hard disk, when prudent mode is off, it - takes about 10 microseconds to write a single logging - event. When prudent mode is on, it takes approximately 30 - microseconds to output a single logging event. This - translates to logging throughput of 100'000 events per second - when prudent mode is off and approximately 33'000 events per - second in prudent mode. -

- -

Prudent mode can be used in conjunction with - RollingFileAppender although some restrictions apply. -

-
- -

By default, FileAppender performs a flush on each - event, ensuring that events are immediately written to disk. - Setting the ImmediateFlush option to - false can drastically reduce I/O activity by letting - OutputStreamWriter buffer bytes before writing them on - disk. For short messages, we have observed 2 or 3 fold increases in - logging throughput, i.e. the number of logs output per unit of - time. For longer messages, the throughput gains are somewhat less - dramatic, and range between 1.4 and 2 fold. Enabling the BufferedIO option, that is buffering - character to byte conversions, increases performance by an - additional 10% to 40% compared to only disk I/O buffering (ImmediateFlush=false). Performance varies - somewhat depending on the host machine as well as JDK version. - Throughput measurements are based on the chapter4.IO - application. Please refer to - logback-examples/src/main/java/chapter4/IO.java for - actual source code. -

- -

Below is an example of a configuration file for - FileAppender: -

- - Example 4.: FileAppender configuration (logback-examples/src/main/java/chapter4/conf/logback-fileAppender.xml) -
<configuration>
-
-  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
-    <File>testFile.log</File>
-    <Append>true</Append>
-		
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
-    </layout>
-  </appender>
-	
-  <root level="debug">
-    <appender-ref ref="FILE" />
-  </root>
-</configuration>
- -

After changing the current directory to - logback-examples, run this example by launching the - following command: -

- -

java chapter4.ConfigurationTester src/main/java/chapter4/conf/logback-fileAppender.xml

- - -

- Uniquely named - files (by timestamp) -

- -

During the application development phase or in the case of - short-lived applications, e.g. batch applications, it is desirable - to create a new log file at each new application launch. This is - fairly easy to do with the help of the <timestamp> - element. Here's an example.

- - - Example 4.: Uniquely named FileAppender configuration by timestamp (logback-examples/src/main/java/chapter4/conf/logback-timestamp.xml) -
<configuration>
-
-  <!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under
-       the key "bySecond" into the logger context. This value will be
-       available to all subsequent configuration elements. -->
-  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
-
-  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
-    <!-- use the previously created timestamp to create a uniquely
-         named log file -->
-    <File>log-${bySecond}.txt</File>
-    <layout>
-      <Pattern>%logger{35} - %msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="FILE" />
-  </root>
-</configuration>
- - -

The timestamp element takes two attributes key and datePattern. The key - attribute is the name of the key under which the timestamp will be - available to subsequent configuration elements as a - variable. The datePattern attribute - denoted the date pattern used to convert the current time (at which - the configuration file is parsed) into a string. The date pattern - should follow the conventions defined in SimpleDateFormat. -

- -

- RollingFileAppender -

- -

RollingFileAppender - extends FileAppender with the capability to roll log - files. For example, RollingFileAppender can log to a - file named log.txt file and, once a certain condition is - met, change its logging target to another file. -

- -

There are two important logback components that interact with - RollingFileAppender. First, a - RollingPolicy instance attached to the - RollingFileAppender is responsible for undertaking the - action for performing a rollover. Second, a - TriggeringPolicy instance attached to a - RollingFileAppender will determine if and exactly when - rollover happens Thus, RollingPolicy is responsible - for the what and TriggeringPolicy is - responsible for the when. -

- -

To be of any use, a RollingFileAppender must have - both a RollingPolicy and a - TriggeringPolicy set up. However, if its - RollingPolicy also implements the - TriggeringPolicy interface, then only the former needs - to be set up. -

- -

Here are the available properties for RollingFileAppender:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

See also FileAppender properties.

- - -
Property NameTypeDescription
AppendbooleanSee FileAppender properties.
BufferedIObooleanSee FileAppender properties.
BufferSizeintSee FileAppender properties.
EncodingStringSee WriterAppender properties.
FileStringSee FileAppender properties.
ImmediateFlushbooleanSee WriterAppender properties.
RollingPolicyRollingPolicyThis option is the component that will dictate - RollingFileAppender's behavior when rollover - occurs. See more information below. -
TriggeringPolicyTriggeringPolicy - This option is the component that will tell - RollingFileAppender when to activate the rollover - procedure. See more information below. -
Prudentboolean - -

FixedWindowRollingPolicy - is not supported in prudent mode.

- -

RollingFileAppender supports the prudent - mode in conjunction with TimeBasedRollingPolicy - albeit with two restrictions. - -

    -
  1. In prudent mode, file compression is not supported nor - allowed. (We can't have one JVM writing to a file while - another JVM is compressing it.)
  2. - -
  3. The File property of - FileAppender cannot be set and must be left - blank. Indeed, most operating systems do not allow renaming - of a file while another process has it opened. -
  4. - -
- -
- -

Rolling policies

- -

RollingPolicy - is responsible for the rollover procedure. It manages file renaming - and in occasion file deleting.

- -

The RollingPolicy interface is presented below:

- -
package ch.qos.logback.core.rolling;  
-
-import ch.qos.logback.core.FileAppender;
-import ch.qos.logback.core.spi.LifeCycle;
-
-public interface RollingPolicy extends LifeCycle {
-
-  public void rollover() throws RolloverFailure;
-  public String getNewActiveFileName();
-  public void setParent(FileAppender appender);
-}
- -

The rollover method proceeds to the file change, - renaming or deletion. The getNewActiveFileName() - method is called to compute a new file name, with respect to the - configuration elements that were injected into the - RollingPolicy. Lastly, a RollingPolicy - is given a reference to its parent via the setParent - method. -

- -

- FixedWindowRollingPolicy -

- -

When rolling over, - FixedWindowRollingPolicy renames files according - to a fixed window algorithm as described below. -

- -

The FileNamePattern option - represents the file name pattern for the archived (rolled over) log - files. This option is required and must include an integer token - %i somewhere within the pattern. -

- -

Here are the available properties for - FixedWindowRollingPolicy -

- - - - - - - - - - - - - - - - - - - - - - -
Property NameTypeDescription
MinIndexint -

This option represents the lower bound for the window's - index. -

-
MaxIndexint -

This option represents the upper bound for the window's - index. -

-
FileNamePatternString -

This option represents the pattern that will be followed - by the FixedWindowRollingPolicy when renaming - the log files. If must contain the string %i, which - will indicate the position where the value of the current - window index will be inserted. -

-

For example, using MyLogFile%i.log, associated - with minimum and maximum values of 1 and 3 - will produce archive files named MyLogFile1.log, - MyLogFile2.log and MyLogFile3.log. -

-

Note that file compression is also specified via the FileNamePattern option. For example, the - file name pattern MyLogFile%i.log.zip will indicate - to the FixedWindowRollingPolicy that the archived - file must be compressed using the zip format; - gz format is also supported. -

-
- -

Given that the fixed window rolling policy requires as many file - renaming operations as the window size, large window sizes are - strongly discouraged. The current implementation will automatically - reduce the window size to 12, when larger values are specified by - the user. -

- -

Let us go over a more concrete example of the fixed windows - rollover policy. Suppose that the MinIndex is set to 1, MaxIndex set to 3, that FileNamePattern option is set to - foo%i.log, and that FileNamePattern option is set to - foo.log. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Number of rolloversActive output targetArchived log filesDescription
0foo.log-No rollover has happened yet, logback logs into the initial - file. -
1foo.logfoo1.logFirst rollover. foo.log is renamed as - foo1.log. A new foo.log file is created and - becomes the active output target. -
2foo.logfoo1.log, foo2.logSecond rollover. foo1.log is renamed as - foo2.log. foo.log is renamed as - foo1.log. A new foo.log file is created and - becomes the active output target. -
3foo.logfoo1.log, foo2.log, foo3.logThird rollover. foo2.log is renamed as - foo3.log. foo1.log is renamed as - foo2.log. foo.log is renamed as - foo1.log. A new foo.log file is created and - becomes the active output target. -
4foo.logfoo1.log, foo2.log, foo3.logIn this and subsequent rounds, the rollover begins by - deleting foo3.log. Other files are renamed by - incrementing their index as shown in previous steps. In this and - subsequent rollovers, there will be three archive logs and one - active log file. -
- -

The configuration file below gives an example of configuring - RollingFileAppender and - FixedWindowRollingPolicy. Note that the File option is mandatory even if it contains - some of the same information as conveyed with the FileNamePattern option. -

- - Example 4.: Sample configuration of a RollingFileAppender using a - FixedWindowRollingPolicy (logback-examples/src/main/java/chapter4/conf/logback-RollingFixedWindow.xml) - -
<configuration>
-  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
-    <File>test.log</File>
-
-    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
-      <FileNamePattern>tests.%i.log.zip</FileNamePattern>
-      <MinIndex>1</MinIndex>
-      <MaxIndex>3</MaxIndex>
-    </rollingPolicy>
-
-    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
-      <MaxFileSize>5MB</MaxFileSize>
-    </triggeringPolicy>
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
-    </layout>
-  </appender>
-	
-  <root level="debug">
-    <appender-ref ref="FILE" />
-  </root>
-</configuration>
- -

- TimeBasedRollingPolicy -

- -

- TimeBasedRollingPolicy is possibly the most - popular rolling policy. It defines a rollover policy based on time, - for example by day or by month. -

- -

TimeBasedRollingPolicy's admits two properties, the - mandatory FileNamePattern property and - the optional MaxHistory property. -

- -

FileNamePattern property defines the - name of the rolled (archived) log files. Its value should consist - of the name of the file, plus a suitably placed %d - conversion specifier. The %d conversion specifier may - contain a date-and-time pattern as specified by the - java.text.SimpleDateFormat class. If the - date-and-time pattern is omitted, then the default pattern - yyyy-MM-dd is assumed. The File property in - RollingFileAppender (the parent of - TimeBasedRollingPolicy) can be either set or omitted. - -

- -

By setting the File property you can - decouple the location of the active log file and the location of - the archived log files. The current logs will be always targeted at - the file specified by the File - property. It follows that the name of the currently active log file - will not change over time. However, if you choose to omit the File property, then the active file will be - computed anew for each period based on the value of FileNamePattern. The following examples - should clarify the point. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- FileNamePattern - Rollover scheduleExample
- /wombat/foo.%d - Daily rollover (at midnight). Due to the omission of the - optional time and date pattern for the %d token - specifier, the default pattern of yyyy-MM-dd is - assumed, which corresponds to daily rollover. - -

File property not set: During November - 23rd, 2006, logging output will go to the file - /wombat/foo.2006-11-23. At midnight and for the - rest of the 24th, logging output will be directed to - /wombat/foo.2006-11-24. -

- -

File property set to - /wombat/foo.txt: During November 23rd, 2006, logging - output will go to the file /wombat/foo.txt. At - midnight, foo.txt will be renamed as - /wombat/foo.2006-11-23. A new - /wombat/foo.txt file will be created and for the - rest of November 24th logging output will be directed to - foo.txt. -

- -
- /wombat/%d{yyyy/MM}/foo.txt - Rollover at the beginning of each month. -

File property not set: During the - month of October 2006, logging output will go to - /wombat/2006/10/foo.txt. After midnight of October - 31st and for the rest of November, logging output will be - directed to /wombat/2006/11/foo.txt. -

- -

File property set to - /wombat/foo.txt: The active log file will always be - /wombat/foo.txt. During the month of October 2006, - logging output will go to /wombat/foo.txt. At - midnight of October 31st, /wombat/foo.txt will be - renamed as /wombat/2006/10/foo.txt. A new - /wombat/foo.txt file will be created where logging - output will go for the rest of November. At midnight of - November 30th, /wombat/foo.txt will be renamed as - /wombat/2006/11/foo.txt and so on. -

-
- /wombat/foo.%d{yyyy-ww}.log - Rollover at the first day of each week. Note that the first - day of the week depends on the locale.Similar to previous cases, except that rollover will occur - at the beginning of every new week. -
- /wombat/foo.   /
%d{yyyy-MM-dd_HH}.log
-
Rollover at the top of each hour.Similar to previous cases, except that rollover will occur - at the top of every hour. -
- /wombat/foo.    /
%d{yyyy-MM-dd_HH-mm}.log
-
Rollover at the beginning of every minute.Similar to previous cases, except that rollover will occur - at the beginning of every minute. -
- -

Any forward or backward slash characters are interpreted as - folder (directory) separators. Any required folder will be created - as necessary. You can thus easily place your log files in separate - folders. -

- -

The date-and-time pattern, as found within accolades in %d{} - follow java.text.SimpleDateFormat conventions. This any characters - within the date-and-time pattern outside the ranges - ['a'..'z'] and ['A'..'Z'] will be treated as - quoted text. For instance, characters like '.', ' - ', '#' and '@' will appear in the resulting - time text even when they are not enclosed within single - quotes. Nevertheless, we recommend against using the colon - ':' character anywhere within the FileNamePattern option. The text before the - colon is interpreted as the protocol specification of a URL, which - is most probably not what you intend. The forward slash - '/' or backward slash '\' characters anywhere - within the FileNamePattern property or - within the date-and-time pattern will be interpreted as directory - separators and any missing directories will be created as - necessary. -

- - -

Just like FixedWindowRollingPolicy, - TimeBasedRollingPolicy supports automatic file - compression. This feature is enabled if the value of the FileNamePattern option ends with .gz - or .zip. -

- - - - - - - - - - - -
FileNamePatternRollover scheduleExample
/wombat/foo.%d.gzDaily rollover (at midnight) with automatic GZIP compression of the - archived files. -

File property not set: During - November 23rd, 2009, logging output will go to the file - /wombat/foo.2009-11-23. However, at midnight that - file will be compressed to become - /wombat/foo.2009-11-23.gz. For the 24th of November, - logging output will be directed to - /wombat/folder/foo.2009-11-24 until it's rolled over - at the beginning of the next day. -

- -

File property set to - /wombat/foo.txt: During November 23rd, 2009, logging output - will go to the file /wombat/foo.txt. At midnight that - file will be compressed and renamed as - /wombat/foo.2009-11-23.gz. A new - /wombat/foo.txt file will be created where logging - output will go for the rest of November 24rd. At midnight - November 24th, /wombat/foo.txt will be compressed and - renamed as /wombat/foo.2009-11-24.gz. and so on. -

-
- -

The FileNamePattern serves a dual - purpose. First, by studying the pattern, logback computes the - requested rollover periodicity. Second, it computes each archived - file's name. Note that it is possible for two different patterns to - specify the same periodicity. The patterns yyyy-MM and - yyyy@MM both specify monthly rollover, although the - resulting archive files will carry different names. -

- -

TimeBasedRollingPolicy assumes the responsibility - for rollover as well as for the triggering of said rollover. Indeed, - TimeBasedTriggeringPolicy implements both - RollingPolicy and TriggeringPolicy - interfaces. -

- -

By setting the File property you can - decouple the location of the active log file and the location of the - archived log files. The logging output will be targeted into the - file specified by the File property. It - follows that the name of the active log file will not change over - time. However, if you choose to omit the File property, then the active file will be - computed anew for each period based on the value of FileNamePattern. -

- -

The MaxHistory property controls the - maximum number of archive files to keep, deleting older files. For - example, if you specify monthly rollover, and set MaxHistory to 6, then 6 months worth of - archives files will be kept with files older than 6 months - deleted. Note as old archived log files are removed, any folders - which were created for the purpose of log file archiving will be - removed as appropriate. -

- - -

For various technical reasons, rollovers are not clock-driven but - depend on the arrival of logging events. For example, on 8th of - March 2002, assuming the FileNamePattern - is set to yyyy-MM-dd (daily rollover), the arrival of the - first event after midnight will trigger a rollover. If there are no - logging events during, say 23 minutes and 47 seconds after midnight, - then rollover will actually occur at 00:23'47 AM on March 9th and - not at 0:00 AM. Thus, depending on the arrival rate of events, - rollovers might be triggered with some latency. However, regardless - of the delay, the rollover algorithm is known to be correct, in the - sense that all logging events generated during a certain period will - be output in the correct file delimiting that period. -

- -

Here is a sample configuration for - RollingFileAppender in conjunction with a - TimeBasedRollingPolicy. -

- - Example 4.: Sample configuration of a RollingFileAppender using a - TimeBasedRollingPolicy (logback-examples/src/main/java/chapter4/conf/logback-RollingTimeBased.xml) -
<configuration>
-  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
-    <File>logFile.log</File>
-    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-      <FileNamePattern>logFile.%d{yyyy-MM-dd}.log</FileNamePattern>
-      <!-- keep 30 days' worth of history -->
-      <MaxHistory>30</MaxHistory>
-    </rollingPolicy>
-
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
-    </layout>
-  </appender> 
-
-  <root level="debug">
-    <appender-ref ref="FILE" />
-  </root>
-</configuration>
- -

The next configuration sample illustrates the use of - RollingFileAppender associated with - TimeBasedRollingPolicy in Prudent - mode. -

- - Example 4.: Sample configuration of a RollingFileAppender using a - TimeBasedRollingPolicy (logback-examples/src/main/java/chapter4/conf/logback-PrudentTimeBasedRolling.xml) -
<configuration>
-  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
-    <!-- Support multiple-JVM writing to the same log file -->
-    <Prudent>true</Prudent>
-    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-      <FileNamePattern>logFile.%d{yyyy-MM-dd}.log</FileNamePattern>
-      <MaxHistory>30</MaxHistory> 
-    </rollingPolicy>
-
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
-    </layout>
-  </appender> 
-
-  <root level="debug">
-    <appender-ref ref="FILE" />
-  </root>
-</configuration>
- - -

- Size and time based archiving -

- -

You may sometimes wish to archive files essentially by date but - at the same time limit the size of each log file, in particular if - post-processing tools impose size limits on the log files. In - order to address this requirement, logback ships with a - sub-component for TimeBasedRollingPolicy called - SizeAndTimeBasedFNATP, where FNATP stands for File - Naming And Triggering Policy.

- - - - Example 4.: Sample configuration for - SizeAndTimeBasedFNATP - (logback-examples/src/main/java/chapter4/conf/logback-sizeAndTime.xml) -
<configuration>
- <appender name="ROLLING"
-    class="ch.qos.logback.core.rolling.RollingFileAppender">
-    <File>mylog.txt</File>
-    <rollingPolicy
-      class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-      <FileNamePattern>
-        mylog-%d{yyyy-MM-dd_HH_mm_ss}.%i.txt
-      </FileNamePattern>
-      <TimeBasedFileNamingAndTriggeringPolicy
-            class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
-        <MaxFileSize>${sizeThreshold}</MaxFileSize>
-      </TimeBasedFileNamingAndTriggeringPolicy>
-    </rollingPolicy>
-    <layout>
-      <Pattern>%msg%n</Pattern>
-    </layout>
-  </appender>
-
-
-  <root level="debug">
-    <appender-ref ref="ROLLING" />
-  </root>
-
-</configuration>
- -

Note the "%i" conversion token in addition to "%d{}". Each time - the current log file reaches MaxFileSize before the - current time period end, it will be archived with an increasing - index, starting at 0.

- -

Size and time based archiving supports cleaning of old archive - files. You just need to specify the number of periods to preserve - with the <MaxHistory> element. When your - application is stopped and restarted, logging will continue at the - correct location, i.e. at the largest index number for the current - period. -

- -

- Triggering policy interface -

- -

TriggeringPolicy - implementations are responsible for instructing the - RollingFileAppender when to rollover.

- -

The TriggeringPolicy interface contains only one - method.

- -
package ch.qos.logback.core.rolling;
-
-import java.io.File;
-import ch.qos.logback.core.spi.LifeCycle;
-
-public interface TriggeringPolicy<E> extends LifeCycle {
-
-  public boolean isTriggeringEvent(final File activeFile, final <E> event);
-}
- -

The isTriggeringEvent() method takes as parameters - the active file, and the logging event currently being - processed. The concrete implementation determines whether the - rollover should occur or not, based on the said parameters. -

- - -

SizeBasedTriggeringPolicy

- -

- SizeBasedTriggeringPolicy looks at size of the - currently active file. If it grows larger than the specified size, - the FileAppender using the - SizeBasedTriggeringPolicy will proceed to the - rollover of the existing active file and create a new one. -

- -

This TriggeringPolicy accepts only one parameter, - namely MaxFileSize, with a default - value of 10 MB. -

- -

The MaxFileSize option can be - specified in bytes, kilobytes, megabytes or gigabytes by suffixing - a numeric value with KB, MB and respectively - GB. For example, 5000000, 5000KB, - 5MB and 2GB are all valid values, with the first - three being also equivalent. -

- -

Here is a sample configuration with a - RollingFileAppender in conjunction with - SizeBasedTriggeringPolicy. -

- - Example 4.: Sample configuration of a RollingFileAppender using a - SizeBasedTriggeringPolicy (logback-examples/src/main/java/chapter4/conf/logback-RollingSizeBased.xml) -
<configuration>
-  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
-    <File>testFile.log</File>
-    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
-      <FileNamePattern>testFile.%i.log.zip</FileNamePattern>
-      <MinIndex>1</MinIndex>
-      <MaxIndex>3</MaxIndex>
-    </rollingPolicy>
-
-    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
-      <MaxFileSize>5MB</MaxFileSize>
-    </triggeringPolicy>
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
-    </layout>
-  </appender>
-	
-  <root level="debug">
-    <appender-ref ref="FILE" />
-  </root>
-</configuration>
- - - - -

Logback Classic

- - -

While logging events are generic in logback-core, within - logback-classic they are always instances of - ILoggingEvent. Logback-classic is nothing more than a - specialized processing pipeline handling instances of - ILoggingEvent. - -

- -

- SocketAppender -

- -

The appenders covered this far were only able to log on local - resources. In contrast, the - SocketAppender is designed to log to a remote - entity by transmitting serialized ILoggingEvent - instances over the wire. The actual type of the serialized event - is LoggingEventVO - which implements the ILoggingEvent - interface. Nevertheless, remote logging is non-intrusive as far as - the logging event is concerned. On the receiving end after - deserialization, the event can be logged as if it were generated - locally. Multiple SocketAppender instances running on - different machines can direct their logging output to a central - log server whose format is fixed. SocketAppender - does not admit an associated layout because it sends serialized - events to a remote server. SocketAppender operates - above the Transmission Control Protocol (TCP) layer which - provides a reliable, sequenced, flow-controlled end-to-end octet - stream. Consequently, if the remote server is reachable, then log - events will eventually arrive there. Otherwise, if the remote - server is down or unreachable, the logging events will simply be - dropped. If and when the server comes back up, then event - transmission will be resumed transparently. This transparent - reconnection is performed by a connector thread which periodically - attempts to connect to the server. -

- -

Logging events are automatically buffered by the native TCP - implementation. This means that if the link to server is slow but - still faster than the rate of event production by the client, the - client will not be affected by the slow network - connection. However, if the network connection is slower than the - rate of event production, then the client can only progress at the - network rate. In particular, in the extreme case where the network - link to the server is down, the client will be eventually blocked. - Alternatively, if the network link is up, but the server is down, - the client will not be blocked, although the log events will be - lost due to server unavailability. -

- -

Even if a SocketAppender is no longer attached to - any logger, it will not be garbage collected in the presence of a - connector thread. A connector thread exists only if the - connection to the server is down. To avoid this garbage - collection problem, you should close the - SocketAppender explicitly. Long lived applications - which create/destroy many SocketAppender instances - should be aware of this garbage collection problem. Most other - applications can safely ignore it. If the JVM hosting the - SocketAppender exits before the - SocketAppender is closed, either explicitly or - subsequent to garbage collection, then there might be - untransmitted data in the pipe which may be lost. This is a common - problem on Windows based systems. To avoid lost data, it is - usually sufficient to close() the - SocketAppender either explicitly or by calling the - LoggerContext's stop() - method before exiting the application. -

- -

The remote server is identified by the RemoteHost and Port properties. - SocketAppender properties are listed in the following - table. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
Property NameTypeDescription
IncludeCallerDataboolean -

- The IncludeCallerData option takes a boolean value. - If true, the caller data will be available to the remote host. - By default no caller data is sent to the server. -

-
Portint -

- The port number of the remote server. -

-
ReconnectionDelayint - The ReconnectionDelay option takes a - positive integer representing the number of milliseconds to wait between - each failed connection attempt to the server. - The default value of this option is 30'000 which corresponds to 30 seconds. - Setting this option to zero turns off reconnection capability. - Note that in case of successful connection to the server, there will be no - connector thread present. -
RemoteHostString - The host name of the server. -
- -

The standard logback distribution includes a simple log server - application named - ch.qos.logback.classic.net.SimpleSocketServer that - can service multiple SocketAppender clients. It waits - for logging events from SocketAppender clients. After - reception by SimpleSocketServer, the events are - logged according to local server policy. The - SimpleSocketServer application takes two parameters: - port and configFile; where port is the port to listen on and - configFile is a configuration script in XML format. -

- -

- Assuming you are in the logback-examples/ directory, - start SimpleSocketServer with the following command: -

- -

java ch.qos.logback.classic.net.SimpleSocketServer 6000 \ - src/main/java/chapter4/socket/server1.xml

- -

where 6000 is the port number to listen on and - server1.xml is a configuration script that adds a - ConsoleAppender and a - RollingFileAppender to the root logger. After you - have started SimpleSocketServer, you can send it log - events from multiple clients using SocketAppender. - The examples associated with this manual include two such clients: - chapter4.SocketClient1 and - chapter4.SocketClient2 Both clients wait for the user - to type a line of text on the console. The text is encapsulated - in a logging event of level debug and then sent to the remote - server. The two clients differ in the configuration of the - SocketAppender. SocketClient1 configures - the appender programmatically while SocketClient2 - requires a configuration file. -

- -

Assuming SimpleSocketServer is running on the - local host, you connect to it with the following command: -

- -

java chapter4.socket.SocketClient1 localhost 6000

- -

Each line that you type should appear on the console of the - SimpleSocketServer launched in the previous step. If - you stop and restart the SimpleSocketServer the - client will transparently reconnect to the new server instance, - although the events generated while disconnected will be simply - (and irrevocably) lost. -

- -

- Unlike - SocketClient1, the sample application - SocketClient2 does not configure logback by itself. - It requires a configuration file in XML format. - The configuration file client1.xml - shown below creates a SocketAppender - and attaches it to the root logger. -

- - Example 4.: SocketAppender configuration (logback-examples/src/main/java/chapter4/socket/client1.xml) -
<configuration>
-	  
-  <appender name="SOCKET" class="ch.qos.logback.classic.net.SocketAppender">
-    <RemoteHost>${host}</RemoteHost>
-    <Port>${port}</Port>
-    <ReconnectionDelay>10000</ReconnectionDelay>
-    <IncludeCallerData>${includeCallerData}</IncludeCallerData>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="SOCKET" />
-  </root>  
-
-</configuration>
- - -

- Note that in the above configuration scripts the values for the - RemoteHost, Port and - IncludeCallerData properties - are not given directly but as substituted variable keys. The values for the variables - can be specified as system properties: -

- -

java -Dhost=localhost -Dport=6000 -DincludeCallerData=false \ - chapter4.socket.SocketClient2 src/main/java/chapter4/socket/client1.xml

- -

This command should give similar results to the previous - SocketClient1 - example. -

- -

Allow us to repeat for emphasis that serialization of logging - events is not intrusive. A deserialized event carries the same - information as any other logging event. It can be manipulated as - if it were generated locally; except that serialized logging - events by default do not include caller data. Here is an example - to illustrate the point. First, start - SimpleSocketServer with the following command: -

- -

java ch.qos.logback.classic.net.SimpleSocketServer 6000 \ - src/main/java/chapter4/socket/server2.xml

- -

The configuration file server2.xml creates a - ConsoleAppender whose layout outputs the caller's file - name and line number along with other information. If you run - SocketClient2 with the configuration file - client1.xml as previously, you will notice that the output - on the server side will contain two question marks between - parentheses instead of the file name and the line number of the - caller: -

- -

2006-11-06 17:37:30,968 DEBUG [Thread-0] [?:?] chapter4.socket.SocketClient2 - Hi

- -

- The outcome can be easily changed by instructing the SocketAppender - to include caller data by setting the IncludeCallerData - option to true. Using the following command will do the trick: -

- -
java -Dhost=localhost -Dport=6000 -DincludeCallerData=true \
-  chapter4.socket.SocketClient2 src/main/java/chapter4/socket/client1.xml
-
- -

- As deserialized events can be handled in the same way as locally - generated events, they even can be sent to a second server for further treatment. - As an exercise, you may wish to setup two servers where the first server - tunnels the events it receives from its clients to a second server. -

- - -

JMSAppenderBase

- -

- The - JMSAppenderBase subclasses conceptually accomplish - the same task as the SocketAppender but as the name - suggests it is based on the JMS API instead of TCP sockets. - JMS or the Java Message Service API - provides an abstraction for Message-Oriented Middleware (MOM) products. - One of the key architectural concepts in JMS is the decoupling of message - producers and message consumers. Senders do not have to wait for receivers - to handle messages and conversely the receiver consumes messages as they - become available; messages are said to be delivered asynchronously. Just as - importantly, consumers as well as producers can be added or removed at will - to a JMS channel. The set of the message producers and message consumers can - vary independently and transparently over time, with both sets oblivious - to each other. -

- -

The JMS specification provides for two types of messaging - models, publish-and-subscribe and point-to-point queueing. Logback - supports the former model with JMSTopicAppender and - the latter with JMSQueueAppender Both appenders - extend the JMSAppenderBase class and publish - serialized events to a topic or queue specified by the user. -

- -

One or more JMSTopicSink or - JMSQueueSink applications can register with a JMS - server and consume the serialized events. The consumers of events - generated by JMS appenders need not only be - JMSTopicSink or JMSQueueSink - applications. Any application or MessageDrivenBean capable of - subscribing to the appropriate topic or queue and consuming - serialized logging event messages would be suitable. Additional - consumers could be quickly built based on the - JMSTopicSink or JMSQueueSink model. -

- -

- Here are JMSAppenderBase's properties: -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Property NameTypeDescription
InitialContextFactoryNameString -

- The class name of the initial JNDI context factory. There is no need - to set this option if you have a properly configured jndi.properties - file or if JMSAppenderBase subclass is running - within an application server. -

-

- If you set this option, you should - also set the ProviderURL option. -

-
ProviderURLString -

- This option specifies configuration information for the - JNDI service provider. The value of the property should contain a - URL string (e.g. ldap://somehost:389). -

-

- The ProviderURL option is taken into - account only if the InitialContextFactoryName - option is specified. It is ignored otherwise. -

-
URLPkgPrefixesString -

- This option contains the list of package prefixes to - use when loading in URL context factories. The value of the - property should be a colon-separated list of package - prefixes for the class name of the URL context factory class. -

-

- For JBoss the value of this option should be: - org.jboss.naming:org.jnp.interfaces - This option is not needed under Weblogic. -

-

- This option is taken into account only if the - InitialContextFactoryName - option is specified. It is ignored otherwise. -

-
SecurityPrincipalNameString -

- The security principal name to use when accessing the JNDI namespace. - This option is usually not required. -

-

- This option is taken into account only if the - InitialContextFactoryName - option is specified. It is ignored otherwise. -

-
- - SecurityCredentials - - - String - -

- The security credentials to use when accessing the - JNDI namespace. This option is usually not required. -

-

- This option is taken into account only if the - - InitialContextFactoryName - - option is specified. It is ignored otherwise. -

-
- - UserName - - - String - -

- The username to use when creating a topic or queue connection. -

-
- - Password - - - String - -

- The password to use when creating a topic or queue connection. -

-
- -

- JMS topics, queues and connection factories are administered objects that are obtained - using the JNDI API. This in turn implies the necessity of retrieving a JNDI Context. - There are two common methods for obtaining a JNDI Context. If a file resource named - jndi.properties is available to the JNDI API, it will use the information - found therein to retrieve an initial JNDI context. - To obtain an initial context, one simply calls: -

- -
InitialContext jndiContext = new InitialContext();
- -

- Calling the no-argument InitialContext() constructor will also work - from within Enterprise Java Beans (EJBs). - Indeed, it is part of the EJB contract for application servers to provide - each enterprise bean an environment naming context (ENC). -

- -

- In the second approach, several predetermined properties are specified. - These properties are passed to the InitialContext constructor - to connect to the naming service provider. - For example, to connect to an - ActiveMQ - naming server one would write: -

- -
Properties env = new Properties();
-env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
-env.put(Context.PROVIDER_URL, "tcp://hostname:61616");
-Context ctx = new InitialContext(env);
- -

- where hostname is the host where the ActiveMQ server is running. -

- -

- Other JNDI providers will obviously require different values. - As mentioned previously, the initial JNDI context can be obtained by calling - the no-argument InitialContext() constructor from within EJBs. - Only clients running in a separate JVM need to be concerned about - the jndi.properties file or setting the different properties - before calling InitialContext constructor taking a - Properties (i.e. Hashtable) parameter. -

- -

Comments on JMS appenders

- -

Transmitting a packet of information using JMS is certain to be - substantially slower than sending the same packet using raw TCP - sockets. JMS vendors bragging about the performance of their - messaging platform tend to omit this simple fact. Guaranteed - store and forward messaging comes at a hefty price. In return for - increased cost, JMS messaging provides decoupling of sender and - receiver. As long as the JMS provider is reachable, messages will - eventually arrive at the destination. However, what if the JMS - server is down or simply unreachable? -

- -

According to the JMS specification, producers can mark a - message as either persistent or non-persistent. The persistent - delivery mode instructs the JMS provider to log the message to - stable storage as part of the client's send operation, allowing - the message to survive provider crashes. JMS appenders do not set - the delivery mode of messages they produce because according to - the JMS specification, the delivery mode is considered as an - administered property. -

- -

Once a message reaches the JMS provider, the provider assumes - the responsibility of delivering it to its destination, relieving - the client from this chore. What if the JMS server is - unreachable? The JMS API provides an - ExceptionListener interface to deal with this - situation. When the client runtime of the JMS provider detects a - lost connection to the JMS server, it calls the - onException() method of the registered - ExceptionListener. Once notified of the problem, - client code can attempt to reestablish the connection. According - to the section 4.3.8 of the JMS specification, the provider should - attempt to resolve connection problems prior to notifying the - client. The JMS appenders do not implement the - ExceptionListener interface. -

- - -

JMSTopicAppender

- -

- The - JMSTopicAppender acts as a message producer to a publish and subscribe - Topic. -

- -

- Its most important method, doAppend() is listed below: -

- -
public void append(ILoggingEvent event) {
-  if (!isStarted()) {
-    return;
-  }
-
-  try {
-    ObjectMessage msg = topicSession.createObjectMessage();
-    Serializable so = pst.transform(event);
-    msg.setObject(event);
-    topicPublisher.publish(msg);
-    successiveFailureCount = 0;
-  } catch (Exception e) {
-    successiveFailureCount++;
-    if (successiveFailureCount > SUCCESSIVE_FAILURE_LIMIT) {
-      stop();
-    }
-      addError("Could not publish message in JMSTopicAppender [" + name + "].", e);
-  }
-}
- -

- The isStarted() method allows the appender to check - whether prerequisite conditions for its proper functioning, in - particular the availability of a valid and open - TopicConnection and a TopicSession, - are fulfilled. If that is not the case, the append method - returns without performing any work. If the prerequisite - conditions are fulfilled, then the method proceeds to publish - the logging event. This is done by obtaining a - javax.jms.ObjectMessage from the - TopicSession and then setting its payload to the - logging event received as the input parameter. Once the payload - of the message is set, it is published. Note that the - ILoggingEvent is transformed to a serializable - object by a PreSerializationTransformer. Only - Serializable objects can be transported within an - ObjectMessage. -

- -

- In summary, the JMSTopicAppender broadcasts messages consisting - of a serialized LoggingEvent payload over a user-specified - JMS topic. These events can be processed by a - - JMSTopicSink - or a similar consumer. According to JMS specification, the provider - will asynchronously call the onMessage() of duly registered - and subscribed javax.jms.MessageListener objects. - The onMessage() method in JMSTopicSink - is implemented as follows: -

- -
public void onMessage(javax.jms.Message message) {
-  ILoggingEvent event;
-  try {
-    if (message instanceof ObjectMessage) {
-      ObjectMessage objectMessage = (ObjectMessage) message;
-      event = (ILoggingEvent) objectMessage.getObject();
-      Logger log = (Logger) LoggerFactory.getLogger(event.getLoggerName());
-      log.callAppenders(event);
-    } else {
-      logger.warn("Received message is of type " + message.getJMSType()
-          + ", was expecting ObjectMessage.");
-    }
-  } catch (JMSException jmse) {
-    logger.error("Exception thrown while processing incoming message.", jmse);
-  }
-}
- -

- The onMessage() method begins by retrieving the logging event's payload. - It then obtains a Logger with the same name as the logger name of the incoming event. - The event is then logged through this logger as if it were generated locally, - by calling its callAppenders() method. The SocketNode class used by - SimpleSocketServer handles incoming logging events essentially in the same way. -

- -

- Some properties are proper to JMSTopicAppender. They are - listed below. -

- - - - - - - - - - - - - - - - - -
Property NameTypeDescription
TopicConnectionFactoryBindingNameString -

- The name of the topic factory. There is no default value for this mandatory option. -

-
TopicBindingNameString -

- The name of the topic to use. There is no default value for this mandatory option. -

-
- -

- JMSTopicAppender is rather straightforward to configure: -

- - Example 4.: JMSTopicAppender configuration (logback-examples/src/main/java/chapter4/conf/logback-JMSTopic.xml) -
<configuration>
-
-  <appender name="Topic"
-    class="ch.qos.logback.classic.net.JMSTopicAppender">
-    <InitialContextFactoryName>
-      org.apache.activemq.jndi.ActiveMQInitialContextFactory
-    </InitialContextFactoryName>
-    <ProviderURL>tcp://localhost:61616</ProviderURL>
-    <TopicConnectionFactoryBindingName>
-      ConnectionFactory
-    </TopicConnectionFactoryBindingName>
-    <TopicBindingName>MyTopic</TopicBindingName>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="Topic" />
-  </root>
-</configuration>
- - -

JMSQueueAppender

- -

- The - JMSQueueAppender acts as a message producer to a point-to-point - Queue. -

- -

- It works in a very similar manner to the JMSTopicAppender. -

- -

- Some properties are proper to JMSQueueAppender. They are - listed below. -

- - - - - - - - - - - - - - - - - -
Property NameTypeDescription
QueueConnectionFactoryBindingNameString -

- The name of the queue factory. There is no default value for this mandatory option. -

-
QueueBindingNameString -

- The name of the queue to use. There is no default value for this mandatory option. -

-
- -

- A typical JMSQueueAppender configuration file looks very - similar to that of a JMSTopicAppender. -

- Example 4.: JMSQueueAppender configuration (logback-examples/src/main/java/chapter4/conf/logback-JMSQueue.xml) -
<configuration>
-
-  <appender name="Queue"
-    class="ch.qos.logback.classic.net.JMSQueueAppender">
-    <InitialContextFactoryName>
-      org.apache.activemq.jndi.ActiveMQInitialContextFactory
-    </InitialContextFactoryName>
-    <ProviderURL>tcp://localhost:61616</ProviderURL>
-    <QueueConnectionFactoryBindingName>
-      ConnectionFactory
-    </QueueConnectionFactoryBindingName>
-    <QueueBindingName>MyQueue</QueueBindingName>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="Queue" />
-  </root>
-</configuration>
- -

SMTPAppender

- -

The SMTPAppender - accumulates logging events in a fixed-size buffer and sends them in - an email after a user-specified event occurs. By default, the - email transmission is triggered by a logging event of level ERROR - or higher. -

- -

The various properties for SMTPAppender are - summarized in the following table. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Property NameTypeDescription
SMTPHostStringThe host name of the SMTP server. This parameter is mandatory.
SMTPPortintThe port where the SMTP server is listening. Defaults to - 25.
ToStringThe email address of the recipient. Multiple recipients - can be specified by using several <To> elements.
FromStringThe stated originator of the email messages sent by - SMTPAppender. -
SubjectString -

The subject of the email. It can be any value accepted as - a valid conversion pattern by PatternLayout. Layouts - will be discussed in the next chapter. -

- -

The outgoing email message will have a subject line - corresponding to applying the pattern on the logging event - that triggered the email message. -

- -

Assuming the Subject option - is set to "Log: %logger - %msg" and the triggering event's - logger is named "com.foo.Bar", and contains the message - "Hello world", then the outgoing email will have the subject - line "Log: com.foo.Bar - Hello World". -

- -

By default, this option is set to "%logger{20} - %m".

-
BufferSizeint - The BufferSize option takes a - positive integer representing the maximum number of logging - events to collect in a cyclic buffer. When the BufferSize is reached, oldest events - are deleted as new events are added to the buffer. The - default size of the cyclic buffer is 512. -
EvaluatorString -

This option is declared by creating a new - <EventEvaluator/> element. The name of the - class that the user wishes to use as the - SMTPAppender's Evaluator can needs - to be specified via the class - attribute. -

- - -

In the absence of this option, SMTPAppender - is assigned an OnErrorEveluator - instance which triggers email transmission when it - encounters an event of level ERROR or higher. -

- - - -

You can find more information on event evaluators further - down this document. -

- -
UsernameString The username value to use - during plain user/password authentication. By default, this - parameter is null.
PasswordString The password value to use for - plain user/password authentication. By default, this parameter - is null.
STARTTLSboolean If this parameter is set to - true, then this appender will issue the STARTTLS command (if - the server supports it) causing the connection to switch to - SSL. Note that the connection is initially non-encrypted. By - default, this parameter is set to false.
SSLboolean If this parameter is set to - true, then this appender will open an SSL connection to the - server. By default, this parameter is set to false.
CharsetEncodingStringThe outgoing email message will be encoded in the - designated charset. The - default charset encoding is "UTF-8" which works well for most - purposes. -
- -

The SMTPAppender keeps only the last BufferSize logging events in its cyclic - buffer, throwing away older events when its buffer becomes full. - Thus, the number of logging events delivered in any e-mail sent by - SMTPAppender is upper-bounded by BufferSize. This keeps memory requirements - bounded while still delivering a reasonable amount of application - context. -

- -

The SMTPAppender relies on the JavaMail API. It - has been tested with JavaMail API version 1.4. The JavaMail API - requires the JavaBeans Activation Framework package. You can - download the JavaMail API and - the Java-Beans - Activation Framework from their respective websites. Make - sure to place these two jar files in the classpath before trying - the following examples. -

- - -

A sample application, chapter4.mail.EMail - generates a number of log messages messages followed by a single - error message. It takes two parameters. The first parameter is an - integer corresponding to the number of logging events to - generate. The second parameter is the logback configuration - file. The last logging event generated by EMail - application, an ERROR, will trigger the transmission of an email - message. -

- -

Here is a sample configuration file intended for the - Email application: -

- - Example 4.: A sample SMTPAppender configuration (logback-examples/src/main/java/chapter4/mail/mail1.xml) -
<configuration>	  
-  <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
-    <SMTPHost>ADDRESS-OF-YOUR-SMTP-HOST</SMTPHost>
-    <To>EMAIL-DESTINATION</To>
-    <To>ANOTHER_EMAIL_DESTINATION</To> <!-- additional destinations are possible -->
-    <From>SENDER-EMAIL</From>
-    <Subject>TESTING: %logger{20} - %m</Subject>
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%date %-5level %logger{35} - %message%n</Pattern>
-    </layout>	    
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="EMAIL" />
-  </root>  
-</configuration>
- -

Before trying out chapter4.mail.Email application - with the above configuration file, you must set the SMTPHost, To and - From properties to values appropriate for - your environment. Once you have set the correct values in the - configuration file, execute the following command: -

- -
java chapter4.mail.EMail 300 src/main/java/chapter4/mail/mail.xml
- -

The recipient you specified should receive an email message - containing 300 logging events formatted by - PatternLayout The figure below is the resulting email - message as shown by Mozilla Thunderbird. -

- -

resulting email

- -

In the next example configuration file mail2.xml, the - values for the SMTPHost, To and From - properties are determined by variable substitution. Here is the - relevant part of mail2.xml. -

- -
<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
-  <SMTPHost>${smtpHost}</SMTPHost>
-  <To>${to}</To>
-  <From>${from}</From>
-  <layout class="ch.qos.logback.classic.html.HTMLLayout"/>
-</appender>
- -

You can pass the required parameters on the command line:

- -
java -Dfrom=source@xyz.com -Dto=recipient@xyz.com -DsmtpHost=some_smtp_host \
-  src/main/java/chapter4.mail.EMail 10000 chapter4/mail/mail2.xml
-
- -

Be sure to replace with values as appropriate for your - environment. -

- -

Note that in this latest example, PatternLayout - was replaced by HTMLLayout which formats logs as an - HTML table. You can change the list and order of columns as well - as the CSS of the table. Please refer to HTMLLayout documentation - for further details. -

- -

Given that the default size of the cyclic buffer is 512, the - recipient should see an email message containing 512 events - conveniently formatted in an HTML table. Note that this run of the - chapter4.mail.Email application generated 10'000 - events of which only the last 512 were included in the outgoing - email. -

- -

2nd email

- -

Email clients such as Mozilla Thunderbird, Eudora or MS - Outlook, offer reasonably good CSS support for HTML email. - However, they sometimes automatically downgrade HTML to - plaintext. For example, to view HTML email in Thunderbird, the - "View→Message Body As→Original HTML" option - must be set. Yahoo!Mail's support for HTML email, in particular - its CSS support is very good. GMail on the other hand, while it - honors the basic HTML table structure, ignores the internal CSS - formatting. Gmail supports inline CSS formatitng but since inline - CSS would make the resulting output too voluminous, - HTMLLayout does not use inline CSS. -

- -

Triggering event

- -

By default, the SMTPAppender will initiate the - transmission of an email message as a response to an event of - level ERROR or higher. However, it is possible to - override this default behavior by providing a custom - implementation of the EventEvaluator interface. -

- -

The SMTPAppender submits each incoming event to - its evaluator by calling evaluate() method in order - to check whether the event should trigger an email or just be - placed in the cyclic buffer. When the evaluator gives a positive - answer to its evaluation, an email is sent. The - SMTPAppender contains one and only one evaluator - object. This object may possess its own state. For illustrative - purposes, the CounterBasedEvaluator class listed - next, implements an event evaluator whereby every 1024th event - triggers an email message. -

- -Example 4.: A EventEvaluator implementation -that evaluates to true every 1024th event (logback-examples/src/main/java/chapter4/mail/CounterBasedEvaluator.java) -
package chapter4.mail;
-
-import ch.qos.logback.core.boolex.EvaluationException;
-import ch.qos.logback.core.boolex.EventEvaluator;
-import ch.qos.logback.core.spi.ContextAwareBase;
-
-public class CounterBasedEvaluator extends ContextAwareBase implements EventEvaluator {
-
-  static int LIMIT = 1024;
-  int counter = 0;
-  String name;
-
-  public boolean evaluate(Object event) throws NullPointerException,
-      EvaluationException {
-    counter++;
-
-    if (counter == LIMIT) {
-      counter = 0;
-
-      return true;
-    } else {
-      return false;
-    }
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public void setName(String name) {
-    this.name = name;
-  }
-}
- -

- Note that this implementation extends ContextAwareBase and - implements EventEvaluator. This allows the user to concentrate - on the core functions of her EventEvaluator and let the base class - provide the common functionality. -

- -

- Setting the EventEvaluator option of - SMTPAppender instructs it to use a custom evaluator. - The next configuration file attaches a SMTPAppender to the root logger. - This appender has a buffer size of 2048 and uses a CounterBasedEvaluator instance - as its event evaluator. -

- -Example 4.: SMTPAppender with custom -Evaluator and buffer size (logback-examples/src/main/java/chapter4/mail/mail3.xml) - -
<configuration>
-  <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
-    <Evaluator class="chapter4.mail.CounterBasedEvaluator" />
-    <BufferSize>1050</BufferSize>
-    <SMTPHost>${smtpHost}</SMTPHost>
-    <To>${to}</To>
-    <From>${from}</From>
-    <layout class="ch.qos.logback.classic.html.HTMLLayout"/>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="EMAIL" />
-  </root>  
-</configuration>
- - -

Authentication/STARTTLS/SSL

- -

SMTPAppender supports authentication via plain - user passwords as well as both the STARTTLS and SSL - protocols. Note that STARTTLS differs from SSL in that, in - STARTTLS, the connection is initially non-encrypted and only after - the STARTTLS command is issued by the client (if the server - supports it) does the connection switch to SSL. In SSL mode, the - connection is encrypted right from the start. -

- -

SMTPAppender configuration - for Gmail (SSL)

- -

The next example shows you how to configure - SMTPAppender for Gmail with the SSL protocol.

- - Example 4.: SMTPAppender to Gmail using SSL (logback-examples/src/main/java/chapter4/mail/gmailSSL.xml) - -
<configuration>
-  <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
-    <SMTPHost>smtp.gmail.com</SMTPHost>
-    <SMTPPort>465</SMTPPort>
-    <SSL>true</SSL>
-    <Username>YOUR_USERNAME@gmail.com</Username>
-    <Password>YOUR_GMAIL_PASSWORD</Password>
-
-    <To>EMAIL-DESTINATION</To>
-    <To>ANOTHER_EMAIL_DESTINATION</To> <!-- additional destinations are possible -->
-    <From>YOUR_USERNAME@gmail.com</From>
-    <Subject>TESTING: %logger{20} - %m</Subject>
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%date %-5level %logger{35} - %message%n</Pattern>
-    </layout>	    
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="EMAIL" />
-  </root>  
-</configuration>
- - -

SMTPAppender for Gmail - (STARTTLS)

- -

The next example shows you how to configure - SMTPAppender for Gmail for the STARTTLS protocol.

- - Example 4.: SMTPAppender to GMAIL using STARTTLS (logback-examples/src/main/java/chapter4/mail/gmailSTARTTLS.xml) - -
<configuration>	  
-  <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
-    <SMTPHost>smtp.gmail.com</SMTPHost>
-    <SMTPPort>587</SMTPPort>
-    <STARTTLS>true</STARTTLS>
-    <Username>YOUR_USERNAME@gmail.com</Username>
-    <Password>YOUR_GMAIL_xPASSWORD</Password>
-    
-    <To>EMAIL-DESTINATION</To>
-    <To>ANOTHER_EMAIL_DESTINATION</To> <!-- additional destinations are possible -->
-    <From>YOUR_USERNAME@gmail.com</From>
-    <Subject>TESTING: %logger{20} - %m</Subject>
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%date %-5level %logger - %message%n</Pattern>
-    </layout>	    
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="EMAIL" />
-  </root>  
-</configuration>
- - - -

- DBAppender -

- -

The DBAppender - inserts logging events into three database tables in a format - independent of the Java programming language. -

- -

These three tables are logging_event, - logging_event_property and - logging_event_exception. They must exist before - DBAppender can be used. Logback ships with SQL - scripts that will create the tables. They can be found in the - found in the - logback-classic/src/main/java/ch/qos/logback/classic/db/dialect - directory. There is a specific script for each of the most popular - database systems. If the script for your particular type of - database system is missing, it should be quite easy to write one, - taking example on the already existing scripts. If you send them - to us, we will gladly include missing scripts in future releases. -

- -

If your JDBC driver supports the getGeneratedKeys - method introduced in JDBC 3.0 specification, assuming you have - created the appropriate database tables as mentioned above, then - no more steps are required, excluding the usual logback - configuration. -

- -

Otherwise, there must be an SQLDialect appropriate - for your database system. Currently, we have dialects for - PostgreSQL, MySQL, Oracle and MS SQL Server.

- -

The table below summarizes the database types and their support - of the getGeneratedKeys() method. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RDBMStested version(s) - tested JDBC driver version(s) - - supports -
- getGeneratedKeys() - method -
DB2untesteduntestedunknown
HSQL1.8.0.7-NO
Microsoft SQL Server20052.0.1008.2 (sqljdbc.jar)YES
MySQL5.0.225.0.8 (mysql-connector.jar)YES
PostgreSQL - - NO
Oracle10g10.2.0.1 (ojdbc14.jar)YES (10.2.0.1)
- -

Experiments show that writing a single event into the database - takes approximately 10 milliseconds, on a "standard" PC. If pooled - connections are used, this figure drops to around 1 - millisecond. Note that most JDBC drivers already ship with - connection pooling support. -

- -

Configuring logback to use DBAppender can be done - in several different ways, depending on the tools one has to - connect to the database, and the database itself. The key issue in - configuring DBAppender is about setting its - ConnectionSource object, as we shall discover - shortly. -

- -

Once logback is configured properly, the logging events are - sent to the specified database. As stated previously, there are - three tables used by logback to store logging event data. -

- -

- The logging_event table contains the following fields: -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldTypeDescription
timestampbig intThe timestamp that was valid at the logging event's creation.
formatted_messagetextThe message that has been added to the logging event, - after formatting with - org.slf4j.impl.MessageFormatter, in case objects - were passed along with the message.
logger_namevarcharThe name of the logger used to issue the logging request.
level_stringvarcharThe level of the logging event.
reference_flagsmallint -

This field is used by logback to identify logging events - that have an exception or MDCproperty values - associated. -

- -

Its value is computed by - ch.qos.logback.classic.db.DBHelper. A logging - event that contains MDC or Context - properties has a flag number of 1. One that - contains an exception has a flag number of 2. A - logging event that contains both elements has a flag number - of 3. -

-
caller_filenamevarcharThe name of the file where the logging request was issued.
caller_classvarcharThe class where the logging request was issued.
caller_methodvarcharThe name of the method where the logging request was issued.
caller_linecharThe line number where the logging request was issued.
event_idintThe database id of the logging event.
- -

- The logging_event_property is used to store the keys and values - contained in the MDC or the Context. - It contains these fields: -

- - - - - - - - - - - - - - - - - - - - - - -
FieldTypeDescription
event_idintThe database id of the logging event.
mapped_keyvarcharThe key of the MDC property
mapped_valuetextThe value of the MDC property
- -

- The logging_event_exception table contains the following fields: -

- - - - - - - - - - - - - - - - - - - - - - -
FieldTypeDescription
event_idintThe database id of the logging event.
ismallintThe index of the line in the full stack trace.
trace_linevarcharThe corresponding line
- -

- To give a more visual example of the work done by DBAppender, here - is a screenshot of a MySQL database with content provided by DBAppender. -

- -

The logging_event table:

- - Logging Event table - -

The logging_event_exception table:

- - Logging Event Exception table - -

The logging_event_property table:

- - Logging Event Property table - - -

ConnectionSource

- -

The ConnectionSource interface provides a - pluggable means of transparently obtaining JDBC connections for - logback classes that require the use of a - java.sql.Connection. There are currently three - implementations of ConnectionSource, namely - DataSourceConnectionSource, - DriverManagerConnectionSource and - JNDIConnectionSource. -

- -

- The first example that we will review is a configuration using - DriverManagerConnectionSource and a MySQL database. - The following configuration file is what one would need. -

- -Example 4.: DBAppender configuration (logback-examples/src/main/java/chapter4/db/append-toMySQL-with-driverManager.xml) -
<configuration>
-
-  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
-    <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
-      <driverClass>com.mysql.jdbc.Driver</driverClass>
-      <url>jdbc:mysql://host_name:3306/datebase_name</url>
-      <user>username</user>
-      <password>password</password>
-    </connectionSource>
-  </appender>
-  
-  <root level="debug" >
-    <appender-ref ref="DB" />
-  </root>
-</configuration>
- -

- The correct driver must be declared. Here, the com.mysql.jdbc.Driver - class is used. The url must begin with jdbc:myslq://. -

- -

- The - - DriverManagerConnectionSource is an implementation of - ConnectionSource that obtains the connection in the - traditional JDBC manner based on the connection URL. -

-

- Note that this class will establish a new Connection for - each call to getConnection(). It is recommended - that you either use a JDBC driver that natively supports - connection pooling or that you create your own - implementation of ConnectionSource that taps into - whatever pooling mechanism you are already using. (If you - have access to a JNDI implementation that supports - javax.sql.DataSource, e.g. within a J2EE application - server, see JNDIConnectionSource). -

- - -

- Connecting to a database using a DataSource is rather similar. - The configuration now uses - - DataSourceConnectionSource, - which is an implementation of ConnectionSource that obtains the - Connection in the recommended JDBC manner based on a - javax.sql.DataSource. -

- -Example 4.: DBAppender configuration (logback-examples/src/main/java/chapter4/db/append-with-datasource.xml) -
<configuration>
-
-  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
-     <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
-       
-       <dataSource class="${dataSourceClass}">
-       	 <!-- Joran cannot substitute variables
-       	 that are not attribute values. Therefore, we cannot
-       	 declare the next parameter like the others. 
-       	 -->
-         <param name="${url-key:-url}" value="${url_value}"/>
-         <serverName>${serverName}</serverName>
-         <databaseName>${databaseName}</databaseName>
-       </dataSource>
-       
-       <user>${user}</user>
-       <password>${password}</password>
-     </connectionSource>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="DB" />
-  </root>  
-</configuration>
- -

- Not that in this configuration sample, we make heavy use of substitution variables. - They are sometimes handy when connection details have to be centralized in a - single configuration file and shared by logback and other frameworks. -

- - - -

- The third implementation of ConnectionSource that is shipped with - logback is the JNDIConnectionSource. -

- -

- The - - JNDIConnectionSource - is an implementation of ConnectionSource that - obtains a javax.sql.DataSource from a JNDI provider - and uses it to obtain a java.sql.Connection. It is - primarily designed to be used inside of J2EE application - servers or application server clients, assuming the - application server supports remote access of javax.sql.DataSource. - In this way one can take advantage of connection pooling and whatever other goodies the - application server provides. -

- -
<connectionSource class="ch.qos.logback.core.db.JNDIConnectionSource">
-  <param name="jndiLocation" value="jdbc/MySQLDS" />
-  <param name="username" value="myUser" />
-  <param name="password" value="myPassword" />
-</connectionSource>
- -

- Note that this class will obtain an - javax.naming.InitialContext - using the no-argument constructor. This will usually work - when executing within a J2EE environment. When outside the - J2EE environment, make sure that you provide a - jndi.properties - file as described by your JNDI provider's documentation. -

- -

Connection pooling

- -

- Logging events can be created at a rather fast pace. To keep up - with the flow of events that must be inserted into a database, - it is recommended to use connection pooling with - DBAppender. -

- -

- Experiment shows that using connection pooling with DBAppender - gives a big performance boost. With the following - configuration file, logging events are sent to a MySQL database, - without any pooling. -

- - Example 4. DBAppender configuration without pooling (logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource.xml) -
<configuration>
-
-  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
-    <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
-      <dataSource class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
-        <serverName>${serverName}</serverName>
-        <port>${port$</port>
-        <databaseName>${dbName}</databaseName>
-        <user>${user}</user>
-        <password>${pass}</password>
-      </dataSource>
-    </connectionSource>
-  </appender>
-    
-  <root level="debug">
-    <appender-ref ref="DB" />
-  </root>
-</configuration
- -

With this configuration file, sending 500 logging events to a - MySQL database takes a whopping 5 seconds, that is 10 milliseconds - per request. This figure is unacceptable when dealing with large - applications. -

- -

A dedicated external library is necessary to use connection - pooling with DBAppender. The next example uses c3p0. To be able - to use c3p0, one must download it and place - c3p0-VERSION.jar in the classpath. -

- - Example 4.: DBAppender configuration with pooling (logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource-and-pooling.xml) -
<configuration>
-
-  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
-    <connectionSource
-      class="ch.qos.logback.core.db.DataSourceConnectionSource">
-      <dataSource
-        class="com.mchange.v2.c3p0.ComboPooledDataSource">
-        <driverClass>com.mysql.jdbc.Driver</driverClass>
-        <jdbcUrl>jdbc:mysql://${serverName}:${port}/${dbName}</jdbcUrl>
-        <user>${user}</user>
-        <password>${password}</password>
-      </dataSource>
-    </connectionSource>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="DB" />
-  </root>
-</configuration>
- -

With this new configuration, sending 500 logging requests to - the aforementioned MySQL database takes around 0.5 seconds, for an - average of 1 millisecond per request, that is a tenfold - improvement in performance. -

- -

SyslogAppender -

- -

The syslog protocol is a very simple protocol: a syslog sender - sends a small message to a syslog receiver. The receiver is - commonly called syslog daemon or syslog server. - Logback can send messages to a remote syslog daemon. This is - achieved by using SyslogAppender. -

- -

Here are the properties you can pass to a SyslogAppender.

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
Property NameTypeDescription
- - SyslogHost - - - String - - The host name of the syslog server. -
- - Port - - - String - - The port number on the syslog server to connect to. Normally, one would not want - to change the default value, that is 514. -
- - Facility - - - String - -

- The Facility is meant to identify - the source of a message. -

-

- The Facility option must be set one - of the strings KERN, USER, MAIL, DAEMON, AUTH, SYSLOG, LPR, NEWS, UUCP, - CRON, AUTHPRIV, FTP, NTP, AUDIT, ALERT, CLOCK, LOCAL0, LOCAL1, LOCAL2, - LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. Case is not important. -

-
- - SuffixPattern - - - String - -

The SuffixPattern option - specifies the format of the non-standardized part of the - message sent to the syslog server. By default, its value is - [%thread] %logger %msg. Any value that a - PatternLayout could use is a correct SuffixPattern value. -

-
- -

- The syslog severity of a logging event is converted from the level of the logging event. - The DEBUG level is converted to 7, INFO is converted to - 6, WARN is converted to 4 and ERROR is converted - to 3. -

- -

- Since the format of a syslog request follows rather strict rules, there is no layout - to be used with SyslogAppender. However, the using the - SuffixPattern option lets the user display whatever - information she wishes. -

- -

- Here is a sample configuration using a SyslogAppender. -

- -Example 4.: SyslogAppender configuration (logback-examples/src/main/java/chapter4/conf/logback-syslog.xml) -
<configuration>
-
-  <appender name="SYSLOG"
-    class="ch.qos.logback.classic.net.SyslogAppender">
-    <SyslogHost>remote_home</SyslogHost>
-    <Facility>AUTH</Facility>
-    <SuffixPattern>[%thread] %logger %msg</SuffixPattern>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

When testing this configuration, you should verify that the - remote syslog daemon accepts requests from an external - source. Experience shows that, by default, syslog daemons usually - deny requests coming via a network connection. -

- - -

SiftingAppender

- -

As its name implies, a SiftingAppender can be used - to separate (or sift) logging according to a given runtime - attribute. For example, SiftingAppender can separate - logging events according to user sessions, so that the logs - generated by every user go into distinct log files, one log file - per user. For example, SiftingAppender can separate - logging events into distinct log files, one file per user. -

- - -

SiftingAppender embeds and manages multiple - appenders which it builds dynamically depending on discriminating - values. The built appender is specified in a configuration file - within the SiftingAppender definition itself. By - default, SiftingAppender uses MDC key/value pairs as - a discriminator. -

- -

After configuring logback, the SiftExample - application logs a message stating that the application has - started. It then sets the MDC key "userid" to "Alice" and logs a - message. Here is the salient code:

- -

logger.debug("Application started"); -MDC.put("userid", "Alice"); -logger.debug("Alice says hello");

- -

The next configuration file illustrates the use of - SiftingAppender.

- - - Example 4.: SiftingAppender - configuration - (logback-examples/src/main/java/chapter4/sift/byUserid.xml) - -
<configuration>
-
-  <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
-    <!-- in the absence of the class attribute, it is assumed that the
-         desired discriminator type is
-         ch.qos.logback.classic.sift.MDCBasedDiscriminator -->
-    <discriminator>
-      <Key>userid</Key>
-      <DefaultValue>unknown</DefaultValue>
-    </discriminator>
-    <sift>
-      <appender name="FILE-${userid}" class="ch.qos.logback.core.FileAppender">
-        <File>${userid}.log</File>
-        <Append>false</Append>
-        <layout class="ch.qos.logback.classic.PatternLayout">
-          <Pattern>%d [%thread] %level %mdc %logger{35} - %msg%n</Pattern>
-        </layout>
-      </appender>
-    </sift>
-  </appender>
-
-  <root level="DEBUG">
-    <appender-ref ref="SIFT" />
-  </root>
-</configuration>
- - -

In the absence of a class attribute, it is assumed that the - discriminator type is MDCBasedDiscriminator. It - will use the MDC value associated with the Key property as a discriminator. If that - value is null, then the value associated with the DefaultValue property will be used. -

- -

The SiftingAppender is unique in its capacity to - reference and configure nested appenders. In the above example, - within the SiftingAppender there will be nested - FileAppender instances, each instance identified by the value - associated with the "userid" MDC key. Whenever the "userid" MDC - key is assigned a new value, a new FileAppender - instance will be built from scratch. The SiftingAppender keeps - track of the appenders it creates. Appenders unused for 30 minutes - will be automatically closed and discarded. -

- -

It is not enough to have different appender instances; each - instance must output to a distinct target resource. To allow such - differentiation, within the nested appender (FileAppender above), - the key passed to the discriminator, "userid" in the above - example, becomes a variable. Consequently, - this variable can be used to differentiate the actual resource - used by a given nested appender. -

- -

Running the SiftExample application with the - "byUserid.xml" configuration file shown above, will result in two - distinct log files, "unknown.log" and "Alice.log". -

- - -

Writing your own Appender

- - -

You can easily write your appender by subclassing - AppenderBase. It handles support for filters, status - messages and other functionality shared by most appenders. The - derived class only needs to implement one method, namely - append(Object eventObject). -

- -

The CountingConsoleAppender, which we list next, - appends a limited number of incoming events on the console. It - shuts down after the limit is reached. It uses a - Layout to format the events and accepts a parameter. - Thus, a few more methods are needed. -

- - Example 4.: - CountingConsoleAppender - (logback-examples/src/main/java/chapter4/CountingConsoleAppender.java) -
package chapter4;
-
-import ch.qos.logback.core.AppenderBase;
-import ch.qos.logback.core.Layout;
-
-
-public class CountingConsoleAppender extends AppenderBase<ILoggingEvent> {
-  static int DEFAULT_LIMIT = 16;
-  int counter = 0;
-  int limit = DEFAULT_LIMIT;
-
-  public CountingConsoleAppender() {
-  }
-
-  public void setLimit(int limit) {
-    this.limit = limit;
-  }
-
-  public int getLimit() {
-    return limit;
-  }  
-  
-  @Override
-  public void start() {
-    if (this.layout == null) {
-      addError("No layout set for the appender named ["+ name +"].");
-      return;
-    }
-    
-    super.start();
-  }
-
-  public void append(ILoggingEvent event) {
-
-    if (counter >= limit) {
-      return;
-    }
-
-    // output the events as formatted by our layout
-    System.out.print(this.layout.doLayout(event));
-
-    // prepare for next event
-    counter++;
-  }
-
-}
- -

The start() method checks for the presence of a - Layout. In case the layout is not set, the appender - fails to start with an error message. -

- -

This custom appender illustrates two points:

- -
    - -
  • All properties that follow the setter/getter JavaBeans - conventions are handled transparently. The start() - method, which is called automatically during logback - configuration, has the responsibility of verifying that the - various properties of the appender are coherent. -
  • - -
  • The AppenderBase.doAppend() method invokes the - append() method of its derived classes. Actual output - operations occur in the append() method. In - particular, it is in this method that appenders format events by - invoking their layouts. -
  • -
- -

The CountingConsoleAppender - can be configured like any other appender. See sample - configuration file - logback-examples/src/main/java/chapter4/countingConsole.xml - for an example. -

- - -

Logback - Access

- -

Most of the appenders found in logback-classic have their - equivalent in logback-access. These work essentially in the same - way as their logback-classic counterparts. In the next section, we - will cover their use. -

- - -

SocketAppender

- -

The - SocketAppender is designed to log to a remote - entity by transmitting serialized AccessEvent objects - over the wire. Remote logging is non-intrusive as far as the - access event is concerned. On the receiving end after - deserialization, the event can be logged as if it were generated - locally. -

-

- The properties of access' SocketAppender are the same as those available - for classic's SocketAppender. -

- - -

SMTPAppender

- -

- Access' - SMTPAppender works in the same way as its Classic counterpart. - However, the evaluator option is rather different. - By default, a URLEvaluator object - is used by SMTPAppender. This evaluator contains a list of URLs that are - checked against the current request's URL. When one of the pages given to the - URLEvaluator is requested, SMTPAppender sends an email. -

- -

- Here is a sample configuration of a SMTPAppender in the access environment. -

-Example 4.: SMTPAppender configuration (logback-examples/src/main/java/chapter4/conf/access/logback-smtp.xml) -
<appender name="SMTP"
-  class="ch.qos.logback.access.net.SMTPAppender">
-  <layout class="ch.qos.logback.access.html.HTMLLayout">
-    <Pattern>%h%l%u%t%r%s%b</Pattern>
-  </layout>
-    
-  <Evaluator class="ch.qos.logback.access.net.URLEvaluator">
-    <URL>url1.jsp</URL>
-    <URL>directory/url2.html</URL>
-  </Evaluator>
-  <From>sender_email@host.com</From>
-  <SMTPHost>mail.domain.com</SMTPHost>
-  <To>recipient_email@host.com</To>
-</appender>
- -

This way of triggering the email lets users select pages that - are important steps in a specific process, for example. When such - a page is accessed, the email is sent with the pages that were - accessed previously, and any information the user wants to be - included in the email. -

- - - - -

DBAppender

- -

- DBAppender - is used to insert the access events into a database. -

- -

Two tables are used by DBAppender: - access_event and access_event_header. They all - must exist before DBAppender can be used. Logback - ships with SQL scripts that will create the tables. They can be - found in the - logback-access/src/main/java/ch/qos/logback/access/db/dialect - directory. There is a specific script for each of the most popular - database systems. If the script for your particular type of - database system is missing, it should be quite easy to write one, - taking as example one of the existing scripts. You are encouraged - to contribute such missing scripts back to the project. -

- -

The access_event table's fields are described below:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldTypeDescription
timestampbig intThe timestamp that was valid at the access event's creation.
requestURIvarcharThe URI that was requested.
requestURLvarcharThe URL that was requested. This is a string composed of the request method, - the request URI and the request protocol. -
remoteHostvarcharThe name of the remote host.
remoteUservarchar - The name of the remote user. -
remoteAddrvarcharThe remote IP address.
protocolvarcharThe request protocol, like HTTP or HTTPS.
methodvarcharThe request method, usually GET or POST.
serverNamevarcharThe name of the server that issued the request.
event_idintThe database id of the access event.
- -

- The access_event_header table contains the header of each - requests. The information is organised as shown below: -

- - - - - - - - - - - - - - - - - - - - - - -
FieldTypeDescription
event_idintThe database id of the corresponding access event.
header_keyvarcharThe header name, for example User-Agent.
header_valuevarcharThe header value, for example Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.1) Gecko/20061010 Firefox/2.0
- -

- All properties of classic's DBAppender are available - in access' DBAppender. The latter offers one more option, - described below. -

- - - - - - - - - - - - -
Property NameTypeDescription
- - insertHeaders - - - boolean - - Tells the DBAppender to populate the database with the header - information of all incoming requests. -
- -

- Here is a sample configuration that uses DBAppender. -

- - Example 4.: DBAppender configuration (logback-examples/src/main/java/chapter4/conf/access/logback-DB.xml) -
<configuration>
-
-  <appender name="DB" class="ch.qos.logback.access.db.DBAppender">
-    <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
-      <driverClass>com.mysql.jdbc.Driver</driverClass>
-      <url>jdbc:mysql://localhost:3306/logbackdb</url>
-      <user>logback</user>
-      <password>logback</password>
-    </connectionSource>
-    <insertHeaders>true</insertHeaders>
-  </appender>
-
-  <appender-ref ref="DB" />
-</configuration>
- - -

SiftingAppender

- -

The SiftingAppender in logback-access is quite similar to its - logback-classic counterpart. The main difference is that in - logback-access the default discriminator, namely AccessEventDiscriminator, - is not MDC based. As its name suggests, AccessEventDiscriminator, - uses a designated field in AccessEvent as basis for selecting a - nested appender. If the value of the designated field is null, - then the value specified in the DefaultValue property is used. -

- -

The desginated AccessEvent field can be one of COOKIE, - REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, LOCAL_PORT, - REQUEST_URI. Note that the first three fields require that the - AdditionalKey property also be - specified.

- -

Below is an example configuration file.

- - Example 4.: SiftingAppender configuration (logback-examples/src/main/java/chapter4/conf/sift/access-siftingFile.xml) - -
<configuration>
-  <appender name="SIFTING" class="ch.qos.logback.access.sift.SiftingAppender">
-    <Discriminator class="ch.qos.logback.access.sift.AccessEventDiscriminator">
-      <Key>id</Key>
-      <FieldName>SESSION_ATTRIBUTE</FieldName>
-      <AdditionalKey>username</AdditionalKey>
-      <DefaultValue>NA</DefaultValue>
-    </Discriminator>
-    <sift>
-       <appender name="${id}" class="ch.qos.logback.core.FileAppender">
-        <File>byUser/${id}.log</File>
-        <layout class="ch.qos.logback.access.PatternLayout">
-          <Pattern>%h %l %u %t \"%r\" %s %b</Pattern>
-        </layout>
-      </appender>
-    </sift>
-  </appender>
-  <appender-ref ref="SIFTING" />
-</configuration>
- - -

In the above configuration file, a SiftingAppender - nests FileAppender instances. The key "id" is - designated as a variable which will be availabe to the nested - FileAppender instances. The default discriminator, - namely AccessEventDiscriminator, will search for a - "username" session attribute in each AccessEvent. If - no such attribute is available, then the default value "NA" will - be used. Thus, assuming the session attribute named "username" - contains the username of each logged on user, there will be a log - file under the byUser/ folder (of the current folder) - named after each user containing the access logs for that user. -

- - - - - -
- - - + + + + + Chapter 4: Appenders + + + + + + + + +
+ + +
+ + +
+ +

Chapter 4: Appenders

+ +
+ +

There is so much to tell about the Western country in + that day that it is hard to know where to start. One thing sets + off a hundred others. The problem is to decide which one to tell + first.

+ +

—JOHN STEINBECK, East of Eden

+
+ + + + + +

What is an Appender?

+ +

Logback delegates the task of writing a logging event to + components called appenders. Appenders must implement the ch.qos.logback.core.Appender + interface. The salient methods of this interface are summarized + below: +

+
package ch.qos.logback.core;
+  
+import ch.qos.logback.core.spi.ContextAware;
+import ch.qos.logback.core.spi.FilterAttachable;
+import ch.qos.logback.core.spi.LifeCycle;
+  
+
+public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable {
+
+  public String getName();
+  void doAppend(E event);
+  public void setLayout(Layout<E> layout);
+  public Layout<E> getLayout();
+  public void setName(String name);
+  
+}
+ +

Most of the methods in the Appender interface are + made of setter and getter methods. A notable exception is the + doAppend() method taking an object instance of type + E as its only parameter. The actual type of E + would vary depending on the logback module. Within the + logback-classic module E would be of type ILoggingEvent + and within the logback-access module it would be of type AccessEvent. + The doAppend() method is perhaps the most important in + the logback framework. It is responsible for outputting the logging + events in a suitable format to the appropriate output device. +

+ +

Appenders are named entities. This ensures that they can be + referenced by name, a quality confirmed to be instrumental in + configuration scripts. The Appender interface extends + the FilterAttachable interface. It follows that one or + more filters can be attached to an appender instance. Filters are + discussed in detail in a subsequent chapter. +

+ +

Appenders are ultimately responsible for outputting logging + events. However, they may delegate the actual formatting of the + event to a Layout object. Each layout is associated + with one and only one appender, referred to as the owning + appender. Some appenders have a built-in or fixed event + format. Consequently, they do not require nor have a layout. For + example, the SocketAppender simply serializes logging + events before transmitting them over the wire. +

+ + +

AppenderBase

+ +

The + ch.qos.logback.core.AppenderBase class is an + abstract class implementing the Appender interface. It + provides basic functionality shared by all appenders, such as + methods for getting or setting their name, their activation status, + their layout and their filters. It is the super-class of all + appenders shipped with logback. Although an abstract class, + AppenderBase actually implements the + doAppend() method in the Append interface. + Perhaps the clearest way to discuss AppenderBase class + is by presenting an excerpt of actual source code. +

+ +
public synchronized void doAppend(E eventObject) {
+
+  // prevent re-entry.
+  if (guard) {
+    return;
+  }
+
+  try {
+    guard = true;
+
+    if (!this.started) {
+      if (statusRepeatCount++ < ALLOWED_REPEATS) {
+        addStatus(new WarnStatus(
+            "Attempted to append to non started appender [" + name + "].",this));
+      }
+      return;
+    }
+
+    if (getFilterChainDecision(eventObject) == FilterReply.DENY) {
+      return;
+    }
+    
+    // ok, we now invoke derived class' implementation of append
+    this.append(eventObject);
+
+  } finally {
+    guard = false;
+  }
+}
+ +

This implementation of the doAppend() method is + synchronized. It follows that logging to the same appender from + different threads is safe. While a thread, say T, is + executing the doAppend() method, subsequent calls by + other threads are queued until T leaves the + doAppend() method, ensuring T's exclusive + access to the appender. +

+ +

The first thing the doAppend() method does is to + check whether the guard is set to true. If it is, it immediately + exits. If the guard is not set, it is set to true at the next + statement. The guard ensures that the doAppend() method + will not recursively call itself. Just imagine that a component, + called somewhere beyond the append() method, wants to + log something. Its call could be directed to the very same appender + that just called it. +

+ +

In the following statement we check whether the + started field is true. If it is not, + doAppend() will send a warning message and return. In + other words, once an appender is closed, it is impossible to write + to it. Appender objects implement the + LifeCycle interface, which implies that they implement + start(), stop() and + isStarted() methods. After setting all the properties of + an appender, Joran, logback's configuration framework, calls the + start() method to signal the appender to activate its + properties. Depending on its kind, an appender may fail to start if + certain properties are missing or because of interferences between + various properties. For example, given that file creation depends on + truncation mode, FileAppender cannot act on the value + of its File option until the value of the Append option + is also known with certainty. The explicit activation step ensures + that an appender acts on its properties after their values + become known. +

+ +

If the appender could not be started or if it has been stopped, a + warning message will be issued through logback's internal status + management system. After several attempts, in order to avoid + flooding the internal status system with copies of the same warning + message, the doAppend() method will stop issuing these + warnings. +

+ +

The next if statement checks the result of the + attached filters. Depending on the decision resulting from the + filter chain, events can be denied or alternatively accepted. In + the absence of a decision by the filter chain, events are accepted + by default. +

+ +

The doAppend() method then invokes the derived + classes' implementation of the append() method. This + method does the actual work of appending the event to the + appropriate device. +

+ +

Finally, the guard is released so as to allow a subsequent + invocation of the doAppend() method. +

+ +

For the remainder of this manual, we reserve the term "option" or + alternatively "property" for any attribute that is inferred + dynamically using JavaBeans introspection through setter and getter + methods.

+ +

Logback-core

+ +

Logback-core lays the foundation upon which the other logback + modules are built. In general, the components in logback-core + require some, albeit minimal, customization. However, in the next + few sections, we describe several appenders which are ready for use + out of the box. +

+ + + +

+ WriterAppender +

+ +

WriterAppender + appends events to a java.io.Writer. This class + provides basic services that other appenders build upon. Users do + not usually instantiate WriterAppender objects + directly. Since java.io.Writer type cannot be mapped + to a string, as there is no way to specify the target + Writer object in a configuration script. Simply put, + you cannot configure a WriterAppender from a script. + However, this does not mean that WriterAppender lacks + configurable properties. These properties are described next. +

+ + + + + + + + + + + + + + + + + + + + + +
Property NameTypeDescription
EncodingStringThe encoding specifies the method of conversion between + Java's internal 16-bit Unicode representation of characters into + raw 8-bit bytes. This appender will use the local platform's + default encoding unless you say otherwise by specifying an Encoding value. According to the + java.lang package documentation, acceptable values + are dependent on the VM implementation although all + implementations are required to support at least the following + encodings: US-ASCII, ISO-8859-1, + UTF-8, UTF-16BE, UTF-16LE and + UTF-16. As mentioned previously, by default, the Encoding option is null such + that the platform's default encoding is used. +
ImmediateFlushbooleanIf the ImmediateFlush option is + set to true, then each write of a logging event will be followed + by a flush operation on the underlying Writer + object. Conversely, if the option is set to false, each write + will not be followed by a flush. In general, skipping the flush + operation improves logging throughput by roughly 15%. The + downside is that if the application exits abruptly, the + unwritten characters buffered inside the Writer + might be lost. This can be particularly troublesome as those + unwritten characters may contain crucial information needed in + identifying the reasons behind a crash. By default, the ImmediateFlush option is set to true. +
+ +

In general, if you disable immediate flushing, then make sure to + flush any output streams when your application exits. Otherwise, log + messages will be lost as illustrated by the next example. +

+ + Example 4.: Exiting an application without flushing (logback-examples/src/main/java/chapter4/ExitWoes1.java) + +
package chapter4;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.WriterAppender;
+import ch.qos.logback.core.layout.EchoLayout;
+
+public class ExitWoes1 {
+
+  public static void main(String[] args) throws Exception {
+    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+    lc.reset(); // we want to override the default-config.
+    WriterAppender<ILoggingEvent> writerAppender = new WriterAppender<ILoggingEvent>();
+    writerAppender.setContext(lc);
+    writerAppender.setLayout(new EchoLayout<ILoggingEvent>());
+
+    OutputStream os = new FileOutputStream("exitWoes1.log");
+    writerAppender.setWriter(new OutputStreamWriter(os));
+    writerAppender.setImmediateFlush(false);
+    writerAppender.start();
+    Logger root = lc.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
+    root.addAppender(writerAppender);
+
+    Logger logger = lc.getLogger(ExitWoes1.class);
+
+    logger.debug("Hello world.");
+  }
+}
+ +

This example creates a WriterAppender that uses an + OutputStreamWriter wrapping a + FileOutputStream as its underlying Writer + object, with immediate flushing disabled. It then proceeds to log a + single debug message. According to OutputStreamWriter + javadocs, each invocation of a write() method causes + the encoding converter to be invoked on the given character(s). The + resulting bytes are accumulated in a buffer before being written to + the underlying output stream. As astonishing as this may seem, + running ExitWoes1 will not produce any data in the file + exitWoes1.log because the Java VM does not flush output + streams when it exits. Calling the stop() + method of a LoggerContext ensures that all appenders in + the hierarchy are closed and their buffers are flushed. The ExitWoes2 class + uses this statement and outputs a logging request. +

+ +

The WriterAppender is the superclass of three other + appenders, namely ConsoleAppender, + FileAppender which in turn is the super class of + RollingFileAppender. The next figure illustrates the + class diagram for WriterAppender and its subclasses. +

+ + A UML diagram showing FileAppender + + +

+ ConsoleAppender +

+ +

The + ConsoleAppender, as the name indicates, appends on + the console, or more precisely on System.out or + System.err, the former being the default + target. ConsoleAppender formats events with a layout + specified by the user. Layouts will be discussed in the next + chapter. Both System.out and System.err are + java.io.PrintStream objects. Consequently, they are + wrapped inside an OutputStreamWriter which buffers I/O + operations but not character conversions. +

+ + + + + + + + + + + + + + + + + + + + + + +
Property NameTypeDescription
EncodingStringSee WriterAppender properties.
ImmediateFlushbooleanSee WriterAppender properties.
TargetString + One of the String values System.out or + System.err. The default target is System.out. +
+ +

Here is a sample configuration that uses + ConsoleAppender. +

+ + Example 4.: ConsoleAppender configuration (logback-examples/src/main/java/chapter4/conf/logback-Console.xml) +
<configuration>
+
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

After you have set your current path to the + logback-examples directory, you can give the above + configuration file a whirl by issuing the following command: +

+ +

java chapter4.ConfigurationTester src/main/java/chapter4/conf/logback-Console.xml

+ + +

+ FileAppender +

+ +

The FileAppender, + a subclass of WriterAppender, appends log events into + a file. The target file is specified by the File option. If the file already exists, it + is either appended to, or truncated depending on the value of the + Append option. + FileAppender uses a FileOutputStream + which is wrapped by an OutputStreamWriter. Note that + OutputStreamWriter buffers I/O operations but not + character conversions. To optimize character conversions one can + set the BufferedIO option to true which + effectively wraps the OutputStreamWriter with a + BufferedWriter. Properties for FileAppender + are summarized below. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Property NameTypeDescription
AppendbooleanIf true, events are appended at the end of an existing + file. Otherwise, if Append is + false, any existing file is truncated. The Append option is set to true by + default. +
EncodingStringSee WriterAppender properties.
BufferedIObooleanThe BufferedIO option is set to + false by default. If set to true, the underlying + OutputStreamWriter is wrapped by a + BufferedWriter object. Setting BufferedIO to true automatically sets the + ImmediateFlush option to false. + The name BufferedIO is slightly + misleading because buffered I/O is already supported by + OutputStreamWriter. Setting BufferedIO to true has the effect of + buffering I/O as well as character to raw byte conversions, + saving a few CPU cycles in the process. +
BufferSizeintSize of BufferedWriter buffer. The default value is 8192.
FileStringThe name of the file to write to. If the file does not + exist, it is created. On the MS Windows platform users + frequently forget to escape back slashes. For example, the + value c:\temp\test.log is not likely to be interpreted + properly as '\t' is an escape sequence interpreted as + a single tab character (\u0009). Correct values can + be specified as c:/temp/test.log or alternatively as + c:\\temp\\test.log. The File option has no default value. + +

If the parent directory of the file does now exist, the + FileAppender will automatically create it, including any + necessary but nonexistent parent directories. +

+
ImmediateFlushbooleanSee WriterAppender properties.
Prudentboolean +

In prudent mode, FileAppeder will safely + write to the specified file, even in the presence of other + FileAppender instances running in different + JVMs, potentially running on different hosts. The default + value for prudent mode is false. +

+ +

Prudent mode implies that Append and ImmediateFlush properties are + automatically set to true and the BufferedIO set to false. +

+ +

Prudent mode will approximately triple (x3) the cost of + writing a logging event. On an "average" PC writing to a file + located on a local hard disk, when prudent mode is off, it + takes about 10 microseconds to write a single logging + event. When prudent mode is on, it takes approximately 30 + microseconds to output a single logging event. This + translates to logging throughput of 100'000 events per second + when prudent mode is off and approximately 33'000 events per + second in prudent mode. +

+ +

Prudent mode can be used in conjunction with + RollingFileAppender although some restrictions apply. +

+
+ +

By default, FileAppender performs a flush on each + event, ensuring that events are immediately written to disk. + Setting the ImmediateFlush option to + false can drastically reduce I/O activity by letting + OutputStreamWriter buffer bytes before writing them on + disk. For short messages, we have observed 2 or 3 fold increases in + logging throughput, i.e. the number of logs output per unit of + time. For longer messages, the throughput gains are somewhat less + dramatic, and range between 1.4 and 2 fold. Enabling the BufferedIO option, that is buffering + character to byte conversions, increases performance by an + additional 10% to 40% compared to only disk I/O buffering (ImmediateFlush=false). Performance varies + somewhat depending on the host machine as well as JDK version. + Throughput measurements are based on the chapter4.IO + application. Please refer to + logback-examples/src/main/java/chapter4/IO.java for + actual source code. +

+ +

Below is an example of a configuration file for + FileAppender: +

+ + Example 4.: FileAppender configuration (logback-examples/src/main/java/chapter4/conf/logback-fileAppender.xml) +
<configuration>
+
+  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+    <File>testFile.log</File>
+    <Append>true</Append>
+		
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
+    </layout>
+  </appender>
+	
+  <root level="debug">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+ +

After changing the current directory to + logback-examples, run this example by launching the + following command: +

+ +

java chapter4.ConfigurationTester src/main/java/chapter4/conf/logback-fileAppender.xml

+ + +

+ Uniquely named + files (by timestamp) +

+ +

During the application development phase or in the case of + short-lived applications, e.g. batch applications, it is desirable + to create a new log file at each new application launch. This is + fairly easy to do with the help of the <timestamp> + element. Here's an example.

+ + + Example 4.: Uniquely named FileAppender configuration by timestamp (logback-examples/src/main/java/chapter4/conf/logback-timestamp.xml) +
<configuration>
+
+  <!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under
+       the key "bySecond" into the logger context. This value will be
+       available to all subsequent configuration elements. -->
+  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
+
+  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+    <!-- use the previously created timestamp to create a uniquely
+         named log file -->
+    <File>log-${bySecond}.txt</File>
+    <layout>
+      <Pattern>%logger{35} - %msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+ + +

The timestamp element takes two attributes key and datePattern. The key + attribute is the name of the key under which the timestamp will be + available to subsequent configuration elements as a + variable. The datePattern attribute + denoted the date pattern used to convert the current time (at which + the configuration file is parsed) into a string. The date pattern + should follow the conventions defined in SimpleDateFormat. +

+ +

+ RollingFileAppender +

+ +

RollingFileAppender + extends FileAppender with the capability to roll log + files. For example, RollingFileAppender can log to a + file named log.txt file and, once a certain condition is + met, change its logging target to another file. +

+ +

There are two important logback components that interact with + RollingFileAppender. First, a + RollingPolicy instance attached to the + RollingFileAppender is responsible for undertaking the + action for performing a rollover. Second, a + TriggeringPolicy instance attached to a + RollingFileAppender will determine if and exactly when + rollover happens Thus, RollingPolicy is responsible + for the what and TriggeringPolicy is + responsible for the when. +

+ +

To be of any use, a RollingFileAppender must have + both a RollingPolicy and a + TriggeringPolicy set up. However, if its + RollingPolicy also implements the + TriggeringPolicy interface, then only the former needs + to be set up. +

+ +

Here are the available properties for RollingFileAppender:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

See also FileAppender properties.

+ + +
Property NameTypeDescription
AppendbooleanSee FileAppender properties.
BufferedIObooleanSee FileAppender properties.
BufferSizeintSee FileAppender properties.
EncodingStringSee WriterAppender properties.
FileStringSee FileAppender properties.
ImmediateFlushbooleanSee WriterAppender properties.
RollingPolicyRollingPolicyThis option is the component that will dictate + RollingFileAppender's behavior when rollover + occurs. See more information below. +
TriggeringPolicyTriggeringPolicy + This option is the component that will tell + RollingFileAppender when to activate the rollover + procedure. See more information below. +
Prudentboolean + +

FixedWindowRollingPolicy + is not supported in prudent mode.

+ +

RollingFileAppender supports the prudent + mode in conjunction with TimeBasedRollingPolicy + albeit with two restrictions. + +

    +
  1. In prudent mode, file compression is not supported nor + allowed. (We can't have one JVM writing to a file while + another JVM is compressing it.)
  2. + +
  3. The File property of + FileAppender cannot be set and must be left + blank. Indeed, most operating systems do not allow renaming + of a file while another process has it opened. +
  4. + +
+ +
+ +

Rolling policies

+ +

RollingPolicy + is responsible for the rollover procedure. It manages file renaming + and in occasion file deleting.

+ +

The RollingPolicy interface is presented below:

+ +
package ch.qos.logback.core.rolling;  
+
+import ch.qos.logback.core.FileAppender;
+import ch.qos.logback.core.spi.LifeCycle;
+
+public interface RollingPolicy extends LifeCycle {
+
+  public void rollover() throws RolloverFailure;
+  public String getNewActiveFileName();
+  public void setParent(FileAppender appender);
+}
+ +

The rollover method proceeds to the file change, + renaming or deletion. The getNewActiveFileName() + method is called to compute a new file name, with respect to the + configuration elements that were injected into the + RollingPolicy. Lastly, a RollingPolicy + is given a reference to its parent via the setParent + method. +

+ +

+ FixedWindowRollingPolicy +

+ +

When rolling over, + FixedWindowRollingPolicy renames files according + to a fixed window algorithm as described below. +

+ +

The FileNamePattern option + represents the file name pattern for the archived (rolled over) log + files. This option is required and must include an integer token + %i somewhere within the pattern. +

+ +

Here are the available properties for + FixedWindowRollingPolicy +

+ + + + + + + + + + + + + + + + + + + + + + +
Property NameTypeDescription
MinIndexint +

This option represents the lower bound for the window's + index. +

+
MaxIndexint +

This option represents the upper bound for the window's + index. +

+
FileNamePatternString +

This option represents the pattern that will be followed + by the FixedWindowRollingPolicy when renaming + the log files. If must contain the string %i, which + will indicate the position where the value of the current + window index will be inserted. +

+

For example, using MyLogFile%i.log, associated + with minimum and maximum values of 1 and 3 + will produce archive files named MyLogFile1.log, + MyLogFile2.log and MyLogFile3.log. +

+

Note that file compression is also specified via the FileNamePattern option. For example, the + file name pattern MyLogFile%i.log.zip will indicate + to the FixedWindowRollingPolicy that the archived + file must be compressed using the zip format; + gz format is also supported. +

+
+ +

Given that the fixed window rolling policy requires as many file + renaming operations as the window size, large window sizes are + strongly discouraged. The current implementation will automatically + reduce the window size to 12, when larger values are specified by + the user. +

+ +

Let us go over a more concrete example of the fixed windows + rollover policy. Suppose that the MinIndex is set to 1, MaxIndex set to 3, that FileNamePattern option is set to + foo%i.log, and that FileNamePattern option is set to + foo.log. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Number of rolloversActive output targetArchived log filesDescription
0foo.log-No rollover has happened yet, logback logs into the initial + file. +
1foo.logfoo1.logFirst rollover. foo.log is renamed as + foo1.log. A new foo.log file is created and + becomes the active output target. +
2foo.logfoo1.log, foo2.logSecond rollover. foo1.log is renamed as + foo2.log. foo.log is renamed as + foo1.log. A new foo.log file is created and + becomes the active output target. +
3foo.logfoo1.log, foo2.log, foo3.logThird rollover. foo2.log is renamed as + foo3.log. foo1.log is renamed as + foo2.log. foo.log is renamed as + foo1.log. A new foo.log file is created and + becomes the active output target. +
4foo.logfoo1.log, foo2.log, foo3.logIn this and subsequent rounds, the rollover begins by + deleting foo3.log. Other files are renamed by + incrementing their index as shown in previous steps. In this and + subsequent rollovers, there will be three archive logs and one + active log file. +
+ +

The configuration file below gives an example of configuring + RollingFileAppender and + FixedWindowRollingPolicy. Note that the File option is mandatory even if it contains + some of the same information as conveyed with the FileNamePattern option. +

+ + Example 4.: Sample configuration of a RollingFileAppender using a + FixedWindowRollingPolicy (logback-examples/src/main/java/chapter4/conf/logback-RollingFixedWindow.xml) + +
<configuration>
+  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+    <File>test.log</File>
+
+    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+      <FileNamePattern>tests.%i.log.zip</FileNamePattern>
+      <MinIndex>1</MinIndex>
+      <MaxIndex>3</MaxIndex>
+    </rollingPolicy>
+
+    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+      <MaxFileSize>5MB</MaxFileSize>
+    </triggeringPolicy>
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
+    </layout>
+  </appender>
+	
+  <root level="debug">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+ +

+ TimeBasedRollingPolicy +

+ +

+ TimeBasedRollingPolicy is possibly the most + popular rolling policy. It defines a rollover policy based on time, + for example by day or by month. +

+ +

TimeBasedRollingPolicy's admits two properties, the + mandatory FileNamePattern property and + the optional MaxHistory property. +

+ +

FileNamePattern property defines the + name of the rolled (archived) log files. Its value should consist + of the name of the file, plus a suitably placed %d + conversion specifier. The %d conversion specifier may + contain a date-and-time pattern as specified by the + java.text.SimpleDateFormat class. If the + date-and-time pattern is omitted, then the default pattern + yyyy-MM-dd is assumed. The File property in + RollingFileAppender (the parent of + TimeBasedRollingPolicy) can be either set or omitted. + +

+ +

By setting the File property you can + decouple the location of the active log file and the location of + the archived log files. The current logs will be always targeted at + the file specified by the File + property. It follows that the name of the currently active log file + will not change over time. However, if you choose to omit the File property, then the active file will be + computed anew for each period based on the value of FileNamePattern. The following examples + should clarify the point. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ FileNamePattern + Rollover scheduleExample
+ /wombat/foo.%d + Daily rollover (at midnight). Due to the omission of the + optional time and date pattern for the %d token + specifier, the default pattern of yyyy-MM-dd is + assumed, which corresponds to daily rollover. + +

File property not set: During November + 23rd, 2006, logging output will go to the file + /wombat/foo.2006-11-23. At midnight and for the + rest of the 24th, logging output will be directed to + /wombat/foo.2006-11-24. +

+ +

File property set to + /wombat/foo.txt: During November 23rd, 2006, logging + output will go to the file /wombat/foo.txt. At + midnight, foo.txt will be renamed as + /wombat/foo.2006-11-23. A new + /wombat/foo.txt file will be created and for the + rest of November 24th logging output will be directed to + foo.txt. +

+ +
+ /wombat/%d{yyyy/MM}/foo.txt + Rollover at the beginning of each month. +

File property not set: During the + month of October 2006, logging output will go to + /wombat/2006/10/foo.txt. After midnight of October + 31st and for the rest of November, logging output will be + directed to /wombat/2006/11/foo.txt. +

+ +

File property set to + /wombat/foo.txt: The active log file will always be + /wombat/foo.txt. During the month of October 2006, + logging output will go to /wombat/foo.txt. At + midnight of October 31st, /wombat/foo.txt will be + renamed as /wombat/2006/10/foo.txt. A new + /wombat/foo.txt file will be created where logging + output will go for the rest of November. At midnight of + November 30th, /wombat/foo.txt will be renamed as + /wombat/2006/11/foo.txt and so on. +

+
+ /wombat/foo.%d{yyyy-ww}.log + Rollover at the first day of each week. Note that the first + day of the week depends on the locale.Similar to previous cases, except that rollover will occur + at the beginning of every new week. +
+ /wombat/foo.   /
%d{yyyy-MM-dd_HH}.log
+
Rollover at the top of each hour.Similar to previous cases, except that rollover will occur + at the top of every hour. +
+ /wombat/foo.    /
%d{yyyy-MM-dd_HH-mm}.log
+
Rollover at the beginning of every minute.Similar to previous cases, except that rollover will occur + at the beginning of every minute. +
+ +

Any forward or backward slash characters are interpreted as + folder (directory) separators. Any required folder will be created + as necessary. You can thus easily place your log files in separate + folders. +

+ +

The date-and-time pattern, as found within accolades in %d{} + follow java.text.SimpleDateFormat conventions. This any characters + within the date-and-time pattern outside the ranges + ['a'..'z'] and ['A'..'Z'] will be treated as + quoted text. For instance, characters like '.', ' + ', '#' and '@' will appear in the resulting + time text even when they are not enclosed within single + quotes. Nevertheless, we recommend against using the colon + ':' character anywhere within the FileNamePattern option. The text before the + colon is interpreted as the protocol specification of a URL, which + is most probably not what you intend. The forward slash + '/' or backward slash '\' characters anywhere + within the FileNamePattern property or + within the date-and-time pattern will be interpreted as directory + separators and any missing directories will be created as + necessary. +

+ + +

Just like FixedWindowRollingPolicy, + TimeBasedRollingPolicy supports automatic file + compression. This feature is enabled if the value of the FileNamePattern option ends with .gz + or .zip. +

+ + + + + + + + + + + +
FileNamePatternRollover scheduleExample
/wombat/foo.%d.gzDaily rollover (at midnight) with automatic GZIP compression of the + archived files. +

File property not set: During + November 23rd, 2009, logging output will go to the file + /wombat/foo.2009-11-23. However, at midnight that + file will be compressed to become + /wombat/foo.2009-11-23.gz. For the 24th of November, + logging output will be directed to + /wombat/folder/foo.2009-11-24 until it's rolled over + at the beginning of the next day. +

+ +

File property set to + /wombat/foo.txt: During November 23rd, 2009, logging output + will go to the file /wombat/foo.txt. At midnight that + file will be compressed and renamed as + /wombat/foo.2009-11-23.gz. A new + /wombat/foo.txt file will be created where logging + output will go for the rest of November 24rd. At midnight + November 24th, /wombat/foo.txt will be compressed and + renamed as /wombat/foo.2009-11-24.gz. and so on. +

+
+ +

The FileNamePattern serves a dual + purpose. First, by studying the pattern, logback computes the + requested rollover periodicity. Second, it computes each archived + file's name. Note that it is possible for two different patterns to + specify the same periodicity. The patterns yyyy-MM and + yyyy@MM both specify monthly rollover, although the + resulting archive files will carry different names. +

+ +

TimeBasedRollingPolicy assumes the responsibility + for rollover as well as for the triggering of said rollover. Indeed, + TimeBasedTriggeringPolicy implements both + RollingPolicy and TriggeringPolicy + interfaces. +

+ +

By setting the File property you can + decouple the location of the active log file and the location of the + archived log files. The logging output will be targeted into the + file specified by the File property. It + follows that the name of the active log file will not change over + time. However, if you choose to omit the File property, then the active file will be + computed anew for each period based on the value of FileNamePattern. +

+ +

The MaxHistory property controls the + maximum number of archive files to keep, deleting older files. For + example, if you specify monthly rollover, and set MaxHistory to 6, then 6 months worth of + archives files will be kept with files older than 6 months + deleted. Note as old archived log files are removed, any folders + which were created for the purpose of log file archiving will be + removed as appropriate. +

+ + +

For various technical reasons, rollovers are not clock-driven but + depend on the arrival of logging events. For example, on 8th of + March 2002, assuming the FileNamePattern + is set to yyyy-MM-dd (daily rollover), the arrival of the + first event after midnight will trigger a rollover. If there are no + logging events during, say 23 minutes and 47 seconds after midnight, + then rollover will actually occur at 00:23'47 AM on March 9th and + not at 0:00 AM. Thus, depending on the arrival rate of events, + rollovers might be triggered with some latency. However, regardless + of the delay, the rollover algorithm is known to be correct, in the + sense that all logging events generated during a certain period will + be output in the correct file delimiting that period. +

+ +

Here is a sample configuration for + RollingFileAppender in conjunction with a + TimeBasedRollingPolicy. +

+ + Example 4.: Sample configuration of a RollingFileAppender using a + TimeBasedRollingPolicy (logback-examples/src/main/java/chapter4/conf/logback-RollingTimeBased.xml) +
<configuration>
+  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+    <File>logFile.log</File>
+    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+      <FileNamePattern>logFile.%d{yyyy-MM-dd}.log</FileNamePattern>
+      <!-- keep 30 days' worth of history -->
+      <MaxHistory>30</MaxHistory>
+    </rollingPolicy>
+
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
+    </layout>
+  </appender> 
+
+  <root level="debug">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+ +

The next configuration sample illustrates the use of + RollingFileAppender associated with + TimeBasedRollingPolicy in Prudent + mode. +

+ + Example 4.: Sample configuration of a RollingFileAppender using a + TimeBasedRollingPolicy (logback-examples/src/main/java/chapter4/conf/logback-PrudentTimeBasedRolling.xml) +
<configuration>
+  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+    <!-- Support multiple-JVM writing to the same log file -->
+    <Prudent>true</Prudent>
+    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+      <FileNamePattern>logFile.%d{yyyy-MM-dd}.log</FileNamePattern>
+      <MaxHistory>30</MaxHistory> 
+    </rollingPolicy>
+
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
+    </layout>
+  </appender> 
+
+  <root level="debug">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+ + +

+ Size and time based archiving +

+ +

You may sometimes wish to archive files essentially by date but + at the same time limit the size of each log file, in particular if + post-processing tools impose size limits on the log files. In + order to address this requirement, logback ships with a + sub-component for TimeBasedRollingPolicy called + SizeAndTimeBasedFNATP, where FNATP stands for File + Naming And Triggering Policy.

+ + + + Example 4.: Sample configuration for + SizeAndTimeBasedFNATP + (logback-examples/src/main/java/chapter4/conf/logback-sizeAndTime.xml) +
<configuration>
+ <appender name="ROLLING"
+    class="ch.qos.logback.core.rolling.RollingFileAppender">
+    <File>mylog.txt</File>
+    <rollingPolicy
+      class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+      <FileNamePattern>
+        mylog-%d{yyyy-MM-dd_HH_mm_ss}.%i.txt
+      </FileNamePattern>
+      <TimeBasedFileNamingAndTriggeringPolicy
+            class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+        <MaxFileSize>${sizeThreshold}</MaxFileSize>
+      </TimeBasedFileNamingAndTriggeringPolicy>
+    </rollingPolicy>
+    <layout>
+      <Pattern>%msg%n</Pattern>
+    </layout>
+  </appender>
+
+
+  <root level="debug">
+    <appender-ref ref="ROLLING" />
+  </root>
+
+</configuration>
+ +

Note the "%i" conversion token in addition to "%d{}". Each time + the current log file reaches MaxFileSize before the + current time period end, it will be archived with an increasing + index, starting at 0.

+ +

Size and time based archiving supports cleaning of old archive + files. You just need to specify the number of periods to preserve + with the <MaxHistory> element. When your + application is stopped and restarted, logging will continue at the + correct location, i.e. at the largest index number for the current + period. +

+ +

+ Triggering policy interface +

+ +

TriggeringPolicy + implementations are responsible for instructing the + RollingFileAppender when to rollover.

+ +

The TriggeringPolicy interface contains only one + method.

+ +
package ch.qos.logback.core.rolling;
+
+import java.io.File;
+import ch.qos.logback.core.spi.LifeCycle;
+
+public interface TriggeringPolicy<E> extends LifeCycle {
+
+  public boolean isTriggeringEvent(final File activeFile, final <E> event);
+}
+ +

The isTriggeringEvent() method takes as parameters + the active file, and the logging event currently being + processed. The concrete implementation determines whether the + rollover should occur or not, based on the said parameters. +

+ + +

SizeBasedTriggeringPolicy

+ +

+ SizeBasedTriggeringPolicy looks at size of the + currently active file. If it grows larger than the specified size, + the FileAppender using the + SizeBasedTriggeringPolicy will proceed to the + rollover of the existing active file and create a new one. +

+ +

This TriggeringPolicy accepts only one parameter, + namely MaxFileSize, with a default + value of 10 MB. +

+ +

The MaxFileSize option can be + specified in bytes, kilobytes, megabytes or gigabytes by suffixing + a numeric value with KB, MB and respectively + GB. For example, 5000000, 5000KB, + 5MB and 2GB are all valid values, with the first + three being also equivalent. +

+ +

Here is a sample configuration with a + RollingFileAppender in conjunction with + SizeBasedTriggeringPolicy. +

+ + Example 4.: Sample configuration of a RollingFileAppender using a + SizeBasedTriggeringPolicy (logback-examples/src/main/java/chapter4/conf/logback-RollingSizeBased.xml) +
<configuration>
+  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+    <File>testFile.log</File>
+    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+      <FileNamePattern>testFile.%i.log.zip</FileNamePattern>
+      <MinIndex>1</MinIndex>
+      <MaxIndex>3</MaxIndex>
+    </rollingPolicy>
+
+    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+      <MaxFileSize>5MB</MaxFileSize>
+    </triggeringPolicy>
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
+    </layout>
+  </appender>
+	
+  <root level="debug">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+ + + + +

Logback Classic

+ + +

While logging events are generic in logback-core, within + logback-classic they are always instances of + ILoggingEvent. Logback-classic is nothing more than a + specialized processing pipeline handling instances of + ILoggingEvent. + +

+ +

+ SocketAppender +

+ +

The appenders covered this far were only able to log on local + resources. In contrast, the + SocketAppender is designed to log to a remote + entity by transmitting serialized ILoggingEvent + instances over the wire. The actual type of the serialized event + is LoggingEventVO + which implements the ILoggingEvent + interface. Nevertheless, remote logging is non-intrusive as far as + the logging event is concerned. On the receiving end after + deserialization, the event can be logged as if it were generated + locally. Multiple SocketAppender instances running on + different machines can direct their logging output to a central + log server whose format is fixed. SocketAppender + does not admit an associated layout because it sends serialized + events to a remote server. SocketAppender operates + above the Transmission Control Protocol (TCP) layer which + provides a reliable, sequenced, flow-controlled end-to-end octet + stream. Consequently, if the remote server is reachable, then log + events will eventually arrive there. Otherwise, if the remote + server is down or unreachable, the logging events will simply be + dropped. If and when the server comes back up, then event + transmission will be resumed transparently. This transparent + reconnection is performed by a connector thread which periodically + attempts to connect to the server. +

+ +

Logging events are automatically buffered by the native TCP + implementation. This means that if the link to server is slow but + still faster than the rate of event production by the client, the + client will not be affected by the slow network + connection. However, if the network connection is slower than the + rate of event production, then the client can only progress at the + network rate. In particular, in the extreme case where the network + link to the server is down, the client will be eventually blocked. + Alternatively, if the network link is up, but the server is down, + the client will not be blocked, although the log events will be + lost due to server unavailability. +

+ +

Even if a SocketAppender is no longer attached to + any logger, it will not be garbage collected in the presence of a + connector thread. A connector thread exists only if the + connection to the server is down. To avoid this garbage + collection problem, you should close the + SocketAppender explicitly. Long lived applications + which create/destroy many SocketAppender instances + should be aware of this garbage collection problem. Most other + applications can safely ignore it. If the JVM hosting the + SocketAppender exits before the + SocketAppender is closed, either explicitly or + subsequent to garbage collection, then there might be + untransmitted data in the pipe which may be lost. This is a common + problem on Windows based systems. To avoid lost data, it is + usually sufficient to close() the + SocketAppender either explicitly or by calling the + LoggerContext's stop() + method before exiting the application. +

+ +

The remote server is identified by the RemoteHost and Port properties. + SocketAppender properties are listed in the following + table. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Property NameTypeDescription
IncludeCallerDataboolean +

+ The IncludeCallerData option takes a boolean value. + If true, the caller data will be available to the remote host. + By default no caller data is sent to the server. +

+
Portint +

+ The port number of the remote server. +

+
ReconnectionDelayint + The ReconnectionDelay option takes a + positive integer representing the number of milliseconds to wait between + each failed connection attempt to the server. + The default value of this option is 30'000 which corresponds to 30 seconds. + Setting this option to zero turns off reconnection capability. + Note that in case of successful connection to the server, there will be no + connector thread present. +
RemoteHostString + The host name of the server. +
+ +

The standard logback distribution includes a simple log server + application named + ch.qos.logback.classic.net.SimpleSocketServer that + can service multiple SocketAppender clients. It waits + for logging events from SocketAppender clients. After + reception by SimpleSocketServer, the events are + logged according to local server policy. The + SimpleSocketServer application takes two parameters: + port and configFile; where port is the port to listen on and + configFile is a configuration script in XML format. +

+ +

+ Assuming you are in the logback-examples/ directory, + start SimpleSocketServer with the following command: +

+ +

java ch.qos.logback.classic.net.SimpleSocketServer 6000 \ + src/main/java/chapter4/socket/server1.xml

+ +

where 6000 is the port number to listen on and + server1.xml is a configuration script that adds a + ConsoleAppender and a + RollingFileAppender to the root logger. After you + have started SimpleSocketServer, you can send it log + events from multiple clients using SocketAppender. + The examples associated with this manual include two such clients: + chapter4.SocketClient1 and + chapter4.SocketClient2 Both clients wait for the user + to type a line of text on the console. The text is encapsulated + in a logging event of level debug and then sent to the remote + server. The two clients differ in the configuration of the + SocketAppender. SocketClient1 configures + the appender programmatically while SocketClient2 + requires a configuration file. +

+ +

Assuming SimpleSocketServer is running on the + local host, you connect to it with the following command: +

+ +

java chapter4.socket.SocketClient1 localhost 6000

+ +

Each line that you type should appear on the console of the + SimpleSocketServer launched in the previous step. If + you stop and restart the SimpleSocketServer the + client will transparently reconnect to the new server instance, + although the events generated while disconnected will be simply + (and irrevocably) lost. +

+ +

+ Unlike + SocketClient1, the sample application + SocketClient2 does not configure logback by itself. + It requires a configuration file in XML format. + The configuration file client1.xml + shown below creates a SocketAppender + and attaches it to the root logger. +

+ + Example 4.: SocketAppender configuration (logback-examples/src/main/java/chapter4/socket/client1.xml) +
<configuration>
+	  
+  <appender name="SOCKET" class="ch.qos.logback.classic.net.SocketAppender">
+    <RemoteHost>${host}</RemoteHost>
+    <Port>${port}</Port>
+    <ReconnectionDelay>10000</ReconnectionDelay>
+    <IncludeCallerData>${includeCallerData}</IncludeCallerData>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="SOCKET" />
+  </root>  
+
+</configuration>
+ + +

+ Note that in the above configuration scripts the values for the + RemoteHost, Port and + IncludeCallerData properties + are not given directly but as substituted variable keys. The values for the variables + can be specified as system properties: +

+ +

java -Dhost=localhost -Dport=6000 -DincludeCallerData=false \ + chapter4.socket.SocketClient2 src/main/java/chapter4/socket/client1.xml

+ +

This command should give similar results to the previous + SocketClient1 + example. +

+ +

Allow us to repeat for emphasis that serialization of logging + events is not intrusive. A deserialized event carries the same + information as any other logging event. It can be manipulated as + if it were generated locally; except that serialized logging + events by default do not include caller data. Here is an example + to illustrate the point. First, start + SimpleSocketServer with the following command: +

+ +

java ch.qos.logback.classic.net.SimpleSocketServer 6000 \ + src/main/java/chapter4/socket/server2.xml

+ +

The configuration file server2.xml creates a + ConsoleAppender whose layout outputs the caller's file + name and line number along with other information. If you run + SocketClient2 with the configuration file + client1.xml as previously, you will notice that the output + on the server side will contain two question marks between + parentheses instead of the file name and the line number of the + caller: +

+ +

2006-11-06 17:37:30,968 DEBUG [Thread-0] [?:?] chapter4.socket.SocketClient2 - Hi

+ +

+ The outcome can be easily changed by instructing the SocketAppender + to include caller data by setting the IncludeCallerData + option to true. Using the following command will do the trick: +

+ +
java -Dhost=localhost -Dport=6000 -DincludeCallerData=true \
+  chapter4.socket.SocketClient2 src/main/java/chapter4/socket/client1.xml
+
+ +

+ As deserialized events can be handled in the same way as locally + generated events, they even can be sent to a second server for further treatment. + As an exercise, you may wish to setup two servers where the first server + tunnels the events it receives from its clients to a second server. +

+ + +

JMSAppenderBase

+ +

+ The + JMSAppenderBase subclasses conceptually accomplish + the same task as the SocketAppender but as the name + suggests it is based on the JMS API instead of TCP sockets. + JMS or the Java Message Service API + provides an abstraction for Message-Oriented Middleware (MOM) products. + One of the key architectural concepts in JMS is the decoupling of message + producers and message consumers. Senders do not have to wait for receivers + to handle messages and conversely the receiver consumes messages as they + become available; messages are said to be delivered asynchronously. Just as + importantly, consumers as well as producers can be added or removed at will + to a JMS channel. The set of the message producers and message consumers can + vary independently and transparently over time, with both sets oblivious + to each other. +

+ +

The JMS specification provides for two types of messaging + models, publish-and-subscribe and point-to-point queueing. Logback + supports the former model with JMSTopicAppender and + the latter with JMSQueueAppender Both appenders + extend the JMSAppenderBase class and publish + serialized events to a topic or queue specified by the user. +

+ +

One or more JMSTopicSink or + JMSQueueSink applications can register with a JMS + server and consume the serialized events. The consumers of events + generated by JMS appenders need not only be + JMSTopicSink or JMSQueueSink + applications. Any application or MessageDrivenBean capable of + subscribing to the appropriate topic or queue and consuming + serialized logging event messages would be suitable. Additional + consumers could be quickly built based on the + JMSTopicSink or JMSQueueSink model. +

+ +

+ Here are JMSAppenderBase's properties: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Property NameTypeDescription
InitialContextFactoryNameString +

+ The class name of the initial JNDI context factory. There is no need + to set this option if you have a properly configured jndi.properties + file or if JMSAppenderBase subclass is running + within an application server. +

+

+ If you set this option, you should + also set the ProviderURL option. +

+
ProviderURLString +

+ This option specifies configuration information for the + JNDI service provider. The value of the property should contain a + URL string (e.g. ldap://somehost:389). +

+

+ The ProviderURL option is taken into + account only if the InitialContextFactoryName + option is specified. It is ignored otherwise. +

+
URLPkgPrefixesString +

+ This option contains the list of package prefixes to + use when loading in URL context factories. The value of the + property should be a colon-separated list of package + prefixes for the class name of the URL context factory class. +

+

+ For JBoss the value of this option should be: + org.jboss.naming:org.jnp.interfaces + This option is not needed under Weblogic. +

+

+ This option is taken into account only if the + InitialContextFactoryName + option is specified. It is ignored otherwise. +

+
SecurityPrincipalNameString +

+ The security principal name to use when accessing the JNDI namespace. + This option is usually not required. +

+

+ This option is taken into account only if the + InitialContextFactoryName + option is specified. It is ignored otherwise. +

+
+ + SecurityCredentials + + + String + +

+ The security credentials to use when accessing the + JNDI namespace. This option is usually not required. +

+

+ This option is taken into account only if the + + InitialContextFactoryName + + option is specified. It is ignored otherwise. +

+
+ + UserName + + + String + +

+ The username to use when creating a topic or queue connection. +

+
+ + Password + + + String + +

+ The password to use when creating a topic or queue connection. +

+
+ +

+ JMS topics, queues and connection factories are administered objects that are obtained + using the JNDI API. This in turn implies the necessity of retrieving a JNDI Context. + There are two common methods for obtaining a JNDI Context. If a file resource named + jndi.properties is available to the JNDI API, it will use the information + found therein to retrieve an initial JNDI context. + To obtain an initial context, one simply calls: +

+ +
InitialContext jndiContext = new InitialContext();
+ +

+ Calling the no-argument InitialContext() constructor will also work + from within Enterprise Java Beans (EJBs). + Indeed, it is part of the EJB contract for application servers to provide + each enterprise bean an environment naming context (ENC). +

+ +

+ In the second approach, several predetermined properties are specified. + These properties are passed to the InitialContext constructor + to connect to the naming service provider. + For example, to connect to an + ActiveMQ + naming server one would write: +

+ +
Properties env = new Properties();
+env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
+env.put(Context.PROVIDER_URL, "tcp://hostname:61616");
+Context ctx = new InitialContext(env);
+ +

+ where hostname is the host where the ActiveMQ server is running. +

+ +

+ Other JNDI providers will obviously require different values. + As mentioned previously, the initial JNDI context can be obtained by calling + the no-argument InitialContext() constructor from within EJBs. + Only clients running in a separate JVM need to be concerned about + the jndi.properties file or setting the different properties + before calling InitialContext constructor taking a + Properties (i.e. Hashtable) parameter. +

+ +

Comments on JMS appenders

+ +

Transmitting a packet of information using JMS is certain to be + substantially slower than sending the same packet using raw TCP + sockets. JMS vendors bragging about the performance of their + messaging platform tend to omit this simple fact. Guaranteed + store and forward messaging comes at a hefty price. In return for + increased cost, JMS messaging provides decoupling of sender and + receiver. As long as the JMS provider is reachable, messages will + eventually arrive at the destination. However, what if the JMS + server is down or simply unreachable? +

+ +

According to the JMS specification, producers can mark a + message as either persistent or non-persistent. The persistent + delivery mode instructs the JMS provider to log the message to + stable storage as part of the client's send operation, allowing + the message to survive provider crashes. JMS appenders do not set + the delivery mode of messages they produce because according to + the JMS specification, the delivery mode is considered as an + administered property. +

+ +

Once a message reaches the JMS provider, the provider assumes + the responsibility of delivering it to its destination, relieving + the client from this chore. What if the JMS server is + unreachable? The JMS API provides an + ExceptionListener interface to deal with this + situation. When the client runtime of the JMS provider detects a + lost connection to the JMS server, it calls the + onException() method of the registered + ExceptionListener. Once notified of the problem, + client code can attempt to reestablish the connection. According + to the section 4.3.8 of the JMS specification, the provider should + attempt to resolve connection problems prior to notifying the + client. The JMS appenders do not implement the + ExceptionListener interface. +

+ + +

JMSTopicAppender

+ +

+ The + JMSTopicAppender acts as a message producer to a publish and subscribe + Topic. +

+ +

+ Its most important method, doAppend() is listed below: +

+ +
public void append(ILoggingEvent event) {
+  if (!isStarted()) {
+    return;
+  }
+
+  try {
+    ObjectMessage msg = topicSession.createObjectMessage();
+    Serializable so = pst.transform(event);
+    msg.setObject(event);
+    topicPublisher.publish(msg);
+    successiveFailureCount = 0;
+  } catch (Exception e) {
+    successiveFailureCount++;
+    if (successiveFailureCount > SUCCESSIVE_FAILURE_LIMIT) {
+      stop();
+    }
+      addError("Could not publish message in JMSTopicAppender [" + name + "].", e);
+  }
+}
+ +

+ The isStarted() method allows the appender to check + whether prerequisite conditions for its proper functioning, in + particular the availability of a valid and open + TopicConnection and a TopicSession, + are fulfilled. If that is not the case, the append method + returns without performing any work. If the prerequisite + conditions are fulfilled, then the method proceeds to publish + the logging event. This is done by obtaining a + javax.jms.ObjectMessage from the + TopicSession and then setting its payload to the + logging event received as the input parameter. Once the payload + of the message is set, it is published. Note that the + ILoggingEvent is transformed to a serializable + object by a PreSerializationTransformer. Only + Serializable objects can be transported within an + ObjectMessage. +

+ +

+ In summary, the JMSTopicAppender broadcasts messages consisting + of a serialized LoggingEvent payload over a user-specified + JMS topic. These events can be processed by a + + JMSTopicSink + or a similar consumer. According to JMS specification, the provider + will asynchronously call the onMessage() of duly registered + and subscribed javax.jms.MessageListener objects. + The onMessage() method in JMSTopicSink + is implemented as follows: +

+ +
public void onMessage(javax.jms.Message message) {
+  ILoggingEvent event;
+  try {
+    if (message instanceof ObjectMessage) {
+      ObjectMessage objectMessage = (ObjectMessage) message;
+      event = (ILoggingEvent) objectMessage.getObject();
+      Logger log = (Logger) LoggerFactory.getLogger(event.getLoggerName());
+      log.callAppenders(event);
+    } else {
+      logger.warn("Received message is of type " + message.getJMSType()
+          + ", was expecting ObjectMessage.");
+    }
+  } catch (JMSException jmse) {
+    logger.error("Exception thrown while processing incoming message.", jmse);
+  }
+}
+ +

+ The onMessage() method begins by retrieving the logging event's payload. + It then obtains a Logger with the same name as the logger name of the incoming event. + The event is then logged through this logger as if it were generated locally, + by calling its callAppenders() method. The SocketNode class used by + SimpleSocketServer handles incoming logging events essentially in the same way. +

+ +

+ Some properties are proper to JMSTopicAppender. They are + listed below. +

+ + + + + + + + + + + + + + + + + +
Property NameTypeDescription
TopicConnectionFactoryBindingNameString +

+ The name of the topic factory. There is no default value for this mandatory option. +

+
TopicBindingNameString +

+ The name of the topic to use. There is no default value for this mandatory option. +

+
+ +

+ JMSTopicAppender is rather straightforward to configure: +

+ + Example 4.: JMSTopicAppender configuration (logback-examples/src/main/java/chapter4/conf/logback-JMSTopic.xml) +
<configuration>
+
+  <appender name="Topic"
+    class="ch.qos.logback.classic.net.JMSTopicAppender">
+    <InitialContextFactoryName>
+      org.apache.activemq.jndi.ActiveMQInitialContextFactory
+    </InitialContextFactoryName>
+    <ProviderURL>tcp://localhost:61616</ProviderURL>
+    <TopicConnectionFactoryBindingName>
+      ConnectionFactory
+    </TopicConnectionFactoryBindingName>
+    <TopicBindingName>MyTopic</TopicBindingName>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="Topic" />
+  </root>
+</configuration>
+ + +

JMSQueueAppender

+ +

+ The + JMSQueueAppender acts as a message producer to a point-to-point + Queue. +

+ +

+ It works in a very similar manner to the JMSTopicAppender. +

+ +

+ Some properties are proper to JMSQueueAppender. They are + listed below. +

+ + + + + + + + + + + + + + + + + +
Property NameTypeDescription
QueueConnectionFactoryBindingNameString +

+ The name of the queue factory. There is no default value for this mandatory option. +

+
QueueBindingNameString +

+ The name of the queue to use. There is no default value for this mandatory option. +

+
+ +

+ A typical JMSQueueAppender configuration file looks very + similar to that of a JMSTopicAppender. +

+ Example 4.: JMSQueueAppender configuration (logback-examples/src/main/java/chapter4/conf/logback-JMSQueue.xml) +
<configuration>
+
+  <appender name="Queue"
+    class="ch.qos.logback.classic.net.JMSQueueAppender">
+    <InitialContextFactoryName>
+      org.apache.activemq.jndi.ActiveMQInitialContextFactory
+    </InitialContextFactoryName>
+    <ProviderURL>tcp://localhost:61616</ProviderURL>
+    <QueueConnectionFactoryBindingName>
+      ConnectionFactory
+    </QueueConnectionFactoryBindingName>
+    <QueueBindingName>MyQueue</QueueBindingName>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="Queue" />
+  </root>
+</configuration>
+ +

SMTPAppender

+ +

The SMTPAppender + accumulates logging events in a fixed-size buffer and sends them in + an email after a user-specified event occurs. By default, the + email transmission is triggered by a logging event of level ERROR + or higher. +

+ +

The various properties for SMTPAppender are + summarized in the following table. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Property NameTypeDescription
SMTPHostStringThe host name of the SMTP server. This parameter is mandatory.
SMTPPortintThe port where the SMTP server is listening. Defaults to + 25.
ToStringThe email address of the recipient. Multiple recipients + can be specified by using several <To> elements.
FromStringThe stated originator of the email messages sent by + SMTPAppender. +
SubjectString +

The subject of the email. It can be any value accepted as + a valid conversion pattern by PatternLayout. Layouts + will be discussed in the next chapter. +

+ +

The outgoing email message will have a subject line + corresponding to applying the pattern on the logging event + that triggered the email message. +

+ +

Assuming the Subject option + is set to "Log: %logger - %msg" and the triggering event's + logger is named "com.foo.Bar", and contains the message + "Hello world", then the outgoing email will have the subject + line "Log: com.foo.Bar - Hello World". +

+ +

By default, this option is set to "%logger{20} - %m".

+
BufferSizeint + The BufferSize option takes a + positive integer representing the maximum number of logging + events to collect in a cyclic buffer. When the BufferSize is reached, oldest events + are deleted as new events are added to the buffer. The + default size of the cyclic buffer is 512. +
EvaluatorString +

This option is declared by creating a new + <EventEvaluator/> element. The name of the + class that the user wishes to use as the + SMTPAppender's Evaluator can needs + to be specified via the class + attribute. +

+ + +

In the absence of this option, SMTPAppender + is assigned an OnErrorEveluator + instance which triggers email transmission when it + encounters an event of level ERROR or higher. +

+ + + +

You can find more information on event evaluators further + down this document. +

+ +
UsernameString The username value to use + during plain user/password authentication. By default, this + parameter is null.
PasswordString The password value to use for + plain user/password authentication. By default, this parameter + is null.
STARTTLSboolean If this parameter is set to + true, then this appender will issue the STARTTLS command (if + the server supports it) causing the connection to switch to + SSL. Note that the connection is initially non-encrypted. By + default, this parameter is set to false.
SSLboolean If this parameter is set to + true, then this appender will open an SSL connection to the + server. By default, this parameter is set to false.
CharsetEncodingStringThe outgoing email message will be encoded in the + designated charset. The + default charset encoding is "UTF-8" which works well for most + purposes. +
+ +

The SMTPAppender keeps only the last BufferSize logging events in its cyclic + buffer, throwing away older events when its buffer becomes full. + Thus, the number of logging events delivered in any e-mail sent by + SMTPAppender is upper-bounded by BufferSize. This keeps memory requirements + bounded while still delivering a reasonable amount of application + context. +

+ +

The SMTPAppender relies on the JavaMail API. It + has been tested with JavaMail API version 1.4. The JavaMail API + requires the JavaBeans Activation Framework package. You can + download the JavaMail API and + the Java-Beans + Activation Framework from their respective websites. Make + sure to place these two jar files in the classpath before trying + the following examples. +

+ + +

A sample application, chapter4.mail.EMail + generates a number of log messages messages followed by a single + error message. It takes two parameters. The first parameter is an + integer corresponding to the number of logging events to + generate. The second parameter is the logback configuration + file. The last logging event generated by EMail + application, an ERROR, will trigger the transmission of an email + message. +

+ +

Here is a sample configuration file intended for the + Email application: +

+ + Example 4.: A sample SMTPAppender configuration (logback-examples/src/main/java/chapter4/mail/mail1.xml) +
<configuration>	  
+  <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
+    <SMTPHost>ADDRESS-OF-YOUR-SMTP-HOST</SMTPHost>
+    <To>EMAIL-DESTINATION</To>
+    <To>ANOTHER_EMAIL_DESTINATION</To> <!-- additional destinations are possible -->
+    <From>SENDER-EMAIL</From>
+    <Subject>TESTING: %logger{20} - %m</Subject>
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%date %-5level %logger{35} - %message%n</Pattern>
+    </layout>	    
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="EMAIL" />
+  </root>  
+</configuration>
+ +

Before trying out chapter4.mail.Email application + with the above configuration file, you must set the SMTPHost, To and + From properties to values appropriate for + your environment. Once you have set the correct values in the + configuration file, execute the following command: +

+ +
java chapter4.mail.EMail 300 src/main/java/chapter4/mail/mail.xml
+ +

The recipient you specified should receive an email message + containing 300 logging events formatted by + PatternLayout The figure below is the resulting email + message as shown by Mozilla Thunderbird. +

+ +

resulting email

+ +

In the next example configuration file mail2.xml, the + values for the SMTPHost, To and From + properties are determined by variable substitution. Here is the + relevant part of mail2.xml. +

+ +
<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
+  <SMTPHost>${smtpHost}</SMTPHost>
+  <To>${to}</To>
+  <From>${from}</From>
+  <layout class="ch.qos.logback.classic.html.HTMLLayout"/>
+</appender>
+ +

You can pass the required parameters on the command line:

+ +
java -Dfrom=source@xyz.com -Dto=recipient@xyz.com -DsmtpHost=some_smtp_host \
+  src/main/java/chapter4.mail.EMail 10000 chapter4/mail/mail2.xml
+
+ +

Be sure to replace with values as appropriate for your + environment. +

+ +

Note that in this latest example, PatternLayout + was replaced by HTMLLayout which formats logs as an + HTML table. You can change the list and order of columns as well + as the CSS of the table. Please refer to HTMLLayout documentation + for further details. +

+ +

Given that the default size of the cyclic buffer is 512, the + recipient should see an email message containing 512 events + conveniently formatted in an HTML table. Note that this run of the + chapter4.mail.Email application generated 10'000 + events of which only the last 512 were included in the outgoing + email. +

+ +

2nd email

+ +

Email clients such as Mozilla Thunderbird, Eudora or MS + Outlook, offer reasonably good CSS support for HTML email. + However, they sometimes automatically downgrade HTML to + plaintext. For example, to view HTML email in Thunderbird, the + "View→Message Body As→Original HTML" option + must be set. Yahoo!Mail's support for HTML email, in particular + its CSS support is very good. GMail on the other hand, while it + honors the basic HTML table structure, ignores the internal CSS + formatting. Gmail supports inline CSS formatitng but since inline + CSS would make the resulting output too voluminous, + HTMLLayout does not use inline CSS. +

+ +

Triggering event

+ +

By default, the SMTPAppender will initiate the + transmission of an email message as a response to an event of + level ERROR or higher. However, it is possible to + override this default behavior by providing a custom + implementation of the EventEvaluator interface. +

+ +

The SMTPAppender submits each incoming event to + its evaluator by calling evaluate() method in order + to check whether the event should trigger an email or just be + placed in the cyclic buffer. When the evaluator gives a positive + answer to its evaluation, an email is sent. The + SMTPAppender contains one and only one evaluator + object. This object may possess its own state. For illustrative + purposes, the CounterBasedEvaluator class listed + next, implements an event evaluator whereby every 1024th event + triggers an email message. +

+ +Example 4.: A EventEvaluator implementation +that evaluates to true every 1024th event (logback-examples/src/main/java/chapter4/mail/CounterBasedEvaluator.java) +
package chapter4.mail;
+
+import ch.qos.logback.core.boolex.EvaluationException;
+import ch.qos.logback.core.boolex.EventEvaluator;
+import ch.qos.logback.core.spi.ContextAwareBase;
+
+public class CounterBasedEvaluator extends ContextAwareBase implements EventEvaluator {
+
+  static int LIMIT = 1024;
+  int counter = 0;
+  String name;
+
+  public boolean evaluate(Object event) throws NullPointerException,
+      EvaluationException {
+    counter++;
+
+    if (counter == LIMIT) {
+      counter = 0;
+
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+}
+ +

+ Note that this implementation extends ContextAwareBase and + implements EventEvaluator. This allows the user to concentrate + on the core functions of her EventEvaluator and let the base class + provide the common functionality. +

+ +

+ Setting the EventEvaluator option of + SMTPAppender instructs it to use a custom evaluator. + The next configuration file attaches a SMTPAppender to the root logger. + This appender has a buffer size of 2048 and uses a CounterBasedEvaluator instance + as its event evaluator. +

+ +Example 4.: SMTPAppender with custom +Evaluator and buffer size (logback-examples/src/main/java/chapter4/mail/mail3.xml) + +
<configuration>
+  <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
+    <Evaluator class="chapter4.mail.CounterBasedEvaluator" />
+    <BufferSize>1050</BufferSize>
+    <SMTPHost>${smtpHost}</SMTPHost>
+    <To>${to}</To>
+    <From>${from}</From>
+    <layout class="ch.qos.logback.classic.html.HTMLLayout"/>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="EMAIL" />
+  </root>  
+</configuration>
+ + +

Authentication/STARTTLS/SSL

+ +

SMTPAppender supports authentication via plain + user passwords as well as both the STARTTLS and SSL + protocols. Note that STARTTLS differs from SSL in that, in + STARTTLS, the connection is initially non-encrypted and only after + the STARTTLS command is issued by the client (if the server + supports it) does the connection switch to SSL. In SSL mode, the + connection is encrypted right from the start. +

+ +

SMTPAppender configuration + for Gmail (SSL)

+ +

The next example shows you how to configure + SMTPAppender for Gmail with the SSL protocol.

+ + Example 4.: SMTPAppender to Gmail using SSL (logback-examples/src/main/java/chapter4/mail/gmailSSL.xml) + +
<configuration>
+  <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
+    <SMTPHost>smtp.gmail.com</SMTPHost>
+    <SMTPPort>465</SMTPPort>
+    <SSL>true</SSL>
+    <Username>YOUR_USERNAME@gmail.com</Username>
+    <Password>YOUR_GMAIL_PASSWORD</Password>
+
+    <To>EMAIL-DESTINATION</To>
+    <To>ANOTHER_EMAIL_DESTINATION</To> <!-- additional destinations are possible -->
+    <From>YOUR_USERNAME@gmail.com</From>
+    <Subject>TESTING: %logger{20} - %m</Subject>
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%date %-5level %logger{35} - %message%n</Pattern>
+    </layout>	    
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="EMAIL" />
+  </root>  
+</configuration>
+ + +

SMTPAppender for Gmail + (STARTTLS)

+ +

The next example shows you how to configure + SMTPAppender for Gmail for the STARTTLS protocol.

+ + Example 4.: SMTPAppender to GMAIL using STARTTLS (logback-examples/src/main/java/chapter4/mail/gmailSTARTTLS.xml) + +
<configuration>	  
+  <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
+    <SMTPHost>smtp.gmail.com</SMTPHost>
+    <SMTPPort>587</SMTPPort>
+    <STARTTLS>true</STARTTLS>
+    <Username>YOUR_USERNAME@gmail.com</Username>
+    <Password>YOUR_GMAIL_xPASSWORD</Password>
+    
+    <To>EMAIL-DESTINATION</To>
+    <To>ANOTHER_EMAIL_DESTINATION</To> <!-- additional destinations are possible -->
+    <From>YOUR_USERNAME@gmail.com</From>
+    <Subject>TESTING: %logger{20} - %m</Subject>
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%date %-5level %logger - %message%n</Pattern>
+    </layout>	    
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="EMAIL" />
+  </root>  
+</configuration>
+ + + +

+ DBAppender +

+ +

The DBAppender + inserts logging events into three database tables in a format + independent of the Java programming language. +

+ +

These three tables are logging_event, + logging_event_property and + logging_event_exception. They must exist before + DBAppender can be used. Logback ships with SQL + scripts that will create the tables. They can be found in the + found in the + logback-classic/src/main/java/ch/qos/logback/classic/db/dialect + directory. There is a specific script for each of the most popular + database systems. If the script for your particular type of + database system is missing, it should be quite easy to write one, + taking example on the already existing scripts. If you send them + to us, we will gladly include missing scripts in future releases. +

+ +

If your JDBC driver supports the getGeneratedKeys + method introduced in JDBC 3.0 specification, assuming you have + created the appropriate database tables as mentioned above, then + no more steps are required, excluding the usual logback + configuration. +

+ +

Otherwise, there must be an SQLDialect appropriate + for your database system. Currently, we have dialects for + PostgreSQL, MySQL, Oracle and MS SQL Server.

+ +

The table below summarizes the database types and their support + of the getGeneratedKeys() method. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RDBMStested version(s) + tested JDBC driver version(s) + + supports +
+ getGeneratedKeys() + method +
DB2untesteduntestedunknown
HSQL1.8.0.7-NO
Microsoft SQL Server20052.0.1008.2 (sqljdbc.jar)YES
MySQL5.0.225.0.8 (mysql-connector.jar)YES
PostgreSQL + + NO
Oracle10g10.2.0.1 (ojdbc14.jar)YES (10.2.0.1)
+ +

Experiments show that writing a single event into the database + takes approximately 10 milliseconds, on a "standard" PC. If pooled + connections are used, this figure drops to around 1 + millisecond. Note that most JDBC drivers already ship with + connection pooling support. +

+ +

Configuring logback to use DBAppender can be done + in several different ways, depending on the tools one has to + connect to the database, and the database itself. The key issue in + configuring DBAppender is about setting its + ConnectionSource object, as we shall discover + shortly. +

+ +

Once logback is configured properly, the logging events are + sent to the specified database. As stated previously, there are + three tables used by logback to store logging event data. +

+ +

+ The logging_event table contains the following fields: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
timestampbig intThe timestamp that was valid at the logging event's creation.
formatted_messagetextThe message that has been added to the logging event, + after formatting with + org.slf4j.impl.MessageFormatter, in case objects + were passed along with the message.
logger_namevarcharThe name of the logger used to issue the logging request.
level_stringvarcharThe level of the logging event.
reference_flagsmallint +

This field is used by logback to identify logging events + that have an exception or MDCproperty values + associated. +

+ +

Its value is computed by + ch.qos.logback.classic.db.DBHelper. A logging + event that contains MDC or Context + properties has a flag number of 1. One that + contains an exception has a flag number of 2. A + logging event that contains both elements has a flag number + of 3. +

+
caller_filenamevarcharThe name of the file where the logging request was issued.
caller_classvarcharThe class where the logging request was issued.
caller_methodvarcharThe name of the method where the logging request was issued.
caller_linecharThe line number where the logging request was issued.
event_idintThe database id of the logging event.
+ +

+ The logging_event_property is used to store the keys and values + contained in the MDC or the Context. + It contains these fields: +

+ + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
event_idintThe database id of the logging event.
mapped_keyvarcharThe key of the MDC property
mapped_valuetextThe value of the MDC property
+ +

+ The logging_event_exception table contains the following fields: +

+ + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
event_idintThe database id of the logging event.
ismallintThe index of the line in the full stack trace.
trace_linevarcharThe corresponding line
+ +

+ To give a more visual example of the work done by DBAppender, here + is a screenshot of a MySQL database with content provided by DBAppender. +

+ +

The logging_event table:

+ + Logging Event table + +

The logging_event_exception table:

+ + Logging Event Exception table + +

The logging_event_property table:

+ + Logging Event Property table + + +

ConnectionSource

+ +

The ConnectionSource interface provides a + pluggable means of transparently obtaining JDBC connections for + logback classes that require the use of a + java.sql.Connection. There are currently three + implementations of ConnectionSource, namely + DataSourceConnectionSource, + DriverManagerConnectionSource and + JNDIConnectionSource. +

+ +

+ The first example that we will review is a configuration using + DriverManagerConnectionSource and a MySQL database. + The following configuration file is what one would need. +

+ +Example 4.: DBAppender configuration (logback-examples/src/main/java/chapter4/db/append-toMySQL-with-driverManager.xml) +
<configuration>
+
+  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
+    <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
+      <driverClass>com.mysql.jdbc.Driver</driverClass>
+      <url>jdbc:mysql://host_name:3306/datebase_name</url>
+      <user>username</user>
+      <password>password</password>
+    </connectionSource>
+  </appender>
+  
+  <root level="debug" >
+    <appender-ref ref="DB" />
+  </root>
+</configuration>
+ +

+ The correct driver must be declared. Here, the com.mysql.jdbc.Driver + class is used. The url must begin with jdbc:myslq://. +

+ +

+ The + + DriverManagerConnectionSource is an implementation of + ConnectionSource that obtains the connection in the + traditional JDBC manner based on the connection URL. +

+

+ Note that this class will establish a new Connection for + each call to getConnection(). It is recommended + that you either use a JDBC driver that natively supports + connection pooling or that you create your own + implementation of ConnectionSource that taps into + whatever pooling mechanism you are already using. (If you + have access to a JNDI implementation that supports + javax.sql.DataSource, e.g. within a J2EE application + server, see JNDIConnectionSource). +

+ + +

+ Connecting to a database using a DataSource is rather similar. + The configuration now uses + + DataSourceConnectionSource, + which is an implementation of ConnectionSource that obtains the + Connection in the recommended JDBC manner based on a + javax.sql.DataSource. +

+ +Example 4.: DBAppender configuration (logback-examples/src/main/java/chapter4/db/append-with-datasource.xml) +
<configuration>
+
+  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
+     <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
+       
+       <dataSource class="${dataSourceClass}">
+       	 <!-- Joran cannot substitute variables
+       	 that are not attribute values. Therefore, we cannot
+       	 declare the next parameter like the others. 
+       	 -->
+         <param name="${url-key:-url}" value="${url_value}"/>
+         <serverName>${serverName}</serverName>
+         <databaseName>${databaseName}</databaseName>
+       </dataSource>
+       
+       <user>${user}</user>
+       <password>${password}</password>
+     </connectionSource>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="DB" />
+  </root>  
+</configuration>
+ +

+ Not that in this configuration sample, we make heavy use of substitution variables. + They are sometimes handy when connection details have to be centralized in a + single configuration file and shared by logback and other frameworks. +

+ + + +

+ The third implementation of ConnectionSource that is shipped with + logback is the JNDIConnectionSource. +

+ +

+ The + + JNDIConnectionSource + is an implementation of ConnectionSource that + obtains a javax.sql.DataSource from a JNDI provider + and uses it to obtain a java.sql.Connection. It is + primarily designed to be used inside of J2EE application + servers or application server clients, assuming the + application server supports remote access of javax.sql.DataSource. + In this way one can take advantage of connection pooling and whatever other goodies the + application server provides. +

+ +
<connectionSource class="ch.qos.logback.core.db.JNDIConnectionSource">
+  <param name="jndiLocation" value="jdbc/MySQLDS" />
+  <param name="username" value="myUser" />
+  <param name="password" value="myPassword" />
+</connectionSource>
+ +

+ Note that this class will obtain an + javax.naming.InitialContext + using the no-argument constructor. This will usually work + when executing within a J2EE environment. When outside the + J2EE environment, make sure that you provide a + jndi.properties + file as described by your JNDI provider's documentation. +

+ +

Connection pooling

+ +

+ Logging events can be created at a rather fast pace. To keep up + with the flow of events that must be inserted into a database, + it is recommended to use connection pooling with + DBAppender. +

+ +

+ Experiment shows that using connection pooling with DBAppender + gives a big performance boost. With the following + configuration file, logging events are sent to a MySQL database, + without any pooling. +

+ + Example 4. DBAppender configuration without pooling (logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource.xml) +
<configuration>
+
+  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
+    <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
+      <dataSource class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
+        <serverName>${serverName}</serverName>
+        <port>${port$</port>
+        <databaseName>${dbName}</databaseName>
+        <user>${user}</user>
+        <password>${pass}</password>
+      </dataSource>
+    </connectionSource>
+  </appender>
+    
+  <root level="debug">
+    <appender-ref ref="DB" />
+  </root>
+</configuration
+ +

With this configuration file, sending 500 logging events to a + MySQL database takes a whopping 5 seconds, that is 10 milliseconds + per request. This figure is unacceptable when dealing with large + applications. +

+ +

A dedicated external library is necessary to use connection + pooling with DBAppender. The next example uses c3p0. To be able + to use c3p0, one must download it and place + c3p0-VERSION.jar in the classpath. +

+ + Example 4.: DBAppender configuration with pooling (logback-examples/src/main/java/chapter4/db/append-toMySQL-with-datasource-and-pooling.xml) +
<configuration>
+
+  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
+    <connectionSource
+      class="ch.qos.logback.core.db.DataSourceConnectionSource">
+      <dataSource
+        class="com.mchange.v2.c3p0.ComboPooledDataSource">
+        <driverClass>com.mysql.jdbc.Driver</driverClass>
+        <jdbcUrl>jdbc:mysql://${serverName}:${port}/${dbName}</jdbcUrl>
+        <user>${user}</user>
+        <password>${password}</password>
+      </dataSource>
+    </connectionSource>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="DB" />
+  </root>
+</configuration>
+ +

With this new configuration, sending 500 logging requests to + the aforementioned MySQL database takes around 0.5 seconds, for an + average of 1 millisecond per request, that is a tenfold + improvement in performance. +

+ +

SyslogAppender +

+ +

The syslog protocol is a very simple protocol: a syslog sender + sends a small message to a syslog receiver. The receiver is + commonly called syslog daemon or syslog server. + Logback can send messages to a remote syslog daemon. This is + achieved by using SyslogAppender. +

+ +

Here are the properties you can pass to a SyslogAppender.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Property NameTypeDescription
+ + SyslogHost + + + String + + The host name of the syslog server. +
+ + Port + + + String + + The port number on the syslog server to connect to. Normally, one would not want + to change the default value, that is 514. +
+ + Facility + + + String + +

+ The Facility is meant to identify + the source of a message. +

+

+ The Facility option must be set one + of the strings KERN, USER, MAIL, DAEMON, AUTH, SYSLOG, LPR, NEWS, UUCP, + CRON, AUTHPRIV, FTP, NTP, AUDIT, ALERT, CLOCK, LOCAL0, LOCAL1, LOCAL2, + LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. Case is not important. +

+
+ + SuffixPattern + + + String + +

The SuffixPattern option + specifies the format of the non-standardized part of the + message sent to the syslog server. By default, its value is + [%thread] %logger %msg. Any value that a + PatternLayout could use is a correct SuffixPattern value. +

+
+ +

+ The syslog severity of a logging event is converted from the level of the logging event. + The DEBUG level is converted to 7, INFO is converted to + 6, WARN is converted to 4 and ERROR is converted + to 3. +

+ +

+ Since the format of a syslog request follows rather strict rules, there is no layout + to be used with SyslogAppender. However, the using the + SuffixPattern option lets the user display whatever + information she wishes. +

+ +

+ Here is a sample configuration using a SyslogAppender. +

+ +Example 4.: SyslogAppender configuration (logback-examples/src/main/java/chapter4/conf/logback-syslog.xml) +
<configuration>
+
+  <appender name="SYSLOG"
+    class="ch.qos.logback.classic.net.SyslogAppender">
+    <SyslogHost>remote_home</SyslogHost>
+    <Facility>AUTH</Facility>
+    <SuffixPattern>[%thread] %logger %msg</SuffixPattern>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

When testing this configuration, you should verify that the + remote syslog daemon accepts requests from an external + source. Experience shows that, by default, syslog daemons usually + deny requests coming via a network connection. +

+ + +

SiftingAppender

+ +

As its name implies, a SiftingAppender can be used + to separate (or sift) logging according to a given runtime + attribute. For example, SiftingAppender can separate + logging events according to user sessions, so that the logs + generated by every user go into distinct log files, one log file + per user. For example, SiftingAppender can separate + logging events into distinct log files, one file per user. +

+ + +

SiftingAppender embeds and manages multiple + appenders which it builds dynamically depending on discriminating + values. The built appender is specified in a configuration file + within the SiftingAppender definition itself. By + default, SiftingAppender uses MDC key/value pairs as + a discriminator. +

+ +

After configuring logback, the SiftExample + application logs a message stating that the application has + started. It then sets the MDC key "userid" to "Alice" and logs a + message. Here is the salient code:

+ +

logger.debug("Application started"); +MDC.put("userid", "Alice"); +logger.debug("Alice says hello");

+ +

The next configuration file illustrates the use of + SiftingAppender.

+ + + Example 4.: SiftingAppender + configuration + (logback-examples/src/main/java/chapter4/sift/byUserid.xml) + +
<configuration>
+
+  <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
+    <!-- in the absence of the class attribute, it is assumed that the
+         desired discriminator type is
+         ch.qos.logback.classic.sift.MDCBasedDiscriminator -->
+    <discriminator>
+      <Key>userid</Key>
+      <DefaultValue>unknown</DefaultValue>
+    </discriminator>
+    <sift>
+      <appender name="FILE-${userid}" class="ch.qos.logback.core.FileAppender">
+        <File>${userid}.log</File>
+        <Append>false</Append>
+        <layout class="ch.qos.logback.classic.PatternLayout">
+          <Pattern>%d [%thread] %level %mdc %logger{35} - %msg%n</Pattern>
+        </layout>
+      </appender>
+    </sift>
+  </appender>
+
+  <root level="DEBUG">
+    <appender-ref ref="SIFT" />
+  </root>
+</configuration>
+ + +

In the absence of a class attribute, it is assumed that the + discriminator type is MDCBasedDiscriminator. It + will use the MDC value associated with the Key property as a discriminator. If that + value is null, then the value associated with the DefaultValue property will be used. +

+ +

The SiftingAppender is unique in its capacity to + reference and configure nested appenders. In the above example, + within the SiftingAppender there will be nested + FileAppender instances, each instance identified by the value + associated with the "userid" MDC key. Whenever the "userid" MDC + key is assigned a new value, a new FileAppender + instance will be built from scratch. The SiftingAppender keeps + track of the appenders it creates. Appenders unused for 30 minutes + will be automatically closed and discarded. +

+ +

It is not enough to have different appender instances; each + instance must output to a distinct target resource. To allow such + differentiation, within the nested appender (FileAppender above), + the key passed to the discriminator, "userid" in the above + example, becomes a variable. Consequently, + this variable can be used to differentiate the actual resource + used by a given nested appender. +

+ +

Running the SiftExample application with the + "byUserid.xml" configuration file shown above, will result in two + distinct log files, "unknown.log" and "Alice.log". +

+ + +

Writing your own Appender

+ + +

You can easily write your appender by subclassing + AppenderBase. It handles support for filters, status + messages and other functionality shared by most appenders. The + derived class only needs to implement one method, namely + append(Object eventObject). +

+ +

The CountingConsoleAppender, which we list next, + appends a limited number of incoming events on the console. It + shuts down after the limit is reached. It uses a + Layout to format the events and accepts a parameter. + Thus, a few more methods are needed. +

+ + Example 4.: + CountingConsoleAppender + (logback-examples/src/main/java/chapter4/CountingConsoleAppender.java) +
package chapter4;
+
+import ch.qos.logback.core.AppenderBase;
+import ch.qos.logback.core.Layout;
+
+
+public class CountingConsoleAppender extends AppenderBase<ILoggingEvent> {
+  static int DEFAULT_LIMIT = 16;
+  int counter = 0;
+  int limit = DEFAULT_LIMIT;
+
+  public CountingConsoleAppender() {
+  }
+
+  public void setLimit(int limit) {
+    this.limit = limit;
+  }
+
+  public int getLimit() {
+    return limit;
+  }  
+  
+  @Override
+  public void start() {
+    if (this.layout == null) {
+      addError("No layout set for the appender named ["+ name +"].");
+      return;
+    }
+    
+    super.start();
+  }
+
+  public void append(ILoggingEvent event) {
+
+    if (counter >= limit) {
+      return;
+    }
+
+    // output the events as formatted by our layout
+    System.out.print(this.layout.doLayout(event));
+
+    // prepare for next event
+    counter++;
+  }
+
+}
+ +

The start() method checks for the presence of a + Layout. In case the layout is not set, the appender + fails to start with an error message. +

+ +

This custom appender illustrates two points:

+ +
    + +
  • All properties that follow the setter/getter JavaBeans + conventions are handled transparently. The start() + method, which is called automatically during logback + configuration, has the responsibility of verifying that the + various properties of the appender are coherent. +
  • + +
  • The AppenderBase.doAppend() method invokes the + append() method of its derived classes. Actual output + operations occur in the append() method. In + particular, it is in this method that appenders format events by + invoking their layouts. +
  • +
+ +

The CountingConsoleAppender + can be configured like any other appender. See sample + configuration file + logback-examples/src/main/java/chapter4/countingConsole.xml + for an example. +

+ + +

Logback + Access

+ +

Most of the appenders found in logback-classic have their + equivalent in logback-access. These work essentially in the same + way as their logback-classic counterparts. In the next section, we + will cover their use. +

+ + +

SocketAppender

+ +

The + SocketAppender is designed to log to a remote + entity by transmitting serialized AccessEvent objects + over the wire. Remote logging is non-intrusive as far as the + access event is concerned. On the receiving end after + deserialization, the event can be logged as if it were generated + locally. +

+

+ The properties of access' SocketAppender are the same as those available + for classic's SocketAppender. +

+ + +

SMTPAppender

+ +

+ Access' + SMTPAppender works in the same way as its Classic counterpart. + However, the evaluator option is rather different. + By default, a URLEvaluator object + is used by SMTPAppender. This evaluator contains a list of URLs that are + checked against the current request's URL. When one of the pages given to the + URLEvaluator is requested, SMTPAppender sends an email. +

+ +

+ Here is a sample configuration of a SMTPAppender in the access environment. +

+Example 4.: SMTPAppender configuration (logback-examples/src/main/java/chapter4/conf/access/logback-smtp.xml) +
<appender name="SMTP"
+  class="ch.qos.logback.access.net.SMTPAppender">
+  <layout class="ch.qos.logback.access.html.HTMLLayout">
+    <Pattern>%h%l%u%t%r%s%b</Pattern>
+  </layout>
+    
+  <Evaluator class="ch.qos.logback.access.net.URLEvaluator">
+    <URL>url1.jsp</URL>
+    <URL>directory/url2.html</URL>
+  </Evaluator>
+  <From>sender_email@host.com</From>
+  <SMTPHost>mail.domain.com</SMTPHost>
+  <To>recipient_email@host.com</To>
+</appender>
+ +

This way of triggering the email lets users select pages that + are important steps in a specific process, for example. When such + a page is accessed, the email is sent with the pages that were + accessed previously, and any information the user wants to be + included in the email. +

+ + + + +

DBAppender

+ +

+ DBAppender + is used to insert the access events into a database. +

+ +

Two tables are used by DBAppender: + access_event and access_event_header. They all + must exist before DBAppender can be used. Logback + ships with SQL scripts that will create the tables. They can be + found in the + logback-access/src/main/java/ch/qos/logback/access/db/dialect + directory. There is a specific script for each of the most popular + database systems. If the script for your particular type of + database system is missing, it should be quite easy to write one, + taking as example one of the existing scripts. You are encouraged + to contribute such missing scripts back to the project. +

+ +

The access_event table's fields are described below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
timestampbig intThe timestamp that was valid at the access event's creation.
requestURIvarcharThe URI that was requested.
requestURLvarcharThe URL that was requested. This is a string composed of the request method, + the request URI and the request protocol. +
remoteHostvarcharThe name of the remote host.
remoteUservarchar + The name of the remote user. +
remoteAddrvarcharThe remote IP address.
protocolvarcharThe request protocol, like HTTP or HTTPS.
methodvarcharThe request method, usually GET or POST.
serverNamevarcharThe name of the server that issued the request.
event_idintThe database id of the access event.
+ +

+ The access_event_header table contains the header of each + requests. The information is organised as shown below: +

+ + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
event_idintThe database id of the corresponding access event.
header_keyvarcharThe header name, for example User-Agent.
header_valuevarcharThe header value, for example Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.1) Gecko/20061010 Firefox/2.0
+ +

+ All properties of classic's DBAppender are available + in access' DBAppender. The latter offers one more option, + described below. +

+ + + + + + + + + + + + +
Property NameTypeDescription
+ + insertHeaders + + + boolean + + Tells the DBAppender to populate the database with the header + information of all incoming requests. +
+ +

+ Here is a sample configuration that uses DBAppender. +

+ + Example 4.: DBAppender configuration (logback-examples/src/main/java/chapter4/conf/access/logback-DB.xml) +
<configuration>
+
+  <appender name="DB" class="ch.qos.logback.access.db.DBAppender">
+    <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
+      <driverClass>com.mysql.jdbc.Driver</driverClass>
+      <url>jdbc:mysql://localhost:3306/logbackdb</url>
+      <user>logback</user>
+      <password>logback</password>
+    </connectionSource>
+    <insertHeaders>true</insertHeaders>
+  </appender>
+
+  <appender-ref ref="DB" />
+</configuration>
+ + +

SiftingAppender

+ +

The SiftingAppender in logback-access is quite similar to its + logback-classic counterpart. The main difference is that in + logback-access the default discriminator, namely AccessEventDiscriminator, + is not MDC based. As its name suggests, AccessEventDiscriminator, + uses a designated field in AccessEvent as basis for selecting a + nested appender. If the value of the designated field is null, + then the value specified in the DefaultValue property is used. +

+ +

The desginated AccessEvent field can be one of COOKIE, + REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, LOCAL_PORT, + REQUEST_URI. Note that the first three fields require that the + AdditionalKey property also be + specified.

+ +

Below is an example configuration file.

+ + Example 4.: SiftingAppender configuration (logback-examples/src/main/java/chapter4/conf/sift/access-siftingFile.xml) + +
<configuration>
+  <appender name="SIFTING" class="ch.qos.logback.access.sift.SiftingAppender">
+    <Discriminator class="ch.qos.logback.access.sift.AccessEventDiscriminator">
+      <Key>id</Key>
+      <FieldName>SESSION_ATTRIBUTE</FieldName>
+      <AdditionalKey>username</AdditionalKey>
+      <DefaultValue>NA</DefaultValue>
+    </Discriminator>
+    <sift>
+       <appender name="${id}" class="ch.qos.logback.core.FileAppender">
+        <File>byUser/${id}.log</File>
+        <layout class="ch.qos.logback.access.PatternLayout">
+          <Pattern>%h %l %u %t \"%r\" %s %b</Pattern>
+        </layout>
+      </appender>
+    </sift>
+  </appender>
+  <appender-ref ref="SIFTING" />
+</configuration>
+ + +

In the above configuration file, a SiftingAppender + nests FileAppender instances. The key "id" is + designated as a variable which will be availabe to the nested + FileAppender instances. The default discriminator, + namely AccessEventDiscriminator, will search for a + "username" session attribute in each AccessEvent. If + no such attribute is available, then the default value "NA" will + be used. Thus, assuming the session attribute named "username" + contains the username of each logged on user, there will be a log + file under the byUser/ folder (of the current folder) + named after each user containing the access logs for that user. +

+ + + + + +
+ + + diff --git a/logback-site/src/site/pages/manual/architecture.html b/logback-site/src/site/pages/manual/architecture.html index 6d353c3520b75236b2d28a569936ef211068f2d9..782d36a49548730bf3fd4ff6b9d5060a85982275 100644 --- a/logback-site/src/site/pages/manual/architecture.html +++ b/logback-site/src/site/pages/manual/architecture.html @@ -1,918 +1,918 @@ - - - - - - Chapter 2: Architecture - - - - - - - - - -
- - -
- -
- -

Chapter 2: Architecture

- -
-

All true classification is genealogical.

-

—CHARLES DARWIN, The Origin of Species

- -

It is difficult, if not impossible, for anyone to learn a - subject purely by reading about it, without applying the - information to specific problems and thereby forcing himself to - think about what has been read. Furthermore, we all learn best - the things that we have discovered ourselves. -

-

—DONALD KNUTH, The Art of Computer Programming

-
- - - - -

Logback's architecture

- -

Logback's basic architecture is sufficiently generic so as to + + + + + + Chapter 2: Architecture + + + + + + + + + +

+ + +
+ +
+ +

Chapter 2: Architecture

+ +
+

All true classification is genealogical.

+

—CHARLES DARWIN, The Origin of Species

+ +

It is difficult, if not impossible, for anyone to learn a + subject purely by reading about it, without applying the + information to specific problems and thereby forcing himself to + think about what has been read. Furthermore, we all learn best + the things that we have discovered ourselves. +

+

—DONALD KNUTH, The Art of Computer Programming

+
+ + + + +

Logback's architecture

+ +

Logback's basic architecture is sufficiently generic so as to apply under different circumstances. At the present time, logback is - divided into three modules, Core, Classic and Access. -

- -

The core module lays the groundwork for the other two - modules. The classic module extends core. The - classic module corresponds to a significantly improved version of - log4j. Logback-classic natively implements the SLF4J API so that you can readily - switch back and forth between logback and other logging systems - such as log4j or java.util.logging (JUL) introduced in JDK - 1.4. The third module called access integrates with - Servlet containers to provide HTTP-access log functionality. The - access module will be covered in a separate document. -

- -

In the reminder of this document, we will write "logback" to - refer to the logback-classic module. -

- -

Logger, Appenders and Layouts

- -

Logback is built upon three main classes: Logger, - Appender and Layout. These three types - of components work together to enable developers to log messages - according to message type and level, and to control at runtime how - these messages are formatted and where they are reported. -

- -

The Logger class is part of the logback-classic - module. On the other hand, the Appender and - Layout interfaces are part of logback-core. As a - general-purpose module, logback-core has no notion of - loggers. -

- -

Logger - context

- -

The first and foremost advantage of any logging API over plain - System.out.println resides in its ability to disable - certain log statements while allowing others to print - unhindered. This capability assumes that the logging space, that - is, the space of all possible logging statements, is categorized - according to some developer-chosen criteria. In logback-classic, - this categorization is an inherent part of loggers. Every single - loggers is attached to a LoggerContext which is - responsible for manufacturing loggers as well as arranging them in - a tree like hierarchy. -

- -

Loggers are named entities. Their names are case-sensitive and - they follow the hierarchical naming rule: -

- -
-
Named Hierarchy
-

- A logger is said to be an ancestor of another logger if - its name followed by a dot is a prefix of the descendant - logger name. A logger is said to be a parent of a child - logger if there are no ancestors between itself and the - descendant logger. -

-
- -

For example, the logger named "com.foo" is a - parent of the logger named "com.foo.Bar". Similarly, - "java" is a parent of "java.util" and an - ancestor of "java.util.Vector". This naming scheme - should be familiar to most developers. -

- -

The root logger resides at the top of the logger hierarchy. It - is exceptional in that it is part of every hierarchy at its - inception. Like every logger, it can be retrieved by its name, as - follows: -

- -
Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
- -

All other loggers are also retrieved with the class static - getLogger method found in the org.slf4j.LoggerFactory - class. This method takes the name of the desired logger as a - parameter. Some of the basic methods in the Logger - interface are listed below. -

- -
package org.slf4j; 
-public interface Logger {
-
-  // Printing methods: 
-  public void trace(String message);
-  public void debug(String message);
-  public void info(String message); 
-  public void warn(String message); 
-  public void error(String message); 
-}
- -

Loggers may be assigned levels. The set of possible levels, - that is TRACE, DEBUG, INFO, WARN and ERROR are defined in the - ch.qos.logback.classic.Level class. Note that in - logback, the level class is final and cannot be derived, as a much + divided into three modules, Core, Classic and Access. +

+ +

The core module lays the groundwork for the other two + modules. The classic module extends core. The + classic module corresponds to a significantly improved version of + log4j. Logback-classic natively implements the SLF4J API so that you can readily + switch back and forth between logback and other logging systems + such as log4j or java.util.logging (JUL) introduced in JDK + 1.4. The third module called access integrates with + Servlet containers to provide HTTP-access log functionality. The + access module will be covered in a separate document. +

+ +

In the reminder of this document, we will write "logback" to + refer to the logback-classic module. +

+ +

Logger, Appenders and Layouts

+ +

Logback is built upon three main classes: Logger, + Appender and Layout. These three types + of components work together to enable developers to log messages + according to message type and level, and to control at runtime how + these messages are formatted and where they are reported. +

+ +

The Logger class is part of the logback-classic + module. On the other hand, the Appender and + Layout interfaces are part of logback-core. As a + general-purpose module, logback-core has no notion of + loggers. +

+ +

Logger + context

+ +

The first and foremost advantage of any logging API over plain + System.out.println resides in its ability to disable + certain log statements while allowing others to print + unhindered. This capability assumes that the logging space, that + is, the space of all possible logging statements, is categorized + according to some developer-chosen criteria. In logback-classic, + this categorization is an inherent part of loggers. Every single + loggers is attached to a LoggerContext which is + responsible for manufacturing loggers as well as arranging them in + a tree like hierarchy. +

+ +

Loggers are named entities. Their names are case-sensitive and + they follow the hierarchical naming rule: +

+ +
+
Named Hierarchy
+

+ A logger is said to be an ancestor of another logger if + its name followed by a dot is a prefix of the descendant + logger name. A logger is said to be a parent of a child + logger if there are no ancestors between itself and the + descendant logger. +

+
+ +

For example, the logger named "com.foo" is a + parent of the logger named "com.foo.Bar". Similarly, + "java" is a parent of "java.util" and an + ancestor of "java.util.Vector". This naming scheme + should be familiar to most developers. +

+ +

The root logger resides at the top of the logger hierarchy. It + is exceptional in that it is part of every hierarchy at its + inception. Like every logger, it can be retrieved by its name, as + follows: +

+ +
Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
+ +

All other loggers are also retrieved with the class static + getLogger method found in the org.slf4j.LoggerFactory + class. This method takes the name of the desired logger as a + parameter. Some of the basic methods in the Logger + interface are listed below. +

+ +
package org.slf4j; 
+public interface Logger {
+
+  // Printing methods: 
+  public void trace(String message);
+  public void debug(String message);
+  public void info(String message); 
+  public void warn(String message); 
+  public void error(String message); 
+}
+ +

Loggers may be assigned levels. The set of possible levels, + that is TRACE, DEBUG, INFO, WARN and ERROR are defined in the + ch.qos.logback.classic.Level class. Note that in + logback, the level class is final and cannot be derived, as a much more flexible approach exists in the form of Marker - objects. -

- -

If a given logger is not assigned a level, then it inherits one - from its closest ancestor with an assigned level. More formally: -

- -
- - -

The effective level for a given logger L, is equal - to the first non-null level in its hierarchy, starting at - L itself and proceeding upwards in the hierarchy - towards the root logger. -

-
- -

To ensure that all loggers can eventually inherit a level, the - root logger always has an assigned level. By default, this level - is DEBUG. -

-

Below are four examples with various assigned level values and - the resulting effective (inherited) levels according to the level - inheritance rule. -

- - Example 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Logger nameAssigned levelEffective level
rootDEBUGDEBUG
XnoneDEBUG
X.YnoneDEBUG
X.Y.ZnoneDEBUG
- -

In example 1 above, only the root logger is assigned a level. - This level value, DEBUG, is inherited by the other - loggers X, X.Y and X.Y.Z -

- - Example 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Logger nameAssigned levelEffective level
rootERRORERROR
XINFOINFO
X.YDEBUGDEBUG
X.Y.ZWARNWARN
- -

In example 2 above, all loggers have an assigned level value. + objects. +

+ +

If a given logger is not assigned a level, then it inherits one + from its closest ancestor with an assigned level. More formally: +

+ +
+ + +

The effective level for a given logger L, is equal + to the first non-null level in its hierarchy, starting at + L itself and proceeding upwards in the hierarchy + towards the root logger. +

+
+ +

To ensure that all loggers can eventually inherit a level, the + root logger always has an assigned level. By default, this level + is DEBUG. +

+

Below are four examples with various assigned level values and + the resulting effective (inherited) levels according to the level + inheritance rule. +

+ + Example 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Logger nameAssigned levelEffective level
rootDEBUGDEBUG
XnoneDEBUG
X.YnoneDEBUG
X.Y.ZnoneDEBUG
+ +

In example 1 above, only the root logger is assigned a level. + This level value, DEBUG, is inherited by the other + loggers X, X.Y and X.Y.Z +

+ + Example 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Logger nameAssigned levelEffective level
rootERRORERROR
XINFOINFO
X.YDEBUGDEBUG
X.Y.ZWARNWARN
+ +

In example 2 above, all loggers have an assigned level value. Level inheritance does not come into play. -

- - Example 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Logger nameAssigned levelEffective level
rootDEBUGDEBUG
XINFOINFO
X.YnoneINFO
X.Y.ZERRORERROR
- -

In example 3 above, the loggers root, - X and X.Y.Z are assigned the levels - DEBUG, INFO and ERROR - respectively. Logger X.Y inherits its level value - from its parent X. -

- - Example 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Logger nameAssigned levelEffective level
rootDEBUGDEBUG
XINFOINFO
X.YnoneINFO
X.Y.ZnoneINFO
- - -

In example 4 above, the loggers root and - X and are assigned the levels DEBUG and - INFO respectively. The loggers X.Y and - X.Y.Z inherit their level value from their nearest - parent X, which has an assigned level. -

- -

Printing - methods and the basic selection rule

- -

By definition, the printing method determines the level of a - logging request. For example, if L is a logger - instance, then the statement L.info("..") is a - logging statement of level INFO. -

- - -

A logging request is said to be enabled if its level - is higher than or equal to the effective level of its - logger. Otherwise, the request is said to be disabled. As - described previously, a logger without an assigned level will - inherit one from its nearest ancestor. This rule is summarized - below. -

- - -
-
Basic Selection Rule
- -

A log request of level p issued to a logger having - an effective level q, is enabled if - p >= q. -

-
- -

This rule is at the heart of logback. It assumes that levels - are ordered as follows: - TRACE < DEBUG < INFO < -  WARN < ERROR. -

- -

In a more graphic way, here is how the selection rule works. In +

+ + Example 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Logger nameAssigned levelEffective level
rootDEBUGDEBUG
XINFOINFO
X.YnoneINFO
X.Y.ZERRORERROR
+ +

In example 3 above, the loggers root, + X and X.Y.Z are assigned the levels + DEBUG, INFO and ERROR + respectively. Logger X.Y inherits its level value + from its parent X. +

+ + Example 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Logger nameAssigned levelEffective level
rootDEBUGDEBUG
XINFOINFO
X.YnoneINFO
X.Y.ZnoneINFO
+ + +

In example 4 above, the loggers root and + X and are assigned the levels DEBUG and + INFO respectively. The loggers X.Y and + X.Y.Z inherit their level value from their nearest + parent X, which has an assigned level. +

+ +

Printing + methods and the basic selection rule

+ +

By definition, the printing method determines the level of a + logging request. For example, if L is a logger + instance, then the statement L.info("..") is a + logging statement of level INFO. +

+ + +

A logging request is said to be enabled if its level + is higher than or equal to the effective level of its + logger. Otherwise, the request is said to be disabled. As + described previously, a logger without an assigned level will + inherit one from its nearest ancestor. This rule is summarized + below. +

+ + +
+
Basic Selection Rule
+ +

A log request of level p issued to a logger having + an effective level q, is enabled if + p >= q. +

+
+ +

This rule is at the heart of logback. It assumes that levels + are ordered as follows: + TRACE < DEBUG < INFO < +  WARN < ERROR. +

+ +

In a more graphic way, here is how the selection rule works. In the following table, the vertical header shows the level of - the logging request, designated by p, while the - horizontal header shows effective level of the logger, designated - by q. The intersection of the rows (level request) and - columns (effective level) is the boolean resulting from the basic - selection rule. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
level of
request p
effective level q
TRACEDEBUGINFOWARNERROROFF
TRACEYESNONONONONO
DEBUGYESYESNONONONO
INFOYESYESYESNONONO
WARNYESYESYESYESNONO
ERRORYESYESYESYESYESNO
- -

Here is an example of the basic selection rule.

- -
// get a logger instance named "com.foo"
-Logger logger = LoggerFactory.getLogger("com.foo");
-//set its Level to INFO
-logger.setLevel(Level. INFO);
-Logger barlogger = LoggerFactory.getLogger("com.foo.Bar");
-
-// This request is enabled, because WARN >= INFO
-logger.warn("Low fuel level.");
-
-// This request is disabled, because DEBUG < INFO. 
-logger.debug("Starting search for nearest gas station.");
-
-// The logger instance barlogger, named "com.foo.Bar", 
-// will inherit its level from the logger named 
-// "com.foo" Thus, the following request is enabled 
-// because INFO >= INFO. 
-barlogger.info("Located nearest gas station.");
-
-// This request is disabled, because DEBUG < INFO. 
-barlogger.debug("Exiting gas station search");
- - -

Retrieving Loggers

-

- Calling the LoggerFactory.getLogger - method with the same name will always return a reference to - the exact same logger object. -

- -

For example, in

-
Logger x = LoggerFactory.getLogger("wombat"); 
-Logger y = LoggerFactory.getLogger("wombat");
- -

- x and y refer to - exactly the same logger object. -

- -

Thus, it is possible to configure a logger and then to retrieve - the same instance somewhere else in the code without passing - around references. In fundamental contradiction to biological - parenthood, where parents always preceed their children, logback - loggers can be created and configured in any order. In particular, - a "parent" logger will find and link to its descendants even if it - is instantiated after them. -

-

Configuration of the logback environment is typically done at - application initialization. The preferred way is by reading a - configuration file. This approach will be discussed shortly. -

-

Logback makes it easy to name loggers by software - component. This can be accomplished by instantiating a - logger in each class, with the logger name equal to the fully - qualified name of the class. This is a useful and straightforward - method of defining loggers. As the log output bears the name of - the generating logger, this naming strategy makes it easy to - identify the origin of a log message. However, this is only one - possible, albeit common, strategy for naming loggers. Logback does - not restrict the possible set of loggers. As a developer, you are - free to name loggers as you wish. -

- -

Nevertheless, naming loggers after the class where they are - located seems to be the best general strategy known so far. -

- - -

Appenders and Layouts

- -

The ability to selectively enable or disable logging requests - based on their logger is only part of the picture. Logback allows - logging requests to print to multiple destinations. In logback - speak, an output destination is called an appender. Currently, - appenders exist for the console, files, remote socket servers, to - MySQL, PostgreSQL, Oracle and other databases, JMS, and remote - UNIX Syslog daemons. - - -

- -

More than one appender can be attached to a logger.

- -

The addAppender - method adds an appender to a given logger. Each enabled logging - request for a given logger will be forwarded to all the appenders - in that logger as well as the appenders higher in the - hierarchy. In other words, appenders are inherited additively from - the logger hierarchy. For example, if a console appender is added - to the root logger, then all enabled logging requests will at - least print on the console. If in addition a file appender is - added to a logger, say L, then enabled logging requests - for L and L's children will print on a file - and on the console. It is possible to override this - default behavior so that appender accumulation is no longer - additive by setting the additivity flag of a logger to false. -

- -

The rules governing appender additivity are summarized below. -

-
- -
Appender Additivity
- -

The output of a log statement of logger L will go to - all the appenders in L and its ancestors. This is the - meaning of the term "appender additivity". -

- -

However, if an ancestor of logger L, say P, - has the additivity flag set to false, then L's output + the logging request, designated by p, while the + horizontal header shows effective level of the logger, designated + by q. The intersection of the rows (level request) and + columns (effective level) is the boolean resulting from the basic + selection rule. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
level of
request p
effective level q
TRACEDEBUGINFOWARNERROROFF
TRACEYESNONONONONO
DEBUGYESYESNONONONO
INFOYESYESYESNONONO
WARNYESYESYESYESNONO
ERRORYESYESYESYESYESNO
+ +

Here is an example of the basic selection rule.

+ +
// get a logger instance named "com.foo"
+Logger logger = LoggerFactory.getLogger("com.foo");
+//set its Level to INFO
+logger.setLevel(Level. INFO);
+Logger barlogger = LoggerFactory.getLogger("com.foo.Bar");
+
+// This request is enabled, because WARN >= INFO
+logger.warn("Low fuel level.");
+
+// This request is disabled, because DEBUG < INFO. 
+logger.debug("Starting search for nearest gas station.");
+
+// The logger instance barlogger, named "com.foo.Bar", 
+// will inherit its level from the logger named 
+// "com.foo" Thus, the following request is enabled 
+// because INFO >= INFO. 
+barlogger.info("Located nearest gas station.");
+
+// This request is disabled, because DEBUG < INFO. 
+barlogger.debug("Exiting gas station search");
+ + +

Retrieving Loggers

+

+ Calling the LoggerFactory.getLogger + method with the same name will always return a reference to + the exact same logger object. +

+ +

For example, in

+
Logger x = LoggerFactory.getLogger("wombat"); 
+Logger y = LoggerFactory.getLogger("wombat");
+ +

+ x and y refer to + exactly the same logger object. +

+ +

Thus, it is possible to configure a logger and then to retrieve + the same instance somewhere else in the code without passing + around references. In fundamental contradiction to biological + parenthood, where parents always preceed their children, logback + loggers can be created and configured in any order. In particular, + a "parent" logger will find and link to its descendants even if it + is instantiated after them. +

+

Configuration of the logback environment is typically done at + application initialization. The preferred way is by reading a + configuration file. This approach will be discussed shortly. +

+

Logback makes it easy to name loggers by software + component. This can be accomplished by instantiating a + logger in each class, with the logger name equal to the fully + qualified name of the class. This is a useful and straightforward + method of defining loggers. As the log output bears the name of + the generating logger, this naming strategy makes it easy to + identify the origin of a log message. However, this is only one + possible, albeit common, strategy for naming loggers. Logback does + not restrict the possible set of loggers. As a developer, you are + free to name loggers as you wish. +

+ +

Nevertheless, naming loggers after the class where they are + located seems to be the best general strategy known so far. +

+ + +

Appenders and Layouts

+ +

The ability to selectively enable or disable logging requests + based on their logger is only part of the picture. Logback allows + logging requests to print to multiple destinations. In logback + speak, an output destination is called an appender. Currently, + appenders exist for the console, files, remote socket servers, to + MySQL, PostgreSQL, Oracle and other databases, JMS, and remote + UNIX Syslog daemons. + + +

+ +

More than one appender can be attached to a logger.

+ +

The addAppender + method adds an appender to a given logger. Each enabled logging + request for a given logger will be forwarded to all the appenders + in that logger as well as the appenders higher in the + hierarchy. In other words, appenders are inherited additively from + the logger hierarchy. For example, if a console appender is added + to the root logger, then all enabled logging requests will at + least print on the console. If in addition a file appender is + added to a logger, say L, then enabled logging requests + for L and L's children will print on a file + and on the console. It is possible to override this + default behavior so that appender accumulation is no longer + additive by setting the additivity flag of a logger to false. +

+ +

The rules governing appender additivity are summarized below. +

+
+ +
Appender Additivity
+ +

The output of a log statement of logger L will go to + all the appenders in L and its ancestors. This is the + meaning of the term "appender additivity". +

+ +

However, if an ancestor of logger L, say P, + has the additivity flag set to false, then L's output will be directed to all the appenders in L and its ancestors up to and including P but not the appenders in - any of the ancestors of P. -

- -

Loggers have their additivity flag set to true by default. -

- -
- The table below shows an example: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Logger NameAttached AppendersAdditivity FlagOutput TargetsComment
rootA1not applicableA1Since the root logger stands at the top of the logger - hiearchy, the additivity flag does not apply to it. -
xA-x1, A-x2trueA1, A-x1, A-x2Appenders of "x" and of root.
x.ynonetrueA1, A-x1, A-x2Appenders of "x" and of root.
x.y.zA-xyz1trueA1, A-x1, A-x2, A-xyz1Appenders of "x.y.z", "x" and of root.
securityA-secfalseA-sec - No appender accumulation since the additivity flag is set to - false. Only appender A-sec will be used. -
security.accessnonetrueA-sec - Only appenders of "security" because the additivity - flag in "security" is set to - false. -
- - -

More often than not, users wish to customize not only the - output destination but also the output format. This is - accomplished by associating a layout with an - appender. The layout is responsible for formatting the logging - request according to the user's wishes, whereas an appender takes - care of sending the formatted output to its destination. The - PatternLayout, part of the standard logback - distribution, lets the user specify the output format according to - conversion patterns similar to the C language printf - function. -

- -

For example, the PatternLayout with the conversion pattern - "%-4relative [%thread] %-5level %logger{32} - %msg%n" will output - something akin to: -

- -
176  [main] DEBUG chapter2.HelloWorld2 - Hello world.
- -

The first field is the number of milliseconds elapsed since the - start of the program. The second field is the thread making the - log request. The third field is the level of the log request. The - fourth field is the name of the logger associated with the log - request. The text after the '-' is the message of the request. -

- - -

Parameterized logging

- -

Given that loggers in logback-classic implement the SLF4J's - Logger interface, certain printing methods admit more than one - parameter. These printing method variants are mainly intended to - improve performance while minimizing the impact on the readability - of the code. -

- -

For some Logger logger, writing,

- -
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
- -

incurs the cost of constructing the message parameter, that is - converting both integer i and entry[i] - to a String, and concatenating intermediate strings. This, - regardless of whether the message will be logged or not. -

- -

One possible way to avoid the cost of parameter construction is - by surrounding the log statement with a test. Here is an example. -

- -
if(logger.isDebugEnabled()) { 
-  logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
-}
- - -

This way you will not incur the cost of parameter construction - if debugging is disabled for logger. On the other - hand, if the logger is enabled for the DEBUG level, you will incur - the cost of evaluating whether the logger is enabled or not, - twice: once in debugEnabled and once in - debug. This is an insignificant overhead because - evaluating a logger takes less than 1% of the time it takes to - actually log a request. -

- -

Better alternative

- -

There exists a convenient alternative based on message - formats. Assuming entry is an object, you can write: -

- - -
Object entry = new SomeObject(); 
-logger.debug("The entry is {}.", entry);
- -

After evaluting whether to log or not, and only if the decision - is positive, will the logger implementation format the message and - replace the '{}' pair with the string value of entry. - In other words, this form does not incur the cost of parameter - construction in case the log statement is disabled. -

- - -

The following two lines will yield the exact same output. - However, in case of a disabled logging statement, the - second variant will outperform the first variant by a factor of at - least 30. -

- -
logger.debug("The new entry is "+entry+".");
-logger.debug("The new entry is {}.", entry);
- - -

A two argument variant is also availalble. For example, you can - write: -

- -
logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);
- -

If three or more arguments need to be passed, an - Object[] variant is also availalble. For example, you - can write: -

- - -
Object[] paramArray = {newVal, below, above};
-logger.debug("Value {} was inserted between {} and {}.", paramArray);
- - - + any of the ancestors of P. +

+ +

Loggers have their additivity flag set to true by default. +

+ +
+ The table below shows an example: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Logger NameAttached AppendersAdditivity FlagOutput TargetsComment
rootA1not applicableA1Since the root logger stands at the top of the logger + hiearchy, the additivity flag does not apply to it. +
xA-x1, A-x2trueA1, A-x1, A-x2Appenders of "x" and of root.
x.ynonetrueA1, A-x1, A-x2Appenders of "x" and of root.
x.y.zA-xyz1trueA1, A-x1, A-x2, A-xyz1Appenders of "x.y.z", "x" and of root.
securityA-secfalseA-sec + No appender accumulation since the additivity flag is set to + false. Only appender A-sec will be used. +
security.accessnonetrueA-sec + Only appenders of "security" because the additivity + flag in "security" is set to + false. +
+ + +

More often than not, users wish to customize not only the + output destination but also the output format. This is + accomplished by associating a layout with an + appender. The layout is responsible for formatting the logging + request according to the user's wishes, whereas an appender takes + care of sending the formatted output to its destination. The + PatternLayout, part of the standard logback + distribution, lets the user specify the output format according to + conversion patterns similar to the C language printf + function. +

+ +

For example, the PatternLayout with the conversion pattern + "%-4relative [%thread] %-5level %logger{32} - %msg%n" will output + something akin to: +

+ +
176  [main] DEBUG chapter2.HelloWorld2 - Hello world.
+ +

The first field is the number of milliseconds elapsed since the + start of the program. The second field is the thread making the + log request. The third field is the level of the log request. The + fourth field is the name of the logger associated with the log + request. The text after the '-' is the message of the request. +

+ + +

Parameterized logging

+ +

Given that loggers in logback-classic implement the SLF4J's + Logger interface, certain printing methods admit more than one + parameter. These printing method variants are mainly intended to + improve performance while minimizing the impact on the readability + of the code. +

+ +

For some Logger logger, writing,

+ +
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
+ +

incurs the cost of constructing the message parameter, that is + converting both integer i and entry[i] + to a String, and concatenating intermediate strings. This, + regardless of whether the message will be logged or not. +

+ +

One possible way to avoid the cost of parameter construction is + by surrounding the log statement with a test. Here is an example. +

+ +
if(logger.isDebugEnabled()) { 
+  logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
+}
+ + +

This way you will not incur the cost of parameter construction + if debugging is disabled for logger. On the other + hand, if the logger is enabled for the DEBUG level, you will incur + the cost of evaluating whether the logger is enabled or not, + twice: once in debugEnabled and once in + debug. This is an insignificant overhead because + evaluating a logger takes less than 1% of the time it takes to + actually log a request. +

+ +

Better alternative

+ +

There exists a convenient alternative based on message + formats. Assuming entry is an object, you can write: +

+ + +
Object entry = new SomeObject(); 
+logger.debug("The entry is {}.", entry);
+ +

After evaluting whether to log or not, and only if the decision + is positive, will the logger implementation format the message and + replace the '{}' pair with the string value of entry. + In other words, this form does not incur the cost of parameter + construction in case the log statement is disabled. +

+ + +

The following two lines will yield the exact same output. + However, in case of a disabled logging statement, the + second variant will outperform the first variant by a factor of at + least 30. +

+ +
logger.debug("The new entry is "+entry+".");
+logger.debug("The new entry is {}.", entry);
+ + +

A two argument variant is also availalble. For example, you can + write: +

+ +
logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);
+ +

If three or more arguments need to be passed, an + Object[] variant is also availalble. For example, you + can write: +

+ + +
Object[] paramArray = {newVal, below, above};
+logger.debug("Value {} was inserted between {} and {}.", paramArray);
+ + +

A peek under the hood

- -

After we have introduced the essential logback components, we are - now ready to describe the steps that the logback framework takes - when the user invokes a logger's printing method. Let us now analyze - the steps logback takes when the user invokes the - info() method of a logger named com.wombat. -

- -

1. Get the filter chain decision

- -

If it exists, the TurboFilter chain is - invoked. Turbo filters can set a context-wide threshold, or to - filter out certain events based on information such as - Marker, Level, Logger, - message, or the Throwable that are associated with each - logging request. If the reply of the filter chain is - FilterReply.DENY, then the logging request is - dropped. If it is FilterReply.NEUTRAL, then we continue - with the next step, i.e. step 2. In case the reply is - FilterReply.ACCEPT, we skip the next and directly jump - to step 3. -

- -

2. Apply the basic selection - rule

- -

At this step, logback compares the effective level of the logger - with the level of the request. If the logging request is disabled - according to this test, then logback will drop the request without - further processing. Otherwise, it proceeds to the next step. -

- -

3. Create a LoggingEvent object

- + +

After we have introduced the essential logback components, we are + now ready to describe the steps that the logback framework takes + when the user invokes a logger's printing method. Let us now analyze + the steps logback takes when the user invokes the + info() method of a logger named com.wombat. +

+ +

1. Get the filter chain decision

+ +

If it exists, the TurboFilter chain is + invoked. Turbo filters can set a context-wide threshold, or to + filter out certain events based on information such as + Marker, Level, Logger, + message, or the Throwable that are associated with each + logging request. If the reply of the filter chain is + FilterReply.DENY, then the logging request is + dropped. If it is FilterReply.NEUTRAL, then we continue + with the next step, i.e. step 2. In case the reply is + FilterReply.ACCEPT, we skip the next and directly jump + to step 3. +

+ +

2. Apply the basic selection + rule

+ +

At this step, logback compares the effective level of the logger + with the level of the request. If the logging request is disabled + according to this test, then logback will drop the request without + further processing. Otherwise, it proceeds to the next step. +

+ +

3. Create a LoggingEvent object

+

If the request survived the previous filters, logback will - create a ch.qos.logback.classic.LoggingEvent object - containing all the relevant parameters of the request, such as the - logger of the request, the request level, the message itself, the - exception that might have been passed along with the request, the - current time, the current thread, various data about the class that - issued the logging request and the MDC. Note that some - of these fields are initialized lazily, that is only when they are - actually needed. The MDC is used to decorate the - logging request with additional contextual information. MDC is - discussed in a subsequent chapter.

- -

4. Invoking appenders

- -

After the creation of a LoggingEvent object, logback - will invoke the doAppend() methods of all the - applicable appenders, that is, the appenders inherited from the - logger context. -

- -

All appenders shipped with the logback distribution extend the - AppenderBase abstract class that implements the - doAppend method in a synchronized block ensuring - thread-safety. The doAppend() method of - AppenderBase also invokes custom filters attached to - the appender, if any such filters exist. Custom filters, which can - be dynamically attached to any appender, are presented in a separate chapter. -

- -

5. Formatting the output

- -

It is responsibility of the invoked appender to format the - logging event. However, some (but not all) appenders delegate the - task of formatting the logging event to a layout. A layout formats - the LoggingEvent instance and returns the result as a - String. Note that some appenders, such as the - SocketAppender, do not transform the logging event into - a string but serialize it instead. Consequently, they do not - require nor have a layout. -

- -

6. Sending out the LoggingEvent

- -

After the logging event is fully formatted it is sent to its - destination by each appender. -

- -

- Here is a sequence UML diagram to show how everything works. You might - want to click on the image to display its bigger version. -

- - underTheHoodSequence2_small.gif - - -

Performance

- -

One of the often-cited arguments against logging is its - computational cost. This is a legitimate concern as even moderately - sized applications can generate thousands of log requests. Much - effort is spent measuring and tweaking logging performance. - Independently of these efforts, the user should still be aware of - the following performance issues. -

- -

1. Logging performance when logging is turned off entirely

- -

- You can turn off logging entirely by setting the level of the root logger - to Level.OFF, the highest possible level. - When logging is turned off entirely, - the cost of a log request consists of a method invocation plus an - integer comparison. On a 3.2Ghz Pentium D machine this cost is typically - around 20 nanoseconds. -

- -

- However, any method invocation involves the "hidden" cost of parameter construction. - For example, for some logger x writing, -

- -
x.debug("Entry number: " + i + "is " + entry[i]);
- -

- incurs the cost of constructing the message parameter, i.e. converting both - integer i and entry[i] to a string, and concatenating - intermediate strings, regardless of whether the message will be logged or not. -

- -

The cost of parameter construction can be quite high and depends - on the size of the parameters involved. To avoid the cost of + create a ch.qos.logback.classic.LoggingEvent object + containing all the relevant parameters of the request, such as the + logger of the request, the request level, the message itself, the + exception that might have been passed along with the request, the + current time, the current thread, various data about the class that + issued the logging request and the MDC. Note that some + of these fields are initialized lazily, that is only when they are + actually needed. The MDC is used to decorate the + logging request with additional contextual information. MDC is + discussed in a subsequent chapter.

+ +

4. Invoking appenders

+ +

After the creation of a LoggingEvent object, logback + will invoke the doAppend() methods of all the + applicable appenders, that is, the appenders inherited from the + logger context. +

+ +

All appenders shipped with the logback distribution extend the + AppenderBase abstract class that implements the + doAppend method in a synchronized block ensuring + thread-safety. The doAppend() method of + AppenderBase also invokes custom filters attached to + the appender, if any such filters exist. Custom filters, which can + be dynamically attached to any appender, are presented in a separate chapter. +

+ +

5. Formatting the output

+ +

It is responsibility of the invoked appender to format the + logging event. However, some (but not all) appenders delegate the + task of formatting the logging event to a layout. A layout formats + the LoggingEvent instance and returns the result as a + String. Note that some appenders, such as the + SocketAppender, do not transform the logging event into + a string but serialize it instead. Consequently, they do not + require nor have a layout. +

+ +

6. Sending out the LoggingEvent

+ +

After the logging event is fully formatted it is sent to its + destination by each appender. +

+ +

+ Here is a sequence UML diagram to show how everything works. You might + want to click on the image to display its bigger version. +

+ + underTheHoodSequence2_small.gif + + +

Performance

+ +

One of the often-cited arguments against logging is its + computational cost. This is a legitimate concern as even moderately + sized applications can generate thousands of log requests. Much + effort is spent measuring and tweaking logging performance. + Independently of these efforts, the user should still be aware of + the following performance issues. +

+ +

1. Logging performance when logging is turned off entirely

+ +

+ You can turn off logging entirely by setting the level of the root logger + to Level.OFF, the highest possible level. + When logging is turned off entirely, + the cost of a log request consists of a method invocation plus an + integer comparison. On a 3.2Ghz Pentium D machine this cost is typically + around 20 nanoseconds. +

+ +

+ However, any method invocation involves the "hidden" cost of parameter construction. + For example, for some logger x writing, +

+ +
x.debug("Entry number: " + i + "is " + entry[i]);
+ +

+ incurs the cost of constructing the message parameter, i.e. converting both + integer i and entry[i] to a string, and concatenating + intermediate strings, regardless of whether the message will be logged or not. +

+ +

The cost of parameter construction can be quite high and depends + on the size of the parameters involved. To avoid the cost of parameter construction you can take advantage of SLF4J's parameterized - logging: -

- -
x.debug("Entry number: {} is {}", i, entry[i]);
- -

- This variant will not incur the cost of parameter - construction. Compared to the previous call to the - debug() method, it will be faster by a very wide - margin. The message will be formatted only if the request is - processed to the appenders. If it is processed, the component - that formats the message offers high performance and does not - impact negatively the overall process. It respectively takes 2 - and 4 microseconds to format a message with 1 and 3 parameters. -

- -

Please notice that, despite the performance points that we just + logging: +

+ +
x.debug("Entry number: {} is {}", i, entry[i]);
+ +

+ This variant will not incur the cost of parameter + construction. Compared to the previous call to the + debug() method, it will be faster by a very wide + margin. The message will be formatted only if the request is + processed to the appenders. If it is processed, the component + that formats the message offers high performance and does not + impact negatively the overall process. It respectively takes 2 + and 4 microseconds to format a message with 1 and 3 parameters. +

+ +

Please notice that, despite the performance points that we just discussed, inserting logging statements in tight loops or very - frequently invoked code is a lose-lose proposal and is likely to + frequently invoked code is a lose-lose proposal and is likely to result in degraded performance. Logging in tight loops slow down - your application even if logging is turned off, and if logging is - turned on, they will generate massive (and hence useless) output. -

- -

2. The performance of deciding whether to log or not to log when - logging is turned on.

- -

- In logback, there is no need to walk the logger hierarchy. A - logger knows its effective level (that is, its level, once level - inheritance has been taken into consideration) when it is - created. Should the level of a parent logger be changed, then all - child loggers are contacted to take notice of the change. Thus, - before accepting or denying a request based on the effective - level, the logger can make an quasi-instantaneous decision, - without needing to consult its ancestors. -

- - -

3. Actual logging (formatting and writing to the output device)

- -

This is the cost of formatting the log output and sending it to - its target destination. Here again, a serious effort was made to - make layouts (formatters) perform as quickly as possible. The same - is true for appenders. The typical cost of actually logging is about - 9 to 12 microseconds when logging to a file on the local machine. - It goes up to several milliseconds when logging to a database on a - remote server. -

- -

Although feature-rich, one of the foremost design goals of - logback was speed of execution, a requirement which is second only - to reliability. Some logback components have been rewritten several - times to improve performance. -

- - - -
- - + your application even if logging is turned off, and if logging is + turned on, they will generate massive (and hence useless) output. +

+ +

2. The performance of deciding whether to log or not to log when + logging is turned on.

+ +

+ In logback, there is no need to walk the logger hierarchy. A + logger knows its effective level (that is, its level, once level + inheritance has been taken into consideration) when it is + created. Should the level of a parent logger be changed, then all + child loggers are contacted to take notice of the change. Thus, + before accepting or denying a request based on the effective + level, the logger can make an quasi-instantaneous decision, + without needing to consult its ancestors. +

+ + +

3. Actual logging (formatting and writing to the output device)

+ +

This is the cost of formatting the log output and sending it to + its target destination. Here again, a serious effort was made to + make layouts (formatters) perform as quickly as possible. The same + is true for appenders. The typical cost of actually logging is about + 9 to 12 microseconds when logging to a file on the local machine. + It goes up to several milliseconds when logging to a database on a + remote server. +

+ +

Although feature-rich, one of the foremost design goals of + logback was speed of execution, a requirement which is second only + to reliability. Some logback components have been rewritten several + times to improve performance. +

+ + + +
+ + diff --git a/logback-site/src/site/pages/manual/configuration.html b/logback-site/src/site/pages/manual/configuration.html index d1fa5dc8690ed8765e20f0657dea72c2ac1eda97..169360a603e82b76b2b05379664533448c4715e0 100644 --- a/logback-site/src/site/pages/manual/configuration.html +++ b/logback-site/src/site/pages/manual/configuration.html @@ -1,1452 +1,1452 @@ - - - - - - Chapter3: Logback configuration - - - - - - - - - - - - -
- - -
- -
- -

Chapter 3: Logback configuration

- -
-

In symbols one observes an advantage in discovery which - is greatest when they express the exact nature of a thing - briefly and, as it were, picture it; then indeed the labor of - thought is wonderfully diminished. -

-

—GOTTFRIED WILHELM LEIBNIZ

-
- - - - - -

Joran stands for a cold north-west wind which, every now and - then, blows forcefully on Lake Geneva. Located right in the middle - of Europe, the Geneva lake happens to be the continent's largest - sweet water reserve. -

- -

In the first part, we start by presenting ways for configuring - logback, with many example configuration scripts. In the second part, we present Joran, a generic - configuration framework, which you can put into use in order to - configure your own applications. -

- - -

- - Configuration in logback - -

- -

Inserting log requests into the application code requires a - fair amount of planning and effort. Observation shows that - approximately four percent of code is dedicated to - logging. Consequently, even a moderately sized application will - contain thousands of logging statements embedded within its - code. Given their number, we need tools to manage these log - statements. -

- -

Logback can be configured either programmatically or with a - configuration script (expressed in XML format). By the way, - existing log4j users can convert their log4j.properties - files to logback.xml using our PropertiesTranslator - web-application. -

- -

Let us begin by discussing the initialization steps that - logback follows to try to configure itself: -

- -
    -
  1. -

    Logback tries to find a file called - logback-test.xml in the - classpath.

    -
  2. - -
  3. If no such file is found, it checks for the file - logback.xml in the - classpath..

    -
  4. - -
  5. In case neither file is found, logback configures itself - automatically using the BasicConfigurator - which will cause logging output to be directed on the console. -

    -
  6. - -
- -

The third and last step is meant to provide a default (but very - basic) logging functionality in the absence of a configuration - file. -

- - -

If you are using Maven and assuming the - logback-test.xml file is placed under - src/test/resources folder, Maven will ensure that it - won't be included in the artifact produced. Thus, you can use a - different configuration file, namely logback-test.xml - during testing, and another file, namely, logback.xml, in - production. The same principle applies by analogy for Ant. -

- - -

Automatically configuring logback

- -

The simplest way to configure logback is by letting logback - fall back to its default configuration. Let us give a taste of how - this is done in an imaginary application called - MyApp1. -

- - Example 3.: Simple example of - BasicConfigurator usage (logback-examples/src/main/java/chapter3/MyApp1.java) - -
package chapter3;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class MyApp1 {
-  final static Logger logger = LoggerFactory.getLogger(MyApp1.class);
-
-  public static void main(String[] args) {
-    logger.info("Entering application.");
-
-    Foo foo = new Foo();
-    foo.doIt();
-    logger.info("Exiting application.");
-  }
-}
- -

This class defines a static logger variable. It then - instantiates a Foo object. The Foo class is listed below: -

- - Example 3.: Small class doing logging - (logback-examples/src/main/java/chapter3/Foo.java) - - -
package chapter3;
-  
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-   
-public class Foo {
-  static final Logger logger = LoggerFactory.getLogger(Foo.class);
-  
-  public void doIt() {
-    logger.debug("Did it again!");
-  }
-}
- - -

In order to run the examples in this chapter, you need to make - sure that certain jar files are present on the class path. Please - refer to the setup page for further - details. -

- - - -

Assuming the configuration files logback-test.xml or - logback.xml are not present, logback will default to - invoking BasicConfigurator - which will set up a minimal configuration. This minimal - configuration consists of a ConsoleAppender attached - to the root logger. The output is formatted using a - PatternLayout set to the pattern %d{HH:mm:ss.SSS} - [%thread] %-5level %logger{36} - %msg%n. Moreover, by default - the root logger is assigned the DEBUG level. -

- -

Thus, the output of the command java chapter3.MyApp1 - should be similar to: -

- -

16:06:09.031 [main] INFO chapter3.MyApp1 - Entering application. -16:06:09.046 [main] DEBUG chapter3.Foo - Did it again! -16:06:09.046 [main] INFO chapter3.MyApp1 - Exiting application.

- - -
-

- Except code that configures logback (if such code exists) - client code does not need to depend on logback. Applications - that use logback as their logging framework will have a - compile-time dependency on SLF4J but not logback. -

-
- -

The MyApp1 application links to logback via calls - org.slf4j.LoggerFactory and - org.slf4j.Logger classes, retrieve the loggers it - wishes to use, and chugs on. Note that the only dependencies of - the Foo class on logback are through - org.slf4j.LoggerFactory and - org.slf4j.Logger imports. Except code that configures - logback (if such code exists) client code does not need to depend - on logback. Given that SLF4J permits the use of any logging - framework under its abstraction layer, it is rather easy to migrate - large bodies of code from one logging framework to another. -

- -

Automatic configuration with logback-test.xml or - logback.xml

- -

As mentioned earlier, logback will try to configure itself using - the files logback-test.xml or logback.xml if - found on the class path. Here is a configuration file equivalent to - the one established by BasicConfigurator we've just - seen. -

- -

Example 3.: Basic configuration file - (logback-examples/src/main/java/chapter3/sample0.xml)

- - -
<configuration>
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

After you have renamed sample0.xml as - logback.xml (or logback-test.xml) place it into a - directory accessible from the class path. Running the MyApp1 - application should give identical results to its previous run.

- -

Automatic printing of status messages in case of warning or errors

- -
-

If warning or errors occur during the parsing of the - configuration file, logback will automatically print its internal - status messages on the console. -

-
- -

If warnings or errors occur during the parsing of the - configuration file, logback will automatically print status data on - the console. In the absence of warnings or errors, if you still - wish to inspect logback's internal status, then you can instruct - logback to print status data by invoking the print() - of the StatusPrinter class. The MyApp2 - application shown below is identical to MyApp1 except the - addition of two lines of code for printing internal status - data.

- - Example 3.: Print logback's internal status information - (logback-examples/src/main/java/chapter3/MyApp2.java) - - -
-  public static void main(String[] args) {
-    // assume SLF4J is bound to logback in the current environment
-    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-    // print logback's internal status
-    StatusPrinter.print(lc);
-    ...
-  }
- -

If everything goes well, you should see the following output on the console

- -
17:44:58,578 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml]
-17:44:58,671 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
-17:44:58,671 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
-17:44:58,687 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
-17:44:58,812 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Popping appender named [STDOUT] from the object stack
-17:44:58,812 |-INFO in ch.qos.logback.classic.joran.action.LevelAction - root level set to DEBUG
-17:44:58,812 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[root]
-
-17:44:58.828 [main] INFO  chapter3.MyApp2 - Entering application.
-17:44:58.828 [main] DEBUG chapter3.Foo - Did it again!
-17:44:58.828 [main] INFO  chapter3.MyApp2 - Exiting application.
-
- -

At the end of this output, you can recognize the lines that were - printed in the previous example. You should also notice the - logback's internal messages, a.k.a. Status objects, - which allow convenient access to logback's internal state. -

- -

Instead of invoking StatusPrinter programmatically - from your code, you can instruct the configuration file to dump - status data, even in the absence of errors. To achieve this, you - need to set the debug attribute of the - configuration element, i.e. the top-most element in the - configuration file, as shown below. Please note that this debug attribute relates only to the status - data. It does not affect logback's configuration - otherwise, in particular with respect to logger levels. (If you are - asking, no, the root logger will not be set to - DEBUG.) -

- - - Example 3.: Basic configuration file - using debug mode - (logback-examples/src/main/java/chapter3/sample1.xml) - -
-<configuration debug="true"> 
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

Setting the debug attribute within the - <configuration> element will output status information, under - the assumption that -

-
    -
  1. the configuration file is found
  2. -
  3. the configuration file is well-formed XML.
  4. -
- -

If any of these two conditions is not fulfilled, Joran cannot - interpret debug attribute since the configuration file - cannot be read. If the configuration file is found but is - ill-formed, then logback will detect the error condition and - automatically print its internal status on the console. However, if - the configuration file cannot be found, since this is not - necessarily an error condition, logback will not automatically - print its status data. Programmatically invoking - StatusPrinter.print(), as as in MyApp2 - application above, ensures that status information is always - printed. -

- -

Specifying the location of the default configuration file as a - system property

- -

If you wish, you can specify the location of the default - configuration file with a system property named - logback.configurationFile. The value of the this - property can be a URL, a resource on the class path or a path to a - file external to the application. -

- -

java -Dlogback.configurationFile=/path/to/config.xml chapter3.MyApp1

- - -

Automatically reloading - configuration file upon modification

- -
-

Logback-classic can scan for changes in its configuration file - and automatically reconfigure itself when the said configuration - file changes. -

-
- -

If instructed to do so, logback-classic will scan for changes in - its configuration file and automatically reconfigure itself when - the said configuration file changes. In order to instruct - logback-classic to scan for changes in its configuration file and - to automatically re-configure itself set the scan atrribute of the - <configuration> element to true, as shown next. - -

- Example 3.: Scanning for changes in - configuration file and automatic re-configuraion - (logback-examples/src/main/java/chapter3/scan1.xml) - -
-<configuration scan="true"> 
-  ...
-</configuration> 
- - -

By default, the configuration file will be scanned for changes - once every minute. You can specify a different scanning period by - setting the scanPeriod attribute of the - <configuration> element. Values can be specified in - units of milliseconds, seconds, minutes or hours. Here is an - example:

- - Example 3.: Specifying a different - scanning period - (logback-examples/src/main/java/chapter3/scan2.xml) - -
-<configuration scan="true" scanPeriod="30 seconds" > 
-  ...
-</configuration> 
- -

If no unit of time is specified, then the unit of time is - assumed to be milliseconds, which is usually inappropriate. If you - change the default scanning period, do not forget to specify a time - unit. -

- -

Behind the scenes, when you set the scan attribute to true, a - TurboFilter called ReconfigureOnChangeFilter - will be installed. TurboFilters are described in a later chapter. As a - consequence, scanning is done "in-thread", that is anytime a - printing method of logger is invoked. For example, for a logger - named myLogger, when you write - "myLogger.debug("hello");", and if the scan attribute is set to - true, then ReconfigureOnChangeFilter will be - invoked. Moreover, the said filter will be invoked even if - myLogger is disabled for the debug level. -

- -

Given that ReconfigureOnChangeFilter is invoked - every time any logger is invoked, the filter is - performance critical. In order to improve performance, instead of - checking whether to scan or not on every logger invocation, - ReconfigureOnChangeFilter is in reality "alive" only - once every 16 logging operations. In short, when a configuration - file changes, it will be automatically reloaded after a delay - determined by the scanning period and several logger invocations. -

- - - -

Invoking JoranConfigurator directly

- -

Logback relies on a configuration library called Joran which is - part of logback-core. Logback's default configuration mechanism - invokes JoranConfigurator on the default configuration - file it finds on the class path. For whatever reason if you wish to - override logback's default configuration mechanism, you can do so - by invoking JoranConfigurator directly. The next - application, MyApp3, invokes JoranConfigurator on a - configuration file passed as a parameter.

- -

Example 3.: Invoking - JoranConfigurator directly (logback-examples/src/main/java/chapter3/MyApp3.java)

- -
package chapter3;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.joran.JoranConfigurator;
-import ch.qos.logback.core.joran.spi.JoranException;
-import ch.qos.logback.core.util.StatusPrinter;
-
-public class MyApp3 {
-  final static Logger logger = LoggerFactory.getLogger(MyApp3.class);
-
-  public static void main(String[] args) {
-    // assume SLF4J is bound to logback in the current environment
-    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-    
-    try {
-      JoranConfigurator configurator = new JoranConfigurator();
-      configurator.setContext(lc);
-      // the context was probably already configured by default configuration 
-      // rules
-      lc.reset(); 
-      configurator.doConfigure(args[0]);
-    } catch (JoranException je) {
-       je.printStackTrace();
-    }
-    StatusPrinter.printInCaseOfErrorsOrWarnings(lc);
-
-    logger.info("Entering application.");
-
-    Foo foo = new Foo();
-    foo.doIt();
-    logger.info("Exiting application.");
-  }
-}
- -

This application fetches the LoggerContext - currently in effect, creates a new JoranConfigurator, - sets the context on which it will operate, resets the logger - context, and then finally asks the configurator to configure the - context using configuration file passed as parameter to the - application. Internal status data is printed in case of warnings or - errors. -

- -

Viewing status messages -

- - - -

Logback collects its internal status data in a StatusManager - object, accessible via the LoggerContext. -

- -

Given a StatusManager you an access all the status - data associated with a logback context. To keep memory usage at - reasonable levels, the default StatusManager - implementation stores the status messages in two separate parts: - the header part and the tail part. The header part stores the fist - H status messages whereas the tail part stores the last - T messages. At present time H=T=150, - although these values may change in future releases.

- -

Logback-classic ships with a servlet called - ViewStatusMessagesServlet. This servlet prints the contents of the - StatusManager associated with the current - LoggerContext as an HTML table. Here is sample output. -

- - - click to enlarge - - -

To add this servlet to your web-application, add the following - lines to its WEB-INF/web.xml file.

- -
  <servlet>
-    <servlet-name>ViewStatusMessages</servlet-name>
-    <servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet</servlet-class>
-  </servlet>
-
-  <servlet-mapping>
-    <servlet-name>ViewStatusMessages</servlet-name>
-    <url-pattern>/lbClassicStatus</url-pattern>
-  </servlet-mapping>
- -

The ViewStatusMessages servlet will viewable under - the URL http://host/yourWebapp/lbClassicStatus -

- -

- Listening to - status messages -

- - - -

You may also attach a StatusListener to a - StatusManager so that you can take immediate action in - response to status messages, especially to messages occurring after - logback configuration. Registering a status listener is a - convenient way to supervise logback's internal state without human - intervention. -

- -

Logback ships with a StatusListener implementation - called OnConsoleStatusListener - which, as its name indicates, prints all new incoming - status messages on the console. -

- -

Here is sample code - to register an OnConsoleStatusListener instance with the - StatusManager. -

- -
   LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); 
-   StatusManager statusManager = lc.getStatusManager();
-   OnConsoleStatusListener onConsoleListener = new OnConsoleStatusListener();
-   statusManager.add(onConsoleListener);
- -

Note that the registered status listener will receive status - events subsequent to its registration. It will not receive prior - messages.

- -

It is also possible to register one or more status listeners - within a configuration file. Here is an example.

- -

Example 3.: Registering a status listener (logback-examples/src/main/java/chapter3/onConsoleStatusListener.xml)

- -
<configuration>
-  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />  
-
-  ... the rest of the configuration file  
-</configuration>
- -

One may also register a status listener by setting the - "logback.statusListenerClass" Java system property to the name of - the listener class you wish to register. For example, -

- -

java -Dlogback.statusListenerClass=ch.qos.logback.core.status.OnConsoleStatusListener ...

- - - - -

- Configuration file Syntax -

- -

To obtain these different logging behaviors we do not need to - recompile code. You can easily configure logback so as to disable - logging for certain parts of your application, or direct output to a - UNIX Syslog daemon, to a database, to a log visualizer, or forward - logging events to a remote logback server, which would log according - to local server policy, for example by forwarding the log event to a - second logback server. -

- -

The remainder of this section presents the syntax of - configuration files. -

- -

As shall become clear, the syntax of logback configuration files - is extremely flexible. As such, it is not possible to specify the - allowed syntax with a DTD file or an XML schema. Nevertheless, the - very basic structure of the configuration file can be described as, - <configuration> element, followed by zero or more <appender> - elements, followed by zero or more <logger> elements, followed by - at most one <root> element. The following diagram illustrates - this basic structure.

- - -

- basic Syntax -

- - -
-

If you are unsure which case to use for a given tag name, just - follow the camelCase convention which should usually be - corrrect.

-
- -

As of logback version 0.9.17, tag names pertaining to explicit - rules are case insensitive. For example, both - <logger>, <Logger> and - <LOGGER> are valid configuration elements and will - be interpreted in the same way. Note that XML well-formedness rules - still apply, if you open a tag as <xyz> you must - close it as </xyz>, </XyZ> will not - work. As for implicit rules, tag - names are case sensitive except for the first letter. Thus, - <xyz> and <Xyz> are equivalent but - not <xYz>. Implicit rules usually follow the camel case - convention, common in the Java world. Since it is not trivially easy - tell when a tag is associated with an explicit action and when it is - associated with an implicit action, it is not trivial to say whether - an XML tag is totally case-insensitive or case-insensitive with - respect to the first letter. If you are unsure which case to use for - a given tag name, just follow the camelCase convention which should - usually be correct. -

- -

Configuring Loggers, or the <logger> element

- -

A logger is configured using the logger element. A - logger element takes exactly one mandatory name attribute, an optional level attribute, and an optional additivity attribute, which admits the values - true or false. The value of the level attribute can be one of the - case-insensitive strings TRACE, DEBUG, INFO, WARN, ERROR, ALL or - OFF. The special case-insensitive value INHERITED, or its - synonym NULL, will force the level of the logger to be - inherited from higher up in the hierarchy. This comes in handy in - case you set the level of a logger and later decide that it should - inherit its level. -

- -

The logger element may contain zero or more - appender-ref elements; each appender thus referenced is - added to the named logger. It is important to keep mind that each - named logger that is declared with a <logger element first has - all its appenders removed and only then are the referenced appenders - attached to it. In particular, if there are no appender references, - then the named logger will lose all its appenders. -

- - - -

Configuring the root logger, or the <root> - element

- - - -

The <root> element configures the root logger. It admits a - single attribute, namely the level - attribute. It does not admit any other attributes because the - additivity flag does not apply to the root logger. Moreover, since - the root logger is already named as "ROOT", it does not admit a name - attribute either. The value of the level attribute can be set to one - of the case-insensitive strings TRACE, DEBUG, INFO, WARN, ERROR, ALL - or OFF. Note that the level of the root logger cannot be set to - INHERITED or NULL. -

- - -

The <root> element admits zero or more <appender-ref> - elements. Similar to the <logger element, declaring a <root - element will have the effect of first closing and then detaching all - its current appenders and only subsequently will referenced - appenders, if any, will be added. In particular, if it has no - appender references, then the root logger will lose all its - appenders. -

- -

Example

- -

Setting the level of a logger or root logger is as simple as - declaring it and setting its level, as the next example - illustrates. Suppose we are no longer interested in seeing any DEBUG - messages from any component belonging to the "chapter3" package. The - following configuration file shows how to achieve that. -

- -Example 3.: Setting the level of a logger (logback-examples/src/main/java/chapter3/sample2.xml) -
<configuration>
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <logger name="chapter3" level="INFO"/>
-
-  <!-- Strictly speaking, the level attribute is not necessary since -->
-  <!-- the level of the root level is set to DEBUG by default.       -->
-  <root level="DEBUG">		
-    <appender-ref ref="STDOUT" />
-  </root>  
-  
-</configuration>
- -

This new configuration will yield the following output, when - invoked with the MyApp3 application. -

- -
17:34:07.578 [main] INFO  chapter3.MyApp3 - Entering application.
-17:34:07.578 [main] INFO  chapter3.MyApp3 - Exiting application.
- -

You can configure the levels of as many loggers as you wish. In - the next configuration file, we set the level of the - chapter3 logger to INFO but at the same time set the level - of the chapter3.Foo logger to DEBUG. -

- -Example 3.: Setting the level of multiple loggers (logback-examples/src/main/java/chapter3/sample3.xml) -
<configuration>
-
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>
-        %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
-     </Pattern>
-    </layout>
-  </appender>
-
-  <logger name="chapter3" level="INFO" />
-  <logger name="chapter3.Foo" level="DEBUG" />
-
-  <root level="DEBUG">
-    <appender-ref ref="STDOUT" />
-  </root>
-
-</configuration>
- -

Running MyApp3 with this configuration file will - result in the following output on the console: -

- -

17:39:27.593 [main] INFO chapter3.MyApp3 - Entering application. -17:39:27.593 [main] DEBUG chapter3.Foo - Did it again! -17:39:27.593 [main] INFO chapter3.MyApp3 - Exiting application.

- -

The table below list the loggers and their levels, after - JoranConfigurator has configured logback with the - sample3.xml configuration file. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
Logger nameAssigned LevelEffective Level
rootDEBUGDEBUG
chapter3INFOINFO
chapter3.MyApp3nullINFO
chapter3.FooDEBUGDEBUG
- -

It follows that the two logging statements of level - INFO in the MyApp3 class as well as the - DEBUG messages in Foo.doIt() are all enabled. Note that - the level of the root logger is always set to a non-null value, - which is DEBUG by default. -

- -

Let us note that the basic-selection rule - depends on the effective level of the logger being invoked, not the - level of the logger where appenders are attached. Loback will first - determine wheteher a logging statement is enabled or not, and if - enabled, it will invoke the appenders found in the logger hierarchy, - regardless of their level. The configuration file - sample4.xml is a case in point: -

- - Example 3.: Logger level sample - (logback-examples/src/main/java/chapter3/sample4.xml) -
<configuration>
-
-  <appender name="STDOUT"
-   class="ch.qos.logback.core.ConsoleAppender">
-   <layout class="ch.qos.logback.classic.PatternLayout">
-     <Pattern>
-        %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
-      </Pattern>
-    </layout>
-  </appender>
-
-  <logger name="chapter3" level="INFO" />
-
-  <!-- turn OFF all logging (children can override) -->
-  <root level="OFF">
-    <appender-ref ref="STDOUT" />
-  </root>
-
-</configuration>
- -

The following table lists the loggers and their levels after - applying the sample4.xml configuration file. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
Logger nameAssigned LevelEffective Level
rootOFFOFF
chapter3INFOINFO
chapter3.MyApp3nullINFO
chapter3.FoonullINFO
- -

The ConsoleAppender named STDOUT, the only configured - appender in sample4.xml, is attached to the root logger - whose level is set to OFF. However, running - MyApp3 with configuration script sample4.xml will - yield: -

- -
17:52:23.609 [main] INFO chapter3.MyApp3 - Entering application.
-17:52:23.609 [main] INFO chapter3.MyApp3 - Exiting application.
- -

Thus, the level of the root logger has no apparent effect because - the loggers in chapter3.MyApp3 and - chapter3.Foo classes are all enabled for the - INFO level. As a side note, the chapter3 - logger exists by virtue of its declaration in the configuration file - - even if the Java source code does not directly refer to it. -

- -

Configuring Appenders

- -

Appenders are configured using <appender> - elements, taking two attributes name and - class, both of which are mandatory. The - name attribute specifies the name of the - appender whereas the class attribute - specifies the fully qualified name of the class of which the named - appender will be an instance. The <appender> - element may contain zero or one <layout> elements - and zero or more <filter> elements. Appart from - these two common elements, <appender> elements may - contain any number of element corresponding to javabean properties - of the appender class. Seamlessly supporting any property of a given - logback component is one of the major strengths of Joran. The - following diagram illustrates the common structure. Note that - support for properties is not visible. -

- -

- Appender Syntax -

- -

The <layout> element takes a mandatory class - attribute specifying the fully qualified name of the class of which - the associated layout should be an instance. Like the - <appender> element, it may contain other elements - corresponding to properties of the layout class. -

- -

Logging to multiple appenders is as easy as defining the various - appenders and referencing them in a logger, as the next - configuration file illustrates: -

- -Example 3.: Multiple loggers (logback-examples/src/main/java/chapter3/multiple.xml) -
<configuration>
-
-  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
-    <file>myApp.log</file>
-
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="FILE" />
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

This configuration scripts defines two appenders called - FILE and STDOUT. The FILE appender logs - to a file called myApp.log. The layout for this appender is - a PatternLayout that outputs the date, level, thread - name, logger name, file name and line number where the log request - is located, the message and line separator character(s). The second - appender called STDOUT outputs to the console. The - layout for this appender outputs only the message string followed by - a line separator. -

- -

The appenders are attached to the root logger by referencing them - by name within an appender-ref element. Note that each - appender has its own layout. Layouts are usually not designed to be - shared by multiple appenders. As such, logback configuration files - do not provide any syntactical means for sharing layouts. -

- -

By default, appenders are cumulative: a logger will log to - the appenders attached to itself (if any) as well as all the - appenders attached to its ancestors. Thus, attaching the same - appender to multiple loggers will cause logging output to be - duplicated. -

- - Example 3.: Duplicate appender - (logback-examples/src/main/java/chapter3/duplicate.xml) -
<configuration>
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <logger name="chapter3">
-    <appender-ref ref="STDOUT" />
-  </logger>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

Running MyApp3 with duplicate.xml will - yield the following output: -

- -

14:25:36.343 [main] INFO chapter3.MyApp3 - Entering application. -14:25:36.343 [main] INFO chapter3.MyApp3 - Entering application. -14:25:36.359 [main] DEBUG chapter3.Foo - Did it again! -14:25:36.359 [main] DEBUG chapter3.Foo - Did it again! -14:25:36.359 [main] INFO chapter3.MyApp3 - Exiting application. -14:25:36.359 [main] INFO chapter3.MyApp3 - Exiting application.

- -

Notice the duplicated output. The appender named STDOUT - is attached to two loggers, to root and to chapter3. Since - the root logger is the ancestor of all loggers and chapter3 - is the parent of chapter3.MyApp3 and chapter3.Foo, - logging request made with these two loggers will be output twice, - once because STDOUT is attached to chapter3 and - once because it is attached to root. -

- -

Appender additivity is not intended as a trap for new users. It - is a quite convenient logback feature. For instance, you can - configure logging such that log messages appear on the console (for - all loggers in the system) while messages only from some specific - set of loggers flow into a specific appender. -

- - Example 3.: Multiple appender - (logback-examples/src/main/java/chapter3/restricted.xml) -
<configuration>
-
-  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
-    <file>myApp.log</file>
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <logger name="chapter3">
-    <appender-ref ref="FILE" />
-  </logger>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

In this example, the console appender will log all the messages - (for all loggers in the system) whereas only logging request - originating from loggers chapter3 and below go into the - myApp.log file. -

- -

Overriding the default cumulative behaviour

- -

In case the default cumulative behavior turns out to be - unsuitable for your needs, you can override it by setting the - additivity flag to false. Thus, a branch in your logger tree may - direct output to a set of appenders different than those of the rest - of the tree. -

- -Example 3.: Additivity flag (logback-examples/src/main/java/chapter3/additivityFlag.xml) -
<configuration>
-
-  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
-    <file>foo.log</file>
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%date %level [%thread] %logger{10} [%file : %line] %msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <logger name="chapter3.Foo" additivity="false">
-    <appender-ref ref="FILE" />
-  </logger>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

This example, the appender named FILE is attached to the - chapter3.Foo logger. Moreover, the chapter3.Foo - logger has its additivity flag set to false such that its logging - output will be sent to the appender named FILE but not to - any appender attached higher in the hierarchy. Other loggers remain - oblivious to the additivity setting of the chapter3.Foo - logger. Running the MyApp3 application with the - additivityFlag.xml configuration file will output results - on the console from the chapter3.MyApp3 logger. However, - output from the chapter3.Foo logger will appear in the - foo.log file and only in that file. -

- -

Variable substitution

- -

In principle, variable substitution can occur at any point where - a value can be specified. The syntax of variable substitution is - similar to that of Unix shells. The string between an opening - ${ and closing } is interpreted as a key. The - value of the substituted variable can be defined in the - configuration file itself, in an external properties file or as a - system property. The corresponding value replaces ${aKey} - sequence. For example, if java.home.dir system property is - set to /home/xyz, then every occurrence of the sequence - ${java.home.dir} will be interpreted as /home/xyz. -

- -

properties are inserted into the logger context

- -

Note that the values defined via <property> - element are actually inserted into the logger context. In other - words, they become properties of the logger context. Consequently, - they will be available in all logging events as well as remotely - after serialization.

- -

The next example shows a variable, a.k.a. a substitution - property, declared the beginning of the configuration file. It is - then used further down the file to specify the location of the - output file. -

- - Example 3.: Simple Variable substitution - (logback-examples/src/main/java/chapter3/variableSubstitution1.xml) - - -
<configuration>
-
-  <property name="USER_HOME" value="/home/sebastien" />
-
-  <appender name="FILE"
-    class="ch.qos.logback.core.FileAppender">
-    <file>${USER_HOME}/myApp.log</file>
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="FILE" />
-  </root>
-</configuration>
- - -

The next example shows the use of a System property to achieve - the same result. The property is not declared in the configuration - file, thus logback will look for it in the System properties. Java - system properties can be set on the command line. -

- -

java -DUSER_HOME="/home/sebastien" MyApp2

- - Example 3.: System Variable substitution - (logback-examples/src/main/java/chapter3/variableSubstitution2.xml) - - -
<configuration>
-
-  <appender name="FILE"
-    class="ch.qos.logback.core.FileAppender">
-    <file>${USER_HOME}/myApp.log</file>
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="FILE" />
-  </root>
-</configuration>
- - -

When multiple variables are needed, it may be more convenient to - create a separate file that will contain all the variables. Here is - how one can do such a setup. -

- - Example 3.: Variable substitution using a - separate file - (logback-examples/src/main/java/chapter3/variableSubstitution3.xml) - - -
<configuration>
-
-  <property file="src/main/java/chapter3/variables1.properties" />
-
-  <appender name="FILE"
-     class="ch.qos.logback.core.FileAppender">
-     <file>${USER_HOME}/myApp.log</file>
-     <layout class="ch.qos.logback.classic.PatternLayout">
-       <Pattern>%msg%n</Pattern>
-     </layout>
-   </appender>
-
-   <root level="debug">
-     <appender-ref ref="FILE" />
-   </root>
-</configuration>
- -

This configuration file contains a reference to a file named - variables1.properties. The variables contained in that - file will be read defined within the context of the logback - configuration file. Here is what the variable.properties - file might look like. -

- - Example 3.: Variable file - (logback-examples/src/main/java/chapter3/variables1.properties) - -
USER_HOME=/home/sebastien
- -

You may also reference a resource on the class path instead of a - file.

- -
<configuration>
-
-  <property resource="resource1.properties" />
-
-  <appender name="FILE"
-     class="ch.qos.logback.core.FileAppender">
-     <file>${USER_HOME}/myApp.log</file>
-     <layout class="ch.qos.logback.classic.PatternLayout">
-       <Pattern>%msg%n</Pattern>
-     </layout>
-   </appender>
-
-   <root level="debug">
-     <appender-ref ref="FILE" />
-   </root>
-</configuration>
- -

Nested variable substitution

- -

Nested variabled subsitution is also supported. By nested, we - mean that the value definition of a variable contains references to - other variables. Suppose you wish to use variables to specify not - only the destination directory but also the file name, and combine - those two variables in a third variable called "destination". The - properties file shown below gives an example. -

- - - Example 3.: Nested variable references - (logback-examples/src/main/java/chapter3/variables2.properties) - -
USER_HOME=/home/sebastien
-fileName=myApp.log
-destination=${USER_HOME}/${fileName}
- -

Note that in the properties file above, "destination" is - composed out of two other variables, namely "USER_HOME" and - "fileName". -

- - Example 3.: Variable substitution using - a separate file - (logback-examples/src/main/java/chapter3/variableSubstitution4.xml) - -
<configuration>
-
-  <property file="variables2.properties" />
-
-  <appender name="FILE"
-    class="ch.qos.logback.core.FileAppender">
-    <file>${destination}</file>
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="FILE" />
-  </root>
-</configuration>
- -

Default substitution values for - variables

- -

Under certain circumstances, it may be desirable for a variable - to have a default value in case it is not declared or its value is - null. As in the Bash - shell, default values can be specified using the ":-" - operator. For example, assuming aKey is not defined, - "${aKey:-golden}" will be interpreted as - "golden".

- - - -

File - inclusion

- -

Joran supports including parts of a configuration file from - another file. This is done by declaring a <include> - element, as shown below: -

- - Example 3.: File include - (logback-examples/src/main/java/chapter3/containingConfig.xml) - -
<configuration>
-  <include file="src/main/java/chapter3/includedConfig.xml"/>
-
-  <root level="DEBUG">
-    <appender-ref ref="includedConsole" />
-  </root>
-
-</configuration>
- -

The target file MUST have its elements nested inside an - <included> element. For example, a - ConsoleAppender could be declared as: -

- - Example 3.: File include - (logback-examples/src/main/java/chapter3/includedConfig.xml) - -
<included>
-  <appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>"%d - %m%n"</Pattern>
-    </layout>
-  </appender>
-</included>
- -

The file to be included can be referenced as a file, as a URL or - as a resource. To reference a file use the file attribute. To reference a URL use the url attribute. To reference a resource, use the - resource attribute. -

- - -

Setting the context name

- -

As mentioned in an - earlier chapter, every logger is attached to logger context. By - default, the logger context is called "default". However, you can - set a different name with the help of the - <contextName> configuration directive. Note that - once set, the logger context name cannot - be changed. Setting the context name is a simple and - straightforward method in order to distinguish between multiple - applications logging to the same target. -

- - Example 3.: Set the context name and display it - (logback-examples/src/main/java/chapter3/contextName.xml) -
<configuration>
-  <contextName>myAppName</contextName>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

This last examples illustrates naming of the logger - context. Adding the the contextName conversion word - in layout's pattern will output the said name.

- -

Obtaining - variables from JNDI

- -

Under certain circumstances, you may want to make use of - env-entries stored in JNDI. The <insertFromJNDI> - configuration directive extracts an env-entry stored in JNDI and - inserts it as variable as specified by the as attribute. -

- - Example 3.: Insert as properties env-entries obtained via JNDI - (logback-examples/src/main/java/chapter3/insertFromJNDI.xml) -
<configuration>
-  <insertFromJNDI env-entry-name="java:comp/env/appName" as="appName" />
-  <contextName>${appName}</contextName>
-
-  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%d %contextName %level %msg %logger{50}%n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="DEBUG">
-    <appender-ref ref="CONSOLE" />
-  </root>
-</configuration>
- -

In this last example, the "java:comp/env/appName" env-entry is - inserted as the appName property. Note - that the <contextName> directive sets the context - name based on the value of the appName - property inserted by the previous <insertFromJNDI> - directive.. - -

- - -
- - + + + + + + Chapter3: Logback configuration + + + + + + + + + + + + +
+ + +
+ +
+ +

Chapter 3: Logback configuration

+ +
+

In symbols one observes an advantage in discovery which + is greatest when they express the exact nature of a thing + briefly and, as it were, picture it; then indeed the labor of + thought is wonderfully diminished. +

+

—GOTTFRIED WILHELM LEIBNIZ

+
+ + + + + +

Joran stands for a cold north-west wind which, every now and + then, blows forcefully on Lake Geneva. Located right in the middle + of Europe, the Geneva lake happens to be the continent's largest + sweet water reserve. +

+ +

In the first part, we start by presenting ways for configuring + logback, with many example configuration scripts. In the second part, we present Joran, a generic + configuration framework, which you can put into use in order to + configure your own applications. +

+ + +

+ + Configuration in logback + +

+ +

Inserting log requests into the application code requires a + fair amount of planning and effort. Observation shows that + approximately four percent of code is dedicated to + logging. Consequently, even a moderately sized application will + contain thousands of logging statements embedded within its + code. Given their number, we need tools to manage these log + statements. +

+ +

Logback can be configured either programmatically or with a + configuration script (expressed in XML format). By the way, + existing log4j users can convert their log4j.properties + files to logback.xml using our PropertiesTranslator + web-application. +

+ +

Let us begin by discussing the initialization steps that + logback follows to try to configure itself: +

+ +
    +
  1. +

    Logback tries to find a file called + logback-test.xml in the + classpath.

    +
  2. + +
  3. If no such file is found, it checks for the file + logback.xml in the + classpath..

    +
  4. + +
  5. In case neither file is found, logback configures itself + automatically using the BasicConfigurator + which will cause logging output to be directed on the console. +

    +
  6. + +
+ +

The third and last step is meant to provide a default (but very + basic) logging functionality in the absence of a configuration + file. +

+ + +

If you are using Maven and assuming the + logback-test.xml file is placed under + src/test/resources folder, Maven will ensure that it + won't be included in the artifact produced. Thus, you can use a + different configuration file, namely logback-test.xml + during testing, and another file, namely, logback.xml, in + production. The same principle applies by analogy for Ant. +

+ + +

Automatically configuring logback

+ +

The simplest way to configure logback is by letting logback + fall back to its default configuration. Let us give a taste of how + this is done in an imaginary application called + MyApp1. +

+ + Example 3.: Simple example of + BasicConfigurator usage (logback-examples/src/main/java/chapter3/MyApp1.java) + +
package chapter3;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MyApp1 {
+  final static Logger logger = LoggerFactory.getLogger(MyApp1.class);
+
+  public static void main(String[] args) {
+    logger.info("Entering application.");
+
+    Foo foo = new Foo();
+    foo.doIt();
+    logger.info("Exiting application.");
+  }
+}
+ +

This class defines a static logger variable. It then + instantiates a Foo object. The Foo class is listed below: +

+ + Example 3.: Small class doing logging + (logback-examples/src/main/java/chapter3/Foo.java) + + +
package chapter3;
+  
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+   
+public class Foo {
+  static final Logger logger = LoggerFactory.getLogger(Foo.class);
+  
+  public void doIt() {
+    logger.debug("Did it again!");
+  }
+}
+ + +

In order to run the examples in this chapter, you need to make + sure that certain jar files are present on the class path. Please + refer to the setup page for further + details. +

+ + + +

Assuming the configuration files logback-test.xml or + logback.xml are not present, logback will default to + invoking BasicConfigurator + which will set up a minimal configuration. This minimal + configuration consists of a ConsoleAppender attached + to the root logger. The output is formatted using a + PatternLayout set to the pattern %d{HH:mm:ss.SSS} + [%thread] %-5level %logger{36} - %msg%n. Moreover, by default + the root logger is assigned the DEBUG level. +

+ +

Thus, the output of the command java chapter3.MyApp1 + should be similar to: +

+ +

16:06:09.031 [main] INFO chapter3.MyApp1 - Entering application. +16:06:09.046 [main] DEBUG chapter3.Foo - Did it again! +16:06:09.046 [main] INFO chapter3.MyApp1 - Exiting application.

+ + +
+

+ Except code that configures logback (if such code exists) + client code does not need to depend on logback. Applications + that use logback as their logging framework will have a + compile-time dependency on SLF4J but not logback. +

+
+ +

The MyApp1 application links to logback via calls + org.slf4j.LoggerFactory and + org.slf4j.Logger classes, retrieve the loggers it + wishes to use, and chugs on. Note that the only dependencies of + the Foo class on logback are through + org.slf4j.LoggerFactory and + org.slf4j.Logger imports. Except code that configures + logback (if such code exists) client code does not need to depend + on logback. Given that SLF4J permits the use of any logging + framework under its abstraction layer, it is rather easy to migrate + large bodies of code from one logging framework to another. +

+ +

Automatic configuration with logback-test.xml or + logback.xml

+ +

As mentioned earlier, logback will try to configure itself using + the files logback-test.xml or logback.xml if + found on the class path. Here is a configuration file equivalent to + the one established by BasicConfigurator we've just + seen. +

+ +

Example 3.: Basic configuration file + (logback-examples/src/main/java/chapter3/sample0.xml)

+ + +
<configuration>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

After you have renamed sample0.xml as + logback.xml (or logback-test.xml) place it into a + directory accessible from the class path. Running the MyApp1 + application should give identical results to its previous run.

+ +

Automatic printing of status messages in case of warning or errors

+ +
+

If warning or errors occur during the parsing of the + configuration file, logback will automatically print its internal + status messages on the console. +

+
+ +

If warnings or errors occur during the parsing of the + configuration file, logback will automatically print status data on + the console. In the absence of warnings or errors, if you still + wish to inspect logback's internal status, then you can instruct + logback to print status data by invoking the print() + of the StatusPrinter class. The MyApp2 + application shown below is identical to MyApp1 except the + addition of two lines of code for printing internal status + data.

+ + Example 3.: Print logback's internal status information + (logback-examples/src/main/java/chapter3/MyApp2.java) + + +
+  public static void main(String[] args) {
+    // assume SLF4J is bound to logback in the current environment
+    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+    // print logback's internal status
+    StatusPrinter.print(lc);
+    ...
+  }
+ +

If everything goes well, you should see the following output on the console

+ +
17:44:58,578 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml]
+17:44:58,671 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
+17:44:58,671 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
+17:44:58,687 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
+17:44:58,812 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Popping appender named [STDOUT] from the object stack
+17:44:58,812 |-INFO in ch.qos.logback.classic.joran.action.LevelAction - root level set to DEBUG
+17:44:58,812 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[root]
+
+17:44:58.828 [main] INFO  chapter3.MyApp2 - Entering application.
+17:44:58.828 [main] DEBUG chapter3.Foo - Did it again!
+17:44:58.828 [main] INFO  chapter3.MyApp2 - Exiting application.
+
+ +

At the end of this output, you can recognize the lines that were + printed in the previous example. You should also notice the + logback's internal messages, a.k.a. Status objects, + which allow convenient access to logback's internal state. +

+ +

Instead of invoking StatusPrinter programmatically + from your code, you can instruct the configuration file to dump + status data, even in the absence of errors. To achieve this, you + need to set the debug attribute of the + configuration element, i.e. the top-most element in the + configuration file, as shown below. Please note that this debug attribute relates only to the status + data. It does not affect logback's configuration + otherwise, in particular with respect to logger levels. (If you are + asking, no, the root logger will not be set to + DEBUG.) +

+ + + Example 3.: Basic configuration file + using debug mode + (logback-examples/src/main/java/chapter3/sample1.xml) + +
+<configuration debug="true"> 
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

Setting the debug attribute within the + <configuration> element will output status information, under + the assumption that +

+
    +
  1. the configuration file is found
  2. +
  3. the configuration file is well-formed XML.
  4. +
+ +

If any of these two conditions is not fulfilled, Joran cannot + interpret debug attribute since the configuration file + cannot be read. If the configuration file is found but is + ill-formed, then logback will detect the error condition and + automatically print its internal status on the console. However, if + the configuration file cannot be found, since this is not + necessarily an error condition, logback will not automatically + print its status data. Programmatically invoking + StatusPrinter.print(), as as in MyApp2 + application above, ensures that status information is always + printed. +

+ +

Specifying the location of the default configuration file as a + system property

+ +

If you wish, you can specify the location of the default + configuration file with a system property named + logback.configurationFile. The value of the this + property can be a URL, a resource on the class path or a path to a + file external to the application. +

+ +

java -Dlogback.configurationFile=/path/to/config.xml chapter3.MyApp1

+ + +

Automatically reloading + configuration file upon modification

+ +
+

Logback-classic can scan for changes in its configuration file + and automatically reconfigure itself when the said configuration + file changes. +

+
+ +

If instructed to do so, logback-classic will scan for changes in + its configuration file and automatically reconfigure itself when + the said configuration file changes. In order to instruct + logback-classic to scan for changes in its configuration file and + to automatically re-configure itself set the scan atrribute of the + <configuration> element to true, as shown next. + +

+ Example 3.: Scanning for changes in + configuration file and automatic re-configuraion + (logback-examples/src/main/java/chapter3/scan1.xml) + +
+<configuration scan="true"> 
+  ...
+</configuration> 
+ + +

By default, the configuration file will be scanned for changes + once every minute. You can specify a different scanning period by + setting the scanPeriod attribute of the + <configuration> element. Values can be specified in + units of milliseconds, seconds, minutes or hours. Here is an + example:

+ + Example 3.: Specifying a different + scanning period + (logback-examples/src/main/java/chapter3/scan2.xml) + +
+<configuration scan="true" scanPeriod="30 seconds" > 
+  ...
+</configuration> 
+ +

If no unit of time is specified, then the unit of time is + assumed to be milliseconds, which is usually inappropriate. If you + change the default scanning period, do not forget to specify a time + unit. +

+ +

Behind the scenes, when you set the scan attribute to true, a + TurboFilter called ReconfigureOnChangeFilter + will be installed. TurboFilters are described in a later chapter. As a + consequence, scanning is done "in-thread", that is anytime a + printing method of logger is invoked. For example, for a logger + named myLogger, when you write + "myLogger.debug("hello");", and if the scan attribute is set to + true, then ReconfigureOnChangeFilter will be + invoked. Moreover, the said filter will be invoked even if + myLogger is disabled for the debug level. +

+ +

Given that ReconfigureOnChangeFilter is invoked + every time any logger is invoked, the filter is + performance critical. In order to improve performance, instead of + checking whether to scan or not on every logger invocation, + ReconfigureOnChangeFilter is in reality "alive" only + once every 16 logging operations. In short, when a configuration + file changes, it will be automatically reloaded after a delay + determined by the scanning period and several logger invocations. +

+ + + +

Invoking JoranConfigurator directly

+ +

Logback relies on a configuration library called Joran which is + part of logback-core. Logback's default configuration mechanism + invokes JoranConfigurator on the default configuration + file it finds on the class path. For whatever reason if you wish to + override logback's default configuration mechanism, you can do so + by invoking JoranConfigurator directly. The next + application, MyApp3, invokes JoranConfigurator on a + configuration file passed as a parameter.

+ +

Example 3.: Invoking + JoranConfigurator directly (logback-examples/src/main/java/chapter3/MyApp3.java)

+ +
package chapter3;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class MyApp3 {
+  final static Logger logger = LoggerFactory.getLogger(MyApp3.class);
+
+  public static void main(String[] args) {
+    // assume SLF4J is bound to logback in the current environment
+    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+    
+    try {
+      JoranConfigurator configurator = new JoranConfigurator();
+      configurator.setContext(lc);
+      // the context was probably already configured by default configuration 
+      // rules
+      lc.reset(); 
+      configurator.doConfigure(args[0]);
+    } catch (JoranException je) {
+       je.printStackTrace();
+    }
+    StatusPrinter.printInCaseOfErrorsOrWarnings(lc);
+
+    logger.info("Entering application.");
+
+    Foo foo = new Foo();
+    foo.doIt();
+    logger.info("Exiting application.");
+  }
+}
+ +

This application fetches the LoggerContext + currently in effect, creates a new JoranConfigurator, + sets the context on which it will operate, resets the logger + context, and then finally asks the configurator to configure the + context using configuration file passed as parameter to the + application. Internal status data is printed in case of warnings or + errors. +

+ +

Viewing status messages +

+ + + +

Logback collects its internal status data in a StatusManager + object, accessible via the LoggerContext. +

+ +

Given a StatusManager you an access all the status + data associated with a logback context. To keep memory usage at + reasonable levels, the default StatusManager + implementation stores the status messages in two separate parts: + the header part and the tail part. The header part stores the fist + H status messages whereas the tail part stores the last + T messages. At present time H=T=150, + although these values may change in future releases.

+ +

Logback-classic ships with a servlet called + ViewStatusMessagesServlet. This servlet prints the contents of the + StatusManager associated with the current + LoggerContext as an HTML table. Here is sample output. +

+ + + click to enlarge + + +

To add this servlet to your web-application, add the following + lines to its WEB-INF/web.xml file.

+ +
  <servlet>
+    <servlet-name>ViewStatusMessages</servlet-name>
+    <servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet</servlet-class>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>ViewStatusMessages</servlet-name>
+    <url-pattern>/lbClassicStatus</url-pattern>
+  </servlet-mapping>
+ +

The ViewStatusMessages servlet will viewable under + the URL http://host/yourWebapp/lbClassicStatus +

+ +

+ Listening to + status messages +

+ + + +

You may also attach a StatusListener to a + StatusManager so that you can take immediate action in + response to status messages, especially to messages occurring after + logback configuration. Registering a status listener is a + convenient way to supervise logback's internal state without human + intervention. +

+ +

Logback ships with a StatusListener implementation + called OnConsoleStatusListener + which, as its name indicates, prints all new incoming + status messages on the console. +

+ +

Here is sample code + to register an OnConsoleStatusListener instance with the + StatusManager. +

+ +
   LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); 
+   StatusManager statusManager = lc.getStatusManager();
+   OnConsoleStatusListener onConsoleListener = new OnConsoleStatusListener();
+   statusManager.add(onConsoleListener);
+ +

Note that the registered status listener will receive status + events subsequent to its registration. It will not receive prior + messages.

+ +

It is also possible to register one or more status listeners + within a configuration file. Here is an example.

+ +

Example 3.: Registering a status listener (logback-examples/src/main/java/chapter3/onConsoleStatusListener.xml)

+ +
<configuration>
+  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />  
+
+  ... the rest of the configuration file  
+</configuration>
+ +

One may also register a status listener by setting the + "logback.statusListenerClass" Java system property to the name of + the listener class you wish to register. For example, +

+ +

java -Dlogback.statusListenerClass=ch.qos.logback.core.status.OnConsoleStatusListener ...

+ + + + +

+ Configuration file Syntax +

+ +

To obtain these different logging behaviors we do not need to + recompile code. You can easily configure logback so as to disable + logging for certain parts of your application, or direct output to a + UNIX Syslog daemon, to a database, to a log visualizer, or forward + logging events to a remote logback server, which would log according + to local server policy, for example by forwarding the log event to a + second logback server. +

+ +

The remainder of this section presents the syntax of + configuration files. +

+ +

As shall become clear, the syntax of logback configuration files + is extremely flexible. As such, it is not possible to specify the + allowed syntax with a DTD file or an XML schema. Nevertheless, the + very basic structure of the configuration file can be described as, + <configuration> element, followed by zero or more <appender> + elements, followed by zero or more <logger> elements, followed by + at most one <root> element. The following diagram illustrates + this basic structure.

+ + +

+ basic Syntax +

+ + +
+

If you are unsure which case to use for a given tag name, just + follow the camelCase convention which should usually be + corrrect.

+
+ +

As of logback version 0.9.17, tag names pertaining to explicit + rules are case insensitive. For example, both + <logger>, <Logger> and + <LOGGER> are valid configuration elements and will + be interpreted in the same way. Note that XML well-formedness rules + still apply, if you open a tag as <xyz> you must + close it as </xyz>, </XyZ> will not + work. As for implicit rules, tag + names are case sensitive except for the first letter. Thus, + <xyz> and <Xyz> are equivalent but + not <xYz>. Implicit rules usually follow the camel case + convention, common in the Java world. Since it is not trivially easy + tell when a tag is associated with an explicit action and when it is + associated with an implicit action, it is not trivial to say whether + an XML tag is totally case-insensitive or case-insensitive with + respect to the first letter. If you are unsure which case to use for + a given tag name, just follow the camelCase convention which should + usually be correct. +

+ +

Configuring Loggers, or the <logger> element

+ +

A logger is configured using the logger element. A + logger element takes exactly one mandatory name attribute, an optional level attribute, and an optional additivity attribute, which admits the values + true or false. The value of the level attribute can be one of the + case-insensitive strings TRACE, DEBUG, INFO, WARN, ERROR, ALL or + OFF. The special case-insensitive value INHERITED, or its + synonym NULL, will force the level of the logger to be + inherited from higher up in the hierarchy. This comes in handy in + case you set the level of a logger and later decide that it should + inherit its level. +

+ +

The logger element may contain zero or more + appender-ref elements; each appender thus referenced is + added to the named logger. It is important to keep mind that each + named logger that is declared with a <logger element first has + all its appenders removed and only then are the referenced appenders + attached to it. In particular, if there are no appender references, + then the named logger will lose all its appenders. +

+ + + +

Configuring the root logger, or the <root> + element

+ + + +

The <root> element configures the root logger. It admits a + single attribute, namely the level + attribute. It does not admit any other attributes because the + additivity flag does not apply to the root logger. Moreover, since + the root logger is already named as "ROOT", it does not admit a name + attribute either. The value of the level attribute can be set to one + of the case-insensitive strings TRACE, DEBUG, INFO, WARN, ERROR, ALL + or OFF. Note that the level of the root logger cannot be set to + INHERITED or NULL. +

+ + +

The <root> element admits zero or more <appender-ref> + elements. Similar to the <logger element, declaring a <root + element will have the effect of first closing and then detaching all + its current appenders and only subsequently will referenced + appenders, if any, will be added. In particular, if it has no + appender references, then the root logger will lose all its + appenders. +

+ +

Example

+ +

Setting the level of a logger or root logger is as simple as + declaring it and setting its level, as the next example + illustrates. Suppose we are no longer interested in seeing any DEBUG + messages from any component belonging to the "chapter3" package. The + following configuration file shows how to achieve that. +

+ +Example 3.: Setting the level of a logger (logback-examples/src/main/java/chapter3/sample2.xml) +
<configuration>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <logger name="chapter3" level="INFO"/>
+
+  <!-- Strictly speaking, the level attribute is not necessary since -->
+  <!-- the level of the root level is set to DEBUG by default.       -->
+  <root level="DEBUG">		
+    <appender-ref ref="STDOUT" />
+  </root>  
+  
+</configuration>
+ +

This new configuration will yield the following output, when + invoked with the MyApp3 application. +

+ +
17:34:07.578 [main] INFO  chapter3.MyApp3 - Entering application.
+17:34:07.578 [main] INFO  chapter3.MyApp3 - Exiting application.
+ +

You can configure the levels of as many loggers as you wish. In + the next configuration file, we set the level of the + chapter3 logger to INFO but at the same time set the level + of the chapter3.Foo logger to DEBUG. +

+ +Example 3.: Setting the level of multiple loggers (logback-examples/src/main/java/chapter3/sample3.xml) +
<configuration>
+
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>
+        %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+     </Pattern>
+    </layout>
+  </appender>
+
+  <logger name="chapter3" level="INFO" />
+  <logger name="chapter3.Foo" level="DEBUG" />
+
+  <root level="DEBUG">
+    <appender-ref ref="STDOUT" />
+  </root>
+
+</configuration>
+ +

Running MyApp3 with this configuration file will + result in the following output on the console: +

+ +

17:39:27.593 [main] INFO chapter3.MyApp3 - Entering application. +17:39:27.593 [main] DEBUG chapter3.Foo - Did it again! +17:39:27.593 [main] INFO chapter3.MyApp3 - Exiting application.

+ +

The table below list the loggers and their levels, after + JoranConfigurator has configured logback with the + sample3.xml configuration file. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Logger nameAssigned LevelEffective Level
rootDEBUGDEBUG
chapter3INFOINFO
chapter3.MyApp3nullINFO
chapter3.FooDEBUGDEBUG
+ +

It follows that the two logging statements of level + INFO in the MyApp3 class as well as the + DEBUG messages in Foo.doIt() are all enabled. Note that + the level of the root logger is always set to a non-null value, + which is DEBUG by default. +

+ +

Let us note that the basic-selection rule + depends on the effective level of the logger being invoked, not the + level of the logger where appenders are attached. Loback will first + determine wheteher a logging statement is enabled or not, and if + enabled, it will invoke the appenders found in the logger hierarchy, + regardless of their level. The configuration file + sample4.xml is a case in point: +

+ + Example 3.: Logger level sample + (logback-examples/src/main/java/chapter3/sample4.xml) +
<configuration>
+
+  <appender name="STDOUT"
+   class="ch.qos.logback.core.ConsoleAppender">
+   <layout class="ch.qos.logback.classic.PatternLayout">
+     <Pattern>
+        %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+      </Pattern>
+    </layout>
+  </appender>
+
+  <logger name="chapter3" level="INFO" />
+
+  <!-- turn OFF all logging (children can override) -->
+  <root level="OFF">
+    <appender-ref ref="STDOUT" />
+  </root>
+
+</configuration>
+ +

The following table lists the loggers and their levels after + applying the sample4.xml configuration file. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Logger nameAssigned LevelEffective Level
rootOFFOFF
chapter3INFOINFO
chapter3.MyApp3nullINFO
chapter3.FoonullINFO
+ +

The ConsoleAppender named STDOUT, the only configured + appender in sample4.xml, is attached to the root logger + whose level is set to OFF. However, running + MyApp3 with configuration script sample4.xml will + yield: +

+ +
17:52:23.609 [main] INFO chapter3.MyApp3 - Entering application.
+17:52:23.609 [main] INFO chapter3.MyApp3 - Exiting application.
+ +

Thus, the level of the root logger has no apparent effect because + the loggers in chapter3.MyApp3 and + chapter3.Foo classes are all enabled for the + INFO level. As a side note, the chapter3 + logger exists by virtue of its declaration in the configuration file + - even if the Java source code does not directly refer to it. +

+ +

Configuring Appenders

+ +

Appenders are configured using <appender> + elements, taking two attributes name and + class, both of which are mandatory. The + name attribute specifies the name of the + appender whereas the class attribute + specifies the fully qualified name of the class of which the named + appender will be an instance. The <appender> + element may contain zero or one <layout> elements + and zero or more <filter> elements. Appart from + these two common elements, <appender> elements may + contain any number of element corresponding to javabean properties + of the appender class. Seamlessly supporting any property of a given + logback component is one of the major strengths of Joran. The + following diagram illustrates the common structure. Note that + support for properties is not visible. +

+ +

+ Appender Syntax +

+ +

The <layout> element takes a mandatory class + attribute specifying the fully qualified name of the class of which + the associated layout should be an instance. Like the + <appender> element, it may contain other elements + corresponding to properties of the layout class. +

+ +

Logging to multiple appenders is as easy as defining the various + appenders and referencing them in a logger, as the next + configuration file illustrates: +

+ +Example 3.: Multiple loggers (logback-examples/src/main/java/chapter3/multiple.xml) +
<configuration>
+
+  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+    <file>myApp.log</file>
+
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="FILE" />
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

This configuration scripts defines two appenders called + FILE and STDOUT. The FILE appender logs + to a file called myApp.log. The layout for this appender is + a PatternLayout that outputs the date, level, thread + name, logger name, file name and line number where the log request + is located, the message and line separator character(s). The second + appender called STDOUT outputs to the console. The + layout for this appender outputs only the message string followed by + a line separator. +

+ +

The appenders are attached to the root logger by referencing them + by name within an appender-ref element. Note that each + appender has its own layout. Layouts are usually not designed to be + shared by multiple appenders. As such, logback configuration files + do not provide any syntactical means for sharing layouts. +

+ +

By default, appenders are cumulative: a logger will log to + the appenders attached to itself (if any) as well as all the + appenders attached to its ancestors. Thus, attaching the same + appender to multiple loggers will cause logging output to be + duplicated. +

+ + Example 3.: Duplicate appender + (logback-examples/src/main/java/chapter3/duplicate.xml) +
<configuration>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <logger name="chapter3">
+    <appender-ref ref="STDOUT" />
+  </logger>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

Running MyApp3 with duplicate.xml will + yield the following output: +

+ +

14:25:36.343 [main] INFO chapter3.MyApp3 - Entering application. +14:25:36.343 [main] INFO chapter3.MyApp3 - Entering application. +14:25:36.359 [main] DEBUG chapter3.Foo - Did it again! +14:25:36.359 [main] DEBUG chapter3.Foo - Did it again! +14:25:36.359 [main] INFO chapter3.MyApp3 - Exiting application. +14:25:36.359 [main] INFO chapter3.MyApp3 - Exiting application.

+ +

Notice the duplicated output. The appender named STDOUT + is attached to two loggers, to root and to chapter3. Since + the root logger is the ancestor of all loggers and chapter3 + is the parent of chapter3.MyApp3 and chapter3.Foo, + logging request made with these two loggers will be output twice, + once because STDOUT is attached to chapter3 and + once because it is attached to root. +

+ +

Appender additivity is not intended as a trap for new users. It + is a quite convenient logback feature. For instance, you can + configure logging such that log messages appear on the console (for + all loggers in the system) while messages only from some specific + set of loggers flow into a specific appender. +

+ + Example 3.: Multiple appender + (logback-examples/src/main/java/chapter3/restricted.xml) +
<configuration>
+
+  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+    <file>myApp.log</file>
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <logger name="chapter3">
+    <appender-ref ref="FILE" />
+  </logger>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

In this example, the console appender will log all the messages + (for all loggers in the system) whereas only logging request + originating from loggers chapter3 and below go into the + myApp.log file. +

+ +

Overriding the default cumulative behaviour

+ +

In case the default cumulative behavior turns out to be + unsuitable for your needs, you can override it by setting the + additivity flag to false. Thus, a branch in your logger tree may + direct output to a set of appenders different than those of the rest + of the tree. +

+ +Example 3.: Additivity flag (logback-examples/src/main/java/chapter3/additivityFlag.xml) +
<configuration>
+
+  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+    <file>foo.log</file>
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%date %level [%thread] %logger{10} [%file : %line] %msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <logger name="chapter3.Foo" additivity="false">
+    <appender-ref ref="FILE" />
+  </logger>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

This example, the appender named FILE is attached to the + chapter3.Foo logger. Moreover, the chapter3.Foo + logger has its additivity flag set to false such that its logging + output will be sent to the appender named FILE but not to + any appender attached higher in the hierarchy. Other loggers remain + oblivious to the additivity setting of the chapter3.Foo + logger. Running the MyApp3 application with the + additivityFlag.xml configuration file will output results + on the console from the chapter3.MyApp3 logger. However, + output from the chapter3.Foo logger will appear in the + foo.log file and only in that file. +

+ +

Variable substitution

+ +

In principle, variable substitution can occur at any point where + a value can be specified. The syntax of variable substitution is + similar to that of Unix shells. The string between an opening + ${ and closing } is interpreted as a key. The + value of the substituted variable can be defined in the + configuration file itself, in an external properties file or as a + system property. The corresponding value replaces ${aKey} + sequence. For example, if java.home.dir system property is + set to /home/xyz, then every occurrence of the sequence + ${java.home.dir} will be interpreted as /home/xyz. +

+ +

properties are inserted into the logger context

+ +

Note that the values defined via <property> + element are actually inserted into the logger context. In other + words, they become properties of the logger context. Consequently, + they will be available in all logging events as well as remotely + after serialization.

+ +

The next example shows a variable, a.k.a. a substitution + property, declared the beginning of the configuration file. It is + then used further down the file to specify the location of the + output file. +

+ + Example 3.: Simple Variable substitution + (logback-examples/src/main/java/chapter3/variableSubstitution1.xml) + + +
<configuration>
+
+  <property name="USER_HOME" value="/home/sebastien" />
+
+  <appender name="FILE"
+    class="ch.qos.logback.core.FileAppender">
+    <file>${USER_HOME}/myApp.log</file>
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+ + +

The next example shows the use of a System property to achieve + the same result. The property is not declared in the configuration + file, thus logback will look for it in the System properties. Java + system properties can be set on the command line. +

+ +

java -DUSER_HOME="/home/sebastien" MyApp2

+ + Example 3.: System Variable substitution + (logback-examples/src/main/java/chapter3/variableSubstitution2.xml) + + +
<configuration>
+
+  <appender name="FILE"
+    class="ch.qos.logback.core.FileAppender">
+    <file>${USER_HOME}/myApp.log</file>
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+ + +

When multiple variables are needed, it may be more convenient to + create a separate file that will contain all the variables. Here is + how one can do such a setup. +

+ + Example 3.: Variable substitution using a + separate file + (logback-examples/src/main/java/chapter3/variableSubstitution3.xml) + + +
<configuration>
+
+  <property file="src/main/java/chapter3/variables1.properties" />
+
+  <appender name="FILE"
+     class="ch.qos.logback.core.FileAppender">
+     <file>${USER_HOME}/myApp.log</file>
+     <layout class="ch.qos.logback.classic.PatternLayout">
+       <Pattern>%msg%n</Pattern>
+     </layout>
+   </appender>
+
+   <root level="debug">
+     <appender-ref ref="FILE" />
+   </root>
+</configuration>
+ +

This configuration file contains a reference to a file named + variables1.properties. The variables contained in that + file will be read defined within the context of the logback + configuration file. Here is what the variable.properties + file might look like. +

+ + Example 3.: Variable file + (logback-examples/src/main/java/chapter3/variables1.properties) + +
USER_HOME=/home/sebastien
+ +

You may also reference a resource on the class path instead of a + file.

+ +
<configuration>
+
+  <property resource="resource1.properties" />
+
+  <appender name="FILE"
+     class="ch.qos.logback.core.FileAppender">
+     <file>${USER_HOME}/myApp.log</file>
+     <layout class="ch.qos.logback.classic.PatternLayout">
+       <Pattern>%msg%n</Pattern>
+     </layout>
+   </appender>
+
+   <root level="debug">
+     <appender-ref ref="FILE" />
+   </root>
+</configuration>
+ +

Nested variable substitution

+ +

Nested variabled subsitution is also supported. By nested, we + mean that the value definition of a variable contains references to + other variables. Suppose you wish to use variables to specify not + only the destination directory but also the file name, and combine + those two variables in a third variable called "destination". The + properties file shown below gives an example. +

+ + + Example 3.: Nested variable references + (logback-examples/src/main/java/chapter3/variables2.properties) + +
USER_HOME=/home/sebastien
+fileName=myApp.log
+destination=${USER_HOME}/${fileName}
+ +

Note that in the properties file above, "destination" is + composed out of two other variables, namely "USER_HOME" and + "fileName". +

+ + Example 3.: Variable substitution using + a separate file + (logback-examples/src/main/java/chapter3/variableSubstitution4.xml) + +
<configuration>
+
+  <property file="variables2.properties" />
+
+  <appender name="FILE"
+    class="ch.qos.logback.core.FileAppender">
+    <file>${destination}</file>
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+ +

Default substitution values for + variables

+ +

Under certain circumstances, it may be desirable for a variable + to have a default value in case it is not declared or its value is + null. As in the Bash + shell, default values can be specified using the ":-" + operator. For example, assuming aKey is not defined, + "${aKey:-golden}" will be interpreted as + "golden".

+ + + +

File + inclusion

+ +

Joran supports including parts of a configuration file from + another file. This is done by declaring a <include> + element, as shown below: +

+ + Example 3.: File include + (logback-examples/src/main/java/chapter3/containingConfig.xml) + +
<configuration>
+  <include file="src/main/java/chapter3/includedConfig.xml"/>
+
+  <root level="DEBUG">
+    <appender-ref ref="includedConsole" />
+  </root>
+
+</configuration>
+ +

The target file MUST have its elements nested inside an + <included> element. For example, a + ConsoleAppender could be declared as: +

+ + Example 3.: File include + (logback-examples/src/main/java/chapter3/includedConfig.xml) + +
<included>
+  <appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>"%d - %m%n"</Pattern>
+    </layout>
+  </appender>
+</included>
+ +

The file to be included can be referenced as a file, as a URL or + as a resource. To reference a file use the file attribute. To reference a URL use the url attribute. To reference a resource, use the + resource attribute. +

+ + +

Setting the context name

+ +

As mentioned in an + earlier chapter, every logger is attached to logger context. By + default, the logger context is called "default". However, you can + set a different name with the help of the + <contextName> configuration directive. Note that + once set, the logger context name cannot + be changed. Setting the context name is a simple and + straightforward method in order to distinguish between multiple + applications logging to the same target. +

+ + Example 3.: Set the context name and display it + (logback-examples/src/main/java/chapter3/contextName.xml) +
<configuration>
+  <contextName>myAppName</contextName>
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

This last examples illustrates naming of the logger + context. Adding the the contextName conversion word + in layout's pattern will output the said name.

+ +

Obtaining + variables from JNDI

+ +

Under certain circumstances, you may want to make use of + env-entries stored in JNDI. The <insertFromJNDI> + configuration directive extracts an env-entry stored in JNDI and + inserts it as variable as specified by the as attribute. +

+ + Example 3.: Insert as properties env-entries obtained via JNDI + (logback-examples/src/main/java/chapter3/insertFromJNDI.xml) +
<configuration>
+  <insertFromJNDI env-entry-name="java:comp/env/appName" as="appName" />
+  <contextName>${appName}</contextName>
+
+  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%d %contextName %level %msg %logger{50}%n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="DEBUG">
+    <appender-ref ref="CONSOLE" />
+  </root>
+</configuration>
+ +

In this last example, the "java:comp/env/appName" env-entry is + inserted as the appName property. Note + that the <contextName> directive sets the context + name based on the value of the appName + property inserted by the previous <insertFromJNDI> + directive.. + +

+ + +
+ + diff --git a/logback-site/src/site/pages/manual/filters.html b/logback-site/src/site/pages/manual/filters.html index b2aa23cd0855e237a1abc93d18425f9c845cfeee..46a2f6825022858b96e378b38e4a541fcdcd63f1 100644 --- a/logback-site/src/site/pages/manual/filters.html +++ b/logback-site/src/site/pages/manual/filters.html @@ -1,954 +1,954 @@ - - - - - - Chapter 6: Filters - - - - - - - - - - -
- - -
- -
- -

Chapter 6: Filters

- -
-

Have lots of ideas and throw away the bad ones. You aren't - going to have good ideas unless you have lots of ideas and some - sort of principle of selection.

- -

—LINUS PAULING

-
- - - - -

In the preceding chapters, the basic selection rule, - which lies at the heart of logback-classic, has been presented. In - this chapter, additional filtering methods will be introduced. -

- - -

Logback filters are based on ternary logic allowing them to be - assembled or chained together to compose an arbitrarily complex - filtering policy. They are largely inspired by Linux's iptables. -

- - - -

In logback-classic

- - -

Logback-classic offers two types of filters, regular filters - and turbo filters. -

- -

Regular filters

- -

Regular logback-classic filters extend the Filter - abstract class which essentially consists of a single method, - decide() method taking an ILoggingEvent - instance as parameter. -

- - -

Filters are organized as an ordered list and are based on - ternary logic. The decide(ILoggingEvent event) method - of each filter is called in sequence. This method returns one of - the FilterReply - enumeration values, i.e. one of DENY, - NEUTRAL or ACCEPT. If the value - returned by decide() is DENY, then the - log event is dropped immediately without consulting the remaining - filters. If the value returned is NEUTRAL, then the - next filter in the list is consulted. If there are no further - filters to consult, then the logging event is processed normally. - If the returned value is ACCEPT, then the logging - event is processed immediately skipping the invocation of the - remaining filters. -

- -

In logback-classic, filters can be added to - Appender instances. By adding one or more filters to - an appender, you can filter events by arbitrary criteria, such as - the contents of the log message, the contents of the MDC, the time - of day or any other part of the logging event. -

- -

Implementing your own Filter

- -

Creating your own filter is easy. All you have to do is extend - the Filter abstract class and implement the - decide() method. -

- -

The SampleFilter class shown below provides an example. Its - decide method returns ACCEPT for logging events - containing the string "sample" in its message field. For other - events, the value NEUTRAL is returned. -

- -Example 6.: Basic custom filter (logback-examples/src/main/java/chapter6/SampleFilter.java) -
package chapter6;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.filter.Filter;
-import ch.qos.logback.core.spi.FilterReply;
-
-public class SampleFilter extends Filter>ILoggingEvent> {
-
-  @Override
-  public FilterReply decide(ILoggingEvent event) {    
-    if (event.getMessage().contains("sample")) {
-      return FilterReply.ACCEPT;
-    } else {
-      return FilterReply.NEUTRAL;
-    }
-  }
-}
- -

The configutation files shown next attaches a - SampleFilter to a ConsoleAppener. -

- -Example 6.: SampleFilter configuration (logback-examples/src/main/java/chapter6/SampleFilterConfig.xml) -
<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-
-    <Filter class="chapter6.SampleFilter" />
-
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <pattern>
-        %-4relative [%thread] %-5level %logger - %msg%n
-      </pattern>
-    </layout>
-  </appender>
-	
-  <root>
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

With the help of Joran, logback's configuration framework, - specifiying properties or sub-componenets to filters is also - easy. After adding the corresponding setter method in the filter - class, specify the value of the property in an xml element named - after the property, nesting it within <filter> - element. -

- -

Often times, the desired filter logic consists of two - orthogonal parts, a match/mismatch test and a response depending - on the match/mismatch. For example, for a given test, say message - equals "foobar", one filter might respond ACCEPT on match and - NEUTRAL on mismatch, and another filter might respond NEUTRAL on - match and DENY on mismatch. -

- -

Taking notice of this orthogonality, logback ships with the - AbstractMatcherFilter class which provides a - useful skeleton for specifiying the appropriate response on match - and on mistmatch, with the help of two properties, named - OnMatch and OnMismatch. Most of the regular - filters included in logback are derived from - AbstractMatcherFilter. -

- -

LevelFilter

- -

- LevelFilter filters events based on exact level - matching. If the event's level is equal to the configured level, - the filter accepts or denies the event, depending on the - configuration of the onMatch and onMismatch properties. Here is a sample - configuration file. -

- -Example 6.: Sample LevelFilter configuration (logback-examples/src/main/java/chapter6/levelFilterConfig.xml) -
<configuration>
-  <appender name="CONSOLE"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <filter class="ch.qos.logback.classic.filter.LevelFilter">
-      <level>INFO</level>
-      <onMatch>ACCEPT</onMatch>
-      <onMismatch>DENY</onMismatch>
-    </filter>
-    <layout>
-      <pattern>
-        %-4relative [%thread] %-5level %logger{30} - %msg%n
-      </pattern>
-    </layout>
-  </appender>
-  <root level="DEBUG">
-    <appender-ref ref="CONSOLE" />
-  </root>
-</configuration>
- -

ThresholdFilter

- -

The - ThresholdFilter filters events below the - specified threshold. For events of level equal or above the - threshold, ThresholdFilter will respond NEUTRAL when - its decide() method is invoked. However, events with - a level below the threshold will be denied. Here is a sample - configuration file. -

- -Example 6.: Sample ThresholdFilter configuration (logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml) -
<configuration>
-  <appender name="CONSOLE"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
-    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-      <level>INFO</level>
-    </filter>
-    <layout>
-      <pattern>
-        %-4relative [%thread] %-5level %logger{30} - %msg%n
-      </pattern>
-    </layout>
-  </appender>
-  <root level="DEBUG">
-    <appender-ref ref="CONSOLE" />
-  </root>
-</configuration>
- - -

EvaluatorFilter

- -

EvaluatorFilter - is a generic filter encapsulating an - EventEvaluator which evaluates whether a given - criteria is met. On match and respectively on mismatch, the - EvaluatorFilter will return the value set for the - OnMatch and respectively for the OnMismatch properties. -

- -

The EventEvaluator is an abstract class and you - can implement your own event evaluation logic by sub-classing - EventEvaluator. However, logback-classic also ships - with a concrete evaluator implementation called JaninoEventEvaluator - which takes artibtrary java language boolean expressions as the - evaluation criteria. We refer to such java language boolean - expressions as "evaulation expressions". Evaluation - expressions enable hereto unprecedented flexibility in event - filtering. -

- -

Evaluation expressions are compiled on-the-fly during the - interpretation of the configuration file. As a user, you do not - need to worry about the actual plumbing. However, it is your - reponsibility to ensure that the java-language expression is - boolean, that it evaluates to true or false.

- - -

Given that an evaluation expression acts on the current logging - event, logback automatically exports various fields of the logging - event as variables accessible from the evaluation expression. The - case-sensitive names these variables is listed below. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
eventLoggingEventThe raw logging event associated with the logging - request. All of the following variables are also available - from the event. For example, event.getMessage() - returns the same String value as the message variable - described next. -
messageStringThe raw message of the logging request. For some logger - l, when you write l.info("Hello {}", name); where - name is assigned the value "Alice", then "Hello {}" is the - message.
formatedMessageStringThe formatted message in the logging request. For some - logger l, when you write l.info("Hello {}", name); - where name is assigned the value "Alice", then "Hello Alice" - is the formatted message.
loggerStringThe name of the logger. -
loggerContextLoggerContextVOA restricted (value object) view of the logger context to which the logging event belongs to. -
levelintThe int value corresponding to the level. To help create - easily expressions involving levels, the default value - DEBUG, INFO, WARN and - ERROR are also available. Thus, using level > - INFO is a correct expression. -
timeStamp - longThe timestamp corresponding to the logging event's - creation. -
markerMarkerThe Marker object associated with the logging - request. Note that marker can be null and it is your - responsibility to check for this condition in order to avoid - NullPointerException. -
mdcMapA map containing all the MDC values at the time of the - creation of the logging event. A value can be accessed by - using the following expression: mdc.get("myKey"). -
throwablejava.lang.ThrowableIf no exception is associated with the event, then the - value of the "throwable" variable will be null. Unfortunately, - "throwable" does not survive serialization. Thus, on remote - systems, its value will always be null. For location - independent expresisons, use the throwableProxy - variable described next. -
throwableProxyIThrowableProxyA proxy for the exception associated with the logging - event. If no exception is associated with the event, then the - value of the "throwableProxy" variable will be null. In - contrast to "throwable", when an exception is associated with - an event, the value of "throwableProxy" will be non-null even - on remote systems, that is even after serialization. -
- -

Here is a concrete example.

- -Example 6.: Basic event evaluator usage (logback-examples/src/main/java/chapter6/basicEventEvaluator.xml) - -
<configuration>
-
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">      
-      <evaluator> <!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
-        <expression>message.contains("billing")</expression>
-      </evaluator>
-      <OnMismatch>NEUTRAL</OnMismatch>
-      <OnMatch>DENY</OnMatch>
-    </filter>
-    <layout>
-      <pattern>
-        %-4relative [%thread] %-5level %logger - %msg%n
-      </pattern>
-    </layout>
-  </appender>
-
-  <root level="INFO">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

The bold part in the above configuration file adds an - EvaluatorFilter to a ConsoleAppender. An - evaluator of type JaninoEventEvaluator is then - injected into the EvaluatorFilter. In the absence of - class attribute in the - <evaluator> element specified by the user, joran - will infer a default type, i.e. JaninoEventEvaluator, - for the evaluator. This is one of the few occurrences where - Joran implicitly infers the type of a component. -

- -

The expression element corresponds to the evaluation - expression just discussed. The expression - message.contains("billing") returns a boolean - value. Notice that the message variable is exported - automatically by JaninoEventEvaluator. -

- -

Given that the OnMatch property is - set to NEUTRAL and the OnMismatch - property set to DENY, this evalutor filter will drop all logging - events whose message contains the string "billing". -

- -

The FilterEvents - application issues ten logging requests, numbered 0 to 9. Let us - first run FilterEvents class without any filters: -

- -
-java chapter6.FilterEvents src/main/java/chapter6/basicConfiguration.xml
-
- -

All requests will be displayed, as shown below:

- -
0    [main] INFO  chapter6.FilterEvents - logging statement 0
-0    [main] INFO  chapter6.FilterEvents - logging statement 1
-0    [main] INFO  chapter6.FilterEvents - logging statement 2
-0    [main] DEBUG chapter6.FilterEvents - logging statement 3
-0    [main] INFO  chapter6.FilterEvents - logging statement 4
-0    [main] INFO  chapter6.FilterEvents - logging statement 5
-0    [main] ERROR chapter6.FilterEvents - billing statement 6
-0    [main] INFO  chapter6.FilterEvents - logging statement 7
-0    [main] INFO  chapter6.FilterEvents - logging statement 8
-0    [main] INFO  chapter6.FilterEvents - logging statement 9
- - - -

Suppose that we want to get rid of the "billing statement". - The basicEventEvaluator.xml configuration file listed - above filters messages containing the string "billing" which is - precisely the desired outcome.

- -

Running with basicEventEvaluator.xml:

-

java chapter6.FilterEvents src/main/java/chapter6/basicEventEvaluator.xml

-

we obtain: -

- -

0 [main] INFO chapter6.FilterEvents - logging statement 0 -0 [main] INFO chapter6.FilterEvents - logging statement 1 -0 [main] INFO chapter6.FilterEvents - logging statement 2 -0 [main] DEBUG chapter6.FilterEvents - logging statement 3 -0 [main] INFO chapter6.FilterEvents - logging statement 4 -0 [main] INFO chapter6.FilterEvents - logging statement 5 -0 [main] INFO chapter6.FilterEvents - logging statement 7 -0 [main] INFO chapter6.FilterEvents - logging statement 8 -0 [main] INFO chapter6.FilterEvents - logging statement 9

- -

Matchers

- -

While it is possible to do pattern matching by invoking the matches() - method in the String class, this incurs the cost of - compiling of a brand new Pattern object each time the - filter is invoked. To eliminate this overhead, you can predefine - one or more Matcher - objects. Once a matcher is defined, it can be repeatedly - referenced by name in the evaluator expression.

- -

An example should clarify the point:

- -Example 6.: Defining matchers in an event evaluator (logback-examples/src/main/java/chapter6/evaluatorWithMatcher.xml) - -
<configuration debug="true">
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
-      <evaluator>        
-        <matcher>
-          <Name>odd</Name>
-          <!-- filter out odd numbered statements -->
-          <regex>statement [13579]</regex>
-        </matcher>
-        
-        <expression>odd.matches(formattedMessage)</expression>
-      </evaluator>
-      <OnMismatch>NEUTRAL</OnMismatch>
-      <OnMatch>DENY</OnMatch>
-    </filter>
-    <layout>
-      <pattern>%-4relative [%thread] %-5level %logger - %msg%n</pattern>
-    </layout>
-  </appender>
-
-  <root level="DEBUG">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

Running with evaluatorWithMatcher.xml:

-

java chapter6.FilterEvents src/main/java/chapter6/evaluatorWithMatcher.xml

-

we obtain: -

- -

260 [main] INFO chapter6.FilterEvents - logging statement 0 -264 [main] INFO chapter6.FilterEvents - logging statement 2 -264 [main] INFO chapter6.FilterEvents - logging statement 4 -266 [main] ERROR chapter6.FilterEvents - billing statement 6 -266 [main] INFO chapter6.FilterEvents - logging statement 8

- -

In case you need to define additional matchers, you can do so by - adding further <matcher> elements.

- - - - - -

TurboFilters

- -

TurboFilter objects all extend the - - TurboFilter abstract class. Like the regular - filters, they use ternary logic to return their evaluation of - the logging event. -

- -

Overall, they work much like the previously mentioned - filters. However, there are two main differences between - Filter and TurboFilter objects. -

- -

TurboFilter objects are tied to the logging - context. Hence, they are called not only when a given appender is - used, but each and every time a logging request is issued. Their - scope is wider than appender-attached filters. -

- -

More importantly, they are called before the - LoggingEvent object creation. - TurboFilter objects do not require the instantiation - of a logging event to filter a logging request. As such, turbo - filters are intended for high performance filtering of logging - events, even before they are created. -

- - -

Implementing your own TurboFilter

- -

To create your own TurboFilter component, just - extend the TurboFilter abstract class. As previously, - when implementing a customized filter object, developing a custom - TurboFilter only asks that one implement the - decide() method. In the next example, we create a - slightly more complex filter: -

- -Example 6.: Basic custom TurboFilter (logback-examples/src/main/java/chapter6/SampleTurboFilter.java) -
package chapter6;
-
-import org.slf4j.Marker;
-import org.slf4j.MarkerFactory;
-
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.turbo.TurboFilter;
-import ch.qos.logback.core.spi.FilterReply;
-
-public class SampleTurboFilter extends TurboFilter {
-
-  String marker;
-  Marker markerToAccept;
-
-  @Override
-  public FilterReply decide(Marker marker, Logger logger, Level level,
-      String format, Object[] params, Throwable t) {
-
-    if (!isStarted()) {
-      return FilterReply.NEUTRAL;
-    }
-
-    if ((markerToAccept.equals(marker))) {
-      return FilterReply.ACCEPT;
-    } else {
-      return FilterReply.NEUTRAL;
-    }
-  }
-
-  public String getMarker() {
-    return marker;
-  }
-
-  public void setMarker(String markerStr) {
-    this.marker = markerStr;
-  }
-
-  @Override
-  public void start() {
-    if (marker != null && marker.trim().length() > 0) {
-      markerToAccept = MarkerFactory.getMarker(marker);
-      super.start(); 
-    }
-  }
-}
-
- -

The TurboFilter above accepts events that contain - a specific marker. If said marker is not found, then the filter - passes the responsability to the next filter in the chain. -

- -

To allow more flexibility, the marker that will be tested can - be specified in the configuration file. Hence the getter and - setter methods. We also implemented the start() - method, to check that the option has been specified during the - configuration process. -

- -

Here is a sample configuration that makes use of our newly - created TurboFilter. -

- -Example 6.: Basic custom TurboFilter configuration (logback-examples/src/main/java/chapter6/sampleTurboFilterConfig.xml) -
<configuration>
-  <turboFilter class="chapter6.SampleTurboFilter">
-    <Marker>sample</Marker>
-  </turboFilter>
-
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <pattern>
-        %-4relative [%thread] %-5level %logger - %msg%n
-      </pattern>
-    </layout>
-  </appender>
-
-  <root>
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

Logback classic ships with several TurboFilter - classes ready for use. The MDCFilter - checks the presence of a given value in the MDC whereas DynamicThresholdFilter - allows filtering based on MDC key/level threshold associations. On - the other hand, MarkerFilter - checks for the presence of a specific marker associated with the - logging request. -

- -

Here is a sample configuration, using both - MDCFilter and MarkerFilter. -

- -Example 6.: MDCFilter and MarkerFilter -configuration (logback-examples/src/main/java/chapter6/turboFilters.xml) -
<configuration>
-
-  <turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">
-    <MDCKey>username</MDCKey>
-    <Value>sebastien</Value>
-    <OnMatch>ACCEPT</OnMatch>
-  </turboFilter>
-	
-  <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
-    <Marker>billing</Marker>
-    <OnMatch>DENY</OnMatch>
-  </turboFilter>
-
-  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%date [%thread] %-5level %logger - %msg%n</Pattern>
-  </layout>
-  </appender>
-
-  <root level="info">
-    <appender-ref ref="console" />
-  </root>  
-</configuration>
- -

You can see this configuration in action by issuing the - following command: -

- -

java chapter6.FilterEvents src/main/java/chapter6/turboFilters.xml

- -

As we've seen previously, the FilterEvents - application issues 10 logging requests, numbered 0 to 9. Except - for requests 3 and 6, all of the requests are of level - INFO, the same level as the one assigned to the root - logger. The 3rd request, is issued at the the DEBUG - level, which is below the effective level. However, since the MDC - key "username" is set to "sebastien" just before the 3rd request - and removed just afterwards, the MDCFilter - specifically accepts the request (and only that request). The 6th - request, issued at the ERROR level, is marked as - "billing". As such, it is denied by the MarkerFilter (the second - turbo filter in the configuration). -

- -

Thus, the output of FilterEvents application - configured with turboFilters.xml file shown above is: -

- -

2006-12-04 15:17:22,859 [main] INFO chapter6.FilterEvents - logging statement 0 -2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 1 -2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 2 -2006-12-04 15:17:22,875 [main] DEBUG chapter6.FilterEvents - logging statement 3 -2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 4 -2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 5 -2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 7 -2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 8 -2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 9

- - -

One can see that the 3rd request, which should not be displayed - if we only followed the overall INFO level, appears - anyway, because it matched the first TurboFilter - requirements and was accepted. -

- -

On the other hand, the 6th request, that is an ERROR - level request should have been displayed. But it satisfied the - second TurboFilter whose OnMatch option is set to DENY. - Thus, the 6th request was not displayed. -

- - - - -

DuplicateMessageFilter

- -

The DuplicateMessageFilter merits a separate - presentation. This filter detects duplicate messages, and beyond - a certain number of repetitions, drops repeated messages. -

- -

To detect repetition, this filter uses simple String equality - between messages. It does not detect messages which are very - similar, varying only by few characters. For example, if you - write: -

- -
logger.debug("Hello "+name0);
-logger.debug("Hello "+name1);
- -

Assuming name0 and name1 have - different values, the two "Hello" messages will be considered as - unrelated. Depending on user demand, future releases may check for - string similarity, eliminating repetitions of similar but not - identical messages. -

- -

Note that in case of parameterized logging, only the raw - message is taken into consideration. For example, in the next two - requests, the raw messages, i.e. "Hello {}.", are identical, and - thus considered as repetitions. -

- -
logger.debug("Hello {}.", name0);
-logger.debug("Hello {}.", name1);
- -

The number of allowed repetitions can be specified by the AllowedRepetitions property. For example, if - the said property is set to 1, then the 2nd and subsequent - occurrences of the same message will be dropped. Similarly, if the - said property is set to 2, then the 3rd and subsequent occurrences - of the same message will be dropped. By default, the AllowedRepetitions property is set to 5. -

- -

In order to detect repetitions, this filter needs to keep - references to old messages in an internal cache. The size of this - cache is determined by the CacheSize - property. By the default, this is set to 100. -

- - -Example 6.: DuplicateMessageFilter -configuration (logback-examples/src/main/java/chapter6/duplicateMessage.xml) -
<configuration>
-
-  <turboFilter class="ch.qos.logback.classic.turbo.DuplicateMessageFilter"/>
-
-  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%date [%thread] %-5level %logger - %msg%n</Pattern>
-  </layout>
-  </appender>
-
-  <root level="info">
-    <appender-ref ref="console" />
-  </root>  
-</configuration>
- -

Thus, the output for FilterEvents application - configured with duplicateMessage.xml is: -

- -

2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 0 -2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 1 -2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 2 -2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 4 -2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 5 -2008-12-19 15:04:26,171 [main] ERROR chapter6.FilterEvents - billing statement 6

- -

"logging statement 0" is the first occurrence of the - message "logging statement {}". "logging statement 1" is the first - repetition, "logging statement 2" is the second - repetition. Interestingly enough, "logging statement 3" of level - DEBUG, is the third repetition, even though it is later - dropped by virtue of the basic selection - rule. This can be explained by the fact that turbo filters are - invoked before other types of filters, including the basic - selection rule. Thus, DuplicateMessageFilter - considers "logging statement 3" as a repetition, oblivious to the - fact that it will be dropped further down in the processing - chain. "logging statement 4" is the fourth repetition and "logging - statement 5" the fifth. Statements 6 and beyond are dropped - because only 5 repetitions are allowed by default. -

- -

In logback-access

- -

Logback-access offers most of the features available with - logback-classic. Filter objects are available and - work in the same way as their logback-classic counterparts. They - handle access' implementation of logging events: - AccessEvent. Thus, a customized filter for logback - access follows strictly the same rules as those for - logback-classic, except for the event type received as parameter. - On the other hand, TurboFilter objects are supported - by logback-access. -

- -

Filters

- -

EvaluatorFilter objects with java expressions - supplied in in evaluator configuration elements are - supported by logback-access. However, list implicit variables - available for constructing an expression are different. Only the - AccessEvent object can be used by inserting the - event variable in the expression. Nevertheless the access - evaluator is just as powerfull. All the request and - response components are reachable from the event - variable. -

- -

Here is a sample configuration that will ensure that any 404 - error will be logged: -

- -Example 6.: Access Evaluator (logback-examples/src/main/java/chapter6/accessEventEvaluator.xml) -
<configuration>
-
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
-      <evaluator name="myEval">
-        <expression>event.getStatusCode() == 404</expression>
-      </evaluator>
-      <OnMismatch>NEUTRAL</OnMismatch>
-      <OnMatch>ACCEPT</OnMatch>
-    </filter>
-    <layout class="ch.qos.logback.access.PatternLayout">
-      <pattern>
-        %h %l %u %t %r %s %b
-      </pattern>
-    </layout>
-  </appender>
-
-  <appender-ref ref="STDOUT" />
-</configuration>
- -

We might imagine a slightly more complex use of filters to - ensure logging of 404 errors, except those returned on access to - CSS resources. Here is what such a configuration would look like: -

- - Example 6.10: Access Evaluator (logback-examples/src/main/java/chapter6/accessEventEvaluator2.xml) -
<configuration>
-
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
-      <evaluator name="Eval404">
-        <expression>event.getStatusCode() == 404</expression>
-      </evaluator>
-      <OnMismatch>NEUTRAL</OnMismatch>
-      <OnMatch>ACCEPT</OnMatch>
-    </filter>
-    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
-      <evaluator name="EvalCSS">
-        <expression>event.getRequestURI().contains("css")</expression>
-      </evaluator>
-      <OnMismatch>NEUTRAL</OnMismatch>
-      <OnMatch>DENY</OnMatch>
-    </filter>
-    <layout class="ch.qos.logback.access.PatternLayout">
-      <pattern>
-        %h %l %u %t %r %s %b
-      </pattern>
-    </layout>
-  </appender>
-
-  <appender-ref ref="STDOUT" />
-</configuration>
-    
- - - -
- - + + + + + + Chapter 6: Filters + + + + + + + + + + +
+ + +
+ +
+ +

Chapter 6: Filters

+ +
+

Have lots of ideas and throw away the bad ones. You aren't + going to have good ideas unless you have lots of ideas and some + sort of principle of selection.

+ +

—LINUS PAULING

+
+ + + + +

In the preceding chapters, the basic selection rule, + which lies at the heart of logback-classic, has been presented. In + this chapter, additional filtering methods will be introduced. +

+ + +

Logback filters are based on ternary logic allowing them to be + assembled or chained together to compose an arbitrarily complex + filtering policy. They are largely inspired by Linux's iptables. +

+ + + +

In logback-classic

+ + +

Logback-classic offers two types of filters, regular filters + and turbo filters. +

+ +

Regular filters

+ +

Regular logback-classic filters extend the Filter + abstract class which essentially consists of a single method, + decide() method taking an ILoggingEvent + instance as parameter. +

+ + +

Filters are organized as an ordered list and are based on + ternary logic. The decide(ILoggingEvent event) method + of each filter is called in sequence. This method returns one of + the FilterReply + enumeration values, i.e. one of DENY, + NEUTRAL or ACCEPT. If the value + returned by decide() is DENY, then the + log event is dropped immediately without consulting the remaining + filters. If the value returned is NEUTRAL, then the + next filter in the list is consulted. If there are no further + filters to consult, then the logging event is processed normally. + If the returned value is ACCEPT, then the logging + event is processed immediately skipping the invocation of the + remaining filters. +

+ +

In logback-classic, filters can be added to + Appender instances. By adding one or more filters to + an appender, you can filter events by arbitrary criteria, such as + the contents of the log message, the contents of the MDC, the time + of day or any other part of the logging event. +

+ +

Implementing your own Filter

+ +

Creating your own filter is easy. All you have to do is extend + the Filter abstract class and implement the + decide() method. +

+ +

The SampleFilter class shown below provides an example. Its + decide method returns ACCEPT for logging events + containing the string "sample" in its message field. For other + events, the value NEUTRAL is returned. +

+ +Example 6.: Basic custom filter (logback-examples/src/main/java/chapter6/SampleFilter.java) +
package chapter6;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.filter.Filter;
+import ch.qos.logback.core.spi.FilterReply;
+
+public class SampleFilter extends Filter>ILoggingEvent> {
+
+  @Override
+  public FilterReply decide(ILoggingEvent event) {    
+    if (event.getMessage().contains("sample")) {
+      return FilterReply.ACCEPT;
+    } else {
+      return FilterReply.NEUTRAL;
+    }
+  }
+}
+ +

The configutation files shown next attaches a + SampleFilter to a ConsoleAppener. +

+ +Example 6.: SampleFilter configuration (logback-examples/src/main/java/chapter6/SampleFilterConfig.xml) +
<configuration>
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+
+    <Filter class="chapter6.SampleFilter" />
+
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <pattern>
+        %-4relative [%thread] %-5level %logger - %msg%n
+      </pattern>
+    </layout>
+  </appender>
+	
+  <root>
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

With the help of Joran, logback's configuration framework, + specifiying properties or sub-componenets to filters is also + easy. After adding the corresponding setter method in the filter + class, specify the value of the property in an xml element named + after the property, nesting it within <filter> + element. +

+ +

Often times, the desired filter logic consists of two + orthogonal parts, a match/mismatch test and a response depending + on the match/mismatch. For example, for a given test, say message + equals "foobar", one filter might respond ACCEPT on match and + NEUTRAL on mismatch, and another filter might respond NEUTRAL on + match and DENY on mismatch. +

+ +

Taking notice of this orthogonality, logback ships with the + AbstractMatcherFilter class which provides a + useful skeleton for specifiying the appropriate response on match + and on mistmatch, with the help of two properties, named + OnMatch and OnMismatch. Most of the regular + filters included in logback are derived from + AbstractMatcherFilter. +

+ +

LevelFilter

+ +

+ LevelFilter filters events based on exact level + matching. If the event's level is equal to the configured level, + the filter accepts or denies the event, depending on the + configuration of the onMatch and onMismatch properties. Here is a sample + configuration file. +

+ +Example 6.: Sample LevelFilter configuration (logback-examples/src/main/java/chapter6/levelFilterConfig.xml) +
<configuration>
+  <appender name="CONSOLE"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <filter class="ch.qos.logback.classic.filter.LevelFilter">
+      <level>INFO</level>
+      <onMatch>ACCEPT</onMatch>
+      <onMismatch>DENY</onMismatch>
+    </filter>
+    <layout>
+      <pattern>
+        %-4relative [%thread] %-5level %logger{30} - %msg%n
+      </pattern>
+    </layout>
+  </appender>
+  <root level="DEBUG">
+    <appender-ref ref="CONSOLE" />
+  </root>
+</configuration>
+ +

ThresholdFilter

+ +

The + ThresholdFilter filters events below the + specified threshold. For events of level equal or above the + threshold, ThresholdFilter will respond NEUTRAL when + its decide() method is invoked. However, events with + a level below the threshold will be denied. Here is a sample + configuration file. +

+ +Example 6.: Sample ThresholdFilter configuration (logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml) +
<configuration>
+  <appender name="CONSOLE"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
+    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+      <level>INFO</level>
+    </filter>
+    <layout>
+      <pattern>
+        %-4relative [%thread] %-5level %logger{30} - %msg%n
+      </pattern>
+    </layout>
+  </appender>
+  <root level="DEBUG">
+    <appender-ref ref="CONSOLE" />
+  </root>
+</configuration>
+ + +

EvaluatorFilter

+ +

EvaluatorFilter + is a generic filter encapsulating an + EventEvaluator which evaluates whether a given + criteria is met. On match and respectively on mismatch, the + EvaluatorFilter will return the value set for the + OnMatch and respectively for the OnMismatch properties. +

+ +

The EventEvaluator is an abstract class and you + can implement your own event evaluation logic by sub-classing + EventEvaluator. However, logback-classic also ships + with a concrete evaluator implementation called JaninoEventEvaluator + which takes artibtrary java language boolean expressions as the + evaluation criteria. We refer to such java language boolean + expressions as "evaulation expressions". Evaluation + expressions enable hereto unprecedented flexibility in event + filtering. +

+ +

Evaluation expressions are compiled on-the-fly during the + interpretation of the configuration file. As a user, you do not + need to worry about the actual plumbing. However, it is your + reponsibility to ensure that the java-language expression is + boolean, that it evaluates to true or false.

+ + +

Given that an evaluation expression acts on the current logging + event, logback automatically exports various fields of the logging + event as variables accessible from the evaluation expression. The + case-sensitive names these variables is listed below. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
eventLoggingEventThe raw logging event associated with the logging + request. All of the following variables are also available + from the event. For example, event.getMessage() + returns the same String value as the message variable + described next. +
messageStringThe raw message of the logging request. For some logger + l, when you write l.info("Hello {}", name); where + name is assigned the value "Alice", then "Hello {}" is the + message.
formatedMessageStringThe formatted message in the logging request. For some + logger l, when you write l.info("Hello {}", name); + where name is assigned the value "Alice", then "Hello Alice" + is the formatted message.
loggerStringThe name of the logger. +
loggerContextLoggerContextVOA restricted (value object) view of the logger context to which the logging event belongs to. +
levelintThe int value corresponding to the level. To help create + easily expressions involving levels, the default value + DEBUG, INFO, WARN and + ERROR are also available. Thus, using level > + INFO is a correct expression. +
timeStamp + longThe timestamp corresponding to the logging event's + creation. +
markerMarkerThe Marker object associated with the logging + request. Note that marker can be null and it is your + responsibility to check for this condition in order to avoid + NullPointerException. +
mdcMapA map containing all the MDC values at the time of the + creation of the logging event. A value can be accessed by + using the following expression: mdc.get("myKey"). +
throwablejava.lang.ThrowableIf no exception is associated with the event, then the + value of the "throwable" variable will be null. Unfortunately, + "throwable" does not survive serialization. Thus, on remote + systems, its value will always be null. For location + independent expresisons, use the throwableProxy + variable described next. +
throwableProxyIThrowableProxyA proxy for the exception associated with the logging + event. If no exception is associated with the event, then the + value of the "throwableProxy" variable will be null. In + contrast to "throwable", when an exception is associated with + an event, the value of "throwableProxy" will be non-null even + on remote systems, that is even after serialization. +
+ +

Here is a concrete example.

+ +Example 6.: Basic event evaluator usage (logback-examples/src/main/java/chapter6/basicEventEvaluator.xml) + +
<configuration>
+
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">      
+      <evaluator> <!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
+        <expression>message.contains("billing")</expression>
+      </evaluator>
+      <OnMismatch>NEUTRAL</OnMismatch>
+      <OnMatch>DENY</OnMatch>
+    </filter>
+    <layout>
+      <pattern>
+        %-4relative [%thread] %-5level %logger - %msg%n
+      </pattern>
+    </layout>
+  </appender>
+
+  <root level="INFO">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

The bold part in the above configuration file adds an + EvaluatorFilter to a ConsoleAppender. An + evaluator of type JaninoEventEvaluator is then + injected into the EvaluatorFilter. In the absence of + class attribute in the + <evaluator> element specified by the user, joran + will infer a default type, i.e. JaninoEventEvaluator, + for the evaluator. This is one of the few occurrences where + Joran implicitly infers the type of a component. +

+ +

The expression element corresponds to the evaluation + expression just discussed. The expression + message.contains("billing") returns a boolean + value. Notice that the message variable is exported + automatically by JaninoEventEvaluator. +

+ +

Given that the OnMatch property is + set to NEUTRAL and the OnMismatch + property set to DENY, this evalutor filter will drop all logging + events whose message contains the string "billing". +

+ +

The FilterEvents + application issues ten logging requests, numbered 0 to 9. Let us + first run FilterEvents class without any filters: +

+ +
+java chapter6.FilterEvents src/main/java/chapter6/basicConfiguration.xml
+
+ +

All requests will be displayed, as shown below:

+ +
0    [main] INFO  chapter6.FilterEvents - logging statement 0
+0    [main] INFO  chapter6.FilterEvents - logging statement 1
+0    [main] INFO  chapter6.FilterEvents - logging statement 2
+0    [main] DEBUG chapter6.FilterEvents - logging statement 3
+0    [main] INFO  chapter6.FilterEvents - logging statement 4
+0    [main] INFO  chapter6.FilterEvents - logging statement 5
+0    [main] ERROR chapter6.FilterEvents - billing statement 6
+0    [main] INFO  chapter6.FilterEvents - logging statement 7
+0    [main] INFO  chapter6.FilterEvents - logging statement 8
+0    [main] INFO  chapter6.FilterEvents - logging statement 9
+ + + +

Suppose that we want to get rid of the "billing statement". + The basicEventEvaluator.xml configuration file listed + above filters messages containing the string "billing" which is + precisely the desired outcome.

+ +

Running with basicEventEvaluator.xml:

+

java chapter6.FilterEvents src/main/java/chapter6/basicEventEvaluator.xml

+

we obtain: +

+ +

0 [main] INFO chapter6.FilterEvents - logging statement 0 +0 [main] INFO chapter6.FilterEvents - logging statement 1 +0 [main] INFO chapter6.FilterEvents - logging statement 2 +0 [main] DEBUG chapter6.FilterEvents - logging statement 3 +0 [main] INFO chapter6.FilterEvents - logging statement 4 +0 [main] INFO chapter6.FilterEvents - logging statement 5 +0 [main] INFO chapter6.FilterEvents - logging statement 7 +0 [main] INFO chapter6.FilterEvents - logging statement 8 +0 [main] INFO chapter6.FilterEvents - logging statement 9

+ +

Matchers

+ +

While it is possible to do pattern matching by invoking the matches() + method in the String class, this incurs the cost of + compiling of a brand new Pattern object each time the + filter is invoked. To eliminate this overhead, you can predefine + one or more Matcher + objects. Once a matcher is defined, it can be repeatedly + referenced by name in the evaluator expression.

+ +

An example should clarify the point:

+ +Example 6.: Defining matchers in an event evaluator (logback-examples/src/main/java/chapter6/evaluatorWithMatcher.xml) + +
<configuration debug="true">
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+      <evaluator>        
+        <matcher>
+          <Name>odd</Name>
+          <!-- filter out odd numbered statements -->
+          <regex>statement [13579]</regex>
+        </matcher>
+        
+        <expression>odd.matches(formattedMessage)</expression>
+      </evaluator>
+      <OnMismatch>NEUTRAL</OnMismatch>
+      <OnMatch>DENY</OnMatch>
+    </filter>
+    <layout>
+      <pattern>%-4relative [%thread] %-5level %logger - %msg%n</pattern>
+    </layout>
+  </appender>
+
+  <root level="DEBUG">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

Running with evaluatorWithMatcher.xml:

+

java chapter6.FilterEvents src/main/java/chapter6/evaluatorWithMatcher.xml

+

we obtain: +

+ +

260 [main] INFO chapter6.FilterEvents - logging statement 0 +264 [main] INFO chapter6.FilterEvents - logging statement 2 +264 [main] INFO chapter6.FilterEvents - logging statement 4 +266 [main] ERROR chapter6.FilterEvents - billing statement 6 +266 [main] INFO chapter6.FilterEvents - logging statement 8

+ +

In case you need to define additional matchers, you can do so by + adding further <matcher> elements.

+ + + + + +

TurboFilters

+ +

TurboFilter objects all extend the + + TurboFilter abstract class. Like the regular + filters, they use ternary logic to return their evaluation of + the logging event. +

+ +

Overall, they work much like the previously mentioned + filters. However, there are two main differences between + Filter and TurboFilter objects. +

+ +

TurboFilter objects are tied to the logging + context. Hence, they are called not only when a given appender is + used, but each and every time a logging request is issued. Their + scope is wider than appender-attached filters. +

+ +

More importantly, they are called before the + LoggingEvent object creation. + TurboFilter objects do not require the instantiation + of a logging event to filter a logging request. As such, turbo + filters are intended for high performance filtering of logging + events, even before they are created. +

+ + +

Implementing your own TurboFilter

+ +

To create your own TurboFilter component, just + extend the TurboFilter abstract class. As previously, + when implementing a customized filter object, developing a custom + TurboFilter only asks that one implement the + decide() method. In the next example, we create a + slightly more complex filter: +

+ +Example 6.: Basic custom TurboFilter (logback-examples/src/main/java/chapter6/SampleTurboFilter.java) +
package chapter6;
+
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.turbo.TurboFilter;
+import ch.qos.logback.core.spi.FilterReply;
+
+public class SampleTurboFilter extends TurboFilter {
+
+  String marker;
+  Marker markerToAccept;
+
+  @Override
+  public FilterReply decide(Marker marker, Logger logger, Level level,
+      String format, Object[] params, Throwable t) {
+
+    if (!isStarted()) {
+      return FilterReply.NEUTRAL;
+    }
+
+    if ((markerToAccept.equals(marker))) {
+      return FilterReply.ACCEPT;
+    } else {
+      return FilterReply.NEUTRAL;
+    }
+  }
+
+  public String getMarker() {
+    return marker;
+  }
+
+  public void setMarker(String markerStr) {
+    this.marker = markerStr;
+  }
+
+  @Override
+  public void start() {
+    if (marker != null && marker.trim().length() > 0) {
+      markerToAccept = MarkerFactory.getMarker(marker);
+      super.start(); 
+    }
+  }
+}
+
+ +

The TurboFilter above accepts events that contain + a specific marker. If said marker is not found, then the filter + passes the responsability to the next filter in the chain. +

+ +

To allow more flexibility, the marker that will be tested can + be specified in the configuration file. Hence the getter and + setter methods. We also implemented the start() + method, to check that the option has been specified during the + configuration process. +

+ +

Here is a sample configuration that makes use of our newly + created TurboFilter. +

+ +Example 6.: Basic custom TurboFilter configuration (logback-examples/src/main/java/chapter6/sampleTurboFilterConfig.xml) +
<configuration>
+  <turboFilter class="chapter6.SampleTurboFilter">
+    <Marker>sample</Marker>
+  </turboFilter>
+
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <pattern>
+        %-4relative [%thread] %-5level %logger - %msg%n
+      </pattern>
+    </layout>
+  </appender>
+
+  <root>
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

Logback classic ships with several TurboFilter + classes ready for use. The MDCFilter + checks the presence of a given value in the MDC whereas DynamicThresholdFilter + allows filtering based on MDC key/level threshold associations. On + the other hand, MarkerFilter + checks for the presence of a specific marker associated with the + logging request. +

+ +

Here is a sample configuration, using both + MDCFilter and MarkerFilter. +

+ +Example 6.: MDCFilter and MarkerFilter +configuration (logback-examples/src/main/java/chapter6/turboFilters.xml) +
<configuration>
+
+  <turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">
+    <MDCKey>username</MDCKey>
+    <Value>sebastien</Value>
+    <OnMatch>ACCEPT</OnMatch>
+  </turboFilter>
+	
+  <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
+    <Marker>billing</Marker>
+    <OnMatch>DENY</OnMatch>
+  </turboFilter>
+
+  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%date [%thread] %-5level %logger - %msg%n</Pattern>
+  </layout>
+  </appender>
+
+  <root level="info">
+    <appender-ref ref="console" />
+  </root>  
+</configuration>
+ +

You can see this configuration in action by issuing the + following command: +

+ +

java chapter6.FilterEvents src/main/java/chapter6/turboFilters.xml

+ +

As we've seen previously, the FilterEvents + application issues 10 logging requests, numbered 0 to 9. Except + for requests 3 and 6, all of the requests are of level + INFO, the same level as the one assigned to the root + logger. The 3rd request, is issued at the the DEBUG + level, which is below the effective level. However, since the MDC + key "username" is set to "sebastien" just before the 3rd request + and removed just afterwards, the MDCFilter + specifically accepts the request (and only that request). The 6th + request, issued at the ERROR level, is marked as + "billing". As such, it is denied by the MarkerFilter (the second + turbo filter in the configuration). +

+ +

Thus, the output of FilterEvents application + configured with turboFilters.xml file shown above is: +

+ +

2006-12-04 15:17:22,859 [main] INFO chapter6.FilterEvents - logging statement 0 +2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 1 +2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 2 +2006-12-04 15:17:22,875 [main] DEBUG chapter6.FilterEvents - logging statement 3 +2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 4 +2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 5 +2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 7 +2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 8 +2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 9

+ + +

One can see that the 3rd request, which should not be displayed + if we only followed the overall INFO level, appears + anyway, because it matched the first TurboFilter + requirements and was accepted. +

+ +

On the other hand, the 6th request, that is an ERROR + level request should have been displayed. But it satisfied the + second TurboFilter whose OnMatch option is set to DENY. + Thus, the 6th request was not displayed. +

+ + + + +

DuplicateMessageFilter

+ +

The DuplicateMessageFilter merits a separate + presentation. This filter detects duplicate messages, and beyond + a certain number of repetitions, drops repeated messages. +

+ +

To detect repetition, this filter uses simple String equality + between messages. It does not detect messages which are very + similar, varying only by few characters. For example, if you + write: +

+ +
logger.debug("Hello "+name0);
+logger.debug("Hello "+name1);
+ +

Assuming name0 and name1 have + different values, the two "Hello" messages will be considered as + unrelated. Depending on user demand, future releases may check for + string similarity, eliminating repetitions of similar but not + identical messages. +

+ +

Note that in case of parameterized logging, only the raw + message is taken into consideration. For example, in the next two + requests, the raw messages, i.e. "Hello {}.", are identical, and + thus considered as repetitions. +

+ +
logger.debug("Hello {}.", name0);
+logger.debug("Hello {}.", name1);
+ +

The number of allowed repetitions can be specified by the AllowedRepetitions property. For example, if + the said property is set to 1, then the 2nd and subsequent + occurrences of the same message will be dropped. Similarly, if the + said property is set to 2, then the 3rd and subsequent occurrences + of the same message will be dropped. By default, the AllowedRepetitions property is set to 5. +

+ +

In order to detect repetitions, this filter needs to keep + references to old messages in an internal cache. The size of this + cache is determined by the CacheSize + property. By the default, this is set to 100. +

+ + +Example 6.: DuplicateMessageFilter +configuration (logback-examples/src/main/java/chapter6/duplicateMessage.xml) +
<configuration>
+
+  <turboFilter class="ch.qos.logback.classic.turbo.DuplicateMessageFilter"/>
+
+  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%date [%thread] %-5level %logger - %msg%n</Pattern>
+  </layout>
+  </appender>
+
+  <root level="info">
+    <appender-ref ref="console" />
+  </root>  
+</configuration>
+ +

Thus, the output for FilterEvents application + configured with duplicateMessage.xml is: +

+ +

2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 0 +2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 1 +2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 2 +2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 4 +2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 5 +2008-12-19 15:04:26,171 [main] ERROR chapter6.FilterEvents - billing statement 6

+ +

"logging statement 0" is the first occurrence of the + message "logging statement {}". "logging statement 1" is the first + repetition, "logging statement 2" is the second + repetition. Interestingly enough, "logging statement 3" of level + DEBUG, is the third repetition, even though it is later + dropped by virtue of the basic selection + rule. This can be explained by the fact that turbo filters are + invoked before other types of filters, including the basic + selection rule. Thus, DuplicateMessageFilter + considers "logging statement 3" as a repetition, oblivious to the + fact that it will be dropped further down in the processing + chain. "logging statement 4" is the fourth repetition and "logging + statement 5" the fifth. Statements 6 and beyond are dropped + because only 5 repetitions are allowed by default. +

+ +

In logback-access

+ +

Logback-access offers most of the features available with + logback-classic. Filter objects are available and + work in the same way as their logback-classic counterparts. They + handle access' implementation of logging events: + AccessEvent. Thus, a customized filter for logback + access follows strictly the same rules as those for + logback-classic, except for the event type received as parameter. + On the other hand, TurboFilter objects are supported + by logback-access. +

+ +

Filters

+ +

EvaluatorFilter objects with java expressions + supplied in in evaluator configuration elements are + supported by logback-access. However, list implicit variables + available for constructing an expression are different. Only the + AccessEvent object can be used by inserting the + event variable in the expression. Nevertheless the access + evaluator is just as powerfull. All the request and + response components are reachable from the event + variable. +

+ +

Here is a sample configuration that will ensure that any 404 + error will be logged: +

+ +Example 6.: Access Evaluator (logback-examples/src/main/java/chapter6/accessEventEvaluator.xml) +
<configuration>
+
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+      <evaluator name="myEval">
+        <expression>event.getStatusCode() == 404</expression>
+      </evaluator>
+      <OnMismatch>NEUTRAL</OnMismatch>
+      <OnMatch>ACCEPT</OnMatch>
+    </filter>
+    <layout class="ch.qos.logback.access.PatternLayout">
+      <pattern>
+        %h %l %u %t %r %s %b
+      </pattern>
+    </layout>
+  </appender>
+
+  <appender-ref ref="STDOUT" />
+</configuration>
+ +

We might imagine a slightly more complex use of filters to + ensure logging of 404 errors, except those returned on access to + CSS resources. Here is what such a configuration would look like: +

+ + Example 6.10: Access Evaluator (logback-examples/src/main/java/chapter6/accessEventEvaluator2.xml) +
<configuration>
+
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+      <evaluator name="Eval404">
+        <expression>event.getStatusCode() == 404</expression>
+      </evaluator>
+      <OnMismatch>NEUTRAL</OnMismatch>
+      <OnMatch>ACCEPT</OnMatch>
+    </filter>
+    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+      <evaluator name="EvalCSS">
+        <expression>event.getRequestURI().contains("css")</expression>
+      </evaluator>
+      <OnMismatch>NEUTRAL</OnMismatch>
+      <OnMatch>DENY</OnMatch>
+    </filter>
+    <layout class="ch.qos.logback.access.PatternLayout">
+      <pattern>
+        %h %l %u %t %r %s %b
+      </pattern>
+    </layout>
+  </appender>
+
+  <appender-ref ref="STDOUT" />
+</configuration>
+    
+ + + +
+ + diff --git a/logback-site/src/site/pages/manual/index.html b/logback-site/src/site/pages/manual/index.html index ed93b24644308fad3b56f0d07974433889d2710e..f4ac339af183320d9d4fc7ccedc43eefd2c3dfd9 100644 --- a/logback-site/src/site/pages/manual/index.html +++ b/logback-site/src/site/pages/manual/index.html @@ -1,122 +1,122 @@ - - - - - - Logback Manual - - - - - - - - - -
- - -
- -
- -

The logback manual

- -
-

- If you wish to print chapters in this document, we recommend - that you do so using Firefox 2, with Adapt to - page size enabled, or Opera. -

-
- -

The complete logback manual documents the latest version of - logback framework. In over 150 pages and dozens of concrete - examples, it covers both basic and advanced logback features: -

- - -
-
    -
  • the overall logback architecture

  • -
  • discussion of best logback practices and anti-patterns

  • -
  • logback configuration scripts in XML format

  • -
  • appenders

  • -
  • layouts

  • -
  • filters

  • -
  • mapped diagnostic contexts

  • -
  • joran, logback's configuration system

  • -
-
- - -

The logback manual describes the logback API in considerable - detail, including its features and design rationale. Authored by - Ceki Gülcü and Sébastien Pennec, the main - contributors to the logback project, the logback manual is - intended for developers already familiar with the Java language - but new to logback, as much as for experienced logback users. With - the aid of introductory material and many examples, new users - should quickly come up to speed. -

- - - - - - -
- - + + + + + + Logback Manual + + + + + + + + + +
+ + +
+ +
+ +

The logback manual

+ +
+

+ If you wish to print chapters in this document, we recommend + that you do so using Firefox 2, with Adapt to + page size enabled, or Opera. +

+
+ +

The complete logback manual documents the latest version of + logback framework. In over 150 pages and dozens of concrete + examples, it covers both basic and advanced logback features: +

+ + +
+
    +
  • the overall logback architecture

  • +
  • discussion of best logback practices and anti-patterns

  • +
  • logback configuration scripts in XML format

  • +
  • appenders

  • +
  • layouts

  • +
  • filters

  • +
  • mapped diagnostic contexts

  • +
  • joran, logback's configuration system

  • +
+
+ + +

The logback manual describes the logback API in considerable + detail, including its features and design rationale. Authored by + Ceki Gülcü and Sébastien Pennec, the main + contributors to the logback project, the logback manual is + intended for developers already familiar with the Java language + but new to logback, as much as for experienced logback users. With + the aid of introductory material and many examples, new users + should quickly come up to speed. +

+ + + + + + +
+ + diff --git a/logback-site/src/site/pages/manual/introduction.html b/logback-site/src/site/pages/manual/introduction.html index 32d993f00c626390b0ed1b757a216e486f7f51df..909a40dd142d5540fd1b2025361732c548583668 100644 --- a/logback-site/src/site/pages/manual/introduction.html +++ b/logback-site/src/site/pages/manual/introduction.html @@ -1,292 +1,292 @@ - - - - - Chapter 1: Introduction - - - - - - - - - - -
- - -
- -
- -

Introduction

- -
-

The morale effects are startling. Enthusiasm jumps when - there is a running system, even a simple one. Efforts redouble when - the first picture from a new graphics software system appears on the - screen, even if it is only a rectangle. One always has, at every - stage in the process, a working system. I find that teams can grow - much more complex entities in four months than they can - build.

- -

—FREDERIC P. BROOKS, JR., The Mythical Man-Month

-
- - - - -

What is logback?

- -

Logback is intended as a successor to the popular log4j - project. It was designed by Ceki Gülcü, log4j's - founder. It builds upon a decade long experience gained in - designing industrial-strength logging systems. The resulting - product, logback is faster with a smaller footprint than all - existing logging systems, sometimes by a wide margin. Logback also - offers unique and rather useful features such as Markers, - parameterized logging statements, conditional stack tracing and - powerful event filtering. These are only few examples of useful - features logback has to offer. For its own error reporting, - logback relies on Status objects, which greatly - facilitate troubleshooting. You may wish to rely on Status objects - in contexts other than logging. Logback-core bundles Joran, a - powerful and generic configuration system, which can be put to use - in your own projects to great effect. -

- -

First Baby Step

- - - - -

Requirements

- -

Logback-classic module requires the presence - slf4j-api.jar, logback-core.jar in addition to - logback-classic.jar on the classpath. -

- -

The logback-*.jar files are part of the logback - distribution whereas slf4j-api-${slf4j.version}.jar ships - with SLF4J, a separate project. -

- -

Let us now begin experimenting with logback.

- -Example 1.1: Basic template for logging (logback-examples/src/main/java/chapter1/HelloWorld1.java) -
package chapter1;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class HelloWorld1 {
-
-  public static void main(String[] args) {
-
-    Logger logger = LoggerFactory.getLogger("chapter1.HelloWorld1");
-    logger.debug("Hello world.");
-
-  }
-}
- -

HelloWorld class is defined in the - chapter1 package. It starts by importing the Logger - and LoggerFactory - classes defined in the SLF4J API, more specifically within the - org.slf4j package. -

- - -

On the first line of the main() method, the variable named - logger is assigned a Logger instance - retrieved by invoking the static getLogger method - from the LoggerFactory class. This logger is named - "chapter1.HelloWorld1". The main method proceeds to call the - debug method of this logger passing "Hello World" as - an argument. We say that the main method contains a logging - statement of level DEBUG with the message "Hello world". -

- -

Note that the above example does not reference any logback - classes. In most cases, as far as logging is concerned, your - classes will only need to import SLF4J classes. Thus, the vast - majority, if not all, of your classes will be cognizant of SLF4J - API and oblivious to the existence of logback. -

- - -

You can launch the first - sample application, chapter1.HelloWorld1 with the command: -

-
java chapter1.HelloWorld1
- -

Launching the HelloWorld1 application will output - a single line on the console. By virtue of logback's default - configuration policy, when no default configuration file is found, - logback will add a ConsoleAppender to the root - logger. -

- -

20:49:07.962 [main] DEBUG chapter1.HelloWorld1 - Hello world.

- -

Logback can report information about its internal state using a - built-in status system. Important events occuring during logback's - lifetime can be accessed through a StatusManager. For - the time being, let us instruct logback to print its internal - state. This is accomplished by a static method in the - LoggerStatusPrinter class. -

- -Example 1.2: Printing Logger Status (logback-examples/src/main/java/chapter1/HelloWorld2.java) -
package chapter1;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.core.util.StatusPrinter;
-
-public class HelloWorld2 {
-
-  public static void main(String[] args) {
-    Logger logger = LoggerFactory.getLogger("chapter1.HelloWorld2");
-    logger.debug("Hello world.");
-
-    // print internal state
-    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-    StatusPrinter.print(lc);
-  }
-}
- - -

Running the HelloWorld2 application will produce - the following output:

- -
12:49:22.203 [main] DEBUG chapter1.HelloWorld2 - Hello world.
-12:49:22,078 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
-12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
-12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Setting up default configuration.
-
- - -

Logback explains that having failed to find the - logback-test.xml and logback.xml configuration - files (discussed later), it configured itself using its default - policy, which is a basic ConsoleAppender. An - Appender is a class that can be seen as an output - destination. Appenders exist for many different destinations - including the console, files, Syslog, TCP Socket, JMS and many - more. Users can also easily create their own Appenders as - appropriate for their specific situation. -

- -

Note that in case of errors, logback will automatically print its - internal state on the console.

- -

The previous examples are rather simple. Actual logging in a - larger application would not be that different. The general pattern - for logging statements would not change. Only the configuration - process would be different. However, you would probably want to - customize or configure logback according to your needs. Logback - configuration will be covered in subsequent chapters. -

- -

Note that in the above example we have instructed logback to - print its internal state by invoking - StatusPrinter.print() method. Logback's internal status - information can be very useful in diagnosing logback-related - problems. -

- -

Here is a list of the three required steps in order to enable - logging in your application. -

- -
    -
  1. Configure the logback environment. You can do so in several - more or less sophisticated ways. More on this later.
  2. - -
  3. In every class where you wish to perform logging, retrieve a - Logger instance by invoking the - org.slf4j.LoggerFactory class' - getLogger() method, passing the current class name - or the class itself as a parameter.
  4. - -
  5. Use this logger instance by invoking its printing methods, - namely the debug(), info(), warn() and error(). This will - produce logging output on the configured appenders.
  6. -
- - -

Building logback

- - - - -

As its build tool, logback relies on Maven2, a widely-used open-source - build tool. -

- -

Once you have installed Maven2, building the logback project, - including all its modules, should be as easy as issuing a mvn - package command from within the directory where you - unarchived the logback distribution. Maven will automatically - download the required external libraries. -

- -

Logback distributions contain complete source code such that you - can modify parts of logback library and build your own version of - it. You may even redistribute the modified version, as long as you - adhere to the conditions of the LGPL License. -

- -

Logback has been built and tested with the follwing JDKs.

- - - - - - - - - - - - - - - - - - - - - - - - - - -
JDKOperating System
Sun JDK 1.5.0.06Windows XP
Sun JDK 1.5.0.08Linux 64bit AMD
WebLogic JRockit 1.5.0.14Linux 64bit AMD
IBM JDK 1.6.0.1Linux 64bit AMD
- - - -
- - + + + + + Chapter 1: Introduction + + + + + + + + + + +
+ + +
+ +
+ +

Introduction

+ +
+

The morale effects are startling. Enthusiasm jumps when + there is a running system, even a simple one. Efforts redouble when + the first picture from a new graphics software system appears on the + screen, even if it is only a rectangle. One always has, at every + stage in the process, a working system. I find that teams can grow + much more complex entities in four months than they can + build.

+ +

—FREDERIC P. BROOKS, JR., The Mythical Man-Month

+
+ + + + +

What is logback?

+ +

Logback is intended as a successor to the popular log4j + project. It was designed by Ceki Gülcü, log4j's + founder. It builds upon a decade long experience gained in + designing industrial-strength logging systems. The resulting + product, logback is faster with a smaller footprint than all + existing logging systems, sometimes by a wide margin. Logback also + offers unique and rather useful features such as Markers, + parameterized logging statements, conditional stack tracing and + powerful event filtering. These are only few examples of useful + features logback has to offer. For its own error reporting, + logback relies on Status objects, which greatly + facilitate troubleshooting. You may wish to rely on Status objects + in contexts other than logging. Logback-core bundles Joran, a + powerful and generic configuration system, which can be put to use + in your own projects to great effect. +

+ +

First Baby Step

+ + + + +

Requirements

+ +

Logback-classic module requires the presence + slf4j-api.jar, logback-core.jar in addition to + logback-classic.jar on the classpath. +

+ +

The logback-*.jar files are part of the logback + distribution whereas slf4j-api-${slf4j.version}.jar ships + with SLF4J, a separate project. +

+ +

Let us now begin experimenting with logback.

+ +Example 1.1: Basic template for logging (logback-examples/src/main/java/chapter1/HelloWorld1.java) +
package chapter1;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HelloWorld1 {
+
+  public static void main(String[] args) {
+
+    Logger logger = LoggerFactory.getLogger("chapter1.HelloWorld1");
+    logger.debug("Hello world.");
+
+  }
+}
+ +

HelloWorld class is defined in the + chapter1 package. It starts by importing the Logger + and LoggerFactory + classes defined in the SLF4J API, more specifically within the + org.slf4j package. +

+ + +

On the first line of the main() method, the variable named + logger is assigned a Logger instance + retrieved by invoking the static getLogger method + from the LoggerFactory class. This logger is named + "chapter1.HelloWorld1". The main method proceeds to call the + debug method of this logger passing "Hello World" as + an argument. We say that the main method contains a logging + statement of level DEBUG with the message "Hello world". +

+ +

Note that the above example does not reference any logback + classes. In most cases, as far as logging is concerned, your + classes will only need to import SLF4J classes. Thus, the vast + majority, if not all, of your classes will be cognizant of SLF4J + API and oblivious to the existence of logback. +

+ + +

You can launch the first + sample application, chapter1.HelloWorld1 with the command: +

+
java chapter1.HelloWorld1
+ +

Launching the HelloWorld1 application will output + a single line on the console. By virtue of logback's default + configuration policy, when no default configuration file is found, + logback will add a ConsoleAppender to the root + logger. +

+ +

20:49:07.962 [main] DEBUG chapter1.HelloWorld1 - Hello world.

+ +

Logback can report information about its internal state using a + built-in status system. Important events occuring during logback's + lifetime can be accessed through a StatusManager. For + the time being, let us instruct logback to print its internal + state. This is accomplished by a static method in the + LoggerStatusPrinter class. +

+ +Example 1.2: Printing Logger Status (logback-examples/src/main/java/chapter1/HelloWorld2.java) +
package chapter1;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class HelloWorld2 {
+
+  public static void main(String[] args) {
+    Logger logger = LoggerFactory.getLogger("chapter1.HelloWorld2");
+    logger.debug("Hello world.");
+
+    // print internal state
+    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+    StatusPrinter.print(lc);
+  }
+}
+ + +

Running the HelloWorld2 application will produce + the following output:

+ +
12:49:22.203 [main] DEBUG chapter1.HelloWorld2 - Hello world.
+12:49:22,078 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
+12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
+12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Setting up default configuration.
+
+ + +

Logback explains that having failed to find the + logback-test.xml and logback.xml configuration + files (discussed later), it configured itself using its default + policy, which is a basic ConsoleAppender. An + Appender is a class that can be seen as an output + destination. Appenders exist for many different destinations + including the console, files, Syslog, TCP Socket, JMS and many + more. Users can also easily create their own Appenders as + appropriate for their specific situation. +

+ +

Note that in case of errors, logback will automatically print its + internal state on the console.

+ +

The previous examples are rather simple. Actual logging in a + larger application would not be that different. The general pattern + for logging statements would not change. Only the configuration + process would be different. However, you would probably want to + customize or configure logback according to your needs. Logback + configuration will be covered in subsequent chapters. +

+ +

Note that in the above example we have instructed logback to + print its internal state by invoking + StatusPrinter.print() method. Logback's internal status + information can be very useful in diagnosing logback-related + problems. +

+ +

Here is a list of the three required steps in order to enable + logging in your application. +

+ +
    +
  1. Configure the logback environment. You can do so in several + more or less sophisticated ways. More on this later.
  2. + +
  3. In every class where you wish to perform logging, retrieve a + Logger instance by invoking the + org.slf4j.LoggerFactory class' + getLogger() method, passing the current class name + or the class itself as a parameter.
  4. + +
  5. Use this logger instance by invoking its printing methods, + namely the debug(), info(), warn() and error(). This will + produce logging output on the configured appenders.
  6. +
+ + +

Building logback

+ + + + +

As its build tool, logback relies on Maven2, a widely-used open-source + build tool. +

+ +

Once you have installed Maven2, building the logback project, + including all its modules, should be as easy as issuing a mvn + package command from within the directory where you + unarchived the logback distribution. Maven will automatically + download the required external libraries. +

+ +

Logback distributions contain complete source code such that you + can modify parts of logback library and build your own version of + it. You may even redistribute the modified version, as long as you + adhere to the conditions of the LGPL License. +

+ +

Logback has been built and tested with the follwing JDKs.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
JDKOperating System
Sun JDK 1.5.0.06Windows XP
Sun JDK 1.5.0.08Linux 64bit AMD
WebLogic JRockit 1.5.0.14Linux 64bit AMD
IBM JDK 1.6.0.1Linux 64bit AMD
+ + + +
+ + diff --git a/logback-site/src/site/pages/manual/jmxConfig.html b/logback-site/src/site/pages/manual/jmxConfig.html index 13af29393a6824595ef30fe131dca514e4d0d685..e7eb93372ce6c7ef4f256db5625298ce1b72d8bd 100644 --- a/logback-site/src/site/pages/manual/jmxConfig.html +++ b/logback-site/src/site/pages/manual/jmxConfig.html @@ -1,397 +1,397 @@ - - - - - - - - - - - - JMX Configuration - - - - - -
- - -
- -
- -

JMX Configurator

- -

As its name indicates, JMXConfigurator allows - configuration of logback via JMX. In a nutshell, it lets you - reconfigure logback from the default configuration file, from a - designated file or URL, list loggers and modify logger levels. -

- -

Using the JMX Configurator

- - -

If your server run on JDK 1.6 or later, then you can just - invoke jconsole application on the commmand line and - then connect to your server's MBeanServer. If you are running an - older JVM, then you should read the section on JMX enabling your server. -

- -

JMXConfigurator is enabled by a single line in - your logback configuration file, as shown below: -

- -
<configuration>
-  <jmxConfigurator />
-  
-  <appender name="console" class="ch.qos.logback.classic.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%date [%thread] %-5level %logger{25} - %msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug"/>
-    <appender-ref ref="console" />
-  </root>  
-</configuration>
- -

After you connect to your server with jconsole, on the - MBeans panel, under "ch.qos.logback.classic.jmx.Configurator" - folder you should see several operations to choose from, as shown - in the figure below: -

- -

Screen-shot - of JMXConfigurator viewed in - jconsole

- jmxConfigurator - -

Thus, you can

- -
    -
  • Reload logback configuration using the default configuration - file
  • - -
  • Reload the configuration with the specified URL
  • -
  • Reload the configuration with the specified file
  • - -
  • Set the level of a specified logger. To set to null, pass - the string "null" as value.
  • -
  • Get the level of a specified logger. Returned value can be - null.
  • -
  • Get the effective - level of a specified logger
  • -
- -

JMXConfigurator exposes the list of existing - loggers and a status list as attributes.

- -

The status list can help you diagnose logbacks internal - state.

- - statusList.gif - -

Avoiding memory leaks

- -

If your application is deployed in a web-server or an - application server, the registration of an - JMXConfigurator instance creates a reference from the - system class loader into your application which will prevent it - from being garbage collected when it is stopped or re-deployed, - resulting in a severe memory leak.

- -

Thus, unless your application is standalone java application, - you MUST unregister the JMXConfigurator instance from - the JVM's Mbeans server. Invoking the reset() method - of the appropriate LoggerContext will automatically - unregister any JMXConfigurator instance. A good place to reset the - logger context is in the the contextDestroyed() - method of a - javax.servlet.ServletContextListener. Here is sample - code:

- -
import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-
-import org.slf4j.LoggerFactory;
-import ch.qos.logback.classic.LoggerContext;
-
-public class MyContextListener implements ServletContextListener {
-
-  public void contextDestroyed(ServletContextEvent sce) {
-    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-    lc.stop();
-  }
-
-  public void contextInitialized(ServletContextEvent sce) {
-  }
-} 
- - - - - -

- JMXConfigurator - with multiple web-applications -

- -

If you deploy multiple web-applications in the same server, - then, and assuming you have not overriden the default context selector, and assuming you - have placed a copy of logback-*.jar and - slf4j-api.jar under the WEB-INF/lib folder of - each web-application, by default each JMXConfigurator - instance will be registered under the same name, that is, - "ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator". In - other words, by default the various JMXConfigurator - instances associated with the logger contexts in each of your - web-applications will collide. -

- -

To avoid such undesirable collisions, you can instruct each - JMXConfigurator instance to have a different name by - setting the "contextName" attribute of the - <jmxConfigurator> element in the logback - configuration file. -

- -

For example, if you deploy two web-applications named "Koala" - and "Wombat", then you would write in Koala's logback - configuration -

- -

<jmxConfigurator contextName="Koala" />

- -

and in Wombat logback configuration file, you would write:

- -

<jmxConfigurator contextName="Womcat" />

- -

In jconsole's MBeans panel, you would two distinct - JMXConfigurator instances:

- - multiple.gif - -

You may fully control the name under which JMXConfigurator is - registered with MBeans server with the help of the "objectName" - attribute of <jmxConfigurator> element.

- - - -

- JMX enabling your - server -

- -

If your server runs with JDK 1.6 or later, your server should - be JMX enabled by default.

- -

For older JVMs, we suggest that you refer JMX-related - documentation of your web-server. Such documentation is available - for both Tomcat - and Jetty. In - this document, we briefly describe the required configuration - steps for Tomcat and Jetty. -

- - - -

Enabling JMX in Jetty (tested under JDK 1.5 and JDK 1.6)

- -

The following has been tested under JDK 1.5 and 1.6. Under JDK - 1.6 and later, your server is JMX enabled by default and you can, - but do not need to, follow the steps discussed below. Under JDK - 1.5, adding JMX support in Jetty requires a number of additions to - the $JETTY_HOME/etc/jetty.xml configuration file. Here - are the elements that need to be added: -

- -
<Call id="MBeanServer" class="java.lang.management.ManagementFactory" 
-      name="getPlatformMBeanServer"/>
-
-<Get id="Container" name="container">
-  <Call name="addEventListener">
-    <Arg>
-      <New class="org.mortbay.management.MBeanContainer">
-        <Arg><Ref id="MBeanServer"/></Arg>
-        <Call name="start" />
-      </New>
-    </Arg>
-  </Call>
-</Get> 
- -

If you wish to access the MBeans exposed by Jetty via the - jconsole application, then you need start jetty after - having set the "com.sun.management.jmxremote" java system - property. -

- -

For a standalone version of Jetty, this translates to:

- - -

java -Dcom.sun.management.jmxremote -jar start.jar [config files]

- -

And if you wish to launch jetty as a Maven plugin, then you - need set the "com.sun.management.jmxremote" system property via - the MAVEN_OPTS shell variable: -

- -

MAVEN_OPTS="-Dcom.sun.management.jmxremote" -mvn jetty:run

- -

You can then access the MBeans exposed by Jetty as well as - logback's JMXConfigurator via - jconsole.

- - jconsole15_jetty.gif - -

After you are connected, you should be able to access - JMXXConfigurator as shown in the screenshot above.

- -

MX4J with Jetty (tested under JDK 1.5 and 1.6)

- -

Ig you wish to acces JMXConfigurator via MX4J's - HTTP interface and assuming you have already downloaded MX4J, you then need to - modify the jetty configuration file discussed previously by adding - an instruction to set the management port. -

- -
<Call id="MBeanServer"
-    class="java.lang.management.ManagementFactory"
-    name="getPlatformMBeanServer"/>
-
-<Get id="Container" name="container">
-  <Call name="addEventListener">
-    <Arg>
-      <New class="org.mortbay.management.MBeanContainer">
-        <Arg><Ref id="MBeanServer"/></Arg>
-        <Set name="managementPort">8082</Set>
-        <Call name="start" />
-      </New>
-    </Arg>
-  </Call>
-</Get> 
-    
- -

Moreover, mx4j-tools.jar needs to be added to Jetty's - class path. -

- -

If you are running jetty as a Maven plug-in, then you need to add - mx4j-tools as a dependency.

- -
<plugin>
-  <groupId>org.mortbay.jetty</groupId>
-  <artifactId>maven-jetty-plugin</artifactId>
-  <configuration>
-    <jettyConfig>path/to/jetty.xml</jettyConfig>
-    ...
-  </configuration>
-  <dependencies>
-    <dependency>
-      <groupId>mx4j</groupId>
-      <artifactId>mx4j-tools</artifactId>
-      <version>3.0.1</version>
-    </dependency>
-  </dependencies>
-</plugin>
- -

After Jetty is started with the above configuration, - JMXConfigurator will be available at the following - URL (search for "ch.qos.logback.classic"): -

- -

http://localhost:8082/

- -

Below is a screen shot view of the MX4J interface.

- - mx4j_jetty.gif - - - - -

Configuring JMX for Tomcat (tested under JDK 1.5 and 1.6)

- -

If you are using JDK 1.6 and later, your server is already JMX - enabled by default and you can, but do not need to, follow the - steps discussed below. Under JDK 1.5, Tomcat requires the addition - of the following lines to the - $TOMCAT_HOME/bin/catalina.bat/sh shell script: -

- -

CATALINA_OPTS="-Dcom.sun.management.jmxremote"

- -

Once started with these options, Mbeans exposed by Tomcat as - well logback's JMXConfigurator can be accessed with - jconsole by issuing the following command in a shell: -

- -

jconsole

- - jconsole15_tomcat.gif - -

After you are connected, you should be able to access - JMXXConfigurator as shown in the screenshot above.

- - -

MX4J with Tomcat (tested under JDK 1.5 and 1.6)

- -

You might prefer to access JMX components via a web-based - interface provided by MX4J. In that case, here are the required - steps: -

- -

Assuming you have already downloaded MX4J, placethe - mx4j-tools.jar file under the $TOMCAT_HOME/bin/ - directory. Then, add the following lines to the - $TOMCAT_HOME/bin/catalina.sh configuration file: -

- -

<!-- at the beginning of the file --> -CATALINA_OPTS="-Dcom.sun.management.jmxremote" - -<!-- in the "Add on extra jar files to CLASSPATH" section --> -CLASSPATH="$CLASSPATH":"$CATALINA_HOME"/bin/mx4j-tools.jar

- -

Finally, declare a new Connector in the - $TOMCAT_HOME/conf/server.xml file: -

- - -
<Connector port="0" 
-  handler.list="mx"
-  mx.enabled="true" 
-  mx.httpHost="localhost" 
-  mx.httpPort="8082" 
-  protocol="AJP/1.3" />
- -

Once Tomcat is started, you should be able to find - JMXConfigurator by pointing your browser at the following URL - (search for "ch.qos.logback.classic"): -

- -

http://localhost:8082/

- -

Below is a screen shot view of the MX4J interface.

- - mx4j_tomcat.gif - - - - - -
- - + + + + + + + + + + + + JMX Configuration + + + + + +
+ + +
+ +
+ +

JMX Configurator

+ +

As its name indicates, JMXConfigurator allows + configuration of logback via JMX. In a nutshell, it lets you + reconfigure logback from the default configuration file, from a + designated file or URL, list loggers and modify logger levels. +

+ +

Using the JMX Configurator

+ + +

If your server run on JDK 1.6 or later, then you can just + invoke jconsole application on the commmand line and + then connect to your server's MBeanServer. If you are running an + older JVM, then you should read the section on JMX enabling your server. +

+ +

JMXConfigurator is enabled by a single line in + your logback configuration file, as shown below: +

+ +
<configuration>
+  <jmxConfigurator />
+  
+  <appender name="console" class="ch.qos.logback.classic.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%date [%thread] %-5level %logger{25} - %msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug"/>
+    <appender-ref ref="console" />
+  </root>  
+</configuration>
+ +

After you connect to your server with jconsole, on the + MBeans panel, under "ch.qos.logback.classic.jmx.Configurator" + folder you should see several operations to choose from, as shown + in the figure below: +

+ +

Screen-shot + of JMXConfigurator viewed in + jconsole

+ jmxConfigurator + +

Thus, you can

+ +
    +
  • Reload logback configuration using the default configuration + file
  • + +
  • Reload the configuration with the specified URL
  • +
  • Reload the configuration with the specified file
  • + +
  • Set the level of a specified logger. To set to null, pass + the string "null" as value.
  • +
  • Get the level of a specified logger. Returned value can be + null.
  • +
  • Get the effective + level of a specified logger
  • +
+ +

JMXConfigurator exposes the list of existing + loggers and a status list as attributes.

+ +

The status list can help you diagnose logbacks internal + state.

+ + statusList.gif + +

Avoiding memory leaks

+ +

If your application is deployed in a web-server or an + application server, the registration of an + JMXConfigurator instance creates a reference from the + system class loader into your application which will prevent it + from being garbage collected when it is stopped or re-deployed, + resulting in a severe memory leak.

+ +

Thus, unless your application is standalone java application, + you MUST unregister the JMXConfigurator instance from + the JVM's Mbeans server. Invoking the reset() method + of the appropriate LoggerContext will automatically + unregister any JMXConfigurator instance. A good place to reset the + logger context is in the the contextDestroyed() + method of a + javax.servlet.ServletContextListener. Here is sample + code:

+ +
import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.slf4j.LoggerFactory;
+import ch.qos.logback.classic.LoggerContext;
+
+public class MyContextListener implements ServletContextListener {
+
+  public void contextDestroyed(ServletContextEvent sce) {
+    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+    lc.stop();
+  }
+
+  public void contextInitialized(ServletContextEvent sce) {
+  }
+} 
+ + + + + +

+ JMXConfigurator + with multiple web-applications +

+ +

If you deploy multiple web-applications in the same server, + then, and assuming you have not overriden the default context selector, and assuming you + have placed a copy of logback-*.jar and + slf4j-api.jar under the WEB-INF/lib folder of + each web-application, by default each JMXConfigurator + instance will be registered under the same name, that is, + "ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator". In + other words, by default the various JMXConfigurator + instances associated with the logger contexts in each of your + web-applications will collide. +

+ +

To avoid such undesirable collisions, you can instruct each + JMXConfigurator instance to have a different name by + setting the "contextName" attribute of the + <jmxConfigurator> element in the logback + configuration file. +

+ +

For example, if you deploy two web-applications named "Koala" + and "Wombat", then you would write in Koala's logback + configuration +

+ +

<jmxConfigurator contextName="Koala" />

+ +

and in Wombat logback configuration file, you would write:

+ +

<jmxConfigurator contextName="Womcat" />

+ +

In jconsole's MBeans panel, you would two distinct + JMXConfigurator instances:

+ + multiple.gif + +

You may fully control the name under which JMXConfigurator is + registered with MBeans server with the help of the "objectName" + attribute of <jmxConfigurator> element.

+ + + +

+ JMX enabling your + server +

+ +

If your server runs with JDK 1.6 or later, your server should + be JMX enabled by default.

+ +

For older JVMs, we suggest that you refer JMX-related + documentation of your web-server. Such documentation is available + for both Tomcat + and Jetty. In + this document, we briefly describe the required configuration + steps for Tomcat and Jetty. +

+ + + +

Enabling JMX in Jetty (tested under JDK 1.5 and JDK 1.6)

+ +

The following has been tested under JDK 1.5 and 1.6. Under JDK + 1.6 and later, your server is JMX enabled by default and you can, + but do not need to, follow the steps discussed below. Under JDK + 1.5, adding JMX support in Jetty requires a number of additions to + the $JETTY_HOME/etc/jetty.xml configuration file. Here + are the elements that need to be added: +

+ +
<Call id="MBeanServer" class="java.lang.management.ManagementFactory" 
+      name="getPlatformMBeanServer"/>
+
+<Get id="Container" name="container">
+  <Call name="addEventListener">
+    <Arg>
+      <New class="org.mortbay.management.MBeanContainer">
+        <Arg><Ref id="MBeanServer"/></Arg>
+        <Call name="start" />
+      </New>
+    </Arg>
+  </Call>
+</Get> 
+ +

If you wish to access the MBeans exposed by Jetty via the + jconsole application, then you need start jetty after + having set the "com.sun.management.jmxremote" java system + property. +

+ +

For a standalone version of Jetty, this translates to:

+ + +

java -Dcom.sun.management.jmxremote -jar start.jar [config files]

+ +

And if you wish to launch jetty as a Maven plugin, then you + need set the "com.sun.management.jmxremote" system property via + the MAVEN_OPTS shell variable: +

+ +

MAVEN_OPTS="-Dcom.sun.management.jmxremote" +mvn jetty:run

+ +

You can then access the MBeans exposed by Jetty as well as + logback's JMXConfigurator via + jconsole.

+ + jconsole15_jetty.gif + +

After you are connected, you should be able to access + JMXXConfigurator as shown in the screenshot above.

+ +

MX4J with Jetty (tested under JDK 1.5 and 1.6)

+ +

Ig you wish to acces JMXConfigurator via MX4J's + HTTP interface and assuming you have already downloaded MX4J, you then need to + modify the jetty configuration file discussed previously by adding + an instruction to set the management port. +

+ +
<Call id="MBeanServer"
+    class="java.lang.management.ManagementFactory"
+    name="getPlatformMBeanServer"/>
+
+<Get id="Container" name="container">
+  <Call name="addEventListener">
+    <Arg>
+      <New class="org.mortbay.management.MBeanContainer">
+        <Arg><Ref id="MBeanServer"/></Arg>
+        <Set name="managementPort">8082</Set>
+        <Call name="start" />
+      </New>
+    </Arg>
+  </Call>
+</Get> 
+    
+ +

Moreover, mx4j-tools.jar needs to be added to Jetty's + class path. +

+ +

If you are running jetty as a Maven plug-in, then you need to add + mx4j-tools as a dependency.

+ +
<plugin>
+  <groupId>org.mortbay.jetty</groupId>
+  <artifactId>maven-jetty-plugin</artifactId>
+  <configuration>
+    <jettyConfig>path/to/jetty.xml</jettyConfig>
+    ...
+  </configuration>
+  <dependencies>
+    <dependency>
+      <groupId>mx4j</groupId>
+      <artifactId>mx4j-tools</artifactId>
+      <version>3.0.1</version>
+    </dependency>
+  </dependencies>
+</plugin>
+ +

After Jetty is started with the above configuration, + JMXConfigurator will be available at the following + URL (search for "ch.qos.logback.classic"): +

+ +

http://localhost:8082/

+ +

Below is a screen shot view of the MX4J interface.

+ + mx4j_jetty.gif + + + + +

Configuring JMX for Tomcat (tested under JDK 1.5 and 1.6)

+ +

If you are using JDK 1.6 and later, your server is already JMX + enabled by default and you can, but do not need to, follow the + steps discussed below. Under JDK 1.5, Tomcat requires the addition + of the following lines to the + $TOMCAT_HOME/bin/catalina.bat/sh shell script: +

+ +

CATALINA_OPTS="-Dcom.sun.management.jmxremote"

+ +

Once started with these options, Mbeans exposed by Tomcat as + well logback's JMXConfigurator can be accessed with + jconsole by issuing the following command in a shell: +

+ +

jconsole

+ + jconsole15_tomcat.gif + +

After you are connected, you should be able to access + JMXXConfigurator as shown in the screenshot above.

+ + +

MX4J with Tomcat (tested under JDK 1.5 and 1.6)

+ +

You might prefer to access JMX components via a web-based + interface provided by MX4J. In that case, here are the required + steps: +

+ +

Assuming you have already downloaded MX4J, placethe + mx4j-tools.jar file under the $TOMCAT_HOME/bin/ + directory. Then, add the following lines to the + $TOMCAT_HOME/bin/catalina.sh configuration file: +

+ +

<!-- at the beginning of the file --> +CATALINA_OPTS="-Dcom.sun.management.jmxremote" + +<!-- in the "Add on extra jar files to CLASSPATH" section --> +CLASSPATH="$CLASSPATH":"$CATALINA_HOME"/bin/mx4j-tools.jar

+ +

Finally, declare a new Connector in the + $TOMCAT_HOME/conf/server.xml file: +

+ + +
<Connector port="0" 
+  handler.list="mx"
+  mx.enabled="true" 
+  mx.httpHost="localhost" 
+  mx.httpPort="8082" 
+  protocol="AJP/1.3" />
+ +

Once Tomcat is started, you should be able to find + JMXConfigurator by pointing your browser at the following URL + (search for "ch.qos.logback.classic"): +

+ +

http://localhost:8082/

+ +

Below is a screen shot view of the MX4J interface.

+ + mx4j_tomcat.gif + + + + + +
+ + diff --git a/logback-site/src/site/pages/manual/layouts.html b/logback-site/src/site/pages/manual/layouts.html index 18ac274f11c6a5b0aec0eab8aa991e0800396c4b..adacb6b6193a042b68851324ad008184a20275f2 100644 --- a/logback-site/src/site/pages/manual/layouts.html +++ b/logback-site/src/site/pages/manual/layouts.html @@ -1,2058 +1,2058 @@ - - - - - - Chapter 5: Layouts - - - - - - - - - - -
- - -
- -
- -

Chapter 5: Layouts

- -
-

TCP implementations will follow a general principle of - robustness: be conservative in what you do, be liberal in what - you accept from others. -

-

—JON POSTEL, RFC 793

-
- - - - -

What is a layout?

- -

While appenders are responsible for writing logging output to - an appender dependent device, layouts are responsible for the - format of the output. In case you were wondering, layouts have - nothing to do with large estates in Florida. The - format() method in the Layout - interface takes an object that represents an event (of any type) - and returns a String. A synopsis of the Layout - interface is shown below. -

- -
public interface Layout<E> extends ContextAware, LifeCycle {
-
-  String doLayout(E event);
-  String getHeader();
-  String getFooter();
-  String getContentType();
-}
- -

This interface is rather simple and yet is sufficent for many - formatting needs. The Texan developer from Texas, who you might - know from Joseph Heller's Catch-22, might exclaim: it - just takes five methods to implement a layout!!? -

- -

Logback-classic

- -

Logback-classic is wired to processes only events of type - - ch.qos.logback.classic.spi.ILoggingEvent. This - fact will be apparent throughout this section.

- -

Writing your own Layout

- -

Let us implement a simple yet functional layout for the - logback-classic module that prints the time elapsed since the - start of the application, the level of the logging event, the - caller thread between brackets, its logger name, a dash followed - by the event message and a new line. -

- -

Sample output might look like:

- -
10489 DEBUG [main] com.marsupial.Pouch - Hello world.
- -

Here is a possible implementation, authored by the Texan developer:

- Example 5.0: Sample implementation of a Layout - - (logback-examples/src/main/java/chapter5/MySampleLayout.java) - -
package chapter5;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.LayoutBase;
-
-public class MySampleLayout extends LayoutBase<ILoggingEvent> {
-
-  public String doLayout(ILoggingEvent event) {
-    StringBuffer sbuf = new StringBuffer(128);
-    sbuf.append(event.getTimeStamp() - event.getLoggingContextVO.getBirthTime());
-    sbuf.append(" ");
-    sbuf.append(event.getLevel());
-    sbuf.append(" [");
-    sbuf.append(event.getThreadName());
-    sbuf.append("] ");
-    sbuf.append(event.getLoggerName();
-    sbuf.append(" - ");
-    sbuf.append(event.getFormattedMessage());
-    sbuf.append(CoreConstants.LINE_SEP);
-    return sbuf.toString();
-  }
-}
- -

Note that MySampleLayout extends - LayoutBase. This class manages state shared by - all Layout classes, such as whether the layout is - started or stopped, header, footer and content type data. It - allows the developer to concentrate on the formatting expected - from his/her Layout. Note that the - LayoutBase class is generic. In its class - declaration, MySampleLayout extends - LayoutBase<ILoggingEvent>. -

- -

The doLayout(ILoggingEvent event) method, i.e. the - only method in MySampleLayout, begins by - instantiating a StringBuffer. It proceeds by adding - various fields of the event parameter. The Texan from Texas was - careful to print the formatted form of the message. This is - significant in case one or more parameters were passed along with - the logging request. -

- -

After adding these various characters to the string buffer, the - doLayout() method converts the buffer into a - String and returns the resulting value. -

- -

In the above example, the doLayout method ignores - any eventual exceptions contained in the event. In a real world - layout implementation, you would most probably want to print the - contents of exceptions as well. -

- -

Configuring your custom layout

- -

Custom layouts are configured as any other layout. Here is as - example:

- - Example 5.0: Configuration of MySampleLayout - (logback-examples/src/main/java/chapter5/sampleLayoutConfig.xml) -
<configuration>
-
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="chapter5.MySampleLayout" />
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

The sample application - chapter5.SampleLogging configures logback with - the configuration script supplied as a parameter and then logs a - debug message, followed by an error message.

- -

- To run this example issue the following command from within the - logback-examples directory. -

- -

java chapter5.SampleLogging src/main/java/chapter5/sampleLayoutConfig.xml

- -

This will produce:

- -
0 DEBUG [main] chapter5.SampleLogging - Everything's going well
-0 ERROR [main] chapter5.SampleLogging - maybe not quite...
- -

That was simple enough. The skeptic Pyrrho of Elea, who - insists that nothing is certain except perhaps uncertainty itself, - which is by no means certain either, might ask: how about a layout - with options? The reader shall find a slightly modified version - of our custom layout in MySampleLayout2.java. She - will discover that adding an option to a layout is as simple as - declaring a setter method for the option. -

- -

- The - MySampleLayout2 - - class contains two attributes. The first one is a prefix that - can be added to the output. The second attribute is used to - choose whether to display the name of the thread from which - the logging request was sent. -

-

Here is the implementation of this class:

- -
package chapter5;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.LayoutBase;
-
-public class MySampleLayout2 extends LayoutBase<ILoggingEvent> {
-
-  String prefix = null;
-  boolean printThreadName = true;
-
-  public void setPrefix(String prefix) {
-    this.prefix = prefix;
-  }
-
-  public void setPrintThreadName(boolean printThreadName) {
-    this.printThreadName = printThreadName;
-  }
-
-  public String doLayout(ILoggingEvent event) {
-    StringBuffer sbuf = new StringBuffer(128);
-    if (prefix != null) {
-      sbuf.append(prefix + ": ");
-    }
-    sbuf.append(event.getTimeStamp() - event.getLoggerContextVO().getBirthTime());
-    sbuf.append(" ");
-    sbuf.append(event.getLevel());
-    if (printThreadName) {
-      sbuf.append(" [");
-      sbuf.append(event.getThreadName());
-      sbuf.append("] ");
-    } else {
-      sbuf.append(" ");
-    }
-    sbuf.append(event.getLoggerName());
-    sbuf.append(" - ");
-    sbuf.append(event.getFormattedMessage());
-    sbuf.append(LINE_SEP);
-    return sbuf.toString();
-  }
-}
- - -

The addition of the corresponding setter method is all that is - needed to enable the configuration of an option. Note that the - PrintThreadName option is boolean and not - String. Configuration of logback components was - covered in detail in "Chapter 3: - Logback configuration". Here is the configuration - file tailor-made for use with MySampleLayout2. -

- - -
<configuration>
-
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="chapter5.MySampleLayout2"> 
-      <prefix>MyPrefix</prefix>
-      <printThreadName>false</printThreadName>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

- - - -

PatternLayout

- -

Logback classic ships with a flexible layout called - PatternLayout. As all layouts, - PatternLayout takes a logging event and returns a - String. However, this String can be - customized at will by tweaking the conversion pattern of - PatternLayout. -

- -

The conversion pattern of PatternLayout is closely - related to the conversion pattern of the printf() - function in the C programming language. A conversion pattern is - composed of literal text and format control expressions called - conversion specifiers. You are free to insert any literal text - within the conversion pattern. Each conversion specifier starts - with a percent sign '%' and is followed by optional format - modifiers, a conversion word and optional parameters between - braces. The conversion word controls the type of data to use, e.g. - logger name, level, date, thread name. The format modifiers - control such things as field width, padding, and left or right - justification. The following is a simple example. -

- - Example 5.1: Sample usage of a PatternLayout - - (logback-examples/src/main/java/chapter5/PatternSample.java) - -
package chapter5;
-
-import org.slf4j.LoggerFactory;
-
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.PatternLayout;
-import ch.qos.logback.core.ConsoleAppender;
-
-public class PatternSample {
-
-  static public void main(String[] args) throws Exception {
-    Logger rootLogger = (Logger)LoggerFactory.getLogger("root");
-
-    PatternLayout layout = new PatternLayout();
-    layout.setPattern("%-5level [%thread]: %message%n");
-    layout.start();
-
-    ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<ILoggingEvent>();
-    appender.setContext(rootLogger.getLoggerContext());
-    appender.setLayout(layout); appender.start();
-
-    rootLogger.addAppender(appender);
-
-    rootLogger.debug("Message 1"); 
-    rootLogger.warn("Message 2");
-  } 
-}
- -

The conversion pattern is set to be "%-5level [%thread]: - %message%n". Running PatternSample will yield the following - output on the console. -

- -

DEBUG [main]: Message 1 -WARN [main]: Message 2

- -

Note that in the conversion pattern "%-5level [%thread]: - %message%n" there is no explicit separator between literal - text and conversion specifiers. When parsing a conversion pattern, - PatternLayout is capable of differentiating between - literal text (space characters, the brackets, colon character) and - conversion specifiers. In the example above, the conversion - specifier %-5level means the level of the logging event should be - left justified to a width of five characters. Format specifiers - will be explained below. -

- -

In PatternLayout, parenthesis can be used to group conversion - patterns. It follows that the '(' and ')' carry special meaning - and need to be escaped to be used as literals. Parentheses - can be escaped by preceding the the opening and closing - parenthesis by a backslash, but since the backslash itself carries - special meaning in Java, we need two backslashes, as in "\\(" and - "\\)". Note that strictly speaking, only the closing parenthesis - needs to be escaped to be used as a literal. -

- -

As mentioned previously, certain conversion specifiers can - include optional parameters which are passed between braces - following the conversion word. A sample conversion specifier with - options could be %logger{10}. Here "logger" is the - conversion word, and 10 is the option. -

- -

The recognized conversions words along with their options are - described in the table below. When multiple conversion words are - listed on the left column, they should be considered as aliases. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Conversion WordEffect
- c{length}
- lo{length}
- logger{length}
-
-

Used to output the name of the logger at the origin of - the logging event. -

- -

This conversion word can take an integer as its first and - only option. The converter's abbreviation algorithm will - shorten the logger name, usually without significant loss of - meaning. Setting the value of this option to zero has - special meaning. It will cause the conversoin specifier to - return the string right to the rightmost dot character. The - next table provides examples of the abbreviation algorithm - in action. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Conversion specifierLogger nameResult
%loggermainPackage.sub.sample.BarmainPackage.sub.sample.Bar
%logger{0}mainPackage.sub.sample.BarBar
%logger{5}mainPackage.sub.sample.Barm.s.s.Bar
%logger{10}mainPackage.sub.sample.Barm.s.s.Bar
%logger{15}mainPackage.sub.sample.Barm.s.sample.Bar
%logger{16}mainPackage.sub.sample.Barm.sub.sample.Bar
%logger{26}mainPackage.sub.sample.BarmainPackage.sub.sample.Bar
- -

Please note that the right most segment in a logger name - is never abbreviated, even if its length is longer than the - length option. Other segments may be shortened to - at most a single character but are never removed.

- -
- C{length}
- class{length}
-
-

Used to output the fully-qualified class name of the - caller issuing the logging request. -

-

Just like the %logger conversion word above, - this word can take an integer as its first option and use - its abbreviation algorithm to shorten the class name. Zero - carries special meaning and will cause the simple class name - to be printed without its package name prefix. By default - the class name is printed in full. -

- -

Generating the caller class information is not - particularly fast. Thus, it's use should be avoided unless - execution speed is not an issue. -

-
- contextName
- cn
Outputs the name of the logger context to which the - logger at the origin of the logging event is attached - to.
- d{pattern}
- date{pattern}
-
-

Used to output the date of the logging event. The date - conversion word may be followed by an option enclosed - between braces.

- -

The option admits the same syntax as the time pattern - string of the java.text.SimpleDateFormat.

- -

A shortcut to the ISO8601 format is available by - specifying the String "ISO8601" in the braces. If - no option is set, the converter uses "ISO8601" as - the default value.

- -

Here are some sample option values. They assume that the - actual date is Friday 20th of October, 2006 and that the - author finished his meal a short while ago.

- - - - - - - - - - - - - - - - - - - - - - -
Conversion PatternResult
%date2006-10-20 14:46:49,812
%date{ISO8601}2006-10-20 14:46:49,812
%date{HH:mm:ss.SSS}14:46:49.812
%date{dd MMM yyyy ;HH:mm:ss.SSS}20 oct. 2006;14:46:49.812
-
- F / file - -

Used to output the file name of the Java source file - where the logging request was issued. -

- -

Generating the file information is not particularly fast. - Thus, its use should be avoided unless execution speed is - not an issue. -

-
- caller{depth} - caller{depth, evaluator-1, ... evaluator-n} - -

Used to output location information of the caller which - generated the logging event. -

- -

The location information depends on the JVM - implementation but usually consists of the fully qualified - name of the calling method followed by the caller's source, - the file name and line number between parentheses. -

- -

A integer can be added to the caller conversion - specifier's options to configure the depth of the - information to be displayed. -

- -

For example, %caller{2} would display the - following excerpt:

- -
0    [main] DEBUG - logging statement 
-Caller+0   at mainPackage.sub.sample.Bar.sampleMethodName(Bar.java:22)
-Caller+1   at mainPackage.sub.sample.Bar.createLoggingRequest(Bar.java:17)
- -

And %caller{3} would display this other excerpt:

- -
16   [main] DEBUG - logging statement 
-Caller+0   at mainPackage.sub.sample.Bar.sampleMethodName(Bar.java:22)
-Caller+1   at mainPackage.sub.sample.Bar.createLoggingRequest(Bar.java:17)
-Caller+2   at mainPackage.ConfigTester.main(ConfigTester.java:38)
- -

This conversion word can also use evaluators to test - logging events against a given criterion before creating the - output. For example, using %caller{3, - CALLER_DISPLAY_EVAL} will display three lines of - stacktrace, only if the evaluator called - CALLER_DISPLAY_EVAL returns a positive - answer. -

- -

Evaluators are described below.

-
- L / line - -

Used to output the line number from where the logging - request was issued. -

- -

Generating the line number information is not particularly - fast. Thus, its use should be avoided unless execution - speed is not an issue. -

-
- m / msg / message - - Used to output the application-supplied message associated - with the logging event. -
- M / method - -

- Used to output the method name where the logging - request was issued. -

-

- Generating the method name is not particularly fast. - Thus, it's use should be avoided unless - execution speed is not an issue. -

-
- n - -

- Outputs the platform dependent line separator - character or characters. -

-

- This conversion word offers practically the - same performance as using non-portable line - separator strings such as "\n", or "\r\n". Thus, - it is the preferred way of specifying a line - separator. -

-
- p / le / level - Used to output the level of the logging event.
- r / relative - - Used to output the number of milliseconds elapsed - since the start of the application until the - creation of the logging event. -
- t / thread - - Used to output the name of the thread that generated - the logging event. -
- X{key}
- mdc{key}
-
- -

- Used to output the MDC (mapped diagnostic - context) associated with the thread that - generated the logging event. -

- -

If mdc conversion word is followed by a key - between braces, as in %mdc{clientNumber}, then the - value in the MDC corresponding to the key will be output. -

- -

If no option is given, then the entire content of the MDC - will be output in the format "key1=val1, key2=val2". -

- -

See Chapter 7 for more details on - the MDC. -

- -
- ex{length}
- exception{length}
- throwable{length}
-
- ex{length, evaluator-1, ..., evaluator-n}
- exception{length, evaluator-1, ..., evaluator-n}
- throwable{length, evaluator-1, ..., evaluator-n} -
-

Used to output the stack trace of the exception - associated with the logging event, if any. By default the - full stack trace will be output. -

- -

If you do not specify the %ex conversion word (or one of - its aliases) in the conversion pattern, - PatternLayout will automatically add it as the - last conversion word, on account of the importance of stack - trace information. The $nopex conversion word can be - substituted for %ex, in case you do not wish stack trace - information to be displayed. See also %nopex conversion word. -

- -

The throwable conversion word can followed by one of - the following options: -

-
    -
  • short: prints the first line of the stack trace
  • -
  • full: prints the full stack trace
  • -
  • Any integer: prints the given number of lines of the stack trace
  • -
- -

Here are some examples:

- - - - - - - - - - - - - - - - - - - - - - -
Conversion PatternResult
%ex
mainPackage.foo.bar.TestException: Houston we have a problem
-  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
-  at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)
-  at mainPackage.ExceptionLauncher.main(ExceptionLauncher.java:38)
%ex{short}
mainPackage.foo.bar.TestException: Houston we have a problem
-  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
%ex{full}
mainPackage.foo.bar.TestException: Houston we have a problem
-  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
-  at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)
-  at mainPackage.ExceptionLauncher.main(ExceptionLauncher.java:38)
%ex{2}
mainPackage.foo.bar.TestException: Houston we have a problem
-  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
-  at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)
- -

This conversion word can also use evaluators to test - logging events against a given criterion before creating the - output. For example, using %ex{full, EX_DISPLAY_EVAL} - will display the full stack trace of the exception, only if - the evaluator called EX_DISPLAY_EVAL returns a - negative answer. Evaluators are described further - down in this document. -

-
- xEx{length}
- xException{length}
- xThrowable{length}
-
- xEx{length, evaluator-1, ..., evaluator-n}
- xException{length, evaluator-1, ..., evaluator-n}
- xThrowable{length, evaluator-1, ..., evaluator-n} -
-

Same as the %exception conversion keyword with the - addition of class packaging information.

- -

At the end of each stack frame of the exception, a string - consisting of the jar file containing the relevant class - followed by the "Implementation-Version" as found in that - jar's manifest will be added. This innovative technique was - suggested - by James Strachan. If the information is uncertain, then - the class packaging data will be preceded by a tilde, i.e. - the '~' character. -

- -

Here is an example:

- -

java.lang.NullPointerException - at com.xyz.Wombat(Wombat.java:57) ~[wombat-1.3.jar:1.3] - at com.xyz.Wombat(Wombat.java:76) ~[wombat-1.3.jar:1.3] - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.5.0_06] - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.5.0_06] - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.5.0_06] - at java.lang.reflect.Method.invoke(Method.java:585) ~[na:1.5.0_06] - at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59) [junit-4.4.jar:na] - at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98) [junit-4.4.jar:na] - ...etc

- -

Logback goes to great lengths to ensure that the class - packaging information it displays is correct, even in - arbirarily complex class loader hierarchies. However, when - it is not able to guarantee the absolute correctness of the - information, then it will prefix the data with a tilde, i.e. - the '~' character. Thus, it is theoretically possible for - the printed class packaging information to differ from the - real class packaging information. So, in the above example, - given that packaging data for the Wombat class is preceded - by a tilde, it possible that the correct packaging data is - in reality [wombat.jar:1.7]. -

- -
- nopex
- nopexception -
-

Altough it pretends to handle stack trace data, this - conversion word does not output any data, thus, effectively - ignoring exceptions. -

- -

The %nopex conversion word allows the user to override - PatternLayout's internal safety mechanism which silently - adds %ex conversion keyword, even it was not specified in - the conversion pattern. -

-
- marker - -

Used to output the marker associated with the logger - request.

- -

In case the marker contains children markers, the - converter displays the parent as well as childrens' names - according to the format shown below. -

-

- parentName [ child1, child2 ] -

-
- property{key} - -

Used to output the value associated with a context - property named key. If key is not a - property of the logger context, then key will be - looked up in the System properties.

- - -

There is no default value for key. If it is - omitted, the returned value will be "Property_HAS_NO_KEY", - expliciting the error condition.

- -

-

- -
- -

Given that in the context of conversion patterns the percent - sign carries special meaning, in order to include it as a literal, - it needs to be escaped with a backslash, e.g. "%d %p \% - %m%n". -

- - -

Format modifiers

- -

By default the relevant information is output as is. However, - with the aid of format modifiers it is possible to change the - minimum field width, the maximum field width as well as - justification. -

- -

The optional format modifier is placed between the percent sign - and the conversion character or word. -

- -

The first optional format modifier is the left - justification flag which is just the minus (-) - character. Then comes the optional minimum field width - modifier. This is a decimal constant that represents the minimum - number of characters to output. If the data item contains fewer - characters, it is padded on either the left or the right until the - minimum width is reached. The default is to pad on the left (right - justify) but you can specify right padding with the left - justification flag. The padding character is space. If the data - item is larger than the minimum field width, the field is expanded - to accommodate the data. The value is never truncated. -

- -

This behavior can be changed using the maximum field - width modifier which is designated by a period followed by a - decimal constant. If the data item is longer than the maximum - field, then the extra characters are removed from the - beginning of the data item. For example, if the maximum - field width is eight and the data item is ten characters long, - then the first two characters of the data item are dropped. This - behavior deviates from the printf function in C where truncation - is done from the end. -

- -

Truncation from the end is possible by appending a minus - character right after the period. In that case, if the maximum - field width is eight and the data item is ten characters long, - then the last two characters of the data item are dropped. -

- -

Below are various format modifier examples for the logger - conversion specifier. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Format modifierLeft justifyMinimum widthMaximum widthComment
%20loggerfalse20none - Left pad with spaces if the logger name is less - than 20 characters long. -
%-20loggertrue20none - Right pad with spaces if the logger name is less - than 20 characters long. -
%.30loggerNAnone30 - Truncate from the beginning if the logger name is - longer than 30 characters. -
%20.30loggerfalse2030 - Left pad with spaces if the logger name is shorter - than 20 characters. However, if logger name is - longer than 30 characters, then truncate from the - beginning. -
%-20.30loggertrue2030 - Right pad with spaces if the logger name is shorter - than 20 characters. However, if logger name is - longer than 30 characters, then truncate from the - beginning. -
%.-30loggerNAnone30 - Truncate from the end if the logger name is - longer than 30 characters. -
- -

The table below list examples for format modifier - truncation. Please note that the brackets, i.e the pair of "[]" - characters, are not part of the output. They are used to delimit - the width of output.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Format modifierLogger nameResult
[%20.20logger]main.Name
[           main.Name]
[%-20.20logger]main.Name
[main.Name           ]
[%10.10logger]main.foo.foo.bar.Name
[o.bar.Name]
[%10.-10logger]main.foo.foo.bar.Name
[main.foo.f]
- -

Parentheses are special

- -

In logback, parentheses within the pattern string are treated - as grouping tokens. Thus, it is possible to group a sub-pattern - and apply formatting directives on that sub-pattern. -

- -

For example, the pattern

- -

%-30(%d{HH:mm:ss.SSS} [%thread]) %-5level %logger{32} - %msg%n

- -

will group the output generated by the sub-pattern - "%d{HH:mm:ss.SSS} [%thread]" so that it is right-padded if less - than 30 characters. -

- -

If without the grouping the output was

- -

13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Classload hashcode is 13995234 -13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Initializing for ServletContext -13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Trying platform Mbean server -13:09:30 [pool-1-thread-1] INFO ch.qos.logback.demo.LoggingTask - Howdydy-diddly-ho - 0 -13:09:38 [btpool0-7] INFO c.q.l.demo.lottery.LotteryAction - Number: 50 was tried. -13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Beginning to factor. -13:09:40 [btpool0-7] DEBUG c.q.l.d.prime.NumberCruncherImpl - Trying 2 as a factor. -13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Found factor 2 -

- -

with the "%-30()" grouping it would be

- -

13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Classload hashcode is 13995234 -13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Initializing for ServletContext -13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Trying platform Mbean server -13:09:30 [pool-1-thread-1] INFO ch.qos.logback.demo.LoggingTask - Howdydy-diddly-ho - 0 -13:09:38 [btpool0-7] INFO c.q.l.demo.lottery.LotteryAction - Number: 50 was tried. -13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Beginning to factor. -13:09:40 [btpool0-7] DEBUG c.q.l.d.prime.NumberCruncherImpl - Trying 2 as a factor. -13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Found factor 2 -

- - -

The latter form is more comfortable to read, especially for - long log files.

- -

If you need to treat the parenthesis character as a literal, - they needs to be escaped by preceding each parenthesis with a - backslash. As in, \(%d{HH:mm:ss.SSS} - [%thread]\). Strictly speaking, only the closing parentesis - needs to be escaped. Thus, "%d [%thread]\)" is - equivalent to "\(%d [%thread]\)". -

- - - -

Options

- -

- A conversion specifier can be followed by options. The are - always declared between braces. We have already seen some of the - possibilities offered by options, for instance in conjunction - with the MDC conversion specifier, as in: - %mdc{someKey}. -

- -

A conversion specifier might have more than one option. For - example, a conversion specifier that makes use of evaluators, - which will be covered soon, may add evaluator names to the option - list, as shown below:

- -
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
-    <layout class="ch.qos.logback.classic.PatternLayout"> 
-      <param name="Pattern" value="%-4relative [%thread] %-5level - %msg%n \
-        %caller{2, DISP_CALLER_EVAL, OTHER_EVAL_NAME, THIRD_EVAL_NAME}" /> 
-    </layout>
-  </appender>
- - -

Evaluators

- -

As mentioned above, option lists come in handy when a - conversion specifier is required to behave dynamically based on - one or more - - EventEvaluator objects. - EventEvaluator objects have the responsibility to - determine whether a given logging event matches the criteria of the - evaluator. -

- -

Let us review an example with EventEvaluator - objects. The following configuration file outputs the logging - events to the console, displaying date, thread, level, message and - caller data. Given that extracting the caller data of a logging - event is on expensive side, we will do so only when the logging - request originates from a specific logger, and whose message - contains a certain string. Thus, we make sure that only specific - logging requests will have their caller information generated and - displayed. In other cases, where the caller data is superfluous, - we will not penalize application performance. -

- - - Example 5.2: Sample usage of EventEvaluators - (logback-examples/src/main/java/chapter5/callerEvaluatorConfig.xml) - -
<configuration>
-  <evaluator name="DISP_CALLER_EVAL">
-    <Expression>logger.getName().contains("chapter5") &amp;&amp; \
-      message.contains("who calls thee")</Expression>
-  </evaluator>
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
-    <layout class="ch.qos.logback.classic.PatternLayout"> 
-      <Pattern>%-4relative [%thread] %-5level - %msg%n%caller{2, DISP_CALLER_EVAL}
-      </Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug"> 
-    <appender-ref ref="STDOUT" /> 
-  </root>
-</configuration>
- -

Due to XML encoding rules, the & character cannot be - written as is, and needs to be escaped as &amp;.

- -

The above configuration file is designed to be accompanied by - the following custom-tailored code.

- -

- Example 5.2: Sample usage of EventEvaluators - - (logback-examples/src/main/java/chapter5/CallerEvaluatorExample.java) - -

-
package chapter5;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.joran.JoranConfigurator;
-import ch.qos.logback.core.joran.spi.JoranException;
-import ch.qos.logback.core.util.StatusPrinter;
-
-public class CallerEvaluatorExample {
-
-  public static void main(String[] args)  {
-    Logger logger = LoggerFactory.getLogger(CallerEvaluatorExample.class);
-    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-
-    try {
-      JoranConfigurator configurator = new JoranConfigurator();
-      configurator.setContext(lc);
-      configurator.doConfigure(args[0]);
-    } catch (JoranException je) {
-      StatusPrinter.print(lc);
-    }
-
-    for (int i = 0; i < 5; i++) {
-      if (i == 3) {
-        logger.debug("who calls thee?");
-      } else {
-        logger.debug("I know me " + i);
-      }
-    }
-  }
-}
-

- The CallerEvaluatorExample application does nothing particularly - fancy. Five logging requests are issued, the third one being - different from the others. -

-

- When a logging request is issued, the corresponding logging - event goes through the evaluation process. The third request - matches the evaluation criteria, causing its caller data to be - displayed. -

- -

- Here is the output of the - CallerEvaluatorExample - class. -

- -
0    [main] DEBUG - I know me 0 
-0    [main] DEBUG - I know me 1 
-0    [main] DEBUG - I know me 2 
-0    [main] DEBUG - who calls thee? 
-Caller+0   at chapter5.CallerEvaluatorExample.main(CallerEvaluatorExample.java:28)
-0    [main] DEBUG - I know me 4
- -

One can change the expression to correspond a real world - scenario. For instance, one could combine the logger name and - request level. Thus, logging requests of level WARN and - up, originating from a sensitive part of an application, e.g. a - financial transaction module, would have their caller data - displayed. -

- -

Important: With the caller conversion - specifier, the data is displayed when the expression evaluates - to true.

- -

Let us consider at a different situation. When exceptions are - included in a logging request, their stack trace is usually - displayed. However, in some cases, one might want to supress the - stack trace of some specific exception. -

- -

The java code shown below creates five log requests, each with - an exception. However, it so happends that we do not wish the - stack trace of the third request to be output.

- -

- Example 5.2: Sample usage of EventEvaluators - - (logback-examples/src/main/java/chapter5/ExceptionEvaluatorExample.java) - -

-
package chapter5;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.joran.JoranConfigurator;
-import ch.qos.logback.core.joran.spi.JoranException;
-import ch.qos.logback.core.util.StatusPrinter;
-
-public class ExceptionEvaluatorExample {
-
-  public static void main(String[] args) {
-    Logger logger = LoggerFactory.getLogger(ExceptionEvaluatorExample.class);
-    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-
-    try {
-      JoranConfigurator configurator = new JoranConfigurator();
-      configurator.setContext(lc);
-      configurator.doConfigure(args[0]);
-    } catch (JoranException je) {
-      StatusPrinter.print(lc);
-    }
-    for (int i = 0; i < 5; i++) {
-      if (i == 3) {
-        logger.debug("logging statement " + i, new TestException(
-            "do not display this"));
-      } else {
-        logger.debug("logging statement " + i, new Exception("display"));
-      }
-    }
-  }
-}
- -

The following configuration will supress the stack trace of the - third logging request.

- - Example 5.3: Sample usage of EventEvaluators - (logback-examples/src/main/java/chapter5/exceptionEvaluatorConfig.xml) - -
<configuration>
-
-  <evaluator name="DISPLAY_EX_EVAL">
-    <Expression>throwable != null &amp;&amp; throwable instanceof  \
-      chapter5.TestException</Expression>
-  </evaluator>
-	
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%-4relative [%thread] %-5level - %msg%n%ex{full, DISPLAY_EX_EVAL}
-      </Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

With this configuration, each time an instance of the - chapter5.TestException is included within a logging - request, the stack trace will be suppressed. -

- -

Important: With the %ex conversion - specifier, the stack trace is displayed when the expression - evaluates to false.

- - -

Creating a custom conversion - specifier

- -

Up to this point we have presented the built-inconversion - specifiers of PatternLayout. But it is also possible - to use a conversion specifier of your own making.

- -

Building a custom conversion specifier consists of two steps. -

- -

First, you must extend the ClassicConverter - class. - ClassicConverter objects are responsible for - extracting information out of ILoggingEvent instances - and producing a String. For example, the - - LoggerConverter, the converter underlying the - %logger conversion word, extracts the name of the logger from - ILoggingEvent and returns it as a String. It might - abbreviate the logger name in the process.

- -

Let us say that our customized ClassicConverter - colors the level of the logging event, according to ANSI terminal - conventions. Here is a possible implementation:

- - Example 5.4: Sample Converter Example - -(src/main/java/chapter5/MySampleConverter.java) -
package chapter5;
-
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.pattern.ClassicConverter;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-
-public class MySampleConverter extends ClassicConverter {
-
-  private static final String END_COLOR = "\u001b[m";
-
-  private static final String ERROR_COLOR = "\u001b[0;31m";
-  private static final String WARN_COLOR = "\u001b[0;33m";
-
-  @Override
-  public String convert(ILoggingEvent event) {
-    StringBuffer sbuf = new StringBuffer();
-    sbuf.append(getColor(event.getLevel()));
-    sbuf.append(event.getLevel());
-    sbuf.append(END_COLOR);
-    return sbuf.toString();
-  }
-
-  /**
-   * Returns the appropriate characters to change the color for the specified
-   * logging level.
-   */
-  private String getColor(Level level) {
-    switch (level.toInt()) {
-    case Level.ERROR_INT:
-      return ERROR_COLOR;
-    case Level.WARN_INT:
-      return WARN_COLOR;
-    default:
-      return "";
-    }
-  }
-}
-
- -

This implementation is relatively straightforward. The - MySampleConverter class extends - ClassicConverter, and implements the - convert method where it returns a level string - decorated with ANSI coloring codes. -

- -

In the second step, we must let logback know about the new - Converter. For this purpose, we need to declare the - new conversion word in the configuration file, as shown below:

- - Example 5.4: Sample Converter Example (src/main/java/chapter5/mySampleConverterConfig.xml) -
<configuration>
-
-  <conversionRule conversionWord="sample" converterClass="chapter5.MySampleConverter" />
-	
-  <appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    <layout class="ch.qos.logback.classic.PatternLayout">
-      <Pattern>%-4relative [%thread] %sample - %msg%n</Pattern>
-    </layout>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
- -

In this configuration file, once the new conversion word has - been declared, we can refert to it within a - PatternLayout pattern, as if the custom conversion - word had always been here.

- -

Given that ANSI terminal codes do not work on Windows, you can - view the results on non-Windows platforms such as Linux or - Mac. The following command:

- -
java chapter5.SampleLogging src/main/java/chapter5/mySampleConverterConfig.xml
- -

should yield:

- -

0 [main] DEBUG - Everything's going well -3 [main] ERROR - maybe not quite...

- - -

Please note that the string "ERROR" is highlighted in red, - which was somewhat the point of the exercise.

- -

The intersted reader might want to take a look at other - Converter implementations such as - - MDCConverter to learn about more complex - behaviours, such as option handling. -

- - - -

- HTMLLayout -

- -

HTMLLayout - (as included in logback-classic) generates logs in HTML - format. HTMLLayout outputs logging events in an HTML - table where each row of the table corresponds to a logging - event.

- -

Here is a sample output produced by HTMLLayout - using its default CSS stylesheet:

- HTML Layout Sample Image - -

The content of table columns are specified with the help of a - conversion pattern. See PatternLayout for - documentation on conversion patterns. As such, you have full - control over the contents and format of the table. You can select - and display any combination of converters - PatternLayout knows about. -

- -

One notable exception about the use of - PatternLayout with HTMLLayout is that - conversion specifiers should not be separated by space characters - or more generally by literal text. Each specifier found in the - pattern will result in a separate column. Likewise a separate - column will be generated for each block of literal text found in - the pattern potentially wasting valuable real estate on your - screen.

- -

Here is simple but functional configuration file illustrating - the use of HTMLLayout. -

- -
<configuration debug="true">
-  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
-    <layout class="ch.qos.logback.classic.html.HTMLLayout">
-      <pattern>%relative%thread%mdc%level%logger%msg</pattern>
-    </layout>
-   <File>/test.html</File>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="FILE" />
-  </root>
-</configuration>
-
- -

Launching the TrivialMain application listed below - will create the file test.html on your local drive.

- -
import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TrivialMain {
-  public static void main(String[] args) throws InterruptedException {
-    Logger logger = LoggerFactory.getLogger(TrivialMain.class);
-    for(int i = 0; i < 6; i ++) {
-      if(i % 5 == 0) {
-        logger.info("an info message "+i);
-      } else {
-        logger.debug("hello world number" +i);
-      }
-    }
-    logger.error("Finish off with fireworks", new Exception("Just testing"));
-  }
-}
- -

The contents of test.html should be similar to: -

- HTML Layout Sample Image - -

Stack traces

- -

If you use the %em conversion word to display stack - traces, a table column will be created to display stack traces. In - most cases the column will be empty, wasting screen - real-estate. Moreover, printing a stack trace on a separate column - does not yield very readable results. Fortunately, the - %ex conversion word is not the only way to display stack - traces. -

- -

A better solution is available through implementations of - IThrowableRenderer interface. Such an implementation - can be assigned to HTMLLayout to manage the display - data related to exceptions. By default, a - - DefaultThrowableRenderer is assigned to each - HTMLLayout instance. It writes exceptions on a - new table row, along with its stack trace, in an easily - readable manner, as shown on the figure above. -

- -

If for some reason, you still wish to use the %ex - pattern, then you can specify - NOPThrowableRenderer in the configuration file in - order to disable displaying a separate row for the stack trace. We - don't have the faintest idea why you would want to do that, but if - you wished, you could. -

- -

CSS

- -

The presentation of the HTML created by HTMLLayout - is controlled through a Cascading Style Sheet (CSS). In the - absence of specific instructions, HTMLLayout will - default to its internal CSS. However, your can instruct - HTMLLayout to use an external CSS file. For this - purpose a cssBuilder element can be nested within a - <layout> element, as shown below. -

- -
<layout>
-  ...
-  <cssBuilder class="ch.qos.logback.core.html.UrlCssBuilder">
-    <url>path_to_StyleFile.css</url>
-  </cssBuilder>	
-  ...
-</layout>
- - -

The HTMLLayout is often used in conjunction with - SMTPAppender, in order to send an email pleasantly - formatted in HTML. Here is a typical configuration: -

- -
<configuration>
-  <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
-    <layout class="ch.qos.logback.classic.html.HTMLLayout">
-      <pattern>%relative%thread%mdc%level%class%msg</pattern>
-    </layout>
-    <From>sender.email@domain.net</From>
-    <SMTPHost>mail.domain.net</SMTPHost>
-    <Subject>LastEvent: %class - %msg </Subject>
-    <To>destination.email@domain.net</To> 
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="SMTP" />
-  </root>
-</configuration>
- -

HTMLLayout can also be used with any - FileAppender, including a a rolling file appender, as - shown in the sample configuration below. -

- -
<configuration>
-   <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
-   <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-     <ActiveFileName>lastLogEntries.html</ActiveFileName>
-     <FileNamePattern>logEntries.%d{yyyy-MM-dd}.log</FileNamePattern>
-   </rollingPolicy>
-   
-   <layout class="ch.qos.logback.classic.html.HTMLLayout">
-      <cssBuilder class="ch.qos.logback.core.html.UrlCssBuilder">
-        <url>address_of_a_custom_stylesheet.css</url>
-      </cssBuilder>	
-      <Pattern>%relative%thread%mdc%level%logger%msg</Pattern>
-      <Title>Logging Events</Title>
-    </layout>
- </appender> 
-
- <root level="debug">
-   <appender-ref ref="FILE" />
- </root>
-</configuration>
- -

Log4j XMLLayout

- - -

XMLLayout - (part of logback-classic) generates output in a log4j.dtd - compliant format. It can be used to inter-operate with tools such - as Chainsaw - and Vigilog capable - of processing files generated by log4j's - XMLLayout. -

- - -

As the original XMLLayout in log4j version 1.2.15, XMLLayout in - logback-classic admits two boolean properties, LocationInfo and Properties. Setting LocationInfo to true enables the inclusion - of location info (caller data) in the each event. Setting Properties to true enables the inclusion of - MDC information. Both options are set to false by default. -

- -

Here is a sample configuration

- -
<configuration>
-  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
-    <File>test.xml</File>
-    <layout class="ch.qos.logback.classic.log4j.XMLLayout">
-      <LocationInfo>true</LocationInfo>
-    </layout>
-  </appender> 
-
-  <root level="debug">
-    <appender-ref ref="FILE" />
-  </root>
-</configuration> 
- -

Logback access

- -

Most logback-access layouts are mere adaptations of - logback-classic layouts. Logback-classic and logback-access - modules address different needs, but in general offer comparable - functionality.

- -

Writing your own Layout

-

Writing a custom Layout for logback access is - nearly identical to its siblingLayout in - logback-classic.

- - - - -

PatternLayout

- -

- PatternLayout in logback-access can be configured - much in the same way as its classic counterpart. However it - features additional conversion specifiers suited for logging - particular bits of information availalbe only in HTTP servlet - requests and HTTP servlet responses. -

- -

Below is a list of conversion specifiers for - PatternLayout in logback-access.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Conversion WordEffect
a / remoteIP -

- Remote IP address. -

-
A / localIP -

- Local IP address. -

-
b / B / byteSent -

- Response's content length. -

-
h / clientHost -

- Remote host. -

-
H / protocol -

- Request protocol. -

-
l -

- Remote log name. In logback-access, this converter always - returns the value "-". -

-
reqParameter{paramName} -

- Parameter of the response. -

-

This conversion word takes the first option in braces and looks - for the corresponding parameter in the request.

-

%reqParameter{input_data} - displays the corresponding parameter.

-
i{header} / header{header} -

- Request header. -

-

This conversion word takes the first option in braces and looks - for the corresponding header in the request.

-

%header{Referer} displays the referer of the request.

-

- If no option is specified, it displays every available header. -

-
m / requestMethod -

- Request method. -

-
r / requestURL -

- URL requested. -

-
s / statusCode -

- Status code of the request. -

-
t / date -

Used to output the date of the logging event. The date - conversion specifier may be followed by a set of braces - containing a date and time pattern strings used by - java.text.SimpleDateFormat. ABSOLUTE, - DATE or ISO8601 are also valid values. -

-

For example, %d{HH:mm:ss,SSS}, - %d{dd MMM yyyy ;HH:mm:ss,SSS} or - %d{DATE}. If no date format specifier is given then - ISO8601 format is assumed. -

-
u / user -

- Remote user. -

-
U / requestURI -

- Requested URI. -

-
v / server -

Server name.

-
localPort -

Local port.

-
reqAttribute{attributeName} -

Attribute of the request.

-

This conversion word takes the first option in braces and looks - for the corresponding attribute in the request.

-

%reqAttribute{SOME_ATTRIBUTE} - displays the corresponding attribute.

-
reqCookie{cookie} -

Request cookie.

-

This conversion word takes the first option in braces and looks - for the corresponding cookie in the request.

-

%cookie{COOKIE_NAME} displays corresponding cookie.

-
responseHeader{header} -

- Header of the response. -

-

This conversion word takes the first option in braces and looks - for the corresponding header in the response.

-

%header{Referer} displays the referer of the response.

-
requestContent -

This conversion word displays the content of the request, - that is the request's InputStream. It is used - in conjunction with a - TeeFilter, a - javax.servlet.Filter that replaces the original - HttpServletRequest by a - TeeHttpServletRequest. The latter object - allows access to the request's InputStream - multiple times without any loss of data. -

-
fullRequest -

This converter outputs the data associated with the - request, including all headers and request contents. -

-
responseContent -

This conversion word displays the content of the - response, that is the response's - InputStream. It is used in conjunction with a - - TeeFilter, a - javax.servlet.Filter that replaces the original - HttpServletResponse by a - TeeHttpServletResponse. The latter object - allows access to the requet's InputStream - multiple times without any loss of data. -

-
fullResponse -

This conversion word takes all the available data - associated with the response, inclusing all headers of the - response and response contents. -

-
- -

Logback access' PatternLayout also recognize three keywords, which - act like shortcuts to a certain pattern.

- - - - - - - - - - - - - - - -
keywordequivalent conversion pattern
common or CLF%h %l %u %t \"%r\" %s %b
combined%h %l %u %t \"%r\" %s %b \"%i{Referer}\" \"%i{User-Agent}\"
- - -

The common keyword corresponds to the pattern %h %l %u %t \"%r\" %s %b - which displays client host, remote log name, user, date, requested URL, status code - and response's content length

- -

The combined keyword is a shortcut for %h %l %u %t - \"%r\" %s %b \"%i{Referer}\" \"%i{User-Agent}\". This pattern - begins much like the common pattern but also displays two - request headers, namely referer, and user-agent.

- - -

HTMLLayout

- -

The HTMLLayout - class found in logback-access is similar to the HTMLLayout class from - logback-classic. -

- -

By default, it will create a table containing the following data:

- -
    -
  • Remote IP
  • -
  • Date
  • -
  • Request URL
  • -
  • Status code
  • -
  • Content Length
  • -
- -

Here is a sample output produced by HTMLLayout in - logback-access:

- Access HTML Layout Sample Image - -

What can be better than a real world example? Our own log4j - properties for logback translator makes use - of logback-access to demonstrate live ouput from - RollingFileAppender with HTMLLayout.

- - -

On every new user request to our translator - web-application, a new entry will be added to the access logs, - which you can view by following - this link.

- - - -
- - + + + + + + Chapter 5: Layouts + + + + + + + + + + +
+ + +
+ +
+ +

Chapter 5: Layouts

+ +
+

TCP implementations will follow a general principle of + robustness: be conservative in what you do, be liberal in what + you accept from others. +

+

—JON POSTEL, RFC 793

+
+ + + + +

What is a layout?

+ +

While appenders are responsible for writing logging output to + an appender dependent device, layouts are responsible for the + format of the output. In case you were wondering, layouts have + nothing to do with large estates in Florida. The + format() method in the Layout + interface takes an object that represents an event (of any type) + and returns a String. A synopsis of the Layout + interface is shown below. +

+ +
public interface Layout<E> extends ContextAware, LifeCycle {
+
+  String doLayout(E event);
+  String getHeader();
+  String getFooter();
+  String getContentType();
+}
+ +

This interface is rather simple and yet is sufficent for many + formatting needs. The Texan developer from Texas, who you might + know from Joseph Heller's Catch-22, might exclaim: it + just takes five methods to implement a layout!!? +

+ +

Logback-classic

+ +

Logback-classic is wired to processes only events of type + + ch.qos.logback.classic.spi.ILoggingEvent. This + fact will be apparent throughout this section.

+ +

Writing your own Layout

+ +

Let us implement a simple yet functional layout for the + logback-classic module that prints the time elapsed since the + start of the application, the level of the logging event, the + caller thread between brackets, its logger name, a dash followed + by the event message and a new line. +

+ +

Sample output might look like:

+ +
10489 DEBUG [main] com.marsupial.Pouch - Hello world.
+ +

Here is a possible implementation, authored by the Texan developer:

+ Example 5.0: Sample implementation of a Layout + + (logback-examples/src/main/java/chapter5/MySampleLayout.java) + +
package chapter5;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.LayoutBase;
+
+public class MySampleLayout extends LayoutBase<ILoggingEvent> {
+
+  public String doLayout(ILoggingEvent event) {
+    StringBuffer sbuf = new StringBuffer(128);
+    sbuf.append(event.getTimeStamp() - event.getLoggingContextVO.getBirthTime());
+    sbuf.append(" ");
+    sbuf.append(event.getLevel());
+    sbuf.append(" [");
+    sbuf.append(event.getThreadName());
+    sbuf.append("] ");
+    sbuf.append(event.getLoggerName();
+    sbuf.append(" - ");
+    sbuf.append(event.getFormattedMessage());
+    sbuf.append(CoreConstants.LINE_SEP);
+    return sbuf.toString();
+  }
+}
+ +

Note that MySampleLayout extends + LayoutBase. This class manages state shared by + all Layout classes, such as whether the layout is + started or stopped, header, footer and content type data. It + allows the developer to concentrate on the formatting expected + from his/her Layout. Note that the + LayoutBase class is generic. In its class + declaration, MySampleLayout extends + LayoutBase<ILoggingEvent>. +

+ +

The doLayout(ILoggingEvent event) method, i.e. the + only method in MySampleLayout, begins by + instantiating a StringBuffer. It proceeds by adding + various fields of the event parameter. The Texan from Texas was + careful to print the formatted form of the message. This is + significant in case one or more parameters were passed along with + the logging request. +

+ +

After adding these various characters to the string buffer, the + doLayout() method converts the buffer into a + String and returns the resulting value. +

+ +

In the above example, the doLayout method ignores + any eventual exceptions contained in the event. In a real world + layout implementation, you would most probably want to print the + contents of exceptions as well. +

+ +

Configuring your custom layout

+ +

Custom layouts are configured as any other layout. Here is as + example:

+ + Example 5.0: Configuration of MySampleLayout + (logback-examples/src/main/java/chapter5/sampleLayoutConfig.xml) +
<configuration>
+
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="chapter5.MySampleLayout" />
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

The sample application + chapter5.SampleLogging configures logback with + the configuration script supplied as a parameter and then logs a + debug message, followed by an error message.

+ +

+ To run this example issue the following command from within the + logback-examples directory. +

+ +

java chapter5.SampleLogging src/main/java/chapter5/sampleLayoutConfig.xml

+ +

This will produce:

+ +
0 DEBUG [main] chapter5.SampleLogging - Everything's going well
+0 ERROR [main] chapter5.SampleLogging - maybe not quite...
+ +

That was simple enough. The skeptic Pyrrho of Elea, who + insists that nothing is certain except perhaps uncertainty itself, + which is by no means certain either, might ask: how about a layout + with options? The reader shall find a slightly modified version + of our custom layout in MySampleLayout2.java. She + will discover that adding an option to a layout is as simple as + declaring a setter method for the option. +

+ +

+ The + MySampleLayout2 + + class contains two attributes. The first one is a prefix that + can be added to the output. The second attribute is used to + choose whether to display the name of the thread from which + the logging request was sent. +

+

Here is the implementation of this class:

+ +
package chapter5;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.LayoutBase;
+
+public class MySampleLayout2 extends LayoutBase<ILoggingEvent> {
+
+  String prefix = null;
+  boolean printThreadName = true;
+
+  public void setPrefix(String prefix) {
+    this.prefix = prefix;
+  }
+
+  public void setPrintThreadName(boolean printThreadName) {
+    this.printThreadName = printThreadName;
+  }
+
+  public String doLayout(ILoggingEvent event) {
+    StringBuffer sbuf = new StringBuffer(128);
+    if (prefix != null) {
+      sbuf.append(prefix + ": ");
+    }
+    sbuf.append(event.getTimeStamp() - event.getLoggerContextVO().getBirthTime());
+    sbuf.append(" ");
+    sbuf.append(event.getLevel());
+    if (printThreadName) {
+      sbuf.append(" [");
+      sbuf.append(event.getThreadName());
+      sbuf.append("] ");
+    } else {
+      sbuf.append(" ");
+    }
+    sbuf.append(event.getLoggerName());
+    sbuf.append(" - ");
+    sbuf.append(event.getFormattedMessage());
+    sbuf.append(LINE_SEP);
+    return sbuf.toString();
+  }
+}
+ + +

The addition of the corresponding setter method is all that is + needed to enable the configuration of an option. Note that the + PrintThreadName option is boolean and not + String. Configuration of logback components was + covered in detail in "Chapter 3: + Logback configuration". Here is the configuration + file tailor-made for use with MySampleLayout2. +

+ + +
<configuration>
+
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="chapter5.MySampleLayout2"> 
+      <prefix>MyPrefix</prefix>
+      <printThreadName>false</printThreadName>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

+ + + +

PatternLayout

+ +

Logback classic ships with a flexible layout called + PatternLayout. As all layouts, + PatternLayout takes a logging event and returns a + String. However, this String can be + customized at will by tweaking the conversion pattern of + PatternLayout. +

+ +

The conversion pattern of PatternLayout is closely + related to the conversion pattern of the printf() + function in the C programming language. A conversion pattern is + composed of literal text and format control expressions called + conversion specifiers. You are free to insert any literal text + within the conversion pattern. Each conversion specifier starts + with a percent sign '%' and is followed by optional format + modifiers, a conversion word and optional parameters between + braces. The conversion word controls the type of data to use, e.g. + logger name, level, date, thread name. The format modifiers + control such things as field width, padding, and left or right + justification. The following is a simple example. +

+ + Example 5.1: Sample usage of a PatternLayout + + (logback-examples/src/main/java/chapter5/PatternSample.java) + +
package chapter5;
+
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.PatternLayout;
+import ch.qos.logback.core.ConsoleAppender;
+
+public class PatternSample {
+
+  static public void main(String[] args) throws Exception {
+    Logger rootLogger = (Logger)LoggerFactory.getLogger("root");
+
+    PatternLayout layout = new PatternLayout();
+    layout.setPattern("%-5level [%thread]: %message%n");
+    layout.start();
+
+    ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<ILoggingEvent>();
+    appender.setContext(rootLogger.getLoggerContext());
+    appender.setLayout(layout); appender.start();
+
+    rootLogger.addAppender(appender);
+
+    rootLogger.debug("Message 1"); 
+    rootLogger.warn("Message 2");
+  } 
+}
+ +

The conversion pattern is set to be "%-5level [%thread]: + %message%n". Running PatternSample will yield the following + output on the console. +

+ +

DEBUG [main]: Message 1 +WARN [main]: Message 2

+ +

Note that in the conversion pattern "%-5level [%thread]: + %message%n" there is no explicit separator between literal + text and conversion specifiers. When parsing a conversion pattern, + PatternLayout is capable of differentiating between + literal text (space characters, the brackets, colon character) and + conversion specifiers. In the example above, the conversion + specifier %-5level means the level of the logging event should be + left justified to a width of five characters. Format specifiers + will be explained below. +

+ +

In PatternLayout, parenthesis can be used to group conversion + patterns. It follows that the '(' and ')' carry special meaning + and need to be escaped to be used as literals. Parentheses + can be escaped by preceding the the opening and closing + parenthesis by a backslash, but since the backslash itself carries + special meaning in Java, we need two backslashes, as in "\\(" and + "\\)". Note that strictly speaking, only the closing parenthesis + needs to be escaped to be used as a literal. +

+ +

As mentioned previously, certain conversion specifiers can + include optional parameters which are passed between braces + following the conversion word. A sample conversion specifier with + options could be %logger{10}. Here "logger" is the + conversion word, and 10 is the option. +

+ +

The recognized conversions words along with their options are + described in the table below. When multiple conversion words are + listed on the left column, they should be considered as aliases. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Conversion WordEffect
+ c{length}
+ lo{length}
+ logger{length}
+
+

Used to output the name of the logger at the origin of + the logging event. +

+ +

This conversion word can take an integer as its first and + only option. The converter's abbreviation algorithm will + shorten the logger name, usually without significant loss of + meaning. Setting the value of this option to zero has + special meaning. It will cause the conversoin specifier to + return the string right to the rightmost dot character. The + next table provides examples of the abbreviation algorithm + in action. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Conversion specifierLogger nameResult
%loggermainPackage.sub.sample.BarmainPackage.sub.sample.Bar
%logger{0}mainPackage.sub.sample.BarBar
%logger{5}mainPackage.sub.sample.Barm.s.s.Bar
%logger{10}mainPackage.sub.sample.Barm.s.s.Bar
%logger{15}mainPackage.sub.sample.Barm.s.sample.Bar
%logger{16}mainPackage.sub.sample.Barm.sub.sample.Bar
%logger{26}mainPackage.sub.sample.BarmainPackage.sub.sample.Bar
+ +

Please note that the right most segment in a logger name + is never abbreviated, even if its length is longer than the + length option. Other segments may be shortened to + at most a single character but are never removed.

+ +
+ C{length}
+ class{length}
+
+

Used to output the fully-qualified class name of the + caller issuing the logging request. +

+

Just like the %logger conversion word above, + this word can take an integer as its first option and use + its abbreviation algorithm to shorten the class name. Zero + carries special meaning and will cause the simple class name + to be printed without its package name prefix. By default + the class name is printed in full. +

+ +

Generating the caller class information is not + particularly fast. Thus, it's use should be avoided unless + execution speed is not an issue. +

+
+ contextName
+ cn
Outputs the name of the logger context to which the + logger at the origin of the logging event is attached + to.
+ d{pattern}
+ date{pattern}
+
+

Used to output the date of the logging event. The date + conversion word may be followed by an option enclosed + between braces.

+ +

The option admits the same syntax as the time pattern + string of the java.text.SimpleDateFormat.

+ +

A shortcut to the ISO8601 format is available by + specifying the String "ISO8601" in the braces. If + no option is set, the converter uses "ISO8601" as + the default value.

+ +

Here are some sample option values. They assume that the + actual date is Friday 20th of October, 2006 and that the + author finished his meal a short while ago.

+ + + + + + + + + + + + + + + + + + + + + + +
Conversion PatternResult
%date2006-10-20 14:46:49,812
%date{ISO8601}2006-10-20 14:46:49,812
%date{HH:mm:ss.SSS}14:46:49.812
%date{dd MMM yyyy ;HH:mm:ss.SSS}20 oct. 2006;14:46:49.812
+
+ F / file + +

Used to output the file name of the Java source file + where the logging request was issued. +

+ +

Generating the file information is not particularly fast. + Thus, its use should be avoided unless execution speed is + not an issue. +

+
+ caller{depth} + caller{depth, evaluator-1, ... evaluator-n} + +

Used to output location information of the caller which + generated the logging event. +

+ +

The location information depends on the JVM + implementation but usually consists of the fully qualified + name of the calling method followed by the caller's source, + the file name and line number between parentheses. +

+ +

A integer can be added to the caller conversion + specifier's options to configure the depth of the + information to be displayed. +

+ +

For example, %caller{2} would display the + following excerpt:

+ +
0    [main] DEBUG - logging statement 
+Caller+0   at mainPackage.sub.sample.Bar.sampleMethodName(Bar.java:22)
+Caller+1   at mainPackage.sub.sample.Bar.createLoggingRequest(Bar.java:17)
+ +

And %caller{3} would display this other excerpt:

+ +
16   [main] DEBUG - logging statement 
+Caller+0   at mainPackage.sub.sample.Bar.sampleMethodName(Bar.java:22)
+Caller+1   at mainPackage.sub.sample.Bar.createLoggingRequest(Bar.java:17)
+Caller+2   at mainPackage.ConfigTester.main(ConfigTester.java:38)
+ +

This conversion word can also use evaluators to test + logging events against a given criterion before creating the + output. For example, using %caller{3, + CALLER_DISPLAY_EVAL} will display three lines of + stacktrace, only if the evaluator called + CALLER_DISPLAY_EVAL returns a positive + answer. +

+ +

Evaluators are described below.

+
+ L / line + +

Used to output the line number from where the logging + request was issued. +

+ +

Generating the line number information is not particularly + fast. Thus, its use should be avoided unless execution + speed is not an issue. +

+
+ m / msg / message + + Used to output the application-supplied message associated + with the logging event. +
+ M / method + +

+ Used to output the method name where the logging + request was issued. +

+

+ Generating the method name is not particularly fast. + Thus, it's use should be avoided unless + execution speed is not an issue. +

+
+ n + +

+ Outputs the platform dependent line separator + character or characters. +

+

+ This conversion word offers practically the + same performance as using non-portable line + separator strings such as "\n", or "\r\n". Thus, + it is the preferred way of specifying a line + separator. +

+
+ p / le / level + Used to output the level of the logging event.
+ r / relative + + Used to output the number of milliseconds elapsed + since the start of the application until the + creation of the logging event. +
+ t / thread + + Used to output the name of the thread that generated + the logging event. +
+ X{key}
+ mdc{key}
+
+ +

+ Used to output the MDC (mapped diagnostic + context) associated with the thread that + generated the logging event. +

+ +

If mdc conversion word is followed by a key + between braces, as in %mdc{clientNumber}, then the + value in the MDC corresponding to the key will be output. +

+ +

If no option is given, then the entire content of the MDC + will be output in the format "key1=val1, key2=val2". +

+ +

See Chapter 7 for more details on + the MDC. +

+ +
+ ex{length}
+ exception{length}
+ throwable{length}
+
+ ex{length, evaluator-1, ..., evaluator-n}
+ exception{length, evaluator-1, ..., evaluator-n}
+ throwable{length, evaluator-1, ..., evaluator-n} +
+

Used to output the stack trace of the exception + associated with the logging event, if any. By default the + full stack trace will be output. +

+ +

If you do not specify the %ex conversion word (or one of + its aliases) in the conversion pattern, + PatternLayout will automatically add it as the + last conversion word, on account of the importance of stack + trace information. The $nopex conversion word can be + substituted for %ex, in case you do not wish stack trace + information to be displayed. See also %nopex conversion word. +

+ +

The throwable conversion word can followed by one of + the following options: +

+
    +
  • short: prints the first line of the stack trace
  • +
  • full: prints the full stack trace
  • +
  • Any integer: prints the given number of lines of the stack trace
  • +
+ +

Here are some examples:

+ + + + + + + + + + + + + + + + + + + + + + +
Conversion PatternResult
%ex
mainPackage.foo.bar.TestException: Houston we have a problem
+  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
+  at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)
+  at mainPackage.ExceptionLauncher.main(ExceptionLauncher.java:38)
%ex{short}
mainPackage.foo.bar.TestException: Houston we have a problem
+  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
%ex{full}
mainPackage.foo.bar.TestException: Houston we have a problem
+  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
+  at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)
+  at mainPackage.ExceptionLauncher.main(ExceptionLauncher.java:38)
%ex{2}
mainPackage.foo.bar.TestException: Houston we have a problem
+  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
+  at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)
+ +

This conversion word can also use evaluators to test + logging events against a given criterion before creating the + output. For example, using %ex{full, EX_DISPLAY_EVAL} + will display the full stack trace of the exception, only if + the evaluator called EX_DISPLAY_EVAL returns a + negative answer. Evaluators are described further + down in this document. +

+
+ xEx{length}
+ xException{length}
+ xThrowable{length}
+
+ xEx{length, evaluator-1, ..., evaluator-n}
+ xException{length, evaluator-1, ..., evaluator-n}
+ xThrowable{length, evaluator-1, ..., evaluator-n} +
+

Same as the %exception conversion keyword with the + addition of class packaging information.

+ +

At the end of each stack frame of the exception, a string + consisting of the jar file containing the relevant class + followed by the "Implementation-Version" as found in that + jar's manifest will be added. This innovative technique was + suggested + by James Strachan. If the information is uncertain, then + the class packaging data will be preceded by a tilde, i.e. + the '~' character. +

+ +

Here is an example:

+ +

java.lang.NullPointerException + at com.xyz.Wombat(Wombat.java:57) ~[wombat-1.3.jar:1.3] + at com.xyz.Wombat(Wombat.java:76) ~[wombat-1.3.jar:1.3] + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.5.0_06] + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.5.0_06] + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.5.0_06] + at java.lang.reflect.Method.invoke(Method.java:585) ~[na:1.5.0_06] + at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59) [junit-4.4.jar:na] + at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98) [junit-4.4.jar:na] + ...etc

+ +

Logback goes to great lengths to ensure that the class + packaging information it displays is correct, even in + arbirarily complex class loader hierarchies. However, when + it is not able to guarantee the absolute correctness of the + information, then it will prefix the data with a tilde, i.e. + the '~' character. Thus, it is theoretically possible for + the printed class packaging information to differ from the + real class packaging information. So, in the above example, + given that packaging data for the Wombat class is preceded + by a tilde, it possible that the correct packaging data is + in reality [wombat.jar:1.7]. +

+ +
+ nopex
+ nopexception +
+

Altough it pretends to handle stack trace data, this + conversion word does not output any data, thus, effectively + ignoring exceptions. +

+ +

The %nopex conversion word allows the user to override + PatternLayout's internal safety mechanism which silently + adds %ex conversion keyword, even it was not specified in + the conversion pattern. +

+
+ marker + +

Used to output the marker associated with the logger + request.

+ +

In case the marker contains children markers, the + converter displays the parent as well as childrens' names + according to the format shown below. +

+

+ parentName [ child1, child2 ] +

+
+ property{key} + +

Used to output the value associated with a context + property named key. If key is not a + property of the logger context, then key will be + looked up in the System properties.

+ + +

There is no default value for key. If it is + omitted, the returned value will be "Property_HAS_NO_KEY", + expliciting the error condition.

+ +

+

+ +
+ +

Given that in the context of conversion patterns the percent + sign carries special meaning, in order to include it as a literal, + it needs to be escaped with a backslash, e.g. "%d %p \% + %m%n". +

+ + +

Format modifiers

+ +

By default the relevant information is output as is. However, + with the aid of format modifiers it is possible to change the + minimum field width, the maximum field width as well as + justification. +

+ +

The optional format modifier is placed between the percent sign + and the conversion character or word. +

+ +

The first optional format modifier is the left + justification flag which is just the minus (-) + character. Then comes the optional minimum field width + modifier. This is a decimal constant that represents the minimum + number of characters to output. If the data item contains fewer + characters, it is padded on either the left or the right until the + minimum width is reached. The default is to pad on the left (right + justify) but you can specify right padding with the left + justification flag. The padding character is space. If the data + item is larger than the minimum field width, the field is expanded + to accommodate the data. The value is never truncated. +

+ +

This behavior can be changed using the maximum field + width modifier which is designated by a period followed by a + decimal constant. If the data item is longer than the maximum + field, then the extra characters are removed from the + beginning of the data item. For example, if the maximum + field width is eight and the data item is ten characters long, + then the first two characters of the data item are dropped. This + behavior deviates from the printf function in C where truncation + is done from the end. +

+ +

Truncation from the end is possible by appending a minus + character right after the period. In that case, if the maximum + field width is eight and the data item is ten characters long, + then the last two characters of the data item are dropped. +

+ +

Below are various format modifier examples for the logger + conversion specifier. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Format modifierLeft justifyMinimum widthMaximum widthComment
%20loggerfalse20none + Left pad with spaces if the logger name is less + than 20 characters long. +
%-20loggertrue20none + Right pad with spaces if the logger name is less + than 20 characters long. +
%.30loggerNAnone30 + Truncate from the beginning if the logger name is + longer than 30 characters. +
%20.30loggerfalse2030 + Left pad with spaces if the logger name is shorter + than 20 characters. However, if logger name is + longer than 30 characters, then truncate from the + beginning. +
%-20.30loggertrue2030 + Right pad with spaces if the logger name is shorter + than 20 characters. However, if logger name is + longer than 30 characters, then truncate from the + beginning. +
%.-30loggerNAnone30 + Truncate from the end if the logger name is + longer than 30 characters. +
+ +

The table below list examples for format modifier + truncation. Please note that the brackets, i.e the pair of "[]" + characters, are not part of the output. They are used to delimit + the width of output.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Format modifierLogger nameResult
[%20.20logger]main.Name
[           main.Name]
[%-20.20logger]main.Name
[main.Name           ]
[%10.10logger]main.foo.foo.bar.Name
[o.bar.Name]
[%10.-10logger]main.foo.foo.bar.Name
[main.foo.f]
+ +

Parentheses are special

+ +

In logback, parentheses within the pattern string are treated + as grouping tokens. Thus, it is possible to group a sub-pattern + and apply formatting directives on that sub-pattern. +

+ +

For example, the pattern

+ +

%-30(%d{HH:mm:ss.SSS} [%thread]) %-5level %logger{32} - %msg%n

+ +

will group the output generated by the sub-pattern + "%d{HH:mm:ss.SSS} [%thread]" so that it is right-padded if less + than 30 characters. +

+ +

If without the grouping the output was

+ +

13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Classload hashcode is 13995234 +13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Initializing for ServletContext +13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Trying platform Mbean server +13:09:30 [pool-1-thread-1] INFO ch.qos.logback.demo.LoggingTask - Howdydy-diddly-ho - 0 +13:09:38 [btpool0-7] INFO c.q.l.demo.lottery.LotteryAction - Number: 50 was tried. +13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Beginning to factor. +13:09:40 [btpool0-7] DEBUG c.q.l.d.prime.NumberCruncherImpl - Trying 2 as a factor. +13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Found factor 2 +

+ +

with the "%-30()" grouping it would be

+ +

13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Classload hashcode is 13995234 +13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Initializing for ServletContext +13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Trying platform Mbean server +13:09:30 [pool-1-thread-1] INFO ch.qos.logback.demo.LoggingTask - Howdydy-diddly-ho - 0 +13:09:38 [btpool0-7] INFO c.q.l.demo.lottery.LotteryAction - Number: 50 was tried. +13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Beginning to factor. +13:09:40 [btpool0-7] DEBUG c.q.l.d.prime.NumberCruncherImpl - Trying 2 as a factor. +13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Found factor 2 +

+ + +

The latter form is more comfortable to read, especially for + long log files.

+ +

If you need to treat the parenthesis character as a literal, + they needs to be escaped by preceding each parenthesis with a + backslash. As in, \(%d{HH:mm:ss.SSS} + [%thread]\). Strictly speaking, only the closing parentesis + needs to be escaped. Thus, "%d [%thread]\)" is + equivalent to "\(%d [%thread]\)". +

+ + + +

Options

+ +

+ A conversion specifier can be followed by options. The are + always declared between braces. We have already seen some of the + possibilities offered by options, for instance in conjunction + with the MDC conversion specifier, as in: + %mdc{someKey}. +

+ +

A conversion specifier might have more than one option. For + example, a conversion specifier that makes use of evaluators, + which will be covered soon, may add evaluator names to the option + list, as shown below:

+ +
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
+    <layout class="ch.qos.logback.classic.PatternLayout"> 
+      <param name="Pattern" value="%-4relative [%thread] %-5level - %msg%n \
+        %caller{2, DISP_CALLER_EVAL, OTHER_EVAL_NAME, THIRD_EVAL_NAME}" /> 
+    </layout>
+  </appender>
+ + +

Evaluators

+ +

As mentioned above, option lists come in handy when a + conversion specifier is required to behave dynamically based on + one or more + + EventEvaluator objects. + EventEvaluator objects have the responsibility to + determine whether a given logging event matches the criteria of the + evaluator. +

+ +

Let us review an example with EventEvaluator + objects. The following configuration file outputs the logging + events to the console, displaying date, thread, level, message and + caller data. Given that extracting the caller data of a logging + event is on expensive side, we will do so only when the logging + request originates from a specific logger, and whose message + contains a certain string. Thus, we make sure that only specific + logging requests will have their caller information generated and + displayed. In other cases, where the caller data is superfluous, + we will not penalize application performance. +

+ + + Example 5.2: Sample usage of EventEvaluators + (logback-examples/src/main/java/chapter5/callerEvaluatorConfig.xml) + +
<configuration>
+  <evaluator name="DISP_CALLER_EVAL">
+    <Expression>logger.getName().contains("chapter5") &amp;&amp; \
+      message.contains("who calls thee")</Expression>
+  </evaluator>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
+    <layout class="ch.qos.logback.classic.PatternLayout"> 
+      <Pattern>%-4relative [%thread] %-5level - %msg%n%caller{2, DISP_CALLER_EVAL}
+      </Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug"> 
+    <appender-ref ref="STDOUT" /> 
+  </root>
+</configuration>
+ +

Due to XML encoding rules, the & character cannot be + written as is, and needs to be escaped as &amp;.

+ +

The above configuration file is designed to be accompanied by + the following custom-tailored code.

+ +

+ Example 5.2: Sample usage of EventEvaluators + + (logback-examples/src/main/java/chapter5/CallerEvaluatorExample.java) + +

+
package chapter5;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class CallerEvaluatorExample {
+
+  public static void main(String[] args)  {
+    Logger logger = LoggerFactory.getLogger(CallerEvaluatorExample.class);
+    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+    try {
+      JoranConfigurator configurator = new JoranConfigurator();
+      configurator.setContext(lc);
+      configurator.doConfigure(args[0]);
+    } catch (JoranException je) {
+      StatusPrinter.print(lc);
+    }
+
+    for (int i = 0; i < 5; i++) {
+      if (i == 3) {
+        logger.debug("who calls thee?");
+      } else {
+        logger.debug("I know me " + i);
+      }
+    }
+  }
+}
+

+ The CallerEvaluatorExample application does nothing particularly + fancy. Five logging requests are issued, the third one being + different from the others. +

+

+ When a logging request is issued, the corresponding logging + event goes through the evaluation process. The third request + matches the evaluation criteria, causing its caller data to be + displayed. +

+ +

+ Here is the output of the + CallerEvaluatorExample + class. +

+ +
0    [main] DEBUG - I know me 0 
+0    [main] DEBUG - I know me 1 
+0    [main] DEBUG - I know me 2 
+0    [main] DEBUG - who calls thee? 
+Caller+0   at chapter5.CallerEvaluatorExample.main(CallerEvaluatorExample.java:28)
+0    [main] DEBUG - I know me 4
+ +

One can change the expression to correspond a real world + scenario. For instance, one could combine the logger name and + request level. Thus, logging requests of level WARN and + up, originating from a sensitive part of an application, e.g. a + financial transaction module, would have their caller data + displayed. +

+ +

Important: With the caller conversion + specifier, the data is displayed when the expression evaluates + to true.

+ +

Let us consider at a different situation. When exceptions are + included in a logging request, their stack trace is usually + displayed. However, in some cases, one might want to supress the + stack trace of some specific exception. +

+ +

The java code shown below creates five log requests, each with + an exception. However, it so happends that we do not wish the + stack trace of the third request to be output.

+ +

+ Example 5.2: Sample usage of EventEvaluators + + (logback-examples/src/main/java/chapter5/ExceptionEvaluatorExample.java) + +

+
package chapter5;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class ExceptionEvaluatorExample {
+
+  public static void main(String[] args) {
+    Logger logger = LoggerFactory.getLogger(ExceptionEvaluatorExample.class);
+    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+    try {
+      JoranConfigurator configurator = new JoranConfigurator();
+      configurator.setContext(lc);
+      configurator.doConfigure(args[0]);
+    } catch (JoranException je) {
+      StatusPrinter.print(lc);
+    }
+    for (int i = 0; i < 5; i++) {
+      if (i == 3) {
+        logger.debug("logging statement " + i, new TestException(
+            "do not display this"));
+      } else {
+        logger.debug("logging statement " + i, new Exception("display"));
+      }
+    }
+  }
+}
+ +

The following configuration will supress the stack trace of the + third logging request.

+ + Example 5.3: Sample usage of EventEvaluators + (logback-examples/src/main/java/chapter5/exceptionEvaluatorConfig.xml) + +
<configuration>
+
+  <evaluator name="DISPLAY_EX_EVAL">
+    <Expression>throwable != null &amp;&amp; throwable instanceof  \
+      chapter5.TestException</Expression>
+  </evaluator>
+	
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%-4relative [%thread] %-5level - %msg%n%ex{full, DISPLAY_EX_EVAL}
+      </Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

With this configuration, each time an instance of the + chapter5.TestException is included within a logging + request, the stack trace will be suppressed. +

+ +

Important: With the %ex conversion + specifier, the stack trace is displayed when the expression + evaluates to false.

+ + +

Creating a custom conversion + specifier

+ +

Up to this point we have presented the built-inconversion + specifiers of PatternLayout. But it is also possible + to use a conversion specifier of your own making.

+ +

Building a custom conversion specifier consists of two steps. +

+ +

First, you must extend the ClassicConverter + class. + ClassicConverter objects are responsible for + extracting information out of ILoggingEvent instances + and producing a String. For example, the + + LoggerConverter, the converter underlying the + %logger conversion word, extracts the name of the logger from + ILoggingEvent and returns it as a String. It might + abbreviate the logger name in the process.

+ +

Let us say that our customized ClassicConverter + colors the level of the logging event, according to ANSI terminal + conventions. Here is a possible implementation:

+ + Example 5.4: Sample Converter Example + +(src/main/java/chapter5/MySampleConverter.java) +
package chapter5;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.pattern.ClassicConverter;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+
+public class MySampleConverter extends ClassicConverter {
+
+  private static final String END_COLOR = "\u001b[m";
+
+  private static final String ERROR_COLOR = "\u001b[0;31m";
+  private static final String WARN_COLOR = "\u001b[0;33m";
+
+  @Override
+  public String convert(ILoggingEvent event) {
+    StringBuffer sbuf = new StringBuffer();
+    sbuf.append(getColor(event.getLevel()));
+    sbuf.append(event.getLevel());
+    sbuf.append(END_COLOR);
+    return sbuf.toString();
+  }
+
+  /**
+   * Returns the appropriate characters to change the color for the specified
+   * logging level.
+   */
+  private String getColor(Level level) {
+    switch (level.toInt()) {
+    case Level.ERROR_INT:
+      return ERROR_COLOR;
+    case Level.WARN_INT:
+      return WARN_COLOR;
+    default:
+      return "";
+    }
+  }
+}
+
+ +

This implementation is relatively straightforward. The + MySampleConverter class extends + ClassicConverter, and implements the + convert method where it returns a level string + decorated with ANSI coloring codes. +

+ +

In the second step, we must let logback know about the new + Converter. For this purpose, we need to declare the + new conversion word in the configuration file, as shown below:

+ + Example 5.4: Sample Converter Example (src/main/java/chapter5/mySampleConverterConfig.xml) +
<configuration>
+
+  <conversionRule conversionWord="sample" converterClass="chapter5.MySampleConverter" />
+	
+  <appender name="STDOUT"
+    class="ch.qos.logback.core.ConsoleAppender">
+    <layout class="ch.qos.logback.classic.PatternLayout">
+      <Pattern>%-4relative [%thread] %sample - %msg%n</Pattern>
+    </layout>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+ +

In this configuration file, once the new conversion word has + been declared, we can refert to it within a + PatternLayout pattern, as if the custom conversion + word had always been here.

+ +

Given that ANSI terminal codes do not work on Windows, you can + view the results on non-Windows platforms such as Linux or + Mac. The following command:

+ +
java chapter5.SampleLogging src/main/java/chapter5/mySampleConverterConfig.xml
+ +

should yield:

+ +

0 [main] DEBUG - Everything's going well +3 [main] ERROR - maybe not quite...

+ + +

Please note that the string "ERROR" is highlighted in red, + which was somewhat the point of the exercise.

+ +

The intersted reader might want to take a look at other + Converter implementations such as + + MDCConverter to learn about more complex + behaviours, such as option handling. +

+ + + +

+ HTMLLayout +

+ +

HTMLLayout + (as included in logback-classic) generates logs in HTML + format. HTMLLayout outputs logging events in an HTML + table where each row of the table corresponds to a logging + event.

+ +

Here is a sample output produced by HTMLLayout + using its default CSS stylesheet:

+ HTML Layout Sample Image + +

The content of table columns are specified with the help of a + conversion pattern. See PatternLayout for + documentation on conversion patterns. As such, you have full + control over the contents and format of the table. You can select + and display any combination of converters + PatternLayout knows about. +

+ +

One notable exception about the use of + PatternLayout with HTMLLayout is that + conversion specifiers should not be separated by space characters + or more generally by literal text. Each specifier found in the + pattern will result in a separate column. Likewise a separate + column will be generated for each block of literal text found in + the pattern potentially wasting valuable real estate on your + screen.

+ +

Here is simple but functional configuration file illustrating + the use of HTMLLayout. +

+ +
<configuration debug="true">
+  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+    <layout class="ch.qos.logback.classic.html.HTMLLayout">
+      <pattern>%relative%thread%mdc%level%logger%msg</pattern>
+    </layout>
+   <File>/test.html</File>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+
+ +

Launching the TrivialMain application listed below + will create the file test.html on your local drive.

+ +
import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TrivialMain {
+  public static void main(String[] args) throws InterruptedException {
+    Logger logger = LoggerFactory.getLogger(TrivialMain.class);
+    for(int i = 0; i < 6; i ++) {
+      if(i % 5 == 0) {
+        logger.info("an info message "+i);
+      } else {
+        logger.debug("hello world number" +i);
+      }
+    }
+    logger.error("Finish off with fireworks", new Exception("Just testing"));
+  }
+}
+ +

The contents of test.html should be similar to: +

+ HTML Layout Sample Image + +

Stack traces

+ +

If you use the %em conversion word to display stack + traces, a table column will be created to display stack traces. In + most cases the column will be empty, wasting screen + real-estate. Moreover, printing a stack trace on a separate column + does not yield very readable results. Fortunately, the + %ex conversion word is not the only way to display stack + traces. +

+ +

A better solution is available through implementations of + IThrowableRenderer interface. Such an implementation + can be assigned to HTMLLayout to manage the display + data related to exceptions. By default, a + + DefaultThrowableRenderer is assigned to each + HTMLLayout instance. It writes exceptions on a + new table row, along with its stack trace, in an easily + readable manner, as shown on the figure above. +

+ +

If for some reason, you still wish to use the %ex + pattern, then you can specify + NOPThrowableRenderer in the configuration file in + order to disable displaying a separate row for the stack trace. We + don't have the faintest idea why you would want to do that, but if + you wished, you could. +

+ +

CSS

+ +

The presentation of the HTML created by HTMLLayout + is controlled through a Cascading Style Sheet (CSS). In the + absence of specific instructions, HTMLLayout will + default to its internal CSS. However, your can instruct + HTMLLayout to use an external CSS file. For this + purpose a cssBuilder element can be nested within a + <layout> element, as shown below. +

+ +
<layout>
+  ...
+  <cssBuilder class="ch.qos.logback.core.html.UrlCssBuilder">
+    <url>path_to_StyleFile.css</url>
+  </cssBuilder>	
+  ...
+</layout>
+ + +

The HTMLLayout is often used in conjunction with + SMTPAppender, in order to send an email pleasantly + formatted in HTML. Here is a typical configuration: +

+ +
<configuration>
+  <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
+    <layout class="ch.qos.logback.classic.html.HTMLLayout">
+      <pattern>%relative%thread%mdc%level%class%msg</pattern>
+    </layout>
+    <From>sender.email@domain.net</From>
+    <SMTPHost>mail.domain.net</SMTPHost>
+    <Subject>LastEvent: %class - %msg </Subject>
+    <To>destination.email@domain.net</To> 
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="SMTP" />
+  </root>
+</configuration>
+ +

HTMLLayout can also be used with any + FileAppender, including a a rolling file appender, as + shown in the sample configuration below. +

+ +
<configuration>
+   <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+   <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+     <ActiveFileName>lastLogEntries.html</ActiveFileName>
+     <FileNamePattern>logEntries.%d{yyyy-MM-dd}.log</FileNamePattern>
+   </rollingPolicy>
+   
+   <layout class="ch.qos.logback.classic.html.HTMLLayout">
+      <cssBuilder class="ch.qos.logback.core.html.UrlCssBuilder">
+        <url>address_of_a_custom_stylesheet.css</url>
+      </cssBuilder>	
+      <Pattern>%relative%thread%mdc%level%logger%msg</Pattern>
+      <Title>Logging Events</Title>
+    </layout>
+ </appender> 
+
+ <root level="debug">
+   <appender-ref ref="FILE" />
+ </root>
+</configuration>
+ +

Log4j XMLLayout

+ + +

XMLLayout + (part of logback-classic) generates output in a log4j.dtd + compliant format. It can be used to inter-operate with tools such + as Chainsaw + and Vigilog capable + of processing files generated by log4j's + XMLLayout. +

+ + +

As the original XMLLayout in log4j version 1.2.15, XMLLayout in + logback-classic admits two boolean properties, LocationInfo and Properties. Setting LocationInfo to true enables the inclusion + of location info (caller data) in the each event. Setting Properties to true enables the inclusion of + MDC information. Both options are set to false by default. +

+ +

Here is a sample configuration

+ +
<configuration>
+  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+    <File>test.xml</File>
+    <layout class="ch.qos.logback.classic.log4j.XMLLayout">
+      <LocationInfo>true</LocationInfo>
+    </layout>
+  </appender> 
+
+  <root level="debug">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration> 
+ +

Logback access

+ +

Most logback-access layouts are mere adaptations of + logback-classic layouts. Logback-classic and logback-access + modules address different needs, but in general offer comparable + functionality.

+ +

Writing your own Layout

+

Writing a custom Layout for logback access is + nearly identical to its siblingLayout in + logback-classic.

+ + + + +

PatternLayout

+ +

+ PatternLayout in logback-access can be configured + much in the same way as its classic counterpart. However it + features additional conversion specifiers suited for logging + particular bits of information availalbe only in HTTP servlet + requests and HTTP servlet responses. +

+ +

Below is a list of conversion specifiers for + PatternLayout in logback-access.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Conversion WordEffect
a / remoteIP +

+ Remote IP address. +

+
A / localIP +

+ Local IP address. +

+
b / B / byteSent +

+ Response's content length. +

+
h / clientHost +

+ Remote host. +

+
H / protocol +

+ Request protocol. +

+
l +

+ Remote log name. In logback-access, this converter always + returns the value "-". +

+
reqParameter{paramName} +

+ Parameter of the response. +

+

This conversion word takes the first option in braces and looks + for the corresponding parameter in the request.

+

%reqParameter{input_data} + displays the corresponding parameter.

+
i{header} / header{header} +

+ Request header. +

+

This conversion word takes the first option in braces and looks + for the corresponding header in the request.

+

%header{Referer} displays the referer of the request.

+

+ If no option is specified, it displays every available header. +

+
m / requestMethod +

+ Request method. +

+
r / requestURL +

+ URL requested. +

+
s / statusCode +

+ Status code of the request. +

+
t / date +

Used to output the date of the logging event. The date + conversion specifier may be followed by a set of braces + containing a date and time pattern strings used by + java.text.SimpleDateFormat. ABSOLUTE, + DATE or ISO8601 are also valid values. +

+

For example, %d{HH:mm:ss,SSS}, + %d{dd MMM yyyy ;HH:mm:ss,SSS} or + %d{DATE}. If no date format specifier is given then + ISO8601 format is assumed. +

+
u / user +

+ Remote user. +

+
U / requestURI +

+ Requested URI. +

+
v / server +

Server name.

+
localPort +

Local port.

+
reqAttribute{attributeName} +

Attribute of the request.

+

This conversion word takes the first option in braces and looks + for the corresponding attribute in the request.

+

%reqAttribute{SOME_ATTRIBUTE} + displays the corresponding attribute.

+
reqCookie{cookie} +

Request cookie.

+

This conversion word takes the first option in braces and looks + for the corresponding cookie in the request.

+

%cookie{COOKIE_NAME} displays corresponding cookie.

+
responseHeader{header} +

+ Header of the response. +

+

This conversion word takes the first option in braces and looks + for the corresponding header in the response.

+

%header{Referer} displays the referer of the response.

+
requestContent +

This conversion word displays the content of the request, + that is the request's InputStream. It is used + in conjunction with a + TeeFilter, a + javax.servlet.Filter that replaces the original + HttpServletRequest by a + TeeHttpServletRequest. The latter object + allows access to the request's InputStream + multiple times without any loss of data. +

+
fullRequest +

This converter outputs the data associated with the + request, including all headers and request contents. +

+
responseContent +

This conversion word displays the content of the + response, that is the response's + InputStream. It is used in conjunction with a + + TeeFilter, a + javax.servlet.Filter that replaces the original + HttpServletResponse by a + TeeHttpServletResponse. The latter object + allows access to the requet's InputStream + multiple times without any loss of data. +

+
fullResponse +

This conversion word takes all the available data + associated with the response, inclusing all headers of the + response and response contents. +

+
+ +

Logback access' PatternLayout also recognize three keywords, which + act like shortcuts to a certain pattern.

+ + + + + + + + + + + + + + + +
keywordequivalent conversion pattern
common or CLF%h %l %u %t \"%r\" %s %b
combined%h %l %u %t \"%r\" %s %b \"%i{Referer}\" \"%i{User-Agent}\"
+ + +

The common keyword corresponds to the pattern %h %l %u %t \"%r\" %s %b + which displays client host, remote log name, user, date, requested URL, status code + and response's content length

+ +

The combined keyword is a shortcut for %h %l %u %t + \"%r\" %s %b \"%i{Referer}\" \"%i{User-Agent}\". This pattern + begins much like the common pattern but also displays two + request headers, namely referer, and user-agent.

+ + +

HTMLLayout

+ +

The HTMLLayout + class found in logback-access is similar to the HTMLLayout class from + logback-classic. +

+ +

By default, it will create a table containing the following data:

+ +
    +
  • Remote IP
  • +
  • Date
  • +
  • Request URL
  • +
  • Status code
  • +
  • Content Length
  • +
+ +

Here is a sample output produced by HTMLLayout in + logback-access:

+ Access HTML Layout Sample Image + +

What can be better than a real world example? Our own log4j + properties for logback translator makes use + of logback-access to demonstrate live ouput from + RollingFileAppender with HTMLLayout.

+ + +

On every new user request to our translator + web-application, a new entry will be added to the access logs, + which you can view by following + this link.

+ + + +
+ + diff --git a/logback-site/src/site/pages/manual/loggingSeparation.html b/logback-site/src/site/pages/manual/loggingSeparation.html index d2dd37113845af6e5d2cf457b2c949aa780fa8b7..43508413e295f59df7b48ddbf8ab458c5e3aed2d 100644 --- a/logback-site/src/site/pages/manual/loggingSeparation.html +++ b/logback-site/src/site/pages/manual/loggingSeparation.html @@ -1,298 +1,298 @@ - - - - - - Chapter 8: Context Selector - - - - - - - - - -
- - -
- -
- -

Chapter 9: Context Selectors

- -
-

It is not knowledge, but the act of learning, not - possession but the act of getting there, which grants the greatest - enjoyment. When I have clarified and exhausted a subject, then I - turn away from it, in order to go into darkness again; the - never-satisfied man is so strange if he has completed a structure, - then it is not in order to dwell in it peacefully, but in order to - begin another. I imagine the world conqueror must feel thus, who, - after one kingdom is scarcely conquered, stretches out his arms - for others.

- -

—KARL FRIEDRICH GAUSS, Letter to Bolyai, 1808.

- -

Style, like sheer silk, too often hides eczema.

- -

—ALBERT CAMUS, The Fall

- -
- - - - -

The problem: Logging Separation

- -

The chapter deals with a relatively difficult problem of - providing a separate logging environment for multiple applications - running on the same web or EJB container. In the remainder of this - chapter the term "application" will be used to refer either a - web-application or a J2EE application interchangeably. In a - separated logging environment, each application sees a distinct - logback environment, so that the logback configuration of one - application does not interfere with the settings of another. In - more technical terms, each web-application has a distinct copy of - LoggerContext reserved for its own use. Recall that - in logback, each logger object is manufactured by a - LoggerContext to which it remains attached for as - long as the logger object lives in memory. A variant of this - problem is the separation of application logging and the logging - of the container itself. -

- -

The simplest and easiest approach

- -

Assuming your container supports child first class loading, - separation of logging can be accomplished by embedding a copy of - slf4j and logback jar files in each of your applications. For - web-applications, placing slf4j and logback jar files under the - WEB-INF/lib directory of the web-application is - sufficient to endow each web-application with a separate logging - environment. A copy of the logback.xml configuration file - placed under WEB-INF/classes will be picked up when - logback is loaded into memory. -

- -

By virtue of class loader separation provided by the container, - each web-application will load its own copy of - LoggerContext which will pickup its own copy of - logback.xml.

- -

Easy as pie.

- -

Well, not exactly. First, although most do, not all containers - support child first class loading. Second, logging generated by - shared libraries will not be separated. The common idiom for - referencing a logger is via a static reference. For example, -

- -
public class Foo {
-  static Logger logger = LoggerFactory.getLogger(Foo.class);
-  ...
-}
- -

Static references are both memory and CPU efficient. Only one - logger reference is used for all instances of the class. Moreover, - the logger instance is retrieved only once, when the class is - loaded into memory. Static logger references are fine as long as - they are used in classes loaded by different class - loaders. However, when a class is loaded by a parent class loader - common to multiple applications, then the shared class in question - will be loaded once and for all applications. If the shared class - contains a static logger reference, than the logger will be - retrieved once, when the shared class is loaded into memory and - initialized. Moreover, for the shared class to successfully load - into memory, slf4j and logback classed must be resolvable by the - parent class loader. This implies that slf4j and logback jar - files must also be accessible to the parent class loader. Note - that for this scenario to occur a class must be shared - and use slf4j, which is somewhat uncommon. -

- -

However, if the container itself uses SLF4J and defaults to - parent-first class loading, then you need context selectors. Read - on. -

- -

Context Selectors

- - -

Logback provides a mechanism for a single instance of SLF4J and - logback classes loaded into memory to provide multiple logger - contexts. When you write: -

- -
Logger logger = LoggerFactory.getLogger("foo");
- -

the getLogger() method in - LoggerFactory class asks the SLF4J binding for a - ILoggerFactory. When SLF4J is bound to logback, the - task of returning an ILoggerFactory is delegated to - an instance of ContextSelector. Note - that ContextSelector implementations always return - instances of the LoggerContext class. This class - implements the ILoggerFactory interface. In other - words, a context selector has the option to returning any - LoggerContext instance it sees fit according to its - own criteria. Hence the name context selector. -

- -

By default, the logback binding uses DefaultContextSelector - which always returns the same LoggerContext, called - the default logger context.

- -

You can specify a different context selector by setting the - logback.ContextSelector system property. Suppose you - would like to specify that context selector to an instance of the - myPackage.myContextSelector class, you would add the - following system property:

- -

-Dlogback.ContextSelector=myPackage.myContextSelector

- -

The context selector needs to implement the - ContextSelector interface and have a constructor - method admitting a LoggerContext instance as its only - parameter. -

- - -

ContextJNDISelector

- -

Logback-classic ships with a selector called - ContextJNDISelector which selects the logger context - based on data available in JNDI. This leverages JNDI data - separation mandated by the J2EE specification. The same - environment variable can be set to carry a different value in each - application. -

- -

To enable ContextJNDISelector, the - logback.ContextSelector system property needs to be set - to "JNDI", as follows:

- -

-Dlogback.ContextSelector=JNDI

- -

Note that JNDI is a convenient shorthand for - "ch.qos.logback.classic.selector.ContextJNDISelector".

- -

Setting JNDI variables in applications

- -

In each of your applications, you need to name the logging - context for the application. For a web-application, JNDI - environment entries are specified within the web.xml - file. If "kenobi" was the name of your application, you would add - the following XML element to kenobi's web.xml file:

- -
<env-entry>
-  <env-entry-name>logback/context-name</env-entry-name>
-  <env-entry-type>java.lang.String</env-entry-type>
-  <env-entry-value>kenobi</env-entry-value>
-</env-entry>
- -

Assuming you have enabled ContextJNDISelector, - logging for Kenobi will be done using a logger context named - "kenobi". Moreover, the "kenobi" logger context will be - initialized by convention using the configuration file - called logback-kenobi.xml which should be packaged within - Kenobi web-application under the WEB-INF/classes folder. -

- -

Although not required, you may specify a different - configuration file other than the convention, by setting the - "logback/configuration-resource" JNDI variable. For example, if - you wish to specify my_config.xml instead of the - conventional logback-kenobi.xml, you would add the - following XML element to web.xml -

- - -
<env-entry>
-  <env-entry-name>logback/configuration-resource</env-entry-name>
-  <env-entry-type>java.lang.String</env-entry-type>
-  <env-entry-value>my_config.xml</env-entry-value>
-</env-entry>
- - -

Configuring Tomcat for ContextJNDISelector

- -

First, place the logback jars (that is - logback-classic-${project.version}.jar, - logback-core-${project.version}.jar and - slf4j-api-${slff4j.version}.jar) in Tomcat's global (shared) class - folder. In Tomcat 6.x, this directory is - $TOMCAT_HOME/lib/. -

- -

The logback.ContextSelector system property can be set - by adding the following line to the catalina.sh script, - catalina.bat in Windows, found under $TOMCAT_HOME/bin - folder.

- -

JAVA_OPTS="$JAVA_OPTS -Dlogback.ContextSelector=JNDI"

- - -

Hot deploying applications

- - -

When the web-application is recycled or shutdown, we strongly - recommend that the older LoggerContext be closed and - subsequently discarded. Logback ships with a - ServletContextListener called - ContextDetachingSCL, designed specifically for - detaching the ContextSelector instance associated - with the older web-application instance. In order to install it, - add the following lines to your web-applications web.xml - file.

- -
<listener>
-  <listener-class>ch.qos.logback.classic.selector.servlet.ContextDetachingSCL</listener-class>
-</listener>
- -

Better performance

- -

When ContextJNDISelector is active, each time a - logger is retrieved, a JNDI lookup must be performed. This can - negatively impact performance, especially if you are using - non-static (aka instance) logger references. Logback ships with a - servlet filter named LoggerContextFilter, - specifically designed to circumvent the JNDI lookup cost. It can - be installed by adding the following lines to your applications - web.xml file.

- -
<filter>
-  <filter-name>LoggerContextFilter</filter-name>
-  <filter-class>ch.qos.logback.classic.selector.servlet.LoggerContextFilter</filter-class>
-</filter>
-<filter-mapping>
-  <filter-name>LoggerContextFilter</filter-name>
-  <url-pattern>/*</url-pattern>
-</filter-mapping>
- -

At the beginning of each http-request, - LoggerContextFilter will obtain the logger context - associated with the application and then place it in a - ThreadLocal variable. ContextJNDISelector - will first check if the said ThreadLocal variable is - set. If it is set, then JNDI lookup will skipped. Note that at the - end of the http request, the ThreadLocal variable will - be nulled. Installing LoggerContextFilter improves - logger retrieval performance by a wide margin. -

- -

Nulling the ThreadLocal variable allows garbage - collection of the web-application when it is stopped or - recycled.

- - -
- - + + + + + + Chapter 8: Context Selector + + + + + + + + + +
+ + +
+ +
+ +

Chapter 9: Context Selectors

+ +
+

It is not knowledge, but the act of learning, not + possession but the act of getting there, which grants the greatest + enjoyment. When I have clarified and exhausted a subject, then I + turn away from it, in order to go into darkness again; the + never-satisfied man is so strange if he has completed a structure, + then it is not in order to dwell in it peacefully, but in order to + begin another. I imagine the world conqueror must feel thus, who, + after one kingdom is scarcely conquered, stretches out his arms + for others.

+ +

—KARL FRIEDRICH GAUSS, Letter to Bolyai, 1808.

+ +

Style, like sheer silk, too often hides eczema.

+ +

—ALBERT CAMUS, The Fall

+ +
+ + + + +

The problem: Logging Separation

+ +

The chapter deals with a relatively difficult problem of + providing a separate logging environment for multiple applications + running on the same web or EJB container. In the remainder of this + chapter the term "application" will be used to refer either a + web-application or a J2EE application interchangeably. In a + separated logging environment, each application sees a distinct + logback environment, so that the logback configuration of one + application does not interfere with the settings of another. In + more technical terms, each web-application has a distinct copy of + LoggerContext reserved for its own use. Recall that + in logback, each logger object is manufactured by a + LoggerContext to which it remains attached for as + long as the logger object lives in memory. A variant of this + problem is the separation of application logging and the logging + of the container itself. +

+ +

The simplest and easiest approach

+ +

Assuming your container supports child first class loading, + separation of logging can be accomplished by embedding a copy of + slf4j and logback jar files in each of your applications. For + web-applications, placing slf4j and logback jar files under the + WEB-INF/lib directory of the web-application is + sufficient to endow each web-application with a separate logging + environment. A copy of the logback.xml configuration file + placed under WEB-INF/classes will be picked up when + logback is loaded into memory. +

+ +

By virtue of class loader separation provided by the container, + each web-application will load its own copy of + LoggerContext which will pickup its own copy of + logback.xml.

+ +

Easy as pie.

+ +

Well, not exactly. First, although most do, not all containers + support child first class loading. Second, logging generated by + shared libraries will not be separated. The common idiom for + referencing a logger is via a static reference. For example, +

+ +
public class Foo {
+  static Logger logger = LoggerFactory.getLogger(Foo.class);
+  ...
+}
+ +

Static references are both memory and CPU efficient. Only one + logger reference is used for all instances of the class. Moreover, + the logger instance is retrieved only once, when the class is + loaded into memory. Static logger references are fine as long as + they are used in classes loaded by different class + loaders. However, when a class is loaded by a parent class loader + common to multiple applications, then the shared class in question + will be loaded once and for all applications. If the shared class + contains a static logger reference, than the logger will be + retrieved once, when the shared class is loaded into memory and + initialized. Moreover, for the shared class to successfully load + into memory, slf4j and logback classed must be resolvable by the + parent class loader. This implies that slf4j and logback jar + files must also be accessible to the parent class loader. Note + that for this scenario to occur a class must be shared + and use slf4j, which is somewhat uncommon. +

+ +

However, if the container itself uses SLF4J and defaults to + parent-first class loading, then you need context selectors. Read + on. +

+ +

Context Selectors

+ + +

Logback provides a mechanism for a single instance of SLF4J and + logback classes loaded into memory to provide multiple logger + contexts. When you write: +

+ +
Logger logger = LoggerFactory.getLogger("foo");
+ +

the getLogger() method in + LoggerFactory class asks the SLF4J binding for a + ILoggerFactory. When SLF4J is bound to logback, the + task of returning an ILoggerFactory is delegated to + an instance of ContextSelector. Note + that ContextSelector implementations always return + instances of the LoggerContext class. This class + implements the ILoggerFactory interface. In other + words, a context selector has the option to returning any + LoggerContext instance it sees fit according to its + own criteria. Hence the name context selector. +

+ +

By default, the logback binding uses DefaultContextSelector + which always returns the same LoggerContext, called + the default logger context.

+ +

You can specify a different context selector by setting the + logback.ContextSelector system property. Suppose you + would like to specify that context selector to an instance of the + myPackage.myContextSelector class, you would add the + following system property:

+ +

-Dlogback.ContextSelector=myPackage.myContextSelector

+ +

The context selector needs to implement the + ContextSelector interface and have a constructor + method admitting a LoggerContext instance as its only + parameter. +

+ + +

ContextJNDISelector

+ +

Logback-classic ships with a selector called + ContextJNDISelector which selects the logger context + based on data available in JNDI. This leverages JNDI data + separation mandated by the J2EE specification. The same + environment variable can be set to carry a different value in each + application. +

+ +

To enable ContextJNDISelector, the + logback.ContextSelector system property needs to be set + to "JNDI", as follows:

+ +

-Dlogback.ContextSelector=JNDI

+ +

Note that JNDI is a convenient shorthand for + "ch.qos.logback.classic.selector.ContextJNDISelector".

+ +

Setting JNDI variables in applications

+ +

In each of your applications, you need to name the logging + context for the application. For a web-application, JNDI + environment entries are specified within the web.xml + file. If "kenobi" was the name of your application, you would add + the following XML element to kenobi's web.xml file:

+ +
<env-entry>
+  <env-entry-name>logback/context-name</env-entry-name>
+  <env-entry-type>java.lang.String</env-entry-type>
+  <env-entry-value>kenobi</env-entry-value>
+</env-entry>
+ +

Assuming you have enabled ContextJNDISelector, + logging for Kenobi will be done using a logger context named + "kenobi". Moreover, the "kenobi" logger context will be + initialized by convention using the configuration file + called logback-kenobi.xml which should be packaged within + Kenobi web-application under the WEB-INF/classes folder. +

+ +

Although not required, you may specify a different + configuration file other than the convention, by setting the + "logback/configuration-resource" JNDI variable. For example, if + you wish to specify my_config.xml instead of the + conventional logback-kenobi.xml, you would add the + following XML element to web.xml +

+ + +
<env-entry>
+  <env-entry-name>logback/configuration-resource</env-entry-name>
+  <env-entry-type>java.lang.String</env-entry-type>
+  <env-entry-value>my_config.xml</env-entry-value>
+</env-entry>
+ + +

Configuring Tomcat for ContextJNDISelector

+ +

First, place the logback jars (that is + logback-classic-${project.version}.jar, + logback-core-${project.version}.jar and + slf4j-api-${slff4j.version}.jar) in Tomcat's global (shared) class + folder. In Tomcat 6.x, this directory is + $TOMCAT_HOME/lib/. +

+ +

The logback.ContextSelector system property can be set + by adding the following line to the catalina.sh script, + catalina.bat in Windows, found under $TOMCAT_HOME/bin + folder.

+ +

JAVA_OPTS="$JAVA_OPTS -Dlogback.ContextSelector=JNDI"

+ + +

Hot deploying applications

+ + +

When the web-application is recycled or shutdown, we strongly + recommend that the older LoggerContext be closed and + subsequently discarded. Logback ships with a + ServletContextListener called + ContextDetachingSCL, designed specifically for + detaching the ContextSelector instance associated + with the older web-application instance. In order to install it, + add the following lines to your web-applications web.xml + file.

+ +
<listener>
+  <listener-class>ch.qos.logback.classic.selector.servlet.ContextDetachingSCL</listener-class>
+</listener>
+ +

Better performance

+ +

When ContextJNDISelector is active, each time a + logger is retrieved, a JNDI lookup must be performed. This can + negatively impact performance, especially if you are using + non-static (aka instance) logger references. Logback ships with a + servlet filter named LoggerContextFilter, + specifically designed to circumvent the JNDI lookup cost. It can + be installed by adding the following lines to your applications + web.xml file.

+ +
<filter>
+  <filter-name>LoggerContextFilter</filter-name>
+  <filter-class>ch.qos.logback.classic.selector.servlet.LoggerContextFilter</filter-class>
+</filter>
+<filter-mapping>
+  <filter-name>LoggerContextFilter</filter-name>
+  <url-pattern>/*</url-pattern>
+</filter-mapping>
+ +

At the beginning of each http-request, + LoggerContextFilter will obtain the logger context + associated with the application and then place it in a + ThreadLocal variable. ContextJNDISelector + will first check if the said ThreadLocal variable is + set. If it is set, then JNDI lookup will skipped. Note that at the + end of the http request, the ThreadLocal variable will + be nulled. Installing LoggerContextFilter improves + logger retrieval performance by a wide margin. +

+ +

Nulling the ThreadLocal variable allows garbage + collection of the web-application when it is stopped or + recycled.

+ + +
+ + diff --git a/logback-site/src/site/pages/manual/mdc.html b/logback-site/src/site/pages/manual/mdc.html index f9c7437be2a492dc023c45e9189b24d6811d6754..a31ebfd8ffedf96f170d3fa7f8c6dea5604cfba3 100644 --- a/logback-site/src/site/pages/manual/mdc.html +++ b/logback-site/src/site/pages/manual/mdc.html @@ -1,641 +1,641 @@ - - - - - - Chapter 7: Diagnostic Context - - - - - - - - - -
- - -
- -
- -

Chapter 7: Mapped Diagnostic Context

- -
-

Lock the doors.

-

—LEROY CAIN, Flight Director, Columbia Mission Control

-
- - - -

One of the design goals of logback is to audit and debug - complex distributed applications. Most real-world distributed - systems need to deal with multiple clients simultaneously. In a - typical multithreaded implementation of such a system, different - threads will handle different clients. A possible but discouraged - approach to differentiate the logging output of one client from - another consists of instantiating a new and separate logger for - each client. This technique promotes the proliferation of loggers - and considerably increases their management overhead. -

- - - - -

A lighter technique consists of uniquely stamping each log - request servicing a given client. Neil Harrison described this - method in the book Patterns for Logging Diagnostic - Messages in Pattern Languages of Program Design 3, edited by - R. Martin, D. Riehle, and F. Buschmann (Addison-Wesley, - 1997). Logback leverages a variant of this technique included in - the SLF4J API: Mapped Diagnostic Contexts (MDC). -

- -

To uniquely stamp each request, the user puts contextual - information into the MDC, the abbreviation of Mapped - Diagnostic Context. The salient parts of the MDC class are shown - below. Please refer to the MDC - javadocs for a complete list of methods. -

- -
package org.slf4j;
-
-public class MDC {
-  //Put a context value as identified by key
-  //into the current thread's context map.
-  public static void put(String key, String val);
-
-  //Get the context identified by the key parameter.
-  public static String get(String key);
-
-  //Remove the the context identified by the key parameter.
-  public static void remove(String key);
-
-  //Clear all entries in the MDC.
-  public static void clear();
-}
- -

The MDC class contains only static methods. It - lets the developer place information in a diagnostic - context that can be subsequently retrieved by certain logback - components. The MDC manages contextual information on - a per thread basis. A child thread automatically - inherits a copy of the mapped diagnostic context of its - parent. Typically, while starting to service a new client request, - the developer will insert pertinent contextual information, such - as the client id, client's IP address, request parameters - etc. into the MDC. Logback components, if - appropriately configured, will automatically include this - information in each log entry. -

- -

- The next application named - SimpleMDC - demonstrates this basic principle. -

-Example 7.1: Basic MDC usage ( -logback-examples/src/main/java/chapter7/SimpleMDC.java) -
package chapter7;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.slf4j.MDC;
-
-import ch.qos.logback.classic.PatternLayout;
-import ch.qos.logback.core.ConsoleAppender;
-
-public class SimpleMDC {
-  static public void main(String[] args) throws Exception {
-
-   // You can put values in the MDC at any time. Before anything else 
-    // we put the first name
-    MDC.put("first", "Dorothy");
-
-    [ SNIP ]
-    
-    Logger logger = LoggerFactory.getLogger(SimpleMDC.class);
-    // We now put the last name
-    MDC.put("last", "Parker");
-
-    // The most beautiful two words in the English language according
-    // to Dorothy Parker:
-    logger.info("Check enclosed.");
-    logger.debug("The most beautiful two words in English.");
-
-    MDC.put("first", "Richard");
-    MDC.put("last", "Nixon");
-    logger.info("I am not a crook.");
-    logger.info("Attributed to the former US president. 17 Nov 1973.");
-  }
-
-  [ SNIP ]
-
-}
- -

The main method starts by associating the value - Dorothy with the key first in the - MDC. You can place as many value/key associations in - the MDC as you wish. Multiple insertions with the - same key will overwrite older values. The code then proceeds to - configure logback.

- -

For the sake of conciseness, we have the omitted the code that - configures logback with the configuration file simpleMDC.xml. Here is the - relevant section from that file. -

- -
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> 
-  <layout>
-    <Pattern>%X{first} %X{last} - %m%n</Pattern>
-  </layout> 
-</appender>
- - - -

Note the usage of the %X specifier within the - PatternLayout conversion pattern. The %X - conversion specifier is employed twice, once for the key named - first and once for the key named last. After - obtaining a logger corresponding to SimpleMDC.class, - the code associates the value Parker with the key named - last. It then invokes the logger twice with different - messages. The code finishes by setting the MDC to - different values and issuing several logging requests. Running - SimpleMDC yields: -

- -
Dorothy Parker - Check enclosed.
-Dorothy Parker - The most beautiful two words in English.
-Richard Nixon - I am not a crook.
-Richard Nixon - Attributed to the former US president. 17 Nov 1973.
- - -

The SimpleMDC application illustrates how logback - layouts, if configured appropriately, can automatically output - MDC information. Moreover, the information placed - into the MDC can be used by multiple logger - invocations. -

- -

Advanced Use

- -

Mapped Diagnostic Contexts shine brightest within client server - architectures. Typically, multiple clients will be served by - multiple threads on the server. Although the methods in the - MDC class are static, the diagnostic context is - managed on a per thread basis, allowing each server thread to bear - a distinct MDC stamp. MDC operations - such as put() and get() affect only the - MDC of the current thread, and the children - of the current thread. The MDC in other threads - remain unaffected. Given that MDC information is - managed on a per thread basis, each thread will have its own copy - of the MDC. Thus, there is no need for the developer - to worry about thread-safety or synchronization when programming - with the MDC because it handles these issues safely - and transparently. -

- -

The next example is somewhat more advanced. It shows how the - MDC can be used in a client-server setting. The - server-side implements the NumberCruncher interface - shown in Example 7.2 below. The NumberCruncher - interface contains a single method named - factor(). Using RMI technology, the client invokes - the factor() method of the server application to - retrieve the distinct factors of an integer. -

- -Example 7.2: The service interface ( -logback-examples/src/main/java/chapter7/NumberCruncher.java) -
package chapter7;
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-/**
- * NumberCruncher factors positive integers.
- */
-public interface NumberCruncher extends Remote {
-  /**
-   * Factor a positive integer number and return its
-   * distinct factor's as an integer array.
-   * */
-  int[] factor(int number) throws RemoteException;
-}
- -

- The NumberCruncherServer application, listed in Example 7.3 below, - implements the NumberCruncher interface. Its main method exports - an RMI Registry on the local host that accepts requests on a well-known port. -

- -Example 7.3: The server side ( -logback-examples/src/main/java/chapter7/NumberCruncherServer.java) -
package chapter7;
-
-import java.rmi.RemoteException;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.registry.Registry;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.Vector;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.slf4j.MDC;
-
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.joran.JoranConfigurator;
-import ch.qos.logback.core.joran.spi.JoranException;
-
-
-/**
- * A simple NumberCruncher implementation that logs its progress when
- * factoring numbers. The purpose of the whole exercise is to show the
- * use of mapped diagnostic contexts in order to distinguish the log
- * output from different client requests.
- * */
-public class NumberCruncherServer extends UnicastRemoteObject
-  implements NumberCruncher {
-
-  private static final long serialVersionUID = 1L;
-
-  static Logger logger = LoggerFactory.getLogger(NumberCruncherServer.class);
-
-  public NumberCruncherServer() throws RemoteException {
-  }
-
-  public int[] factor(int number) throws RemoteException {
-    // The client's host is an important source of information.
-    try {
-      MDC.put("client", NumberCruncherServer.getClientHost());
-    } catch (java.rmi.server.ServerNotActiveException e) {
-      logger.warn("Caught unexpected ServerNotActiveException.", e);
-    }
-
-    // The information contained within the request is another source
-    // of distinctive information. It might reveal the users name,
-    // date of request, request ID etc. In servlet type environments,
-    // useful information is contained in the HttpRequest or in the  
-    // HttpSession.
-    MDC.put("number", String.valueOf(number));
-
-    logger.info("Beginning to factor.");
-
-    if (number <= 0) {
-      throw new IllegalArgumentException(number +
-        " is not a positive integer.");
-    } else if (number == 1) {
-      return new int[] { 1 };
-    }
-
-    Vector<Integer> factors = new Vector<Integer>();
-    int n = number;
-
-    for (int i = 2; (i <= n) && ((i * i) <= number); i++) {
-      // It is bad practice to place log requests within tight loops.
-      // It is done here to show interleaved log output from
-      // different requests. 
-      logger.debug("Trying " + i + " as a factor.");
-
-      if ((n % i) == 0) {
-        logger.info("Found factor " + i);
-        factors.addElement(new Integer(i));
-
-        do {
-          n /= i;
-        } while ((n % i) == 0);
-      }
-
-      // Placing artificial delays in tight loops will also lead to
-      // sub-optimal resuts. :-)
-      delay(100);
-    }
-
-    if (n != 1) {
-      logger.info("Found factor " + n);
-      factors.addElement(new Integer(n));
-    }
-
-    int len = factors.size();
-
-    int[] result = new int[len];
-
-    for (int i = 0; i < len; i++) {
-      result[i] = ((Integer) factors.elementAt(i)).intValue();
-    }
-
-    // clean up
-    MDC.remove("client");
-    MDC.remove("number");
-
-    return result;
-  }
-
-  static void usage(String msg) {
-    System.err.println(msg);
-    System.err.println("Usage: java chapter7.NumberCruncherServer configFile\n" +
-      "   where configFile is a logback configuration file.");
-    System.exit(1);
-  }
-
-  public static void delay(int millis) {
-    try {
-      Thread.sleep(millis);
-    } catch (InterruptedException e) {
-    }
-  }
-
-  public static void main(String[] args) {
-    if (args.length != 1) {
-      usage("Wrong number of arguments.");
-    }
-
-    String configFile = args[0];
-
-    if (configFile.endsWith(".xml")) {
-      try {
-        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-        JoranConfigurator configurator = new JoranConfigurator();
-        configurator.setContext(lc);
-        lc.reset();
-        configurator.doConfigure(args[0]);
-      } catch (JoranException je) {
-        je.printStackTrace();
-      }
-    }
-
-    NumberCruncherServer ncs;
-
-    try {
-      ncs = new NumberCruncherServer();
-      logger.info("Creating registry.");
-
-      Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
-      registry.rebind("Factor", ncs);
-      logger.info("NumberCruncherServer bound and ready.");
-    } catch (Exception e) {
-      logger.error("Could not bind NumberCruncherServer.", e);
-
-      return;
-    }
-  }
-}
- -

The implementation of the factor(int number) - method is of particular relevance. It starts by putting the - client's hostname into the MDC under the key - client. The number to factor, as requested by the client, - is put into the MDC under the key - number. After computing the distinct factors of the - integer parameter, the result is returned to the client. Before - returning the result however, the values for the client - and number are cleared by calling the - MDC.remove() method. Normally, a put() - operation should be balanced by the corresponding - remove() operation. Otherwise, the MDC - will contain stale values for certain keys. We would recommend - that whenever possible, remove() operations be - performed within finally blocks, ensuring their invocation - regardless of the execution path of the code. -

- -

- After these theoretical explanations, we are ready to run the number - cruncher example. Start the server with the following command: -

- -
java chapter7.NumberCruncherServer src/main/java/chapter7/mdc1.xml
- -

- The mdc1.xml configuration file is listed below: -

-Example 7.4: Configuration file (logback-examples/src/main/java/chapter7/mdc1.xml) -
<configuration>
-  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
-    <layout>
-      <Pattern>%-4r [%thread] %-5level C:%X{client} N:%X{number} - %msg%n</Pattern>
-    </layout>	    
-  </appender>
-  
-  <root level="debug">
-    <appender-ref ref="CONSOLE"/>
-  </root>  
-</configuration>
- -

- Note the use of the %X conversion specifier within the - Pattern option. -

- -

- The following command starts an instance of NumberCruncherClient - application: -

- -
java chapter7.NumberCruncherClient hostname
- -

- where hostname is the host where the - NumberCruncherServer is running -

- -

- Executing multiple instances of the client and requesting the server to factor - the numbers 129 from the first client and shortly thereafter - the number 71 from the second client, the server outputs the following: -

- -
-70984 [RMI TCP Connection(4)-192.168.1.6] INFO  C:orion N:129 - Beginning to factor.
-70984 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 2 as a factor.
-71093 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 3 as a factor.
-71093 [RMI TCP Connection(4)-192.168.1.6] INFO  C:orion N:129 - Found factor 3
-71187 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 4 as a factor.
-71297 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 5 as a factor.
-71390 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 6 as a factor.
-71453 [RMI TCP Connection(5)-192.168.1.6] INFO  C:orion N:71 - Beginning to factor.
-71453 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 2 as a factor.
-71484 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 7 as a factor.
-71547 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 3 as a factor.
-71593 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 8 as a factor.
-71656 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 4 as a factor.
-71687 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 9 as a factor.
-71750 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 5 as a factor.
-71797 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 10 as a factor.
-71859 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 6 as a factor.
-71890 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 11 as a factor.
-71953 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 7 as a factor.
-72000 [RMI TCP Connection(4)-192.168.1.6] INFO  C:orion N:129 - Found factor 43
-72062 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 8 as a factor.
-72156 [RMI TCP Connection(5)-192.168.1.6] INFO  C:orion N:71 - Found factor 71
- -

- The clients were run from a machine called orion as can be seen in - the above output. Even if the server processes the requests of clients - near-simultaneously in separate threads, the logging output pertaining - to each client request can be distinguished by studying the output of the - MDC. Note for example the stamp associated with number, - i.e. the number to factor. -

- -

- The attentive reader might have observed that the thread name could - also have been used to distinguish each request. The thread name can cause - confusion if the server side technology recycles threads. In that case, - it may be hard to determine the boundaries of each request, that is, - when a given thread finishes servicing a request and when it begins servicing the next. - Because the MDC is under the control of the application developer, - MDC stamps do not suffer from this problem. -

- - - -

Automating access to the MDC

- -

As we've seen, the MDC is very useful when dealing - with multiple clients. In the case of a web application that - manages user authentication, one simple solution could be to set - the user's name in the MDC and remove it once the - user logs out. Unfortunately, it is not always possible to - achieve reliable results using this technique. Since - MDC manages data on a per thread basis, a - server that recycles threads might lead to false information - contained in the MDC. -

- -

To allow the information contained in the MDC to - be correct at all times when a request is processed, a possible - approach would be to store the username at the beginning of the - process, and remove it at the end of said process. A servlet - Filter comes in handy in this case. -

- -

Within the servlet filter's doFilter method, we - can retrieve the relevant user data through the request (or a - cookie therein), store it the MDC. Subsequent - processing by other filters and servlets will automatically - benefit from the MDC data that was stored previously. Finally, - when our servlet filter regains control, we have an opportunity to - clean MDC data. -

- -

Here is an implementation of such a filter:

- -Example 7.5: User servlet filter ( -logback-examples/src/main/java/chapter7/UserServletFilter.java) -
package chapter7;
-
-import java.io.IOException;
-import java.security.Principal;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-
-import org.slf4j.MDC;
-
-public class UserServletFilter implements Filter {
-
-  boolean userRegistered = false;
-  
-  private final String userKey = "username";
-  
-  public void destroy() {
-  }
-
-  public void doFilter(ServletRequest request, ServletResponse response,
-    FilterChain chain) throws IOException, ServletException {
-
-    HttpServletRequest req = (HttpServletRequest) request;
-    
-    Principal principal = req.getUserPrincipal();
-    // Please note that we could have also used a cookie to 
-    // retrieve the user name
-
-    if (principal != null) {
-      String username = principal.getName();
-      registerUsername(username);
-    } else {
-      HttpSession session = req.getSession();
-      String username = (String)session.getAttribute(userKey);
-      registerUsername(username);
-    }
-    
-    try {
-      chain.doFilter(request, response);
-    } finally {
-      if (userRegistered) {
-        MDC.remove(userKey);
-      }
-    }
-  }
-
-  public void init(FilterConfig arg0) throws ServletException {
-  }
-  
-  private void registerUsername(String username) {
-    if (username != null && username.trim().length() > 0) {
-      MDC.put(userKey, username);
-      userRegistered = true;
-    }
-  }
-}
- -

When the filter's doFilter() method is called, it - first looks for a java.security.Principal object in the - request. This object contains the name of the currently - authenticated user. In case the user principal is not set, the - filter looks for a session attribute matching a given key (here - username). If a user information is found, it is - registered in the MDC. -

- -

Once the filter chain has completed, the filter removes the user - information from the MDC. -

- -

The approach we just outlined sets MDC data only for the duration - of the request and only for the thread processing it. Other threads - are unaffected. Furthermore, any given thread will contain correct - MDC data at any point in time.

- - - -

MDC And Managed Threads

- -

A copy of the mapped diagnostic context can not always be - inherited by worker threads from the initiating thread. This is the - case when java.util.concurrent.Executors is used for - thread management. For instance, newCachedThreadPool - method creates a ThreadPoolExecutor and like other - thread pooling code, it has intricate thread creation logic. -

- -

In such cases, it is recommended that - MDC.getCopyOfContextMap() is invoked on the original - (master) thread before submitting a task to the executor. When the - task runs, as its first action, it should invoke - MDC.setContextMapValues() to associate the stored copy - of the original MDC values with the new Executor - managed thread. -

- - - -
- - + + + + + + Chapter 7: Diagnostic Context + + + + + + + + + +
+ + +
+ +
+ +

Chapter 7: Mapped Diagnostic Context

+ +
+

Lock the doors.

+

—LEROY CAIN, Flight Director, Columbia Mission Control

+
+ + + +

One of the design goals of logback is to audit and debug + complex distributed applications. Most real-world distributed + systems need to deal with multiple clients simultaneously. In a + typical multithreaded implementation of such a system, different + threads will handle different clients. A possible but discouraged + approach to differentiate the logging output of one client from + another consists of instantiating a new and separate logger for + each client. This technique promotes the proliferation of loggers + and considerably increases their management overhead. +

+ + + + +

A lighter technique consists of uniquely stamping each log + request servicing a given client. Neil Harrison described this + method in the book Patterns for Logging Diagnostic + Messages in Pattern Languages of Program Design 3, edited by + R. Martin, D. Riehle, and F. Buschmann (Addison-Wesley, + 1997). Logback leverages a variant of this technique included in + the SLF4J API: Mapped Diagnostic Contexts (MDC). +

+ +

To uniquely stamp each request, the user puts contextual + information into the MDC, the abbreviation of Mapped + Diagnostic Context. The salient parts of the MDC class are shown + below. Please refer to the MDC + javadocs for a complete list of methods. +

+ +
package org.slf4j;
+
+public class MDC {
+  //Put a context value as identified by key
+  //into the current thread's context map.
+  public static void put(String key, String val);
+
+  //Get the context identified by the key parameter.
+  public static String get(String key);
+
+  //Remove the the context identified by the key parameter.
+  public static void remove(String key);
+
+  //Clear all entries in the MDC.
+  public static void clear();
+}
+ +

The MDC class contains only static methods. It + lets the developer place information in a diagnostic + context that can be subsequently retrieved by certain logback + components. The MDC manages contextual information on + a per thread basis. A child thread automatically + inherits a copy of the mapped diagnostic context of its + parent. Typically, while starting to service a new client request, + the developer will insert pertinent contextual information, such + as the client id, client's IP address, request parameters + etc. into the MDC. Logback components, if + appropriately configured, will automatically include this + information in each log entry. +

+ +

+ The next application named + SimpleMDC + demonstrates this basic principle. +

+Example 7.1: Basic MDC usage ( +logback-examples/src/main/java/chapter7/SimpleMDC.java) +
package chapter7;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+import ch.qos.logback.classic.PatternLayout;
+import ch.qos.logback.core.ConsoleAppender;
+
+public class SimpleMDC {
+  static public void main(String[] args) throws Exception {
+
+   // You can put values in the MDC at any time. Before anything else 
+    // we put the first name
+    MDC.put("first", "Dorothy");
+
+    [ SNIP ]
+    
+    Logger logger = LoggerFactory.getLogger(SimpleMDC.class);
+    // We now put the last name
+    MDC.put("last", "Parker");
+
+    // The most beautiful two words in the English language according
+    // to Dorothy Parker:
+    logger.info("Check enclosed.");
+    logger.debug("The most beautiful two words in English.");
+
+    MDC.put("first", "Richard");
+    MDC.put("last", "Nixon");
+    logger.info("I am not a crook.");
+    logger.info("Attributed to the former US president. 17 Nov 1973.");
+  }
+
+  [ SNIP ]
+
+}
+ +

The main method starts by associating the value + Dorothy with the key first in the + MDC. You can place as many value/key associations in + the MDC as you wish. Multiple insertions with the + same key will overwrite older values. The code then proceeds to + configure logback.

+ +

For the sake of conciseness, we have the omitted the code that + configures logback with the configuration file simpleMDC.xml. Here is the + relevant section from that file. +

+ +
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> 
+  <layout>
+    <Pattern>%X{first} %X{last} - %m%n</Pattern>
+  </layout> 
+</appender>
+ + + +

Note the usage of the %X specifier within the + PatternLayout conversion pattern. The %X + conversion specifier is employed twice, once for the key named + first and once for the key named last. After + obtaining a logger corresponding to SimpleMDC.class, + the code associates the value Parker with the key named + last. It then invokes the logger twice with different + messages. The code finishes by setting the MDC to + different values and issuing several logging requests. Running + SimpleMDC yields: +

+ +
Dorothy Parker - Check enclosed.
+Dorothy Parker - The most beautiful two words in English.
+Richard Nixon - I am not a crook.
+Richard Nixon - Attributed to the former US president. 17 Nov 1973.
+ + +

The SimpleMDC application illustrates how logback + layouts, if configured appropriately, can automatically output + MDC information. Moreover, the information placed + into the MDC can be used by multiple logger + invocations. +

+ +

Advanced Use

+ +

Mapped Diagnostic Contexts shine brightest within client server + architectures. Typically, multiple clients will be served by + multiple threads on the server. Although the methods in the + MDC class are static, the diagnostic context is + managed on a per thread basis, allowing each server thread to bear + a distinct MDC stamp. MDC operations + such as put() and get() affect only the + MDC of the current thread, and the children + of the current thread. The MDC in other threads + remain unaffected. Given that MDC information is + managed on a per thread basis, each thread will have its own copy + of the MDC. Thus, there is no need for the developer + to worry about thread-safety or synchronization when programming + with the MDC because it handles these issues safely + and transparently. +

+ +

The next example is somewhat more advanced. It shows how the + MDC can be used in a client-server setting. The + server-side implements the NumberCruncher interface + shown in Example 7.2 below. The NumberCruncher + interface contains a single method named + factor(). Using RMI technology, the client invokes + the factor() method of the server application to + retrieve the distinct factors of an integer. +

+ +Example 7.2: The service interface ( +logback-examples/src/main/java/chapter7/NumberCruncher.java) +
package chapter7;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * NumberCruncher factors positive integers.
+ */
+public interface NumberCruncher extends Remote {
+  /**
+   * Factor a positive integer number and return its
+   * distinct factor's as an integer array.
+   * */
+  int[] factor(int number) throws RemoteException;
+}
+ +

+ The NumberCruncherServer application, listed in Example 7.3 below, + implements the NumberCruncher interface. Its main method exports + an RMI Registry on the local host that accepts requests on a well-known port. +

+ +Example 7.3: The server side ( +logback-examples/src/main/java/chapter7/NumberCruncherServer.java) +
package chapter7;
+
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Vector;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+
+
+/**
+ * A simple NumberCruncher implementation that logs its progress when
+ * factoring numbers. The purpose of the whole exercise is to show the
+ * use of mapped diagnostic contexts in order to distinguish the log
+ * output from different client requests.
+ * */
+public class NumberCruncherServer extends UnicastRemoteObject
+  implements NumberCruncher {
+
+  private static final long serialVersionUID = 1L;
+
+  static Logger logger = LoggerFactory.getLogger(NumberCruncherServer.class);
+
+  public NumberCruncherServer() throws RemoteException {
+  }
+
+  public int[] factor(int number) throws RemoteException {
+    // The client's host is an important source of information.
+    try {
+      MDC.put("client", NumberCruncherServer.getClientHost());
+    } catch (java.rmi.server.ServerNotActiveException e) {
+      logger.warn("Caught unexpected ServerNotActiveException.", e);
+    }
+
+    // The information contained within the request is another source
+    // of distinctive information. It might reveal the users name,
+    // date of request, request ID etc. In servlet type environments,
+    // useful information is contained in the HttpRequest or in the  
+    // HttpSession.
+    MDC.put("number", String.valueOf(number));
+
+    logger.info("Beginning to factor.");
+
+    if (number <= 0) {
+      throw new IllegalArgumentException(number +
+        " is not a positive integer.");
+    } else if (number == 1) {
+      return new int[] { 1 };
+    }
+
+    Vector<Integer> factors = new Vector<Integer>();
+    int n = number;
+
+    for (int i = 2; (i <= n) && ((i * i) <= number); i++) {
+      // It is bad practice to place log requests within tight loops.
+      // It is done here to show interleaved log output from
+      // different requests. 
+      logger.debug("Trying " + i + " as a factor.");
+
+      if ((n % i) == 0) {
+        logger.info("Found factor " + i);
+        factors.addElement(new Integer(i));
+
+        do {
+          n /= i;
+        } while ((n % i) == 0);
+      }
+
+      // Placing artificial delays in tight loops will also lead to
+      // sub-optimal resuts. :-)
+      delay(100);
+    }
+
+    if (n != 1) {
+      logger.info("Found factor " + n);
+      factors.addElement(new Integer(n));
+    }
+
+    int len = factors.size();
+
+    int[] result = new int[len];
+
+    for (int i = 0; i < len; i++) {
+      result[i] = ((Integer) factors.elementAt(i)).intValue();
+    }
+
+    // clean up
+    MDC.remove("client");
+    MDC.remove("number");
+
+    return result;
+  }
+
+  static void usage(String msg) {
+    System.err.println(msg);
+    System.err.println("Usage: java chapter7.NumberCruncherServer configFile\n" +
+      "   where configFile is a logback configuration file.");
+    System.exit(1);
+  }
+
+  public static void delay(int millis) {
+    try {
+      Thread.sleep(millis);
+    } catch (InterruptedException e) {
+    }
+  }
+
+  public static void main(String[] args) {
+    if (args.length != 1) {
+      usage("Wrong number of arguments.");
+    }
+
+    String configFile = args[0];
+
+    if (configFile.endsWith(".xml")) {
+      try {
+        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+        JoranConfigurator configurator = new JoranConfigurator();
+        configurator.setContext(lc);
+        lc.reset();
+        configurator.doConfigure(args[0]);
+      } catch (JoranException je) {
+        je.printStackTrace();
+      }
+    }
+
+    NumberCruncherServer ncs;
+
+    try {
+      ncs = new NumberCruncherServer();
+      logger.info("Creating registry.");
+
+      Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
+      registry.rebind("Factor", ncs);
+      logger.info("NumberCruncherServer bound and ready.");
+    } catch (Exception e) {
+      logger.error("Could not bind NumberCruncherServer.", e);
+
+      return;
+    }
+  }
+}
+ +

The implementation of the factor(int number) + method is of particular relevance. It starts by putting the + client's hostname into the MDC under the key + client. The number to factor, as requested by the client, + is put into the MDC under the key + number. After computing the distinct factors of the + integer parameter, the result is returned to the client. Before + returning the result however, the values for the client + and number are cleared by calling the + MDC.remove() method. Normally, a put() + operation should be balanced by the corresponding + remove() operation. Otherwise, the MDC + will contain stale values for certain keys. We would recommend + that whenever possible, remove() operations be + performed within finally blocks, ensuring their invocation + regardless of the execution path of the code. +

+ +

+ After these theoretical explanations, we are ready to run the number + cruncher example. Start the server with the following command: +

+ +
java chapter7.NumberCruncherServer src/main/java/chapter7/mdc1.xml
+ +

+ The mdc1.xml configuration file is listed below: +

+Example 7.4: Configuration file (logback-examples/src/main/java/chapter7/mdc1.xml) +
<configuration>
+  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+    <layout>
+      <Pattern>%-4r [%thread] %-5level C:%X{client} N:%X{number} - %msg%n</Pattern>
+    </layout>	    
+  </appender>
+  
+  <root level="debug">
+    <appender-ref ref="CONSOLE"/>
+  </root>  
+</configuration>
+ +

+ Note the use of the %X conversion specifier within the + Pattern option. +

+ +

+ The following command starts an instance of NumberCruncherClient + application: +

+ +
java chapter7.NumberCruncherClient hostname
+ +

+ where hostname is the host where the + NumberCruncherServer is running +

+ +

+ Executing multiple instances of the client and requesting the server to factor + the numbers 129 from the first client and shortly thereafter + the number 71 from the second client, the server outputs the following: +

+ +
+70984 [RMI TCP Connection(4)-192.168.1.6] INFO  C:orion N:129 - Beginning to factor.
+70984 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 2 as a factor.
+71093 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 3 as a factor.
+71093 [RMI TCP Connection(4)-192.168.1.6] INFO  C:orion N:129 - Found factor 3
+71187 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 4 as a factor.
+71297 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 5 as a factor.
+71390 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 6 as a factor.
+71453 [RMI TCP Connection(5)-192.168.1.6] INFO  C:orion N:71 - Beginning to factor.
+71453 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 2 as a factor.
+71484 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 7 as a factor.
+71547 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 3 as a factor.
+71593 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 8 as a factor.
+71656 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 4 as a factor.
+71687 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 9 as a factor.
+71750 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 5 as a factor.
+71797 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 10 as a factor.
+71859 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 6 as a factor.
+71890 [RMI TCP Connection(4)-192.168.1.6] DEBUG C:orion N:129 - Trying 11 as a factor.
+71953 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 7 as a factor.
+72000 [RMI TCP Connection(4)-192.168.1.6] INFO  C:orion N:129 - Found factor 43
+72062 [RMI TCP Connection(5)-192.168.1.6] DEBUG C:orion N:71 - Trying 8 as a factor.
+72156 [RMI TCP Connection(5)-192.168.1.6] INFO  C:orion N:71 - Found factor 71
+ +

+ The clients were run from a machine called orion as can be seen in + the above output. Even if the server processes the requests of clients + near-simultaneously in separate threads, the logging output pertaining + to each client request can be distinguished by studying the output of the + MDC. Note for example the stamp associated with number, + i.e. the number to factor. +

+ +

+ The attentive reader might have observed that the thread name could + also have been used to distinguish each request. The thread name can cause + confusion if the server side technology recycles threads. In that case, + it may be hard to determine the boundaries of each request, that is, + when a given thread finishes servicing a request and when it begins servicing the next. + Because the MDC is under the control of the application developer, + MDC stamps do not suffer from this problem. +

+ + + +

Automating access to the MDC

+ +

As we've seen, the MDC is very useful when dealing + with multiple clients. In the case of a web application that + manages user authentication, one simple solution could be to set + the user's name in the MDC and remove it once the + user logs out. Unfortunately, it is not always possible to + achieve reliable results using this technique. Since + MDC manages data on a per thread basis, a + server that recycles threads might lead to false information + contained in the MDC. +

+ +

To allow the information contained in the MDC to + be correct at all times when a request is processed, a possible + approach would be to store the username at the beginning of the + process, and remove it at the end of said process. A servlet + Filter comes in handy in this case. +

+ +

Within the servlet filter's doFilter method, we + can retrieve the relevant user data through the request (or a + cookie therein), store it the MDC. Subsequent + processing by other filters and servlets will automatically + benefit from the MDC data that was stored previously. Finally, + when our servlet filter regains control, we have an opportunity to + clean MDC data. +

+ +

Here is an implementation of such a filter:

+ +Example 7.5: User servlet filter ( +logback-examples/src/main/java/chapter7/UserServletFilter.java) +
package chapter7;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.slf4j.MDC;
+
+public class UserServletFilter implements Filter {
+
+  boolean userRegistered = false;
+  
+  private final String userKey = "username";
+  
+  public void destroy() {
+  }
+
+  public void doFilter(ServletRequest request, ServletResponse response,
+    FilterChain chain) throws IOException, ServletException {
+
+    HttpServletRequest req = (HttpServletRequest) request;
+    
+    Principal principal = req.getUserPrincipal();
+    // Please note that we could have also used a cookie to 
+    // retrieve the user name
+
+    if (principal != null) {
+      String username = principal.getName();
+      registerUsername(username);
+    } else {
+      HttpSession session = req.getSession();
+      String username = (String)session.getAttribute(userKey);
+      registerUsername(username);
+    }
+    
+    try {
+      chain.doFilter(request, response);
+    } finally {
+      if (userRegistered) {
+        MDC.remove(userKey);
+      }
+    }
+  }
+
+  public void init(FilterConfig arg0) throws ServletException {
+  }
+  
+  private void registerUsername(String username) {
+    if (username != null && username.trim().length() > 0) {
+      MDC.put(userKey, username);
+      userRegistered = true;
+    }
+  }
+}
+ +

When the filter's doFilter() method is called, it + first looks for a java.security.Principal object in the + request. This object contains the name of the currently + authenticated user. In case the user principal is not set, the + filter looks for a session attribute matching a given key (here + username). If a user information is found, it is + registered in the MDC. +

+ +

Once the filter chain has completed, the filter removes the user + information from the MDC. +

+ +

The approach we just outlined sets MDC data only for the duration + of the request and only for the thread processing it. Other threads + are unaffected. Furthermore, any given thread will contain correct + MDC data at any point in time.

+ + + +

MDC And Managed Threads

+ +

A copy of the mapped diagnostic context can not always be + inherited by worker threads from the initiating thread. This is the + case when java.util.concurrent.Executors is used for + thread management. For instance, newCachedThreadPool + method creates a ThreadPoolExecutor and like other + thread pooling code, it has intricate thread creation logic. +

+ +

In such cases, it is recommended that + MDC.getCopyOfContextMap() is invoked on the original + (master) thread before submitting a task to the executor. When the + task runs, as its first action, it should invoke + MDC.setContextMapValues() to associate the stored copy + of the original MDC values with the new Executor + managed thread. +

+ + + +
+ + diff --git a/logback-site/src/site/pages/manual/menu.js b/logback-site/src/site/pages/manual/menu.js index 3560e4c64131453330f8459be787a1a634cbddea..5459e114a5f27dff8f4b3458a11a3118822659e8 100644 --- a/logback-site/src/site/pages/manual/menu.js +++ b/logback-site/src/site/pages/manual/menu.js @@ -1,13 +1,13 @@ - -document.write('') -document.write(''); -document.write('') +document.write(''); +document.write('
- - -
- -
- -

Migration from log4j

- - -

This chapter deals with the topic of migrating custom log4j - components such as appenders or layouts to logback-classic. -

- -

Software which merely invokes log4j client API, that is the - Logger or Category classes in - org.apache.log4j package, can be automatically - migrated to use SLF4J via the SLF4J migrator - tool. -

- -

From a broader perspective, log4j and logback-classic are - closely related. The core components, such as loggers, appenders - and layouts exist in both frameworks and serve identical - purposes. Similarly, the most important internal data-structure, - namely LoggingEvent exists in both frameworks with - rather similar but non-identical implementations. Most notably, In - logback-classic LoggingEvent implements the - ILoggingEvent interface. Most of the changes requried - in migrating log4j components to logback-classic are related to - differences in implementation of the LoggingEvent - class. Rest assured, these differences are rather limited. If in - spite of your best efforts you are unable to migrate any given - log4j component to logback-classic, do post a question on the logback-dev mailing list. A logback - developper should be able to provide guidance. -

- - -

Migrating a log4j layout

- -

Let us begin by migrating a hypothetcical and trivially simple - log4j layout named TrivialLog4jLayout - which returns the message contained in a logging events as the - formatted message. Here is the code. -

- - -
package chapter11;
-
-import org.apache.log4j.Layout;
-import org.apache.log4j.spi.LoggingEvent;
-
-public class TrivialLog4jLayout extends Layout {
-
-  public void activateOptions() {
-    // there are no options to activate
-  }
-
-  public String format(LoggingEvent loggingEvent) {
-    return loggingEvent.getRenderedMessage();
-  }
-
-  public boolean ignoresThrowable() {
-    return true;
-  }
-}
- -

The logback-classic equivalent named TrivialLogbackLayout - would be

- -
package chapter11;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.LayoutBase;
-
-public class TrivialLogbackLayout extends LayoutBase<ILoggingEvent> {
-
-  public String doLayout(ILoggingEvent loggingEvent) {
-    return loggingEvent.getMessage();
-  }
-}    
- -

As you can see, in a logback-classic layout, the formatting - method is named doLayout instead of - format() in log4j. The ignoresThrowable() - method is not needed and has no equivalent in logback-classic. Note - that a logback-classic layout must extend the - LayoutBase<ILoggingEvent> class. -

- -

The activateOptions() method merits further - discussion. In log4j, a layout will have its - activateOptions() method invoked by log4j - configurators, that is PropertyConfigurator or - DOMConfigurator just after all the options of the - layout have been set. Thus, the layout will have an oppurtunity to - check that its options are coherent and if so, proceed to fully - intialize itself.

- - -

In logback-classic, layouts must implement the LifeCycle - interface which includes a method called start(). The - start() method is the equivalent of log4j's - activateOptions() method. -

- -

Migrating a log4j appender

- -

Migrating an appender is quite similar to migrating layout. Here - is a trivially simple appender called TrivialLog4jLayout - which writes on the console the string returned by its layout.

- -
package chapter11;
-
-import org.apache.log4j.AppenderSkeleton;
-import org.apache.log4j.spi.LoggingEvent;
-
-
-public class TrivialLog4jAppender extends AppenderSkeleton {
-
-  protected void append(LoggingEvent loggingevent) {
-    String s = this.layout.format(loggingevent);
-    System.out.println(s);
-  }
-
-  public void close() {
-    // nothing to do
-  }
-
-  public boolean requiresLayout() {
-    return true;
-  }
-}
- -

The logback-classic equivalent named TrivialLogbackAppender - would be written as

- - -
package chapter11;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.AppenderBase;
-
-public class TrivialLogbackAppender extends AppenderBase<ILoggingEvent> {
-
-  @Override
-  public void start() {
-    if (this.layout == null) {
-      addError("No layout set for the appender named [" + name + "].");
-      return;
-    }
-    super.start();
-  }
-
-  @Override
-  protected void append(ILoggingEvent loggingevent) {
-    // note that AppenderBase.doAppend will invoke this method only if
-    // this appender was successfully started.
-    
-    String s = this.layout.doLayout(loggingevent);
-    System.out.println(s);
-  }
-}
- - -

Comparing the two classes, you should notice that the contents - of the append() method remains unchanged. The - requiresLayout method is not used in logback and can - be removed. In logback, the stop() method is the - equivalent of log4j's close() method. However, - AppenderBase in logback-classic, contains an nop - implementation for stop which is sufficient for the - purposes of this trivial appender. -

- - - - -
- - + + + + + + Migration from log4j + + + + + + + + + +
+ + +
+ +
+ +

Migration from log4j

+ + +

This chapter deals with the topic of migrating custom log4j + components such as appenders or layouts to logback-classic. +

+ +

Software which merely invokes log4j client API, that is the + Logger or Category classes in + org.apache.log4j package, can be automatically + migrated to use SLF4J via the SLF4J migrator + tool. +

+ +

From a broader perspective, log4j and logback-classic are + closely related. The core components, such as loggers, appenders + and layouts exist in both frameworks and serve identical + purposes. Similarly, the most important internal data-structure, + namely LoggingEvent exists in both frameworks with + rather similar but non-identical implementations. Most notably, In + logback-classic LoggingEvent implements the + ILoggingEvent interface. Most of the changes requried + in migrating log4j components to logback-classic are related to + differences in implementation of the LoggingEvent + class. Rest assured, these differences are rather limited. If in + spite of your best efforts you are unable to migrate any given + log4j component to logback-classic, do post a question on the logback-dev mailing list. A logback + developper should be able to provide guidance. +

+ + +

Migrating a log4j layout

+ +

Let us begin by migrating a hypothetcical and trivially simple + log4j layout named TrivialLog4jLayout + which returns the message contained in a logging events as the + formatted message. Here is the code. +

+ + +
package chapter11;
+
+import org.apache.log4j.Layout;
+import org.apache.log4j.spi.LoggingEvent;
+
+public class TrivialLog4jLayout extends Layout {
+
+  public void activateOptions() {
+    // there are no options to activate
+  }
+
+  public String format(LoggingEvent loggingEvent) {
+    return loggingEvent.getRenderedMessage();
+  }
+
+  public boolean ignoresThrowable() {
+    return true;
+  }
+}
+ +

The logback-classic equivalent named TrivialLogbackLayout + would be

+ +
package chapter11;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.LayoutBase;
+
+public class TrivialLogbackLayout extends LayoutBase<ILoggingEvent> {
+
+  public String doLayout(ILoggingEvent loggingEvent) {
+    return loggingEvent.getMessage();
+  }
+}    
+ +

As you can see, in a logback-classic layout, the formatting + method is named doLayout instead of + format() in log4j. The ignoresThrowable() + method is not needed and has no equivalent in logback-classic. Note + that a logback-classic layout must extend the + LayoutBase<ILoggingEvent> class. +

+ +

The activateOptions() method merits further + discussion. In log4j, a layout will have its + activateOptions() method invoked by log4j + configurators, that is PropertyConfigurator or + DOMConfigurator just after all the options of the + layout have been set. Thus, the layout will have an oppurtunity to + check that its options are coherent and if so, proceed to fully + intialize itself.

+ + +

In logback-classic, layouts must implement the LifeCycle + interface which includes a method called start(). The + start() method is the equivalent of log4j's + activateOptions() method. +

+ +

Migrating a log4j appender

+ +

Migrating an appender is quite similar to migrating layout. Here + is a trivially simple appender called TrivialLog4jLayout + which writes on the console the string returned by its layout.

+ +
package chapter11;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.spi.LoggingEvent;
+
+
+public class TrivialLog4jAppender extends AppenderSkeleton {
+
+  protected void append(LoggingEvent loggingevent) {
+    String s = this.layout.format(loggingevent);
+    System.out.println(s);
+  }
+
+  public void close() {
+    // nothing to do
+  }
+
+  public boolean requiresLayout() {
+    return true;
+  }
+}
+ +

The logback-classic equivalent named TrivialLogbackAppender + would be written as

+ + +
package chapter11;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+
+public class TrivialLogbackAppender extends AppenderBase<ILoggingEvent> {
+
+  @Override
+  public void start() {
+    if (this.layout == null) {
+      addError("No layout set for the appender named [" + name + "].");
+      return;
+    }
+    super.start();
+  }
+
+  @Override
+  protected void append(ILoggingEvent loggingevent) {
+    // note that AppenderBase.doAppend will invoke this method only if
+    // this appender was successfully started.
+    
+    String s = this.layout.doLayout(loggingevent);
+    System.out.println(s);
+  }
+}
+ + +

Comparing the two classes, you should notice that the contents + of the append() method remains unchanged. The + requiresLayout method is not used in logback and can + be removed. In logback, the stop() method is the + equivalent of log4j's close() method. However, + AppenderBase in logback-classic, contains an nop + implementation for stop which is sufficient for the + purposes of this trivial appender. +

+ + + + +
+ + diff --git a/logback-site/src/site/pages/manual/onJoran.html b/logback-site/src/site/pages/manual/onJoran.html index ba08ea4e485f205cc553e106e4096196c4fee948..8027707539d6b795f5c3735bfbd10c5af7a9c9f2 100644 --- a/logback-site/src/site/pages/manual/onJoran.html +++ b/logback-site/src/site/pages/manual/onJoran.html @@ -1,746 +1,746 @@ - - - - - - Joran - - - - - - - - - -
- - -
- -
- -

Joran in your own applications

- -

As apparent in previous chapters, logback relies on Joran, a - mature, flexible and powerful configuration framework. Many of the - capabilities offered by logback modules are only possible on - account of Joran. This chapter focuses on Joran, its basic design - and its salient features. -

- -

Joran is actually a generic configuration system which can be - used independently of logging. To emphaises this point, we should - mention that the logback-core module does not have a notion of - loggers. In that spirit, most of the examples in this chapter have - nothing to do with loggers, appenders or layouts. -

- -

The examples presented in this chapter can be found under - LOGBACK_HOME/logback-examples/src/main/java/chapter10 - folder. -

- -

To install joran, simply download - logback and add logback-core-${version}.jar to your - classpath.

- -

Historical perspective

- -

Reflection is a powerful feature of the Java language, making - it possible to configure software systems declaratively. For - example, many important properties of an EJB are configured with - the ejb.xml file. While EJBs are written in Java, many of - their properties are specified within the ejb.xml - file. Similarly, logback settings can be specified in a - configuration file, expressed in XML format. Annotations available - in JDK 1.5 and heavily used in EJB 3.0 replace many of directives - previously found in XML files. Joran also makes use of annonations - but at a much smaller extent. Due to the dynamic nature of logback - configuration data (compared to EJBs) Joran's use of annonations - is rather limited. -

- -

In log4j, logback's predecessor, the - DOMConfigurator class, which is part of log4j version - 1.2.x and later, could also parse configuration files written in - XML. DOMConfigurator was written in a way that forced - us, the developers, to tweak the code each time the structure of - the configuration file changed. The modified code had to be - recompiled and redeployed. Just as importantly, the code of the - DOMConfigurator consisted of loops dealing with - children elements containing many interspersed if/else - statements. One could not help but notice that that particular - code reeked of redundancy and duplication. The commons-digester - project had shown us that it was possible to parse XML files - using pattern matching rules. At parse time, digester would apply - rules that matched designated patterns. Rule classes were usually - quite small and specialized. Consequently, they were relatively - easy to understand and maintain. -

- -

Armed with the DOMConfigurator experience, we - began developing Joran, a powerful configuration - framework to be used in logback. Joran was largely inspired by the - commons-digester project. Nevertheless, it uses a slightly - different terminology. In commons-digester, a rule can be seen as - consisting of a pattern and a rule, as shown by the - Digester.addRule(String pattern, Rule rule) - method. We find it unnecessarily confusing to have a rule to - consist of itself, not recursively but with a different - meaning. In Joran, a rule consists of a pattern and an action. An - action is invoked when a match occurs for the corresponding - pattern. This relation between patterns and actions lies at the - core of Joran. Quite remarkably, one can deal with quite complex - requirements by using simple patterns, or more precisely with - exact matches and wildcard matches. -

- -

SAX or DOM?

- -

Due to the event-based architecture of the SAX API, a tool based - on SAX cannot easily deal with forward references, that is, - references to elements which are defined later than the current - element being processed. Elements with cyclical references are - equally problematic. More generally, the DOM API allows the user to - perform searches on all the elements and make forward jumps. -

- -

This extra flexibility initially led us to choose the DOM API - as the underlying parsing API for Joran. After some - experimentation, it quickly became clear that dealing with jumps - to distant elements while parsing the DOM tree did not make sense - when the interpretation rules were expressed in the form of - patterns and actions. Joran only needs to be given the - elements in the XML document in a sequential, depth-first - order. -

- -

Joran was first implemented in DOM. However, the author - migrated to SAX in order to benefit from element location - information, available only with the SAX API. Location information - allows Joran to display the exact line and column number where an - error occured, which comes in very handy in indentifying parsing - problems. -

- -

Non goals

- -

Given its highly dynamic nature, the Joran API is not intended - to be used to parse very large XML documents with many thousands - of elements. -

- - -

Pattern

- -

A Joran pattern is essentially a string. There are two kind of - patterns, exact and wildcard. The pattern "a/b" - can be used to match <b> element nested within a - top-level <a> element. The "a/b" will not match - any other element, hence the exact match designation.

- -

Wildcards can be used to match suffixes or prefixes. For - example, the "*/a" pattern can be used to match any suffix ending - with "a", that is any <a> element within an XML - document but not any elements nested within <a>. - The "a/*" pattern will match any element prefixed by - <a>, that is any element nested within an - <a> element. -

- -

Actions

- -

As mentioned above, Joran parsing rules consists of the - association of patterns. Actions extend the Action - class, consisting of the following abstract methods. Other methods - have been omitted for berevity. -

- - -
package ch.qos.logback.core.joran.action;
-
-import org.xml.sax.Attributes;
-import ch.qos.logback.core.joran.spi.ExecutionContext;
-
-public abstract class Action {
-  
-
-  /**
-   * Called when the parser encounters an element matching a
-   * {@link ch.qos.logback.core.joran.spi.Pattern Pattern}.
-   */
-  public abstract void begin(InterpretationContext ec, String name,
-      Attributes attributes) throws ActionException;
-
-  /*
-   * Called when the parser encounters an endElement event matching a
-   * {@link ch.qos.logback.core.joran.spi.Pattern Pattern}.
-   */
-  public abstract void end(InterpretationContext ec, String name)
-      throws ActionException;
-}
- -

Thus, every action must implement the begin and end methods.

- - -

RuleStore

- -

As mentioned previously, the invocation of actions according to - matching patterns is a central concept in Joran. A rule is an - association of a pattern and an action. Rules are stored in a RuleStore. -

- -

As mentioned above, Joran is built on top of the SAX API. As an - XML document is parsed, each element generates events corresponding - to the start, body and end of each element. When a joran - configurator receives these events, it will attempt to find in its - rule store an action corresponding to the current - pattern.. For example, the current pattern for the start, body - or end event of element B nested within a top-level - A element is "A/B". The current pattern is a data - structure maintained automatically by Joran as it receives and - processes SAX events.

- -

When several rules match the current pattern, then exact - matches override suffix matches, and suffix matches overide prefix - matches. For exact details of implementation, please see the SimpleRuleStore - class. -

- - -

Interpretation context

- -

To allow various actions to collaborate, the invocation of begin - and end methods include an interpretation context as the first - parameter. The interpretation context includes an object stack, an - object map, an error list and a reference to the Joran interpreter - invoking the action. Please see the InterpretationContext - class for the exact list of fields contained in the interpretation - context. -

- -

Actions can collaborate together by fetching, pushing or popping - objects from the common object stack, or by putting and fetching - keyed objects on the common object map. Actions can report any error - conditions by adding error items on the interpretation context's - StatusManager. -

- -

Hello world

- -

The first example in this chapter illustrates the minimal - plumbing required for using Joran. The example consists of a - trivial action called - HelloWorldAction which prints "Hello World" on the - console when it's begin() method is invoked. The - parsing of XML files is done by a configurator. For the purposes of - this chapter, we have developped a very simple configurator called - SimpleConfigurator. - The HelloWorld - application brings all pieces together. -

- -
    -
  • It creates a map of rules and a Context
  • -
  • It creates a parsing rule by associating the - hello-world pattern with a corresponding - HelloWorldAction instance
  • -
  • It creates a SimpleConfigutator, passing it the - aforementioned rules map
  • -
  • it then invokes the doConfigure method of the - configurator, passing the designated XML file as parameter -
  • -
  • as a last step, the accumulated Status message in the context, - if any, are printed
  • -
- -

The hello.xml file contains one <hello-world> - element, without any other nested elements. See the - logback-examples/src/main/java/chapter10/helloWorld/ - folder for exact contents. -

- -

Running the HelloWorld application with hello.xml file - will print "Hello World" on the console.

- -

java chapter10.helloWorld.HelloWorld src/main/java/chapter10/helloWorld/hello.xml

- -

You are highly encourared to poke about this example, by adding - new rules on the rule store, modifying the XML document - (hello.xml) and adding new actions. -

- - - -

Collaborating - actions

- -

The logback-examples/src/main/java/joran/calculator/ - directory includes several actions which collaborate together - through the common object stack in order to accomplish simple - computations. -

- -

The calculator1.xml file contains a - computation element, with a nested - literal element. Here are its contents. -

- - Example 10.: First calculator example - (logback-examples/src/main/java/chapter10/calculator/calculator1.xml) - - -
<computation name="total">
-  <literal value="3"/>
-</computation>
- -

In the - Calculator1 application, we declare various - parsing rules (patterns and actions) collaborating together to - compute a result based on the contents of an XML document. -

- -

Running Calculator1 application with - calculator1.xml

- -

java chapter10.calculator.Calculator1 src/main/java/chapter10/calculator/calculator1.xml

- -

will print:

- -

The computation named [total] resulted in the value 3

- - -

Parsing the calculator1.xml document (listed above) - involves the following steps: -

- -
    -
  • The start event corresponding to the <computation> - element translates into the current pattern - "/computation". Since in the - Calculator1 application we associated the - pattern "/computation" with a - - ComputationAction1 instance, the - begin() method of that - ComputationAction1 instance is invoked. -
  • - -
  • The start event corresponding to the <literal> - element translates into the current pattern - "/computation/literal". Given the association of the - "/computation/literal" pattern with a - - LiteralAction instance, the - begin() method of that LiteralAction - instance is called.

    -
  • - -
  • By the same token, the end event corresponding to the - <literal> element triggers the invocation of the - end() method of the same LiteralAction - instance.

    -
  • - - -
  • Similarly, the event corresponding to the end of - <computation> element triggers the invocation the - end() method of the ComputationAction1 - same instance. -

    -
  • -
- -

What is interesting here is the way actions collaborate. The - LiteralAction reads a literal value and pushes it in - the object stack maintained by the - InterpretationContext. Once done, any other action - can pop the value to read or modify it. Here, the - end() method of the ComputationAction1 - class pops the value from the stack and prints it. -

- - - -

The next example, calculator2.xml file is a bit more - complex, but also more interesting.

- - Example 10.: Calculator configuration - file - (logback-examples/src/main/java/chapter10/calculator/calculator2.xml) -
<computation name="toto">
-  <literal value="7"/>
-  <literal value="3"/>
-  <add/>
-  <literal value="3"/>
-  <multiply/>
-</computation>
- - -

As in the previous example, in response to the <literal> - element,the appropriate - LiteralAction instance will push an integer, - corresponding to the value attribute, at the top of the - interpretation context's object stack. In this example, that is - calculator2.xml, the values are 7 and 3. In response to the - <add> element, the appropriate AddAction - will pop two previously pushed integers, compute their sum and push - the result, i.e. 10 (=7+3), at the top of the interpretation - context's stack. The next literal element will cause LiteralAction - to push an integer with value 3 at the top of the stack. In response - to the <multiply> element, the appropriate MultiplyAction - will pop two previously pushed integers, i.e. 10 and 3, and compute - their product. It will push the result, i.e. 30, at the top of the - stack. At the very end, in reponse to the end event corresponding to - the <;/computation> tag, the ComputationAction1 will print the - object at the top of the stack. Thus, running: -

- -

java chapter10.calculator.Calculator1 src/main/java/chapter10/calculator/calculator2.xml

- -

will yield

- -

The computation named [toto] resulted in the value 30

- - - - -

Implicit actions

- -

The rules defined thus far are called explicit actions because an - pattern/action association could be found in the rule store for the - current element. However, in highly extensible systems, the number - and type of components can be so large so as to make it very tedious - to associate an explicit action for all patterns. -

- -

At the same time, even in highly extensible systems one can - observe recurrent rules linking various parts together. Assuming we - could identify such rules, we could process components composed of - sub-components unknown at compilation time (of logback). For - example, Apache Ant is capable of handling tasks which contain tags - unknown at compile time, simply by inspecting the component for - methods whose names start with add, as in - addFile, or addClassPath. When Ant - encounters an embedded tag within a task, it simply instantiates an - object that matches the signature of the task class' add method and - attaches the resulting object to the parent. -

- -

Joran supports similar capability in the form of implicit - actions. Joran keeps a list of implicit actions which are applied if - no explicit pattern could match the current pattern. However, - applying an implicit action may not be always appropriate. Before - executing the implicit action, Joran asks a given implicit action - whether it is appropriate in the current situation. Only if the - action replies in the affirmative does the Joran configurator invoke - the (implicit) action. Note that this extra step makes it possible - to support multiple implicit actions for or possibly none, if no - implicit action is appropriate for a given situation. -

- -

You can create and register a custom implicit action as - illustrated in the next example contained within the - logback-examples/src/main/java/chapter10/implicit folder. -

- -

The PrintMe - application associates an - NOPAction instance with the pattern "*/foo", that - is any element named as "foo". As its name indicates, the - begin() and end() methods of - NOPAction are empty. The PrintMe - application also registers an instance of PrintMeImplicitAction - in its list of implicit actions. The - PrintMeImplicitAction is applicable for any element - which has a printme attribute set to - true. See the isApplicable() method in - PrintMeImplicitAction. The begin()() method - of PrintMeImplicitAction prints the name of the current - element on the console. -

- -

The XML document implicit1.xml is designed to illustrate - how implicit actions come into play.

- - Example 10.: Usage of implicit rules - (logback-examples/src/main/java/chapter10/implicit/implicit1.xml) -
<foo>
-  <xyz printme="true">
-    <abc printme="true"/>
-  </xyz>
-
-  <xyz/>
-
-  <foo printme="true"/>
-
-</foo>
- -

Running

- -

java chapter10.implicit.PrintMe src/main/java/chapter10/implicit/implicit1.xml

-

yields:

- -

Element [xyz] asked to be printed. -Element [abc] asked to be printed. -20:33:43,750 |-ERROR in c.q.l.c.joran.spi.Interpreter@10:9 - no applicable action for [xyz], current pattern is [[foo][xyz]]

- -

Given that NOPAction instance is explicitly - associated with the "*/foo" pattern, NOPActgion's - begin() and end() methods are invoked on - <foo> elements. PrintMeImplicitAction is never - triggered for any of the <foo> elements. For other elements, - since there are no matching explicit actions, the - isApplicable() method of - PrintMeImplicitAction is invoked. It will return true - only for elements having a printme - attribute set to true, namely the first <xyz> element (but not - the second) and the <abc> element. The second <xyz> element on - line 10, there are no applicable actions, an internal error message - is generated. This message is printed by the - StatusPrinter.print invocation, the last statement in - the PrintMe application. This explains the output shown - above (see previous paragraph). -

- -

Implicit actions in - practice

- -

The respective Joran configurators of logback-classic and - logback-access include just two implicit actions, namely - NestedComplexPropertyIA and - NestedComplexPropertyIA. -

- -

NestedBasicPropertyIA is applicable for any property - whose type, is a primitive type, or equivalent object type in the - java.lang package, an enumeration type, or any type - adhering to the "valueOf" convention. Such properties are said to - be basic or simple. A class is said to adhere to - the "valueOf" convention if it contains a static method named - valueOf() taking a java.lang.String as - parameter and returning an instance of the type in question. At - present time, Level, - Duration - and FileSize - classes follow this convention.. -

- -

NestedComplexPropertyIA action is applicable, in the - remaining cases where NestedBasicPropertyIA is not - applicable and if the object at the top of the object stack - has a setter or adder method for a property name equal to the - current element name. Note that such properties can in turn contain - other components. Thus, such properties are said to be - complex. In presence of a complex property, - NestedComplexPropertyIA will instantiate the - appropriate class for the nested component and attach it to the - parent component (at the top of the object stack) by using the - setter/adder method of the parent component and the nested element's - name. The corresponding class is specified by the class attribute of the (nested) current - element. However, if the class attribute - is missing, the class name can be deduced implicitly, if any of the - following is true: -

- -
    -
  1. there is an internal rule associating the parent object's - property with a designated class, -
  2. -
  3. the setter method contains a @DefaultClass attribute - designating a given class,
  4. - -
  5. the parameter type of the setter method is a contcrete class - possessing a public constructor, -
  6. -
- -

Default class mapping

- -

In logback-classic, there are a handful of inernal rules mapping - parent class/property name couples to a default class. These are - listed in the table below.

- - - - - - - - - - - - - - - - - - - - - - - - - -
Parent class property name default nested class
ch.qos.logback.core.AppenderBaselayoutch.qos.logback.classic.PatternLayout
ch.qos.logback.core.UnsynchronizedAppenderBaselayoutch.qos.logback.classic.PatternLayout
ch.qos.logback.core.filter.EvaluatorFilterevaluatorch.qos.logback.classic.boolex.JaninoEventEvaluator
- -

This list may change in future releases. Please see - logback-classic JoranConfigurator's - addDefaultNestedComponentRegistryRules method for the - latest rules. -

- -

In logback-access, the rules are very similar. In the default - class for the nested component, the ch.qos.logback.classic package - is replaced by ch.qos.logback.access. See logback-access JoranConfigurator's - addDefaultNestedComponentRegistryRules method for the - latest rules. -

- -

Collection of properties

- - -

Note that in addition to single simple properties or single - complex properties, logback's implicit actions support collectons of - properties, be they simple or complex. Instead of a setter method, - the property is specified by an "adder" method.

- -

New rules on the fly

- -

Joran includes an action which allows the Joran interpreter to - learn new rules on the fly, that is while interpreting an XML - document. See the - logback-examples/src/main/java/chapter10/newRule/ directory - for sample code. In this package, the - NewRuleCalculator application sets up just two - rules, one rule to process the top-most element, and a second rule - to learn new rules. Here is the relevant code from - NewRuleCalculator. -

- -
ruleMap.put(new Pattern("*/computation"), new ComputationAction1());
-ruleStore.addRule(new Pattern("/computation/new-rule"), new NewRuleAction());
- -

NewRuleAction, - part of logback-core, works pretty much like the other actions. It - has a begin() and end() method, and is - called each time the parser finds a new-rule element. When - invoked, the begin() method looks for pattern - and actionClass attributes. It then instantiates the - corresponding action class and adds the pattern/action association - as a new rule in Joran's rule store.

- - -

Here is how new rules can be declared in an xml file:

- -
<new-rule pattern="*/computation/literal"
-          actionClass="chapter10.calculator.LiteralAction"/>
- -

Using such new-rule declarations, we can transform - NewRuleCalculator to behave like the - Calculator1 application we saw earlier. involving the - calculation, could be expressed this way:

- - Example 10..: Configuration file using new - rules on the fly - (logback-examples/src/main/java/chapter10/newrule/new-rule.xml) - -
<computation name="toto">
-  <new-rule pattern="*/computation/literal" 
-            actionClass="chapter10.calculator.LiteralAction"/>
-  <new-rule pattern="*/computation/add" 
-            actionClass="chapter10.calculator.AddAction"/>
-  <new-rule pattern="*/computation/multiply" 
-            actionClass="chapter10.calculator.MultiplyAction"/>
-
-  <computation>
-    <literal value="7"/>
-    <literal value="3"/>
-    <add/>
-  </computation>   
- 
-  <literal value="3"/>
-  <multiply/>
-</computation>
- - -

java java chapter10.newRule.NewRuleCalculator src/main/java/chapter10/newRule/new-rule.xml

- -

yields

- -

The computation named [toto] resulted in the value 30

- -

which is identical to the output of the original calculator example.

- - - -
- - + + + + + + Joran + + + + + + + + + +
+ + +
+ +
+ +

Joran in your own applications

+ +

As apparent in previous chapters, logback relies on Joran, a + mature, flexible and powerful configuration framework. Many of the + capabilities offered by logback modules are only possible on + account of Joran. This chapter focuses on Joran, its basic design + and its salient features. +

+ +

Joran is actually a generic configuration system which can be + used independently of logging. To emphaises this point, we should + mention that the logback-core module does not have a notion of + loggers. In that spirit, most of the examples in this chapter have + nothing to do with loggers, appenders or layouts. +

+ +

The examples presented in this chapter can be found under + LOGBACK_HOME/logback-examples/src/main/java/chapter10 + folder. +

+ +

To install joran, simply download + logback and add logback-core-${version}.jar to your + classpath.

+ +

Historical perspective

+ +

Reflection is a powerful feature of the Java language, making + it possible to configure software systems declaratively. For + example, many important properties of an EJB are configured with + the ejb.xml file. While EJBs are written in Java, many of + their properties are specified within the ejb.xml + file. Similarly, logback settings can be specified in a + configuration file, expressed in XML format. Annotations available + in JDK 1.5 and heavily used in EJB 3.0 replace many of directives + previously found in XML files. Joran also makes use of annonations + but at a much smaller extent. Due to the dynamic nature of logback + configuration data (compared to EJBs) Joran's use of annonations + is rather limited. +

+ +

In log4j, logback's predecessor, the + DOMConfigurator class, which is part of log4j version + 1.2.x and later, could also parse configuration files written in + XML. DOMConfigurator was written in a way that forced + us, the developers, to tweak the code each time the structure of + the configuration file changed. The modified code had to be + recompiled and redeployed. Just as importantly, the code of the + DOMConfigurator consisted of loops dealing with + children elements containing many interspersed if/else + statements. One could not help but notice that that particular + code reeked of redundancy and duplication. The commons-digester + project had shown us that it was possible to parse XML files + using pattern matching rules. At parse time, digester would apply + rules that matched designated patterns. Rule classes were usually + quite small and specialized. Consequently, they were relatively + easy to understand and maintain. +

+ +

Armed with the DOMConfigurator experience, we + began developing Joran, a powerful configuration + framework to be used in logback. Joran was largely inspired by the + commons-digester project. Nevertheless, it uses a slightly + different terminology. In commons-digester, a rule can be seen as + consisting of a pattern and a rule, as shown by the + Digester.addRule(String pattern, Rule rule) + method. We find it unnecessarily confusing to have a rule to + consist of itself, not recursively but with a different + meaning. In Joran, a rule consists of a pattern and an action. An + action is invoked when a match occurs for the corresponding + pattern. This relation between patterns and actions lies at the + core of Joran. Quite remarkably, one can deal with quite complex + requirements by using simple patterns, or more precisely with + exact matches and wildcard matches. +

+ +

SAX or DOM?

+ +

Due to the event-based architecture of the SAX API, a tool based + on SAX cannot easily deal with forward references, that is, + references to elements which are defined later than the current + element being processed. Elements with cyclical references are + equally problematic. More generally, the DOM API allows the user to + perform searches on all the elements and make forward jumps. +

+ +

This extra flexibility initially led us to choose the DOM API + as the underlying parsing API for Joran. After some + experimentation, it quickly became clear that dealing with jumps + to distant elements while parsing the DOM tree did not make sense + when the interpretation rules were expressed in the form of + patterns and actions. Joran only needs to be given the + elements in the XML document in a sequential, depth-first + order. +

+ +

Joran was first implemented in DOM. However, the author + migrated to SAX in order to benefit from element location + information, available only with the SAX API. Location information + allows Joran to display the exact line and column number where an + error occured, which comes in very handy in indentifying parsing + problems. +

+ +

Non goals

+ +

Given its highly dynamic nature, the Joran API is not intended + to be used to parse very large XML documents with many thousands + of elements. +

+ + +

Pattern

+ +

A Joran pattern is essentially a string. There are two kind of + patterns, exact and wildcard. The pattern "a/b" + can be used to match <b> element nested within a + top-level <a> element. The "a/b" will not match + any other element, hence the exact match designation.

+ +

Wildcards can be used to match suffixes or prefixes. For + example, the "*/a" pattern can be used to match any suffix ending + with "a", that is any <a> element within an XML + document but not any elements nested within <a>. + The "a/*" pattern will match any element prefixed by + <a>, that is any element nested within an + <a> element. +

+ +

Actions

+ +

As mentioned above, Joran parsing rules consists of the + association of patterns. Actions extend the Action + class, consisting of the following abstract methods. Other methods + have been omitted for berevity. +

+ + +
package ch.qos.logback.core.joran.action;
+
+import org.xml.sax.Attributes;
+import ch.qos.logback.core.joran.spi.ExecutionContext;
+
+public abstract class Action {
+  
+
+  /**
+   * Called when the parser encounters an element matching a
+   * {@link ch.qos.logback.core.joran.spi.Pattern Pattern}.
+   */
+  public abstract void begin(InterpretationContext ec, String name,
+      Attributes attributes) throws ActionException;
+
+  /*
+   * Called when the parser encounters an endElement event matching a
+   * {@link ch.qos.logback.core.joran.spi.Pattern Pattern}.
+   */
+  public abstract void end(InterpretationContext ec, String name)
+      throws ActionException;
+}
+ +

Thus, every action must implement the begin and end methods.

+ + +

RuleStore

+ +

As mentioned previously, the invocation of actions according to + matching patterns is a central concept in Joran. A rule is an + association of a pattern and an action. Rules are stored in a RuleStore. +

+ +

As mentioned above, Joran is built on top of the SAX API. As an + XML document is parsed, each element generates events corresponding + to the start, body and end of each element. When a joran + configurator receives these events, it will attempt to find in its + rule store an action corresponding to the current + pattern.. For example, the current pattern for the start, body + or end event of element B nested within a top-level + A element is "A/B". The current pattern is a data + structure maintained automatically by Joran as it receives and + processes SAX events.

+ +

When several rules match the current pattern, then exact + matches override suffix matches, and suffix matches overide prefix + matches. For exact details of implementation, please see the SimpleRuleStore + class. +

+ + +

Interpretation context

+ +

To allow various actions to collaborate, the invocation of begin + and end methods include an interpretation context as the first + parameter. The interpretation context includes an object stack, an + object map, an error list and a reference to the Joran interpreter + invoking the action. Please see the InterpretationContext + class for the exact list of fields contained in the interpretation + context. +

+ +

Actions can collaborate together by fetching, pushing or popping + objects from the common object stack, or by putting and fetching + keyed objects on the common object map. Actions can report any error + conditions by adding error items on the interpretation context's + StatusManager. +

+ +

Hello world

+ +

The first example in this chapter illustrates the minimal + plumbing required for using Joran. The example consists of a + trivial action called + HelloWorldAction which prints "Hello World" on the + console when it's begin() method is invoked. The + parsing of XML files is done by a configurator. For the purposes of + this chapter, we have developped a very simple configurator called + SimpleConfigurator. + The HelloWorld + application brings all pieces together. +

+ +
    +
  • It creates a map of rules and a Context
  • +
  • It creates a parsing rule by associating the + hello-world pattern with a corresponding + HelloWorldAction instance
  • +
  • It creates a SimpleConfigutator, passing it the + aforementioned rules map
  • +
  • it then invokes the doConfigure method of the + configurator, passing the designated XML file as parameter +
  • +
  • as a last step, the accumulated Status message in the context, + if any, are printed
  • +
+ +

The hello.xml file contains one <hello-world> + element, without any other nested elements. See the + logback-examples/src/main/java/chapter10/helloWorld/ + folder for exact contents. +

+ +

Running the HelloWorld application with hello.xml file + will print "Hello World" on the console.

+ +

java chapter10.helloWorld.HelloWorld src/main/java/chapter10/helloWorld/hello.xml

+ +

You are highly encourared to poke about this example, by adding + new rules on the rule store, modifying the XML document + (hello.xml) and adding new actions. +

+ + + +

Collaborating + actions

+ +

The logback-examples/src/main/java/joran/calculator/ + directory includes several actions which collaborate together + through the common object stack in order to accomplish simple + computations. +

+ +

The calculator1.xml file contains a + computation element, with a nested + literal element. Here are its contents. +

+ + Example 10.: First calculator example + (logback-examples/src/main/java/chapter10/calculator/calculator1.xml) + + +
<computation name="total">
+  <literal value="3"/>
+</computation>
+ +

In the + Calculator1 application, we declare various + parsing rules (patterns and actions) collaborating together to + compute a result based on the contents of an XML document. +

+ +

Running Calculator1 application with + calculator1.xml

+ +

java chapter10.calculator.Calculator1 src/main/java/chapter10/calculator/calculator1.xml

+ +

will print:

+ +

The computation named [total] resulted in the value 3

+ + +

Parsing the calculator1.xml document (listed above) + involves the following steps: +

+ +
    +
  • The start event corresponding to the <computation> + element translates into the current pattern + "/computation". Since in the + Calculator1 application we associated the + pattern "/computation" with a + + ComputationAction1 instance, the + begin() method of that + ComputationAction1 instance is invoked. +
  • + +
  • The start event corresponding to the <literal> + element translates into the current pattern + "/computation/literal". Given the association of the + "/computation/literal" pattern with a + + LiteralAction instance, the + begin() method of that LiteralAction + instance is called.

    +
  • + +
  • By the same token, the end event corresponding to the + <literal> element triggers the invocation of the + end() method of the same LiteralAction + instance.

    +
  • + + +
  • Similarly, the event corresponding to the end of + <computation> element triggers the invocation the + end() method of the ComputationAction1 + same instance. +

    +
  • +
+ +

What is interesting here is the way actions collaborate. The + LiteralAction reads a literal value and pushes it in + the object stack maintained by the + InterpretationContext. Once done, any other action + can pop the value to read or modify it. Here, the + end() method of the ComputationAction1 + class pops the value from the stack and prints it. +

+ + + +

The next example, calculator2.xml file is a bit more + complex, but also more interesting.

+ + Example 10.: Calculator configuration + file + (logback-examples/src/main/java/chapter10/calculator/calculator2.xml) +
<computation name="toto">
+  <literal value="7"/>
+  <literal value="3"/>
+  <add/>
+  <literal value="3"/>
+  <multiply/>
+</computation>
+ + +

As in the previous example, in response to the <literal> + element,the appropriate + LiteralAction instance will push an integer, + corresponding to the value attribute, at the top of the + interpretation context's object stack. In this example, that is + calculator2.xml, the values are 7 and 3. In response to the + <add> element, the appropriate AddAction + will pop two previously pushed integers, compute their sum and push + the result, i.e. 10 (=7+3), at the top of the interpretation + context's stack. The next literal element will cause LiteralAction + to push an integer with value 3 at the top of the stack. In response + to the <multiply> element, the appropriate MultiplyAction + will pop two previously pushed integers, i.e. 10 and 3, and compute + their product. It will push the result, i.e. 30, at the top of the + stack. At the very end, in reponse to the end event corresponding to + the <;/computation> tag, the ComputationAction1 will print the + object at the top of the stack. Thus, running: +

+ +

java chapter10.calculator.Calculator1 src/main/java/chapter10/calculator/calculator2.xml

+ +

will yield

+ +

The computation named [toto] resulted in the value 30

+ + + + +

Implicit actions

+ +

The rules defined thus far are called explicit actions because an + pattern/action association could be found in the rule store for the + current element. However, in highly extensible systems, the number + and type of components can be so large so as to make it very tedious + to associate an explicit action for all patterns. +

+ +

At the same time, even in highly extensible systems one can + observe recurrent rules linking various parts together. Assuming we + could identify such rules, we could process components composed of + sub-components unknown at compilation time (of logback). For + example, Apache Ant is capable of handling tasks which contain tags + unknown at compile time, simply by inspecting the component for + methods whose names start with add, as in + addFile, or addClassPath. When Ant + encounters an embedded tag within a task, it simply instantiates an + object that matches the signature of the task class' add method and + attaches the resulting object to the parent. +

+ +

Joran supports similar capability in the form of implicit + actions. Joran keeps a list of implicit actions which are applied if + no explicit pattern could match the current pattern. However, + applying an implicit action may not be always appropriate. Before + executing the implicit action, Joran asks a given implicit action + whether it is appropriate in the current situation. Only if the + action replies in the affirmative does the Joran configurator invoke + the (implicit) action. Note that this extra step makes it possible + to support multiple implicit actions for or possibly none, if no + implicit action is appropriate for a given situation. +

+ +

You can create and register a custom implicit action as + illustrated in the next example contained within the + logback-examples/src/main/java/chapter10/implicit folder. +

+ +

The PrintMe + application associates an + NOPAction instance with the pattern "*/foo", that + is any element named as "foo". As its name indicates, the + begin() and end() methods of + NOPAction are empty. The PrintMe + application also registers an instance of PrintMeImplicitAction + in its list of implicit actions. The + PrintMeImplicitAction is applicable for any element + which has a printme attribute set to + true. See the isApplicable() method in + PrintMeImplicitAction. The begin()() method + of PrintMeImplicitAction prints the name of the current + element on the console. +

+ +

The XML document implicit1.xml is designed to illustrate + how implicit actions come into play.

+ + Example 10.: Usage of implicit rules + (logback-examples/src/main/java/chapter10/implicit/implicit1.xml) +
<foo>
+  <xyz printme="true">
+    <abc printme="true"/>
+  </xyz>
+
+  <xyz/>
+
+  <foo printme="true"/>
+
+</foo>
+ +

Running

+ +

java chapter10.implicit.PrintMe src/main/java/chapter10/implicit/implicit1.xml

+

yields:

+ +

Element [xyz] asked to be printed. +Element [abc] asked to be printed. +20:33:43,750 |-ERROR in c.q.l.c.joran.spi.Interpreter@10:9 - no applicable action for [xyz], current pattern is [[foo][xyz]]

+ +

Given that NOPAction instance is explicitly + associated with the "*/foo" pattern, NOPActgion's + begin() and end() methods are invoked on + <foo> elements. PrintMeImplicitAction is never + triggered for any of the <foo> elements. For other elements, + since there are no matching explicit actions, the + isApplicable() method of + PrintMeImplicitAction is invoked. It will return true + only for elements having a printme + attribute set to true, namely the first <xyz> element (but not + the second) and the <abc> element. The second <xyz> element on + line 10, there are no applicable actions, an internal error message + is generated. This message is printed by the + StatusPrinter.print invocation, the last statement in + the PrintMe application. This explains the output shown + above (see previous paragraph). +

+ +

Implicit actions in + practice

+ +

The respective Joran configurators of logback-classic and + logback-access include just two implicit actions, namely + NestedComplexPropertyIA and + NestedComplexPropertyIA. +

+ +

NestedBasicPropertyIA is applicable for any property + whose type, is a primitive type, or equivalent object type in the + java.lang package, an enumeration type, or any type + adhering to the "valueOf" convention. Such properties are said to + be basic or simple. A class is said to adhere to + the "valueOf" convention if it contains a static method named + valueOf() taking a java.lang.String as + parameter and returning an instance of the type in question. At + present time, Level, + Duration + and FileSize + classes follow this convention.. +

+ +

NestedComplexPropertyIA action is applicable, in the + remaining cases where NestedBasicPropertyIA is not + applicable and if the object at the top of the object stack + has a setter or adder method for a property name equal to the + current element name. Note that such properties can in turn contain + other components. Thus, such properties are said to be + complex. In presence of a complex property, + NestedComplexPropertyIA will instantiate the + appropriate class for the nested component and attach it to the + parent component (at the top of the object stack) by using the + setter/adder method of the parent component and the nested element's + name. The corresponding class is specified by the class attribute of the (nested) current + element. However, if the class attribute + is missing, the class name can be deduced implicitly, if any of the + following is true: +

+ +
    +
  1. there is an internal rule associating the parent object's + property with a designated class, +
  2. +
  3. the setter method contains a @DefaultClass attribute + designating a given class,
  4. + +
  5. the parameter type of the setter method is a contcrete class + possessing a public constructor, +
  6. +
+ +

Default class mapping

+ +

In logback-classic, there are a handful of inernal rules mapping + parent class/property name couples to a default class. These are + listed in the table below.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Parent class property name default nested class
ch.qos.logback.core.AppenderBaselayoutch.qos.logback.classic.PatternLayout
ch.qos.logback.core.UnsynchronizedAppenderBaselayoutch.qos.logback.classic.PatternLayout
ch.qos.logback.core.filter.EvaluatorFilterevaluatorch.qos.logback.classic.boolex.JaninoEventEvaluator
+ +

This list may change in future releases. Please see + logback-classic JoranConfigurator's + addDefaultNestedComponentRegistryRules method for the + latest rules. +

+ +

In logback-access, the rules are very similar. In the default + class for the nested component, the ch.qos.logback.classic package + is replaced by ch.qos.logback.access. See logback-access JoranConfigurator's + addDefaultNestedComponentRegistryRules method for the + latest rules. +

+ +

Collection of properties

+ + +

Note that in addition to single simple properties or single + complex properties, logback's implicit actions support collectons of + properties, be they simple or complex. Instead of a setter method, + the property is specified by an "adder" method.

+ +

New rules on the fly

+ +

Joran includes an action which allows the Joran interpreter to + learn new rules on the fly, that is while interpreting an XML + document. See the + logback-examples/src/main/java/chapter10/newRule/ directory + for sample code. In this package, the + NewRuleCalculator application sets up just two + rules, one rule to process the top-most element, and a second rule + to learn new rules. Here is the relevant code from + NewRuleCalculator. +

+ +
ruleMap.put(new Pattern("*/computation"), new ComputationAction1());
+ruleStore.addRule(new Pattern("/computation/new-rule"), new NewRuleAction());
+ +

NewRuleAction, + part of logback-core, works pretty much like the other actions. It + has a begin() and end() method, and is + called each time the parser finds a new-rule element. When + invoked, the begin() method looks for pattern + and actionClass attributes. It then instantiates the + corresponding action class and adds the pattern/action association + as a new rule in Joran's rule store.

+ + +

Here is how new rules can be declared in an xml file:

+ +
<new-rule pattern="*/computation/literal"
+          actionClass="chapter10.calculator.LiteralAction"/>
+ +

Using such new-rule declarations, we can transform + NewRuleCalculator to behave like the + Calculator1 application we saw earlier. involving the + calculation, could be expressed this way:

+ + Example 10..: Configuration file using new + rules on the fly + (logback-examples/src/main/java/chapter10/newrule/new-rule.xml) + +
<computation name="toto">
+  <new-rule pattern="*/computation/literal" 
+            actionClass="chapter10.calculator.LiteralAction"/>
+  <new-rule pattern="*/computation/add" 
+            actionClass="chapter10.calculator.AddAction"/>
+  <new-rule pattern="*/computation/multiply" 
+            actionClass="chapter10.calculator.MultiplyAction"/>
+
+  <computation>
+    <literal value="7"/>
+    <literal value="3"/>
+    <add/>
+  </computation>   
+ 
+  <literal value="3"/>
+  <multiply/>
+</computation>
+ + +

java java chapter10.newRule.NewRuleCalculator src/main/java/chapter10/newRule/new-rule.xml

+ +

yields

+ +

The computation named [toto] resulted in the value 30

+ +

which is identical to the output of the original calculator example.

+ + + +
+ + diff --git a/logback-site/src/site/pages/manual/underTheHood.html b/logback-site/src/site/pages/manual/underTheHood.html index a51ba16074580e99f8cb1471f834e56eba0ed9be..c68fdcfc29ba5eaee1fcb9b432053bb1e67c9b5c 100644 --- a/logback-site/src/site/pages/manual/underTheHood.html +++ b/logback-site/src/site/pages/manual/underTheHood.html @@ -1,15 +1,15 @@ - - - - - - under the hood - - -

Under The Hood Sequence Diagram

- - underTheHoodSequence2.gif - - - + + + + + + under the hood + + +

Under The Hood Sequence Diagram

+ + underTheHoodSequence2.gif + + + diff --git a/logback-site/src/site/pages/news.html b/logback-site/src/site/pages/news.html index 9f9e3ecb6c4ffd67d390964db42b19a27fab4729..c5cb13dd31f5946899f1639e97a57c58ab6c8ff6 100644 --- a/logback-site/src/site/pages/news.html +++ b/logback-site/src/site/pages/news.html @@ -1,1171 +1,1171 @@ - - - - - - News - - - - - - - - - -
- - -
-
- -

Logback News

- -

You can receive logback-related announcements by subscribing to - the QOS.ch - announce mailing list.

- -
- -

13th of November 2009 - Release of version 0.9.18

- -

After a very long investigation resulting in somewhat a better - understanding of licensing issues, logback is now dual-licensed under the EPL 1.0 and LGPL - 2.1. -

- -

Due to a clerical error LBCORE-26 has - re-raised its ugly head. It has now been tamed for good.

- -

Fixed Private-Package and Export-Package sections in - logback-classic.jar MANIFEST as reported in LBCLASSIC-165 - and LBCLASSIC-121 - by applying the relavant patches supplied by Hugues Malphettes. -

- -

Made the OSGi import declerations for Janino and javax optional - as proposed by David Varnes in LBCORE-101.

- -

ReconfigureOnChangeFilter did not pick up changes - for configuration files containing spaces. This issue was reported - in LBCORE-119 - by Anders Wallgren. -

- -

When ill-formed configuration files fragments were included in - another configuration file, the included file was not closed - correctly. This issue was reported in LBCORE-122 by - Michael Franz. -

- -

JaninoEventEvaluator now passes the throwable associated with - an event as a java.lang.Throwable instead of an - IThrowableProxy. This fixes LBCLASSIC-155 - as reported by Hontvári József. See EvaluatorFilter - documentation for more details.

- -

The name of the log file nested within .zip archives was - incorrectly set to be that of the tmp file logback creates during - compression. Anders Wallgren reported and posted an appropriate - patch for this problem in LBCORE-98. The - nested file is now named after the zip archive file. Analysis - showed that this was an appropriate strategy in all the cases we - considered.

- -

Fixed LBCLASSIC-149. The - ContextNameConverter now correctly uses the context name of the - event instead of its own context name. -

- -

When a logger is named after an inner class, the '$' is used as - a separator, instead of the usual '.'. This fixes the level - inheritence issue described in LBCLASSIC-102 - and as reported by Joern Huxhorn.

- -
- -

9th of August 2009 - Release of version 0.9.17

- -

PackagingDataCalculator now correctly deals with - NoClassDefFoundError thrown by class loaders. This - fixes LBCLASSIC-125 - reported by Roland Klein and independently by Didier Besset. -

- -

In configuration files, all tags names associated with explicit - actions are now case-insensitive. This should diminish - case-related errors users may make when writing configuration - files. Tag names associated with implicit actions which are - closely linked to the actual Java class being configured, still - need to follow the camelCase convention. If you are unsure which - case to use for a given tag name, just follow the camelCase - convention for tag names which should be correct in most - cases.

- -

It is now possible to create uniquely named files by - timestamp. Such files are appropriate for log files associated - with batch applications. This enhancement fulfills LBCORE-91 as - requested by Rick Beton and Szel Zoltan. -

- -

Append mode is now mandatory in - RollingFileAppender. This was already the default and - truncation mode is unreasonable in most cases. For example, in - truncate mode when an application stops and is quickly re-started, - any pre-existing log file for the current period will be lost.

- -

The activeFile field in - RollingFileAppender is now properly updated, fixing - LBCORE-90 as - reported by Valery Shorin.

- - -

The TimeBasedTriggeringPolicy has been heavily - refactored. It is now possible to trigger rolling simultaenously - by time and - by size, fixing LBCORE-61. -

- -

Fixed LBCLASSIC-145 - reported by Joern Huxhorn. The LoggingEventVO class - now correctly populates its callerData field if the original - ILoggingEvent already has it.

- -
- -

15th of July 2009 - Release of version 0.9.16

- -

In addition to nifty new features, this release contains - several important internal changes. Given the importance of some - of those internal changes, this release may be less stable - than previous logback releases.

- -

In logback-classic, LoggingEvent - now implements the ILoggingEvent - interface. All logback-classic components expect to process - ILoggingEvent instances. Moreover, events which sent - to a remote host are now of type LoggingEventVO. -

- -

Logback-classic will now automatically - re-configure itself when its configuration file is - modified. This enhancement was requested in LBCORE-59 by - Michael Osipov.

- -

FileAppender and its derived class RolllingFileAppender are now - based on a finer-grain synchronization model. This change is aimed - at reducing various synchronization related bugs, namely LBCLASSIC-135 - and its various sub-tasks. -

- -

Fixed a bug in the localLevelReset() method in the - Logger class which inadvertently used the DEBUG_INT - value in the org.slf4j.spi.LocationAwareLogger interface instead - of the DEBUG_INT value in ch.qos.logback.classic.Level class. The - issue was first identified by Andy Ruch in - a message to the logback-user list -

- -

If the logger name had 12 or more segments, a the logger - conversion specified would throw an - ArrayIndexOfBounds exception. Lukas Zapletal has - kindly reported this problem in LBCLASSIC-110 - and provided a test case. -

- -

A new discriminator class called "ContextBasedDiscriminator" - allows SiftingAppender to separate logging based on the context - name. This fits nicely with the requirements expressed in LBCLASSIC-117 - by Rick Janda. -

- -

When a context is reset, then its object and property maps are - now cleared. This fixes LBCORE-104 - reported by Johan Bos. -

- -

Fixed LBCORE-105. Configuration - files placed in jar files will no longer lock the jar file. This - issue was initially reported for log4j in bug - 47465 Mark Thomas. -

- -

Fixed LBCORE-94. While - configuring a RollingFileAppender, if the File property is - declared after any rolling or triggering policies, then logback will - now generate an error status message. -

- -

Fixed LBCLASSIC-134 - reported by Darryl Smith. DuplicateMessageFilter will - now behave correctly when invoked via - Logger.isXXXEnabled methods. -

- -

Fixed LBCORE-107, - incorrectly set context information for the - NestedBasicPropertyIA instance in Joran, reported by - Lóránt Pintér. -

- -

Fixed LBCLASSIC-109, - reported by Andrew Ruch when a logger context was reset, the trace - level was erroneously enabled. -

- -
- -

12th of February 2009 - Release of version 0.9.15

- -

When the reset() method in LoggerContext is - called, registered turbo filters are first stopped before being - unregistered. This fixes LBCLASSIC-89 - reported by Alexis Morillo. -

- -

Added a servlet for viewing internal status messages as an HTML - table. Two separate implementations are available; one for logback-classic - and the other for logback-access.

- -

Added the clear() mthod to the - StatusManager interface. After reconfiguration, it - may be desirable to clear the status list maintained by a - StatusManager. This change was requested by Alexis - Morillo in LBCORE-77. -

- -

Fixed problem LBCLASSIC-104 - related to loss of MDC information in deferred logging events. -

- -

Fixed issue LBCLASSIC-101. Logback - jar files now include full OSGi bundle information in their - manifests. This information is automatically added by Apache - Felix' Maven bundle plug-in. The generated manifest files contain - an appropriate Bundle-RequiredExecutionEnvironment directive, - fixing LBGENERAL-8. -

- -

The setter and getter methods for the layout property in - AppenderBase class now have reasonable default - implementations, instead of nop previously. This change was - requested by Thilo Tanner in LBCORE-56. -

- - -

Added log4j.dtd compatible XMLLayout - as requested in LBCLASSIC-22. -

- -

New chapter on Joran.

- -
- -

29th of December 2008 - Release of version 0.9.14

- -

Corrected a serious dead-lock problem occuring during - configuration. It was reported in LBCLASSIC-81 by - Holger Mense.

- -

Corrected thread leakage observed with - TimeBasedRollingPolicy's - AsynchronousCompressor. This bug was reported in LBCORE-78 by Szel - Zoltan.

- -

Added DuplicateMessageFilter, - a turbo filter which detects duplicate messages, and beyond a - certain number of repetitions, drops repeated messages.

- -

Added a new appender called SiftingAppender. As - its name intimates, a SiftingAppender - can be used to separate (or sift) logging according to a given - runtime attribute. For example, SiftingAppender can - separate logging events according to user sessions, so that the - logs generated by each user go into distinct log files, one log - file per user. -

- -

BasicStatusManager's internal buffer is now split - into two parts, the header part and the tail part. The header part - stores the fist H status messages whereas the tail part stores the - last T messages. At present time H=T=150, although these values may - change in future releases.

- -

Fixed NullPointerException thrown when calling - setContextMap on a fresh MDC. Issue was - reported by Francois Terrier. -

- - -

Evaluators are now wired into an appender automatically - (implicit rules) without the help of - EvaluatorAction. EvaluatorAction is now only needed - for global evaluator elements. It follows that name attribute is - necessary only for global evaluators. Embedded evaluators no - longer need a name. This change fixes LBCLASSIC-100. In - addition, EvaluatorAction has been modified to accept - evaluators of any type and not just instances of - JaninoEvaluator. -

- -

Logback-classic default configuration process will now - automatically print status data on the console in case of warnings - as well as errors. Previously, status data was printed only in - case of errors.

- -

ContextInitializer will now print the url of the - configuration it is using. This should help reduce confusion when - multiple config files are found on the class path. This change - resolves LBCLASSIC-55 - reported by Anton Tagunov and Henric Larsson. -

- -

In case multiple configuration files are found on the class - path, ContextInitializer will now emit a - warning. This fixes LBCLASSIC-85 - filed by Szel Zoltan. -

- -

HTMLLayout now honors custom conversion words, - thus fixing LBCORE-74 as - reported by Natan Cox.

- -

Fixed LBCORE-69 as - reported by Andrey Rybin. SMTPAppenderBase now has - support for charset encodings so that email messages can contain - characters beyond US-ASCII. -

- -

SMTPAppender in logback-classic now defaults to - OnErrorEvaluator instead of a janino-based - evaluator. Thus, by default SMTPAppender no longer - depends on Janino.

- -

Added UnsynchronizedAppenderBase class based on Ralph Goers' - contribution in LBCORE-58. Note - that AppenderBase remains unchanged. Appenders which - need to handle synchronization on their own can do so by deriving - from UnsynchronizedAppenderBase.

- -

5th of December 2008 - Release of version 0.9.13

- -

A NullPointerException was being thrown when a the - level of a logger was set to null. The logger in question had to - have children. This problem was reported in LBCLASSIC-91 - by Mateusz Jedruch. -

- -

4th of December 2008 - Release of version 0.9.12

- -

Fixed bug - LBCORE-26 reported by Tsutomu YANO and independently by - Hontvári József and Gamaliel - Amaudruz. RollingFileAppender when used in conjunction - with DateBasedRollingPolicy will rollover existing log - files at initialization if their timestamp warrants it. -

- -

Added support for file appending in prudent mode. Thus, - multiple FileAppender instances running on multiple - JVMs can safely write to the same log file. With certain - limitations, prudent mode extends to - RollingFileAppender. -

- - -

Fixed LBCLASSIC-83. - It is now possible to set the level of a logger to null, even if - it was previously set to a non-null level. Previously, a - NullPointerException would be thrown. -

- -

In reponse to LBCLASSIC-61, LBCLASSIC-33, LBCLASSIC-24 and - LBCLASSIC-14 - JMXConfigurator has been redesigned. -

- -

Fixed LBGENERAL-22. The - log4j.properties - translator web-application has been significatnly refactored. -

- -

Fixed improvement request LBCLASSIC-59 - relation to StatusListeners, originally submitted by Anton Tagunov. -

- -

The logger and class name converters now consider zero as - having special meaning, and will return the simple class name, - removing the package name prefix. This feature was asked by - Silvano Maffeis.

- -

In response to LBCLASSIC-54 - support for turbo filters has refactored. The present code is safe - under concurrent access while still offering good performance. -

- -

Fixed LBCORE-43 reported - by Bruno Navert. Configuration files can now look up property - files from classpath resources. -

- -

Fixed LBCLASSIC-86 - related to AccessControlException thrown when run in - a JVM with a SecurityManager. -

- -

Invoking the LoggerContext.reset() method resets - logger levels to their default value, that is DEBUG - for the root logger and null for all other - loggers. This was requested in LBCLASSIC-90 by - Mateusz Jedruch. -

- - - -

Fixed bug - LBCLASSIC-69 reported by Anton Tagunov. The - LevelToSyslogSeverity now correctly handles the TRACE level. -

- -

Fixed bug - LBCLASSIC-57 reported by Anton Tagunov. SyslogAppender could - overwhelm the Syslog server with very large messages. SyslogAppender - now limits its message size to 256K. -

- -

Logback now supports setting the logger context - name as well as inserting variables stored in JNDI as - properties. -

- -

Fixed issue LBCLASSIC-49 - reported by Oliver Lietz. The getLogger() method in - LoggerContext class will now throw an - IllegalArgumentException when invoked with a null - argument. -

- - -
- -

28th of October 2008 - Release of version 0.9.11

- -

Fixed LBCLASSIC-77 - reported independenly by Gianni Doe, Yannick Haudry and Yossi Shaul. - The childValue() method of CopyOnInheritThreadLocal - class part of MDC code no longer throws a - NullPointerException. -

- -
- -

27th of October 2008 - Release of version 0.9.10

- -

In case of errors during initialization, logback-classic now - automatically prints out its internal status. This has been - a frequently requested feature. -

- -

The LogbackValve in logback-access (ensuring integration with - Tomcat), will now systematically print its internal status upon - initialization, unless told to be quiet. This greatly helps - troubleshooting the configration of logback-access under Tomcat. -

- -

Fixed bug - 147 which occured when the user inadvertently attempted to set - the layout of a SyslogAppender. The code now actively - prevents this. Documenation has been updated to reflect the change. -

- -

Fixed bug - LBCLASSIC-56 originally reported by Michel Colette. Backslash - characters are now correctly interpreted in filename patterns. -

- -

The TurboFilterChain in a LoggerContext is now - cleared when the reset() method is called. This - problem was reported on May 1st, 2008, by Julia Hu on the logback - developpers list. -

- - - -

Fixed issue LBCORE-48. During - rollover, compression of large files would bring all logging to a - halt. In this latest release, the rolled over file is first renamed, - which is a relatively fast operation, and only then is the renamed - file compressed asyncronously (in a separate thread). -

- -

Fixed issue LBCORE-11. It is now - possible to instruct TimeBasedRollingPolicy to delete old files, - thus controlling then number of archived log files.

- -

Fixed issue LBCORE-42. If the - parent directory of the log file does not exist, then FileAppender - will create it, including any necessary but nonexistent parent - directories. -

- -

Fixed LBCORE-15 - reported by Klaus Unger and others. DBAppender should now work with - Oracle 9, 10g and 11g, regardless of the JDBC driver type used. -

- -

Fixed issue LBCORE-17 reported by - Thorbjørn Ravn Andersen. Logback now relies on Geronimo JMS - API specifications instead of Sun's JMS API specification, the - latter requiring manual installation. With Geronimo JMS, logback can - be built using Maven without needing to manually install any - dependencies. -

- -

Fixed issue LBCORE-23. In - PatternLayout, parenthesis can be used to group conversion - patterns. It follows that the '(' and ')' carry special meaning and - need to be escaped to be used as literals. This is now properly - documented. -

- -

The location of the default configuration file can be specified - by a system property. This feature was requested in LBCORE-32 by Ted - Graham, Matt Fowles, Ivan Biddles and Ralph Goers. -

- -

Fixed issue LBCORE-55 reported by - Natan Cox. WriterAppender now outputs its presentation - footer and file footer in the the correct order. -

- - -

Fixed issue LBCORE-27 reported by - Peter Royal. SMTPAppender now outputs its presentation - footer and file footer in the the correct order. -

- - - -

Fixed issue LBCLASSIC-67 - reported by Alessandro Fustini. SMTPAppender now correctly - configures the layout used to format the subject line of the - outgoing email. It no longer appends a lengthy stack trace to the - subject line. -

- - -

Fixed issue LBCLASSIC-68 - reported by Gili Tzabari. In environments where the TCCL (Thread - Context Class Laoder) was not set, logback was unable to located its - default configuraiton files. Logback now uses the class loader that - loaded logback itself to locate its resources instead of the - TCCL. This approach is simpler and deemed to cover more - environments, i.e. more widely applicable. -

- - -

Fixed issue LBGENERAL-24 - reported by Hung Tang. SMTPAppender now supports plain - username/password authentication as well as both the STARTTLS - command and SSL connections. -

- - -

Fixed issue LBCLASSIC-48 - reported by Peter Royal. SyslogAppender now correctly outputs hours - as 0-23 and not as 1-12 as previously. -

- -

Added a new TurboFilter called DynamicThresholdFilter which can - filter events depending on MDC values based on a variery of criteria - such as company name, product or the end user. This filter was - contributed by Ralph Goers in LBCLASSIC-53. -

- - -
- - - -

26th of March 2008 - Release of version 0.9.9

- -

MDC data in now inherited by child threads. This behaviour was - already specified in the javadocs. The issue was raised by Martin - Benda in bug - 64 and independently by Peter Huber. -

- -

Logback no longer includes retro-weaver generted jars for JDK - 1.4. There seemes to be little interest in JDK 1.4 builds. Calling - retro-weaver increases logback's build time by a few seconds each - time – seconds in which we can do more productive things. -

- -

Fixed bug - 104, silly but but nonetheless serious copy-and-paste errors in - the c.q.l.classic.Logger class, reported by Joern Huxhorn. -

- -

Having been replaced by SimpleSocketServer, the - SocketServer class has been removed. -

- -

Fixed bug - 105, sockets created by SocketAppenderBase is now - closed, reported by Joern Huxhorn. More generally, - SimpleSocketServer is much more careful to track open - client connections and to close them. -

- -

Fixed bug - 110 in relation with the requestParameterMap field - in AccessEvent - reported by Joern Huxhorn. -

- -

Fixed - SLF4J bug 66 in relation with caller data when using - log4j-over-slf4j - reported by Frnack Routier. -

- -

Fixed bug - 129 reported by Michael Franz. As a result, Joran now supports - nested as well as multiple file inclusions. -

- -

Fixed bug - 100 reported by Joern Huxhorn. At serialization time, object - array passed as parameter, when the LoggingEvent is are now - serialized as strings. -

- -

Fixed bug - 109 reported by Joern Huxhorn. There should no longer be any - NullPointerExceptions thrown by deserialized - AccessEvent instances. -

- -

Fixed bug - 8 reported by Sebastien Pennec. The documentation has been - updated to reflect the fact that that in the context of conversion - patterns the percent sign carries special meaning, in order to - include the percent sign as a literal, it must be escaped with a - backslash. -

- -

Fixed bug - 52 reported by Kenichi Masuko. The bug has been fixed on March - 8th, 2007. Starting with this release, Joran will support the - injection of any enum tpye, not just FilterReply. -

- -
- - -

22th of August 2007 - Release of version 0.9.8

- -

This version of logback synchronizes with SLF4J version 1.4.3. In - particular, logback now natively supports SLF4J's MDC API introduced - in SLF4J version 1.4.1. If you are using SLF4J version 1.4.1 or - later please make sure upgrade to logback version 0.9.8 or later. -

- -

Fixed a number of documentation related bugs, in particular bug 90 reported - by Luc Maisonobe and bug 88 reported - by Sebastian Davids. -

- -

It is now possible to include configuration file fragments (in - XML) as a resource. Previously, it was only possible to include a - file by specifying a path to a file or a URL. This feature was - requested by Michael Newcomb in bug 89. -

- -

Fixed caller data extraction problem as reported in bug 78 by Hans - van der Meer. -

- -

The LoggingEvent class' constructor now correctly takes into - account the argument array passed by the user. This problem was - reported in bug - 85 by Robert Christian. -

- -
- - -

29th of May 2007 - Release of version 0.9.7

- - -

This release corrects packaging bugs 75 and 76 related to - the migration of logback to SLF4J version 1.4.0. There are no other - changes. -

- - -
- -

23rd of May 2007 - Release of version 0.9.6

- - -

Logback is now aligned and compatible with SLF4J version 1.4.0, - thus correcting bug 73 as - reported by Andy Gerweck. -

- -

Fixed NoClassDefFoundError problem when running - under JDK 1.4 as - reported by Brian Suksomwong. -

- -

Fixed bug - 63 as reported by La Canea Rosario. Calling log4j (bridge) with - the trace level will no longer cause an IllegalStateException to be - thrown. -

- -

Fixed bug - 70 as reported by Dirk Ooms. The %throwable conversion word is - now recognized as documented in the logback manual. Moreover, the - manual now mentions the %nopex word which can be used to force - PatternLayout to ignore the exception contained in the - logging request. -

- - -

As in most releases, the documentation has been improved.

- -
- - -

April 2nd, 2007 - Release of version 0.9.5

- -

Fixed methods isInfoEnabled, - isWarnEnabled and isErrorEnabled methods - in ch.qos.logback.classic.Logger class which failed to - work correctly. This bug was reported today by Pavel Kral on the - slf4j-user list. -

- -

Contrary to previous versions of logback, the various - Logger.isXYZEnabled(Marker) methods now take into account the marker - information passed as parameter. -

- - -

As discussed in bug 54, during - automatic initialization, it makes better sense to first check for - logback-test.xml file and only if that fails, to check for - logback.xml. Maven2 will guarantee that the - logback-test.xml file, if places undder test/resources will not be - included in the artifact it produces. -

- - -
- -

March 29th, 2007 - Release of version 0.9.4

- -

Significant bug fixes made to c.q.l.access.TeeFilter - and Co. Images and other binary files are now intercepted and - replayed correctly. As for "x-www-form-urlencoded" post requests, - their input buffer is left untouched. In a best-effort attempt, the - input buffer for "x-www-form-urlencoded" post requests is later - reconstructed through the request parameters. However, it may differ - from the original buffer. -

- -

The logback team released today the first version of a plugin for - Eclipse that allows developpers to visualize logs generated by a - running application. It offers several nice features. Please check - the console plugin-in guide for - more details. -

- - -

March 20th, 2007 - Release of version 0.9.3

- -

Includes in configuration files are now supported by Joran, - logback's configuration framework. A file can contain an - include element that has a file or url - attribute pointing to a configuration file. See the chapter about - configuration in the logback's online manual for more - information. -

- -

Corrected bug 53 reported by Wilkins Poe. There is now a dependencies page that shows the - requirements of each of logback's modules. -

- -

After a - discussion on the SLF4J mailing list started by Franck Routier, - a correction has been made when logging using the - JCL104-over-slf4j module. Logback now correctly shows the - caller location information. -

- -

As in most logback releases, the documentation has been improved. -

- - -

March 5th, 2007 - Release of version 0.9.2

- -

The documentation is now in the docs/ directory to allow an - easier access to the logback manual and website for offline viewing. -

- -

March 5th, 2007 - Release of version 0.9.1

- -

Logback-class now depends on SLF4J version 1.3.0 instead of - 1.2.

- -

Numerous improvements to the documentation.

- -

Bug #46 - reported by Mark Renyolds has been fixed. The - TimeUtilTest should now run fine under any time - zone.

- -

Bug - #45, also reported by Mark Reynolds, has been fixed. There - should be no ClassCastException thrown anymore when - passing an Object to the printing methods using the - log4j-bridge module.

- -
- -

January 31st, 2007 - Release of version 0.9

- -

This version contains a new component, namely the - ContextSelector, that provides context separation and - management when logback is used by several web-apps running under - the same server. A new - chapter was added to the logback manual to detail the use of the - ContextSelector, along with its associated components. -

- -

The JMXConfigurator has been improved. It now shows - the context's Status objects, which lets users check the internal - state of logback. -

- -

The logback manual's chapter 2, about logback's architecture, has been - updated with two sections: Under the hood and Performance. -

- -
- -

January 23th, 2007 - Release of version 0.8.1

- -

This version contains new components in the Access module, - allowing users to display the full HttpServletRequest or - HttpServletResponse of an access event. -

- -

The documentation section has been updated. The short - introduction was split into the chapter 1 and chapter 2 of the - logback manual. The chapters about Appenders and Layouts have been - updated to document new components of logback. -

- -

A demonstration webApp presenting logback's major components is - available. A document explains how to run it, and provides a - step-by-step visit of the demo. -

- -

A first translation of logback jars to JDK1.4 is present in - this release. -

- - -
- -

January 12th, 2007 - Release of version 0.8

- -

This version contains a whole new chapter, namely Chapter 3, - about logback configuration. Several other documentation pages - have been improved. -

- -

Logback now uses Generics in many components. -

- -

Several new components have been added to logback. A JMX - Configurator now allows users to see and modify loggers or reload - configuration among other possibilities. A document about this configurator is - available in the corresponding - section of the site. We'd like to thank Sebastian Davids for his - ideas and contributions to this component. -

- -

A JMSTopicAppender and JMSQueueAppender are now available, as - well as two new filters: LevelFilter and ThresholdFilter. A - refactoring was done in the filters objects to ease the - implementation of custom filters. -

- -
- - -

December 19th, 2006 - Release of version 0.7.1

- -

Version 0.7.1 of logback has been released. -

- -

This version contains more detailled information about logback - access module, and its JMX components. A dedicated page explains how to configure and - use logback access in Tomcat and Jetty, and access some of its - components via JMX. -

- -
- -

December 18th, 2006 - Release of version 0.7

- -

Version 0.7 of logback has been released.

- -

Logback now ships with a new module: log4j-bridge. This - new module can be used to intercept log4j calls and redirects them - to logback components. More information about this module can be - found in the corresponding documentation - page. -

- -

The documentation has been vastly updated. Two new chapters, - namely Filters and MDC, are available in the manual section. -

- -
- -

November 30th, 2006 - Release of version 0.6

- -

Version 0.6 of logback has been released. -

- -

Logback classic now supports automatic configuration, allowing - test and production environment - configuration. TurboFilters make their first appearance - in a logback release. They provide ultra-fast filtering - possibilities. The logging context now supports listeners which - will be contacted each time the context is reset or - started. SMTPAppender allows for much more flexible - configuration than before. -

- -

In logback access, new Appenders are available, namely - SocketAppender and DBAppender. Logback - access now supports filtering and event evaluations. A - CountingFilter has been added. It provides statistical - views of server access, reachable via JMX. -

- -

The documentation has also been improved. A complete new chapter - has been added about Appenders, the short introduction to logback - classic has been updated and a new module, containing many - configuration examples has been added. -

- -

Logback now uses continous integration in its development. -

- -

Tests have been improved, many new have been added. This release - also provides some bug fixes. -

- -
- -

October 26th, 2006 - Release of version 0.5

- -

Version 0.5 of logback has been released. -

- -

This release offers a important improvements in Joran. In - particular, Joran can now replay configuration elements. -

- -

As in the previous release, a major area of work is the - documentation which is being continously improved. -

- -
- -

October 9th, 2006 - Release of version 0.4

- -

Version 0.3 of logback has been released. -

- -

This release includes an improved access module, with specific - implementations for the Jetty and Tomcat servers. Documentation was - also added to show how to integrate logback-access with Jetty. -

- -

As for the classic module, several appenders and layouts have - been added or improved. The error reporting of logback has also - been enhanced, presenting the user with a link to an online page - explaining possible reasons for the error. -

- -

A joran documentation was added, with examples in the core - module. -

- -
- -

September 8th, 2006 - Release of version 0.3

-

- Version 0.3 of logback has been released. -

- -

This release offers several new Appenders, support for Mapped - Diagnostic Context, improved tests and documentation
-

- -

In response to a bug report by Rickard Nilsson on the logback - mailing list, a bug affecting parametrized logging was fixed. -

- -

We also released a PropertiesTranslator - webapp that converts log4j.properties files to joran - configuration files (in XML format).
-

- -
- -

August 23th, 2006 - Release of version 0.2.5

- -

Version 0.2.5 of logback has been released.

- -

This release offers better documentation. With a number of - correction mande in the short introduction to logback-classic. -

- -
- - -

August 15th, 2006 - Release of version 0.2

- -

Version 0.2 of logback has been released.

- -

It offers better tests, a few more functionalities, and enhanced - documentation. We also improved the site design to make it simpler - and more efficient. -

- -
- -

July 26th, 2006 - Release of version 0.1

- -

Version 0.1 of logback has been released.

- -
- -

February 9th, 2006 - Logback web-site goes live

- -

The logback web-site goes live on the 9th of February. At its - present state, it is pretty primitive but updates will follow. -

- - - -
- - + + + + + + News + + + + + + + + + +
+ + +
+
+ +

Logback News

+ +

You can receive logback-related announcements by subscribing to + the QOS.ch + announce mailing list.

+ +
+ +

13th of November 2009 - Release of version 0.9.18

+ +

After a very long investigation resulting in somewhat a better + understanding of licensing issues, logback is now dual-licensed under the EPL 1.0 and LGPL + 2.1. +

+ +

Due to a clerical error LBCORE-26 has + re-raised its ugly head. It has now been tamed for good.

+ +

Fixed Private-Package and Export-Package sections in + logback-classic.jar MANIFEST as reported in LBCLASSIC-165 + and LBCLASSIC-121 + by applying the relavant patches supplied by Hugues Malphettes. +

+ +

Made the OSGi import declerations for Janino and javax optional + as proposed by David Varnes in LBCORE-101.

+ +

ReconfigureOnChangeFilter did not pick up changes + for configuration files containing spaces. This issue was reported + in LBCORE-119 + by Anders Wallgren. +

+ +

When ill-formed configuration files fragments were included in + another configuration file, the included file was not closed + correctly. This issue was reported in LBCORE-122 by + Michael Franz. +

+ +

JaninoEventEvaluator now passes the throwable associated with + an event as a java.lang.Throwable instead of an + IThrowableProxy. This fixes LBCLASSIC-155 + as reported by Hontvári József. See EvaluatorFilter + documentation for more details.

+ +

The name of the log file nested within .zip archives was + incorrectly set to be that of the tmp file logback creates during + compression. Anders Wallgren reported and posted an appropriate + patch for this problem in LBCORE-98. The + nested file is now named after the zip archive file. Analysis + showed that this was an appropriate strategy in all the cases we + considered.

+ +

Fixed LBCLASSIC-149. The + ContextNameConverter now correctly uses the context name of the + event instead of its own context name. +

+ +

When a logger is named after an inner class, the '$' is used as + a separator, instead of the usual '.'. This fixes the level + inheritence issue described in LBCLASSIC-102 + and as reported by Joern Huxhorn.

+ +
+ +

9th of August 2009 - Release of version 0.9.17

+ +

PackagingDataCalculator now correctly deals with + NoClassDefFoundError thrown by class loaders. This + fixes LBCLASSIC-125 + reported by Roland Klein and independently by Didier Besset. +

+ +

In configuration files, all tags names associated with explicit + actions are now case-insensitive. This should diminish + case-related errors users may make when writing configuration + files. Tag names associated with implicit actions which are + closely linked to the actual Java class being configured, still + need to follow the camelCase convention. If you are unsure which + case to use for a given tag name, just follow the camelCase + convention for tag names which should be correct in most + cases.

+ +

It is now possible to create uniquely named files by + timestamp. Such files are appropriate for log files associated + with batch applications. This enhancement fulfills LBCORE-91 as + requested by Rick Beton and Szel Zoltan. +

+ +

Append mode is now mandatory in + RollingFileAppender. This was already the default and + truncation mode is unreasonable in most cases. For example, in + truncate mode when an application stops and is quickly re-started, + any pre-existing log file for the current period will be lost.

+ +

The activeFile field in + RollingFileAppender is now properly updated, fixing + LBCORE-90 as + reported by Valery Shorin.

+ + +

The TimeBasedTriggeringPolicy has been heavily + refactored. It is now possible to trigger rolling simultaenously + by time and + by size, fixing LBCORE-61. +

+ +

Fixed LBCLASSIC-145 + reported by Joern Huxhorn. The LoggingEventVO class + now correctly populates its callerData field if the original + ILoggingEvent already has it.

+ +
+ +

15th of July 2009 - Release of version 0.9.16

+ +

In addition to nifty new features, this release contains + several important internal changes. Given the importance of some + of those internal changes, this release may be less stable + than previous logback releases.

+ +

In logback-classic, LoggingEvent + now implements the ILoggingEvent + interface. All logback-classic components expect to process + ILoggingEvent instances. Moreover, events which sent + to a remote host are now of type LoggingEventVO. +

+ +

Logback-classic will now automatically + re-configure itself when its configuration file is + modified. This enhancement was requested in LBCORE-59 by + Michael Osipov.

+ +

FileAppender and its derived class RolllingFileAppender are now + based on a finer-grain synchronization model. This change is aimed + at reducing various synchronization related bugs, namely LBCLASSIC-135 + and its various sub-tasks. +

+ +

Fixed a bug in the localLevelReset() method in the + Logger class which inadvertently used the DEBUG_INT + value in the org.slf4j.spi.LocationAwareLogger interface instead + of the DEBUG_INT value in ch.qos.logback.classic.Level class. The + issue was first identified by Andy Ruch in + a message to the logback-user list +

+ +

If the logger name had 12 or more segments, a the logger + conversion specified would throw an + ArrayIndexOfBounds exception. Lukas Zapletal has + kindly reported this problem in LBCLASSIC-110 + and provided a test case. +

+ +

A new discriminator class called "ContextBasedDiscriminator" + allows SiftingAppender to separate logging based on the context + name. This fits nicely with the requirements expressed in LBCLASSIC-117 + by Rick Janda. +

+ +

When a context is reset, then its object and property maps are + now cleared. This fixes LBCORE-104 + reported by Johan Bos. +

+ +

Fixed LBCORE-105. Configuration + files placed in jar files will no longer lock the jar file. This + issue was initially reported for log4j in bug + 47465 Mark Thomas. +

+ +

Fixed LBCORE-94. While + configuring a RollingFileAppender, if the File property is + declared after any rolling or triggering policies, then logback will + now generate an error status message. +

+ +

Fixed LBCLASSIC-134 + reported by Darryl Smith. DuplicateMessageFilter will + now behave correctly when invoked via + Logger.isXXXEnabled methods. +

+ +

Fixed LBCORE-107, + incorrectly set context information for the + NestedBasicPropertyIA instance in Joran, reported by + Lóránt Pintér. +

+ +

Fixed LBCLASSIC-109, + reported by Andrew Ruch when a logger context was reset, the trace + level was erroneously enabled. +

+ +
+ +

12th of February 2009 - Release of version 0.9.15

+ +

When the reset() method in LoggerContext is + called, registered turbo filters are first stopped before being + unregistered. This fixes LBCLASSIC-89 + reported by Alexis Morillo. +

+ +

Added a servlet for viewing internal status messages as an HTML + table. Two separate implementations are available; one for logback-classic + and the other for logback-access.

+ +

Added the clear() mthod to the + StatusManager interface. After reconfiguration, it + may be desirable to clear the status list maintained by a + StatusManager. This change was requested by Alexis + Morillo in LBCORE-77. +

+ +

Fixed problem LBCLASSIC-104 + related to loss of MDC information in deferred logging events. +

+ +

Fixed issue LBCLASSIC-101. Logback + jar files now include full OSGi bundle information in their + manifests. This information is automatically added by Apache + Felix' Maven bundle plug-in. The generated manifest files contain + an appropriate Bundle-RequiredExecutionEnvironment directive, + fixing LBGENERAL-8. +

+ +

The setter and getter methods for the layout property in + AppenderBase class now have reasonable default + implementations, instead of nop previously. This change was + requested by Thilo Tanner in LBCORE-56. +

+ + +

Added log4j.dtd compatible XMLLayout + as requested in LBCLASSIC-22. +

+ +

New chapter on Joran.

+ +
+ +

29th of December 2008 - Release of version 0.9.14

+ +

Corrected a serious dead-lock problem occuring during + configuration. It was reported in LBCLASSIC-81 by + Holger Mense.

+ +

Corrected thread leakage observed with + TimeBasedRollingPolicy's + AsynchronousCompressor. This bug was reported in LBCORE-78 by Szel + Zoltan.

+ +

Added DuplicateMessageFilter, + a turbo filter which detects duplicate messages, and beyond a + certain number of repetitions, drops repeated messages.

+ +

Added a new appender called SiftingAppender. As + its name intimates, a SiftingAppender + can be used to separate (or sift) logging according to a given + runtime attribute. For example, SiftingAppender can + separate logging events according to user sessions, so that the + logs generated by each user go into distinct log files, one log + file per user. +

+ +

BasicStatusManager's internal buffer is now split + into two parts, the header part and the tail part. The header part + stores the fist H status messages whereas the tail part stores the + last T messages. At present time H=T=150, although these values may + change in future releases.

+ +

Fixed NullPointerException thrown when calling + setContextMap on a fresh MDC. Issue was + reported by Francois Terrier. +

+ + +

Evaluators are now wired into an appender automatically + (implicit rules) without the help of + EvaluatorAction. EvaluatorAction is now only needed + for global evaluator elements. It follows that name attribute is + necessary only for global evaluators. Embedded evaluators no + longer need a name. This change fixes LBCLASSIC-100. In + addition, EvaluatorAction has been modified to accept + evaluators of any type and not just instances of + JaninoEvaluator. +

+ +

Logback-classic default configuration process will now + automatically print status data on the console in case of warnings + as well as errors. Previously, status data was printed only in + case of errors.

+ +

ContextInitializer will now print the url of the + configuration it is using. This should help reduce confusion when + multiple config files are found on the class path. This change + resolves LBCLASSIC-55 + reported by Anton Tagunov and Henric Larsson. +

+ +

In case multiple configuration files are found on the class + path, ContextInitializer will now emit a + warning. This fixes LBCLASSIC-85 + filed by Szel Zoltan. +

+ +

HTMLLayout now honors custom conversion words, + thus fixing LBCORE-74 as + reported by Natan Cox.

+ +

Fixed LBCORE-69 as + reported by Andrey Rybin. SMTPAppenderBase now has + support for charset encodings so that email messages can contain + characters beyond US-ASCII. +

+ +

SMTPAppender in logback-classic now defaults to + OnErrorEvaluator instead of a janino-based + evaluator. Thus, by default SMTPAppender no longer + depends on Janino.

+ +

Added UnsynchronizedAppenderBase class based on Ralph Goers' + contribution in LBCORE-58. Note + that AppenderBase remains unchanged. Appenders which + need to handle synchronization on their own can do so by deriving + from UnsynchronizedAppenderBase.

+ +

5th of December 2008 - Release of version 0.9.13

+ +

A NullPointerException was being thrown when a the + level of a logger was set to null. The logger in question had to + have children. This problem was reported in LBCLASSIC-91 + by Mateusz Jedruch. +

+ +

4th of December 2008 - Release of version 0.9.12

+ +

Fixed bug + LBCORE-26 reported by Tsutomu YANO and independently by + Hontvári József and Gamaliel + Amaudruz. RollingFileAppender when used in conjunction + with DateBasedRollingPolicy will rollover existing log + files at initialization if their timestamp warrants it. +

+ +

Added support for file appending in prudent mode. Thus, + multiple FileAppender instances running on multiple + JVMs can safely write to the same log file. With certain + limitations, prudent mode extends to + RollingFileAppender. +

+ + +

Fixed LBCLASSIC-83. + It is now possible to set the level of a logger to null, even if + it was previously set to a non-null level. Previously, a + NullPointerException would be thrown. +

+ +

In reponse to LBCLASSIC-61, LBCLASSIC-33, LBCLASSIC-24 and + LBCLASSIC-14 + JMXConfigurator has been redesigned. +

+ +

Fixed LBGENERAL-22. The + log4j.properties + translator web-application has been significatnly refactored. +

+ +

Fixed improvement request LBCLASSIC-59 + relation to StatusListeners, originally submitted by Anton Tagunov. +

+ +

The logger and class name converters now consider zero as + having special meaning, and will return the simple class name, + removing the package name prefix. This feature was asked by + Silvano Maffeis.

+ +

In response to LBCLASSIC-54 + support for turbo filters has refactored. The present code is safe + under concurrent access while still offering good performance. +

+ +

Fixed LBCORE-43 reported + by Bruno Navert. Configuration files can now look up property + files from classpath resources. +

+ +

Fixed LBCLASSIC-86 + related to AccessControlException thrown when run in + a JVM with a SecurityManager. +

+ +

Invoking the LoggerContext.reset() method resets + logger levels to their default value, that is DEBUG + for the root logger and null for all other + loggers. This was requested in LBCLASSIC-90 by + Mateusz Jedruch. +

+ + + +

Fixed bug + LBCLASSIC-69 reported by Anton Tagunov. The + LevelToSyslogSeverity now correctly handles the TRACE level. +

+ +

Fixed bug + LBCLASSIC-57 reported by Anton Tagunov. SyslogAppender could + overwhelm the Syslog server with very large messages. SyslogAppender + now limits its message size to 256K. +

+ +

Logback now supports setting the logger context + name as well as inserting variables stored in JNDI as + properties. +

+ +

Fixed issue LBCLASSIC-49 + reported by Oliver Lietz. The getLogger() method in + LoggerContext class will now throw an + IllegalArgumentException when invoked with a null + argument. +

+ + +
+ +

28th of October 2008 - Release of version 0.9.11

+ +

Fixed LBCLASSIC-77 + reported independenly by Gianni Doe, Yannick Haudry and Yossi Shaul. + The childValue() method of CopyOnInheritThreadLocal + class part of MDC code no longer throws a + NullPointerException. +

+ +
+ +

27th of October 2008 - Release of version 0.9.10

+ +

In case of errors during initialization, logback-classic now + automatically prints out its internal status. This has been + a frequently requested feature. +

+ +

The LogbackValve in logback-access (ensuring integration with + Tomcat), will now systematically print its internal status upon + initialization, unless told to be quiet. This greatly helps + troubleshooting the configration of logback-access under Tomcat. +

+ +

Fixed bug + 147 which occured when the user inadvertently attempted to set + the layout of a SyslogAppender. The code now actively + prevents this. Documenation has been updated to reflect the change. +

+ +

Fixed bug + LBCLASSIC-56 originally reported by Michel Colette. Backslash + characters are now correctly interpreted in filename patterns. +

+ +

The TurboFilterChain in a LoggerContext is now + cleared when the reset() method is called. This + problem was reported on May 1st, 2008, by Julia Hu on the logback + developpers list. +

+ + + +

Fixed issue LBCORE-48. During + rollover, compression of large files would bring all logging to a + halt. In this latest release, the rolled over file is first renamed, + which is a relatively fast operation, and only then is the renamed + file compressed asyncronously (in a separate thread). +

+ +

Fixed issue LBCORE-11. It is now + possible to instruct TimeBasedRollingPolicy to delete old files, + thus controlling then number of archived log files.

+ +

Fixed issue LBCORE-42. If the + parent directory of the log file does not exist, then FileAppender + will create it, including any necessary but nonexistent parent + directories. +

+ +

Fixed LBCORE-15 + reported by Klaus Unger and others. DBAppender should now work with + Oracle 9, 10g and 11g, regardless of the JDBC driver type used. +

+ +

Fixed issue LBCORE-17 reported by + Thorbjørn Ravn Andersen. Logback now relies on Geronimo JMS + API specifications instead of Sun's JMS API specification, the + latter requiring manual installation. With Geronimo JMS, logback can + be built using Maven without needing to manually install any + dependencies. +

+ +

Fixed issue LBCORE-23. In + PatternLayout, parenthesis can be used to group conversion + patterns. It follows that the '(' and ')' carry special meaning and + need to be escaped to be used as literals. This is now properly + documented. +

+ +

The location of the default configuration file can be specified + by a system property. This feature was requested in LBCORE-32 by Ted + Graham, Matt Fowles, Ivan Biddles and Ralph Goers. +

+ +

Fixed issue LBCORE-55 reported by + Natan Cox. WriterAppender now outputs its presentation + footer and file footer in the the correct order. +

+ + +

Fixed issue LBCORE-27 reported by + Peter Royal. SMTPAppender now outputs its presentation + footer and file footer in the the correct order. +

+ + + +

Fixed issue LBCLASSIC-67 + reported by Alessandro Fustini. SMTPAppender now correctly + configures the layout used to format the subject line of the + outgoing email. It no longer appends a lengthy stack trace to the + subject line. +

+ + +

Fixed issue LBCLASSIC-68 + reported by Gili Tzabari. In environments where the TCCL (Thread + Context Class Laoder) was not set, logback was unable to located its + default configuraiton files. Logback now uses the class loader that + loaded logback itself to locate its resources instead of the + TCCL. This approach is simpler and deemed to cover more + environments, i.e. more widely applicable. +

+ + +

Fixed issue LBGENERAL-24 + reported by Hung Tang. SMTPAppender now supports plain + username/password authentication as well as both the STARTTLS + command and SSL connections. +

+ + +

Fixed issue LBCLASSIC-48 + reported by Peter Royal. SyslogAppender now correctly outputs hours + as 0-23 and not as 1-12 as previously. +

+ +

Added a new TurboFilter called DynamicThresholdFilter which can + filter events depending on MDC values based on a variery of criteria + such as company name, product or the end user. This filter was + contributed by Ralph Goers in LBCLASSIC-53. +

+ + +
+ + + +

26th of March 2008 - Release of version 0.9.9

+ +

MDC data in now inherited by child threads. This behaviour was + already specified in the javadocs. The issue was raised by Martin + Benda in bug + 64 and independently by Peter Huber. +

+ +

Logback no longer includes retro-weaver generted jars for JDK + 1.4. There seemes to be little interest in JDK 1.4 builds. Calling + retro-weaver increases logback's build time by a few seconds each + time – seconds in which we can do more productive things. +

+ +

Fixed bug + 104, silly but but nonetheless serious copy-and-paste errors in + the c.q.l.classic.Logger class, reported by Joern Huxhorn. +

+ +

Having been replaced by SimpleSocketServer, the + SocketServer class has been removed. +

+ +

Fixed bug + 105, sockets created by SocketAppenderBase is now + closed, reported by Joern Huxhorn. More generally, + SimpleSocketServer is much more careful to track open + client connections and to close them. +

+ +

Fixed bug + 110 in relation with the requestParameterMap field + in AccessEvent - reported by Joern Huxhorn. +

+ +

Fixed + SLF4J bug 66 in relation with caller data when using + log4j-over-slf4j - reported by Frnack Routier. +

+ +

Fixed bug + 129 reported by Michael Franz. As a result, Joran now supports + nested as well as multiple file inclusions. +

+ +

Fixed bug + 100 reported by Joern Huxhorn. At serialization time, object + array passed as parameter, when the LoggingEvent is are now + serialized as strings. +

+ +

Fixed bug + 109 reported by Joern Huxhorn. There should no longer be any + NullPointerExceptions thrown by deserialized + AccessEvent instances. +

+ +

Fixed bug + 8 reported by Sebastien Pennec. The documentation has been + updated to reflect the fact that that in the context of conversion + patterns the percent sign carries special meaning, in order to + include the percent sign as a literal, it must be escaped with a + backslash. +

+ +

Fixed bug + 52 reported by Kenichi Masuko. The bug has been fixed on March + 8th, 2007. Starting with this release, Joran will support the + injection of any enum tpye, not just FilterReply. +

+ +
+ + +

22th of August 2007 - Release of version 0.9.8

+ +

This version of logback synchronizes with SLF4J version 1.4.3. In + particular, logback now natively supports SLF4J's MDC API introduced + in SLF4J version 1.4.1. If you are using SLF4J version 1.4.1 or + later please make sure upgrade to logback version 0.9.8 or later. +

+ +

Fixed a number of documentation related bugs, in particular bug 90 reported + by Luc Maisonobe and bug 88 reported + by Sebastian Davids. +

+ +

It is now possible to include configuration file fragments (in + XML) as a resource. Previously, it was only possible to include a + file by specifying a path to a file or a URL. This feature was + requested by Michael Newcomb in bug 89. +

+ +

Fixed caller data extraction problem as reported in bug 78 by Hans + van der Meer. +

+ +

The LoggingEvent class' constructor now correctly takes into + account the argument array passed by the user. This problem was + reported in bug + 85 by Robert Christian. +

+ +
+ + +

29th of May 2007 - Release of version 0.9.7

+ + +

This release corrects packaging bugs 75 and 76 related to + the migration of logback to SLF4J version 1.4.0. There are no other + changes. +

+ + +
+ +

23rd of May 2007 - Release of version 0.9.6

+ + +

Logback is now aligned and compatible with SLF4J version 1.4.0, + thus correcting bug 73 as + reported by Andy Gerweck. +

+ +

Fixed NoClassDefFoundError problem when running + under JDK 1.4 as + reported by Brian Suksomwong. +

+ +

Fixed bug + 63 as reported by La Canea Rosario. Calling log4j (bridge) with + the trace level will no longer cause an IllegalStateException to be + thrown. +

+ +

Fixed bug + 70 as reported by Dirk Ooms. The %throwable conversion word is + now recognized as documented in the logback manual. Moreover, the + manual now mentions the %nopex word which can be used to force + PatternLayout to ignore the exception contained in the + logging request. +

+ + +

As in most releases, the documentation has been improved.

+ +
+ + +

April 2nd, 2007 - Release of version 0.9.5

+ +

Fixed methods isInfoEnabled, + isWarnEnabled and isErrorEnabled methods + in ch.qos.logback.classic.Logger class which failed to + work correctly. This bug was reported today by Pavel Kral on the + slf4j-user list. +

+ +

Contrary to previous versions of logback, the various + Logger.isXYZEnabled(Marker) methods now take into account the marker + information passed as parameter. +

+ + +

As discussed in bug 54, during + automatic initialization, it makes better sense to first check for + logback-test.xml file and only if that fails, to check for + logback.xml. Maven2 will guarantee that the + logback-test.xml file, if places undder test/resources will not be + included in the artifact it produces. +

+ + +
+ +

March 29th, 2007 - Release of version 0.9.4

+ +

Significant bug fixes made to c.q.l.access.TeeFilter + and Co. Images and other binary files are now intercepted and + replayed correctly. As for "x-www-form-urlencoded" post requests, + their input buffer is left untouched. In a best-effort attempt, the + input buffer for "x-www-form-urlencoded" post requests is later + reconstructed through the request parameters. However, it may differ + from the original buffer. +

+ +

The logback team released today the first version of a plugin for + Eclipse that allows developpers to visualize logs generated by a + running application. It offers several nice features. Please check + the console plugin-in guide for + more details. +

+ + +

March 20th, 2007 - Release of version 0.9.3

+ +

Includes in configuration files are now supported by Joran, + logback's configuration framework. A file can contain an + include element that has a file or url + attribute pointing to a configuration file. See the chapter about + configuration in the logback's online manual for more + information. +

+ +

Corrected bug 53 reported by Wilkins Poe. There is now a dependencies page that shows the + requirements of each of logback's modules. +

+ +

After a + discussion on the SLF4J mailing list started by Franck Routier, + a correction has been made when logging using the + JCL104-over-slf4j module. Logback now correctly shows the + caller location information. +

+ +

As in most logback releases, the documentation has been improved. +

+ + +

March 5th, 2007 - Release of version 0.9.2

+ +

The documentation is now in the docs/ directory to allow an + easier access to the logback manual and website for offline viewing. +

+ +

March 5th, 2007 - Release of version 0.9.1

+ +

Logback-class now depends on SLF4J version 1.3.0 instead of + 1.2.

+ +

Numerous improvements to the documentation.

+ +

Bug #46 + reported by Mark Renyolds has been fixed. The + TimeUtilTest should now run fine under any time + zone.

+ +

Bug + #45, also reported by Mark Reynolds, has been fixed. There + should be no ClassCastException thrown anymore when + passing an Object to the printing methods using the + log4j-bridge module.

+ +
+ +

January 31st, 2007 - Release of version 0.9

+ +

This version contains a new component, namely the + ContextSelector, that provides context separation and + management when logback is used by several web-apps running under + the same server. A new + chapter was added to the logback manual to detail the use of the + ContextSelector, along with its associated components. +

+ +

The JMXConfigurator has been improved. It now shows + the context's Status objects, which lets users check the internal + state of logback. +

+ +

The logback manual's chapter 2, about logback's architecture, has been + updated with two sections: Under the hood and Performance. +

+ +
+ +

January 23th, 2007 - Release of version 0.8.1

+ +

This version contains new components in the Access module, + allowing users to display the full HttpServletRequest or + HttpServletResponse of an access event. +

+ +

The documentation section has been updated. The short + introduction was split into the chapter 1 and chapter 2 of the + logback manual. The chapters about Appenders and Layouts have been + updated to document new components of logback. +

+ +

A demonstration webApp presenting logback's major components is + available. A document explains how to run it, and provides a + step-by-step visit of the demo. +

+ +

A first translation of logback jars to JDK1.4 is present in + this release. +

+ + +
+ +

January 12th, 2007 - Release of version 0.8

+ +

This version contains a whole new chapter, namely Chapter 3, + about logback configuration. Several other documentation pages + have been improved. +

+ +

Logback now uses Generics in many components. +

+ +

Several new components have been added to logback. A JMX + Configurator now allows users to see and modify loggers or reload + configuration among other possibilities. A document about this configurator is + available in the corresponding + section of the site. We'd like to thank Sebastian Davids for his + ideas and contributions to this component. +

+ +

A JMSTopicAppender and JMSQueueAppender are now available, as + well as two new filters: LevelFilter and ThresholdFilter. A + refactoring was done in the filters objects to ease the + implementation of custom filters. +

+ +
+ + +

December 19th, 2006 - Release of version 0.7.1

+ +

Version 0.7.1 of logback has been released. +

+ +

This version contains more detailled information about logback + access module, and its JMX components. A dedicated page explains how to configure and + use logback access in Tomcat and Jetty, and access some of its + components via JMX. +

+ +
+ +

December 18th, 2006 - Release of version 0.7

+ +

Version 0.7 of logback has been released.

+ +

Logback now ships with a new module: log4j-bridge. This + new module can be used to intercept log4j calls and redirects them + to logback components. More information about this module can be + found in the corresponding documentation + page. +

+ +

The documentation has been vastly updated. Two new chapters, + namely Filters and MDC, are available in the manual section. +

+ +
+ +

November 30th, 2006 - Release of version 0.6

+ +

Version 0.6 of logback has been released. +

+ +

Logback classic now supports automatic configuration, allowing + test and production environment + configuration. TurboFilters make their first appearance + in a logback release. They provide ultra-fast filtering + possibilities. The logging context now supports listeners which + will be contacted each time the context is reset or + started. SMTPAppender allows for much more flexible + configuration than before. +

+ +

In logback access, new Appenders are available, namely + SocketAppender and DBAppender. Logback + access now supports filtering and event evaluations. A + CountingFilter has been added. It provides statistical + views of server access, reachable via JMX. +

+ +

The documentation has also been improved. A complete new chapter + has been added about Appenders, the short introduction to logback + classic has been updated and a new module, containing many + configuration examples has been added. +

+ +

Logback now uses continous integration in its development. +

+ +

Tests have been improved, many new have been added. This release + also provides some bug fixes. +

+ +
+ +

October 26th, 2006 - Release of version 0.5

+ +

Version 0.5 of logback has been released. +

+ +

This release offers a important improvements in Joran. In + particular, Joran can now replay configuration elements. +

+ +

As in the previous release, a major area of work is the + documentation which is being continously improved. +

+ +
+ +

October 9th, 2006 - Release of version 0.4

+ +

Version 0.3 of logback has been released. +

+ +

This release includes an improved access module, with specific + implementations for the Jetty and Tomcat servers. Documentation was + also added to show how to integrate logback-access with Jetty. +

+ +

As for the classic module, several appenders and layouts have + been added or improved. The error reporting of logback has also + been enhanced, presenting the user with a link to an online page + explaining possible reasons for the error. +

+ +

A joran documentation was added, with examples in the core + module. +

+ +
+ +

September 8th, 2006 - Release of version 0.3

+

+ Version 0.3 of logback has been released. +

+ +

This release offers several new Appenders, support for Mapped + Diagnostic Context, improved tests and documentation
+

+ +

In response to a bug report by Rickard Nilsson on the logback + mailing list, a bug affecting parametrized logging was fixed. +

+ +

We also released a PropertiesTranslator + webapp that converts log4j.properties files to joran + configuration files (in XML format).
+

+ +
+ +

August 23th, 2006 - Release of version 0.2.5

+ +

Version 0.2.5 of logback has been released.

+ +

This release offers better documentation. With a number of + correction mande in the short introduction to logback-classic. +

+ +
+ + +

August 15th, 2006 - Release of version 0.2

+ +

Version 0.2 of logback has been released.

+ +

It offers better tests, a few more functionalities, and enhanced + documentation. We also improved the site design to make it simpler + and more efficient. +

+ +
+ +

July 26th, 2006 - Release of version 0.1

+ +

Version 0.1 of logback has been released.

+ +
+ +

February 9th, 2006 - Logback web-site goes live

+ +

The logback web-site goes live on the 9th of February. At its + present state, it is pretty primitive but updates will follow. +

+ + + +
+ + diff --git a/logback-site/src/site/pages/repos.html b/logback-site/src/site/pages/repos.html index d2867fd970768426aed6cf5c2319c194badce5bc..22f323cc75d8cf11525ce77b7a290ab6e14e1f96 100644 --- a/logback-site/src/site/pages/repos.html +++ b/logback-site/src/site/pages/repos.html @@ -1,105 +1,105 @@ - - - - - - Repository - - - - - - - -
- - -
-
- - -
-

Source Repository

-
- -

We store the project's source code in a revision control system - called Git. Developers have write access to the repository, - enabling them to make changes to the source code. Everyone else - has read-access to the repository. Thus, anyone can check out - latest development version of the software. Note that the latest - version in the repository may not work as expected. It may even - not compile. If you are looking for a stable release, then - download an official distribution. -

- -

There are several ways to access the git repository:

- -

Web Access

- -

If you just wish to browse around or download a few individual - files, you can do so with your web-browser: -

- - - - - - - - - - - - - -
on github - - http://github.com/ceki/logback/tree/master (slow but rich) -
on git.qos.ch - http://git.qos.ch/gitweb/?p=logback.git;a=summary (fast but minimal) -
- -

Cloning

- - -

Anyone can clone logback's source repository. All you need is a - git client. To clone logback's git repository, issue one of the - two following commands:

- - - - - - - - - - - - - - - - - - - - - - -
transport protocolgit clone command
gitgit clone git://git.qos.ch/logback
gitgit clone git://github.com/ceki/logback.git
httpgit clone http://git.qos.ch/logback/
- - -

In principle, the repositories listed above have identical - contents.

- -

Subversion

- -

Previously, we relied on Subversion as our version control - system. Git is considerably better.

- - -
- - + + + + + + Repository + + + + + + + +
+ + +
+
+ + +
+

Source Repository

+
+ +

We store the project's source code in a revision control system + called Git. Developers have write access to the repository, + enabling them to make changes to the source code. Everyone else + has read-access to the repository. Thus, anyone can check out + latest development version of the software. Note that the latest + version in the repository may not work as expected. It may even + not compile. If you are looking for a stable release, then + download an official distribution. +

+ +

There are several ways to access the git repository:

+ +

Web Access

+ +

If you just wish to browse around or download a few individual + files, you can do so with your web-browser: +

+ + + + + + + + + + + + + +
on github + + http://github.com/ceki/logback/tree/master (slow but rich) +
on git.qos.ch + http://git.qos.ch/gitweb/?p=logback.git;a=summary (fast but minimal) +
+ +

Cloning

+ + +

Anyone can clone logback's source repository. All you need is a + git client. To clone logback's git repository, issue one of the + two following commands:

+ + + + + + + + + + + + + + + + + + + + + + +
transport protocolgit clone command
gitgit clone git://git.qos.ch/logback
gitgit clone git://github.com/ceki/logback.git
httpgit clone http://git.qos.ch/logback/
+ + +

In principle, the repositories listed above have identical + contents.

+ +

Subversion

+ +

Previously, we relied on Subversion as our version control + system. Git is considerably better.

+ + +
+ + diff --git a/logback-site/src/site/pages/setup.html b/logback-site/src/site/pages/setup.html index 5af9d3ca6f1b46c6f0da3d8a13fe221540aac7db..4f5d9243a5c2e95d1955e1e8be63c34dc7e34995 100644 --- a/logback-site/src/site/pages/setup.html +++ b/logback-site/src/site/pages/setup.html @@ -1,88 +1,88 @@ - - - - - Setup - - - - - - - - - -
- -
- -
- - -

Classpath Setup

- -

In order to run the examples provided in the documentation, you - need to add the following jars to your class path: -

- -
    -
  • logback-core-${version}.jar
  • -
  • logback-classic-${version}.jar
  • -
  • logback-examples-${version}.jar
  • -
  • slf4j-api-${slf4j.version}.jar
  • -
- -

The logback-*.jar files are part of the logback - distribution whereas slf4j-api-${slf4j.version}.jar ships - with SLF4J, a separate project. -

- -

Running from the command line

- -

Assuming your current directory is - $LOGBACK_HOME/logback-examples, where - $LOGBACK_HOME stands for the directory where you - installed logback, you can launch the first sample application, - chapter1.HelloWord1 with the following command: -

- -

java -cp lib/slf4j-api-${slf4j.version}.jar;../logback-core-${version}.jar;\ - ../logback-classic-${version}.jar;logback-examples-${version}.jar\ - chapter1.HelloWorld1

- -

It is more convenient to set the CLASSPATH environment variable - once and for all before running the examples. -

- -

The setClasspath.cmd script located in the - $LOGBACK_HOME/logback-examples folder will configure the class path - for the MS Windows platform. For Unix, you can use - setClasspath.sh. -

- -

Please edit the script in order to adapt the LB_HOME variable - to match your local environment.

- -

Please be aware that many examples will launch java classes - along with configuration files. To access these files by using the - same commands as written in the documentation, you will need to - issue the commands from within the - $LOGBACK_HOME/logback-examples directory. -

- -

Using an IDE, e.g. Eclipse

- -

You can import the logback project into Eclipse. Since logback - uses maven as its build system, the "maven eclipse:eclipse" command - will create the .classpath and .project files for - Eclipse. You can then import the logback project into Eclipse in one - or two clicks.

- - - - - -
- - + + + + + Setup + + + + + + + + + +
+ +
+ +
+ + +

Classpath Setup

+ +

In order to run the examples provided in the documentation, you + need to add the following jars to your class path: +

+ +
    +
  • logback-core-${version}.jar
  • +
  • logback-classic-${version}.jar
  • +
  • logback-examples-${version}.jar
  • +
  • slf4j-api-${slf4j.version}.jar
  • +
+ +

The logback-*.jar files are part of the logback + distribution whereas slf4j-api-${slf4j.version}.jar ships + with SLF4J, a separate project. +

+ +

Running from the command line

+ +

Assuming your current directory is + $LOGBACK_HOME/logback-examples, where + $LOGBACK_HOME stands for the directory where you + installed logback, you can launch the first sample application, + chapter1.HelloWord1 with the following command: +

+ +

java -cp lib/slf4j-api-${slf4j.version}.jar;../logback-core-${version}.jar;\ + ../logback-classic-${version}.jar;logback-examples-${version}.jar\ + chapter1.HelloWorld1

+ +

It is more convenient to set the CLASSPATH environment variable + once and for all before running the examples. +

+ +

The setClasspath.cmd script located in the + $LOGBACK_HOME/logback-examples folder will configure the class path + for the MS Windows platform. For Unix, you can use + setClasspath.sh. +

+ +

Please edit the script in order to adapt the LB_HOME variable + to match your local environment.

+ +

Please be aware that many examples will launch java classes + along with configuration files. To access these files by using the + same commands as written in the documentation, you will need to + issue the commands from within the + $LOGBACK_HOME/logback-examples directory. +

+ +

Using an IDE, e.g. Eclipse

+ +

You can import the logback project into Eclipse. Since logback + uses maven as its build system, the "maven eclipse:eclipse" command + will create the .classpath and .project files for + Eclipse. You can then import the logback project into Eclipse in one + or two clicks.

+ + + + + +
+ + diff --git a/logback-site/src/site/pages/support.html b/logback-site/src/site/pages/support.html index e3b594238d09e9a92150f74d64880627d6bedf14..511f40ec12f7568a0acf73fb4d7ded404fab3091 100644 --- a/logback-site/src/site/pages/support.html +++ b/logback-site/src/site/pages/support.html @@ -1,56 +1,56 @@ - - - - - - Professional support - - - - - - - - - -
- -
-
- -

Professional Support

- -

Although the quality of support in the various open source - project mailing lists is quite good, these are operated on a - best-effort basis. If you require authoritative responses and - guaranteed response times, then you should consider our - professional support package. -

- -

As the founders and/or current maintainers of the slf4j, log4j, - logback and cal10n projects, - we can offer you timely and competent support. Choosing our - professional support service is a good way to leverage our - expertise. Moreovoer, if you require custom development we are - likely to be of help. -

- -

For more information about Professional Support do not hesitate - to contact us. We will be happy to discuss your needs.

- - - - - - - - - - -
email:
telephone: +41 21 312 32 26
- -
- - + + + + + + Professional support + + + + + + + + + +
+ +
+
+ +

Professional Support

+ +

Although the quality of support in the various open source + project mailing lists is quite good, these are operated on a + best-effort basis. If you require authoritative responses and + guaranteed response times, then you should consider our + professional support package. +

+ +

As the founders and/or current maintainers of the slf4j, log4j, + logback and cal10n projects, + we can offer you timely and competent support. Choosing our + professional support service is a good way to leverage our + expertise. Moreovoer, if you require custom development we are + likely to be of help. +

+ +

For more information about Professional Support do not hesitate + to contact us. We will be happy to discuss your needs.

+ + + + + + + + + + +
email:
telephone: +41 21 312 32 26
+ +
+ + \ No newline at end of file diff --git a/logback-site/src/site/pages/team.html b/logback-site/src/site/pages/team.html index d207e79a8d92f821d309ca5f8f3b96a1aa266379..4cb3a9f0000646f0aafc77e7018019dd7325ef25 100644 --- a/logback-site/src/site/pages/team.html +++ b/logback-site/src/site/pages/team.html @@ -1,77 +1,77 @@ - - - - - - Logback Team - - - - - - - - - -
- -
-
- - - -

Logback Team

- -

Let us introduce you to the logback team members:

- - - - - - - - - - - - - - - -
Jean-Noel -

Jean-Noel Charpin has been designing and developing object - oriented software and decision making systems since 1998. He - is particularly interested in translating lean manufacturing - principles and practices to the software development domain - in order to improve quality and reliability. -

-
Ceki -

Ceki Gülcü has been working on logging systems - since 1996. He is the founder of the log4j, slf4j and - logback projects. Ceki enjoys writing software, a task far - more difficult and time-consuming than what it seems at - first sight. His interests range from cryptography, system - monitoring and testing to application interoperability. -

-
Sebastien -

Sébastien Pennec has been using computers for the most - part of his life, be it as a hobby, or during his studies - or, more recently, as Software Engineer. He loves to write - software in dynamic and enthusiastic environments, while - learning new technologies and practices. -

-

- Sébastien's hobbys include writing articles about - Macintosh products on cuk.ch, - digital photography and playing poker with his friends. -

-
- - - - - -
- - + + + + + + Logback Team + + + + + + + + + +
+ +
+
+ + + +

Logback Team

+ +

Let us introduce you to the logback team members:

+ + + + + + + + + + + + + + + +
Jean-Noel +

Jean-Noel Charpin has been designing and developing object + oriented software and decision making systems since 1998. He + is particularly interested in translating lean manufacturing + principles and practices to the software development domain + in order to improve quality and reliability. +

+
Ceki +

Ceki Gülcü has been working on logging systems + since 1996. He is the founder of the log4j, slf4j and + logback projects. Ceki enjoys writing software, a task far + more difficult and time-consuming than what it seems at + first sight. His interests range from cryptography, system + monitoring and testing to application interoperability. +

+
Sebastien +

Sébastien Pennec has been using computers for the most + part of his life, be it as a hobby, or during his studies + or, more recently, as Software Engineer. He loves to write + software in dynamic and enthusiastic environments, while + learning new technologies and practices. +

+

+ Sébastien's hobbys include writing articles about + Macintosh products on cuk.ch, + digital photography and playing poker with his friends. +

+
+ + + + + +
+ + diff --git a/logback-site/src/site/pages/templates/creative.js b/logback-site/src/site/pages/templates/creative.js index f6b44d7fd2ef504db34b603e324b79412229caa9..68ade795a5d179e287465aa3615ea41e643de593 100644 --- a/logback-site/src/site/pages/templates/creative.js +++ b/logback-site/src/site/pages/templates/creative.js @@ -1,33 +1,33 @@ -document.write(' '); -document.write(' '); -document.write(' '); -document.write(' '); -document.write(' '); -document.write(' '); -document.write(' '); -document.write(' '); -document.write(' '); -document.write('
'); -document.write('

'); -document.write(' Authors: Ceki Gülcü, Sébastien Pennec'); -document.write('
'); -document.write(' Copyright © 2000-2009, QOS.ch

'); -document.write('
'); -document.write(' '); -document.write(' Creative Commons License'); -document.write(' '); -document.write('
'); -document.write('

'); -document.write(' This document is licensed under a'); -document.write(' '); -document.write(' Creative Commons'); -document.write(' Attribution-NonCommercial-ShareAlike 2.5'); -document.write(' License'); -document.write(' '); -document.write('

'); -document.write('
'); +document.write(' '); +document.write(' '); +document.write(' '); +document.write(' '); +document.write(' '); +document.write(' '); +document.write(' '); +document.write(' '); +document.write(' '); +document.write('
'); +document.write('

'); +document.write(' Authors: Ceki Gülcü, Sébastien Pennec'); +document.write('
'); +document.write(' Copyright © 2000-2009, QOS.ch

'); +document.write('
'); +document.write(' '); +document.write(' Creative Commons License'); +document.write(' '); +document.write('
'); +document.write('

'); +document.write(' This document is licensed under a'); +document.write(' '); +document.write(' Creative Commons'); +document.write(' Attribution-NonCommercial-ShareAlike 2.5'); +document.write(' License'); +document.write(' '); +document.write('

'); +document.write('
'); diff --git a/logback-site/src/site/pages/templates/footer.js b/logback-site/src/site/pages/templates/footer.js index 28cdd2309e4c92e320f8e2bb7c61298243094ffa..6e51ecc500e90ec51aa55f1c7c15be383e0a210b 100644 --- a/logback-site/src/site/pages/templates/footer.js +++ b/logback-site/src/site/pages/templates/footer.js @@ -1,17 +1,17 @@ - -document.write('') - -document.write('') - -document.write(' ') - -document.write('') - -document.write('') -document.write('') - + +document.write('') + +document.write('') + +document.write(' ') + +document.write('') + +document.write('') +document.write('') + diff --git a/logback-site/src/site/pages/templates/header.js b/logback-site/src/site/pages/templates/header.js index 5402c42a1738337541650fa55326939a2113b8fb..e89184c288b552a771cbb886f3b93d45b96391b9 100644 --- a/logback-site/src/site/pages/templates/header.js +++ b/logback-site/src/site/pages/templates/header.js @@ -1,7 +1,7 @@ - -document.write('

'); -document.write(''); -document.write(''); -document.write('') -document.write('

'); -document.write('
'); + +document.write('

'); +document.write(''); +document.write(''); +document.write('') +document.write('

'); +document.write('
'); diff --git a/logback-site/src/site/pages/templates/left.js b/logback-site/src/site/pages/templates/left.js index f9e44e1d914c38d2a11d7e97504eff820556982c..035626d372aabcd27a7dae78c8f1f635595f5a77 100644 --- a/logback-site/src/site/pages/templates/left.js +++ b/logback-site/src/site/pages/templates/left.js @@ -1,23 +1,23 @@ - -document.write(''); -document.write(''); -document.write(''); -document.write(''); -document.write(''); -document.write(''); -document.write(''); -document.write(''); -document.write(''); -document.write(''); -document.write(''); - - - -document.write('

'); - - -document.write('

'); - - - + +document.write(''); +document.write(''); +document.write(''); +document.write(''); +document.write(''); +document.write(''); +document.write(''); +document.write(''); +document.write(''); +document.write(''); +document.write(''); + + + +document.write('

'); + + +document.write('

'); + + + diff --git a/logback-site/src/site/pages/templates/right.js b/logback-site/src/site/pages/templates/right.js index 493ae0972bbd228929a0dfe7337da332d9bd96ed..9f88cf17da6f855011553199a65540a06e58a9b1 100644 --- a/logback-site/src/site/pages/templates/right.js +++ b/logback-site/src/site/pages/templates/right.js @@ -1,19 +1,19 @@ -//document.write('') - -document.write('') +//document.write('') + +document.write('') diff --git a/logback-site/src/site/pages/templates/setup.js b/logback-site/src/site/pages/templates/setup.js index 5eef351af69f47e200fb953300b8c78d488c5cb1..d967af3e05123630fb49432985788c33ec02afba 100644 --- a/logback-site/src/site/pages/templates/setup.js +++ b/logback-site/src/site/pages/templates/setup.js @@ -1,10 +1,10 @@ - -document.write('
'); -document.write('

'); -document.write(' In order to run the examples in this chapter, you need'); -document.write(' to make sure that certain jar files are present on the'); -document.write(' classpath.'); -document.write(' Please refer to the setup page'); -document.write(' for further details.'); -document.write('

'); + +document.write('
'); +document.write('

'); +document.write(' In order to run the examples in this chapter, you need'); +document.write(' to make sure that certain jar files are present on the'); +document.write(' classpath.'); +document.write(' Please refer to the setup page'); +document.write(' for further details.'); +document.write('

'); document.write('
'); \ No newline at end of file diff --git a/logback-site/src/site/resources/manual/images/chapter3/sample.xml b/logback-site/src/site/resources/manual/images/chapter3/sample.xml index aac6b07c247024a6ccb82e335d55267d8205c473..aa8e4b813cc252a49d220a1fcb07dd17750f108c 100644 --- a/logback-site/src/site/resources/manual/images/chapter3/sample.xml +++ b/logback-site/src/site/resources/manual/images/chapter3/sample.xml @@ -1,32 +1,32 @@ - - - - myApp.log - - myApp-%d{yyyy-MM-dd-HH-mm-ss}.log - - - %date %level [%thread] %logger{10} [%file : %line] %msg%n - - - - - INFO - ACCEPT - DENY - - - %msg%n - - - - - - - - - - - - - + + + + myApp.log + + myApp-%d{yyyy-MM-dd-HH-mm-ss}.log + + + %date %level [%thread] %logger{10} [%file : %line] %msg%n + + + + + INFO + ACCEPT + DENY + + + %msg%n + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 5186c999b4e1eefc70a6cb0a2cfdfb691222a3fa..ba7281a64c41f8cc8743feb943c076d37e84ec1b 100755 --- a/pom.xml +++ b/pom.xml @@ -1,352 +1,352 @@ - - - 4.0.0 - - ch.qos.logback - logback-parent - 0.9.18-SNAPSHOT - pom - Logback-Parent - - http://logback.qos.ch - - - QOS.ch - http://www.qos.ch - - 2005 - - - logback-core - logback-classic - logback-access - logback-site - logback-examples - - - - - junit - junit - 4.4 - test - - - - - - 1.5.9.RC1 - 1.1.0 - - - - - - - ch.qos.logback - logback-core - ${project.version} - - - - ch.qos.logback - logback-core - ${project.version} - test-jar - - - - ch.qos.logback - logback-classic - ${project.version} - - - - ch.qos.logback - logback-access - ${project.version} - - - org.slf4j - slf4j-api - ${slf4j.version} - - - janino - janino - 2.4.3 - - - javax.mail - mail - 1.4 - - - dom4j - dom4j - 1.6.1 - - - hsqldb - hsqldb - 1.8.0.7 - - - tomcat - catalina - 5.5.15 - - - org.mortbay.jetty - jetty - 6.1.1 - - - org.mortbay.jetty - servlet-api-2.5 - 6.1.1 - - - org.apache.geronimo.specs - geronimo-jms_1.1_spec - 1.0 - - - javax.servlet - servlet-api - 2.5 - - - - - - - - - - org.apache.maven.wagon - wagon-ssh - 1.0-beta-1 - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - - - - org.apache.maven.plugins - maven-source-plugin - - - package - - jar - - - - - - org.apache.maven.plugins - maven-idea-plugin - - 1.5 - true - true - - - - org.apache.maven.plugins - maven-eclipse-plugin - - true - - - - - maven-assembly-plugin - 2.1 - - - - src/main/assembly/dist.xml - - - - logback-${project.version} - - false - target/site/dist/ - - - - - - - - - org.apache.maven.plugins - maven-site-plugin - - - org.apache.maven.plugins - maven-jxr-plugin - - true - target/site/apidocs/ - true - - - - org.apache.maven.plugins - - maven-project-info-reports-plugin - - - - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - true - - - http://java.sun.com/j2se/1.5.0/docs/api - - - - - Logback Core - ch.qos.logback.core:ch.qos.logback.core.* - - - Logback Classic - ch.qos.logback:ch.qos.logback.classic:ch.qos.logback.classic.* - - - Logback Access - ch.qos.logback.access:ch.qos.logback.access.* - - - SLF4J - org.slf4j:org.slf4j.* - - - Examples - chapter*:joran* - - - - - - - - - - - scm:svn:http://svn.qos.ch/repos/logback/trunk/ - scm:svn:https://svn.qos.ch/repos/logback/trunk/ - http://svn.qos.ch/repos/logback/trunk/ - - - - - - - - - - pixie - scp://pixie/var/www/logback.qos.ch/htdocs/ - - - - pixie - scp://pixie/var/mvnrepo/ - - - - pixie-snapshot - scp://pixie/var/mvnrepo-snapshots/ - - - - - - - - - testSkip - - true - - - - license - - - - com.google.code.maven-license-plugin - maven-license-plugin - -
src/main/licenseHeader.txt
- false - true - true - - src/**/*.java - - true - true - - 1999 - - - src/main/javadocHeaders.xml - -
-
-
-
- - - - mc-release - Local Maven repository of releases - http://mc-repo.googlecode.com/svn/maven2/releases - - false - - - true - - - -
-
- + + + 4.0.0 + + ch.qos.logback + logback-parent + 0.9.18-SNAPSHOT + pom + Logback-Parent + + http://logback.qos.ch + + + QOS.ch + http://www.qos.ch + + 2005 + + + logback-core + logback-classic + logback-access + logback-site + logback-examples + + + + + junit + junit + 4.4 + test + + + + + + 1.5.9.RC1 + 1.1.0 + + + + + + + ch.qos.logback + logback-core + ${project.version} + + + + ch.qos.logback + logback-core + ${project.version} + test-jar + + + + ch.qos.logback + logback-classic + ${project.version} + + + + ch.qos.logback + logback-access + ${project.version} + + + org.slf4j + slf4j-api + ${slf4j.version} + + + janino + janino + 2.4.3 + + + javax.mail + mail + 1.4 + + + dom4j + dom4j + 1.6.1 + + + hsqldb + hsqldb + 1.8.0.7 + + + tomcat + catalina + 5.5.15 + + + org.mortbay.jetty + jetty + 6.1.1 + + + org.mortbay.jetty + servlet-api-2.5 + 6.1.1 + + + org.apache.geronimo.specs + geronimo-jms_1.1_spec + 1.0 + + + javax.servlet + servlet-api + 2.5 + + + + + + + + + + org.apache.maven.wagon + wagon-ssh + 1.0-beta-1 + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + org.apache.maven.plugins + maven-source-plugin + + + package + + jar + + + + + + org.apache.maven.plugins + maven-idea-plugin + + 1.5 + true + true + + + + org.apache.maven.plugins + maven-eclipse-plugin + + true + + + + + maven-assembly-plugin + 2.1 + + + + src/main/assembly/dist.xml + + + + logback-${project.version} + + false + target/site/dist/ + + + + + + + + + org.apache.maven.plugins + maven-site-plugin + + + org.apache.maven.plugins + maven-jxr-plugin + + true + target/site/apidocs/ + true + + + + org.apache.maven.plugins + + maven-project-info-reports-plugin + + + + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + true + + + http://java.sun.com/j2se/1.5.0/docs/api + + + + + Logback Core + ch.qos.logback.core:ch.qos.logback.core.* + + + Logback Classic + ch.qos.logback:ch.qos.logback.classic:ch.qos.logback.classic.* + + + Logback Access + ch.qos.logback.access:ch.qos.logback.access.* + + + SLF4J + org.slf4j:org.slf4j.* + + + Examples + chapter*:joran* + + + + + + + + + + + scm:svn:http://svn.qos.ch/repos/logback/trunk/ + scm:svn:https://svn.qos.ch/repos/logback/trunk/ + http://svn.qos.ch/repos/logback/trunk/ + + + + + + + + + + pixie + scp://pixie/var/www/logback.qos.ch/htdocs/ + + + + pixie + scp://pixie/var/mvnrepo/ + + + + pixie-snapshot + scp://pixie/var/mvnrepo-snapshots/ + + + + + + + + + testSkip + + true + + + + license + + + + com.google.code.maven-license-plugin + maven-license-plugin + +
src/main/licenseHeader.txt
+ false + true + true + + src/**/*.java + + true + true + + 1999 + + + src/main/javadocHeaders.xml + +
+
+
+
+ + + + mc-release + Local Maven repository of releases + http://mc-repo.googlecode.com/svn/maven2/releases + + false + + + true + + + +
+
+
\ No newline at end of file diff --git a/src/main/assembly/dist.xml b/src/main/assembly/dist.xml index 2e14462938c4a4f7cec75d999432f1ad31658dcb..f4bf8fad8f9ac61fc70534f92cb668a4bf128093 100755 --- a/src/main/assembly/dist.xml +++ b/src/main/assembly/dist.xml @@ -1,259 +1,259 @@ - - dist - - zip - tar.gz - - - - - logback-core/ - logback-core/ - - - pom.xml - - - - *.bak - - - - log4j-bridge/ - log4j-bridge/ - - - pom.xml - - - - *.bak - - - - logback-classic/ - logback-classic/ - - - pom.xml - - - - *.bak - - - - logback-access/ - logback-access/ - - - pom.xml - - - - *.bak - - - - logback-examples/ - logback-examples/ - - - pom.xml - - - - *.bak - - - - logback-site/ - logback-site/ - - - pom.xml - - - - *.bak - - - - - logback-core/src/ - logback-core/src/ - - - test/output/ - - - - - logback-classic/src/ - logback-classic/src/ - - - logback-access/src/ - logback-access/src/ - - - logback-examples/src/ - logback-examples/src/ - - - main/resources/ - - - - - log4j-bridge/src/ - log4j-bridge/src/ - - - log4j-bridge/compatibility/ - log4j-bridge/compatibility/ - - - target/classes/ - - - target/classes12/ - - - target/classes13/ - - - - - - logback-site/src/ - logback-site/src/ - - - - logback-examples/target/ - logback-examples/ - - logback-examples-${project.version}.jar - - - - logback-examples/lib/ - logback-examples/lib - - - logback-examples/target/classes - logback-examples/ - - setClasspath.sh - setClasspath.cmd - - - - - - logback-core/target/ - / - - logback-core-${project.version}.jar - - - - logback-classic/target/ - / - - logback-classic-${project.version}.jar - - - - logback-access/target/ - / - - logback-access-${project.version}.jar - - - - log4j-bridge/target/ - / - - log4j-bridge-${project.version}.jar - - - - - logback-core/target/ - / - - logback-core-${project.version}-sources.jar - - - - logback-classic/target/ - / - - logback-classic-${project.version}-sources.jar - - - - logback-access/target/ - / - - logback-access-${project.version}-sources.jar - - - - log4j-bridge/target/ - / - - log4j-bridge-${project.version}-sources.jar - - - - - - target/site - docs/ - - dist/* - - - - - - - src/ - README* - LICENSE* - pom.xml - - - *.bak - - - - - + + dist + + zip + tar.gz + + + + + logback-core/ + logback-core/ + + + pom.xml + + + + *.bak + + + + log4j-bridge/ + log4j-bridge/ + + + pom.xml + + + + *.bak + + + + logback-classic/ + logback-classic/ + + + pom.xml + + + + *.bak + + + + logback-access/ + logback-access/ + + + pom.xml + + + + *.bak + + + + logback-examples/ + logback-examples/ + + + pom.xml + + + + *.bak + + + + logback-site/ + logback-site/ + + + pom.xml + + + + *.bak + + + + + logback-core/src/ + logback-core/src/ + + + test/output/ + + + + + logback-classic/src/ + logback-classic/src/ + + + logback-access/src/ + logback-access/src/ + + + logback-examples/src/ + logback-examples/src/ + + + main/resources/ + + + + + log4j-bridge/src/ + log4j-bridge/src/ + + + log4j-bridge/compatibility/ + log4j-bridge/compatibility/ + + + target/classes/ + + + target/classes12/ + + + target/classes13/ + + + + + + logback-site/src/ + logback-site/src/ + + + + logback-examples/target/ + logback-examples/ + + logback-examples-${project.version}.jar + + + + logback-examples/lib/ + logback-examples/lib + + + logback-examples/target/classes + logback-examples/ + + setClasspath.sh + setClasspath.cmd + + + + + + logback-core/target/ + / + + logback-core-${project.version}.jar + + + + logback-classic/target/ + / + + logback-classic-${project.version}.jar + + + + logback-access/target/ + / + + logback-access-${project.version}.jar + + + + log4j-bridge/target/ + / + + log4j-bridge-${project.version}.jar + + + + + logback-core/target/ + / + + logback-core-${project.version}-sources.jar + + + + logback-classic/target/ + / + + logback-classic-${project.version}-sources.jar + + + + logback-access/target/ + / + + logback-access-${project.version}-sources.jar + + + + log4j-bridge/target/ + / + + log4j-bridge-${project.version}-sources.jar + + + + + + target/site + docs/ + + dist/* + + + + + + + src/ + README* + LICENSE* + pom.xml + + + *.bak + + + + + \ No newline at end of file diff --git a/src/main/header.txt b/src/main/header.txt index 981bf543c2ed9d16a2b78886551e20252a2b9daa..56d0e7b7a4ddac604d47599facc086abb8576f2d 100644 --- a/src/main/header.txt +++ b/src/main/header.txt @@ -1,12 +1,12 @@ -Logback: the generic, reliable, 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 as published +Logback: the generic, reliable, 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 as published by the Free Software Foundation. \ No newline at end of file diff --git a/src/main/javadocHeaders.xml b/src/main/javadocHeaders.xml index b011d99709d0a28d025ea07465e9aa79e3cf11ff..a0fccd47f3f259333c0ce138c160f2a5b5aa364b 100644 --- a/src/main/javadocHeaders.xml +++ b/src/main/javadocHeaders.xml @@ -1,10 +1,10 @@ - - - /** - * - */ - - (\s|\t)*/\*.*$ - .*\*/(\s|\t)*$ - + + + /** + * + */ + + (\s|\t)*/\*.*$ + .*\*/(\s|\t)*$ + \ No newline at end of file diff --git a/src/main/licenseHeader.txt b/src/main/licenseHeader.txt index aa146373f05cf3194a8b3593879f6859d1965a51..701f936c3f5785296204a90c82fba99cf68a16e3 100644 --- a/src/main/licenseHeader.txt +++ b/src/main/licenseHeader.txt @@ -1,11 +1,11 @@ -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. +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. diff --git a/version.pl b/version.pl index 8e4d8a534e203ce5745dca20a04316a496de3491..52e831ebbc63e81bce4555db3a2b556ceb8f326f 100644 --- a/version.pl +++ b/version.pl @@ -1,44 +1,44 @@ - -if ($#ARGV < 1) { - print "Usage: version.pl VER FILE {FILE, FILE}\n"; - exit; -} - -$V= $ARGV[0]; -print "VER:$V\r\n"; -shift(@ARGV); - -sub replace () { - my $filename = $_[0]; - - if(-s $filename) { - print "Processing [" . $filename . "]\r\n"; - - my $origFile = "$filename.original"; - - rename($filename, $origFile); - open(OUT, ">$filename"); - open(IN, "$origFile"); - - my $hitCount=0; - while() { - if($hitCount == 0 && /.*<\/version>/) { - s/.*<\/version>/$V<\/version>/; - $hitCount++; - } - print OUT; - } - close(IN); - close(OUT); - unlink($origFile); - } else { - print "File [" . $filename . "] does not exist\r\n" - } -} - -foreach $ARG (@ARGV) { - do replace($ARG); -} - - - + +if ($#ARGV < 1) { + print "Usage: version.pl VER FILE {FILE, FILE}\n"; + exit; +} + +$V= $ARGV[0]; +print "VER:$V\r\n"; +shift(@ARGV); + +sub replace () { + my $filename = $_[0]; + + if(-s $filename) { + print "Processing [" . $filename . "]\r\n"; + + my $origFile = "$filename.original"; + + rename($filename, $origFile); + open(OUT, ">$filename"); + open(IN, "$origFile"); + + my $hitCount=0; + while() { + if($hitCount == 0 && /.*<\/version>/) { + s/.*<\/version>/$V<\/version>/; + $hitCount++; + } + print OUT; + } + close(IN); + close(OUT); + unlink($origFile); + } else { + print "File [" . $filename . "] does not exist\r\n" + } +} + +foreach $ARG (@ARGV) { + do replace($ARG); +} + + +