diff -Nru libcommons-logging-java-1.1.1/LICENSE.txt libcommons-logging-java-1.1.3/LICENSE.txt --- libcommons-logging-java-1.1.1/LICENSE.txt 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/LICENSE.txt 2013-05-16 20:04:22.000000000 +0000 @@ -1,202 +1,202 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. 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. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor 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, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You 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 the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You 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 such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its 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. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. 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. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor 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, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You 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 the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You 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 such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its 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. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff -Nru libcommons-logging-java-1.1.1/NOTICE.txt libcommons-logging-java-1.1.3/NOTICE.txt --- libcommons-logging-java-1.1.1/NOTICE.txt 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/NOTICE.txt 2013-05-16 20:04:22.000000000 +0000 @@ -1,6 +1,6 @@ -Apache Commons Logging -Copyright 2003-2007 The Apache Software Foundation - -This product includes software developed by -The Apache Software Foundation (http://www.apache.org/). - +Apache Commons Logging +Copyright 2003-2013 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + diff -Nru libcommons-logging-java-1.1.1/PROPOSAL.html libcommons-logging-java-1.1.3/PROPOSAL.html --- libcommons-logging-java-1.1.1/PROPOSAL.html 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/PROPOSAL.html 2013-05-16 20:04:22.000000000 +0000 @@ -1,121 +1,121 @@ - - - - -Proposal for Logging Library Package - - - -
-

Proposal for Logging Package

-
- -

(0) Rationale

- -

There is a great need for debugging and logging information inside of -Commons components such as HTTPClient and dbcp. However, there are many -logging APIs out there and it is difficult to choose among them. -

- -

The Logging package will be an ultra-thin bridge between different logging -libraries. Commons components may use the Logging JAR to remove -compile-time/runtime dependencies on any particular logging package, -and contributors may write Log implementations for the library of their choice. -

- -

(1) Scope of the Package

- -

The package shall create and maintain a package that provides extremely -basic logging functionality and bridges to other, more sophisticated logging -implementations. -

- -

-The package should : -

-

- -

-Non-goals: -

-

- -

(1.5) Interaction With Other Packages

- -

Logging relies on: -

- - - -

(2) Required Jakarta-Commons Resources

- - - - -

(4) Initial Committers

- -

The initial committers on the Logging component shall be:

- - - - - + + + + +Proposal for Logging Library Package + + + +
+

Proposal for Logging Package

+
+ +

(0) Rationale

+ +

There is a great need for debugging and logging information inside of +Commons components such as HTTPClient and dbcp. However, there are many +logging APIs out there and it is difficult to choose among them. +

+ +

The Logging package will be an ultra-thin bridge between different logging +libraries. Commons components may use the Logging JAR to remove +compile-time/runtime dependencies on any particular logging package, +and contributors may write Log implementations for the library of their choice. +

+ +

(1) Scope of the Package

+ +

The package shall create and maintain a package that provides extremely +basic logging functionality and bridges to other, more sophisticated logging +implementations. +

+ +

+The package should : +

+

+ +

+Non-goals: +

+

+ +

(1.5) Interaction With Other Packages

+ +

Logging relies on: +

+ + + +

(2) Required Jakarta-Commons Resources

+ + + + +

(4) Initial Committers

+ +

The initial committers on the Logging component shall be:

+ + + + + diff -Nru libcommons-logging-java-1.1.1/RELEASE-NOTES.txt libcommons-logging-java-1.1.3/RELEASE-NOTES.txt --- libcommons-logging-java-1.1.1/RELEASE-NOTES.txt 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/RELEASE-NOTES.txt 2013-05-16 20:04:22.000000000 +0000 @@ -1,166 +1,22 @@ - - -$Id: RELEASE-NOTES.txt 597240 2007-11-21 22:50:06Z dennisl $ - - Commons Logging Package - Version 1.1.1 - Release Notes - -INTRODUCTION: -============ - -This release of Apache Commons Logging is a maintenance release, with just a -couple of fixes for using Commons Logging under restrictive security policies. - -All core classes were compiled with Maven using a 1.4.x JDK, with target set -to 1.1 and source set to 1.2. Commons Logging may work on some -augmented 1.1 series JREs but it is recommended that those wish to run -on 1.1 JREs download the source and create a custom implementation by -stripping out all the complex classloader management code. - -For further details, please see the Apache Commons Logging website: - http://commons.apache.org/logging/ - -For the very latest news, hints, FAQs etc. please see the -Apache Commons Logging wiki site: - http://wiki.apache.org/commons/Logging - -Note that some containers (some versions of Apache Tomcat and JBoss in -particular) prevent webapps, ejbs, etc from overriding the commons-logging -implementation provided by the container. This means that bundling this -updated implementation with a deployed application may not have any effect. -See the commons-logging site and/or the wiki for more information. - -== New Features Since 1.1.0 == - -None. - -== Incompatibilities == - -The protected method LogFactory.getContextClassLoader has been reverted to pre-1.1 -behaviour. In earlier releases, this method did not use an AccessController when -obtaining the context classloader. In version 1.1 it did. In this release, it has -reverted to not using an AccessController; any user-level code that needs to obtain -a context classloader should itself create an AccessController, and call the -LogFactory.getContextClassLoader method via the doPrivileged method. This fixes a -potential security issue, where untrusted code could get access to the context -classloader if a signed Commons Logging library was in the classpath. - -== Dependencies == - -Commons Logging has no mandatory dependencies. - -Java 1.2 and later are supported. It may be possible to use this release with -java 1.1 but this has not been tested; the unit tests certainly don't run on -that version. - -== Distributed Jar Files == - -File commons-logging-nn.jar is the one most people will want. It provides the -base implementation and adapters to a number of popular logging libraries. - -File commons-logging-adapters-nn.jar includes only the adapters to various -concrete logging libraries. When commons-logging-nn.jar or -commons-logging-api-nn.jar is deployed in a container classpath, then this -adapters-only jar file should be deployed in the webapp, not the complete Commons -Logging distribution. This ensures that the core Log/LogFactory classes are only -deployed via one classloader, thus avoiding "Log4JLogger does not implement Log" -and similar problems. - -File commons-logging-api-nn.jar provides minimal adapters to external logging -libraries, just the internally implemented SimpleLog and NoOpLog classes -plus Jdk14Logger (which is currently required by Apache Tomcat). - -The file commons-logging-api-nn.jar may be used as a declared dependency for -projects that care about "transitive dependencies" and can't handle jar files -such as commons-logging-nn.jar which have "optional" dependencies depending on -how they are used. In addition, this jar file can be useful for "rebundlers" of -Commons Logging who recompile the source-code but who may not be able to -recompile against the full set of supported adapters; such projects should be -able to at least recreate an equivalent of this jar file. - -== General Notes == - -The Apache Commons project has migrated to the Subversion version control system -(previously, CVS was used). There should be no effect on users of the Commons -Logging library, but obviously the process of examining the latest source code, -and of creating patches for Commons Logging has now changed. Please see the -Apache Commons website for details (http://commons.apache.org/). - -The Apache Commons project has now moved to using the Apache JIRA installation -as its bugtracking system (formerly, the Apache Bugzilla installation was used). - -All source files for this release have been updated to reflect the new Apache -Software Foundation licensing rules. The terms and conditions are unaltered; -this merely affects how those are presented in the source files. See - http://www.apache.org/legal/src-headers.html - -This release can be built/tested with Maven 2.0.x as well as Ant. Note that -building with Maven 1.x is no longer supported. The files used to build Commons -Logging with Maven 1.x will be removed in a future version of Commons Logging. - -== Bugs Fixed == - -* LOGGING-106: Commons Logging 1.1 was completely unusable under a security - policy that prevented access to system properties. Even signing/authorising - the Commons Logging library was not sufficient. This has been fixed by (a) - catching SecurityException and falling back to a sensible default, and (b) - using AccessController so Commons Logging can be granted privileges without - needing the caller to have them too. - -* LOGGING-107: Commons Logging 1.1 auto-discovery failed under a security - policy that prevented calls to ClassLoader.getParent. Signing/authorising the - Commons Logging library was not sufficient as an AccessController was not used. - This has been fixed by catching SecurityException and using an AccessController. - -* LOGGING-111, LOGGING-114: Show the contents of chained exceptions, to make - debugging easier, in particular when using Commons Logging together with Log4J. - -* LOGGING-113: pom.xml in maven repository does not list dependencies as optional. - -* LOGGING-115: NPE thrown due to exception message logging. - -* LOGGING-117: Unit tests fail on linux with java16. - -* LOGGING-118: Generate source and binary archives. - -* MEV-392 (http://jira.codehaus.org/browse/MEV-392) - As Commons Logging didn't provide a Maven2 pom.xml file, one was helpfully - created by people not involved with the commons-logging project and published - to the standard maven repositories. Unfortunately this pom declared normal - dependencies on all the logging libraries that are supported by the core - Commons Logging distribution, meaning they all get pulled into a project that - declares a dependency on Commons Logging 1.1. This release now provides an - "official" pom.xml which declares these dependencies as optional so they aren't - automatically included in projects that depend on Commons Logging 1.1.1. - -* (no bug#): Fix thread-safety bug (SimpleDateFormat.format is not thread-safe). - Thanks to Martin Wilson of bright-interactive for the bug report. - -* (no bug#): Security issue regarding access to context classloader (see - incompatibilities section above). - -DEPRECATIONS: -============ - - (These are carried forward from Version 1.0.4) - -[LogSource] Previously deprecated, replaced by LogFactory. - + Apache Commons Logging + Version 1.1.3 + RELEASE NOTES + +The Commons Logging team is pleased to announce the release of Apache Commons Logging 1.1.3 + +Commons Logging is a thin adapter allowing configurable bridging to other, +well known logging systems. + +This is a maintenance release containing bug fixes. + +Changes in this version include: + +Fixed Bugs: +o LOGGING-151: Use "org.apache.commons.logging" as bundle symbolic name. Thanks to Krzysztof Daniel. + +Historical list of changes: http://commons.apache.org/proper/commons-logging/changes-report.html + +For complete information on Commons Logging, including instructions on how to submit bug reports, +patches, or suggestions for improvement, see the Apache Commons Logging website: + +http://commons.apache.org/proper/commons-logging/ \ No newline at end of file diff -Nru libcommons-logging-java-1.1.1/STATUS.html libcommons-logging-java-1.1.3/STATUS.html --- libcommons-logging-java-1.1.1/STATUS.html 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/STATUS.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,172 +0,0 @@ - - - - -Status File for Apache Commons "Logging" Component - - - - -
-

The Apache Commons Logging Component

-$Id: STATUS.html 560818 2007-07-29 21:02:06Z dennisl $
-[Introduction] -[Dependencies] -[Release Info] -[Committers] -[Action Items] -

-
- - - -

1. INTRODUCTION

- - -

The commons-logging package provides a simple, component -oriented interface (org.apache.commons.logging.Log) together with wrappers for -logging systems. The user can choose at runtime -which system they want to use. -In addition, a small number of basic implementations are provided -to allow users to use the package standalone. -

- -

commons-logging was heavily influenced by Avalon's Logkit and Log4J. The commons-logging -abstraction is meant to minimixe the differences between the two, and to allow a -developer to not tie himself to a particular logging implementation. -

- -

-The package does : -

-

- -

-Non-goals: -

-

- - - -

2. DEPENDENCIES

- -

The Logging component is dependent upon the following external -components for compilation:

- - -

Of course, the user must ensure that any logging systems that they wish -to use are present in the classpath when they use this component.

- - -

3. RELEASE INFO

- - - - - - - - - - - - - - - - - - - - - - -
VersionRelease Date
commons-logging-1.0.3 is available through the standard mirrors. - Binaries are here and - source is here - 7-Apr-2003
- commons-logging-1.0.227-Sep-2002
- commons-logging-1.0.112-Aug-2002
- commons-logging-1.020-Feb-2002
- -

Planned Next Release: TBD

- - - - -

4. COMMITTERS

- -

The following individuals are the primary developers and maintainers of this -component. Developers who plan to use Logging in their own -projects are encouraged to collaborate on the future development of this -component to ensure that it continues to meet a variety of needs.

- - - - -

5. ACTION ITEMS

- -

TO DO List:

- - - - - - -
Action ItemVolunteer
- - - diff -Nru libcommons-logging-java-1.1.1/build-testing.xml libcommons-logging-java-1.1.3/build-testing.xml --- libcommons-logging-java-1.1.1/build-testing.xml 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/build-testing.xml 2013-05-16 20:04:22.000000000 +0000 @@ -1,350 +1,350 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Log4j12: ${log4j12.jar} - - - LogKit: ${logkit.jar} - Avalon-Framework: ${avalon-framework.jar} - - - - - - - - - - - - - - - - - - - - - - - - *** WARNING *** - Log4J 1.2.x Jar not found: Cannot execute 1.2.x tests - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One or more unit tests failed. - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Log4j12: ${log4j12.jar} + + + LogKit: ${logkit.jar} + Avalon-Framework: ${avalon-framework.jar} + + + + + + + + + + + + + + + + + + + + + + + + *** WARNING *** + Log4J 1.2.x Jar not found: Cannot execute 1.2.x tests + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + One or more unit tests failed. + + + + diff -Nru libcommons-logging-java-1.1.1/build.properties.sample libcommons-logging-java-1.1.3/build.properties.sample --- libcommons-logging-java-1.1.1/build.properties.sample 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/build.properties.sample 2013-05-16 20:04:22.000000000 +0000 @@ -1,59 +1,59 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -###################################################################### -# -# TO USE: -# -# Copy this file to build.properties and either -# -# a) Use 'ant getlibs' to populate the default directory -# with dependencies -# or b) Change the property values to appropriate values -# -######################################################################## - -# Apache Log4j 1.2.x series -log4j12.jar=lib/log4j-1.2.12.jar - -# Apache Log4j 1.3.x series -# Note: Log4j 1.3 support not available in the 1.1 release -#log4j13.jar=lib/log4j-1.3.0.jar - -# logkit.jar - Avalon LogKit classes (see http://jakarta.apache.org/avalon) -logkit.jar=lib/logkit-1.0.1.jar - -# Avalon framework - used for wrapper for avalon framework logger -avalon-framework.jar=lib/avalon-framework-4.1.3.jar - -# ServletApi - used to build ServletContextCleaner class -servletapi.jar=lib/servletapi-2.3.jar - -# -# if you want to run the test cases, junit needs to be in the classpath. -# the build.xml uses a default value so you might not need to set this property. -# Note that version junit 3.8 is required and 3.8.1 recommended. -# -junit.jar=lib/junit-3.8.1.jar - -# Maven properties (for web site build) -# Those committers using agents may like to use -#maven.username=rdonkin -#logging.cvs=lserver:rdonkin@cvs.apache.org:/home/cvs - - -# The path to a 1.4 JSDK javac -# Optional - used when building with a 1.2 JVM for releases -# executable.javac1.4=/opt/java/jdks/j2sdk1.4.2_10/bin/javac +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +###################################################################### +# +# TO USE: +# +# Copy this file to build.properties and either +# +# a) Use 'ant getlibs' to populate the default directory +# with dependencies +# or b) Change the property values to appropriate values +# +######################################################################## + +# Apache Log4j 1.2.x series +log4j12.jar=lib/log4j-1.2.12.jar + +# Apache Log4j 1.3.x series +# Note: Log4j 1.3 support not available in the 1.1 release +#log4j13.jar=lib/log4j-1.3.0.jar + +# logkit.jar - Avalon LogKit classes (see http://jakarta.apache.org/avalon) +logkit.jar=lib/logkit-1.0.1.jar + +# Avalon framework - used for wrapper for avalon framework logger +avalon-framework.jar=lib/avalon-framework-4.1.3.jar + +# ServletApi - used to build ServletContextCleaner class +servletapi.jar=lib/servletapi-2.3.jar + +# +# if you want to run the test cases, junit needs to be in the classpath. +# the build.xml uses a default value so you might not need to set this property. +# Note that version junit 3.8 is required and 3.8.1 recommended. +# +junit.jar=lib/junit-3.8.1.jar + +# Maven properties (for web site build) +# Those committers using agents may like to use +#maven.username=rdonkin +#logging.cvs=lserver:rdonkin@cvs.apache.org:/home/cvs + + +# The path to a 1.4 JSDK javac +# Optional - used when building with a 1.2 JVM for releases +# executable.javac1.4=/opt/java/jdks/j2sdk1.4.2_10/bin/javac diff -Nru libcommons-logging-java-1.1.1/build.xml libcommons-logging-java-1.1.3/build.xml --- libcommons-logging-java-1.1.1/build.xml 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/build.xml 2013-05-16 20:04:22.000000000 +0000 @@ -1,788 +1,776 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Log4j12: ${log4j12.jar} - - - LogKit: ${logkit.jar} - Avalon-Framework: ${avalon-framework.jar} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *** WARNING *** - Log4j 1.2 not found: Cannot Build Log4JLogger - - - - - - - - - - - *** WARNING *** - LogKit not found: Cannot Build LogKitLogger - - - - - - *** WARNING *** - Avalon-Framework not found: Cannot Build AvalonLogger - - - - - - *** WARNING *** - JDK 1.4 not present: Cannot Build Jdk14Logger - - - - - - *** WARNING *** - Log4J 1.2.x Jar not found: Cannot execute 1.2.x tests - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *** WARNING *** - Maven generated documentation not found: Documentation distribution will be empty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One or more unit tests failed. - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Log4j12: ${log4j12.jar} + + + LogKit: ${logkit.jar} + Avalon-Framework: ${avalon-framework.jar} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *** WARNING *** + Log4j 1.2 not found: Cannot Build Log4JLogger + + + + + + + + + + + *** WARNING *** + LogKit not found: Cannot Build LogKitLogger + + + + + + *** WARNING *** + Avalon-Framework not found: Cannot Build AvalonLogger + + + + + + *** WARNING *** + JDK 1.4 not present: Cannot Build Jdk14Logger + + + + + + *** WARNING *** + Log4J 1.2.x Jar not found: Cannot execute 1.2.x tests + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *** WARNING *** + Maven generated documentation not found: Documentation distribution will be empty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + One or more unit tests failed. + + + + diff -Nru libcommons-logging-java-1.1.1/checkstyle.xml libcommons-logging-java-1.1.3/checkstyle.xml --- libcommons-logging-java-1.1.1/checkstyle.xml 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/checkstyle.xml 2013-05-16 20:04:22.000000000 +0000 @@ -1,41 +1,69 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru libcommons-logging-java-1.1.1/commons-logging-api.pom libcommons-logging-java-1.1.3/commons-logging-api.pom --- libcommons-logging-java-1.1.1/commons-logging-api.pom 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/commons-logging-api.pom 1970-01-01 00:00:00.000000000 +0000 @@ -1,245 +0,0 @@ - - - - 3 - - Logging - commons-logging - commons-logging-api - 1.1.1-SNAPSHOT - 2001 - Commons Logging - - Commons Logging is a thin adapter allowing configurable bridging to other, - well known logging systems. - - /images/logo.png - - http://commons.apache.org/logging/ - org.apache.commons.logging - - - The Apache Software Foundation - http://jakarta.apache.org - http://jakarta.apache.org/images/original-jakarta-logo.gif - - - - - The Apache Software License, Version 2.0 - /LICENSE.txt - repo - - - - commons - http://issues.apache.org/jira/browse/LOGGING - people.apache.org - /www/commons.apache.org/logging/ - /www/jakarta.apache.org/builds/jakarta-commons/logging/ - - - scm:svn:http://svn.apache.org/repos/asf/commons/proper/logging/trunk/ - http://svn.apache.org/repos/asf/commons/proper/logging/trunk/ - - - - - 1.0.1 - 1.0.1 - LOGGING_1_0_1 - - - 1.0.2 - 1.0.2 - LOGGING_1_0_2 - - - 1.0.3 - 1.0.3 - LOGGING_1_0_3 - - - 1.0.4 - 1.0.4 - LOGGING_1_0_4 - - - 1.1 - 1.1 - LOGGING_1_1_0 - - - - - - Commons Dev List - dev-subscribe@commons.apache.org - dev-unsubscribe@commons.apache.org - http://mail-archives.apache.org/mod_mbox/commons-dev/ - - - Commons User List - user-subscribe@commons.apache.org - user-unsubscribe@commons.apache.org - http://mail-archives.apache.org/mod_mbox/commons-user/ - - - - - - Morgan Delagrange - morgand - morgand at apache dot org - Apache - Java Developer - - - Rodney Waldhoff - rwaldhoff - rwaldhoff at apache org - Apache Software Foundation - - - Craig McClanahan - craigmcc - craigmcc at apache org - Apache Software Foundation - - - Scott Sanders - sanders - sanders at apache dot org - Apache Software Foundation - - - Robert Burrell Donkin - rdonkin - rdonkin at apache dot org - Apache Software Foundation - - - Peter Donald - donaldp - donaldp at apache dot org - - - - Costin Manolache - costin - costin at apache dot org - Apache Software Foundation - - - Richard Sitze - rsitze - rsitze at apache dot org - Apache Software Foundation - - - Juozas Baliuka - baliuka - baliuka@apache.org - - - Java Developer - - - - Simon Kitching - skitching - skitching@apache.org - Apache Software Foundation - - - Dennis Lundberg - dennisl - dennisl@apache.org - Apache Software Foundation - - - Brian Stansberry - bstansberry - - - - - - - junit - junit - 3.8.1 - http://www.junit.org/index.htm - - Used for testing only. - test - true - - - - - maven - maven-xdoc-plugin - 1.9.2 - http://maven.apache.org/maven-1.x/reference/plugins/xdoc/ - plugin - - - <strong>Site Only</strong> - v1.9.2 (minimum) - - true - - - - - dev@commons.apache.org - src/java - src/test - - - java.util.logging.Logger - - **/Jdk14Logger.java - - - - - - - - - - maven-javadoc-plugin - maven-jdepend-plugin - maven-junit-report-plugin - maven-jxr-plugin - maven-license-plugin - - - - - diff -Nru libcommons-logging-java-1.1.1/debian/changelog libcommons-logging-java-1.1.3/debian/changelog --- libcommons-logging-java-1.1.1/debian/changelog 2012-07-12 14:28:08.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/changelog 2013-05-22 03:01:12.000000000 +0000 @@ -1,14 +1,31 @@ -libcommons-logging-java (1.1.1-9ubuntu1) quantal; urgency=low +libcommons-logging-java (1.1.3-1) unstable; urgency=low - * Transition libservlet2.5-java -> libservlet3.0-java (LP: #1023405). + * New upstream release. + * Refreshed the patches + + -- Emmanuel Bourg Tue, 21 May 2013 22:18:11 +0200 - -- James Page Thu, 12 Jul 2012 15:28:07 +0100 +libcommons-logging-java (1.1.2-2) experimental; urgency=low -libcommons-logging-java (1.1.1-9build1) quantal; urgency=low + * Fix Bundle-SymbolicName commons-logging -> org.apache.commons.logging + (Closes: #705421). + * Add Jakub Adam to Uploaders. + * Fix a typo in package synopsis. - * No-change rebuild with openjdk-7 as default-jdk. + -- Jakub Adam Mon, 15 Apr 2013 18:33:00 +0200 - -- James Page Fri, 18 May 2012 11:42:34 +0100 +libcommons-logging-java (1.1.2-1) experimental; urgency=low + + * Team upload. + * New upstream release. + * Updated Standards-Version to 3.9.4: no changes needed. + * Refreshed the patches + * Fixed the outdated OSGi metadata + * Upgraded the dependency on the Servlet API (2.5 -> 3.0) + * debian/copyright: converted to DEP5 format, updated the contributors + * debian/rules: the clean target now properly removes the debian/.mh directory + + -- Emmanuel Bourg Thu, 04 Apr 2013 14:48:38 +0200 libcommons-logging-java (1.1.1-9) unstable; urgency=low @@ -157,7 +174,7 @@ * debian/copyright: + Add copyright, upstream authors. + Add Debian packaging copyright. - + -- Kumar Appaiah Wed, 26 Sep 2007 06:51:56 +0530 libcommons-logging-java (1.0.4-6) unstable; urgency=low @@ -179,7 +196,7 @@ libcommons-logging-java (1.0.4-4) unstable; urgency=low - * kaffe compiler transition + * kaffe compiler transition -- Wolfgang Baer Sun, 15 Jan 2006 17:55:22 +0100 @@ -229,7 +246,7 @@ libcommons-logging-java (1.0.3-3) unstable; urgency=low * Move to main. (closes: #237365) - * remove libcommons-logging-java-doc because main tools couldn't + * remove libcommons-logging-java-doc because main tools couldn't support javadoc. -- Takashi Okamoto Sat, 1 May 2004 18:06:52 +0900 diff -Nru libcommons-logging-java-1.1.1/debian/control libcommons-logging-java-1.1.3/debian/control --- libcommons-logging-java-1.1.1/debian/control 2012-07-12 14:25:09.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/control 2013-04-30 02:53:35.000000000 +0000 @@ -1,9 +1,9 @@ Source: libcommons-logging-java Section: java Priority: optional -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Debian Java Maintainers -Uploaders: Varun Hiremath , Niels Thykier +Maintainer: Debian Java Maintainers +Uploaders: Varun Hiremath , Niels Thykier , + Emmanuel Bourg , Jakub Adam Build-Depends: ant-optional, cdbs, debhelper (>= 7), default-jdk Build-Depends-Indep: junit, libavalon-framework-java, @@ -12,7 +12,7 @@ liblog4j1.2-java, libservlet3.0-java, maven-repo-helper -Standards-Version: 3.9.2 +Standards-Version: 3.9.4 Vcs-Svn: svn://svn.debian.org/svn/pkg-java/trunk/libcommons-logging-java Vcs-Browser: http://svn.debian.org/wsvn/pkg-java/trunk/libcommons-logging-java Homepage: http://commons.apache.org/logging @@ -25,7 +25,7 @@ libexcalibur-logkit-java, liblog4j1.2-java, libservlet3.0-java -Description: commmon wrapper interface for several logging APIs +Description: common wrapper interface for several logging APIs Provides a simple, component oriented interface together with wrappers for several existing java logging systems. The user can choose at runtime which system he want to use for logging. @@ -34,7 +34,7 @@ Section: doc Architecture: all Depends: ${misc:Depends} -Description: commmon wrapper interface for several logging APIs (documentation) +Description: common wrapper interface for several logging APIs (documentation) Provides a simple, component oriented interface together with wrappers for several existing java logging systems. The user can choose at runtime which system he want to use for logging. diff -Nru libcommons-logging-java-1.1.1/debian/copyright libcommons-logging-java-1.1.3/debian/copyright --- libcommons-logging-java-1.1.1/debian/copyright 2009-07-02 12:23:07.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/copyright 2013-04-04 16:30:16.000000000 +0000 @@ -1,32 +1,38 @@ -This package was debianized by Takashi Okamoto on -Mon, 5 Nov 2001 08:15:04 +0900. - -It was downloaded from http://commons.apache.org/logging/ - -Upstream Authors: Morgan Delagrange , - Rodney Waldhoff , - Craig McClanahan , - Scott Sanders , - Robert Burrell Donkin , - Peter Donald , - Costin Manolache , - Richard Sitze , - Juozas Baliuka , - Simon Kitching , - Dennis Lundberg , - Brian Stansberry - -Copyright: 2001-2008 The Apache Software Foundation - -License: Apache 2.0 - -On Debian systems the full text of the Apache License can be found -in `/usr/share/common-licenses/Apache-2.0'. - -Debian packaging: Copyright 2001 - 2004, Takashi Okamoto - Copyright 2005 - 2007, Arnaud Vandyck , Wolfgang Baer - Copyright 2007, Michael Koch, , Varun Hiremath , - Kumar Appaiah - -The Debian packaging of this package is licensed under the Apache -Software License 2.0 (see above). +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Apache Commons Logging +Upstream-Contact: Apache Commons Developers +Source: http://commons.apache.org/logging/ + +Files: * +Copyright: 2001-2013, The Apache Software Foundation. +License: Apache-2.0 +Comment: + Upstream authors: Juozas Baliuka , + Morgan Delagrange , + Peter Donald , + Robert Burrell Donkin , + Simon Kitching , + Dennis Lundberg , + Costin Manolache , + Craig McClanahan , + Thomas Neidhart , + Scott Sanders , + Richard Sitze , + Brian Stansberry, + Rodney Waldhoff , + Matthew P. Del Buono, + Vince Eagen , + Peter Lawrey, + Berin Loritsch , + Philippe Mouawad, + Neeme Praks + +Files: debian/* +License: Apache-2.0 +Copyright: 2001-2004, Takashi Okamoto + 2005-2007, Arnaud Vandyck , Wolfgang Baer + 2007, Michael Koch, , Varun Hiremath , Kumar Appaiah + +License: Apache-2.0 + On Debian systems, the full text of the Apache License can be found + in the file `/usr/share/common-licenses/Apache-2.0'. diff -Nru libcommons-logging-java-1.1.1/debian/libcommons-logging-java-doc.docs libcommons-logging-java-1.1.3/debian/libcommons-logging-java-doc.docs --- libcommons-logging-java-1.1.1/debian/libcommons-logging-java-doc.docs 2009-08-02 23:10:10.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/libcommons-logging-java-doc.docs 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -STATUS.html - diff -Nru libcommons-logging-java-1.1.1/debian/maven.rules libcommons-logging-java-1.1.3/debian/maven.rules --- libcommons-logging-java-1.1.1/debian/maven.rules 2012-07-12 14:24:02.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/maven.rules 2013-04-04 16:30:16.000000000 +0000 @@ -3,3 +3,4 @@ # force using servlet 3.0 javax.servlet * * s/.*/3.0/ s/avalon-framework/org.apache.avalon/ avalon-framework jar s/.*/debian/ + diff -Nru libcommons-logging-java-1.1.1/debian/patches/01_target13_BuildXml.patch libcommons-logging-java-1.1.3/debian/patches/01_target13_BuildXml.patch --- libcommons-logging-java-1.1.1/debian/patches/01_target13_BuildXml.patch 2009-11-28 08:40:31.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/patches/01_target13_BuildXml.patch 2013-04-04 16:30:16.000000000 +0000 @@ -1,19 +1,17 @@ Description: Bumbs the source and target version options for the java compiler. - -diff -Nur libcommons-logging-java-1.1.1/build.xml libcommons-logging-java-1.1.1.new/build.xml ---- libcommons-logging-java-1.1.1/build.xml 2007-11-22 04:57:52.000000000 +0530 -+++ libcommons-logging-java-1.1.1.new/build.xml 2007-12-10 09:10:40.000000000 +0530 -@@ -127,10 +127,10 @@ - - - -- -+ - - -- -+ - - - - +Forwarded: not-needed +--- a/build.xml ++++ b/build.xml +@@ -130,10 +130,10 @@ + + + +- ++ + + +- ++ + + + diff -Nru libcommons-logging-java-1.1.1/debian/patches/02_build_javadoc.patch libcommons-logging-java-1.1.3/debian/patches/02_build_javadoc.patch --- libcommons-logging-java-1.1.1/debian/patches/02_build_javadoc.patch 2009-11-28 08:40:31.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/patches/02_build_javadoc.patch 2013-05-21 23:50:34.000000000 +0000 @@ -1,54 +1,53 @@ Description: Adds a target to generate the javadoc. - -diff -Nur libcommons-logging-java-1.1.1/build.xml libcommons-logging-java-1.1.1.new/build.xml ---- libcommons-logging-java-1.1.1/build.xml 2007-12-10 08:55:12.000000000 +0530 -+++ libcommons-logging-java-1.1.1.new/build.xml 2007-12-10 08:55:55.000000000 +0530 -@@ -625,7 +625,7 @@ - - - -- - - -@@ -784,5 +784,39 @@ - One or more unit tests failed. - - -+ -+ -+ -+ -+ -+ -+ -+ - - +Forwarded: not-needed +--- a/build.xml ++++ b/build.xml +@@ -613,7 +613,7 @@ + + + +- + + +@@ -773,4 +773,39 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ + diff -Nru libcommons-logging-java-1.1.1/debian/patches/03_disable_securityallow_test.patch libcommons-logging-java-1.1.3/debian/patches/03_disable_securityallow_test.patch --- libcommons-logging-java-1.1.1/debian/patches/03_disable_securityallow_test.patch 2007-12-29 14:48:40.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/patches/03_disable_securityallow_test.patch 2013-04-04 16:30:16.000000000 +0000 @@ -1,27 +1,23 @@ -This patch has been added to disable the SecurityAllowedTestCase -altogether, as it fails to complete successfully on GCJ. The issue -seems to be with GCJ, so till the time that GCJ is fixed, we don't run -this test. - -Kumar Appaiah - -diff -Nur libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/security/SecurityAllowedTestCase.java libcommons-logging-java-1.1.1.new/src/test/org/apache/commons/logging/security/SecurityAllowedTestCase.java ---- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/security/SecurityAllowedTestCase.java 2007-11-22 04:57:51.000000000 +0530 -+++ libcommons-logging-java-1.1.1.new/src/test/org/apache/commons/logging/security/SecurityAllowedTestCase.java 2007-12-29 18:30:21.000000000 +0530 -@@ -89,7 +89,7 @@ - mySecurityManager.addPermission(new AllPermission()); - System.setSecurityManager(mySecurityManager); - -- try { -+ /* try { - // Use reflection so that we can control exactly when the static - // initialiser for the LogFactory class is executed. - Class c = this.getClass().getClassLoader().loadClass( -@@ -130,6 +130,6 @@ - PrintWriter pw = new PrintWriter(sw); - t.printStackTrace(pw); - fail("Unexpected exception:" + t.getMessage() + ":" + sw.toString()); -- } -+ }*/ - } - } +Description: This patch has been added to disable the SecurityAllowedTestCase + altogether, as it fails to complete successfully on GCJ. The issue + seems to be with GCJ, so till the time that GCJ is fixed, we don't run + this test. +Author: Kumar Appaiah +Forwarded: not-needed +--- a/src/test/java/org/apache/commons/logging/security/SecurityAllowedTestCase.java ++++ b/src/test/java/org/apache/commons/logging/security/SecurityAllowedTestCase.java +@@ -92,6 +92,7 @@ + mySecurityManager.addPermission(new AllPermission()); + System.setSecurityManager(mySecurityManager); + ++ /* + try { + // Use reflection so that we can control exactly when the static + // initialiser for the LogFactory class is executed. +@@ -136,5 +137,6 @@ + t.printStackTrace(pw); + fail("Unexpected exception:" + t.getMessage() + ":" + sw.toString()); + } ++ */ + } + } diff -Nru libcommons-logging-java-1.1.1/debian/patches/04_fix_jarname.patch libcommons-logging-java-1.1.3/debian/patches/04_fix_jarname.patch --- libcommons-logging-java-1.1.1/debian/patches/04_fix_jarname.patch 2007-12-29 14:48:40.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/patches/04_fix_jarname.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -Upstream has named the JARs as commons-logging--SNAPSHOT.jar -this time. We don't really want the snapshot, as the JAR should be the -same as the upstream version. - -Kumar Appaiah - -diff -Nur libcommons-logging-java-1.1.1/build.xml libcommons-logging-java-1.1.1.new/build.xml ---- libcommons-logging-java-1.1.1/build.xml 2007-12-29 18:33:28.000000000 +0530 -+++ libcommons-logging-java-1.1.1.new/build.xml 2007-12-29 18:33:36.000000000 +0530 -@@ -94,7 +94,7 @@ - - - -- -+ - - - diff -Nru libcommons-logging-java-1.1.1/debian/patches/05_OSGi_metadata.patch libcommons-logging-java-1.1.3/debian/patches/05_OSGi_metadata.patch --- libcommons-logging-java-1.1.1/debian/patches/05_OSGi_metadata.patch 2009-11-28 08:23:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/patches/05_OSGi_metadata.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -Description: Adds OSGi metadata to the jar file. -Origin: Fedora - ---- a/src/conf/MANIFEST.MF 2006-08-10 18:13:20.000000000 -0400 -+++ b/src/conf/MANIFEST.MF 2007-07-11 13:19:50.000000000 -0400 -@@ -6,3 +6,12 @@ - Implementation-Vendor-Id: org.apache - Implementation-Vendor: Apache Software Foundation - Implementation-Version: 1.1.1 -+Bundle-ManifestVersion: 2 -+Export-Package: org.apache.commons.logging;version="1.0.4",org.apache. -+ commons.logging.impl;version="1.0.4" -+Bundle-Version: 1.0.4.v20080605-1930 -+Bundle-SymbolicName: org.apache.commons.logging -+Bundle-Name: Apache Commons Logging Plug-in -+Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3 -+Bundle-Localization: plugin -+Bundle-Vendor: Apache Software Foundation diff -Nru libcommons-logging-java-1.1.1/debian/patches/06_classpath_manifest.patch libcommons-logging-java-1.1.3/debian/patches/06_classpath_manifest.patch --- libcommons-logging-java-1.1.1/debian/patches/06_classpath_manifest.patch 2012-07-12 14:24:25.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/patches/06_classpath_manifest.patch 2013-05-21 23:50:34.000000000 +0000 @@ -1,9 +1,9 @@ -Index: libcommons-logging-java-1.1.1/src/conf/MANIFEST.MF -=================================================================== ---- libcommons-logging-java-1.1.1.orig/src/conf/MANIFEST.MF 2010-03-17 18:23:29.000000000 +0530 -+++ libcommons-logging-java-1.1.1/src/conf/MANIFEST.MF 2010-03-17 20:10:50.000000000 +0530 -@@ -15,3 +15,4 @@ - Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3 - Bundle-Localization: plugin - Bundle-Vendor: Apache Software Foundation -+Class-Path: avalon-framework.jar excalibur-logkit.jar log4j-1.2.jar servlet-api-3.0.jar +Description: Adds the classpath entry to the manifest file +Forwarded: not-needed +--- a/src/conf/MANIFEST.MF ++++ b/src/conf/MANIFEST.MF +@@ -26,3 +26,4 @@ + Include-Resource: META-INF/NOTICE.txt=NOTICE.txt,META-INF/LICENSE.txt= + LICENSE.txt + Specification-Version: 1.1.3 ++Class-Path: avalon-framework.jar excalibur-logkit.jar log4j-1.2.jar servlet-api-3.0.jar diff -Nru libcommons-logging-java-1.1.1/debian/patches/series libcommons-logging-java-1.1.3/debian/patches/series --- libcommons-logging-java-1.1.1/debian/patches/series 2010-03-17 14:45:24.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/patches/series 2013-05-21 23:50:34.000000000 +0000 @@ -1,6 +1,4 @@ 01_target13_BuildXml.patch 02_build_javadoc.patch 03_disable_securityallow_test.patch -04_fix_jarname.patch -05_OSGi_metadata.patch 06_classpath_manifest.patch diff -Nru libcommons-logging-java-1.1.1/debian/rules libcommons-logging-java-1.1.3/debian/rules --- libcommons-logging-java-1.1.1/debian/rules 2012-07-12 14:23:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/rules 2013-04-04 16:30:16.000000000 +0000 @@ -25,7 +25,7 @@ dh_link usr/share/java/commons-logging-adapters-$(VERSION).jar usr/share/java/commons-logging-adapters.jar clean:: - rm -rf debian/tmp + mh_clean get-orig-source: -uscan --download-version $(DEB_UPSTREAM_VERSION) --force-download --rename diff -Nru libcommons-logging-java-1.1.1/debian/watch libcommons-logging-java-1.1.3/debian/watch --- libcommons-logging-java-1.1.1/debian/watch 2009-06-17 08:55:12.000000000 +0000 +++ libcommons-logging-java-1.1.3/debian/watch 2013-04-04 16:30:16.000000000 +0000 @@ -1,2 +1,2 @@ version=3 -http://www.apache.org/dist/commons/logging/source/commons-logging-(.*)-src\.tar\.gz debian uupdate +http://archive.apache.org/dist/commons/logging/source/commons-logging-(.*)-src\.tar\.gz debian uupdate diff -Nru libcommons-logging-java-1.1.1/doap_logging.rdf libcommons-logging-java-1.1.3/doap_logging.rdf --- libcommons-logging-java-1.1.1/doap_logging.rdf 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/doap_logging.rdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ - - - - Apache Commons Logging - - Java - - - - - - Commons Logging - - Commons Logging is a thin adapter allowing configurable bridging to other, - well known logging systems. - - - - - - - - - - commons-logging - 2004-06-15 - 1.0.4 - - - - - diff -Nru libcommons-logging-java-1.1.1/license-header.txt libcommons-logging-java-1.1.3/license-header.txt --- libcommons-logging-java-1.1.1/license-header.txt 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/license-header.txt 2013-05-16 20:04:22.000000000 +0000 @@ -1,18 +1,16 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ \ No newline at end of file +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff -Nru libcommons-logging-java-1.1.1/maven.xml libcommons-logging-java-1.1.3/maven.xml --- libcommons-logging-java-1.1.1/maven.xml 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/maven.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - Unit testing cannot be done in Maven; the tests require classpaths and - system properties to be set differently for different unit tests which - Maven does not support. Please run "ant test" to execute the unit tests. - - - - - - - - ${maven.build.dir}/logging-api-work - - - - - - - - - - - - - - - - - - - - - - - - diff -Nru libcommons-logging-java-1.1.1/pom.xml libcommons-logging-java-1.1.3/pom.xml --- libcommons-logging-java-1.1.1/pom.xml 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/pom.xml 2013-05-16 20:04:22.000000000 +0000 @@ -1,523 +1,523 @@ - - - - - org.apache.commons - commons-parent - 5 - - 4.0.0 - commons-logging - commons-logging - Commons Logging - 1.1.1 - Commons Logging is a thin adapter allowing configurable bridging to other, - well known logging systems. - http://commons.apache.org/logging - - - JIRA - http://issues.apache.org/jira/browse/LOGGING - - - 2001 - - - - morgand - Morgan Delagrange - morgand at apache dot org - Apache - - Java Developer - - - - rwaldhoff - Rodney Waldhoff - rwaldhoff at apache org - Apache Software Foundation - - - craigmcc - Craig McClanahan - craigmcc at apache org - Apache Software Foundation - - - sanders - Scott Sanders - sanders at apache dot org - Apache Software Foundation - - - rdonkin - Robert Burrell Donkin - rdonkin at apache dot org - Apache Software Foundation - - - donaldp - Peter Donald - donaldp at apache dot org - - - costin - Costin Manolache - costin at apache dot org - Apache Software Foundation - - - rsitze - Richard Sitze - rsitze at apache dot org - Apache Software Foundation - - - baliuka - Juozas Baliuka - baliuka@apache.org - - Java Developer - - - - skitching - Simon Kitching - skitching@apache.org - Apache Software Foundation - - - dennisl - Dennis Lundberg - dennisl@apache.org - Apache Software Foundation - - - bstansberry - Brian Stansberry - - - - - scm:svn:http://svn.apache.org/repos/asf/commons/proper/logging/tags/commons-logging-1.1.1 - scm:svn:https://svn.apache.org/repos/asf/commons/proper/logging/tags/commons-logging-1.1.1 - http://svn.apache.org/repos/asf/commons/proper/logging/tags/commons-logging-1.1.1 - - - - src/java - src/test - - - - src/test - false - - **/*.properties - - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - src/conf/MANIFEST.MF - - - ${maven.compile.target} - - - - - - testjar - package - - test-jar - - - commons-logging - - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.1 - - - apijar - package - - - - - - - - - - - - - - - - - - - - - - - - - - run - - - - adaptersjar - package - - - - - - - - - - - - - - - - - - - - - - - run - - - - site.resources - site - - - - - - - - - - - - - - - run - - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.0 - - - attach-artifacts - package - - attach-artifact - - - - - ${project.build.directory}/${project.artifactId}-adapters-${project.version}.jar - jar - adapters - - - ${project.build.directory}/${project.artifactId}-api-${project.version}.jar - jar - api - - - - - - - - - org.apache.maven.plugins - maven-release-plugin - 2.0-beta-6 - - - site deploy - - -Prelease - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - **/AvalonLoggerTestCase.java - - - - - - integration-test - integration-test - - test - - - - **/*TestCase.java - - - - - commons-logging - target/${project.build.finalName}.jar - - - commons-logging-api - target/${project.artifactId}-api-${project.version}.jar - - - commons-logging-adapters - target/${project.artifactId}-adapters-${project.version}.jar - - - testclasses - target/commons-logging-tests.jar - - - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 2.2-beta-1 - - - false - - src/assembly/bin.xml - src/assembly/src.xml - - gnu - - - - - org.apache.maven.plugins - maven-site-plugin - 2.0-beta-5 - - - - - - - - - ci - - - apache.snapshots - Apache Development Snapshot Repository - ${commons.deployment.protocol}://people.apache.org/www/people.apache.org/repo/m2-snapshot-repository - - - apache.snapshots - Apache Development Snapshot Repository - ${commons.deployment.protocol}://people.apache.org/www/people.apache.org/repo/m2-snapshot-repository - - - - - release - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - - single - - package - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.3 - - - ${deploy.altRepository} - true - - - - - - - - - - junit - junit - 3.8.1 - test - - - log4j - log4j - 1.2.12 - true - - - logkit - logkit - 1.0.1 - true - - - avalon-framework - avalon-framework - 4.1.3 - true - - - javax.servlet - servlet-api - 2.3 - provided - true - - - - - - - - org.codehaus.mojo - clirr-maven-plugin - 2.1.1 - - - org.codehaus.mojo - jdepend-maven-plugin - 2.0-beta-1 - - - - - - - apache.website - ${commons.deployment.protocol}://people.apache.org/www/commons.apache.org/logging/ - - - - - 1.2 - 1.1 - - \ No newline at end of file + + + + + org.apache.commons + commons-parent + 28 + + 4.0.0 + commons-logging + commons-logging + Commons Logging + 1.1.3 + Commons Logging is a thin adapter allowing configurable bridging to other, + well known logging systems. + http://commons.apache.org/proper/commons-logging/ + + + JIRA + http://issues.apache.org/jira/browse/LOGGING + + + 2001 + + + + baliuka + Juozas Baliuka + baliuka@apache.org + + Java Developer + + + + morgand + Morgan Delagrange + morgand@apache.org + Apache + + Java Developer + + + + donaldp + Peter Donald + donaldp@apache.org + + + rdonkin + Robert Burrell Donkin + rdonkin@apache.org + The Apache Software Foundation + + + skitching + Simon Kitching + skitching@apache.org + The Apache Software Foundation + + + dennisl + Dennis Lundberg + dennisl@apache.org + The Apache Software Foundation + + + costin + Costin Manolache + costin@apache.org + The Apache Software Foundation + + + craigmcc + Craig McClanahan + craigmcc@apache.org + The Apache Software Foundation + + + tn + Thomas Neidhart + tn@apache.org + The Apache Software Foundation + + + sanders + Scott Sanders + sanders@apache.org + The Apache Software Foundation + + + rsitze + Richard Sitze + rsitze@apache.org + The Apache Software Foundation + + + bstansberry + Brian Stansberry + + + rwaldhoff + Rodney Waldhoff + rwaldhoff@apache.org + The Apache Software Foundation + + + + + Matthew P. Del Buono + + Provided patch + + + + Vince Eagen + vince256 at comcast dot net + + Lumberjack logging abstraction + + + + Peter Lawrey + + Provided patch + + + + Berin Loritsch + bloritsch at apache dot org + + Lumberjack logging abstraction + JDK 1.4 logging abstraction + + + + Philippe Mouawad + + Provided patch + + + + Neeme Praks + neeme at apache dot org + + Avalon logging abstraction + + + + + + + scm:svn:http://svn.apache.org/repos/asf/commons/proper/logging/trunk + scm:svn:https://svn.apache.org/repos/asf/commons/proper/logging/trunk + http://svn.apache.org/repos/asf/commons/proper/logging/trunk + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + testjar + package + + test-jar + + + commons-logging + + + + + apijar + package + + jar + + + ${project.artifactId}-api-${project.version} + + org/apache/commons/logging/*.class + org/apache/commons/logging/impl/LogFactoryImpl*.class + org/apache/commons/logging/impl/WeakHashtable*.class + org/apache/commons/logging/impl/SimpleLog*.class + org/apache/commons/logging/impl/NoOpLog*.class + org/apache/commons/logging/impl/Jdk14Logger.class + META-INF/LICENSE.txt + META-INF/NOTICE.txt + + + **/package.html + + + + + + adaptersjar + package + + jar + + + ${project.artifactId}-adapters-${project.version} + + org/apache/commons/logging/impl/**.class + META-INF/LICENSE.txt + META-INF/NOTICE.txt + + + org/apache/commons/logging/impl/WeakHashtable*.class + org/apache/commons/logging/impl/LogFactoryImpl*.class + + + + + + + fulljar + package + + jar + + + ${project.artifactId}-${project.version} + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + site.resources + site + + + + + + + + + + + run + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.0 + + + attach-artifacts + package + + attach-artifact + + + + + ${project.build.directory}/${project.artifactId}-adapters-${project.version}.jar + jar + adapters + + + ${project.build.directory}/${project.artifactId}-api-${project.version}.jar + jar + api + + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + org.codehaus.mojo + cobertura-maven-plugin + ${commons.cobertura.version} + + true + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${commons.surefire.version} + + + integration-test + + integration-test + verify + + + + **/*TestCase.java + + + + ${log4j:log4j:jar} + ${logkit:logkit:jar} + ${javax.servlet:servlet-api:jar} + target/${project.build.finalName}.jar + target/${project.artifactId}-api-${project.version}.jar + target/${project.artifactId}-adapters-${project.version}.jar + target/commons-logging-tests.jar + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.3 + + + src/main/assembly/bin.xml + src/main/assembly/src.xml + + gnu + + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.4 + + + + properties + + + + + + + org.apache.maven.plugins + maven-scm-publish-plugin + + + javadocs + commons-logging-** + + + + + + + + + + junit + junit + 3.8.1 + test + + + log4j + log4j + 1.2.17 + true + + + logkit + logkit + 1.0.1 + true + + + avalon-framework + avalon-framework + 4.1.5 + true + + + javax.servlet + servlet-api + 2.3 + provided + true + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.7 + + ${basedir}/checkstyle.xml + false + ${basedir}/license-header.txt + + + + org.codehaus.mojo + clirr-maven-plugin + 2.2.2 + + + org.codehaus.mojo + jdepend-maven-plugin + 2.0-beta-1 + + + + + + + apache.website + ${commons.deployment.protocol}://people.apache.org/www/commons.apache.org/logging/ + + + + + 1.2 + 1.1 + logging + 1.1.3 + LOGGING + 12310484 + + RC2 + 2.12 + true + + + javax.servlet;version="[2.1.0, 3.0.0)";resolution:=optional, + org.apache.avalon.framework.logger;version="[4.1.3, 4.1.5]";resolution:=optional, + org.apache.log;version="[1.0.1, 1.0.1]";resolution:=optional, + org.apache.log4j;version="[1.2.15, 2.0.0)";resolution:=optional + + + diff -Nru libcommons-logging-java-1.1.1/project.properties libcommons-logging-java-1.1.3/project.properties --- libcommons-logging-java-1.1.1/project.properties 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/project.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -maven.repo.remote=http://repo1.maven.org/maven - -maven.changelog.factory=org.apache.maven.svnlib.SvnChangeLogFactory - -maven.checkstyle.properties=checkstyle.xml - -# documentation properties -maven.xdoc.date=left -maven.xdoc.version=${pom.currentVersion} -maven.xdoc.developmentProcessUrl=http://commons.apache.org/charter.html -maven.xdoc.poweredby.image=maven-feather.png - -# Jar Manifest Additional Attributes -maven.jar.manifest.attributes.list=Implementation-Vendor-Id,X-Compile-Source-JDK,X-Compile-Target-JDK -maven.jar.manifest.attribute.Implementation-Vendor-Id=org.apache -maven.jar.manifest.attribute.X-Compile-Source-JDK=${maven.compile.source} -maven.jar.manifest.attribute.X-Compile-Target-JDK=${maven.compile.target} - -maven.junit.fork=true - -# generate .class files that can be loaded into a version 1.1 JVM. -maven.compile.target=1.1 -maven.compile.source=1.2 diff -Nru libcommons-logging-java-1.1.1/project.xml libcommons-logging-java-1.1.3/project.xml --- libcommons-logging-java-1.1.1/project.xml 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/project.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,298 +0,0 @@ - - - - 3 - - Logging - commons-logging - commons-logging - 1.1.1-SNAPSHOT - 2001 - Commons Logging - - Commons Logging is a thin adapter allowing configurable bridging to other, - well known logging systems. - - /images/logo.png - - http://commons.apache.org/logging/ - org.apache.commons.logging - - - The Apache Software Foundation - http://commons.apache.org/ - http://commons.apache.org/images/logo.png - - - - - The Apache Software License, Version 2.0 - /LICENSE.txt - repo - - - - commons - http://issues.apache.org/jira/browse/LOGGING - people.apache.org - /www/commons.apache.org/logging/ - /www/people.apache.org/builds/commons/logging/ - - - scm:svn:http://svn.apache.org/repos/asf/commons/proper/logging/trunk/ - http://svn.apache.org/repos/asf/commons/proper/logging/trunk/ - - - - - 1.0.1 - 1.0.1 - LOGGING_1_0_1 - - - 1.0.2 - 1.0.2 - LOGGING_1_0_2 - - - 1.0.3 - 1.0.3 - LOGGING_1_0_3 - - - 1.0.4 - 1.0.4 - LOGGING_1_0_4 - - - 1.1 - 1.1 - LOGGING_1_1_0 - - - - - - Commons Dev List - dev-subscribe@commons.apache.org - dev-unsubscribe@commons.apache.org - http://mail-archives.apache.org/mod_mbox/commons-dev/ - - - Commons User List - user-subscribe@commons.apache.org - user-unsubscribe@commons.apache.org - http://mail-archives.apache.org/mod_mbox/commons-user/ - - - - - - Morgan Delagrange - morgand - morgand at apache dot org - Apache - Java Developer - - - Rodney Waldhoff - rwaldhoff - rwaldhoff at apache org - Apache Software Foundation - - - Craig McClanahan - craigmcc - craigmcc at apache org - Apache Software Foundation - - - Scott Sanders - sanders - sanders at apache dot org - Apache Software Foundation - - - Robert Burrell Donkin - rdonkin - rdonkin at apache dot org - Apache Software Foundation - - - Peter Donald - donaldp - donaldp at apache dot org - - - - Costin Manolache - costin - costin at apache dot org - Apache Software Foundation - - - Richard Sitze - rsitze - rsitze at apache dot org - Apache Software Foundation - - - Juozas Baliuka - baliuka - baliuka@apache.org - - - Java Developer - - - - Simon Kitching - skitching - skitching@apache.org - Apache Software Foundation - - - Dennis Lundberg - dennisl - dennisl@apache.org - Apache Software Foundation - - - Brian Stansberry - bstansberry - - - - - - - log4j - log4j - 1.2.12 - http://logging.apache.org/log4j/docs/index.html - - -Runtime Optional. -1.2.12 required for compilation but 1.2.6 onwards supported at runtime. - - true - - - - - logkit - logkit - 1.0.1 - http://avalon.apache.org/logkit/ - - Runtime Optional - true - - - - - junit - junit - 3.8.1 - http://www.junit.org/index.htm - - Used for testing only. - test - true - - - - - avalon-framework - avalon-framework - 4.1.3 - http://avalon.apache.org/ - - Runtime Optional - true - - - - - javax.servlet - servlet-api - 2.3 - http://java.sun.com/products/servlet/ - - Used only by servlet filter. Not used by core logging implementation. - true - - - - - maven - maven-xdoc-plugin - 1.9.2 - http://maven.apache.org/maven-1.x/reference/plugins/xdoc/ - plugin - - - <strong>Site Only</strong> - v1.9.2 (minimum) - - true - - - - - dev@commons.apache.org - src/java - src/test - - - java.util.logging.Logger - - **/Jdk14Logger.java - - - - - - - **/AvalonLoggerTest.java - - - - - - - maven-javadoc-plugin - maven-jdepend-plugin - maven-junit-report-plugin - maven-jxr-plugin - maven-license-plugin - - - - - diff -Nru libcommons-logging-java-1.1.1/src/assembly/bin.xml libcommons-logging-java-1.1.3/src/assembly/bin.xml --- libcommons-logging-java-1.1.1/src/assembly/bin.xml 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/assembly/bin.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - bin - - tar.gz - zip - - true - - - - LICENSE* - NOTICE* - RELEASE-NOTES* - - - - target - - - *.jar - - - - \ No newline at end of file diff -Nru libcommons-logging-java-1.1.1/src/assembly/src.xml libcommons-logging-java-1.1.3/src/assembly/src.xml --- libcommons-logging-java-1.1.1/src/assembly/src.xml 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/assembly/src.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ - - - - src - - tar.gz - zip - - ${artifactId}-${version}-src - - - . - - true - - **/target/** - - - - \ No newline at end of file diff -Nru libcommons-logging-java-1.1.1/src/changes/changes.xml libcommons-logging-java-1.1.3/src/changes/changes.xml --- libcommons-logging-java-1.1.1/src/changes/changes.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/changes/changes.xml 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,100 @@ + + + + + + + Release Notes + + + + + Use "org.apache.commons.logging" as bundle symbolic name. + + + + + The jar manifest now contains proper OSGi-related metadata information. + + + LogFactory and LogFactoryImpl will not swallow certain errors anymore (ThreadDeath + and VirtualMachineError). + + + Improved thread-safety for several log adapters, including AvalonLogger, SimpleLog, + Log4JLogger, LogKitLogger. + + + In case of a discovery failure now also the stacktrace of the cause will be + added to the diagnostic message. + + + Jdk14Logger now correctly uses the specified logger name. + + + Change scope of Jdk14Logger.log(Level, String, Throwable) to protected, allowing + subclasses to modify the logging output. + + + Properly synchronize access to protected static field LogFactory.nullClassLoaderFactory. + + + Prevent potential deadlock scenario in WeakHashtable. + + + Potential missing privileged block for class loader. + + + LogFactoryImpl.setAttribute - possible NPE. + + + Log4JLogger uses deprecated static members of Priority such as INFO. + + + Static analysis suggests a number of potential improvements. + + + SimpleLog.log - unsafe update of shortLogName. + + + LogFactory.diagnosticPrefix and diagnosticsStream could be final. + + + + diff -Nru libcommons-logging-java-1.1.1/src/changes/release-notes.vm libcommons-logging-java-1.1.3/src/changes/release-notes.vm --- libcommons-logging-java-1.1.1/src/changes/release-notes.vm 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/changes/release-notes.vm 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,109 @@ +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License. + Apache ${project.name} + Version ${version} + RELEASE NOTES + +The ${developmentTeam} is pleased to announce the release of Apache ${project.name} ${version} + +$introduction.replaceAll("(?A simple logging interface abstracting logging APIs. In order to be - * instantiated successfully by {@link LogFactory}, classes that implement - * this interface must have a constructor that takes a single String - * parameter representing the "name" of this Log.

- * - *

The six logging levels used by Log are (in order): - *

    - *
  1. trace (the least serious)
  2. - *
  3. debug
  4. - *
  5. info
  6. - *
  7. warn
  8. - *
  9. error
  10. - *
  11. fatal (the most serious)
  12. - *
- * The mapping of these log levels to the concepts used by the underlying - * logging system is implementation dependent. - * The implemention should ensure, though, that this ordering behaves - * as expected.

- * - *

Performance is often a logging concern. - * By examining the appropriate property, - * a component can avoid expensive operations (producing information - * to be logged).

- * - *

For example, - *

- *    if (log.isDebugEnabled()) {
- *        ... do something expensive ...
- *        log.debug(theResult);
- *    }
- * 
- *

- * - *

Configuration of the underlying logging system will generally be done - * external to the Logging APIs, through whatever mechanism is supported by - * that system.

- * - * @author Scott Sanders - * @author Rod Waldhoff - * @version $Id: Log.java 424107 2006-07-20 23:15:42Z skitching $ - */ -public interface Log { - - - // ----------------------------------------------------- Logging Properties - - - /** - *

Is debug logging currently enabled?

- * - *

Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than debug.

- * - * @return true if debug is enabled in the underlying logger. - */ - public boolean isDebugEnabled(); - - - /** - *

Is error logging currently enabled?

- * - *

Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than error.

- * - * @return true if error is enabled in the underlying logger. - */ - public boolean isErrorEnabled(); - - - /** - *

Is fatal logging currently enabled?

- * - *

Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than fatal.

- * - * @return true if fatal is enabled in the underlying logger. - */ - public boolean isFatalEnabled(); - - - /** - *

Is info logging currently enabled?

- * - *

Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than info.

- * - * @return true if info is enabled in the underlying logger. - */ - public boolean isInfoEnabled(); - - - /** - *

Is trace logging currently enabled?

- * - *

Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than trace.

- * - * @return true if trace is enabled in the underlying logger. - */ - public boolean isTraceEnabled(); - - - /** - *

Is warn logging currently enabled?

- * - *

Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than warn.

- * - * @return true if warn is enabled in the underlying logger. - */ - public boolean isWarnEnabled(); - - - // -------------------------------------------------------- Logging Methods - - - /** - *

Log a message with trace log level.

- * - * @param message log this message - */ - public void trace(Object message); - - - /** - *

Log an error with trace log level.

- * - * @param message log this message - * @param t log this cause - */ - public void trace(Object message, Throwable t); - - - /** - *

Log a message with debug log level.

- * - * @param message log this message - */ - public void debug(Object message); - - - /** - *

Log an error with debug log level.

- * - * @param message log this message - * @param t log this cause - */ - public void debug(Object message, Throwable t); - - - /** - *

Log a message with info log level.

- * - * @param message log this message - */ - public void info(Object message); - - - /** - *

Log an error with info log level.

- * - * @param message log this message - * @param t log this cause - */ - public void info(Object message, Throwable t); - - - /** - *

Log a message with warn log level.

- * - * @param message log this message - */ - public void warn(Object message); - - - /** - *

Log an error with warn log level.

- * - * @param message log this message - * @param t log this cause - */ - public void warn(Object message, Throwable t); - - - /** - *

Log a message with error log level.

- * - * @param message log this message - */ - public void error(Object message); - - - /** - *

Log an error with error log level.

- * - * @param message log this message - * @param t log this cause - */ - public void error(Object message, Throwable t); - - - /** - *

Log a message with fatal log level.

- * - * @param message log this message - */ - public void fatal(Object message); - - - /** - *

Log an error with fatal log level.

- * - * @param message log this message - * @param t log this cause - */ - public void fatal(Object message, Throwable t); - - -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/LogConfigurationException.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/LogConfigurationException.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/LogConfigurationException.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/LogConfigurationException.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,98 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - - -/** - *

An exception that is thrown only if a suitable LogFactory - * or Log instance cannot be created by the corresponding - * factory methods.

- * - * @author Craig R. McClanahan - * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 2006) $ - */ - -public class LogConfigurationException extends RuntimeException { - - - /** - * Construct a new exception with null as its detail message. - */ - public LogConfigurationException() { - - super(); - - } - - - /** - * Construct a new exception with the specified detail message. - * - * @param message The detail message - */ - public LogConfigurationException(String message) { - - super(message); - - } - - - /** - * Construct a new exception with the specified cause and a derived - * detail message. - * - * @param cause The underlying cause - */ - public LogConfigurationException(Throwable cause) { - - this((cause == null) ? null : cause.toString(), cause); - - } - - - /** - * Construct a new exception with the specified detail message and cause. - * - * @param message The detail message - * @param cause The underlying cause - */ - public LogConfigurationException(String message, Throwable cause) { - - super(message + " (Caused by " + cause + ")"); - this.cause = cause; // Two-argument version requires JDK 1.4 or later - - } - - - /** - * The underlying cause of this exception. - */ - protected Throwable cause = null; - - - /** - * Return the underlying cause of this exception (if any). - */ - public Throwable getCause() { - - return (this.cause); - - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/LogFactory.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/LogFactory.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/LogFactory.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/LogFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1824 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - - -import java.io.BufferedReader; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Properties; - - -/** - *

Factory for creating {@link Log} instances, with discovery and - * configuration features similar to that employed by standard Java APIs - * such as JAXP.

- * - *

IMPLEMENTATION NOTE - This implementation is heavily - * based on the SAXParserFactory and DocumentBuilderFactory implementations - * (corresponding to the JAXP pluggability APIs) found in Apache Xerces.

- * - * @author Craig R. McClanahan - * @author Costin Manolache - * @author Richard A. Sitze - * @version $Revision: 593798 $ $Date: 2007-11-10 18:40:43 +0100 $ - */ - -public abstract class LogFactory { - // Implementation note re AccessController usage - // - // It is important to keep code invoked via an AccessController to small - // auditable blocks. Such code must carefully evaluate all user input - // (parameters, system properties, config file contents, etc). As an - // example, a Log implementation should not write to its logfile - // with an AccessController anywhere in the call stack, otherwise an - // insecure application could configure the log implementation to write - // to a protected file using the privileges granted to JCL rather than - // to the calling application. - // - // Under no circumstance should a non-private method return data that is - // retrieved via an AccessController. That would allow an insecure app - // to invoke that method and obtain data that it is not permitted to have. - // - // Invoking user-supplied code with an AccessController set is not a major - // issue (eg invoking the constructor of the class specified by - // HASHTABLE_IMPLEMENTATION_PROPERTY). That class will be in a different - // trust domain, and therefore must have permissions to do whatever it - // is trying to do regardless of the permissions granted to JCL. There is - // a slight issue in that untrusted code may point that environment var - // to another trusted library, in which case the code runs if both that - // lib and JCL have the necessary permissions even when the untrusted - // caller does not. That's a pretty hard route to exploit though. - - - // ----------------------------------------------------- Manifest Constants - - /** - * The name (priority) of the key in the config file used to - * specify the priority of that particular config file. The associated value - * is a floating-point number; higher values take priority over lower values. - */ - public static final String PRIORITY_KEY = "priority"; - - /** - * The name (use_tccl) of the key in the config file used - * to specify whether logging classes should be loaded via the thread - * context class loader (TCCL), or not. By default, the TCCL is used. - */ - public static final String TCCL_KEY = "use_tccl"; - - /** - * The name (org.apache.commons.logging.LogFactory) of the property - * used to identify the LogFactory implementation - * class name. This can be used as a system property, or as an entry in a - * configuration properties file. - */ - public static final String FACTORY_PROPERTY = - "org.apache.commons.logging.LogFactory"; - - /** - * The fully qualified class name of the fallback LogFactory - * implementation class to use, if no other can be found. - */ - public static final String FACTORY_DEFAULT = - "org.apache.commons.logging.impl.LogFactoryImpl"; - - /** - * The name (commons-logging.properties) of the properties file to search for. - */ - public static final String FACTORY_PROPERTIES = - "commons-logging.properties"; - - /** - * JDK1.3+ - * 'Service Provider' specification. - * - */ - protected static final String SERVICE_ID = - "META-INF/services/org.apache.commons.logging.LogFactory"; - - /** - * The name (org.apache.commons.logging.diagnostics.dest) - * of the property used to enable internal commons-logging - * diagnostic output, in order to get information on what logging - * implementations are being discovered, what classloaders they - * are loaded through, etc. - *

- * If a system property of this name is set then the value is - * assumed to be the name of a file. The special strings - * STDOUT or STDERR (case-sensitive) indicate output to - * System.out and System.err respectively. - *

- * Diagnostic logging should be used only to debug problematic - * configurations and should not be set in normal production use. - */ - public static final String DIAGNOSTICS_DEST_PROPERTY = - "org.apache.commons.logging.diagnostics.dest"; - - /** - * When null (the usual case), no diagnostic output will be - * generated by LogFactory or LogFactoryImpl. When non-null, - * interesting events will be written to the specified object. - */ - private static PrintStream diagnosticsStream = null; - - /** - * A string that gets prefixed to every message output by the - * logDiagnostic method, so that users can clearly see which - * LogFactory class is generating the output. - */ - private static String diagnosticPrefix; - - /** - *

Setting this system property - * (org.apache.commons.logging.LogFactory.HashtableImpl) - * value allows the Hashtable used to store - * classloaders to be substituted by an alternative implementation. - *

- *

- * Note: LogFactory will print: - *

-     * [ERROR] LogFactory: Load of custom hashtable failed
-     * 
- * to system error and then continue using a standard Hashtable. - *

- *

- * Usage: Set this property when Java is invoked - * and LogFactory will attempt to load a new instance - * of the given implementation class. - * For example, running the following ant scriplet: - *

-     *  <java classname="${test.runner}" fork="yes" failonerror="${test.failonerror}">
-     *     ...
-     *     <sysproperty 
-     *        key="org.apache.commons.logging.LogFactory.HashtableImpl"
-     *        value="org.apache.commons.logging.AltHashtable"/>
-     *  </java>
-     * 
- * will mean that LogFactory will load an instance of - * org.apache.commons.logging.AltHashtable. - *

- *

- * A typical use case is to allow a custom - * Hashtable implementation using weak references to be substituted. - * This will allow classloaders to be garbage collected without - * the need to release them (on 1.3+ JVMs only, of course ;) - *

- */ - public static final String HASHTABLE_IMPLEMENTATION_PROPERTY = - "org.apache.commons.logging.LogFactory.HashtableImpl"; - /** Name used to load the weak hashtable implementation by names */ - private static final String WEAK_HASHTABLE_CLASSNAME = - "org.apache.commons.logging.impl.WeakHashtable"; - - /** - * A reference to the classloader that loaded this class. This is the - * same as LogFactory.class.getClassLoader(). However computing this - * value isn't quite as simple as that, as we potentially need to use - * AccessControllers etc. It's more efficient to compute it once and - * cache it here. - */ - private static ClassLoader thisClassLoader; - - // ----------------------------------------------------------- Constructors - - - /** - * Protected constructor that is not available for public use. - */ - protected LogFactory() { - } - - // --------------------------------------------------------- Public Methods - - - /** - * Return the configuration attribute with the specified name (if any), - * or null if there is no such attribute. - * - * @param name Name of the attribute to return - */ - public abstract Object getAttribute(String name); - - - /** - * Return an array containing the names of all currently defined - * configuration attributes. If there are no such attributes, a zero - * length array is returned. - */ - public abstract String[] getAttributeNames(); - - - /** - * Convenience method to derive a name from the specified class and - * call getInstance(String) with it. - * - * @param clazz Class for which a suitable Log name will be derived - * - * @exception LogConfigurationException if a suitable Log - * instance cannot be returned - */ - public abstract Log getInstance(Class clazz) - throws LogConfigurationException; - - - /** - *

Construct (if necessary) and return a Log instance, - * using the factory's current set of configuration attributes.

- * - *

NOTE - Depending upon the implementation of - * the LogFactory you are using, the Log - * instance you are returned may or may not be local to the current - * application, and may or may not be returned again on a subsequent - * call with the same name argument.

- * - * @param name Logical name of the Log instance to be - * returned (the meaning of this name is only known to the underlying - * logging implementation that is being wrapped) - * - * @exception LogConfigurationException if a suitable Log - * instance cannot be returned - */ - public abstract Log getInstance(String name) - throws LogConfigurationException; - - - /** - * Release any internal references to previously created {@link Log} - * instances returned by this factory. This is useful in environments - * like servlet containers, which implement application reloading by - * throwing away a ClassLoader. Dangling references to objects in that - * class loader would prevent garbage collection. - */ - public abstract void release(); - - - /** - * Remove any configuration attribute associated with the specified name. - * If there is no such attribute, no action is taken. - * - * @param name Name of the attribute to remove - */ - public abstract void removeAttribute(String name); - - - /** - * Set the configuration attribute with the specified name. Calling - * this with a null value is equivalent to calling - * removeAttribute(name). - * - * @param name Name of the attribute to set - * @param value Value of the attribute to set, or null - * to remove any setting for this attribute - */ - public abstract void setAttribute(String name, Object value); - - - // ------------------------------------------------------- Static Variables - - - /** - * The previously constructed LogFactory instances, keyed by - * the ClassLoader with which it was created. - */ - protected static Hashtable factories = null; - - /** - * Prevously constructed LogFactory instance as in the - * factories map, but for the case where - * getClassLoader returns null. - * This can happen when: - *
    - *
  • using JDK1.1 and the calling code is loaded via the system - * classloader (very common)
  • - *
  • using JDK1.2+ and the calling code is loaded via the boot - * classloader (only likely for embedded systems work).
  • - *
- * Note that factories is a Hashtable (not a HashMap), - * and hashtables don't allow null as a key. - */ - protected static LogFactory nullClassLoaderFactory = null; - - /** - * Create the hashtable which will be used to store a map of - * (context-classloader -> logfactory-object). Version 1.2+ of Java - * supports "weak references", allowing a custom Hashtable class - * to be used which uses only weak references to its keys. Using weak - * references can fix memory leaks on webapp unload in some cases (though - * not all). Version 1.1 of Java does not support weak references, so we - * must dynamically determine which we are using. And just for fun, this - * code also supports the ability for a system property to specify an - * arbitrary Hashtable implementation name. - *

- * Note that the correct way to ensure no memory leaks occur is to ensure - * that LogFactory.release(contextClassLoader) is called whenever a - * webapp is undeployed. - */ - private static final Hashtable createFactoryStore() { - Hashtable result = null; - String storeImplementationClass; - try { - storeImplementationClass = getSystemProperty(HASHTABLE_IMPLEMENTATION_PROPERTY, null); - } catch(SecurityException ex) { - // Permissions don't allow this to be accessed. Default to the "modern" - // weak hashtable implementation if it is available. - storeImplementationClass = null; - } - - if (storeImplementationClass == null) { - storeImplementationClass = WEAK_HASHTABLE_CLASSNAME; - } - try { - Class implementationClass = Class.forName(storeImplementationClass); - result = (Hashtable) implementationClass.newInstance(); - - } catch (Throwable t) { - // ignore - if (!WEAK_HASHTABLE_CLASSNAME.equals(storeImplementationClass)) { - // if the user's trying to set up a custom implementation, give a clue - if (isDiagnosticsEnabled()) { - // use internal logging to issue the warning - logDiagnostic("[ERROR] LogFactory: Load of custom hashtable failed"); - } else { - // we *really* want this output, even if diagnostics weren't - // explicitly enabled by the user. - System.err.println("[ERROR] LogFactory: Load of custom hashtable failed"); - } - } - } - if (result == null) { - result = new Hashtable(); - } - return result; - } - - - // --------------------------------------------------------- Static Methods - - /** Utility method to safely trim a string. */ - private static String trim(String src) { - if (src == null) { - return null; - } - return src.trim(); - } - - /** - *

Construct (if necessary) and return a LogFactory - * instance, using the following ordered lookup procedure to determine - * the name of the implementation class to be loaded.

- *
    - *
  • The org.apache.commons.logging.LogFactory system - * property.
  • - *
  • The JDK 1.3 Service Discovery mechanism
  • - *
  • Use the properties file commons-logging.properties - * file, if found in the class path of this class. The configuration - * file is in standard java.util.Properties format and - * contains the fully qualified name of the implementation class - * with the key being the system property defined above.
  • - *
  • Fall back to a default implementation class - * (org.apache.commons.logging.impl.LogFactoryImpl).
  • - *
- * - *

NOTE - If the properties file method of identifying the - * LogFactory implementation class is utilized, all of the - * properties defined in this file will be set as configuration attributes - * on the corresponding LogFactory instance.

- * - *

NOTE - In a multithreaded environment it is possible - * that two different instances will be returned for the same - * classloader environment. - *

- * - * @exception LogConfigurationException if the implementation class is not - * available or cannot be instantiated. - */ - public static LogFactory getFactory() throws LogConfigurationException { - // Identify the class loader we will be using - ClassLoader contextClassLoader = getContextClassLoaderInternal(); - - if (contextClassLoader == null) { - // This is an odd enough situation to report about. This - // output will be a nuisance on JDK1.1, as the system - // classloader is null in that environment. - if (isDiagnosticsEnabled()) { - logDiagnostic("Context classloader is null."); - } - } - - // Return any previously registered factory for this class loader - LogFactory factory = getCachedFactory(contextClassLoader); - if (factory != null) { - return factory; - } - - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] LogFactory implementation requested for the first time for context classloader " - + objectId(contextClassLoader)); - logHierarchy("[LOOKUP] ", contextClassLoader); - } - - // Load properties file. - // - // If the properties file exists, then its contents are used as - // "attributes" on the LogFactory implementation class. One particular - // property may also control which LogFactory concrete subclass is - // used, but only if other discovery mechanisms fail.. - // - // As the properties file (if it exists) will be used one way or - // another in the end we may as well look for it first. - - Properties props = getConfigurationFile(contextClassLoader, FACTORY_PROPERTIES); - - // Determine whether we will be using the thread context class loader to - // load logging classes or not by checking the loaded properties file (if any). - ClassLoader baseClassLoader = contextClassLoader; - if (props != null) { - String useTCCLStr = props.getProperty(TCCL_KEY); - if (useTCCLStr != null) { - // The Boolean.valueOf(useTCCLStr).booleanValue() formulation - // is required for Java 1.2 compatability. - if (Boolean.valueOf(useTCCLStr).booleanValue() == false) { - // Don't use current context classloader when locating any - // LogFactory or Log classes, just use the class that loaded - // this abstract class. When this class is deployed in a shared - // classpath of a container, it means webapps cannot deploy their - // own logging implementations. It also means that it is up to the - // implementation whether to load library-specific config files - // from the TCCL or not. - baseClassLoader = thisClassLoader; - } - } - } - - // Determine which concrete LogFactory subclass to use. - // First, try a global system property - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Looking for system property [" + FACTORY_PROPERTY - + "] to define the LogFactory subclass to use..."); - } - - try { - String factoryClass = getSystemProperty(FACTORY_PROPERTY, null); - if (factoryClass != null) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Creating an instance of LogFactory class '" + factoryClass - + "' as specified by system property " + FACTORY_PROPERTY); - } - - factory = newFactory(factoryClass, baseClassLoader, contextClassLoader); - } else { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] No system property [" + FACTORY_PROPERTY - + "] defined."); - } - } - } catch (SecurityException e) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] A security exception occurred while trying to create an" - + " instance of the custom factory class" - + ": [" + trim(e.getMessage()) - + "]. Trying alternative implementations..."); - } - ; // ignore - } catch(RuntimeException e) { - // This is not consistent with the behaviour when a bad LogFactory class is - // specified in a services file. - // - // One possible exception that can occur here is a ClassCastException when - // the specified class wasn't castable to this LogFactory type. - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] An exception occurred while trying to create an" - + " instance of the custom factory class" - + ": [" + trim(e.getMessage()) - + "] as specified by a system property."); - } - throw e; - } - - - // Second, try to find a service by using the JDK1.3 class - // discovery mechanism, which involves putting a file with the name - // of an interface class in the META-INF/services directory, where the - // contents of the file is a single line specifying a concrete class - // that implements the desired interface. - - if (factory == null) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Looking for a resource file of name [" + SERVICE_ID - + "] to define the LogFactory subclass to use..."); - } - try { - InputStream is = getResourceAsStream(contextClassLoader, - SERVICE_ID); - - if( is != null ) { - // This code is needed by EBCDIC and other strange systems. - // It's a fix for bugs reported in xerces - BufferedReader rd; - try { - rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); - } catch (java.io.UnsupportedEncodingException e) { - rd = new BufferedReader(new InputStreamReader(is)); - } - - String factoryClassName = rd.readLine(); - rd.close(); - - if (factoryClassName != null && - ! "".equals(factoryClassName)) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Creating an instance of LogFactory class " + factoryClassName - + " as specified by file '" + SERVICE_ID - + "' which was present in the path of the context" - + " classloader."); - } - factory = newFactory(factoryClassName, baseClassLoader, contextClassLoader ); - } - } else { - // is == null - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] No resource file with name '" + SERVICE_ID - + "' found."); - } - } - } catch( Exception ex ) { - // note: if the specified LogFactory class wasn't compatible with LogFactory - // for some reason, a ClassCastException will be caught here, and attempts will - // continue to find a compatible class. - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] A security exception occurred while trying to create an" - + " instance of the custom factory class" - + ": [" + trim(ex.getMessage()) - + "]. Trying alternative implementations..."); - } - ; // ignore - } - } - - - // Third try looking into the properties file read earlier (if found) - - if (factory == null) { - if (props != null) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Looking in properties file for entry with key '" - + FACTORY_PROPERTY - + "' to define the LogFactory subclass to use..."); - } - String factoryClass = props.getProperty(FACTORY_PROPERTY); - if (factoryClass != null) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Properties file specifies LogFactory subclass '" - + factoryClass + "'"); - } - factory = newFactory(factoryClass, baseClassLoader, contextClassLoader); - - // TODO: think about whether we need to handle exceptions from newFactory - } else { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Properties file has no entry specifying LogFactory subclass."); - } - } - } else { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] No properties file available to determine" - + " LogFactory subclass from.."); - } - } - } - - - // Fourth, try the fallback implementation class - - if (factory == null) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Loading the default LogFactory implementation '" + FACTORY_DEFAULT - + "' via the same classloader that loaded this LogFactory" - + " class (ie not looking in the context classloader)."); - } - - // Note: unlike the above code which can try to load custom LogFactory - // implementations via the TCCL, we don't try to load the default LogFactory - // implementation via the context classloader because: - // * that can cause problems (see comments in newFactory method) - // * no-one should be customising the code of the default class - // Yes, we do give up the ability for the child to ship a newer - // version of the LogFactoryImpl class and have it used dynamically - // by an old LogFactory class in the parent, but that isn't - // necessarily a good idea anyway. - factory = newFactory(FACTORY_DEFAULT, thisClassLoader, contextClassLoader); - } - - if (factory != null) { - /** - * Always cache using context class loader. - */ - cacheFactory(contextClassLoader, factory); - - if( props!=null ) { - Enumeration names = props.propertyNames(); - while (names.hasMoreElements()) { - String name = (String) names.nextElement(); - String value = props.getProperty(name); - factory.setAttribute(name, value); - } - } - } - - return factory; - } - - - /** - * Convenience method to return a named logger, without the application - * having to care about factories. - * - * @param clazz Class from which a log name will be derived - * - * @exception LogConfigurationException if a suitable Log - * instance cannot be returned - */ - public static Log getLog(Class clazz) - throws LogConfigurationException { - - return (getFactory().getInstance(clazz)); - - } - - - /** - * Convenience method to return a named logger, without the application - * having to care about factories. - * - * @param name Logical name of the Log instance to be - * returned (the meaning of this name is only known to the underlying - * logging implementation that is being wrapped) - * - * @exception LogConfigurationException if a suitable Log - * instance cannot be returned - */ - public static Log getLog(String name) - throws LogConfigurationException { - - return (getFactory().getInstance(name)); - - } - - - /** - * Release any internal references to previously created {@link LogFactory} - * instances that have been associated with the specified class loader - * (if any), after calling the instance method release() on - * each of them. - * - * @param classLoader ClassLoader for which to release the LogFactory - */ - public static void release(ClassLoader classLoader) { - - if (isDiagnosticsEnabled()) { - logDiagnostic("Releasing factory for classloader " + objectId(classLoader)); - } - synchronized (factories) { - if (classLoader == null) { - if (nullClassLoaderFactory != null) { - nullClassLoaderFactory.release(); - nullClassLoaderFactory = null; - } - } else { - LogFactory factory = (LogFactory) factories.get(classLoader); - if (factory != null) { - factory.release(); - factories.remove(classLoader); - } - } - } - - } - - - /** - * Release any internal references to previously created {@link LogFactory} - * instances, after calling the instance method release() on - * each of them. This is useful in environments like servlet containers, - * which implement application reloading by throwing away a ClassLoader. - * Dangling references to objects in that class loader would prevent - * garbage collection. - */ - public static void releaseAll() { - - if (isDiagnosticsEnabled()) { - logDiagnostic("Releasing factory for all classloaders."); - } - synchronized (factories) { - Enumeration elements = factories.elements(); - while (elements.hasMoreElements()) { - LogFactory element = (LogFactory) elements.nextElement(); - element.release(); - } - factories.clear(); - - if (nullClassLoaderFactory != null) { - nullClassLoaderFactory.release(); - nullClassLoaderFactory = null; - } - } - - } - - - // ------------------------------------------------------ Protected Methods - - /** - * Safely get access to the classloader for the specified class. - *

- * Theoretically, calling getClassLoader can throw a security exception, - * and so should be done under an AccessController in order to provide - * maximum flexibility. However in practice people don't appear to use - * security policies that forbid getClassLoader calls. So for the moment - * all code is written to call this method rather than Class.getClassLoader, - * so that we could put AccessController stuff in this method without any - * disruption later if we need to. - *

- * Even when using an AccessController, however, this method can still - * throw SecurityException. Commons-logging basically relies on the - * ability to access classloaders, ie a policy that forbids all - * classloader access will also prevent commons-logging from working: - * currently this method will throw an exception preventing the entire app - * from starting up. Maybe it would be good to detect this situation and - * just disable all commons-logging? Not high priority though - as stated - * above, security policies that prevent classloader access aren't common. - *

- * Note that returning an object fetched via an AccessController would - * technically be a security flaw anyway; untrusted code that has access - * to a trusted JCL library could use it to fetch the classloader for - * a class even when forbidden to do so directly. - * - * @since 1.1 - */ - protected static ClassLoader getClassLoader(Class clazz) { - try { - return clazz.getClassLoader(); - } catch(SecurityException ex) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Unable to get classloader for class '" + clazz - + "' due to security restrictions - " + ex.getMessage()); - } - throw ex; - } - } - - /** - * Returns the current context classloader. - *

- * In versions prior to 1.1, this method did not use an AccessController. - * In version 1.1, an AccessController wrapper was incorrectly added to - * this method, causing a minor security flaw. - *

- * In version 1.1.1 this change was reverted; this method no longer uses - * an AccessController. User code wishing to obtain the context classloader - * must invoke this method via AccessController.doPrivileged if it needs - * support for that. - * - * @return the context classloader associated with the current thread, - * or null if security doesn't allow it. - * - * @throws LogConfigurationException if there was some weird error while - * attempting to get the context classloader. - * - * @throws SecurityException if the current java security policy doesn't - * allow this class to access the context classloader. - */ - protected static ClassLoader getContextClassLoader() - throws LogConfigurationException { - - return directGetContextClassLoader(); - } - - /** - * Calls LogFactory.directGetContextClassLoader under the control of an - * AccessController class. This means that java code running under a - * security manager that forbids access to ClassLoaders will still work - * if this class is given appropriate privileges, even when the caller - * doesn't have such privileges. Without using an AccessController, the - * the entire call stack must have the privilege before the call is - * allowed. - * - * @return the context classloader associated with the current thread, - * or null if security doesn't allow it. - * - * @throws LogConfigurationException if there was some weird error while - * attempting to get the context classloader. - * - * @throws SecurityException if the current java security policy doesn't - * allow this class to access the context classloader. - */ - private static ClassLoader getContextClassLoaderInternal() - throws LogConfigurationException { - return (ClassLoader)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return directGetContextClassLoader(); - } - }); - } - - /** - * Return the thread context class loader if available; otherwise return - * null. - *

- * Most/all code should call getContextClassLoaderInternal rather than - * calling this method directly. - *

- * The thread context class loader is available for JDK 1.2 - * or later, if certain security conditions are met. - *

- * Note that no internal logging is done within this method because - * this method is called every time LogFactory.getLogger() is called, - * and we don't want too much output generated here. - * - * @exception LogConfigurationException if a suitable class loader - * cannot be identified. - * - * @exception SecurityException if the java security policy forbids - * access to the context classloader from one of the classes in the - * current call stack. - * @since 1.1 - */ - protected static ClassLoader directGetContextClassLoader() - throws LogConfigurationException - { - ClassLoader classLoader = null; - - try { - // Are we running on a JDK 1.2 or later system? - Method method = Thread.class.getMethod("getContextClassLoader", - (Class[]) null); - - // Get the thread context class loader (if there is one) - try { - classLoader = (ClassLoader)method.invoke(Thread.currentThread(), - (Object[]) null); - } catch (IllegalAccessException e) { - throw new LogConfigurationException - ("Unexpected IllegalAccessException", e); - } catch (InvocationTargetException e) { - /** - * InvocationTargetException is thrown by 'invoke' when - * the method being invoked (getContextClassLoader) throws - * an exception. - * - * getContextClassLoader() throws SecurityException when - * the context class loader isn't an ancestor of the - * calling class's class loader, or if security - * permissions are restricted. - * - * In the first case (not related), we want to ignore and - * keep going. We cannot help but also ignore the second - * with the logic below, but other calls elsewhere (to - * obtain a class loader) will trigger this exception where - * we can make a distinction. - */ - if (e.getTargetException() instanceof SecurityException) { - ; // ignore - } else { - // Capture 'e.getTargetException()' exception for details - // alternate: log 'e.getTargetException()', and pass back 'e'. - throw new LogConfigurationException - ("Unexpected InvocationTargetException", e.getTargetException()); - } - } - } catch (NoSuchMethodException e) { - // Assume we are running on JDK 1.1 - classLoader = getClassLoader(LogFactory.class); - - // We deliberately don't log a message here to outputStream; - // this message would be output for every call to LogFactory.getLog() - // when running on JDK1.1 - // - // if (outputStream != null) { - // outputStream.println( - // "Method Thread.getContextClassLoader does not exist;" - // + " assuming this is JDK 1.1, and that the context" - // + " classloader is the same as the class that loaded" - // + " the concrete LogFactory class."); - // } - - } - - // Return the selected class loader - return classLoader; - } - - /** - * Check cached factories (keyed by contextClassLoader) - * - * @param contextClassLoader is the context classloader associated - * with the current thread. This allows separate LogFactory objects - * per component within a container, provided each component has - * a distinct context classloader set. This parameter may be null - * in JDK1.1, and in embedded systems where jcl-using code is - * placed in the bootclasspath. - * - * @return the factory associated with the specified classloader if - * one has previously been created, or null if this is the first time - * we have seen this particular classloader. - */ - private static LogFactory getCachedFactory(ClassLoader contextClassLoader) - { - LogFactory factory = null; - - if (contextClassLoader == null) { - // We have to handle this specially, as factories is a Hashtable - // and those don't accept null as a key value. - // - // nb: nullClassLoaderFactory might be null. That's ok. - factory = nullClassLoaderFactory; - } else { - factory = (LogFactory) factories.get(contextClassLoader); - } - - return factory; - } - - /** - * Remember this factory, so later calls to LogFactory.getCachedFactory - * can return the previously created object (together with all its - * cached Log objects). - * - * @param classLoader should be the current context classloader. Note that - * this can be null under some circumstances; this is ok. - * - * @param factory should be the factory to cache. This should never be null. - */ - private static void cacheFactory(ClassLoader classLoader, LogFactory factory) - { - // Ideally we would assert(factory != null) here. However reporting - // errors from within a logging implementation is a little tricky! - - if (factory != null) { - if (classLoader == null) { - nullClassLoaderFactory = factory; - } else { - factories.put(classLoader, factory); - } - } - } - - /** - * Return a new instance of the specified LogFactory - * implementation class, loaded by the specified class loader. - * If that fails, try the class loader used to load this - * (abstract) LogFactory. - *

- *

ClassLoader conflicts

- * Note that there can be problems if the specified ClassLoader is not the - * same as the classloader that loaded this class, ie when loading a - * concrete LogFactory subclass via a context classloader. - *

- * The problem is the same one that can occur when loading a concrete Log - * subclass via a context classloader. - *

- * The problem occurs when code running in the context classloader calls - * class X which was loaded via a parent classloader, and class X then calls - * LogFactory.getFactory (either directly or via LogFactory.getLog). Because - * class X was loaded via the parent, it binds to LogFactory loaded via - * the parent. When the code in this method finds some LogFactoryYYYY - * class in the child (context) classloader, and there also happens to be a - * LogFactory class defined in the child classloader, then LogFactoryYYYY - * will be bound to LogFactory@childloader. It cannot be cast to - * LogFactory@parentloader, ie this method cannot return the object as - * the desired type. Note that it doesn't matter if the LogFactory class - * in the child classloader is identical to the LogFactory class in the - * parent classloader, they are not compatible. - *

- * The solution taken here is to simply print out an error message when - * this occurs then throw an exception. The deployer of the application - * must ensure they remove all occurrences of the LogFactory class from - * the child classloader in order to resolve the issue. Note that they - * do not have to move the custom LogFactory subclass; that is ok as - * long as the only LogFactory class it can find to bind to is in the - * parent classloader. - *

- * @param factoryClass Fully qualified name of the LogFactory - * implementation class - * @param classLoader ClassLoader from which to load this class - * @param contextClassLoader is the context that this new factory will - * manage logging for. - * - * @exception LogConfigurationException if a suitable instance - * cannot be created - * @since 1.1 - */ - protected static LogFactory newFactory(final String factoryClass, - final ClassLoader classLoader, - final ClassLoader contextClassLoader) - throws LogConfigurationException - { - // Note that any unchecked exceptions thrown by the createFactory - // method will propagate out of this method; in particular a - // ClassCastException can be thrown. - Object result = AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return createFactory(factoryClass, classLoader); - } - }); - - if (result instanceof LogConfigurationException) { - LogConfigurationException ex = (LogConfigurationException) result; - if (isDiagnosticsEnabled()) { - logDiagnostic( - "An error occurred while loading the factory class:" - + ex.getMessage()); - } - throw ex; - } - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Created object " + objectId(result) - + " to manage classloader " + objectId(contextClassLoader)); - } - return (LogFactory)result; - } - - /** - * Method provided for backwards compatibility; see newFactory version that - * takes 3 parameters. - *

- * This method would only ever be called in some rather odd situation. - * Note that this method is static, so overriding in a subclass doesn't - * have any effect unless this method is called from a method in that - * subclass. However this method only makes sense to use from the - * getFactory method, and as that is almost always invoked via - * LogFactory.getFactory, any custom definition in a subclass would be - * pointless. Only a class with a custom getFactory method, then invoked - * directly via CustomFactoryImpl.getFactory or similar would ever call - * this. Anyway, it's here just in case, though the "managed class loader" - * value output to the diagnostics will not report the correct value. - */ - protected static LogFactory newFactory(final String factoryClass, - final ClassLoader classLoader) { - return newFactory(factoryClass, classLoader, null); - } - - /** - * Implements the operations described in the javadoc for newFactory. - * - * @param factoryClass - * - * @param classLoader used to load the specified factory class. This is - * expected to be either the TCCL or the classloader which loaded this - * class. Note that the classloader which loaded this class might be - * "null" (ie the bootloader) for embedded systems. - * - * @return either a LogFactory object or a LogConfigurationException object. - * @since 1.1 - */ - protected static Object createFactory(String factoryClass, ClassLoader classLoader) { - - // This will be used to diagnose bad configurations - // and allow a useful message to be sent to the user - Class logFactoryClass = null; - try { - if (classLoader != null) { - try { - // First the given class loader param (thread class loader) - - // Warning: must typecast here & allow exception - // to be generated/caught & recast properly. - logFactoryClass = classLoader.loadClass(factoryClass); - if (LogFactory.class.isAssignableFrom(logFactoryClass)) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Loaded class " + logFactoryClass.getName() - + " from classloader " + objectId(classLoader)); - } - } else { - // - // This indicates a problem with the ClassLoader tree. - // An incompatible ClassLoader was used to load the - // implementation. - // As the same classes - // must be available in multiple class loaders, - // it is very likely that multiple JCL jars are present. - // The most likely fix for this - // problem is to remove the extra JCL jars from the - // ClassLoader hierarchy. - // - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Factory class " + logFactoryClass.getName() - + " loaded from classloader " + objectId(logFactoryClass.getClassLoader()) - + " does not extend '" + LogFactory.class.getName() - + "' as loaded by this classloader."); - logHierarchy("[BAD CL TREE] ", classLoader); - } - } - - return (LogFactory) logFactoryClass.newInstance(); - - } catch (ClassNotFoundException ex) { - if (classLoader == thisClassLoader) { - // Nothing more to try, onwards. - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Unable to locate any class called '" + factoryClass - + "' via classloader " + objectId(classLoader)); - } - throw ex; - } - // ignore exception, continue - } catch (NoClassDefFoundError e) { - if (classLoader == thisClassLoader) { - // Nothing more to try, onwards. - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Class '" + factoryClass + "' cannot be loaded" - + " via classloader " + objectId(classLoader) - + " - it depends on some other class that cannot" - + " be found."); - } - throw e; - } - // ignore exception, continue - } catch(ClassCastException e) { - if (classLoader == thisClassLoader) { - // There's no point in falling through to the code below that - // tries again with thisClassLoader, because we've just tried - // loading with that loader (not the TCCL). Just throw an - // appropriate exception here. - - final boolean implementsLogFactory = implementsLogFactory(logFactoryClass); - - // - // Construct a good message: users may not actual expect that a custom implementation - // has been specified. Several well known containers use this mechanism to adapt JCL - // to their native logging system. - // - String msg = - "The application has specified that a custom LogFactory implementation should be used but " + - "Class '" + factoryClass + "' cannot be converted to '" - + LogFactory.class.getName() + "'. "; - if (implementsLogFactory) { - msg = msg + "The conflict is caused by the presence of multiple LogFactory classes in incompatible classloaders. " + - "Background can be found in http://commons.apache.org/logging/tech.html. " + - "If you have not explicitly specified a custom LogFactory then it is likely that " + - "the container has set one without your knowledge. " + - "In this case, consider using the commons-logging-adapters.jar file or " + - "specifying the standard LogFactory from the command line. "; - } else { - msg = msg + "Please check the custom implementation. "; - } - msg = msg + "Help can be found @http://commons.apache.org/logging/troubleshooting.html."; - - if (isDiagnosticsEnabled()) { - logDiagnostic(msg); - } - - ClassCastException ex = new ClassCastException(msg); - throw ex; - } - - // Ignore exception, continue. Presumably the classloader was the - // TCCL; the code below will try to load the class via thisClassLoader. - // This will handle the case where the original calling class is in - // a shared classpath but the TCCL has a copy of LogFactory and the - // specified LogFactory implementation; we will fall back to using the - // LogFactory implementation from the same classloader as this class. - // - // Issue: this doesn't handle the reverse case, where this LogFactory - // is in the webapp, and the specified LogFactory implementation is - // in a shared classpath. In that case: - // (a) the class really does implement LogFactory (bad log msg above) - // (b) the fallback code will result in exactly the same problem. - } - } - - /* At this point, either classLoader == null, OR - * classLoader was unable to load factoryClass. - * - * In either case, we call Class.forName, which is equivalent - * to LogFactory.class.getClassLoader().load(name), ie we ignore - * the classloader parameter the caller passed, and fall back - * to trying the classloader associated with this class. See the - * javadoc for the newFactory method for more info on the - * consequences of this. - * - * Notes: - * * LogFactory.class.getClassLoader() may return 'null' - * if LogFactory is loaded by the bootstrap classloader. - */ - // Warning: must typecast here & allow exception - // to be generated/caught & recast properly. - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Unable to load factory class via classloader " - + objectId(classLoader) - + " - trying the classloader associated with this LogFactory."); - } - logFactoryClass = Class.forName(factoryClass); - return (LogFactory) logFactoryClass.newInstance(); - } catch (Exception e) { - // Check to see if we've got a bad configuration - if (isDiagnosticsEnabled()) { - logDiagnostic("Unable to create LogFactory instance."); - } - if (logFactoryClass != null - && !LogFactory.class.isAssignableFrom(logFactoryClass)) { - - return new LogConfigurationException( - "The chosen LogFactory implementation does not extend LogFactory." - + " Please check your configuration.", - e); - } - return new LogConfigurationException(e); - } - } - - /** - * Determines whether the given class actually implements LogFactory. - * Diagnostic information is also logged. - *

- * Usage: to diagnose whether a classloader conflict is the cause - * of incompatibility. The test used is whether the class is assignable from - * the LogFactory class loaded by the class's classloader. - * @param logFactoryClass Class which may implement LogFactory - * @return true if the logFactoryClass does extend - * LogFactory when that class is loaded via the same - * classloader that loaded the logFactoryClass. - */ - private static boolean implementsLogFactory(Class logFactoryClass) { - boolean implementsLogFactory = false; - if (logFactoryClass != null) { - try { - ClassLoader logFactoryClassLoader = logFactoryClass.getClassLoader(); - if (logFactoryClassLoader == null) { - logDiagnostic("[CUSTOM LOG FACTORY] was loaded by the boot classloader"); - } else { - logHierarchy("[CUSTOM LOG FACTORY] ", logFactoryClassLoader); - Class factoryFromCustomLoader - = Class.forName("org.apache.commons.logging.LogFactory", false, logFactoryClassLoader); - implementsLogFactory = factoryFromCustomLoader.isAssignableFrom(logFactoryClass); - if (implementsLogFactory) { - logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClass.getName() - + " implements LogFactory but was loaded by an incompatible classloader."); - } else { - logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClass.getName() - + " does not implement LogFactory."); - } - } - } catch (SecurityException e) { - // - // The application is running within a hostile security environment. - // This will make it very hard to diagnose issues with JCL. - // Consider running less securely whilst debugging this issue. - // - logDiagnostic("[CUSTOM LOG FACTORY] SecurityException thrown whilst trying to determine whether " + - "the compatibility was caused by a classloader conflict: " - + e.getMessage()); - } catch (LinkageError e) { - // - // This should be an unusual circumstance. - // LinkageError's usually indicate that a dependent class has incompatibly changed. - // Another possibility may be an exception thrown by an initializer. - // Time for a clean rebuild? - // - logDiagnostic("[CUSTOM LOG FACTORY] LinkageError thrown whilst trying to determine whether " + - "the compatibility was caused by a classloader conflict: " - + e.getMessage()); - } catch (ClassNotFoundException e) { - // - // LogFactory cannot be loaded by the classloader which loaded the custom factory implementation. - // The custom implementation is not viable until this is corrected. - // Ensure that the JCL jar and the custom class are available from the same classloader. - // Running with diagnostics on should give information about the classloaders used - // to load the custom factory. - // - logDiagnostic("[CUSTOM LOG FACTORY] LogFactory class cannot be loaded by classloader which loaded the " + - "custom LogFactory implementation. Is the custom factory in the right classloader?"); - } - } - return implementsLogFactory; - } - - /** - * Applets may run in an environment where accessing resources of a loader is - * a secure operation, but where the commons-logging library has explicitly - * been granted permission for that operation. In this case, we need to - * run the operation using an AccessController. - */ - private static InputStream getResourceAsStream(final ClassLoader loader, - final String name) - { - return (InputStream)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - if (loader != null) { - return loader.getResourceAsStream(name); - } else { - return ClassLoader.getSystemResourceAsStream(name); - } - } - }); - } - - /** - * Given a filename, return an enumeration of URLs pointing to - * all the occurrences of that filename in the classpath. - *

- * This is just like ClassLoader.getResources except that the - * operation is done under an AccessController so that this method will - * succeed when this jarfile is privileged but the caller is not. - * This method must therefore remain private to avoid security issues. - *

- * If no instances are found, an Enumeration is returned whose - * hasMoreElements method returns false (ie an "empty" enumeration). - * If resources could not be listed for some reason, null is returned. - */ - private static Enumeration getResources(final ClassLoader loader, - final String name) - { - PrivilegedAction action = - new PrivilegedAction() { - public Object run() { - try { - if (loader != null) { - return loader.getResources(name); - } else { - return ClassLoader.getSystemResources(name); - } - } catch(IOException e) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Exception while trying to find configuration file " - + name + ":" + e.getMessage()); - } - return null; - } catch(NoSuchMethodError e) { - // we must be running on a 1.1 JVM which doesn't support - // ClassLoader.getSystemResources; just return null in - // this case. - return null; - } - } - }; - Object result = AccessController.doPrivileged(action); - return (Enumeration) result; - } - - /** - * Given a URL that refers to a .properties file, load that file. - * This is done under an AccessController so that this method will - * succeed when this jarfile is privileged but the caller is not. - * This method must therefore remain private to avoid security issues. - *

- * Null is returned if the URL cannot be opened. - */ - private static Properties getProperties(final URL url) { - PrivilegedAction action = - new PrivilegedAction() { - public Object run() { - try { - InputStream stream = url.openStream(); - if (stream != null) { - Properties props = new Properties(); - props.load(stream); - stream.close(); - return props; - } - } catch(IOException e) { - if (isDiagnosticsEnabled()) { - logDiagnostic("Unable to read URL " + url); - } - } - - return null; - } - }; - return (Properties) AccessController.doPrivileged(action); - } - - /** - * Locate a user-provided configuration file. - *

- * The classpath of the specified classLoader (usually the context classloader) - * is searched for properties files of the specified name. If none is found, - * null is returned. If more than one is found, then the file with the greatest - * value for its PRIORITY property is returned. If multiple files have the - * same PRIORITY value then the first in the classpath is returned. - *

- * This differs from the 1.0.x releases; those always use the first one found. - * However as the priority is a new field, this change is backwards compatible. - *

- * The purpose of the priority field is to allow a webserver administrator to - * override logging settings in all webapps by placing a commons-logging.properties - * file in a shared classpath location with a priority > 0; this overrides any - * commons-logging.properties files without priorities which are in the - * webapps. Webapps can also use explicit priorities to override a configuration - * file in the shared classpath if needed. - */ - private static final Properties getConfigurationFile( - ClassLoader classLoader, String fileName) { - - Properties props = null; - double priority = 0.0; - URL propsUrl = null; - try { - Enumeration urls = getResources(classLoader, fileName); - - if (urls == null) { - return null; - } - - while (urls.hasMoreElements()) { - URL url = (URL) urls.nextElement(); - - Properties newProps = getProperties(url); - if (newProps != null) { - if (props == null) { - propsUrl = url; - props = newProps; - String priorityStr = props.getProperty(PRIORITY_KEY); - priority = 0.0; - if (priorityStr != null) { - priority = Double.parseDouble(priorityStr); - } - - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Properties file found at '" + url + "'" - + " with priority " + priority); - } - } else { - String newPriorityStr = newProps.getProperty(PRIORITY_KEY); - double newPriority = 0.0; - if (newPriorityStr != null) { - newPriority = Double.parseDouble(newPriorityStr); - } - - if (newPriority > priority) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Properties file at '" + url + "'" - + " with priority " + newPriority - + " overrides file at '" + propsUrl + "'" - + " with priority " + priority); - } - - propsUrl = url; - props = newProps; - priority = newPriority; - } else { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Properties file at '" + url + "'" - + " with priority " + newPriority - + " does not override file at '" + propsUrl + "'" - + " with priority " + priority); - } - } - } - - } - } - } catch (SecurityException e) { - if (isDiagnosticsEnabled()) { - logDiagnostic("SecurityException thrown while trying to find/read config files."); - } - } - - if (isDiagnosticsEnabled()) { - if (props == null) { - logDiagnostic( - "[LOOKUP] No properties file of name '" + fileName - + "' found."); - } else { - logDiagnostic( - "[LOOKUP] Properties file of name '" + fileName - + "' found at '" + propsUrl + '"'); - } - } - - return props; - } - - /** - * Read the specified system property, using an AccessController so that - * the property can be read if JCL has been granted the appropriate - * security rights even if the calling code has not. - *

- * Take care not to expose the value returned by this method to the - * calling application in any way; otherwise the calling app can use that - * info to access data that should not be available to it. - */ - private static String getSystemProperty(final String key, final String def) - throws SecurityException { - return (String) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return System.getProperty(key, def); - } - }); - } - - /** - * Determines whether the user wants internal diagnostic output. If so, - * returns an appropriate writer object. Users can enable diagnostic - * output by setting the system property named {@link #DIAGNOSTICS_DEST_PROPERTY} to - * a filename, or the special values STDOUT or STDERR. - */ - private static void initDiagnostics() { - String dest; - try { - dest = getSystemProperty(DIAGNOSTICS_DEST_PROPERTY, null); - if (dest == null) { - return; - } - } catch(SecurityException ex) { - // We must be running in some very secure environment. - // We just have to assume output is not wanted.. - return; - } - - if (dest.equals("STDOUT")) { - diagnosticsStream = System.out; - } else if (dest.equals("STDERR")) { - diagnosticsStream = System.err; - } else { - try { - // open the file in append mode - FileOutputStream fos = new FileOutputStream(dest, true); - diagnosticsStream = new PrintStream(fos); - } catch(IOException ex) { - // We should report this to the user - but how? - return; - } - } - - // In order to avoid confusion where multiple instances of JCL are - // being used via different classloaders within the same app, we - // ensure each logged message has a prefix of form - // [LogFactory from classloader OID] - // - // Note that this prefix should be kept consistent with that - // in LogFactoryImpl. However here we don't need to output info - // about the actual *instance* of LogFactory, as all methods that - // output diagnostics from this class are static. - String classLoaderName; - try { - ClassLoader classLoader = thisClassLoader; - if (thisClassLoader == null) { - classLoaderName = "BOOTLOADER"; - } else { - classLoaderName = objectId(classLoader); - } - } catch(SecurityException e) { - classLoaderName = "UNKNOWN"; - } - diagnosticPrefix = "[LogFactory from " + classLoaderName + "] "; - } - - /** - * Indicates true if the user has enabled internal logging. - *

- * By the way, sorry for the incorrect grammar, but calling this method - * areDiagnosticsEnabled just isn't java beans style. - * - * @return true if calls to logDiagnostic will have any effect. - * @since 1.1 - */ - protected static boolean isDiagnosticsEnabled() { - return diagnosticsStream != null; - } - - /** - * Write the specified message to the internal logging destination. - *

- * Note that this method is private; concrete subclasses of this class - * should not call it because the diagnosticPrefix string this - * method puts in front of all its messages is LogFactory@...., - * while subclasses should put SomeSubClass@... - *

- * Subclasses should instead compute their own prefix, then call - * logRawDiagnostic. Note that calling isDiagnosticsEnabled is - * fine for subclasses. - *

- * Note that it is safe to call this method before initDiagnostics - * is called; any output will just be ignored (as isDiagnosticsEnabled - * will return false). - * - * @param msg is the diagnostic message to be output. - */ - private static final void logDiagnostic(String msg) { - if (diagnosticsStream != null) { - diagnosticsStream.print(diagnosticPrefix); - diagnosticsStream.println(msg); - diagnosticsStream.flush(); - } - } - - /** - * Write the specified message to the internal logging destination. - * - * @param msg is the diagnostic message to be output. - * @since 1.1 - */ - protected static final void logRawDiagnostic(String msg) { - if (diagnosticsStream != null) { - diagnosticsStream.println(msg); - diagnosticsStream.flush(); - } - } - - /** - * Generate useful diagnostics regarding the classloader tree for - * the specified class. - *

- * As an example, if the specified class was loaded via a webapp's - * classloader, then you may get the following output: - *

-     * Class com.acme.Foo was loaded via classloader 11111
-     * ClassLoader tree: 11111 -> 22222 (SYSTEM) -> 33333 -> BOOT 
-     * 
- *

- * This method returns immediately if isDiagnosticsEnabled() - * returns false. - * - * @param clazz is the class whose classloader + tree are to be - * output. - */ - private static void logClassLoaderEnvironment(Class clazz) { - if (!isDiagnosticsEnabled()) { - return; - } - - try { - // Deliberately use System.getProperty here instead of getSystemProperty; if - // the overall security policy for the calling application forbids access to - // these variables then we do not want to output them to the diagnostic stream. - logDiagnostic("[ENV] Extension directories (java.ext.dir): " + System.getProperty("java.ext.dir")); - logDiagnostic("[ENV] Application classpath (java.class.path): " + System.getProperty("java.class.path")); - } catch(SecurityException ex) { - logDiagnostic("[ENV] Security setting prevent interrogation of system classpaths."); - } - - String className = clazz.getName(); - ClassLoader classLoader; - - try { - classLoader = getClassLoader(clazz); - } catch(SecurityException ex) { - // not much useful diagnostics we can print here! - logDiagnostic( - "[ENV] Security forbids determining the classloader for " + className); - return; - } - - logDiagnostic( - "[ENV] Class " + className + " was loaded via classloader " - + objectId(classLoader)); - logHierarchy("[ENV] Ancestry of classloader which loaded " + className + " is ", classLoader); - } - - /** - * Logs diagnostic messages about the given classloader - * and it's hierarchy. The prefix is prepended to the message - * and is intended to make it easier to understand the logs. - * @param prefix - * @param classLoader - */ - private static void logHierarchy(String prefix, ClassLoader classLoader) { - if (!isDiagnosticsEnabled()) { - return; - } - ClassLoader systemClassLoader; - if (classLoader != null) { - final String classLoaderString = classLoader.toString(); - logDiagnostic(prefix + objectId(classLoader) + " == '" + classLoaderString + "'"); - } - - try { - systemClassLoader = ClassLoader.getSystemClassLoader(); - } catch(SecurityException ex) { - logDiagnostic( - prefix + "Security forbids determining the system classloader."); - return; - } - if (classLoader != null) { - StringBuffer buf = new StringBuffer(prefix + "ClassLoader tree:"); - for(;;) { - buf.append(objectId(classLoader)); - if (classLoader == systemClassLoader) { - buf.append(" (SYSTEM) "); - } - - try { - classLoader = classLoader.getParent(); - } catch(SecurityException ex) { - buf.append(" --> SECRET"); - break; - } - - buf.append(" --> "); - if (classLoader == null) { - buf.append("BOOT"); - break; - } - } - logDiagnostic(buf.toString()); - } - } - - /** - * Returns a string that uniquely identifies the specified object, including - * its class. - *

- * The returned string is of form "classname@hashcode", ie is the same as - * the return value of the Object.toString() method, but works even when - * the specified object's class has overidden the toString method. - * - * @param o may be null. - * @return a string of form classname@hashcode, or "null" if param o is null. - * @since 1.1 - */ - public static String objectId(Object o) { - if (o == null) { - return "null"; - } else { - return o.getClass().getName() + "@" + System.identityHashCode(o); - } - } - - // ---------------------------------------------------------------------- - // Static initialiser block to perform initialisation at class load time. - // - // We can't do this in the class constructor, as there are many - // static methods on this class that can be called before any - // LogFactory instances are created, and they depend upon this - // stuff having been set up. - // - // Note that this block must come after any variable declarations used - // by any methods called from this block, as we want any static initialiser - // associated with the variable to run first. If static initialisers for - // variables run after this code, then (a) their value might be needed - // by methods called from here, and (b) they might *override* any value - // computed here! - // - // So the wisest thing to do is just to place this code at the very end - // of the class file. - // ---------------------------------------------------------------------- - - static { - // note: it's safe to call methods before initDiagnostics (though - // diagnostic output gets discarded). - thisClassLoader = getClassLoader(LogFactory.class); - initDiagnostics(); - logClassLoaderEnvironment(LogFactory.class); - factories = createFactoryStore(); - if (isDiagnosticsEnabled()) { - logDiagnostic("BOOTSTRAP COMPLETED"); - } - } -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/LogSource.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/LogSource.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/LogSource.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/LogSource.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,262 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - - -import java.lang.reflect.Constructor; -import java.util.Hashtable; - -import org.apache.commons.logging.impl.NoOpLog; - - -/** - *

Factory for creating {@link Log} instances. Applications should call - * the makeNewLogInstance() method to instantiate new instances - * of the configured {@link Log} implementation class.

- * - *

By default, calling getInstance() will use the following - * algorithm:

- *
    - *
  • If Log4J is available, return an instance of - * org.apache.commons.logging.impl.Log4JLogger.
  • - *
  • If JDK 1.4 or later is available, return an instance of - * org.apache.commons.logging.impl.Jdk14Logger.
  • - *
  • Otherwise, return an instance of - * org.apache.commons.logging.impl.NoOpLog.
  • - *
- * - *

You can change the default behavior in one of two ways:

- *
    - *
  • On the startup command line, set the system property - * org.apache.commons.logging.log to the name of the - * org.apache.commons.logging.Log implementation class - * you want to use.
  • - *
  • At runtime, call LogSource.setLogImplementation().
  • - *
- * - * @deprecated Use {@link LogFactory} instead - The default factory - * implementation performs exactly the same algorithm as this class did - * - * @author Rod Waldhoff - * @version $Id: LogSource.java 424107 2006-07-20 23:15:42Z skitching $ - */ -public class LogSource { - - // ------------------------------------------------------- Class Attributes - - static protected Hashtable logs = new Hashtable(); - - /** Is log4j available (in the current classpath) */ - static protected boolean log4jIsAvailable = false; - - /** Is JDK 1.4 logging available */ - static protected boolean jdk14IsAvailable = false; - - /** Constructor for current log class */ - static protected Constructor logImplctor = null; - - - // ----------------------------------------------------- Class Initializers - - static { - - // Is Log4J Available? - try { - if (null != Class.forName("org.apache.log4j.Logger")) { - log4jIsAvailable = true; - } else { - log4jIsAvailable = false; - } - } catch (Throwable t) { - log4jIsAvailable = false; - } - - // Is JDK 1.4 Logging Available? - try { - if ((null != Class.forName("java.util.logging.Logger")) && - (null != Class.forName("org.apache.commons.logging.impl.Jdk14Logger"))) { - jdk14IsAvailable = true; - } else { - jdk14IsAvailable = false; - } - } catch (Throwable t) { - jdk14IsAvailable = false; - } - - // Set the default Log implementation - String name = null; - try { - name = System.getProperty("org.apache.commons.logging.log"); - if (name == null) { - name = System.getProperty("org.apache.commons.logging.Log"); - } - } catch (Throwable t) { - } - if (name != null) { - try { - setLogImplementation(name); - } catch (Throwable t) { - try { - setLogImplementation - ("org.apache.commons.logging.impl.NoOpLog"); - } catch (Throwable u) { - ; - } - } - } else { - try { - if (log4jIsAvailable) { - setLogImplementation - ("org.apache.commons.logging.impl.Log4JLogger"); - } else if (jdk14IsAvailable) { - setLogImplementation - ("org.apache.commons.logging.impl.Jdk14Logger"); - } else { - setLogImplementation - ("org.apache.commons.logging.impl.NoOpLog"); - } - } catch (Throwable t) { - try { - setLogImplementation - ("org.apache.commons.logging.impl.NoOpLog"); - } catch (Throwable u) { - ; - } - } - } - - } - - - // ------------------------------------------------------------ Constructor - - - /** Don't allow others to create instances */ - private LogSource() { - } - - - // ---------------------------------------------------------- Class Methods - - - /** - * Set the log implementation/log implementation factory - * by the name of the class. The given class - * must implement {@link Log}, and provide a constructor that - * takes a single {@link String} argument (containing the name - * of the log). - */ - static public void setLogImplementation(String classname) throws - LinkageError, ExceptionInInitializerError, - NoSuchMethodException, SecurityException, - ClassNotFoundException { - try { - Class logclass = Class.forName(classname); - Class[] argtypes = new Class[1]; - argtypes[0] = "".getClass(); - logImplctor = logclass.getConstructor(argtypes); - } catch (Throwable t) { - logImplctor = null; - } - } - - - /** - * Set the log implementation/log implementation factory - * by class. The given class must implement {@link Log}, - * and provide a constructor that takes a single {@link String} - * argument (containing the name of the log). - */ - static public void setLogImplementation(Class logclass) throws - LinkageError, ExceptionInInitializerError, - NoSuchMethodException, SecurityException { - Class[] argtypes = new Class[1]; - argtypes[0] = "".getClass(); - logImplctor = logclass.getConstructor(argtypes); - } - - - /** Get a Log instance by class name */ - static public Log getInstance(String name) { - Log log = (Log) (logs.get(name)); - if (null == log) { - log = makeNewLogInstance(name); - logs.put(name, log); - } - return log; - } - - - /** Get a Log instance by class */ - static public Log getInstance(Class clazz) { - return getInstance(clazz.getName()); - } - - - /** - * Create a new {@link Log} implementation, based - * on the given name. - *

- * The specific {@link Log} implementation returned - * is determined by the value of the - * org.apache.commons.logging.log property. - * The value of org.apache.commons.logging.log may be set to - * the fully specified name of a class that implements - * the {@link Log} interface. This class must also - * have a public constructor that takes a single - * {@link String} argument (containing the name - * of the {@link Log} to be constructed. - *

- * When org.apache.commons.logging.log is not set, - * or when no corresponding class can be found, - * this method will return a Log4JLogger - * if the log4j Logger class is - * available in the {@link LogSource}'s classpath, or a - * Jdk14Logger if we are on a JDK 1.4 or later system, or - * NoOpLog if neither of the above conditions is true. - * - * @param name the log name (or category) - */ - static public Log makeNewLogInstance(String name) { - - Log log = null; - try { - Object[] args = new Object[1]; - args[0] = name; - log = (Log) (logImplctor.newInstance(args)); - } catch (Throwable t) { - log = null; - } - if (null == log) { - log = new NoOpLog(name); - } - return log; - - } - - - /** - * Returns a {@link String} array containing the names of - * all logs known to me. - */ - static public String[] getLogNames() { - return (String[]) (logs.keySet().toArray(new String[logs.size()])); - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/AvalonLogger.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/AvalonLogger.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/AvalonLogger.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/AvalonLogger.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,292 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.impl; - -import org.apache.avalon.framework.logger.Logger; -import org.apache.commons.logging.Log; - -/** - *

Implementation of commons-logging Log interface that delegates all - * logging calls to the Avalon logging abstraction: the Logger interface. - *

- *

- * There are two ways in which this class can be used: - *

- *
    - *
  • the instance can be constructed with an Avalon logger - * (by calling {@link #AvalonLogger(Logger)}). In this case, it acts - * as a simple thin wrapping implementation over the logger. This is - * particularly useful when using a property setter. - *
  • - *
  • the {@link #setDefaultLogger} class property can be called which - * sets the ancesteral Avalon logger for this class. Any AvalonLogger - * instances created through the LogFactory mechanisms will output - * to child loggers of this Logger. - *
  • - *
- *

- * Note: AvalonLogger does not implement Serializable - * because the constructors available for it make this impossible to achieve in all - * circumstances; there is no way to "reconnect" to an underlying Logger object on - * deserialization if one was just passed in to the constructor of the original - * object. This class was marked Serializable in the 1.0.4 release of - * commons-logging, but this never actually worked (a NullPointerException would - * be thrown as soon as the deserialized object was used), so removing this marker - * is not considered to be an incompatible change. - *

- * @author Neeme Praks - * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 2006) $ - */ -public class AvalonLogger implements Log { - - /** Ancesteral avalon logger */ - private static Logger defaultLogger = null; - /** Avalon logger used to perform log */ - private transient Logger logger = null; - - /** - * Constructs an AvalonLogger that outputs to the given - * Logger instance. - * @param logger the avalon logger implementation to delegate to - */ - public AvalonLogger(Logger logger) { - this.logger = logger; - } - - /** - * Constructs an AvalonLogger that will log to a child - * of the Logger set by calling {@link #setDefaultLogger}. - * @param name the name of the avalon logger implementation to delegate to - */ - public AvalonLogger(String name) { - if (defaultLogger == null) - throw new NullPointerException("default logger has to be specified if this constructor is used!"); - this.logger = defaultLogger.getChildLogger(name); - } - - /** - * Gets the Avalon logger implementation used to perform logging. - * @return avalon logger implementation - */ - public Logger getLogger() { - return logger; - } - - /** - * Sets the ancesteral Avalon logger from which the delegating loggers - * will descend. - * @param logger the default avalon logger, - * in case there is no logger instance supplied in constructor - */ - public static void setDefaultLogger(Logger logger) { - defaultLogger = logger; - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.debug. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#debug(Object, Throwable) - */ - public void debug(Object message, Throwable t) { - if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.debug. - * - * @param message to log. - * @see org.apache.commons.logging.Log#debug(Object) - */ - public void debug(Object message) { - if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message)); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.error. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#error(Object, Throwable) - */ - public void error(Object message, Throwable t) { - if (getLogger().isErrorEnabled()) getLogger().error(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.error. - * - * @param message to log - * @see org.apache.commons.logging.Log#error(Object) - */ - public void error(Object message) { - if (getLogger().isErrorEnabled()) getLogger().error(String.valueOf(message)); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.fatalError. - * - * @param message to log. - * @param t log this cause. - * @see org.apache.commons.logging.Log#fatal(Object, Throwable) - */ - public void fatal(Object message, Throwable t) { - if (getLogger().isFatalErrorEnabled()) getLogger().fatalError(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.fatalError. - * - * @param message to log - * @see org.apache.commons.logging.Log#fatal(Object) - */ - public void fatal(Object message) { - if (getLogger().isFatalErrorEnabled()) getLogger().fatalError(String.valueOf(message)); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.info. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#info(Object, Throwable) - */ - public void info(Object message, Throwable t) { - if (getLogger().isInfoEnabled()) getLogger().info(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.info. - * - * @param message to log - * @see org.apache.commons.logging.Log#info(Object) - */ - public void info(Object message) { - if (getLogger().isInfoEnabled()) getLogger().info(String.valueOf(message)); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.debug enabled? - * @see org.apache.commons.logging.Log#isDebugEnabled() - */ - public boolean isDebugEnabled() { - return getLogger().isDebugEnabled(); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.error enabled? - * @see org.apache.commons.logging.Log#isErrorEnabled() - */ - public boolean isErrorEnabled() { - return getLogger().isErrorEnabled(); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.fatalError enabled? - * @see org.apache.commons.logging.Log#isFatalEnabled() - */ - public boolean isFatalEnabled() { - return getLogger().isFatalErrorEnabled(); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.info enabled? - * @see org.apache.commons.logging.Log#isInfoEnabled() - */ - public boolean isInfoEnabled() { - return getLogger().isInfoEnabled(); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.debug enabled? - * @see org.apache.commons.logging.Log#isTraceEnabled() - */ - public boolean isTraceEnabled() { - return getLogger().isDebugEnabled(); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.warn enabled? - * @see org.apache.commons.logging.Log#isWarnEnabled() - */ - public boolean isWarnEnabled() { - return getLogger().isWarnEnabled(); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.debug. - * - * @param message to log. - * @param t log this cause. - * @see org.apache.commons.logging.Log#trace(Object, Throwable) - */ - public void trace(Object message, Throwable t) { - if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.debug. - * - * @param message to log - * @see org.apache.commons.logging.Log#trace(Object) - */ - public void trace(Object message) { - if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message)); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.warn. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#warn(Object, Throwable) - */ - public void warn(Object message, Throwable t) { - if (getLogger().isWarnEnabled()) getLogger().warn(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.warn. - * - * @param message to log - * @see org.apache.commons.logging.Log#warn(Object) - */ - public void warn(Object message) { - if (getLogger().isWarnEnabled()) getLogger().warn(String.valueOf(message)); - } - -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,335 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - - -import java.io.Serializable; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.logging.LogRecord; -import java.util.StringTokenizer; -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.apache.commons.logging.Log; - - -/** - *

Implementation of the org.apache.commons.logging.Log - * interface that wraps the standard JDK logging mechanisms that are - * available in SourceForge's Lumberjack for JDKs prior to 1.4.

- * - * @author Scott Sanders - * @author Berin Loritsch - * @author Peter Donald - * @author Vince Eagen - * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 2006) $ - * @since 1.1 - */ - -public class Jdk13LumberjackLogger implements Log, Serializable { - - - // ----------------------------------------------------- Instance Variables - - - /** - * The underlying Logger implementation we are using. - */ - protected transient Logger logger = null; - protected String name = null; - private String sourceClassName = "unknown"; - private String sourceMethodName = "unknown"; - private boolean classAndMethodFound = false; - - - /** - * This member variable simply ensures that any attempt to initialise - * this class in a pre-1.4 JVM will result in an ExceptionInInitializerError. - * It must not be private, as an optimising compiler could detect that it - * is not used and optimise it away. - */ - protected static final Level dummyLevel = Level.FINE; - - // ----------------------------------------------------------- Constructors - - - /** - * Construct a named instance of this Logger. - * - * @param name Name of the logger to be constructed - */ - public Jdk13LumberjackLogger(String name) { - - this.name = name; - logger = getLogger(); - - } - - - // --------------------------------------------------------- Public Methods - - - private void log( Level level, String msg, Throwable ex ) { - if( getLogger().isLoggable(level) ) { - LogRecord record = new LogRecord(level, msg); - if( !classAndMethodFound ) { - getClassAndMethod(); - } - record.setSourceClassName(sourceClassName); - record.setSourceMethodName(sourceMethodName); - if( ex != null ) { - record.setThrown(ex); - } - getLogger().log(record); - } - } - - /** - *

Gets the class and method by looking at the stack trace for the - * first entry that is not this class.

- */ - private void getClassAndMethod() { - try { - Throwable throwable = new Throwable(); - throwable.fillInStackTrace(); - StringWriter stringWriter = new StringWriter(); - PrintWriter printWriter = new PrintWriter( stringWriter ); - throwable.printStackTrace( printWriter ); - String traceString = stringWriter.getBuffer().toString(); - StringTokenizer tokenizer = - new StringTokenizer( traceString, "\n" ); - tokenizer.nextToken(); - String line = tokenizer.nextToken(); - while ( line.indexOf( this.getClass().getName() ) == -1 ) { - line = tokenizer.nextToken(); - } - while ( line.indexOf( this.getClass().getName() ) >= 0 ) { - line = tokenizer.nextToken(); - } - int start = line.indexOf( "at " ) + 3; - int end = line.indexOf( '(' ); - String temp = line.substring( start, end ); - int lastPeriod = temp.lastIndexOf( '.' ); - sourceClassName = temp.substring( 0, lastPeriod ); - sourceMethodName = temp.substring( lastPeriod + 1 ); - } catch ( Exception ex ) { - // ignore - leave class and methodname unknown - } - classAndMethodFound = true; - } - - /** - * Logs a message with java.util.logging.Level.FINE. - * - * @param message to log - * @see org.apache.commons.logging.Log#debug(Object) - */ - public void debug(Object message) { - log(Level.FINE, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.FINE. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#debug(Object, Throwable) - */ - public void debug(Object message, Throwable exception) { - log(Level.FINE, String.valueOf(message), exception); - } - - - /** - * Logs a message with java.util.logging.Level.SEVERE. - * - * @param message to log - * @see org.apache.commons.logging.Log#error(Object) - */ - public void error(Object message) { - log(Level.SEVERE, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.SEVERE. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#error(Object, Throwable) - */ - public void error(Object message, Throwable exception) { - log(Level.SEVERE, String.valueOf(message), exception); - } - - - /** - * Logs a message with java.util.logging.Level.SEVERE. - * - * @param message to log - * @see org.apache.commons.logging.Log#fatal(Object) - */ - public void fatal(Object message) { - log(Level.SEVERE, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.SEVERE. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#fatal(Object, Throwable) - */ - public void fatal(Object message, Throwable exception) { - log(Level.SEVERE, String.valueOf(message), exception); - } - - - /** - * Return the native Logger instance we are using. - */ - public Logger getLogger() { - if (logger == null) { - logger = Logger.getLogger(name); - } - return (logger); - } - - - /** - * Logs a message with java.util.logging.Level.INFO. - * - * @param message to log - * @see org.apache.commons.logging.Log#info(Object) - */ - public void info(Object message) { - log(Level.INFO, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.INFO. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#info(Object, Throwable) - */ - public void info(Object message, Throwable exception) { - log(Level.INFO, String.valueOf(message), exception); - } - - - /** - * Is debug logging currently enabled? - */ - public boolean isDebugEnabled() { - return (getLogger().isLoggable(Level.FINE)); - } - - - /** - * Is error logging currently enabled? - */ - public boolean isErrorEnabled() { - return (getLogger().isLoggable(Level.SEVERE)); - } - - - /** - * Is fatal logging currently enabled? - */ - public boolean isFatalEnabled() { - return (getLogger().isLoggable(Level.SEVERE)); - } - - - /** - * Is info logging currently enabled? - */ - public boolean isInfoEnabled() { - return (getLogger().isLoggable(Level.INFO)); - } - - - /** - * Is trace logging currently enabled? - */ - public boolean isTraceEnabled() { - return (getLogger().isLoggable(Level.FINEST)); - } - - - /** - * Is warn logging currently enabled? - */ - public boolean isWarnEnabled() { - return (getLogger().isLoggable(Level.WARNING)); - } - - - /** - * Logs a message with java.util.logging.Level.FINEST. - * - * @param message to log - * @see org.apache.commons.logging.Log#trace(Object) - */ - public void trace(Object message) { - log(Level.FINEST, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.FINEST. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#trace(Object, Throwable) - */ - public void trace(Object message, Throwable exception) { - log(Level.FINEST, String.valueOf(message), exception); - } - - - /** - * Logs a message with java.util.logging.Level.WARNING. - * - * @param message to log - * @see org.apache.commons.logging.Log#warn(Object) - */ - public void warn(Object message) { - log(Level.WARNING, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.WARNING. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#warn(Object, Throwable) - */ - public void warn(Object message, Throwable exception) { - log(Level.WARNING, String.valueOf(message), exception); - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/Jdk14Logger.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/Jdk14Logger.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/Jdk14Logger.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/Jdk14Logger.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,304 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - - -import java.io.Serializable; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.commons.logging.Log; - - -/** - *

Implementation of the org.apache.commons.logging.Log - * interface that wraps the standard JDK logging mechanisms that were - * introduced in the Merlin release (JDK 1.4).

- * - * @author Scott Sanders - * @author Berin Loritsch - * @author Peter Donald - * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 2006) $ - */ - -public class Jdk14Logger implements Log, Serializable { - - /** - * This member variable simply ensures that any attempt to initialise - * this class in a pre-1.4 JVM will result in an ExceptionInInitializerError. - * It must not be private, as an optimising compiler could detect that it - * is not used and optimise it away. - */ - protected static final Level dummyLevel = Level.FINE; - - // ----------------------------------------------------------- Constructors - - - /** - * Construct a named instance of this Logger. - * - * @param name Name of the logger to be constructed - */ - public Jdk14Logger(String name) { - - this.name = name; - logger = getLogger(); - - } - - - // ----------------------------------------------------- Instance Variables - - - /** - * The underlying Logger implementation we are using. - */ - protected transient Logger logger = null; - - - /** - * The name of the logger we are wrapping. - */ - protected String name = null; - - - // --------------------------------------------------------- Public Methods - - private void log( Level level, String msg, Throwable ex ) { - - Logger logger = getLogger(); - if (logger.isLoggable(level)) { - // Hack (?) to get the stack trace. - Throwable dummyException=new Throwable(); - StackTraceElement locations[]=dummyException.getStackTrace(); - // Caller will be the third element - String cname="unknown"; - String method="unknown"; - if( locations!=null && locations.length >2 ) { - StackTraceElement caller=locations[2]; - cname=caller.getClassName(); - method=caller.getMethodName(); - } - if( ex==null ) { - logger.logp( level, cname, method, msg ); - } else { - logger.logp( level, cname, method, msg, ex ); - } - } - - } - - /** - * Logs a message with java.util.logging.Level.FINE. - * - * @param message to log - * @see org.apache.commons.logging.Log#debug(Object) - */ - public void debug(Object message) { - log(Level.FINE, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.FINE. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#debug(Object, Throwable) - */ - public void debug(Object message, Throwable exception) { - log(Level.FINE, String.valueOf(message), exception); - } - - - /** - * Logs a message with java.util.logging.Level.SEVERE. - * - * @param message to log - * @see org.apache.commons.logging.Log#error(Object) - */ - public void error(Object message) { - log(Level.SEVERE, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.SEVERE. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#error(Object, Throwable) - */ - public void error(Object message, Throwable exception) { - log(Level.SEVERE, String.valueOf(message), exception); - } - - - /** - * Logs a message with java.util.logging.Level.SEVERE. - * - * @param message to log - * @see org.apache.commons.logging.Log#fatal(Object) - */ - public void fatal(Object message) { - log(Level.SEVERE, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.SEVERE. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#fatal(Object, Throwable) - */ - public void fatal(Object message, Throwable exception) { - log(Level.SEVERE, String.valueOf(message), exception); - } - - - /** - * Return the native Logger instance we are using. - */ - public Logger getLogger() { - if (logger == null) { - logger = Logger.getLogger(name); - } - return (logger); - } - - - /** - * Logs a message with java.util.logging.Level.INFO. - * - * @param message to log - * @see org.apache.commons.logging.Log#info(Object) - */ - public void info(Object message) { - log(Level.INFO, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.INFO. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#info(Object, Throwable) - */ - public void info(Object message, Throwable exception) { - log(Level.INFO, String.valueOf(message), exception); - } - - - /** - * Is debug logging currently enabled? - */ - public boolean isDebugEnabled() { - return (getLogger().isLoggable(Level.FINE)); - } - - - /** - * Is error logging currently enabled? - */ - public boolean isErrorEnabled() { - return (getLogger().isLoggable(Level.SEVERE)); - } - - - /** - * Is fatal logging currently enabled? - */ - public boolean isFatalEnabled() { - return (getLogger().isLoggable(Level.SEVERE)); - } - - - /** - * Is info logging currently enabled? - */ - public boolean isInfoEnabled() { - return (getLogger().isLoggable(Level.INFO)); - } - - - /** - * Is trace logging currently enabled? - */ - public boolean isTraceEnabled() { - return (getLogger().isLoggable(Level.FINEST)); - } - - - /** - * Is warn logging currently enabled? - */ - public boolean isWarnEnabled() { - return (getLogger().isLoggable(Level.WARNING)); - } - - - /** - * Logs a message with java.util.logging.Level.FINEST. - * - * @param message to log - * @see org.apache.commons.logging.Log#trace(Object) - */ - public void trace(Object message) { - log(Level.FINEST, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.FINEST. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#trace(Object, Throwable) - */ - public void trace(Object message, Throwable exception) { - log(Level.FINEST, String.valueOf(message), exception); - } - - - /** - * Logs a message with java.util.logging.Level.WARNING. - * - * @param message to log - * @see org.apache.commons.logging.Log#warn(Object) - */ - public void warn(Object message) { - log(Level.WARNING, String.valueOf(message), null); - } - - - /** - * Logs a message with java.util.logging.Level.WARNING. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#warn(Object, Throwable) - */ - public void warn(Object message, Throwable exception) { - log(Level.WARNING, String.valueOf(message), exception); - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/Log4JLogger.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/Log4JLogger.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/Log4JLogger.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/Log4JLogger.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,342 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - -import java.io.Serializable; -import org.apache.commons.logging.Log; -import org.apache.log4j.Logger; -import org.apache.log4j.Priority; -import org.apache.log4j.Level; - -/** - * Implementation of {@link Log} that maps directly to a - * Logger for log4J version 1.2. - *

- * Initial configuration of the corresponding Logger instances should be done - * in the usual manner, as outlined in the Log4J documentation. - *

- * The reason this logger is distinct from the 1.3 logger is that in version 1.2 - * of Log4J: - *

    - *
  • class Logger takes Priority parameters not Level parameters. - *
  • class Level extends Priority - *
- * Log4J1.3 is expected to change Level so it no longer extends Priority, which is - * a non-binary-compatible change. The class generated by compiling this code against - * log4j 1.2 will therefore not run against log4j 1.3. - * - * @author Scott Sanders - * @author Rod Waldhoff - * @author Robert Burrell Donkin - * @version $Id: Log4JLogger.java 479747 2006-11-27 20:15:01Z dennisl $ - */ - -public class Log4JLogger implements Log, Serializable { - - // ------------------------------------------------------------- Attributes - - /** The fully qualified name of the Log4JLogger class. */ - private static final String FQCN = Log4JLogger.class.getName(); - - /** Log to this logger */ - private transient Logger logger = null; - - /** Logger name */ - private String name = null; - - private static Priority traceLevel; - - // ------------------------------------------------------------ - // Static Initializer. - // - // Note that this must come after the static variable declarations - // otherwise initialiser expressions associated with those variables - // will override any settings done here. - // - // Verify that log4j is available, and that it is version 1.2. - // If an ExceptionInInitializerError is generated, then LogFactoryImpl - // will treat that as meaning that the appropriate underlying logging - // library is just not present - if discovery is in progress then - // discovery will continue. - // ------------------------------------------------------------ - - static { - if (!Priority.class.isAssignableFrom(Level.class)) { - // nope, this is log4j 1.3, so force an ExceptionInInitializerError - throw new InstantiationError("Log4J 1.2 not available"); - } - - // Releases of log4j1.2 >= 1.2.12 have Priority.TRACE available, earlier - // versions do not. If TRACE is not available, then we have to map - // calls to Log.trace(...) onto the DEBUG level. - - try { - traceLevel = (Priority) Level.class.getDeclaredField("TRACE").get(null); - } catch(Exception ex) { - // ok, trace not available - traceLevel = Priority.DEBUG; - } - } - - - // ------------------------------------------------------------ Constructor - - public Log4JLogger() { - } - - - /** - * Base constructor. - */ - public Log4JLogger(String name) { - this.name = name; - this.logger = getLogger(); - } - - /** - * For use with a log4j factory. - */ - public Log4JLogger(Logger logger ) { - if (logger == null) { - throw new IllegalArgumentException( - "Warning - null logger in constructor; possible log4j misconfiguration."); - } - this.name = logger.getName(); - this.logger=logger; - } - - - // --------------------------------------------------------- - // Implementation - // - // Note that in the methods below the Priority class is used to define - // levels even though the Level class is supported in 1.2. This is done - // so that at compile time the call definitely resolves to a call to - // a method that takes a Priority rather than one that takes a Level. - // - // The Category class (and hence its subclass Logger) in version 1.2 only - // has methods that take Priority objects. The Category class (and hence - // Logger class) in version 1.3 has methods that take both Priority and - // Level objects. This means that if we use Level here, and compile - // against log4j 1.3 then calls would be bound to the versions of - // methods taking Level objects and then would fail to run against - // version 1.2 of log4j. - // --------------------------------------------------------- - - - /** - * Logs a message with org.apache.log4j.Priority.TRACE. - * When using a log4j version that does not support the TRACE - * level, the message will be logged at the DEBUG level. - * - * @param message to log - * @see org.apache.commons.logging.Log#trace(Object) - */ - public void trace(Object message) { - getLogger().log(FQCN, traceLevel, message, null ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.TRACE. - * When using a log4j version that does not support the TRACE - * level, the message will be logged at the DEBUG level. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#trace(Object, Throwable) - */ - public void trace(Object message, Throwable t) { - getLogger().log(FQCN, traceLevel, message, t ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.DEBUG. - * - * @param message to log - * @see org.apache.commons.logging.Log#debug(Object) - */ - public void debug(Object message) { - getLogger().log(FQCN, Priority.DEBUG, message, null ); - } - - /** - * Logs a message with org.apache.log4j.Priority.DEBUG. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#debug(Object, Throwable) - */ - public void debug(Object message, Throwable t) { - getLogger().log(FQCN, Priority.DEBUG, message, t ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.INFO. - * - * @param message to log - * @see org.apache.commons.logging.Log#info(Object) - */ - public void info(Object message) { - getLogger().log(FQCN, Priority.INFO, message, null ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.INFO. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#info(Object, Throwable) - */ - public void info(Object message, Throwable t) { - getLogger().log(FQCN, Priority.INFO, message, t ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.WARN. - * - * @param message to log - * @see org.apache.commons.logging.Log#warn(Object) - */ - public void warn(Object message) { - getLogger().log(FQCN, Priority.WARN, message, null ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.WARN. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#warn(Object, Throwable) - */ - public void warn(Object message, Throwable t) { - getLogger().log(FQCN, Priority.WARN, message, t ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.ERROR. - * - * @param message to log - * @see org.apache.commons.logging.Log#error(Object) - */ - public void error(Object message) { - getLogger().log(FQCN, Priority.ERROR, message, null ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.ERROR. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#error(Object, Throwable) - */ - public void error(Object message, Throwable t) { - getLogger().log(FQCN, Priority.ERROR, message, t ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.FATAL. - * - * @param message to log - * @see org.apache.commons.logging.Log#fatal(Object) - */ - public void fatal(Object message) { - getLogger().log(FQCN, Priority.FATAL, message, null ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.FATAL. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#fatal(Object, Throwable) - */ - public void fatal(Object message, Throwable t) { - getLogger().log(FQCN, Priority.FATAL, message, t ); - } - - - /** - * Return the native Logger instance we are using. - */ - public Logger getLogger() { - if (logger == null) { - logger = Logger.getLogger(name); - } - return (this.logger); - } - - - /** - * Check whether the Log4j Logger used is enabled for DEBUG priority. - */ - public boolean isDebugEnabled() { - return getLogger().isDebugEnabled(); - } - - - /** - * Check whether the Log4j Logger used is enabled for ERROR priority. - */ - public boolean isErrorEnabled() { - return getLogger().isEnabledFor(Priority.ERROR); - } - - - /** - * Check whether the Log4j Logger used is enabled for FATAL priority. - */ - public boolean isFatalEnabled() { - return getLogger().isEnabledFor(Priority.FATAL); - } - - - /** - * Check whether the Log4j Logger used is enabled for INFO priority. - */ - public boolean isInfoEnabled() { - return getLogger().isInfoEnabled(); - } - - - /** - * Check whether the Log4j Logger used is enabled for TRACE priority. - * When using a log4j version that does not support the TRACE level, this call - * will report whether DEBUG is enabled or not. - */ - public boolean isTraceEnabled() { - return getLogger().isEnabledFor(traceLevel); - } - - /** - * Check whether the Log4j Logger used is enabled for WARN priority. - */ - public boolean isWarnEnabled() { - return getLogger().isEnabledFor(Priority.WARN); - } -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/LogFactoryImpl.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/LogFactoryImpl.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/LogFactoryImpl.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/LogFactoryImpl.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1500 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.impl; - - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogConfigurationException; -import org.apache.commons.logging.LogFactory; - - -/** - *

Concrete subclass of {@link LogFactory} that implements the - * following algorithm to dynamically select a logging implementation - * class to instantiate a wrapper for.

- *
    - *
  • Use a factory configuration attribute named - * org.apache.commons.logging.Log to identify the - * requested implementation class.
  • - *
  • Use the org.apache.commons.logging.Log system property - * to identify the requested implementation class.
  • - *
  • If Log4J is available, return an instance of - * org.apache.commons.logging.impl.Log4JLogger.
  • - *
  • If JDK 1.4 or later is available, return an instance of - * org.apache.commons.logging.impl.Jdk14Logger.
  • - *
  • Otherwise, return an instance of - * org.apache.commons.logging.impl.SimpleLog.
  • - *
- * - *

If the selected {@link Log} implementation class has a - * setLogFactory() method that accepts a {@link LogFactory} - * parameter, this method will be called on each newly created instance - * to identify the associated factory. This makes factory configuration - * attributes available to the Log instance, if it so desires.

- * - *

This factory will remember previously created Log instances - * for the same name, and will return them on repeated requests to the - * getInstance() method.

- * - * @author Rod Waldhoff - * @author Craig R. McClanahan - * @author Richard A. Sitze - * @author Brian Stansberry - * @version $Revision: 581090 $ $Date: 2007-10-02 00:01:06 +0200 (ti, 02 okt 2007) $ - */ - -public class LogFactoryImpl extends LogFactory { - - - /** Log4JLogger class name */ - private static final String LOGGING_IMPL_LOG4J_LOGGER = "org.apache.commons.logging.impl.Log4JLogger"; - /** Jdk14Logger class name */ - private static final String LOGGING_IMPL_JDK14_LOGGER = "org.apache.commons.logging.impl.Jdk14Logger"; - /** Jdk13LumberjackLogger class name */ - private static final String LOGGING_IMPL_LUMBERJACK_LOGGER = "org.apache.commons.logging.impl.Jdk13LumberjackLogger"; - /** SimpleLog class name */ - private static final String LOGGING_IMPL_SIMPLE_LOGGER = "org.apache.commons.logging.impl.SimpleLog"; - - private static final String PKG_IMPL="org.apache.commons.logging.impl."; - private static final int PKG_LEN = PKG_IMPL.length(); - - // ----------------------------------------------------------- Constructors - - - - /** - * Public no-arguments constructor required by the lookup mechanism. - */ - public LogFactoryImpl() { - super(); - initDiagnostics(); // method on this object - if (isDiagnosticsEnabled()) { - logDiagnostic("Instance created."); - } - } - - - // ----------------------------------------------------- Manifest Constants - - - /** - * The name (org.apache.commons.logging.Log) of the system - * property identifying our {@link Log} implementation class. - */ - public static final String LOG_PROPERTY = - "org.apache.commons.logging.Log"; - - - /** - * The deprecated system property used for backwards compatibility with - * old versions of JCL. - */ - protected static final String LOG_PROPERTY_OLD = - "org.apache.commons.logging.log"; - - /** - * The name (org.apache.commons.logging.Log.allowFlawedContext) - * of the system property which can be set true/false to - * determine system behaviour when a bad context-classloader is encountered. - * When set to false, a LogConfigurationException is thrown if - * LogFactoryImpl is loaded via a child classloader of the TCCL (this - * should never happen in sane systems). - * - * Default behaviour: true (tolerates bad context classloaders) - * - * See also method setAttribute. - */ - public static final String ALLOW_FLAWED_CONTEXT_PROPERTY = - "org.apache.commons.logging.Log.allowFlawedContext"; - - /** - * The name (org.apache.commons.logging.Log.allowFlawedDiscovery) - * of the system property which can be set true/false to - * determine system behaviour when a bad logging adapter class is - * encountered during logging discovery. When set to false, an - * exception will be thrown and the app will fail to start. When set - * to true, discovery will continue (though the user might end up - * with a different logging implementation than they expected). - * - * Default behaviour: true (tolerates bad logging adapters) - * - * See also method setAttribute. - */ - public static final String ALLOW_FLAWED_DISCOVERY_PROPERTY = - "org.apache.commons.logging.Log.allowFlawedDiscovery"; - - /** - * The name (org.apache.commons.logging.Log.allowFlawedHierarchy) - * of the system property which can be set true/false to - * determine system behaviour when a logging adapter class is - * encountered which has bound to the wrong Log class implementation. - * When set to false, an exception will be thrown and the app will fail - * to start. When set to true, discovery will continue (though the user - * might end up with a different logging implementation than they expected). - * - * Default behaviour: true (tolerates bad Log class hierarchy) - * - * See also method setAttribute. - */ - public static final String ALLOW_FLAWED_HIERARCHY_PROPERTY = - "org.apache.commons.logging.Log.allowFlawedHierarchy"; - - - /** - * The names of classes that will be tried (in order) as logging - * adapters. Each class is expected to implement the Log interface, - * and to throw NoClassDefFound or ExceptionInInitializerError when - * loaded if the underlying logging library is not available. Any - * other error indicates that the underlying logging library is available - * but broken/unusable for some reason. - */ - private static final String[] classesToDiscover = { - LOGGING_IMPL_LOG4J_LOGGER, - "org.apache.commons.logging.impl.Jdk14Logger", - "org.apache.commons.logging.impl.Jdk13LumberjackLogger", - "org.apache.commons.logging.impl.SimpleLog" - }; - - - // ----------------------------------------------------- Instance Variables - - /** - * Determines whether logging classes should be loaded using the thread-context - * classloader, or via the classloader that loaded this LogFactoryImpl class. - */ - private boolean useTCCL = true; - - /** - * The string prefixed to every message output by the logDiagnostic method. - */ - private String diagnosticPrefix; - - - /** - * Configuration attributes. - */ - protected Hashtable attributes = new Hashtable(); - - - /** - * The {@link org.apache.commons.logging.Log} instances that have - * already been created, keyed by logger name. - */ - protected Hashtable instances = new Hashtable(); - - - /** - * Name of the class implementing the Log interface. - */ - private String logClassName; - - - /** - * The one-argument constructor of the - * {@link org.apache.commons.logging.Log} - * implementation class that will be used to create new instances. - * This value is initialized by getLogConstructor(), - * and then returned repeatedly. - */ - protected Constructor logConstructor = null; - - - /** - * The signature of the Constructor to be used. - */ - protected Class logConstructorSignature[] = - { java.lang.String.class }; - - - /** - * The one-argument setLogFactory method of the selected - * {@link org.apache.commons.logging.Log} method, if it exists. - */ - protected Method logMethod = null; - - - /** - * The signature of the setLogFactory method to be used. - */ - protected Class logMethodSignature[] = - { LogFactory.class }; - - /** - * See getBaseClassLoader and initConfiguration. - */ - private boolean allowFlawedContext; - - /** - * See handleFlawedDiscovery and initConfiguration. - */ - private boolean allowFlawedDiscovery; - - /** - * See handleFlawedHierarchy and initConfiguration. - */ - private boolean allowFlawedHierarchy; - - // --------------------------------------------------------- Public Methods - - - /** - * Return the configuration attribute with the specified name (if any), - * or null if there is no such attribute. - * - * @param name Name of the attribute to return - */ - public Object getAttribute(String name) { - - return (attributes.get(name)); - - } - - - /** - * Return an array containing the names of all currently defined - * configuration attributes. If there are no such attributes, a zero - * length array is returned. - */ - public String[] getAttributeNames() { - - Vector names = new Vector(); - Enumeration keys = attributes.keys(); - while (keys.hasMoreElements()) { - names.addElement((String) keys.nextElement()); - } - String results[] = new String[names.size()]; - for (int i = 0; i < results.length; i++) { - results[i] = (String) names.elementAt(i); - } - return (results); - - } - - - /** - * Convenience method to derive a name from the specified class and - * call getInstance(String) with it. - * - * @param clazz Class for which a suitable Log name will be derived - * - * @exception LogConfigurationException if a suitable Log - * instance cannot be returned - */ - public Log getInstance(Class clazz) throws LogConfigurationException { - - return (getInstance(clazz.getName())); - - } - - - /** - *

Construct (if necessary) and return a Log instance, - * using the factory's current set of configuration attributes.

- * - *

NOTE - Depending upon the implementation of - * the LogFactory you are using, the Log - * instance you are returned may or may not be local to the current - * application, and may or may not be returned again on a subsequent - * call with the same name argument.

- * - * @param name Logical name of the Log instance to be - * returned (the meaning of this name is only known to the underlying - * logging implementation that is being wrapped) - * - * @exception LogConfigurationException if a suitable Log - * instance cannot be returned - */ - public Log getInstance(String name) throws LogConfigurationException { - - Log instance = (Log) instances.get(name); - if (instance == null) { - instance = newInstance(name); - instances.put(name, instance); - } - return (instance); - - } - - - /** - * Release any internal references to previously created - * {@link org.apache.commons.logging.Log} - * instances returned by this factory. This is useful in environments - * like servlet containers, which implement application reloading by - * throwing away a ClassLoader. Dangling references to objects in that - * class loader would prevent garbage collection. - */ - public void release() { - - logDiagnostic("Releasing all known loggers"); - instances.clear(); - } - - - /** - * Remove any configuration attribute associated with the specified name. - * If there is no such attribute, no action is taken. - * - * @param name Name of the attribute to remove - */ - public void removeAttribute(String name) { - - attributes.remove(name); - - } - - - /** - * Set the configuration attribute with the specified name. Calling - * this with a null value is equivalent to calling - * removeAttribute(name). - *

- * This method can be used to set logging configuration programmatically - * rather than via system properties. It can also be used in code running - * within a container (such as a webapp) to configure behaviour on a - * per-component level instead of globally as system properties would do. - * To use this method instead of a system property, call - *

-     * LogFactory.getFactory().setAttribute(...)
-     * 
- * This must be done before the first Log object is created; configuration - * changes after that point will be ignored. - *

- * This method is also called automatically if LogFactory detects a - * commons-logging.properties file; every entry in that file is set - * automatically as an attribute here. - * - * @param name Name of the attribute to set - * @param value Value of the attribute to set, or null - * to remove any setting for this attribute - */ - public void setAttribute(String name, Object value) { - - if (logConstructor != null) { - logDiagnostic("setAttribute: call too late; configuration already performed."); - } - - if (value == null) { - attributes.remove(name); - } else { - attributes.put(name, value); - } - - if (name.equals(TCCL_KEY)) { - useTCCL = Boolean.valueOf(value.toString()).booleanValue(); - } - - } - - - // ------------------------------------------------------ - // Static Methods - // - // These methods only defined as workarounds for a java 1.2 bug; - // theoretically none of these are needed. - // ------------------------------------------------------ - - /** - * Gets the context classloader. - * This method is a workaround for a java 1.2 compiler bug. - * @since 1.1 - */ - protected static ClassLoader getContextClassLoader() throws LogConfigurationException { - return LogFactory.getContextClassLoader(); - } - - - /** - * Workaround for bug in Java1.2; in theory this method is not needed. - * See LogFactory.isDiagnosticsEnabled. - */ - protected static boolean isDiagnosticsEnabled() { - return LogFactory.isDiagnosticsEnabled(); - } - - - /** - * Workaround for bug in Java1.2; in theory this method is not needed. - * See LogFactory.getClassLoader. - * @since 1.1 - */ - protected static ClassLoader getClassLoader(Class clazz) { - return LogFactory.getClassLoader(clazz); - } - - - // ------------------------------------------------------ Protected Methods - - /** - * Calculate and cache a string that uniquely identifies this instance, - * including which classloader the object was loaded from. - *

- * This string will later be prefixed to each "internal logging" message - * emitted, so that users can clearly see any unexpected behaviour. - *

- * Note that this method does not detect whether internal logging is - * enabled or not, nor where to output stuff if it is; that is all - * handled by the parent LogFactory class. This method just computes - * its own unique prefix for log messages. - */ - private void initDiagnostics() { - // It would be nice to include an identifier of the context classloader - // that this LogFactoryImpl object is responsible for. However that - // isn't possible as that information isn't available. It is possible - // to figure this out by looking at the logging from LogFactory to - // see the context & impl ids from when this object was instantiated, - // in order to link the impl id output as this object's prefix back to - // the context it is intended to manage. - // Note that this prefix should be kept consistent with that - // in LogFactory. - Class clazz = this.getClass(); - ClassLoader classLoader = getClassLoader(clazz); - String classLoaderName; - try { - if (classLoader == null) { - classLoaderName = "BOOTLOADER"; - } else { - classLoaderName = objectId(classLoader); - } - } catch(SecurityException e) { - classLoaderName = "UNKNOWN"; - } - diagnosticPrefix = "[LogFactoryImpl@" + System.identityHashCode(this) + " from " + classLoaderName + "] "; - } - - - /** - * Output a diagnostic message to a user-specified destination (if the - * user has enabled diagnostic logging). - * - * @param msg diagnostic message - * @since 1.1 - */ - protected void logDiagnostic(String msg) { - if (isDiagnosticsEnabled()) { - logRawDiagnostic(diagnosticPrefix + msg); - } - } - - /** - * Return the fully qualified Java classname of the {@link Log} - * implementation we will be using. - * - * @deprecated Never invoked by this class; subclasses should not assume - * it will be. - */ - protected String getLogClassName() { - - if (logClassName == null) { - discoverLogImplementation(getClass().getName()); - } - - return logClassName; - } - - - /** - *

Return the Constructor that can be called to instantiate - * new {@link org.apache.commons.logging.Log} instances.

- * - *

IMPLEMENTATION NOTE - Race conditions caused by - * calling this method from more than one thread are ignored, because - * the same Constructor instance will ultimately be derived - * in all circumstances.

- * - * @exception LogConfigurationException if a suitable constructor - * cannot be returned - * - * @deprecated Never invoked by this class; subclasses should not assume - * it will be. - */ - protected Constructor getLogConstructor() - throws LogConfigurationException { - - // Return the previously identified Constructor (if any) - if (logConstructor == null) { - discoverLogImplementation(getClass().getName()); - } - - return logConstructor; - } - - - /** - * Is JDK 1.3 with Lumberjack logging available? - * - * @deprecated Never invoked by this class; subclasses should not assume - * it will be. - */ - protected boolean isJdk13LumberjackAvailable() { - return isLogLibraryAvailable( - "Jdk13Lumberjack", - "org.apache.commons.logging.impl.Jdk13LumberjackLogger"); - } - - - /** - *

Return true if JDK 1.4 or later logging - * is available. Also checks that the Throwable class - * supports getStackTrace(), which is required by - * Jdk14Logger.

- * - * @deprecated Never invoked by this class; subclasses should not assume - * it will be. - */ - protected boolean isJdk14Available() { - return isLogLibraryAvailable( - "Jdk14", - "org.apache.commons.logging.impl.Jdk14Logger"); - } - - - /** - * Is a Log4J implementation available? - * - * @deprecated Never invoked by this class; subclasses should not assume - * it will be. - */ - protected boolean isLog4JAvailable() { - return isLogLibraryAvailable( - "Log4J", - LOGGING_IMPL_LOG4J_LOGGER); - } - - - /** - * Create and return a new {@link org.apache.commons.logging.Log} - * instance for the specified name. - * - * @param name Name of the new logger - * - * @exception LogConfigurationException if a new instance cannot - * be created - */ - protected Log newInstance(String name) throws LogConfigurationException { - - Log instance = null; - try { - if (logConstructor == null) { - instance = discoverLogImplementation(name); - } - else { - Object params[] = { name }; - instance = (Log) logConstructor.newInstance(params); - } - - if (logMethod != null) { - Object params[] = { this }; - logMethod.invoke(instance, params); - } - - return (instance); - - } catch (LogConfigurationException lce) { - - // this type of exception means there was a problem in discovery - // and we've already output diagnostics about the issue, etc.; - // just pass it on - throw (LogConfigurationException) lce; - - } catch (InvocationTargetException e) { - // A problem occurred invoking the Constructor or Method - // previously discovered - Throwable c = e.getTargetException(); - if (c != null) { - throw new LogConfigurationException(c); - } else { - throw new LogConfigurationException(e); - } - } catch (Throwable t) { - // A problem occurred invoking the Constructor or Method - // previously discovered - throw new LogConfigurationException(t); - } - } - - - // ------------------------------------------------------ Private Methods - - /** - * Calls LogFactory.directGetContextClassLoader under the control of an - * AccessController class. This means that java code running under a - * security manager that forbids access to ClassLoaders will still work - * if this class is given appropriate privileges, even when the caller - * doesn't have such privileges. Without using an AccessController, the - * the entire call stack must have the privilege before the call is - * allowed. - * - * @return the context classloader associated with the current thread, - * or null if security doesn't allow it. - * - * @throws LogConfigurationException if there was some weird error while - * attempting to get the context classloader. - * - * @throws SecurityException if the current java security policy doesn't - * allow this class to access the context classloader. - */ - private static ClassLoader getContextClassLoaderInternal() - throws LogConfigurationException { - return (ClassLoader)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return LogFactory.directGetContextClassLoader(); - } - }); - } - - /** - * Read the specified system property, using an AccessController so that - * the property can be read if JCL has been granted the appropriate - * security rights even if the calling code has not. - *

- * Take care not to expose the value returned by this method to the - * calling application in any way; otherwise the calling app can use that - * info to access data that should not be available to it. - */ - private static String getSystemProperty(final String key, final String def) - throws SecurityException { - return (String) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return System.getProperty(key, def); - } - }); - } - - /** - * Fetch the parent classloader of a specified classloader. - *

- * If a SecurityException occurs, null is returned. - *

- * Note that this method is non-static merely so logDiagnostic is available. - */ - private ClassLoader getParentClassLoader(final ClassLoader cl) { - try { - return (ClassLoader)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return cl.getParent(); - } - }); - } catch(SecurityException ex) { - logDiagnostic("[SECURITY] Unable to obtain parent classloader"); - return null; - } - - } - - /** - * Utility method to check whether a particular logging library is - * present and available for use. Note that this does not - * affect the future behaviour of this class. - */ - private boolean isLogLibraryAvailable(String name, String classname) { - if (isDiagnosticsEnabled()) { - logDiagnostic("Checking for '" + name + "'."); - } - try { - Log log = createLogFromClass( - classname, - this.getClass().getName(), // dummy category - false); - - if (log == null) { - if (isDiagnosticsEnabled()) { - logDiagnostic("Did not find '" + name + "'."); - } - return false; - } else { - if (isDiagnosticsEnabled()) { - logDiagnostic("Found '" + name + "'."); - } - return true; - } - } catch(LogConfigurationException e) { - if (isDiagnosticsEnabled()) { - logDiagnostic("Logging system '" + name + "' is available but not useable."); - } - return false; - } - } - - /** - * Attempt to find an attribute (see method setAttribute) or a - * system property with the provided name and return its value. - *

- * The attributes associated with this object are checked before - * system properties in case someone has explicitly called setAttribute, - * or a configuration property has been set in a commons-logging.properties - * file. - * - * @return the value associated with the property, or null. - */ - private String getConfigurationValue(String property) { - if (isDiagnosticsEnabled()) { - logDiagnostic("[ENV] Trying to get configuration for item " + property); - } - - Object valueObj = getAttribute(property); - if (valueObj != null) { - if (isDiagnosticsEnabled()) { - logDiagnostic("[ENV] Found LogFactory attribute [" + valueObj + "] for " + property); - } - return valueObj.toString(); - } - - if (isDiagnosticsEnabled()) { - logDiagnostic("[ENV] No LogFactory attribute found for " + property); - } - - try { - // warning: minor security hole here, in that we potentially read a system - // property that the caller cannot, then output it in readable form as a - // diagnostic message. However it's only ever JCL-specific properties - // involved here, so the harm is truly trivial. - String value = getSystemProperty(property, null); - if (value != null) { - if (isDiagnosticsEnabled()) { - logDiagnostic("[ENV] Found system property [" + value + "] for " + property); - } - return value; - } - - if (isDiagnosticsEnabled()) { - logDiagnostic("[ENV] No system property found for property " + property); - } - } catch (SecurityException e) { - if (isDiagnosticsEnabled()) { - logDiagnostic("[ENV] Security prevented reading system property " + property); - } - } - - if (isDiagnosticsEnabled()) { - logDiagnostic("[ENV] No configuration defined for item " + property); - } - - return null; - } - - /** - * Get the setting for the user-configurable behaviour specified by key. - * If nothing has explicitly been set, then return dflt. - */ - private boolean getBooleanConfiguration(String key, boolean dflt) { - String val = getConfigurationValue(key); - if (val == null) - return dflt; - return Boolean.valueOf(val).booleanValue(); - } - - /** - * Initialize a number of variables that control the behaviour of this - * class and that can be tweaked by the user. This is done when the first - * logger is created, not in the constructor of this class, because we - * need to give the user a chance to call method setAttribute in order to - * configure this object. - */ - private void initConfiguration() { - allowFlawedContext = getBooleanConfiguration(ALLOW_FLAWED_CONTEXT_PROPERTY, true); - allowFlawedDiscovery = getBooleanConfiguration(ALLOW_FLAWED_DISCOVERY_PROPERTY, true); - allowFlawedHierarchy = getBooleanConfiguration(ALLOW_FLAWED_HIERARCHY_PROPERTY, true); - } - - - /** - * Attempts to create a Log instance for the given category name. - * Follows the discovery process described in the class javadoc. - * - * @param logCategory the name of the log category - * - * @throws LogConfigurationException if an error in discovery occurs, - * or if no adapter at all can be instantiated - */ - private Log discoverLogImplementation(String logCategory) - throws LogConfigurationException - { - if (isDiagnosticsEnabled()) { - logDiagnostic("Discovering a Log implementation..."); - } - - initConfiguration(); - - Log result = null; - - // See if the user specified the Log implementation to use - String specifiedLogClassName = findUserSpecifiedLogClassName(); - - if (specifiedLogClassName != null) { - if (isDiagnosticsEnabled()) { - logDiagnostic("Attempting to load user-specified log class '" + - specifiedLogClassName + "'..."); - } - - result = createLogFromClass(specifiedLogClassName, - logCategory, - true); - if (result == null) { - StringBuffer messageBuffer = new StringBuffer("User-specified log class '"); - messageBuffer.append(specifiedLogClassName); - messageBuffer.append("' cannot be found or is not useable."); - - // Mistyping or misspelling names is a common fault. - // Construct a good error message, if we can - if (specifiedLogClassName != null) { - informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LOG4J_LOGGER); - informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_JDK14_LOGGER); - informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LUMBERJACK_LOGGER); - informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_SIMPLE_LOGGER); - } - throw new LogConfigurationException(messageBuffer.toString()); - } - - return result; - } - - // No user specified log; try to discover what's on the classpath - // - // Note that we deliberately loop here over classesToDiscover and - // expect method createLogFromClass to loop over the possible source - // classloaders. The effect is: - // for each discoverable log adapter - // for each possible classloader - // see if it works - // - // It appears reasonable at first glance to do the opposite: - // for each possible classloader - // for each discoverable log adapter - // see if it works - // - // The latter certainly has advantages for user-installable logging - // libraries such as log4j; in a webapp for example this code should - // first check whether the user has provided any of the possible - // logging libraries before looking in the parent classloader. - // Unfortunately, however, Jdk14Logger will always work in jvm>=1.4, - // and SimpleLog will always work in any JVM. So the loop would never - // ever look for logging libraries in the parent classpath. Yet many - // users would expect that putting log4j there would cause it to be - // detected (and this is the historical JCL behaviour). So we go with - // the first approach. A user that has bundled a specific logging lib - // in a webapp should use a commons-logging.properties file or a - // service file in META-INF to force use of that logging lib anyway, - // rather than relying on discovery. - - if (isDiagnosticsEnabled()) { - logDiagnostic( - "No user-specified Log implementation; performing discovery" + - " using the standard supported logging implementations..."); - } - for(int i=0; (iStringBuffer the message should be appended to, - * not null - * @param name the (trimmed) name to be test against the candidate, not null - * @param candidate the candidate name (not null) - */ - private void informUponSimilarName(final StringBuffer messageBuffer, final String name, - final String candidate) { - if (name.equals(candidate)) { - // Don't suggest a name that is exactly the same as the one the - // user tried... - return; - } - - // If the user provides a name that is in the right package, and gets - // the first 5 characters of the adapter class right (ignoring case), - // then suggest the candidate adapter class name. - if (name.regionMatches(true, 0, candidate, 0, PKG_LEN + 5)) { - messageBuffer.append(" Did you mean '"); - messageBuffer.append(candidate); - messageBuffer.append("'?"); - } - } - - - /** - * Checks system properties and the attribute map for - * a Log implementation specified by the user under the - * property names {@link #LOG_PROPERTY} or {@link #LOG_PROPERTY_OLD}. - * - * @return classname specified by the user, or null - */ - private String findUserSpecifiedLogClassName() - { - if (isDiagnosticsEnabled()) { - logDiagnostic("Trying to get log class from attribute '" + LOG_PROPERTY + "'"); - } - String specifiedClass = (String) getAttribute(LOG_PROPERTY); - - if (specifiedClass == null) { // @deprecated - if (isDiagnosticsEnabled()) { - logDiagnostic("Trying to get log class from attribute '" + - LOG_PROPERTY_OLD + "'"); - } - specifiedClass = (String) getAttribute(LOG_PROPERTY_OLD); - } - - if (specifiedClass == null) { - if (isDiagnosticsEnabled()) { - logDiagnostic("Trying to get log class from system property '" + - LOG_PROPERTY + "'"); - } - try { - specifiedClass = getSystemProperty(LOG_PROPERTY, null); - } catch (SecurityException e) { - if (isDiagnosticsEnabled()) { - logDiagnostic("No access allowed to system property '" + - LOG_PROPERTY + "' - " + e.getMessage()); - } - } - } - - if (specifiedClass == null) { // @deprecated - if (isDiagnosticsEnabled()) { - logDiagnostic("Trying to get log class from system property '" + - LOG_PROPERTY_OLD + "'"); - } - try { - specifiedClass = getSystemProperty(LOG_PROPERTY_OLD, null); - } catch (SecurityException e) { - if (isDiagnosticsEnabled()) { - logDiagnostic("No access allowed to system property '" + - LOG_PROPERTY_OLD + "' - " + e.getMessage()); - } - } - } - - // Remove any whitespace; it's never valid in a classname so its - // presence just means a user mistake. As we know what they meant, - // we may as well strip the spaces. - if (specifiedClass != null) { - specifiedClass = specifiedClass.trim(); - } - - return specifiedClass; - } - - - /** - * Attempts to load the given class, find a suitable constructor, - * and instantiate an instance of Log. - * - * @param logAdapterClassName classname of the Log implementation - * - * @param logCategory argument to pass to the Log implementation's - * constructor - * - * @param affectState true if this object's state should - * be affected by this method call, false otherwise. - * - * @return an instance of the given class, or null if the logging - * library associated with the specified adapter is not available. - * - * @throws LogConfigurationException if there was a serious error with - * configuration and the handleFlawedDiscovery method decided this - * problem was fatal. - */ - private Log createLogFromClass(String logAdapterClassName, - String logCategory, - boolean affectState) - throws LogConfigurationException { - - if (isDiagnosticsEnabled()) { - logDiagnostic("Attempting to instantiate '" + logAdapterClassName + "'"); - } - - Object[] params = { logCategory }; - Log logAdapter = null; - Constructor constructor = null; - - Class logAdapterClass = null; - ClassLoader currentCL = getBaseClassLoader(); - - for(;;) { - // Loop through the classloader hierarchy trying to find - // a viable classloader. - logDiagnostic( - "Trying to load '" - + logAdapterClassName - + "' from classloader " - + objectId(currentCL)); - try { - if (isDiagnosticsEnabled()) { - // Show the location of the first occurrence of the .class file - // in the classpath. This is the location that ClassLoader.loadClass - // will load the class from -- unless the classloader is doing - // something weird. - URL url; - String resourceName = logAdapterClassName.replace('.', '/') + ".class"; - if (currentCL != null) { - url = currentCL.getResource(resourceName ); - } else { - url = ClassLoader.getSystemResource(resourceName + ".class"); - } - - if (url == null) { - logDiagnostic("Class '" + logAdapterClassName + "' [" + resourceName + "] cannot be found."); - } else { - logDiagnostic("Class '" + logAdapterClassName + "' was found at '" + url + "'"); - } - } - - Class c = null; - try { - c = Class.forName(logAdapterClassName, true, currentCL); - } catch (ClassNotFoundException originalClassNotFoundException) { - // The current classloader was unable to find the log adapter - // in this or any ancestor classloader. There's no point in - // trying higher up in the hierarchy in this case.. - String msg = "" + originalClassNotFoundException.getMessage(); - logDiagnostic( - "The log adapter '" - + logAdapterClassName - + "' is not available via classloader " - + objectId(currentCL) - + ": " - + msg.trim()); - try { - // Try the class classloader. - // This may work in cases where the TCCL - // does not contain the code executed or JCL. - // This behaviour indicates that the application - // classloading strategy is not consistent with the - // Java 1.2 classloading guidelines but JCL can - // and so should handle this case. - c = Class.forName(logAdapterClassName); - } catch (ClassNotFoundException secondaryClassNotFoundException) { - // no point continuing: this adapter isn't available - msg = "" + secondaryClassNotFoundException.getMessage(); - logDiagnostic( - "The log adapter '" - + logAdapterClassName - + "' is not available via the LogFactoryImpl class classloader: " - + msg.trim()); - break; - } - } - - constructor = c.getConstructor(logConstructorSignature); - Object o = constructor.newInstance(params); - - // Note that we do this test after trying to create an instance - // [rather than testing Log.class.isAssignableFrom(c)] so that - // we don't complain about Log hierarchy problems when the - // adapter couldn't be instantiated anyway. - if (o instanceof Log) { - logAdapterClass = c; - logAdapter = (Log) o; - break; - } - - // Oops, we have a potential problem here. An adapter class - // has been found and its underlying lib is present too, but - // there are multiple Log interface classes available making it - // impossible to cast to the type the caller wanted. We - // certainly can't use this logger, but we need to know whether - // to keep on discovering or terminate now. - // - // The handleFlawedHierarchy method will throw - // LogConfigurationException if it regards this problem as - // fatal, and just return if not. - handleFlawedHierarchy(currentCL, c); - } catch (NoClassDefFoundError e) { - // We were able to load the adapter but it had references to - // other classes that could not be found. This simply means that - // the underlying logger library is not present in this or any - // ancestor classloader. There's no point in trying higher up - // in the hierarchy in this case.. - String msg = "" + e.getMessage(); - logDiagnostic( - "The log adapter '" - + logAdapterClassName - + "' is missing dependencies when loaded via classloader " - + objectId(currentCL) - + ": " - + msg.trim()); - break; - } catch (ExceptionInInitializerError e) { - // A static initializer block or the initializer code associated - // with a static variable on the log adapter class has thrown - // an exception. - // - // We treat this as meaning the adapter's underlying logging - // library could not be found. - String msg = "" + e.getMessage(); - logDiagnostic( - "The log adapter '" - + logAdapterClassName - + "' is unable to initialize itself when loaded via classloader " - + objectId(currentCL) - + ": " - + msg.trim()); - break; - } catch(LogConfigurationException e) { - // call to handleFlawedHierarchy above must have thrown - // a LogConfigurationException, so just throw it on - throw e; - } catch(Throwable t) { - // handleFlawedDiscovery will determine whether this is a fatal - // problem or not. If it is fatal, then a LogConfigurationException - // will be thrown. - handleFlawedDiscovery(logAdapterClassName, currentCL, t); - } - - if (currentCL == null) { - break; - } - - // try the parent classloader - // currentCL = currentCL.getParent(); - currentCL = getParentClassLoader(currentCL); - } - - if ((logAdapter != null) && affectState) { - // We've succeeded, so set instance fields - this.logClassName = logAdapterClassName; - this.logConstructor = constructor; - - // Identify the setLogFactory method (if there is one) - try { - this.logMethod = logAdapterClass.getMethod("setLogFactory", - logMethodSignature); - logDiagnostic("Found method setLogFactory(LogFactory) in '" - + logAdapterClassName + "'"); - } catch (Throwable t) { - this.logMethod = null; - logDiagnostic( - "[INFO] '" + logAdapterClassName - + "' from classloader " + objectId(currentCL) - + " does not declare optional method " - + "setLogFactory(LogFactory)"); - } - - logDiagnostic( - "Log adapter '" + logAdapterClassName - + "' from classloader " + objectId(logAdapterClass.getClassLoader()) - + " has been selected for use."); - } - - return logAdapter; - } - - - /** - * Return the classloader from which we should try to load the logging - * adapter classes. - *

- * This method usually returns the context classloader. However if it - * is discovered that the classloader which loaded this class is a child - * of the context classloader and the allowFlawedContext option - * has been set then the classloader which loaded this class is returned - * instead. - *

- * The only time when the classloader which loaded this class is a - * descendant (rather than the same as or an ancestor of the context - * classloader) is when an app has created custom classloaders but - * failed to correctly set the context classloader. This is a bug in - * the calling application; however we provide the option for JCL to - * simply generate a warning rather than fail outright. - * - */ - private ClassLoader getBaseClassLoader() throws LogConfigurationException { - ClassLoader thisClassLoader = getClassLoader(LogFactoryImpl.class); - - if (useTCCL == false) { - return thisClassLoader; - } - - ClassLoader contextClassLoader = getContextClassLoaderInternal(); - - ClassLoader baseClassLoader = getLowestClassLoader( - contextClassLoader, thisClassLoader); - - if (baseClassLoader == null) { - // The two classloaders are not part of a parent child relationship. - // In some classloading setups (e.g. JBoss with its - // UnifiedLoaderRepository) this can still work, so if user hasn't - // forbidden it, just return the contextClassLoader. - if (allowFlawedContext) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[WARNING] the context classloader is not part of a" - + " parent-child relationship with the classloader that" - + " loaded LogFactoryImpl."); - } - // If contextClassLoader were null, getLowestClassLoader() would - // have returned thisClassLoader. The fact we are here means - // contextClassLoader is not null, so we can just return it. - return contextClassLoader; - } - else { - throw new LogConfigurationException( - "Bad classloader hierarchy; LogFactoryImpl was loaded via" - + " a classloader that is not related to the current context" - + " classloader."); - } - } - - if (baseClassLoader != contextClassLoader) { - // We really should just use the contextClassLoader as the starting - // point for scanning for log adapter classes. However it is expected - // that there are a number of broken systems out there which create - // custom classloaders but fail to set the context classloader so - // we handle those flawed systems anyway. - if (allowFlawedContext) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Warning: the context classloader is an ancestor of the" - + " classloader that loaded LogFactoryImpl; it should be" - + " the same or a descendant. The application using" - + " commons-logging should ensure the context classloader" - + " is used correctly."); - } - } else { - throw new LogConfigurationException( - "Bad classloader hierarchy; LogFactoryImpl was loaded via" - + " a classloader that is not related to the current context" - + " classloader."); - } - } - - return baseClassLoader; - } - - /** - * Given two related classloaders, return the one which is a child of - * the other. - *

- * @param c1 is a classloader (including the null classloader) - * @param c2 is a classloader (including the null classloader) - * - * @return c1 if it has c2 as an ancestor, c2 if it has c1 as an ancestor, - * and null if neither is an ancestor of the other. - */ - private ClassLoader getLowestClassLoader(ClassLoader c1, ClassLoader c2) { - // TODO: use AccessController when dealing with classloaders here - - if (c1 == null) - return c2; - - if (c2 == null) - return c1; - - ClassLoader current; - - // scan c1's ancestors to find c2 - current = c1; - while (current != null) { - if (current == c2) - return c1; - current = current.getParent(); - } - - // scan c2's ancestors to find c1 - current = c2; - while (current != null) { - if (current == c1) - return c2; - current = current.getParent(); - } - - return null; - } - - /** - * Generates an internal diagnostic logging of the discovery failure and - * then throws a LogConfigurationException that wraps - * the passed Throwable. - * - * @param logAdapterClassName is the class name of the Log implementation - * that could not be instantiated. Cannot be null. - * - * @param classLoader is the classloader that we were trying to load the - * logAdapterClassName from when the exception occurred. - * - * @param discoveryFlaw is the Throwable created by the classloader - * - * @throws LogConfigurationException ALWAYS - */ - private void handleFlawedDiscovery(String logAdapterClassName, - ClassLoader classLoader, - Throwable discoveryFlaw) { - - if (isDiagnosticsEnabled()) { - logDiagnostic("Could not instantiate Log '" - + logAdapterClassName + "' -- " - + discoveryFlaw.getClass().getName() + ": " - + discoveryFlaw.getLocalizedMessage()); - - if (discoveryFlaw instanceof InvocationTargetException ) { - // Ok, the lib is there but while trying to create a real underlying - // logger something failed in the underlying lib; display info about - // that if possible. - InvocationTargetException ite = (InvocationTargetException)discoveryFlaw; - Throwable cause = ite.getTargetException(); - if (cause != null) { - logDiagnostic("... InvocationTargetException: " + - cause.getClass().getName() + ": " + - cause.getLocalizedMessage()); - - if (cause instanceof ExceptionInInitializerError) { - ExceptionInInitializerError eiie = (ExceptionInInitializerError)cause; - Throwable cause2 = eiie.getException(); - if (cause2 != null) { - logDiagnostic("... ExceptionInInitializerError: " + - cause2.getClass().getName() + ": " + - cause2.getLocalizedMessage()); - } - } - } - } - } - - if (!allowFlawedDiscovery) { - throw new LogConfigurationException(discoveryFlaw); - } - } - - - /** - * Report a problem loading the log adapter, then either return - * (if the situation is considered recoverable) or throw a - * LogConfigurationException. - *

- * There are two possible reasons why we successfully loaded the - * specified log adapter class then failed to cast it to a Log object: - *

    - *
  1. the specific class just doesn't implement the Log interface - * (user screwed up), or - *
  2. the specified class has bound to a Log class loaded by some other - * classloader; Log@classloaderX cannot be cast to Log@classloaderY. - *
- *

- * Here we try to figure out which case has occurred so we can give the - * user some reasonable feedback. - * - * @param badClassLoader is the classloader we loaded the problem class from, - * ie it is equivalent to badClass.getClassLoader(). - * - * @param badClass is a Class object with the desired name, but which - * does not implement Log correctly. - * - * @throws LogConfigurationException when the situation - * should not be recovered from. - */ - private void handleFlawedHierarchy(ClassLoader badClassLoader, Class badClass) - throws LogConfigurationException { - - boolean implementsLog = false; - String logInterfaceName = Log.class.getName(); - Class interfaces[] = badClass.getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - if (logInterfaceName.equals(interfaces[i].getName())) { - implementsLog = true; - break; - } - } - - if (implementsLog) { - // the class does implement an interface called Log, but - // it is in the wrong classloader - if (isDiagnosticsEnabled()) { - try { - ClassLoader logInterfaceClassLoader = getClassLoader(Log.class); - logDiagnostic( - "Class '" + badClass.getName() - + "' was found in classloader " - + objectId(badClassLoader) - + ". It is bound to a Log interface which is not" - + " the one loaded from classloader " - + objectId(logInterfaceClassLoader)); - } catch (Throwable t) { - logDiagnostic( - "Error while trying to output diagnostics about" - + " bad class '" + badClass + "'"); - } - } - - if (!allowFlawedHierarchy) { - StringBuffer msg = new StringBuffer(); - msg.append("Terminating logging for this context "); - msg.append("due to bad log hierarchy. "); - msg.append("You have more than one version of '"); - msg.append(Log.class.getName()); - msg.append("' visible."); - if (isDiagnosticsEnabled()) { - logDiagnostic(msg.toString()); - } - throw new LogConfigurationException(msg.toString()); - } - - if (isDiagnosticsEnabled()) { - StringBuffer msg = new StringBuffer(); - msg.append("Warning: bad log hierarchy. "); - msg.append("You have more than one version of '"); - msg.append(Log.class.getName()); - msg.append("' visible."); - logDiagnostic(msg.toString()); - } - } else { - // this is just a bad adapter class - if (!allowFlawedDiscovery) { - StringBuffer msg = new StringBuffer(); - msg.append("Terminating logging for this context. "); - msg.append("Log class '"); - msg.append(badClass.getName()); - msg.append("' does not implement the Log interface."); - if (isDiagnosticsEnabled()) { - logDiagnostic(msg.toString()); - } - - throw new LogConfigurationException(msg.toString()); - } - - if (isDiagnosticsEnabled()) { - StringBuffer msg = new StringBuffer(); - msg.append("[WARNING] Log class '"); - msg.append(badClass.getName()); - msg.append("' does not implement the Log interface."); - logDiagnostic(msg.toString()); - } - } - } -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/LogKitLogger.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/LogKitLogger.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/LogKitLogger.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/LogKitLogger.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,294 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - -import java.io.Serializable; -import org.apache.log.Logger; -import org.apache.log.Hierarchy; -import org.apache.commons.logging.Log; - -/** - *

Implementation of org.apache.commons.logging.Log - * that wraps the avalon-logkit - * logging system. Configuration of LogKit is left to the user. - *

- * - *

LogKit accepts only String messages. - * Therefore, this implementation converts object messages into strings - * by called their toString() method before logging them.

- * - * @author Scott Sanders - * @author Robert Burrell Donkin - * @version $Id: LogKitLogger.java 424107 2006-07-20 23:15:42Z skitching $ - */ - -public class LogKitLogger implements Log, Serializable { - - - // ------------------------------------------------------------- Attributes - - - /** Logging goes to this LogKit logger */ - protected transient Logger logger = null; - - /** Name of this logger */ - protected String name = null; - - - // ------------------------------------------------------------ Constructor - - - /** - * Construct LogKitLogger which wraps the LogKit - * logger with given name. - * - * @param name log name - */ - public LogKitLogger(String name) { - this.name = name; - this.logger = getLogger(); - } - - - // --------------------------------------------------------- Public Methods - - - /** - *

Return the underlying Logger we are using.

- */ - public Logger getLogger() { - - if (logger == null) { - logger = Hierarchy.getDefaultHierarchy().getLoggerFor(name); - } - return (logger); - - } - - - // ----------------------------------------------------- Log Implementation - - - /** - * Logs a message with org.apache.log.Priority.DEBUG. - * - * @param message to log - * @see org.apache.commons.logging.Log#trace(Object) - */ - public void trace(Object message) { - debug(message); - } - - - /** - * Logs a message with org.apache.log.Priority.DEBUG. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#trace(Object, Throwable) - */ - public void trace(Object message, Throwable t) { - debug(message, t); - } - - - /** - * Logs a message with org.apache.log.Priority.DEBUG. - * - * @param message to log - * @see org.apache.commons.logging.Log#debug(Object) - */ - public void debug(Object message) { - if (message != null) { - getLogger().debug(String.valueOf(message)); - } - } - - - /** - * Logs a message with org.apache.log.Priority.DEBUG. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#debug(Object, Throwable) - */ - public void debug(Object message, Throwable t) { - if (message != null) { - getLogger().debug(String.valueOf(message), t); - } - } - - - /** - * Logs a message with org.apache.log.Priority.INFO. - * - * @param message to log - * @see org.apache.commons.logging.Log#info(Object) - */ - public void info(Object message) { - if (message != null) { - getLogger().info(String.valueOf(message)); - } - } - - - /** - * Logs a message with org.apache.log.Priority.INFO. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#info(Object, Throwable) - */ - public void info(Object message, Throwable t) { - if (message != null) { - getLogger().info(String.valueOf(message), t); - } - } - - - /** - * Logs a message with org.apache.log.Priority.WARN. - * - * @param message to log - * @see org.apache.commons.logging.Log#warn(Object) - */ - public void warn(Object message) { - if (message != null) { - getLogger().warn(String.valueOf(message)); - } - } - - - /** - * Logs a message with org.apache.log.Priority.WARN. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#warn(Object, Throwable) - */ - public void warn(Object message, Throwable t) { - if (message != null) { - getLogger().warn(String.valueOf(message), t); - } - } - - - /** - * Logs a message with org.apache.log.Priority.ERROR. - * - * @param message to log - * @see org.apache.commons.logging.Log#error(Object) - */ - public void error(Object message) { - if (message != null) { - getLogger().error(String.valueOf(message)); - } - } - - - /** - * Logs a message with org.apache.log.Priority.ERROR. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#error(Object, Throwable) - */ - public void error(Object message, Throwable t) { - if (message != null) { - getLogger().error(String.valueOf(message), t); - } - } - - - /** - * Logs a message with org.apache.log.Priority.FATAL_ERROR. - * - * @param message to log - * @see org.apache.commons.logging.Log#fatal(Object) - */ - public void fatal(Object message) { - if (message != null) { - getLogger().fatalError(String.valueOf(message)); - } - } - - - /** - * Logs a message with org.apache.log.Priority.FATAL_ERROR. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#fatal(Object, Throwable) - */ - public void fatal(Object message, Throwable t) { - if (message != null) { - getLogger().fatalError(String.valueOf(message), t); - } - } - - - /** - * Checks whether the LogKit logger will log messages of priority DEBUG. - */ - public boolean isDebugEnabled() { - return getLogger().isDebugEnabled(); - } - - - /** - * Checks whether the LogKit logger will log messages of priority ERROR. - */ - public boolean isErrorEnabled() { - return getLogger().isErrorEnabled(); - } - - - /** - * Checks whether the LogKit logger will log messages of priority FATAL_ERROR. - */ - public boolean isFatalEnabled() { - return getLogger().isFatalErrorEnabled(); - } - - - /** - * Checks whether the LogKit logger will log messages of priority INFO. - */ - public boolean isInfoEnabled() { - return getLogger().isInfoEnabled(); - } - - - /** - * Checks whether the LogKit logger will log messages of priority DEBUG. - */ - public boolean isTraceEnabled() { - return getLogger().isDebugEnabled(); - } - - - /** - * Checks whether the LogKit logger will log messages of priority WARN. - */ - public boolean isWarnEnabled() { - return getLogger().isWarnEnabled(); - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/NoOpLog.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/NoOpLog.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/NoOpLog.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/NoOpLog.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - - -import java.io.Serializable; -import org.apache.commons.logging.Log; - - -/** - *

Trivial implementation of Log that throws away all messages. No - * configurable system properties are supported.

- * - * @author Scott Sanders - * @author Rod Waldhoff - * @version $Id: NoOpLog.java 424107 2006-07-20 23:15:42Z skitching $ - */ -public class NoOpLog implements Log, Serializable { - - /** Convenience constructor */ - public NoOpLog() { } - /** Base constructor */ - public NoOpLog(String name) { } - /** Do nothing */ - public void trace(Object message) { } - /** Do nothing */ - public void trace(Object message, Throwable t) { } - /** Do nothing */ - public void debug(Object message) { } - /** Do nothing */ - public void debug(Object message, Throwable t) { } - /** Do nothing */ - public void info(Object message) { } - /** Do nothing */ - public void info(Object message, Throwable t) { } - /** Do nothing */ - public void warn(Object message) { } - /** Do nothing */ - public void warn(Object message, Throwable t) { } - /** Do nothing */ - public void error(Object message) { } - /** Do nothing */ - public void error(Object message, Throwable t) { } - /** Do nothing */ - public void fatal(Object message) { } - /** Do nothing */ - public void fatal(Object message, Throwable t) { } - - /** - * Debug is never enabled. - * - * @return false - */ - public final boolean isDebugEnabled() { return false; } - - /** - * Error is never enabled. - * - * @return false - */ - public final boolean isErrorEnabled() { return false; } - - /** - * Fatal is never enabled. - * - * @return false - */ - public final boolean isFatalEnabled() { return false; } - - /** - * Info is never enabled. - * - * @return false - */ - public final boolean isInfoEnabled() { return false; } - - /** - * Trace is never enabled. - * - * @return false - */ - public final boolean isTraceEnabled() { return false; } - - /** - * Warn is never enabled. - * - * @return false - */ - public final boolean isWarnEnabled() { return false; } - -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; - -import org.apache.commons.logging.LogFactory; - - -/** - * This class is capable of receiving notifications about the undeployment of - * a webapp, and responds by ensuring that commons-logging releases all - * memory associated with the undeployed webapp. - *

- * In general, the WeakHashtable support added in commons-logging release 1.1 - * ensures that logging classes do not hold references that prevent an - * undeployed webapp's memory from being garbage-collected even when multiple - * copies of commons-logging are deployed via multiple classloaders (a - * situation that earlier versions had problems with). However there are - * some rare cases where the WeakHashtable approach does not work; in these - * situations specifying this class as a listener for the web application will - * ensure that all references held by commons-logging are fully released. - *

- * To use this class, configure the webapp deployment descriptor to call - * this class on webapp undeploy; the contextDestroyed method will tell - * every accessable LogFactory class that the entry in its map for the - * current webapp's context classloader should be cleared. - * - * @since 1.1 - */ - -public class ServletContextCleaner implements ServletContextListener { - - private Class[] RELEASE_SIGNATURE = {ClassLoader.class}; - - /** - * Invoked when a webapp is undeployed, this tells the LogFactory - * class to release any logging information related to the current - * contextClassloader. - */ - public void contextDestroyed(ServletContextEvent sce) { - ClassLoader tccl = Thread.currentThread().getContextClassLoader(); - - Object[] params = new Object[1]; - params[0] = tccl; - - // Walk up the tree of classloaders, finding all the available - // LogFactory classes and releasing any objects associated with - // the tccl (ie the webapp). - // - // When there is only one LogFactory in the classpath, and it - // is within the webapp being undeployed then there is no problem; - // garbage collection works fine. - // - // When there are multiple LogFactory classes in the classpath but - // parent-first classloading is used everywhere, this loop is really - // short. The first instance of LogFactory found will - // be the highest in the classpath, and then no more will be found. - // This is ok, as with this setup this will be the only LogFactory - // holding any data associated with the tccl being released. - // - // When there are multiple LogFactory classes in the classpath and - // child-first classloading is used in any classloader, then multiple - // LogFactory instances may hold info about this TCCL; whenever the - // webapp makes a call into a class loaded via an ancestor classloader - // and that class calls LogFactory the tccl gets registered in - // the LogFactory instance that is visible from the ancestor - // classloader. However the concrete logging library it points - // to is expected to have been loaded via the TCCL, so the - // underlying logging lib is only initialised/configured once. - // These references from ancestor LogFactory classes down to - // TCCL classloaders are held via weak references and so should - // be released but there are circumstances where they may not. - // Walking up the classloader ancestry ladder releasing - // the current tccl at each level tree, though, will definitely - // clear any problem references. - ClassLoader loader = tccl; - while (loader != null) { - // Load via the current loader. Note that if the class is not accessable - // via this loader, but is accessable via some ancestor then that class - // will be returned. - try { - Class logFactoryClass = loader.loadClass("org.apache.commons.logging.LogFactory"); - Method releaseMethod = logFactoryClass.getMethod("release", RELEASE_SIGNATURE); - releaseMethod.invoke(null, params); - loader = logFactoryClass.getClassLoader().getParent(); - } catch(ClassNotFoundException ex) { - // Neither the current classloader nor any of its ancestors could find - // the LogFactory class, so we can stop now. - loader = null; - } catch(NoSuchMethodException ex) { - // This is not expected; every version of JCL has this method - System.err.println("LogFactory instance found which does not support release method!"); - loader = null; - } catch(IllegalAccessException ex) { - // This is not expected; every ancestor class should be accessable - System.err.println("LogFactory instance found which is not accessable!"); - loader = null; - } catch(InvocationTargetException ex) { - // This is not expected - System.err.println("LogFactory instance release method failed!"); - loader = null; - } - } - - // Just to be sure, invoke release on the LogFactory that is visible from - // this ServletContextCleaner class too. This should already have been caught - // by the above loop but just in case... - LogFactory.release(tccl); - } - - /** - * Invoked when a webapp is deployed. Nothing needs to be done here. - */ - public void contextInitialized(ServletContextEvent sce) { - // do nothing - } -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/SimpleLog.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/SimpleLog.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/SimpleLog.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/SimpleLog.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,721 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - -import java.io.InputStream; -import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Properties; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogConfigurationException; - -/** - *

Simple implementation of Log that sends all enabled log messages, - * for all defined loggers, to System.err. The following system properties - * are supported to configure the behavior of this logger:

- *
    - *
  • org.apache.commons.logging.simplelog.defaultlog - - * Default logging detail level for all instances of SimpleLog. - * Must be one of ("trace", "debug", "info", "warn", "error", or "fatal"). - * If not specified, defaults to "info".
  • - *
  • org.apache.commons.logging.simplelog.log.xxxxx - - * Logging detail level for a SimpleLog instance named "xxxxx". - * Must be one of ("trace", "debug", "info", "warn", "error", or "fatal"). - * If not specified, the default logging detail level is used.
  • - *
  • org.apache.commons.logging.simplelog.showlogname - - * Set to true if you want the Log instance name to be - * included in output messages. Defaults to false.
  • - *
  • org.apache.commons.logging.simplelog.showShortLogname - - * Set to true if you want the last component of the name to be - * included in output messages. Defaults to true.
  • - *
  • org.apache.commons.logging.simplelog.showdatetime - - * Set to true if you want the current date and time - * to be included in output messages. Default is false.
  • - *
  • org.apache.commons.logging.simplelog.dateTimeFormat - - * The date and time format to be used in the output messages. - * The pattern describing the date and time format is the same that is - * used in java.text.SimpleDateFormat. If the format is not - * specified or is invalid, the default format is used. - * The default format is yyyy/MM/dd HH:mm:ss:SSS zzz.
  • - *
- * - *

In addition to looking for system properties with the names specified - * above, this implementation also checks for a class loader resource named - * "simplelog.properties", and includes any matching definitions - * from this resource (if it exists).

- * - * @author Scott Sanders - * @author Rod Waldhoff - * @author Robert Burrell Donkin - * - * @version $Id: SimpleLog.java 581090 2007-10-01 22:01:06Z dennisl $ - */ -public class SimpleLog implements Log, Serializable { - - - // ------------------------------------------------------- Class Attributes - - /** All system properties used by SimpleLog start with this */ - static protected final String systemPrefix = - "org.apache.commons.logging.simplelog."; - - /** Properties loaded from simplelog.properties */ - static protected final Properties simpleLogProps = new Properties(); - - /** The default format to use when formating dates */ - static protected final String DEFAULT_DATE_TIME_FORMAT = - "yyyy/MM/dd HH:mm:ss:SSS zzz"; - - /** Include the instance name in the log message? */ - static protected boolean showLogName = false; - /** Include the short name ( last component ) of the logger in the log - * message. Defaults to true - otherwise we'll be lost in a flood of - * messages without knowing who sends them. - */ - static protected boolean showShortName = true; - /** Include the current time in the log message */ - static protected boolean showDateTime = false; - /** The date and time format to use in the log message */ - static protected String dateTimeFormat = DEFAULT_DATE_TIME_FORMAT; - - /** - * Used to format times. - *

- * Any code that accesses this object should first obtain a lock on it, - * ie use synchronized(dateFormatter); this requirement was introduced - * in 1.1.1 to fix an existing thread safety bug (SimpleDateFormat.format - * is not thread-safe). - */ - static protected DateFormat dateFormatter = null; - - // ---------------------------------------------------- Log Level Constants - - - /** "Trace" level logging. */ - public static final int LOG_LEVEL_TRACE = 1; - /** "Debug" level logging. */ - public static final int LOG_LEVEL_DEBUG = 2; - /** "Info" level logging. */ - public static final int LOG_LEVEL_INFO = 3; - /** "Warn" level logging. */ - public static final int LOG_LEVEL_WARN = 4; - /** "Error" level logging. */ - public static final int LOG_LEVEL_ERROR = 5; - /** "Fatal" level logging. */ - public static final int LOG_LEVEL_FATAL = 6; - - /** Enable all logging levels */ - public static final int LOG_LEVEL_ALL = (LOG_LEVEL_TRACE - 1); - - /** Enable no logging levels */ - public static final int LOG_LEVEL_OFF = (LOG_LEVEL_FATAL + 1); - - // ------------------------------------------------------------ Initializer - - private static String getStringProperty(String name) { - String prop = null; - try { - prop = System.getProperty(name); - } catch (SecurityException e) { - ; // Ignore - } - return (prop == null) ? simpleLogProps.getProperty(name) : prop; - } - - private static String getStringProperty(String name, String dephault) { - String prop = getStringProperty(name); - return (prop == null) ? dephault : prop; - } - - private static boolean getBooleanProperty(String name, boolean dephault) { - String prop = getStringProperty(name); - return (prop == null) ? dephault : "true".equalsIgnoreCase(prop); - } - - // Initialize class attributes. - // Load properties file, if found. - // Override with system properties. - static { - // Add props from the resource simplelog.properties - InputStream in = getResourceAsStream("simplelog.properties"); - if(null != in) { - try { - simpleLogProps.load(in); - in.close(); - } catch(java.io.IOException e) { - // ignored - } - } - - showLogName = getBooleanProperty( systemPrefix + "showlogname", showLogName); - showShortName = getBooleanProperty( systemPrefix + "showShortLogname", showShortName); - showDateTime = getBooleanProperty( systemPrefix + "showdatetime", showDateTime); - - if(showDateTime) { - dateTimeFormat = getStringProperty(systemPrefix + "dateTimeFormat", - dateTimeFormat); - try { - dateFormatter = new SimpleDateFormat(dateTimeFormat); - } catch(IllegalArgumentException e) { - // If the format pattern is invalid - use the default format - dateTimeFormat = DEFAULT_DATE_TIME_FORMAT; - dateFormatter = new SimpleDateFormat(dateTimeFormat); - } - } - } - - // ------------------------------------------------------------- Attributes - - /** The name of this simple log instance */ - protected String logName = null; - /** The current log level */ - protected int currentLogLevel; - /** The short name of this simple log instance */ - private String shortLogName = null; - - - // ------------------------------------------------------------ Constructor - - /** - * Construct a simple log with given name. - * - * @param name log name - */ - public SimpleLog(String name) { - - logName = name; - - // Set initial log level - // Used to be: set default log level to ERROR - // IMHO it should be lower, but at least info ( costin ). - setLevel(SimpleLog.LOG_LEVEL_INFO); - - // Set log level from properties - String lvl = getStringProperty(systemPrefix + "log." + logName); - int i = String.valueOf(name).lastIndexOf("."); - while(null == lvl && i > -1) { - name = name.substring(0,i); - lvl = getStringProperty(systemPrefix + "log." + name); - i = String.valueOf(name).lastIndexOf("."); - } - - if(null == lvl) { - lvl = getStringProperty(systemPrefix + "defaultlog"); - } - - if("all".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_ALL); - } else if("trace".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_TRACE); - } else if("debug".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_DEBUG); - } else if("info".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_INFO); - } else if("warn".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_WARN); - } else if("error".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_ERROR); - } else if("fatal".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_FATAL); - } else if("off".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_OFF); - } - - } - - - // -------------------------------------------------------- Properties - - /** - *

Set logging level.

- * - * @param currentLogLevel new logging level - */ - public void setLevel(int currentLogLevel) { - - this.currentLogLevel = currentLogLevel; - - } - - - /** - *

Get logging level.

- */ - public int getLevel() { - - return currentLogLevel; - } - - - // -------------------------------------------------------- Logging Methods - - - /** - *

Do the actual logging. - * This method assembles the message - * and then calls write() to cause it to be written.

- * - * @param type One of the LOG_LEVEL_XXX constants defining the log level - * @param message The message itself (typically a String) - * @param t The exception whose stack trace should be logged - */ - protected void log(int type, Object message, Throwable t) { - // Use a string buffer for better performance - StringBuffer buf = new StringBuffer(); - - // Append date-time if so configured - if(showDateTime) { - Date now = new Date(); - String dateText; - synchronized(dateFormatter) { - dateText = dateFormatter.format(now); - } - buf.append(dateText); - buf.append(" "); - } - - // Append a readable representation of the log level - switch(type) { - case SimpleLog.LOG_LEVEL_TRACE: buf.append("[TRACE] "); break; - case SimpleLog.LOG_LEVEL_DEBUG: buf.append("[DEBUG] "); break; - case SimpleLog.LOG_LEVEL_INFO: buf.append("[INFO] "); break; - case SimpleLog.LOG_LEVEL_WARN: buf.append("[WARN] "); break; - case SimpleLog.LOG_LEVEL_ERROR: buf.append("[ERROR] "); break; - case SimpleLog.LOG_LEVEL_FATAL: buf.append("[FATAL] "); break; - } - - // Append the name of the log instance if so configured - if( showShortName) { - if( shortLogName==null ) { - // Cut all but the last component of the name for both styles - shortLogName = logName.substring(logName.lastIndexOf(".") + 1); - shortLogName = - shortLogName.substring(shortLogName.lastIndexOf("/") + 1); - } - buf.append(String.valueOf(shortLogName)).append(" - "); - } else if(showLogName) { - buf.append(String.valueOf(logName)).append(" - "); - } - - // Append the message - buf.append(String.valueOf(message)); - - // Append stack trace if not null - if(t != null) { - buf.append(" <"); - buf.append(t.toString()); - buf.append(">"); - - java.io.StringWriter sw= new java.io.StringWriter(1024); - java.io.PrintWriter pw= new java.io.PrintWriter(sw); - t.printStackTrace(pw); - pw.close(); - buf.append(sw.toString()); - } - - // Print to the appropriate destination - write(buf); - - } - - - /** - *

Write the content of the message accumulated in the specified - * StringBuffer to the appropriate output destination. The - * default implementation writes to System.err.

- * - * @param buffer A StringBuffer containing the accumulated - * text to be logged - */ - protected void write(StringBuffer buffer) { - - System.err.println(buffer.toString()); - - } - - - /** - * Is the given log level currently enabled? - * - * @param logLevel is this level enabled? - */ - protected boolean isLevelEnabled(int logLevel) { - // log level are numerically ordered so can use simple numeric - // comparison - return (logLevel >= currentLogLevel); - } - - - // -------------------------------------------------------- Log Implementation - - - /** - * Logs a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG. - * - * @param message to log - * @see org.apache.commons.logging.Log#debug(Object) - */ - public final void debug(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) { - log(SimpleLog.LOG_LEVEL_DEBUG, message, null); - } - } - - - /** - * Logs a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#debug(Object, Throwable) - */ - public final void debug(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) { - log(SimpleLog.LOG_LEVEL_DEBUG, message, t); - } - } - - - /** - * Logs a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE. - * - * @param message to log - * @see org.apache.commons.logging.Log#trace(Object) - */ - public final void trace(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) { - log(SimpleLog.LOG_LEVEL_TRACE, message, null); - } - } - - - /** - * Logs a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#trace(Object, Throwable) - */ - public final void trace(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) { - log(SimpleLog.LOG_LEVEL_TRACE, message, t); - } - } - - - /** - * Logs a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO. - * - * @param message to log - * @see org.apache.commons.logging.Log#info(Object) - */ - public final void info(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) { - log(SimpleLog.LOG_LEVEL_INFO,message,null); - } - } - - - /** - * Logs a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#info(Object, Throwable) - */ - public final void info(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) { - log(SimpleLog.LOG_LEVEL_INFO, message, t); - } - } - - - /** - * Logs a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN. - * - * @param message to log - * @see org.apache.commons.logging.Log#warn(Object) - */ - public final void warn(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) { - log(SimpleLog.LOG_LEVEL_WARN, message, null); - } - } - - - /** - * Logs a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#warn(Object, Throwable) - */ - public final void warn(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) { - log(SimpleLog.LOG_LEVEL_WARN, message, t); - } - } - - - /** - * Logs a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR. - * - * @param message to log - * @see org.apache.commons.logging.Log#error(Object) - */ - public final void error(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) { - log(SimpleLog.LOG_LEVEL_ERROR, message, null); - } - } - - - /** - * Logs a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#error(Object, Throwable) - */ - public final void error(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) { - log(SimpleLog.LOG_LEVEL_ERROR, message, t); - } - } - - - /** - * Log a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL. - * - * @param message to log - * @see org.apache.commons.logging.Log#fatal(Object) - */ - public final void fatal(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) { - log(SimpleLog.LOG_LEVEL_FATAL, message, null); - } - } - - - /** - * Logs a message with - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#fatal(Object, Throwable) - */ - public final void fatal(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) { - log(SimpleLog.LOG_LEVEL_FATAL, message, t); - } - } - - - /** - *

Are debug messages currently enabled?

- * - *

This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

- */ - public final boolean isDebugEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG); - } - - - /** - *

Are error messages currently enabled?

- * - *

This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

- */ - public final boolean isErrorEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR); - } - - - /** - *

Are fatal messages currently enabled?

- * - *

This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

- */ - public final boolean isFatalEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL); - } - - - /** - *

Are info messages currently enabled?

- * - *

This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

- */ - public final boolean isInfoEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_INFO); - } - - - /** - *

Are trace messages currently enabled?

- * - *

This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

- */ - public final boolean isTraceEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE); - } - - - /** - *

Are warn messages currently enabled?

- * - *

This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

- */ - public final boolean isWarnEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_WARN); - } - - - /** - * Return the thread context class loader if available. - * Otherwise return null. - * - * The thread context class loader is available for JDK 1.2 - * or later, if certain security conditions are met. - * - * @exception LogConfigurationException if a suitable class loader - * cannot be identified. - */ - private static ClassLoader getContextClassLoader() - { - ClassLoader classLoader = null; - - if (classLoader == null) { - try { - // Are we running on a JDK 1.2 or later system? - Method method = Thread.class.getMethod("getContextClassLoader", - (Class[]) null); - - // Get the thread context class loader (if there is one) - try { - classLoader = (ClassLoader)method.invoke(Thread.currentThread(), - (Class[]) null); - } catch (IllegalAccessException e) { - ; // ignore - } catch (InvocationTargetException e) { - /** - * InvocationTargetException is thrown by 'invoke' when - * the method being invoked (getContextClassLoader) throws - * an exception. - * - * getContextClassLoader() throws SecurityException when - * the context class loader isn't an ancestor of the - * calling class's class loader, or if security - * permissions are restricted. - * - * In the first case (not related), we want to ignore and - * keep going. We cannot help but also ignore the second - * with the logic below, but other calls elsewhere (to - * obtain a class loader) will trigger this exception where - * we can make a distinction. - */ - if (e.getTargetException() instanceof SecurityException) { - ; // ignore - } else { - // Capture 'e.getTargetException()' exception for details - // alternate: log 'e.getTargetException()', and pass back 'e'. - throw new LogConfigurationException - ("Unexpected InvocationTargetException", e.getTargetException()); - } - } - } catch (NoSuchMethodException e) { - // Assume we are running on JDK 1.1 - ; // ignore - } - } - - if (classLoader == null) { - classLoader = SimpleLog.class.getClassLoader(); - } - - // Return the selected class loader - return classLoader; - } - - private static InputStream getResourceAsStream(final String name) - { - return (InputStream)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - ClassLoader threadCL = getContextClassLoader(); - - if (threadCL != null) { - return threadCL.getResourceAsStream(name); - } else { - return ClassLoader.getSystemResourceAsStream(name); - } - } - }); - } -} - diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/WeakHashtable.java libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/WeakHashtable.java --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/WeakHashtable.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/WeakHashtable.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,478 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.*; - -/** - *

Implementation of Hashtable that uses WeakReference's - * to hold its keys thus allowing them to be reclaimed by the garbage collector. - * The associated values are retained using strong references.

- * - *

This class follows the symantics of Hashtable as closely as - * possible. It therefore does not accept null values or keys.

- * - *

Note: - * This is not intended to be a general purpose hash table replacement. - * This implementation is also tuned towards a particular purpose: for use as a replacement - * for Hashtable in LogFactory. This application requires - * good liveliness for get and put. Various tradeoffs - * have been made with this in mind. - *

- *

- * Usage: typical use case is as a drop-in replacement - * for the Hashtable used in LogFactory for J2EE enviroments - * running 1.3+ JVMs. Use of this class in most cases (see below) will - * allow classloaders to be collected by the garbage collector without the need - * to call {@link org.apache.commons.logging.LogFactory#release(ClassLoader) LogFactory.release(ClassLoader)}. - *

- * - *

org.apache.commons.logging.LogFactory checks whether this class - * can be supported by the current JVM, and if so then uses it to store - * references to the LogFactory implementationd it loads - * (rather than using a standard Hashtable instance). - * Having this class used instead of Hashtable solves - * certain issues related to dynamic reloading of applications in J2EE-style - * environments. However this class requires java 1.3 or later (due to its use - * of java.lang.ref.WeakReference and associates). - * And by the way, this extends Hashtable rather than HashMap - * for backwards compatibility reasons. See the documentation - * for method LogFactory.createFactoryStore for more details.

- * - *

The reason all this is necessary is due to a issue which - * arises during hot deploy in a J2EE-like containers. - * Each component running in the container owns one or more classloaders; when - * the component loads a LogFactory instance via the component classloader - * a reference to it gets stored in the static LogFactory.factories member, - * keyed by the component's classloader so different components don't - * stomp on each other. When the component is later unloaded, the container - * sets the component's classloader to null with the intent that all the - * component's classes get garbage-collected. However there's still a - * reference to the component's classloader from a key in the "global" - * LogFactory's factories member! If LogFactory.release() - * is called whenever component is unloaded, the classloaders will be correctly - * garbage collected; this should be done by any container that - * bundles commons-logging by default. However, holding the classloader - * references weakly ensures that the classloader will be garbage collected - * without the container performing this step.

- * - *

- * Limitations: - * There is still one (unusual) scenario in which a component will not - * be correctly unloaded without an explicit release. Though weak references - * are used for its keys, it is necessary to use strong references for its values. - *

- * - *

If the abstract class LogFactory is - * loaded by the container classloader but a subclass of - * LogFactory [LogFactory1] is loaded by the component's - * classloader and an instance stored in the static map associated with the - * base LogFactory class, then there is a strong reference from the LogFactory - * class to the LogFactory1 instance (as normal) and a strong reference from - * the LogFactory1 instance to the component classloader via - * getClass().getClassLoader(). This chain of references will prevent - * collection of the child classloader.

- * - *

- * Such a situation occurs when the commons-logging.jar is - * loaded by a parent classloader (e.g. a server level classloader in a - * servlet container) and a custom LogFactory implementation is - * loaded by a child classloader (e.g. a web app classloader).

- * - *

To avoid this scenario, ensure - * that any custom LogFactory subclass is loaded by the same classloader as - * the base LogFactory. Creating custom LogFactory subclasses is, - * however, rare. The standard LogFactoryImpl class should be sufficient - * for most or all users.

- * - * - * @author Brian Stansberry - * - * @since 1.1 - */ -public final class WeakHashtable extends Hashtable { - - /** - * The maximum number of times put() or remove() can be called before - * the map will be purged of all cleared entries. - */ - private static final int MAX_CHANGES_BEFORE_PURGE = 100; - - /** - * The maximum number of times put() or remove() can be called before - * the map will be purged of one cleared entry. - */ - private static final int PARTIAL_PURGE_COUNT = 10; - - /* ReferenceQueue we check for gc'd keys */ - private ReferenceQueue queue = new ReferenceQueue(); - /* Counter used to control how often we purge gc'd entries */ - private int changeCount = 0; - - /** - * Constructs a WeakHashtable with the Hashtable default - * capacity and load factor. - */ - public WeakHashtable() {} - - - /** - *@see Hashtable - */ - public boolean containsKey(Object key) { - // purge should not be required - Referenced referenced = new Referenced(key); - return super.containsKey(referenced); - } - - /** - *@see Hashtable - */ - public Enumeration elements() { - purge(); - return super.elements(); - } - - /** - *@see Hashtable - */ - public Set entrySet() { - purge(); - Set referencedEntries = super.entrySet(); - Set unreferencedEntries = new HashSet(); - for (Iterator it=referencedEntries.iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - Referenced referencedKey = (Referenced) entry.getKey(); - Object key = referencedKey.getValue(); - Object value = entry.getValue(); - if (key != null) { - Entry dereferencedEntry = new Entry(key, value); - unreferencedEntries.add(dereferencedEntry); - } - } - return unreferencedEntries; - } - - /** - *@see Hashtable - */ - public Object get(Object key) { - // for performance reasons, no purge - Referenced referenceKey = new Referenced(key); - return super.get(referenceKey); - } - - /** - *@see Hashtable - */ - public Enumeration keys() { - purge(); - final Enumeration enumer = super.keys(); - return new Enumeration() { - public boolean hasMoreElements() { - return enumer.hasMoreElements(); - } - public Object nextElement() { - Referenced nextReference = (Referenced) enumer.nextElement(); - return nextReference.getValue(); - } - }; - } - - - /** - *@see Hashtable - */ - public Set keySet() { - purge(); - Set referencedKeys = super.keySet(); - Set unreferencedKeys = new HashSet(); - for (Iterator it=referencedKeys.iterator(); it.hasNext();) { - Referenced referenceKey = (Referenced) it.next(); - Object keyValue = referenceKey.getValue(); - if (keyValue != null) { - unreferencedKeys.add(keyValue); - } - } - return unreferencedKeys; - } - - /** - *@see Hashtable - */ - public Object put(Object key, Object value) { - // check for nulls, ensuring symantics match superclass - if (key == null) { - throw new NullPointerException("Null keys are not allowed"); - } - if (value == null) { - throw new NullPointerException("Null values are not allowed"); - } - - // for performance reasons, only purge every - // MAX_CHANGES_BEFORE_PURGE times - if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) { - purge(); - changeCount = 0; - } - // do a partial purge more often - else if ((changeCount % PARTIAL_PURGE_COUNT) == 0) { - purgeOne(); - } - - Referenced keyRef = new Referenced(key, queue); - return super.put(keyRef, value); - } - - /** - *@see Hashtable - */ - public void putAll(Map t) { - if (t != null) { - Set entrySet = t.entrySet(); - for (Iterator it=entrySet.iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - put(entry.getKey(), entry.getValue()); - } - } - } - - /** - *@see Hashtable - */ - public Collection values() { - purge(); - return super.values(); - } - - /** - *@see Hashtable - */ - public Object remove(Object key) { - // for performance reasons, only purge every - // MAX_CHANGES_BEFORE_PURGE times - if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) { - purge(); - changeCount = 0; - } - // do a partial purge more often - else if ((changeCount % PARTIAL_PURGE_COUNT) == 0) { - purgeOne(); - } - return super.remove(new Referenced(key)); - } - - /** - *@see Hashtable - */ - public boolean isEmpty() { - purge(); - return super.isEmpty(); - } - - /** - *@see Hashtable - */ - public int size() { - purge(); - return super.size(); - } - - /** - *@see Hashtable - */ - public String toString() { - purge(); - return super.toString(); - } - - /** - * @see Hashtable - */ - protected void rehash() { - // purge here to save the effort of rehashing dead entries - purge(); - super.rehash(); - } - - /** - * Purges all entries whose wrapped keys - * have been garbage collected. - */ - private void purge() { - synchronized (queue) { - WeakKey key; - while ((key = (WeakKey) queue.poll()) != null) { - super.remove(key.getReferenced()); - } - } - } - - /** - * Purges one entry whose wrapped key - * has been garbage collected. - */ - private void purgeOne() { - - synchronized (queue) { - WeakKey key = (WeakKey) queue.poll(); - if (key != null) { - super.remove(key.getReferenced()); - } - } - } - - /** Entry implementation */ - private final static class Entry implements Map.Entry { - - private final Object key; - private final Object value; - - private Entry(Object key, Object value) { - this.key = key; - this.value = value; - } - - public boolean equals(Object o) { - boolean result = false; - if (o != null && o instanceof Map.Entry) { - Map.Entry entry = (Map.Entry) o; - result = (getKey()==null ? - entry.getKey() == null : - getKey().equals(entry.getKey())) - && - (getValue()==null ? - entry.getValue() == null : - getValue().equals(entry.getValue())); - } - return result; - } - - public int hashCode() { - - return (getKey()==null ? 0 : getKey().hashCode()) ^ - (getValue()==null ? 0 : getValue().hashCode()); - } - - public Object setValue(Object value) { - throw new UnsupportedOperationException("Entry.setValue is not supported."); - } - - public Object getValue() { - return value; - } - - public Object getKey() { - return key; - } - } - - - /** Wrapper giving correct symantics for equals and hashcode */ - private final static class Referenced { - - private final WeakReference reference; - private final int hashCode; - - /** - * - * @throws NullPointerException if referant is null - */ - private Referenced(Object referant) { - reference = new WeakReference(referant); - // Calc a permanent hashCode so calls to Hashtable.remove() - // work if the WeakReference has been cleared - hashCode = referant.hashCode(); - } - - /** - * - * @throws NullPointerException if key is null - */ - private Referenced(Object key, ReferenceQueue queue) { - reference = new WeakKey(key, queue, this); - // Calc a permanent hashCode so calls to Hashtable.remove() - // work if the WeakReference has been cleared - hashCode = key.hashCode(); - - } - - public int hashCode() { - return hashCode; - } - - private Object getValue() { - return reference.get(); - } - - public boolean equals(Object o) { - boolean result = false; - if (o instanceof Referenced) { - Referenced otherKey = (Referenced) o; - Object thisKeyValue = getValue(); - Object otherKeyValue = otherKey.getValue(); - if (thisKeyValue == null) { - result = (otherKeyValue == null); - - // Since our hashcode was calculated from the original - // non-null referant, the above check breaks the - // hashcode/equals contract, as two cleared Referenced - // objects could test equal but have different hashcodes. - // We can reduce (not eliminate) the chance of this - // happening by comparing hashcodes. - if (result == true) { - result = (this.hashCode() == otherKey.hashCode()); - } - // In any case, as our c'tor does not allow null referants - // and Hashtable does not do equality checks between - // existing keys, normal hashtable operations should never - // result in an equals comparison between null referants - } - else - { - result = thisKeyValue.equals(otherKeyValue); - } - } - return result; - } - } - - /** - * WeakReference subclass that holds a hard reference to an - * associated value and also makes accessible - * the Referenced object holding it. - */ - private final static class WeakKey extends WeakReference { - - private final Referenced referenced; - - private WeakKey(Object key, - ReferenceQueue queue, - Referenced referenced) { - super(key, queue); - this.referenced = referenced; - } - - private Referenced getReferenced() { - return referenced; - } - } -} diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/package.html libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/package.html --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/impl/package.html 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/impl/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ - - - -

Concrete implementations of commons-logging wrapper APIs.

- diff -Nru libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/package.html libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/package.html --- libcommons-logging-java-1.1.1/src/java/org/apache/commons/logging/package.html 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/org/apache/commons/logging/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,255 +0,0 @@ - - - -

Simple wrapper API around multiple logging APIs.

- - -

Overview

- -

This package provides an API for logging in server-based applications that -can be used around a variety of different logging implementations, including -prebuilt support for the following:

-
    -
  • Log4J (version 1.2 or later) - from Apache's Logging project. Each named Log - instance is connected to a corresponding Log4J Logger.
  • -
  • - JDK Logging API, included in JDK 1.4 or later systems. Each named - Log instance is connected to a corresponding - java.util.logging.Logger instance.
  • -
  • LogKit from Apache's - Avalon project. Each named Log instance is - connected to a corresponding LogKit Logger.
  • -
  • NoOpLog implementation that simply swallows - all log output, for all named Log instances.
  • -
  • SimpleLog implementation that writes all - log output, for all named Log instances, to - System.err.
  • -
- - -

Quick Start Guide

- -

For those impatient to just get on with it, the following example -illustrates the typical declaration and use of a logger that is named (by -convention) after the calling class: - -

-    import org.apache.commons.logging.Log;
-    import org.apache.commons.logging.LogFactory;
-
-    public class Foo {
-
-        private Log log = LogFactory.getLog(Foo.class);
-
-        public void foo() {
-            ...
-            try {
-                if (log.isDebugEnabled()) {
-                    log.debug("About to do something to object " + name);
-                }
-                name.bar();
-            } catch (IllegalStateException e) {
-                log.error("Something bad happened to " + name, e);
-            }
-            ...
-        }
-
- -

Unless you configure things differently, all log output will be written -to System.err. Therefore, you really will want to review the remainder of -this page in order to understand how to configure logging for your -application.

- - -

Configuring the Commons Logging Package

- - -

Choosing a LogFactory Implementation

- -

From an application perspective, the first requirement is to retrieve an -object reference to the LogFactory instance that will be used -to create Log instances for this -application. This is normally accomplished by calling the static -getFactory() method. This method implements the following -discovery algorithm to select the name of the LogFactory -implementation class this application wants to use:

-
    -
  • Check for a system property named - org.apache.commons.logging.LogFactory.
  • -
  • Use the JDK 1.3 JAR Services Discovery mechanism (see - - http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html for - more information) to look for a resource named - META-INF/services/org.apache.commons.logging.LogFactory - whose first line is assumed to contain the desired class name.
  • -
  • Look for a properties file named commons-logging.properties - visible in the application class path, with a property named - org.apache.commons.logging.LogFactory defining the - desired implementation class name.
  • -
  • Fall back to a default implementation, which is described - further below.
  • -
- -

If a commons-logging.properties file is found, all of the -properties defined there are also used to set configuration attributes on -the instantiated LogFactory instance.

- -

Once an implementation class name is selected, the corresponding class is -loaded from the current Thread context class loader (if there is one), or -from the class loader that loaded the LogFactory class itself -otherwise. This allows a copy of commons-logging.jar to be -shared in a multiple class loader environment (such as a servlet container), -but still allow each web application to provide its own LogFactory -implementation, if it so desires. An instance of this class will then be -created, and cached per class loader. - - -

The Default LogFactory Implementation

- -

The Logging Package APIs include a default LogFactory -implementation class ( -org.apache.commons.logging.impl.LogFactoryImpl) that is selected if no -other implementation class name can be discovered. Its primary purpose is -to create (as necessary) and return Log instances -in response to calls to the getInstance() method. The default -implementation uses the following rules:

-
    -
  • At most one Log instance of the same name will be created. - Subsequent getInstance() calls to the same - LogFactory instance, with the same name or Class - parameter, will return the same Log instance.
  • -
  • When a new Log instance must be created, the default - LogFactory implementation uses the following discovery - process: -
      -
    • Look for a configuration attribute of this factory named - org.apache.commons.logging.Log (for backwards - compatibility to pre-1.0 versions of this API, an attribute - org.apache.commons.logging.log is also consulted).
    • -
    • Look for a system property named - org.apache.commons.logging.Log (for backwards - compatibility to pre-1.0 versions of this API, a system property - org.apache.commons.logging.log is also consulted).
    • -
    • If the Log4J logging system is available in the application - class path, use the corresponding wrapper class - (Log4JLogger).
    • -
    • If the application is executing on a JDK 1.4 system, use - the corresponding wrapper class - (Jdk14Logger).
    • -
    • Fall back to the default simple logging implementation - (SimpleLog).
    • -
  • -
  • Load the class of the specified name from the thread context class - loader (if any), or from the class loader that loaded the - LogFactory class otherwise.
  • -
  • Instantiate an instance of the selected Log - implementation class, passing the specified name as the single - argument to its constructor.
  • -
- -

See the SimpleLog JavaDocs for detailed -configuration information for this default implementation.

- - -

Configuring the Underlying Logging System

- -

The basic principle is that the user is totally responsible for the -configuration of the underlying logging system. -Commons-logging should not change the existing configuration.

- -

Each individual Log implementation may -support its own configuration properties. These will be documented in the -class descriptions for the corresponding implementation class.

- -

Finally, some Log implementations (such as the one for Log4J) -require an external configuration file for the entire logging environment. -This file should be prepared in a manner that is specific to the actual logging -technology being used.

- - -

Using the Logging Package APIs

- -

Use of the Logging Package APIs, from the perspective of an application -component, consists of the following steps:

-
    -
  1. Acquire a reference to an instance of - org.apache.commons.logging.Log, by calling the - factory method - - LogFactory.getInstance(String name). Your application can contain - references to multiple loggers that are used for different - purposes. A typical scenario for a server application is to have each - major component of the server use its own Log instance.
  2. -
  3. Cause messages to be logged (if the corresponding detail level is enabled) - by calling appropriate methods (trace(), debug(), - info(), warn(), error, and - fatal()).
  4. -
- -

For convenience, LogFactory also offers a static method -getLog() that combines the typical two-step pattern:

-
-  Log log = LogFactory.getFactory().getInstance(Foo.class);
-
-

into a single method call:

-
-  Log log = LogFactory.getLog(Foo.class);
-
- -

For example, you might use the following technique to initialize and -use a Log instance in an application component:

-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-public class MyComponent {
-
-  protected Log log =
-    LogFactory.getLog(MyComponent.class);
-
-  // Called once at startup time
-  public void start() {
-    ...
-    log.info("MyComponent started");
-    ...
-  }
-
-  // Called once at shutdown time
-  public void stop() {
-    ...
-    log.info("MyComponent stopped");
-    ...
-  }
-
-  // Called repeatedly to process a particular argument value
-  // which you want logged if debugging is enabled
-  public void process(String value) {
-    ...
-    // Do the string concatenation only if logging is enabled
-    if (log.isDebugEnabled())
-      log.debug("MyComponent processing " + value);
-    ...
-  }
-
-}
-
- - diff -Nru libcommons-logging-java-1.1.1/src/java/overview.html libcommons-logging-java-1.1.3/src/java/overview.html --- libcommons-logging-java-1.1.1/src/java/overview.html 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/java/overview.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ - - - - -Overview Documentation for COMMONS-LOGGING - - -

The Logging Wrapper Library component of the Apache Commons -subproject offers wrappers around an extensible set of concrete logging -implementations, so that application code based on it does not need to be -modified in order to select a different logging implementation.

- -

See the - -Package Description for the org.apache.commons.logging -package for more information.

- - diff -Nru libcommons-logging-java-1.1.1/src/main/assembly/bin.xml libcommons-logging-java-1.1.3/src/main/assembly/bin.xml --- libcommons-logging-java-1.1.1/src/main/assembly/bin.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/assembly/bin.xml 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,47 @@ + + + + bin + + tar.gz + zip + + false + + + + LICENSE* + NOTICE* + RELEASE-NOTES* + + + + target + + + *.jar + + + + target/site/apidocs + apidocs + + + \ No newline at end of file diff -Nru libcommons-logging-java-1.1.1/src/main/assembly/src.xml libcommons-logging-java-1.1.3/src/main/assembly/src.xml --- libcommons-logging-java-1.1.1/src/main/assembly/src.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/assembly/src.xml 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,50 @@ + + + + src + + tar.gz + zip + + ${project.artifactId}-${project.version}-src + + + + checkstyle.xml + LICENSE.txt + NOTICE.txt + pom.xml + PROPOSAL.html + RELEASE-NOTES.txt + STATUS.txt + build.xml + build-testing.xml + build.properties.sample + license-header.txt + + + + src + + **/download*.cgi + + + + \ No newline at end of file diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/Log.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/Log.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/Log.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/Log.java 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging; + +/** + * A simple logging interface abstracting logging APIs. In order to be + * instantiated successfully by {@link LogFactory}, classes that implement + * this interface must have a constructor that takes a single String + * parameter representing the "name" of this Log. + *

+ * The six logging levels used by Log are (in order): + *

    + *
  1. trace (the least serious)
  2. + *
  3. debug
  4. + *
  5. info
  6. + *
  7. warn
  8. + *
  9. error
  10. + *
  11. fatal (the most serious)
  12. + *
+ * The mapping of these log levels to the concepts used by the underlying + * logging system is implementation dependent. + * The implementation should ensure, though, that this ordering behaves + * as expected. + *

+ * Performance is often a logging concern. + * By examining the appropriate property, + * a component can avoid expensive operations (producing information + * to be logged). + *

+ * For example, + *

+ *    if (log.isDebugEnabled()) {
+ *        ... do something expensive ...
+ *        log.debug(theResult);
+ *    }
+ * 
+ *

+ * Configuration of the underlying logging system will generally be done + * external to the Logging APIs, through whatever mechanism is supported by + * that system. + * + * @version $Id: Log.java 1432663 2013-01-13 17:24:18Z tn $ + */ +public interface Log { + + // ----------------------------------------------------- Logging Properties + + /** + * Is debug logging currently enabled? + *

+ * Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than debug. + * + * @return true if debug is enabled in the underlying logger. + */ + public boolean isDebugEnabled(); + + /** + * Is error logging currently enabled? + *

+ * Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than error. + * + * @return true if error is enabled in the underlying logger. + */ + public boolean isErrorEnabled(); + + /** + * Is fatal logging currently enabled? + *

+ * Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than fatal. + * + * @return true if fatal is enabled in the underlying logger. + */ + public boolean isFatalEnabled(); + + /** + * Is info logging currently enabled? + *

+ * Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than info. + * + * @return true if info is enabled in the underlying logger. + */ + public boolean isInfoEnabled(); + + /** + * Is trace logging currently enabled? + *

+ * Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than trace. + * + * @return true if trace is enabled in the underlying logger. + */ + public boolean isTraceEnabled(); + + /** + * Is warn logging currently enabled? + *

+ * Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than warn. + * + * @return true if warn is enabled in the underlying logger. + */ + public boolean isWarnEnabled(); + + // -------------------------------------------------------- Logging Methods + + /** + * Log a message with trace log level. + * + * @param message log this message + */ + public void trace(Object message); + + /** + * Log an error with trace log level. + * + * @param message log this message + * @param t log this cause + */ + public void trace(Object message, Throwable t); + + /** + * Log a message with debug log level. + * + * @param message log this message + */ + public void debug(Object message); + + /** + * Log an error with debug log level. + * + * @param message log this message + * @param t log this cause + */ + public void debug(Object message, Throwable t); + + /** + * Log a message with info log level. + * + * @param message log this message + */ + public void info(Object message); + + /** + * Log an error with info log level. + * + * @param message log this message + * @param t log this cause + */ + public void info(Object message, Throwable t); + + /** + * Log a message with warn log level. + * + * @param message log this message + */ + public void warn(Object message); + + /** + * Log an error with warn log level. + * + * @param message log this message + * @param t log this cause + */ + public void warn(Object message, Throwable t); + + /** + * Log a message with error log level. + * + * @param message log this message + */ + public void error(Object message); + + /** + * Log an error with error log level. + * + * @param message log this message + * @param t log this cause + */ + public void error(Object message, Throwable t); + + /** + * Log a message with fatal log level. + * + * @param message log this message + */ + public void fatal(Object message); + + /** + * Log an error with fatal log level. + * + * @param message log this message + * @param t log this cause + */ + public void fatal(Object message, Throwable t); +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/LogConfigurationException.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/LogConfigurationException.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/LogConfigurationException.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/LogConfigurationException.java 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging; + +/** + * An exception that is thrown only if a suitable LogFactory + * or Log instance cannot be created by the corresponding + * factory methods. + * + * @version $Id: LogConfigurationException.java 1432663 2013-01-13 17:24:18Z tn $ + */ +public class LogConfigurationException extends RuntimeException { + + /** Serializable version identifier. */ + private static final long serialVersionUID = 8486587136871052495L; + + /** + * Construct a new exception with null as its detail message. + */ + public LogConfigurationException() { + super(); + } + + /** + * Construct a new exception with the specified detail message. + * + * @param message The detail message + */ + public LogConfigurationException(String message) { + super(message); + } + + /** + * Construct a new exception with the specified cause and a derived + * detail message. + * + * @param cause The underlying cause + */ + public LogConfigurationException(Throwable cause) { + this(cause == null ? null : cause.toString(), cause); + } + + /** + * Construct a new exception with the specified detail message and cause. + * + * @param message The detail message + * @param cause The underlying cause + */ + public LogConfigurationException(String message, Throwable cause) { + super(message + " (Caused by " + cause + ")"); + this.cause = cause; // Two-argument version requires JDK 1.4 or later + } + + /** + * The underlying cause of this exception. + */ + protected Throwable cause = null; + + /** + * Return the underlying cause of this exception (if any). + */ + public Throwable getCause() { + return this.cause; + } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/LogFactory.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/LogFactory.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/LogFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/LogFactory.java 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,1746 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging; + +import java.io.BufferedReader; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLConnection; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Properties; + +/** + * Factory for creating {@link Log} instances, with discovery and + * configuration features similar to that employed by standard Java APIs + * such as JAXP. + *

+ * IMPLEMENTATION NOTE - This implementation is heavily + * based on the SAXParserFactory and DocumentBuilderFactory implementations + * (corresponding to the JAXP pluggability APIs) found in Apache Xerces. + * + * @version $Id: LogFactory.java 1449064 2013-02-22 14:49:22Z tn $ + */ +public abstract class LogFactory { + // Implementation note re AccessController usage + // + // It is important to keep code invoked via an AccessController to small + // auditable blocks. Such code must carefully evaluate all user input + // (parameters, system properties, config file contents, etc). As an + // example, a Log implementation should not write to its logfile + // with an AccessController anywhere in the call stack, otherwise an + // insecure application could configure the log implementation to write + // to a protected file using the privileges granted to JCL rather than + // to the calling application. + // + // Under no circumstance should a non-private method return data that is + // retrieved via an AccessController. That would allow an insecure app + // to invoke that method and obtain data that it is not permitted to have. + // + // Invoking user-supplied code with an AccessController set is not a major + // issue (eg invoking the constructor of the class specified by + // HASHTABLE_IMPLEMENTATION_PROPERTY). That class will be in a different + // trust domain, and therefore must have permissions to do whatever it + // is trying to do regardless of the permissions granted to JCL. There is + // a slight issue in that untrusted code may point that environment var + // to another trusted library, in which case the code runs if both that + // lib and JCL have the necessary permissions even when the untrusted + // caller does not. That's a pretty hard route to exploit though. + + // ----------------------------------------------------- Manifest Constants + + /** + * The name (priority) of the key in the config file used to + * specify the priority of that particular config file. The associated value + * is a floating-point number; higher values take priority over lower values. + */ + public static final String PRIORITY_KEY = "priority"; + + /** + * The name (use_tccl) of the key in the config file used + * to specify whether logging classes should be loaded via the thread + * context class loader (TCCL), or not. By default, the TCCL is used. + */ + public static final String TCCL_KEY = "use_tccl"; + + /** + * The name (org.apache.commons.logging.LogFactory) of the property + * used to identify the LogFactory implementation + * class name. This can be used as a system property, or as an entry in a + * configuration properties file. + */ + public static final String FACTORY_PROPERTY = "org.apache.commons.logging.LogFactory"; + + /** + * The fully qualified class name of the fallback LogFactory + * implementation class to use, if no other can be found. + */ + public static final String FACTORY_DEFAULT = "org.apache.commons.logging.impl.LogFactoryImpl"; + + /** + * The name (commons-logging.properties) of the properties file to search for. + */ + public static final String FACTORY_PROPERTIES = "commons-logging.properties"; + + /** + * JDK1.3+ + * 'Service Provider' specification. + */ + protected static final String SERVICE_ID = + "META-INF/services/org.apache.commons.logging.LogFactory"; + + /** + * The name (org.apache.commons.logging.diagnostics.dest) + * of the property used to enable internal commons-logging + * diagnostic output, in order to get information on what logging + * implementations are being discovered, what classloaders they + * are loaded through, etc. + *

+ * If a system property of this name is set then the value is + * assumed to be the name of a file. The special strings + * STDOUT or STDERR (case-sensitive) indicate output to + * System.out and System.err respectively. + *

+ * Diagnostic logging should be used only to debug problematic + * configurations and should not be set in normal production use. + */ + public static final String DIAGNOSTICS_DEST_PROPERTY = + "org.apache.commons.logging.diagnostics.dest"; + + /** + * When null (the usual case), no diagnostic output will be + * generated by LogFactory or LogFactoryImpl. When non-null, + * interesting events will be written to the specified object. + */ + private static PrintStream diagnosticsStream = null; + + /** + * A string that gets prefixed to every message output by the + * logDiagnostic method, so that users can clearly see which + * LogFactory class is generating the output. + */ + private static final String diagnosticPrefix; + + /** + * Setting this system property + * (org.apache.commons.logging.LogFactory.HashtableImpl) + * value allows the Hashtable used to store + * classloaders to be substituted by an alternative implementation. + *

+ * Note: LogFactory will print: + *

+     * [ERROR] LogFactory: Load of custom hashtable failed
+     * 
+ * to system error and then continue using a standard Hashtable. + *

+ * Usage: Set this property when Java is invoked + * and LogFactory will attempt to load a new instance + * of the given implementation class. + * For example, running the following ant scriplet: + *

+     *  <java classname="${test.runner}" fork="yes" failonerror="${test.failonerror}">
+     *     ...
+     *     <sysproperty
+     *        key="org.apache.commons.logging.LogFactory.HashtableImpl"
+     *        value="org.apache.commons.logging.AltHashtable"/>
+     *  </java>
+     * 
+ * will mean that LogFactory will load an instance of + * org.apache.commons.logging.AltHashtable. + *

+ * A typical use case is to allow a custom + * Hashtable implementation using weak references to be substituted. + * This will allow classloaders to be garbage collected without + * the need to release them (on 1.3+ JVMs only, of course ;). + */ + public static final String HASHTABLE_IMPLEMENTATION_PROPERTY = + "org.apache.commons.logging.LogFactory.HashtableImpl"; + + /** Name used to load the weak hashtable implementation by names. */ + private static final String WEAK_HASHTABLE_CLASSNAME = + "org.apache.commons.logging.impl.WeakHashtable"; + + /** + * A reference to the classloader that loaded this class. This is the + * same as LogFactory.class.getClassLoader(). However computing this + * value isn't quite as simple as that, as we potentially need to use + * AccessControllers etc. It's more efficient to compute it once and + * cache it here. + */ + private static final ClassLoader thisClassLoader; + + // ----------------------------------------------------------- Constructors + + /** + * Protected constructor that is not available for public use. + */ + protected LogFactory() { + } + + // --------------------------------------------------------- Public Methods + + /** + * Return the configuration attribute with the specified name (if any), + * or null if there is no such attribute. + * + * @param name Name of the attribute to return + */ + public abstract Object getAttribute(String name); + + /** + * Return an array containing the names of all currently defined + * configuration attributes. If there are no such attributes, a zero + * length array is returned. + */ + public abstract String[] getAttributeNames(); + + /** + * Convenience method to derive a name from the specified class and + * call getInstance(String) with it. + * + * @param clazz Class for which a suitable Log name will be derived + * @throws LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public abstract Log getInstance(Class clazz) + throws LogConfigurationException; + + /** + * Construct (if necessary) and return a Log instance, + * using the factory's current set of configuration attributes. + *

+ * NOTE - Depending upon the implementation of + * the LogFactory you are using, the Log + * instance you are returned may or may not be local to the current + * application, and may or may not be returned again on a subsequent + * call with the same name argument. + * + * @param name Logical name of the Log instance to be + * returned (the meaning of this name is only known to the underlying + * logging implementation that is being wrapped) + * @throws LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public abstract Log getInstance(String name) + throws LogConfigurationException; + + /** + * Release any internal references to previously created {@link Log} + * instances returned by this factory. This is useful in environments + * like servlet containers, which implement application reloading by + * throwing away a ClassLoader. Dangling references to objects in that + * class loader would prevent garbage collection. + */ + public abstract void release(); + + /** + * Remove any configuration attribute associated with the specified name. + * If there is no such attribute, no action is taken. + * + * @param name Name of the attribute to remove + */ + public abstract void removeAttribute(String name); + + /** + * Set the configuration attribute with the specified name. Calling + * this with a null value is equivalent to calling + * removeAttribute(name). + * + * @param name Name of the attribute to set + * @param value Value of the attribute to set, or null + * to remove any setting for this attribute + */ + public abstract void setAttribute(String name, Object value); + + // ------------------------------------------------------- Static Variables + + /** + * The previously constructed LogFactory instances, keyed by + * the ClassLoader with which it was created. + */ + protected static Hashtable factories = null; + + /** + * Previously constructed LogFactory instance as in the + * factories map, but for the case where + * getClassLoader returns null. + * This can happen when: + *

    + *
  • using JDK1.1 and the calling code is loaded via the system + * classloader (very common)
  • + *
  • using JDK1.2+ and the calling code is loaded via the boot + * classloader (only likely for embedded systems work).
  • + *
+ * Note that factories is a Hashtable (not a HashMap), + * and hashtables don't allow null as a key. + * @deprecated since 1.1.2 + */ + protected static volatile LogFactory nullClassLoaderFactory = null; + + /** + * Create the hashtable which will be used to store a map of + * (context-classloader -> logfactory-object). Version 1.2+ of Java + * supports "weak references", allowing a custom Hashtable class + * to be used which uses only weak references to its keys. Using weak + * references can fix memory leaks on webapp unload in some cases (though + * not all). Version 1.1 of Java does not support weak references, so we + * must dynamically determine which we are using. And just for fun, this + * code also supports the ability for a system property to specify an + * arbitrary Hashtable implementation name. + *

+ * Note that the correct way to ensure no memory leaks occur is to ensure + * that LogFactory.release(contextClassLoader) is called whenever a + * webapp is undeployed. + */ + private static final Hashtable createFactoryStore() { + Hashtable result = null; + String storeImplementationClass; + try { + storeImplementationClass = getSystemProperty(HASHTABLE_IMPLEMENTATION_PROPERTY, null); + } catch (SecurityException ex) { + // Permissions don't allow this to be accessed. Default to the "modern" + // weak hashtable implementation if it is available. + storeImplementationClass = null; + } + + if (storeImplementationClass == null) { + storeImplementationClass = WEAK_HASHTABLE_CLASSNAME; + } + try { + Class implementationClass = Class.forName(storeImplementationClass); + result = (Hashtable) implementationClass.newInstance(); + } catch (Throwable t) { + handleThrowable(t); // may re-throw t + + // ignore + if (!WEAK_HASHTABLE_CLASSNAME.equals(storeImplementationClass)) { + // if the user's trying to set up a custom implementation, give a clue + if (isDiagnosticsEnabled()) { + // use internal logging to issue the warning + logDiagnostic("[ERROR] LogFactory: Load of custom hashtable failed"); + } else { + // we *really* want this output, even if diagnostics weren't + // explicitly enabled by the user. + System.err.println("[ERROR] LogFactory: Load of custom hashtable failed"); + } + } + } + if (result == null) { + result = new Hashtable(); + } + return result; + } + + // --------------------------------------------------------- Static Methods + + /** Utility method to safely trim a string. */ + private static String trim(String src) { + if (src == null) { + return null; + } + return src.trim(); + } + + /** + * Checks whether the supplied Throwable is one that needs to be + * re-thrown and ignores all others. + * + * The following errors are re-thrown: + *

    + *
  • ThreadDeath
  • + *
  • VirtualMachineError
  • + *
+ * + * @param t the Throwable to check + */ + protected static void handleThrowable(Throwable t) { + if (t instanceof ThreadDeath) { + throw (ThreadDeath) t; + } + if (t instanceof VirtualMachineError) { + throw (VirtualMachineError) t; + } + // All other instances of Throwable will be silently ignored + } + + /** + * Construct (if necessary) and return a LogFactory + * instance, using the following ordered lookup procedure to determine + * the name of the implementation class to be loaded. + *

+ *

    + *
  • The org.apache.commons.logging.LogFactory system + * property.
  • + *
  • The JDK 1.3 Service Discovery mechanism
  • + *
  • Use the properties file commons-logging.properties + * file, if found in the class path of this class. The configuration + * file is in standard java.util.Properties format and + * contains the fully qualified name of the implementation class + * with the key being the system property defined above.
  • + *
  • Fall back to a default implementation class + * (org.apache.commons.logging.impl.LogFactoryImpl).
  • + *
+ *

+ * NOTE - If the properties file method of identifying the + * LogFactory implementation class is utilized, all of the + * properties defined in this file will be set as configuration attributes + * on the corresponding LogFactory instance. + *

+ * NOTE - In a multi-threaded environment it is possible + * that two different instances will be returned for the same + * classloader environment. + * + * @throws LogConfigurationException if the implementation class is not + * available or cannot be instantiated. + */ + public static LogFactory getFactory() throws LogConfigurationException { + // Identify the class loader we will be using + ClassLoader contextClassLoader = getContextClassLoaderInternal(); + + if (contextClassLoader == null) { + // This is an odd enough situation to report about. This + // output will be a nuisance on JDK1.1, as the system + // classloader is null in that environment. + if (isDiagnosticsEnabled()) { + logDiagnostic("Context classloader is null."); + } + } + + // Return any previously registered factory for this class loader + LogFactory factory = getCachedFactory(contextClassLoader); + if (factory != null) { + return factory; + } + + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] LogFactory implementation requested for the first time for context classloader " + + objectId(contextClassLoader)); + logHierarchy("[LOOKUP] ", contextClassLoader); + } + + // Load properties file. + // + // If the properties file exists, then its contents are used as + // "attributes" on the LogFactory implementation class. One particular + // property may also control which LogFactory concrete subclass is + // used, but only if other discovery mechanisms fail.. + // + // As the properties file (if it exists) will be used one way or + // another in the end we may as well look for it first. + + Properties props = getConfigurationFile(contextClassLoader, FACTORY_PROPERTIES); + + // Determine whether we will be using the thread context class loader to + // load logging classes or not by checking the loaded properties file (if any). + ClassLoader baseClassLoader = contextClassLoader; + if (props != null) { + String useTCCLStr = props.getProperty(TCCL_KEY); + if (useTCCLStr != null) { + // The Boolean.valueOf(useTCCLStr).booleanValue() formulation + // is required for Java 1.2 compatibility. + if (Boolean.valueOf(useTCCLStr).booleanValue() == false) { + // Don't use current context classloader when locating any + // LogFactory or Log classes, just use the class that loaded + // this abstract class. When this class is deployed in a shared + // classpath of a container, it means webapps cannot deploy their + // own logging implementations. It also means that it is up to the + // implementation whether to load library-specific config files + // from the TCCL or not. + baseClassLoader = thisClassLoader; + } + } + } + + // Determine which concrete LogFactory subclass to use. + // First, try a global system property + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] Looking for system property [" + FACTORY_PROPERTY + + "] to define the LogFactory subclass to use..."); + } + + try { + String factoryClass = getSystemProperty(FACTORY_PROPERTY, null); + if (factoryClass != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] Creating an instance of LogFactory class '" + factoryClass + + "' as specified by system property " + FACTORY_PROPERTY); + } + factory = newFactory(factoryClass, baseClassLoader, contextClassLoader); + } else { + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] No system property [" + FACTORY_PROPERTY + "] defined."); + } + } + } catch (SecurityException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] A security exception occurred while trying to create an" + + " instance of the custom factory class" + ": [" + trim(e.getMessage()) + + "]. Trying alternative implementations..."); + } + // ignore + } catch (RuntimeException e) { + // This is not consistent with the behaviour when a bad LogFactory class is + // specified in a services file. + // + // One possible exception that can occur here is a ClassCastException when + // the specified class wasn't castable to this LogFactory type. + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] An exception occurred while trying to create an" + + " instance of the custom factory class" + ": [" + + trim(e.getMessage()) + + "] as specified by a system property."); + } + throw e; + } + + // Second, try to find a service by using the JDK1.3 class + // discovery mechanism, which involves putting a file with the name + // of an interface class in the META-INF/services directory, where the + // contents of the file is a single line specifying a concrete class + // that implements the desired interface. + + if (factory == null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] Looking for a resource file of name [" + SERVICE_ID + + "] to define the LogFactory subclass to use..."); + } + try { + final InputStream is = getResourceAsStream(contextClassLoader, SERVICE_ID); + + if( is != null ) { + // This code is needed by EBCDIC and other strange systems. + // It's a fix for bugs reported in xerces + BufferedReader rd; + try { + rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); + } catch (java.io.UnsupportedEncodingException e) { + rd = new BufferedReader(new InputStreamReader(is)); + } + + String factoryClassName = rd.readLine(); + rd.close(); + + if (factoryClassName != null && ! "".equals(factoryClassName)) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] Creating an instance of LogFactory class " + + factoryClassName + + " as specified by file '" + SERVICE_ID + + "' which was present in the path of the context classloader."); + } + factory = newFactory(factoryClassName, baseClassLoader, contextClassLoader ); + } + } else { + // is == null + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] No resource file with name '" + SERVICE_ID + "' found."); + } + } + } catch (Exception ex) { + // note: if the specified LogFactory class wasn't compatible with LogFactory + // for some reason, a ClassCastException will be caught here, and attempts will + // continue to find a compatible class. + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] A security exception occurred while trying to create an" + + " instance of the custom factory class" + + ": [" + trim(ex.getMessage()) + + "]. Trying alternative implementations..."); + } + // ignore + } + } + + // Third try looking into the properties file read earlier (if found) + + if (factory == null) { + if (props != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Looking in properties file for entry with key '" + FACTORY_PROPERTY + + "' to define the LogFactory subclass to use..."); + } + String factoryClass = props.getProperty(FACTORY_PROPERTY); + if (factoryClass != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Properties file specifies LogFactory subclass '" + factoryClass + "'"); + } + factory = newFactory(factoryClass, baseClassLoader, contextClassLoader); + + // TODO: think about whether we need to handle exceptions from newFactory + } else { + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] Properties file has no entry specifying LogFactory subclass."); + } + } + } else { + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] No properties file available to determine" + " LogFactory subclass from.."); + } + } + } + + // Fourth, try the fallback implementation class + + if (factory == null) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Loading the default LogFactory implementation '" + FACTORY_DEFAULT + + "' via the same classloader that loaded this LogFactory" + + " class (ie not looking in the context classloader)."); + } + + // Note: unlike the above code which can try to load custom LogFactory + // implementations via the TCCL, we don't try to load the default LogFactory + // implementation via the context classloader because: + // * that can cause problems (see comments in newFactory method) + // * no-one should be customising the code of the default class + // Yes, we do give up the ability for the child to ship a newer + // version of the LogFactoryImpl class and have it used dynamically + // by an old LogFactory class in the parent, but that isn't + // necessarily a good idea anyway. + factory = newFactory(FACTORY_DEFAULT, thisClassLoader, contextClassLoader); + } + + if (factory != null) { + /** + * Always cache using context class loader. + */ + cacheFactory(contextClassLoader, factory); + + if (props != null) { + Enumeration names = props.propertyNames(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + String value = props.getProperty(name); + factory.setAttribute(name, value); + } + } + } + + return factory; + } + + /** + * Convenience method to return a named logger, without the application + * having to care about factories. + * + * @param clazz Class from which a log name will be derived + * @throws LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public static Log getLog(Class clazz) throws LogConfigurationException { + return getFactory().getInstance(clazz); + } + + /** + * Convenience method to return a named logger, without the application + * having to care about factories. + * + * @param name Logical name of the Log instance to be + * returned (the meaning of this name is only known to the underlying + * logging implementation that is being wrapped) + * @throws LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public static Log getLog(String name) throws LogConfigurationException { + return getFactory().getInstance(name); + } + + /** + * Release any internal references to previously created {@link LogFactory} + * instances that have been associated with the specified class loader + * (if any), after calling the instance method release() on + * each of them. + * + * @param classLoader ClassLoader for which to release the LogFactory + */ + public static void release(ClassLoader classLoader) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Releasing factory for classloader " + objectId(classLoader)); + } + // factories is not final and could be replaced in this block. + final Hashtable factories = LogFactory.factories; + synchronized (factories) { + if (classLoader == null) { + if (nullClassLoaderFactory != null) { + nullClassLoaderFactory.release(); + nullClassLoaderFactory = null; + } + } else { + final LogFactory factory = (LogFactory) factories.get(classLoader); + if (factory != null) { + factory.release(); + factories.remove(classLoader); + } + } + } + } + + /** + * Release any internal references to previously created {@link LogFactory} + * instances, after calling the instance method release() on + * each of them. This is useful in environments like servlet containers, + * which implement application reloading by throwing away a ClassLoader. + * Dangling references to objects in that class loader would prevent + * garbage collection. + */ + public static void releaseAll() { + if (isDiagnosticsEnabled()) { + logDiagnostic("Releasing factory for all classloaders."); + } + // factories is not final and could be replaced in this block. + final Hashtable factories = LogFactory.factories; + synchronized (factories) { + final Enumeration elements = factories.elements(); + while (elements.hasMoreElements()) { + LogFactory element = (LogFactory) elements.nextElement(); + element.release(); + } + factories.clear(); + + if (nullClassLoaderFactory != null) { + nullClassLoaderFactory.release(); + nullClassLoaderFactory = null; + } + } + } + + // ------------------------------------------------------ Protected Methods + + /** + * Safely get access to the classloader for the specified class. + *

+ * Theoretically, calling getClassLoader can throw a security exception, + * and so should be done under an AccessController in order to provide + * maximum flexibility. However in practice people don't appear to use + * security policies that forbid getClassLoader calls. So for the moment + * all code is written to call this method rather than Class.getClassLoader, + * so that we could put AccessController stuff in this method without any + * disruption later if we need to. + *

+ * Even when using an AccessController, however, this method can still + * throw SecurityException. Commons-logging basically relies on the + * ability to access classloaders, ie a policy that forbids all + * classloader access will also prevent commons-logging from working: + * currently this method will throw an exception preventing the entire app + * from starting up. Maybe it would be good to detect this situation and + * just disable all commons-logging? Not high priority though - as stated + * above, security policies that prevent classloader access aren't common. + *

+ * Note that returning an object fetched via an AccessController would + * technically be a security flaw anyway; untrusted code that has access + * to a trusted JCL library could use it to fetch the classloader for + * a class even when forbidden to do so directly. + * + * @since 1.1 + */ + protected static ClassLoader getClassLoader(Class clazz) { + try { + return clazz.getClassLoader(); + } catch (SecurityException ex) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Unable to get classloader for class '" + clazz + + "' due to security restrictions - " + ex.getMessage()); + } + throw ex; + } + } + + /** + * Returns the current context classloader. + *

+ * In versions prior to 1.1, this method did not use an AccessController. + * In version 1.1, an AccessController wrapper was incorrectly added to + * this method, causing a minor security flaw. + *

+ * In version 1.1.1 this change was reverted; this method no longer uses + * an AccessController. User code wishing to obtain the context classloader + * must invoke this method via AccessController.doPrivileged if it needs + * support for that. + * + * @return the context classloader associated with the current thread, + * or null if security doesn't allow it. + * @throws LogConfigurationException if there was some weird error while + * attempting to get the context classloader. + * @throws SecurityException if the current java security policy doesn't + * allow this class to access the context classloader. + */ + protected static ClassLoader getContextClassLoader() throws LogConfigurationException { + return directGetContextClassLoader(); + } + + /** + * Calls LogFactory.directGetContextClassLoader under the control of an + * AccessController class. This means that java code running under a + * security manager that forbids access to ClassLoaders will still work + * if this class is given appropriate privileges, even when the caller + * doesn't have such privileges. Without using an AccessController, the + * the entire call stack must have the privilege before the call is + * allowed. + * + * @return the context classloader associated with the current thread, + * or null if security doesn't allow it. + * @throws LogConfigurationException if there was some weird error while + * attempting to get the context classloader. + * @throws SecurityException if the current java security policy doesn't + * allow this class to access the context classloader. + */ + private static ClassLoader getContextClassLoaderInternal() throws LogConfigurationException { + return (ClassLoader)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return directGetContextClassLoader(); + } + }); + } + + /** + * Return the thread context class loader if available; otherwise return null. + *

+ * Most/all code should call getContextClassLoaderInternal rather than + * calling this method directly. + *

+ * The thread context class loader is available for JDK 1.2 + * or later, if certain security conditions are met. + *

+ * Note that no internal logging is done within this method because + * this method is called every time LogFactory.getLogger() is called, + * and we don't want too much output generated here. + * + * @throws LogConfigurationException if a suitable class loader + * cannot be identified. + * @throws SecurityException if the java security policy forbids + * access to the context classloader from one of the classes in the + * current call stack. + * @since 1.1 + */ + protected static ClassLoader directGetContextClassLoader() throws LogConfigurationException { + ClassLoader classLoader = null; + + try { + // Are we running on a JDK 1.2 or later system? + final Method method = Thread.class.getMethod("getContextClassLoader", (Class[]) null); + + // Get the thread context class loader (if there is one) + try { + classLoader = (ClassLoader)method.invoke(Thread.currentThread(), (Object[]) null); + } catch (IllegalAccessException e) { + throw new LogConfigurationException + ("Unexpected IllegalAccessException", e); + } catch (InvocationTargetException e) { + /** + * InvocationTargetException is thrown by 'invoke' when + * the method being invoked (getContextClassLoader) throws + * an exception. + * + * getContextClassLoader() throws SecurityException when + * the context class loader isn't an ancestor of the + * calling class's class loader, or if security + * permissions are restricted. + * + * In the first case (not related), we want to ignore and + * keep going. We cannot help but also ignore the second + * with the logic below, but other calls elsewhere (to + * obtain a class loader) will trigger this exception where + * we can make a distinction. + */ + if (e.getTargetException() instanceof SecurityException) { + // ignore + } else { + // Capture 'e.getTargetException()' exception for details + // alternate: log 'e.getTargetException()', and pass back 'e'. + throw new LogConfigurationException("Unexpected InvocationTargetException", e.getTargetException()); + } + } + } catch (NoSuchMethodException e) { + // Assume we are running on JDK 1.1 + classLoader = getClassLoader(LogFactory.class); + + // We deliberately don't log a message here to outputStream; + // this message would be output for every call to LogFactory.getLog() + // when running on JDK1.1 + // + // if (outputStream != null) { + // outputStream.println( + // "Method Thread.getContextClassLoader does not exist;" + // + " assuming this is JDK 1.1, and that the context" + // + " classloader is the same as the class that loaded" + // + " the concrete LogFactory class."); + // } + } + + // Return the selected class loader + return classLoader; + } + + /** + * Check cached factories (keyed by contextClassLoader) + * + * @param contextClassLoader is the context classloader associated + * with the current thread. This allows separate LogFactory objects + * per component within a container, provided each component has + * a distinct context classloader set. This parameter may be null + * in JDK1.1, and in embedded systems where jcl-using code is + * placed in the bootclasspath. + * + * @return the factory associated with the specified classloader if + * one has previously been created, or null if this is the first time + * we have seen this particular classloader. + */ + private static LogFactory getCachedFactory(ClassLoader contextClassLoader) { + if (contextClassLoader == null) { + // We have to handle this specially, as factories is a Hashtable + // and those don't accept null as a key value. + // + // nb: nullClassLoaderFactory might be null. That's ok. + return nullClassLoaderFactory; + } else { + return (LogFactory) factories.get(contextClassLoader); + } + } + + /** + * Remember this factory, so later calls to LogFactory.getCachedFactory + * can return the previously created object (together with all its + * cached Log objects). + * + * @param classLoader should be the current context classloader. Note that + * this can be null under some circumstances; this is ok. + * @param factory should be the factory to cache. This should never be null. + */ + private static void cacheFactory(ClassLoader classLoader, LogFactory factory) { + // Ideally we would assert(factory != null) here. However reporting + // errors from within a logging implementation is a little tricky! + + if (factory != null) { + if (classLoader == null) { + nullClassLoaderFactory = factory; + } else { + factories.put(classLoader, factory); + } + } + } + + /** + * Return a new instance of the specified LogFactory + * implementation class, loaded by the specified class loader. + * If that fails, try the class loader used to load this + * (abstract) LogFactory. + *

+ *

ClassLoader conflicts

+ * Note that there can be problems if the specified ClassLoader is not the + * same as the classloader that loaded this class, ie when loading a + * concrete LogFactory subclass via a context classloader. + *

+ * The problem is the same one that can occur when loading a concrete Log + * subclass via a context classloader. + *

+ * The problem occurs when code running in the context classloader calls + * class X which was loaded via a parent classloader, and class X then calls + * LogFactory.getFactory (either directly or via LogFactory.getLog). Because + * class X was loaded via the parent, it binds to LogFactory loaded via + * the parent. When the code in this method finds some LogFactoryYYYY + * class in the child (context) classloader, and there also happens to be a + * LogFactory class defined in the child classloader, then LogFactoryYYYY + * will be bound to LogFactory@childloader. It cannot be cast to + * LogFactory@parentloader, ie this method cannot return the object as + * the desired type. Note that it doesn't matter if the LogFactory class + * in the child classloader is identical to the LogFactory class in the + * parent classloader, they are not compatible. + *

+ * The solution taken here is to simply print out an error message when + * this occurs then throw an exception. The deployer of the application + * must ensure they remove all occurrences of the LogFactory class from + * the child classloader in order to resolve the issue. Note that they + * do not have to move the custom LogFactory subclass; that is ok as + * long as the only LogFactory class it can find to bind to is in the + * parent classloader. + * + * @param factoryClass Fully qualified name of the LogFactory + * implementation class + * @param classLoader ClassLoader from which to load this class + * @param contextClassLoader is the context that this new factory will + * manage logging for. + * @throws LogConfigurationException if a suitable instance + * cannot be created + * @since 1.1 + */ + protected static LogFactory newFactory(final String factoryClass, + final ClassLoader classLoader, + final ClassLoader contextClassLoader) + throws LogConfigurationException { + // Note that any unchecked exceptions thrown by the createFactory + // method will propagate out of this method; in particular a + // ClassCastException can be thrown. + Object result = AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return createFactory(factoryClass, classLoader); + } + }); + + if (result instanceof LogConfigurationException) { + LogConfigurationException ex = (LogConfigurationException) result; + if (isDiagnosticsEnabled()) { + logDiagnostic("An error occurred while loading the factory class:" + ex.getMessage()); + } + throw ex; + } + if (isDiagnosticsEnabled()) { + logDiagnostic("Created object " + objectId(result) + " to manage classloader " + + objectId(contextClassLoader)); + } + return (LogFactory)result; + } + + /** + * Method provided for backwards compatibility; see newFactory version that + * takes 3 parameters. + *

+ * This method would only ever be called in some rather odd situation. + * Note that this method is static, so overriding in a subclass doesn't + * have any effect unless this method is called from a method in that + * subclass. However this method only makes sense to use from the + * getFactory method, and as that is almost always invoked via + * LogFactory.getFactory, any custom definition in a subclass would be + * pointless. Only a class with a custom getFactory method, then invoked + * directly via CustomFactoryImpl.getFactory or similar would ever call + * this. Anyway, it's here just in case, though the "managed class loader" + * value output to the diagnostics will not report the correct value. + */ + protected static LogFactory newFactory(final String factoryClass, + final ClassLoader classLoader) { + return newFactory(factoryClass, classLoader, null); + } + + /** + * Implements the operations described in the javadoc for newFactory. + * + * @param factoryClass + * @param classLoader used to load the specified factory class. This is + * expected to be either the TCCL or the classloader which loaded this + * class. Note that the classloader which loaded this class might be + * "null" (ie the bootloader) for embedded systems. + * @return either a LogFactory object or a LogConfigurationException object. + * @since 1.1 + */ + protected static Object createFactory(String factoryClass, ClassLoader classLoader) { + // This will be used to diagnose bad configurations + // and allow a useful message to be sent to the user + Class logFactoryClass = null; + try { + if (classLoader != null) { + try { + // First the given class loader param (thread class loader) + + // Warning: must typecast here & allow exception + // to be generated/caught & recast properly. + logFactoryClass = classLoader.loadClass(factoryClass); + if (LogFactory.class.isAssignableFrom(logFactoryClass)) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Loaded class " + logFactoryClass.getName() + + " from classloader " + objectId(classLoader)); + } + } else { + // + // This indicates a problem with the ClassLoader tree. + // An incompatible ClassLoader was used to load the + // implementation. + // As the same classes + // must be available in multiple class loaders, + // it is very likely that multiple JCL jars are present. + // The most likely fix for this + // problem is to remove the extra JCL jars from the + // ClassLoader hierarchy. + // + if (isDiagnosticsEnabled()) { + logDiagnostic("Factory class " + logFactoryClass.getName() + + " loaded from classloader " + objectId(logFactoryClass.getClassLoader()) + + " does not extend '" + LogFactory.class.getName() + + "' as loaded by this classloader."); + logHierarchy("[BAD CL TREE] ", classLoader); + } + } + + return (LogFactory) logFactoryClass.newInstance(); + + } catch (ClassNotFoundException ex) { + if (classLoader == thisClassLoader) { + // Nothing more to try, onwards. + if (isDiagnosticsEnabled()) { + logDiagnostic("Unable to locate any class called '" + factoryClass + + "' via classloader " + objectId(classLoader)); + } + throw ex; + } + // ignore exception, continue + } catch (NoClassDefFoundError e) { + if (classLoader == thisClassLoader) { + // Nothing more to try, onwards. + if (isDiagnosticsEnabled()) { + logDiagnostic("Class '" + factoryClass + "' cannot be loaded" + + " via classloader " + objectId(classLoader) + + " - it depends on some other class that cannot be found."); + } + throw e; + } + // ignore exception, continue + } catch (ClassCastException e) { + if (classLoader == thisClassLoader) { + // There's no point in falling through to the code below that + // tries again with thisClassLoader, because we've just tried + // loading with that loader (not the TCCL). Just throw an + // appropriate exception here. + + final boolean implementsLogFactory = implementsLogFactory(logFactoryClass); + + // + // Construct a good message: users may not actual expect that a custom implementation + // has been specified. Several well known containers use this mechanism to adapt JCL + // to their native logging system. + // + final StringBuffer msg = new StringBuffer(); + msg.append("The application has specified that a custom LogFactory implementation "); + msg.append("should be used but Class '"); + msg.append(factoryClass); + msg.append("' cannot be converted to '"); + msg.append(LogFactory.class.getName()); + msg.append("'. "); + if (implementsLogFactory) { + msg.append("The conflict is caused by the presence of multiple LogFactory classes "); + msg.append("in incompatible classloaders. "); + msg.append("Background can be found in http://commons.apache.org/logging/tech.html. "); + msg.append("If you have not explicitly specified a custom LogFactory then it is likely "); + msg.append("that the container has set one without your knowledge. "); + msg.append("In this case, consider using the commons-logging-adapters.jar file or "); + msg.append("specifying the standard LogFactory from the command line. "); + } else { + msg.append("Please check the custom implementation. "); + } + msg.append("Help can be found @http://commons.apache.org/logging/troubleshooting.html."); + + if (isDiagnosticsEnabled()) { + logDiagnostic(msg.toString()); + } + + throw new ClassCastException(msg.toString()); + } + + // Ignore exception, continue. Presumably the classloader was the + // TCCL; the code below will try to load the class via thisClassLoader. + // This will handle the case where the original calling class is in + // a shared classpath but the TCCL has a copy of LogFactory and the + // specified LogFactory implementation; we will fall back to using the + // LogFactory implementation from the same classloader as this class. + // + // Issue: this doesn't handle the reverse case, where this LogFactory + // is in the webapp, and the specified LogFactory implementation is + // in a shared classpath. In that case: + // (a) the class really does implement LogFactory (bad log msg above) + // (b) the fallback code will result in exactly the same problem. + } + } + + /* At this point, either classLoader == null, OR + * classLoader was unable to load factoryClass. + * + * In either case, we call Class.forName, which is equivalent + * to LogFactory.class.getClassLoader().load(name), ie we ignore + * the classloader parameter the caller passed, and fall back + * to trying the classloader associated with this class. See the + * javadoc for the newFactory method for more info on the + * consequences of this. + * + * Notes: + * * LogFactory.class.getClassLoader() may return 'null' + * if LogFactory is loaded by the bootstrap classloader. + */ + // Warning: must typecast here & allow exception + // to be generated/caught & recast properly. + if (isDiagnosticsEnabled()) { + logDiagnostic("Unable to load factory class via classloader " + objectId(classLoader) + + " - trying the classloader associated with this LogFactory."); + } + logFactoryClass = Class.forName(factoryClass); + return (LogFactory) logFactoryClass.newInstance(); + } catch (Exception e) { + // Check to see if we've got a bad configuration + if (isDiagnosticsEnabled()) { + logDiagnostic("Unable to create LogFactory instance."); + } + if (logFactoryClass != null && !LogFactory.class.isAssignableFrom(logFactoryClass)) { + return new LogConfigurationException( + "The chosen LogFactory implementation does not extend LogFactory." + + " Please check your configuration.", e); + } + return new LogConfigurationException(e); + } + } + + /** + * Determines whether the given class actually implements LogFactory. + * Diagnostic information is also logged. + *

+ * Usage: to diagnose whether a classloader conflict is the cause + * of incompatibility. The test used is whether the class is assignable from + * the LogFactory class loaded by the class's classloader. + * @param logFactoryClass Class which may implement LogFactory + * @return true if the logFactoryClass does extend + * LogFactory when that class is loaded via the same + * classloader that loaded the logFactoryClass. + */ + private static boolean implementsLogFactory(Class logFactoryClass) { + boolean implementsLogFactory = false; + if (logFactoryClass != null) { + try { + ClassLoader logFactoryClassLoader = logFactoryClass.getClassLoader(); + if (logFactoryClassLoader == null) { + logDiagnostic("[CUSTOM LOG FACTORY] was loaded by the boot classloader"); + } else { + logHierarchy("[CUSTOM LOG FACTORY] ", logFactoryClassLoader); + Class factoryFromCustomLoader + = Class.forName("org.apache.commons.logging.LogFactory", false, logFactoryClassLoader); + implementsLogFactory = factoryFromCustomLoader.isAssignableFrom(logFactoryClass); + if (implementsLogFactory) { + logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClass.getName() + + " implements LogFactory but was loaded by an incompatible classloader."); + } else { + logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClass.getName() + + " does not implement LogFactory."); + } + } + } catch (SecurityException e) { + // + // The application is running within a hostile security environment. + // This will make it very hard to diagnose issues with JCL. + // Consider running less securely whilst debugging this issue. + // + logDiagnostic("[CUSTOM LOG FACTORY] SecurityException thrown whilst trying to determine whether " + + "the compatibility was caused by a classloader conflict: " + e.getMessage()); + } catch (LinkageError e) { + // + // This should be an unusual circumstance. + // LinkageError's usually indicate that a dependent class has incompatibly changed. + // Another possibility may be an exception thrown by an initializer. + // Time for a clean rebuild? + // + logDiagnostic("[CUSTOM LOG FACTORY] LinkageError thrown whilst trying to determine whether " + + "the compatibility was caused by a classloader conflict: " + e.getMessage()); + } catch (ClassNotFoundException e) { + // + // LogFactory cannot be loaded by the classloader which loaded the custom factory implementation. + // The custom implementation is not viable until this is corrected. + // Ensure that the JCL jar and the custom class are available from the same classloader. + // Running with diagnostics on should give information about the classloaders used + // to load the custom factory. + // + logDiagnostic("[CUSTOM LOG FACTORY] LogFactory class cannot be loaded by classloader which loaded " + + "the custom LogFactory implementation. Is the custom factory in the right classloader?"); + } + } + return implementsLogFactory; + } + + /** + * Applets may run in an environment where accessing resources of a loader is + * a secure operation, but where the commons-logging library has explicitly + * been granted permission for that operation. In this case, we need to + * run the operation using an AccessController. + */ + private static InputStream getResourceAsStream(final ClassLoader loader, final String name) { + return (InputStream)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + if (loader != null) { + return loader.getResourceAsStream(name); + } else { + return ClassLoader.getSystemResourceAsStream(name); + } + } + }); + } + + /** + * Given a filename, return an enumeration of URLs pointing to + * all the occurrences of that filename in the classpath. + *

+ * This is just like ClassLoader.getResources except that the + * operation is done under an AccessController so that this method will + * succeed when this jarfile is privileged but the caller is not. + * This method must therefore remain private to avoid security issues. + *

+ * If no instances are found, an Enumeration is returned whose + * hasMoreElements method returns false (ie an "empty" enumeration). + * If resources could not be listed for some reason, null is returned. + */ + private static Enumeration getResources(final ClassLoader loader, final String name) { + PrivilegedAction action = + new PrivilegedAction() { + public Object run() { + try { + if (loader != null) { + return loader.getResources(name); + } else { + return ClassLoader.getSystemResources(name); + } + } catch (IOException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Exception while trying to find configuration file " + + name + ":" + e.getMessage()); + } + return null; + } catch (NoSuchMethodError e) { + // we must be running on a 1.1 JVM which doesn't support + // ClassLoader.getSystemResources; just return null in + // this case. + return null; + } + } + }; + Object result = AccessController.doPrivileged(action); + return (Enumeration) result; + } + + /** + * Given a URL that refers to a .properties file, load that file. + * This is done under an AccessController so that this method will + * succeed when this jarfile is privileged but the caller is not. + * This method must therefore remain private to avoid security issues. + *

+ * {@code Null} is returned if the URL cannot be opened. + */ + private static Properties getProperties(final URL url) { + PrivilegedAction action = + new PrivilegedAction() { + public Object run() { + InputStream stream = null; + try { + // We must ensure that useCaches is set to false, as the + // default behaviour of java is to cache file handles, and + // this "locks" files, preventing hot-redeploy on windows. + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + stream = connection.getInputStream(); + if (stream != null) { + Properties props = new Properties(); + props.load(stream); + stream.close(); + stream = null; + return props; + } + } catch (IOException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Unable to read URL " + url); + } + } finally { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + // ignore exception; this should not happen + if (isDiagnosticsEnabled()) { + logDiagnostic("Unable to close stream for URL " + url); + } + } + } + } + + return null; + } + }; + return (Properties) AccessController.doPrivileged(action); + } + + /** + * Locate a user-provided configuration file. + *

+ * The classpath of the specified classLoader (usually the context classloader) + * is searched for properties files of the specified name. If none is found, + * null is returned. If more than one is found, then the file with the greatest + * value for its PRIORITY property is returned. If multiple files have the + * same PRIORITY value then the first in the classpath is returned. + *

+ * This differs from the 1.0.x releases; those always use the first one found. + * However as the priority is a new field, this change is backwards compatible. + *

+ * The purpose of the priority field is to allow a webserver administrator to + * override logging settings in all webapps by placing a commons-logging.properties + * file in a shared classpath location with a priority > 0; this overrides any + * commons-logging.properties files without priorities which are in the + * webapps. Webapps can also use explicit priorities to override a configuration + * file in the shared classpath if needed. + */ + private static final Properties getConfigurationFile(ClassLoader classLoader, String fileName) { + Properties props = null; + double priority = 0.0; + URL propsUrl = null; + try { + Enumeration urls = getResources(classLoader, fileName); + + if (urls == null) { + return null; + } + + while (urls.hasMoreElements()) { + URL url = (URL) urls.nextElement(); + + Properties newProps = getProperties(url); + if (newProps != null) { + if (props == null) { + propsUrl = url; + props = newProps; + String priorityStr = props.getProperty(PRIORITY_KEY); + priority = 0.0; + if (priorityStr != null) { + priority = Double.parseDouble(priorityStr); + } + + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] Properties file found at '" + url + "'" + + " with priority " + priority); + } + } else { + String newPriorityStr = newProps.getProperty(PRIORITY_KEY); + double newPriority = 0.0; + if (newPriorityStr != null) { + newPriority = Double.parseDouble(newPriorityStr); + } + + if (newPriority > priority) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] Properties file at '" + url + "'" + + " with priority " + newPriority + + " overrides file at '" + propsUrl + "'" + + " with priority " + priority); + } + + propsUrl = url; + props = newProps; + priority = newPriority; + } else { + if (isDiagnosticsEnabled()) { + logDiagnostic("[LOOKUP] Properties file at '" + url + "'" + + " with priority " + newPriority + + " does not override file at '" + propsUrl + "'" + + " with priority " + priority); + } + } + } + + } + } + } catch (SecurityException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("SecurityException thrown while trying to find/read config files."); + } + } + + if (isDiagnosticsEnabled()) { + if (props == null) { + logDiagnostic("[LOOKUP] No properties file of name '" + fileName + "' found."); + } else { + logDiagnostic("[LOOKUP] Properties file of name '" + fileName + "' found at '" + propsUrl + '"'); + } + } + + return props; + } + + /** + * Read the specified system property, using an AccessController so that + * the property can be read if JCL has been granted the appropriate + * security rights even if the calling code has not. + *

+ * Take care not to expose the value returned by this method to the + * calling application in any way; otherwise the calling app can use that + * info to access data that should not be available to it. + */ + private static String getSystemProperty(final String key, final String def) + throws SecurityException { + return (String) AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return System.getProperty(key, def); + } + }); + } + + /** + * Determines whether the user wants internal diagnostic output. If so, + * returns an appropriate writer object. Users can enable diagnostic + * output by setting the system property named {@link #DIAGNOSTICS_DEST_PROPERTY} to + * a filename, or the special values STDOUT or STDERR. + */ + private static PrintStream initDiagnostics() { + String dest; + try { + dest = getSystemProperty(DIAGNOSTICS_DEST_PROPERTY, null); + if (dest == null) { + return null; + } + } catch (SecurityException ex) { + // We must be running in some very secure environment. + // We just have to assume output is not wanted.. + return null; + } + + if (dest.equals("STDOUT")) { + return System.out; + } else if (dest.equals("STDERR")) { + return System.err; + } else { + try { + // open the file in append mode + FileOutputStream fos = new FileOutputStream(dest, true); + return new PrintStream(fos); + } catch (IOException ex) { + // We should report this to the user - but how? + return null; + } + } + } + + /** + * Indicates true if the user has enabled internal logging. + *

+ * By the way, sorry for the incorrect grammar, but calling this method + * areDiagnosticsEnabled just isn't java beans style. + * + * @return true if calls to logDiagnostic will have any effect. + * @since 1.1 + */ + protected static boolean isDiagnosticsEnabled() { + return diagnosticsStream != null; + } + + /** + * Write the specified message to the internal logging destination. + *

+ * Note that this method is private; concrete subclasses of this class + * should not call it because the diagnosticPrefix string this + * method puts in front of all its messages is LogFactory@...., + * while subclasses should put SomeSubClass@... + *

+ * Subclasses should instead compute their own prefix, then call + * logRawDiagnostic. Note that calling isDiagnosticsEnabled is + * fine for subclasses. + *

+ * Note that it is safe to call this method before initDiagnostics + * is called; any output will just be ignored (as isDiagnosticsEnabled + * will return false). + * + * @param msg is the diagnostic message to be output. + */ + private static final void logDiagnostic(String msg) { + if (diagnosticsStream != null) { + diagnosticsStream.print(diagnosticPrefix); + diagnosticsStream.println(msg); + diagnosticsStream.flush(); + } + } + + /** + * Write the specified message to the internal logging destination. + * + * @param msg is the diagnostic message to be output. + * @since 1.1 + */ + protected static final void logRawDiagnostic(String msg) { + if (diagnosticsStream != null) { + diagnosticsStream.println(msg); + diagnosticsStream.flush(); + } + } + + /** + * Generate useful diagnostics regarding the classloader tree for + * the specified class. + *

+ * As an example, if the specified class was loaded via a webapp's + * classloader, then you may get the following output: + *

+     * Class com.acme.Foo was loaded via classloader 11111
+     * ClassLoader tree: 11111 -> 22222 (SYSTEM) -> 33333 -> BOOT
+     * 
+ *

+ * This method returns immediately if isDiagnosticsEnabled() + * returns false. + * + * @param clazz is the class whose classloader + tree are to be + * output. + */ + private static void logClassLoaderEnvironment(Class clazz) { + if (!isDiagnosticsEnabled()) { + return; + } + + try { + // Deliberately use System.getProperty here instead of getSystemProperty; if + // the overall security policy for the calling application forbids access to + // these variables then we do not want to output them to the diagnostic stream. + logDiagnostic("[ENV] Extension directories (java.ext.dir): " + System.getProperty("java.ext.dir")); + logDiagnostic("[ENV] Application classpath (java.class.path): " + System.getProperty("java.class.path")); + } catch (SecurityException ex) { + logDiagnostic("[ENV] Security setting prevent interrogation of system classpaths."); + } + + String className = clazz.getName(); + ClassLoader classLoader; + + try { + classLoader = getClassLoader(clazz); + } catch (SecurityException ex) { + // not much useful diagnostics we can print here! + logDiagnostic("[ENV] Security forbids determining the classloader for " + className); + return; + } + + logDiagnostic("[ENV] Class " + className + " was loaded via classloader " + objectId(classLoader)); + logHierarchy("[ENV] Ancestry of classloader which loaded " + className + " is ", classLoader); + } + + /** + * Logs diagnostic messages about the given classloader + * and it's hierarchy. The prefix is prepended to the message + * and is intended to make it easier to understand the logs. + * @param prefix + * @param classLoader + */ + private static void logHierarchy(String prefix, ClassLoader classLoader) { + if (!isDiagnosticsEnabled()) { + return; + } + ClassLoader systemClassLoader; + if (classLoader != null) { + final String classLoaderString = classLoader.toString(); + logDiagnostic(prefix + objectId(classLoader) + " == '" + classLoaderString + "'"); + } + + try { + systemClassLoader = ClassLoader.getSystemClassLoader(); + } catch (SecurityException ex) { + logDiagnostic(prefix + "Security forbids determining the system classloader."); + return; + } + if (classLoader != null) { + final StringBuffer buf = new StringBuffer(prefix + "ClassLoader tree:"); + for(;;) { + buf.append(objectId(classLoader)); + if (classLoader == systemClassLoader) { + buf.append(" (SYSTEM) "); + } + + try { + classLoader = classLoader.getParent(); + } catch (SecurityException ex) { + buf.append(" --> SECRET"); + break; + } + + buf.append(" --> "); + if (classLoader == null) { + buf.append("BOOT"); + break; + } + } + logDiagnostic(buf.toString()); + } + } + + /** + * Returns a string that uniquely identifies the specified object, including + * its class. + *

+ * The returned string is of form "classname@hashcode", ie is the same as + * the return value of the Object.toString() method, but works even when + * the specified object's class has overidden the toString method. + * + * @param o may be null. + * @return a string of form classname@hashcode, or "null" if param o is null. + * @since 1.1 + */ + public static String objectId(Object o) { + if (o == null) { + return "null"; + } else { + return o.getClass().getName() + "@" + System.identityHashCode(o); + } + } + + // ---------------------------------------------------------------------- + // Static initialiser block to perform initialisation at class load time. + // + // We can't do this in the class constructor, as there are many + // static methods on this class that can be called before any + // LogFactory instances are created, and they depend upon this + // stuff having been set up. + // + // Note that this block must come after any variable declarations used + // by any methods called from this block, as we want any static initialiser + // associated with the variable to run first. If static initialisers for + // variables run after this code, then (a) their value might be needed + // by methods called from here, and (b) they might *override* any value + // computed here! + // + // So the wisest thing to do is just to place this code at the very end + // of the class file. + // ---------------------------------------------------------------------- + + static { + // note: it's safe to call methods before initDiagnostics (though + // diagnostic output gets discarded). + thisClassLoader = getClassLoader(LogFactory.class); + // In order to avoid confusion where multiple instances of JCL are + // being used via different classloaders within the same app, we + // ensure each logged message has a prefix of form + // [LogFactory from classloader OID] + // + // Note that this prefix should be kept consistent with that + // in LogFactoryImpl. However here we don't need to output info + // about the actual *instance* of LogFactory, as all methods that + // output diagnostics from this class are static. + String classLoaderName; + try { + ClassLoader classLoader = thisClassLoader; + if (thisClassLoader == null) { + classLoaderName = "BOOTLOADER"; + } else { + classLoaderName = objectId(classLoader); + } + } catch (SecurityException e) { + classLoaderName = "UNKNOWN"; + } + diagnosticPrefix = "[LogFactory from " + classLoaderName + "] "; + diagnosticsStream = initDiagnostics(); + logClassLoaderEnvironment(LogFactory.class); + factories = createFactoryStore(); + if (isDiagnosticsEnabled()) { + logDiagnostic("BOOTSTRAP COMPLETED"); + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/LogSource.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/LogSource.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/LogSource.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/LogSource.java 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,219 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging; + +import java.lang.reflect.Constructor; +import java.util.Hashtable; + +import org.apache.commons.logging.impl.NoOpLog; + +/** + * Factory for creating {@link Log} instances. Applications should call + * the makeNewLogInstance() method to instantiate new instances + * of the configured {@link Log} implementation class. + *

+ * By default, calling getInstance() will use the following + * algorithm: + *

    + *
  • If Log4J is available, return an instance of + * org.apache.commons.logging.impl.Log4JLogger.
  • + *
  • If JDK 1.4 or later is available, return an instance of + * org.apache.commons.logging.impl.Jdk14Logger.
  • + *
  • Otherwise, return an instance of + * org.apache.commons.logging.impl.NoOpLog.
  • + *
+ *

+ * You can change the default behavior in one of two ways: + *

    + *
  • On the startup command line, set the system property + * org.apache.commons.logging.log to the name of the + * org.apache.commons.logging.Log implementation class + * you want to use.
  • + *
  • At runtime, call LogSource.setLogImplementation().
  • + *
+ * + * @deprecated Use {@link LogFactory} instead - The default factory + * implementation performs exactly the same algorithm as this class did + * + * @version $Id: LogSource.java 1432675 2013-01-13 17:53:30Z tn $ + */ +public class LogSource { + + // ------------------------------------------------------- Class Attributes + + static protected Hashtable logs = new Hashtable(); + + /** Is log4j available (in the current classpath) */ + static protected boolean log4jIsAvailable = false; + + /** Is JDK 1.4 logging available */ + static protected boolean jdk14IsAvailable = false; + + /** Constructor for current log class */ + static protected Constructor logImplctor = null; + + // ----------------------------------------------------- Class Initializers + + static { + + // Is Log4J Available? + try { + log4jIsAvailable = null != Class.forName("org.apache.log4j.Logger"); + } catch (Throwable t) { + log4jIsAvailable = false; + } + + // Is JDK 1.4 Logging Available? + try { + jdk14IsAvailable = null != Class.forName("java.util.logging.Logger") && + null != Class.forName("org.apache.commons.logging.impl.Jdk14Logger"); + } catch (Throwable t) { + jdk14IsAvailable = false; + } + + // Set the default Log implementation + String name = null; + try { + name = System.getProperty("org.apache.commons.logging.log"); + if (name == null) { + name = System.getProperty("org.apache.commons.logging.Log"); + } + } catch (Throwable t) { + } + if (name != null) { + try { + setLogImplementation(name); + } catch (Throwable t) { + try { + setLogImplementation("org.apache.commons.logging.impl.NoOpLog"); + } catch (Throwable u) { + // ignored + } + } + } else { + try { + if (log4jIsAvailable) { + setLogImplementation("org.apache.commons.logging.impl.Log4JLogger"); + } else if (jdk14IsAvailable) { + setLogImplementation("org.apache.commons.logging.impl.Jdk14Logger"); + } else { + setLogImplementation("org.apache.commons.logging.impl.NoOpLog"); + } + } catch (Throwable t) { + try { + setLogImplementation("org.apache.commons.logging.impl.NoOpLog"); + } catch (Throwable u) { + // ignored + } + } + } + + } + + // ------------------------------------------------------------ Constructor + + /** Don't allow others to create instances. */ + private LogSource() { + } + + // ---------------------------------------------------------- Class Methods + + /** + * Set the log implementation/log implementation factory + * by the name of the class. The given class must implement {@link Log}, + * and provide a constructor that takes a single {@link String} argument + * (containing the name of the log). + */ + static public void setLogImplementation(String classname) + throws LinkageError, NoSuchMethodException, SecurityException, ClassNotFoundException { + try { + Class logclass = Class.forName(classname); + Class[] argtypes = new Class[1]; + argtypes[0] = "".getClass(); + logImplctor = logclass.getConstructor(argtypes); + } catch (Throwable t) { + logImplctor = null; + } + } + + /** + * Set the log implementation/log implementation factory by class. + * The given class must implement {@link Log}, and provide a constructor + * that takes a single {@link String} argument (containing the name of the log). + */ + static public void setLogImplementation(Class logclass) + throws LinkageError, ExceptionInInitializerError, NoSuchMethodException, SecurityException { + Class[] argtypes = new Class[1]; + argtypes[0] = "".getClass(); + logImplctor = logclass.getConstructor(argtypes); + } + + /** Get a Log instance by class name. */ + static public Log getInstance(String name) { + Log log = (Log) logs.get(name); + if (null == log) { + log = makeNewLogInstance(name); + logs.put(name, log); + } + return log; + } + + /** Get a Log instance by class. */ + static public Log getInstance(Class clazz) { + return getInstance(clazz.getName()); + } + + /** + * Create a new {@link Log} implementation, based on the given name. + *

+ * The specific {@link Log} implementation returned is determined by the + * value of the org.apache.commons.logging.log property. The value + * of org.apache.commons.logging.log may be set to the fully specified + * name of a class that implements the {@link Log} interface. This class must + * also have a public constructor that takes a single {@link String} argument + * (containing the name of the {@link Log} to be constructed. + *

+ * When org.apache.commons.logging.log is not set, or when no corresponding + * class can be found, this method will return a Log4JLogger if the log4j Logger + * class is available in the {@link LogSource}'s classpath, or a Jdk14Logger if we + * are on a JDK 1.4 or later system, or NoOpLog if neither of the above conditions is true. + * + * @param name the log name (or category) + */ + static public Log makeNewLogInstance(String name) { + Log log; + try { + Object[] args = { name }; + log = (Log) logImplctor.newInstance(args); + } catch (Throwable t) { + log = null; + } + if (null == log) { + log = new NoOpLog(name); + } + return log; + } + + /** + * Returns a {@link String} array containing the names of + * all logs known to me. + */ + static public String[] getLogNames() { + return (String[]) logs.keySet().toArray(new String[logs.size()]); + } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/AvalonLogger.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/AvalonLogger.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/AvalonLogger.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/AvalonLogger.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,298 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + +import org.apache.avalon.framework.logger.Logger; +import org.apache.commons.logging.Log; + +/** + * Implementation of commons-logging Log interface that delegates all + * logging calls to the Avalon logging abstraction: the Logger interface. + *

+ * There are two ways in which this class can be used: + *

    + *
  • the instance can be constructed with an Avalon logger + * (by calling {@link #AvalonLogger(Logger)}). In this case, it acts + * as a simple thin wrapping implementation over the logger. This is + * particularly useful when using a property setter. + *
  • + *
  • the {@link #setDefaultLogger} class property can be called which + * sets the ancestral Avalon logger for this class. Any AvalonLogger + * instances created through the LogFactory mechanisms will output + * to child loggers of this Logger. + *
  • + *
+ *

+ * Note: AvalonLogger does not implement Serializable + * because the constructors available for it make this impossible to achieve in all + * circumstances; there is no way to "reconnect" to an underlying Logger object on + * deserialization if one was just passed in to the constructor of the original + * object. This class was marked Serializable in the 1.0.4 release of + * commons-logging, but this never actually worked (a NullPointerException would + * be thrown as soon as the deserialized object was used), so removing this marker + * is not considered to be an incompatible change. + * + * @version $Id: AvalonLogger.java 1435115 2013-01-18 12:40:19Z tn $ + */ +public class AvalonLogger implements Log { + + /** Ancestral Avalon logger. */ + private static volatile Logger defaultLogger = null; + /** Avalon logger used to perform log. */ + private final transient Logger logger; + + /** + * Constructs an AvalonLogger that outputs to the given + * Logger instance. + * + * @param logger the Avalon logger implementation to delegate to + */ + public AvalonLogger(Logger logger) { + this.logger = logger; + } + + /** + * Constructs an AvalonLogger that will log to a child + * of the Logger set by calling {@link #setDefaultLogger}. + * + * @param name the name of the avalon logger implementation to delegate to + */ + public AvalonLogger(String name) { + if (defaultLogger == null) { + throw new NullPointerException("default logger has to be specified if this constructor is used!"); + } + this.logger = defaultLogger.getChildLogger(name); + } + + /** + * Gets the Avalon logger implementation used to perform logging. + * + * @return avalon logger implementation + */ + public Logger getLogger() { + return logger; + } + + /** + * Sets the ancestral Avalon logger from which the delegating loggers will descend. + * + * @param logger the default avalon logger, + * in case there is no logger instance supplied in constructor + */ + public static void setDefaultLogger(Logger logger) { + defaultLogger = logger; + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.debug. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public void debug(Object message, Throwable t) { + if (getLogger().isDebugEnabled()) { + getLogger().debug(String.valueOf(message), t); + } + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.debug. + * + * @param message to log. + * @see org.apache.commons.logging.Log#debug(Object) + */ + public void debug(Object message) { + if (getLogger().isDebugEnabled()) { + getLogger().debug(String.valueOf(message)); + } + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.error. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public void error(Object message, Throwable t) { + if (getLogger().isErrorEnabled()) { + getLogger().error(String.valueOf(message), t); + } + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.error. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public void error(Object message) { + if (getLogger().isErrorEnabled()) { + getLogger().error(String.valueOf(message)); + } + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.fatalError. + * + * @param message to log. + * @param t log this cause. + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public void fatal(Object message, Throwable t) { + if (getLogger().isFatalErrorEnabled()) { + getLogger().fatalError(String.valueOf(message), t); + } + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.fatalError. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public void fatal(Object message) { + if (getLogger().isFatalErrorEnabled()) { + getLogger().fatalError(String.valueOf(message)); + } + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.info. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public void info(Object message, Throwable t) { + if (getLogger().isInfoEnabled()) { + getLogger().info(String.valueOf(message), t); + } + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.info. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public void info(Object message) { + if (getLogger().isInfoEnabled()) { + getLogger().info(String.valueOf(message)); + } + } + + /** + * Is logging to org.apache.avalon.framework.logger.Logger.debug enabled? + * @see org.apache.commons.logging.Log#isDebugEnabled() + */ + public boolean isDebugEnabled() { + return getLogger().isDebugEnabled(); + } + + /** + * Is logging to org.apache.avalon.framework.logger.Logger.error enabled? + * @see org.apache.commons.logging.Log#isErrorEnabled() + */ + public boolean isErrorEnabled() { + return getLogger().isErrorEnabled(); + } + + /** + * Is logging to org.apache.avalon.framework.logger.Logger.fatalError enabled? + * @see org.apache.commons.logging.Log#isFatalEnabled() + */ + public boolean isFatalEnabled() { + return getLogger().isFatalErrorEnabled(); + } + + /** + * Is logging to org.apache.avalon.framework.logger.Logger.info enabled? + * @see org.apache.commons.logging.Log#isInfoEnabled() + */ + public boolean isInfoEnabled() { + return getLogger().isInfoEnabled(); + } + + /** + * Is logging to org.apache.avalon.framework.logger.Logger.debug enabled? + * @see org.apache.commons.logging.Log#isTraceEnabled() + */ + public boolean isTraceEnabled() { + return getLogger().isDebugEnabled(); + } + + /** + * Is logging to org.apache.avalon.framework.logger.Logger.warn enabled? + * @see org.apache.commons.logging.Log#isWarnEnabled() + */ + public boolean isWarnEnabled() { + return getLogger().isWarnEnabled(); + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.debug. + * + * @param message to log. + * @param t log this cause. + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public void trace(Object message, Throwable t) { + if (getLogger().isDebugEnabled()) { + getLogger().debug(String.valueOf(message), t); + } + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.debug. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public void trace(Object message) { + if (getLogger().isDebugEnabled()) { + getLogger().debug(String.valueOf(message)); + } + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.warn. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public void warn(Object message, Throwable t) { + if (getLogger().isWarnEnabled()) { + getLogger().warn(String.valueOf(message), t); + } + } + + /** + * Logs a message with org.apache.avalon.framework.logger.Logger.warn. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public void warn(Object message) { + if (getLogger().isWarnEnabled()) { + getLogger().warn(String.valueOf(message)); + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,302 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + +import java.io.Serializable; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.LogRecord; +import java.util.StringTokenizer; +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.apache.commons.logging.Log; + +/** + * Implementation of the org.apache.commons.logging.Log + * interface that wraps the standard JDK logging mechanisms that are + * available in SourceForge's Lumberjack for JDKs prior to 1.4. + * + * @version $Id: Jdk13LumberjackLogger.java 1432663 2013-01-13 17:24:18Z tn $ + * @since 1.1 + */ +public class Jdk13LumberjackLogger implements Log, Serializable { + + /** Serializable version identifier. */ + private static final long serialVersionUID = -8649807923527610591L; + + // ----------------------------------------------------- Instance Variables + + /** + * The underlying Logger implementation we are using. + */ + protected transient Logger logger = null; + protected String name = null; + private String sourceClassName = "unknown"; + private String sourceMethodName = "unknown"; + private boolean classAndMethodFound = false; + + /** + * This member variable simply ensures that any attempt to initialise + * this class in a pre-1.4 JVM will result in an ExceptionInInitializerError. + * It must not be private, as an optimising compiler could detect that it + * is not used and optimise it away. + */ + protected static final Level dummyLevel = Level.FINE; + + // ----------------------------------------------------------- Constructors + + /** + * Construct a named instance of this Logger. + * + * @param name Name of the logger to be constructed + */ + public Jdk13LumberjackLogger(String name) { + this.name = name; + logger = getLogger(); + } + + // --------------------------------------------------------- Public Methods + + private void log( Level level, String msg, Throwable ex ) { + if( getLogger().isLoggable(level) ) { + LogRecord record = new LogRecord(level, msg); + if( !classAndMethodFound ) { + getClassAndMethod(); + } + record.setSourceClassName(sourceClassName); + record.setSourceMethodName(sourceMethodName); + if( ex != null ) { + record.setThrown(ex); + } + getLogger().log(record); + } + } + + /** + * Gets the class and method by looking at the stack trace for the + * first entry that is not this class. + */ + private void getClassAndMethod() { + try { + Throwable throwable = new Throwable(); + throwable.fillInStackTrace(); + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter( stringWriter ); + throwable.printStackTrace( printWriter ); + String traceString = stringWriter.getBuffer().toString(); + StringTokenizer tokenizer = + new StringTokenizer( traceString, "\n" ); + tokenizer.nextToken(); + String line = tokenizer.nextToken(); + while ( line.indexOf( this.getClass().getName() ) == -1 ) { + line = tokenizer.nextToken(); + } + while ( line.indexOf( this.getClass().getName() ) >= 0 ) { + line = tokenizer.nextToken(); + } + int start = line.indexOf( "at " ) + 3; + int end = line.indexOf( '(' ); + String temp = line.substring( start, end ); + int lastPeriod = temp.lastIndexOf( '.' ); + sourceClassName = temp.substring( 0, lastPeriod ); + sourceMethodName = temp.substring( lastPeriod + 1 ); + } catch ( Exception ex ) { + // ignore - leave class and methodname unknown + } + classAndMethodFound = true; + } + + /** + * Logs a message with java.util.logging.Level.FINE. + * + * @param message to log + * @see org.apache.commons.logging.Log#debug(Object) + */ + public void debug(Object message) { + log(Level.FINE, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.FINE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public void debug(Object message, Throwable exception) { + log(Level.FINE, String.valueOf(message), exception); + } + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public void error(Object message) { + log(Level.SEVERE, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public void error(Object message, Throwable exception) { + log(Level.SEVERE, String.valueOf(message), exception); + } + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public void fatal(Object message) { + log(Level.SEVERE, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public void fatal(Object message, Throwable exception) { + log(Level.SEVERE, String.valueOf(message), exception); + } + + /** + * Return the native Logger instance we are using. + */ + public Logger getLogger() { + if (logger == null) { + logger = Logger.getLogger(name); + } + return logger; + } + + /** + * Logs a message with java.util.logging.Level.INFO. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public void info(Object message) { + log(Level.INFO, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.INFO. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public void info(Object message, Throwable exception) { + log(Level.INFO, String.valueOf(message), exception); + } + + /** + * Is debug logging currently enabled? + */ + public boolean isDebugEnabled() { + return getLogger().isLoggable(Level.FINE); + } + + /** + * Is error logging currently enabled? + */ + public boolean isErrorEnabled() { + return getLogger().isLoggable(Level.SEVERE); + } + + /** + * Is fatal logging currently enabled? + */ + public boolean isFatalEnabled() { + return getLogger().isLoggable(Level.SEVERE); + } + + /** + * Is info logging currently enabled? + */ + public boolean isInfoEnabled() { + return getLogger().isLoggable(Level.INFO); + } + + /** + * Is trace logging currently enabled? + */ + public boolean isTraceEnabled() { + return getLogger().isLoggable(Level.FINEST); + } + + /** + * Is warn logging currently enabled? + */ + public boolean isWarnEnabled() { + return getLogger().isLoggable(Level.WARNING); + } + + /** + * Logs a message with java.util.logging.Level.FINEST. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public void trace(Object message) { + log(Level.FINEST, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.FINEST. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public void trace(Object message, Throwable exception) { + log(Level.FINEST, String.valueOf(message), exception); + } + + /** + * Logs a message with java.util.logging.Level.WARNING. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public void warn(Object message) { + log(Level.WARNING, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.WARNING. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public void warn(Object message, Throwable exception) { + log(Level.WARNING, String.valueOf(message), exception); + } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/Jdk14Logger.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/Jdk14Logger.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/Jdk14Logger.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/Jdk14Logger.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,273 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + +import java.io.Serializable; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.commons.logging.Log; + +/** + * Implementation of the org.apache.commons.logging.Log + * interface that wraps the standard JDK logging mechanisms that were + * introduced in the Merlin release (JDK 1.4). + * + * @version $Id: Jdk14Logger.java 1448063 2013-02-20 10:01:41Z tn $ + */ +public class Jdk14Logger implements Log, Serializable { + + /** Serializable version identifier. */ + private static final long serialVersionUID = 4784713551416303804L; + + /** + * This member variable simply ensures that any attempt to initialise + * this class in a pre-1.4 JVM will result in an ExceptionInInitializerError. + * It must not be private, as an optimising compiler could detect that it + * is not used and optimise it away. + */ + protected static final Level dummyLevel = Level.FINE; + + // ----------------------------------------------------------- Constructors + + /** + * Construct a named instance of this Logger. + * + * @param name Name of the logger to be constructed + */ + public Jdk14Logger(String name) { + this.name = name; + logger = getLogger(); + } + + // ----------------------------------------------------- Instance Variables + + /** + * The underlying Logger implementation we are using. + */ + protected transient Logger logger = null; + + /** + * The name of the logger we are wrapping. + */ + protected String name = null; + + // --------------------------------------------------------- Protected Methods + + protected void log( Level level, String msg, Throwable ex ) { + Logger logger = getLogger(); + if (logger.isLoggable(level)) { + // Hack (?) to get the stack trace. + Throwable dummyException = new Throwable(); + StackTraceElement locations[] = dummyException.getStackTrace(); + // LOGGING-132: use the provided logger name instead of the class name + String cname = name; + String method = "unknown"; + // Caller will be the third element + if( locations != null && locations.length > 2 ) { + StackTraceElement caller = locations[2]; + method = caller.getMethodName(); + } + if( ex == null ) { + logger.logp( level, cname, method, msg ); + } else { + logger.logp( level, cname, method, msg, ex ); + } + } + } + + // --------------------------------------------------------- Public Methods + + /** + * Logs a message with java.util.logging.Level.FINE. + * + * @param message to log + * @see org.apache.commons.logging.Log#debug(Object) + */ + public void debug(Object message) { + log(Level.FINE, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.FINE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public void debug(Object message, Throwable exception) { + log(Level.FINE, String.valueOf(message), exception); + } + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public void error(Object message) { + log(Level.SEVERE, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public void error(Object message, Throwable exception) { + log(Level.SEVERE, String.valueOf(message), exception); + } + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public void fatal(Object message) { + log(Level.SEVERE, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public void fatal(Object message, Throwable exception) { + log(Level.SEVERE, String.valueOf(message), exception); + } + + /** + * Return the native Logger instance we are using. + */ + public Logger getLogger() { + if (logger == null) { + logger = Logger.getLogger(name); + } + return logger; + } + + /** + * Logs a message with java.util.logging.Level.INFO. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public void info(Object message) { + log(Level.INFO, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.INFO. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public void info(Object message, Throwable exception) { + log(Level.INFO, String.valueOf(message), exception); + } + + /** + * Is debug logging currently enabled? + */ + public boolean isDebugEnabled() { + return getLogger().isLoggable(Level.FINE); + } + + /** + * Is error logging currently enabled? + */ + public boolean isErrorEnabled() { + return getLogger().isLoggable(Level.SEVERE); + } + + /** + * Is fatal logging currently enabled? + */ + public boolean isFatalEnabled() { + return getLogger().isLoggable(Level.SEVERE); + } + + /** + * Is info logging currently enabled? + */ + public boolean isInfoEnabled() { + return getLogger().isLoggable(Level.INFO); + } + + /** + * Is trace logging currently enabled? + */ + public boolean isTraceEnabled() { + return getLogger().isLoggable(Level.FINEST); + } + + /** + * Is warn logging currently enabled? + */ + public boolean isWarnEnabled() { + return getLogger().isLoggable(Level.WARNING); + } + + /** + * Logs a message with java.util.logging.Level.FINEST. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public void trace(Object message) { + log(Level.FINEST, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.FINEST. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public void trace(Object message, Throwable exception) { + log(Level.FINEST, String.valueOf(message), exception); + } + + /** + * Logs a message with java.util.logging.Level.WARNING. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public void warn(Object message) { + log(Level.WARNING, String.valueOf(message), null); + } + + /** + * Logs a message with java.util.logging.Level.WARNING. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public void warn(Object message, Throwable exception) { + log(Level.WARNING, String.valueOf(message), exception); + } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/Log4JLogger.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/Log4JLogger.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/Log4JLogger.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/Log4JLogger.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,312 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + +import java.io.Serializable; +import org.apache.commons.logging.Log; +import org.apache.log4j.Logger; +import org.apache.log4j.Priority; +import org.apache.log4j.Level; + +/** + * Implementation of {@link Log} that maps directly to a + * Logger for log4J version 1.2. + *

+ * Initial configuration of the corresponding Logger instances should be done + * in the usual manner, as outlined in the Log4J documentation. + *

+ * The reason this logger is distinct from the 1.3 logger is that in version 1.2 + * of Log4J: + *

    + *
  • class Logger takes Priority parameters not Level parameters. + *
  • class Level extends Priority + *
+ * Log4J1.3 is expected to change Level so it no longer extends Priority, which is + * a non-binary-compatible change. The class generated by compiling this code against + * log4j 1.2 will therefore not run against log4j 1.3. + * + * @version $Id: Log4JLogger.java 1448119 2013-02-20 12:28:04Z tn $ + */ +public class Log4JLogger implements Log, Serializable { + + /** Serializable version identifier. */ + private static final long serialVersionUID = 5160705895411730424L; + + // ------------------------------------------------------------- Attributes + + /** The fully qualified name of the Log4JLogger class. */ + private static final String FQCN = Log4JLogger.class.getName(); + + /** Log to this logger */ + private transient volatile Logger logger = null; + + /** Logger name */ + private final String name; + + private static final Priority traceLevel; + + // ------------------------------------------------------------ + // Static Initializer. + // + // Note that this must come after the static variable declarations + // otherwise initialiser expressions associated with those variables + // will override any settings done here. + // + // Verify that log4j is available, and that it is version 1.2. + // If an ExceptionInInitializerError is generated, then LogFactoryImpl + // will treat that as meaning that the appropriate underlying logging + // library is just not present - if discovery is in progress then + // discovery will continue. + // ------------------------------------------------------------ + + static { + if (!Priority.class.isAssignableFrom(Level.class)) { + // nope, this is log4j 1.3, so force an ExceptionInInitializerError + throw new InstantiationError("Log4J 1.2 not available"); + } + + // Releases of log4j1.2 >= 1.2.12 have Priority.TRACE available, earlier + // versions do not. If TRACE is not available, then we have to map + // calls to Log.trace(...) onto the DEBUG level. + + Priority _traceLevel; + try { + _traceLevel = (Priority) Level.class.getDeclaredField("TRACE").get(null); + } catch(Exception ex) { + // ok, trace not available + _traceLevel = Level.DEBUG; + } + traceLevel = _traceLevel; + } + + // ------------------------------------------------------------ Constructor + + public Log4JLogger() { + name = null; + } + + /** + * Base constructor. + */ + public Log4JLogger(String name) { + this.name = name; + this.logger = getLogger(); + } + + /** + * For use with a log4j factory. + */ + public Log4JLogger(Logger logger) { + if (logger == null) { + throw new IllegalArgumentException( + "Warning - null logger in constructor; possible log4j misconfiguration."); + } + this.name = logger.getName(); + this.logger = logger; + } + + /** + * Logs a message with org.apache.log4j.Priority.TRACE. + * When using a log4j version that does not support the TRACE + * level, the message will be logged at the DEBUG level. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public void trace(Object message) { + getLogger().log(FQCN, traceLevel, message, null); + } + + /** + * Logs a message with org.apache.log4j.Priority.TRACE. + * When using a log4j version that does not support the TRACE + * level, the message will be logged at the DEBUG level. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public void trace(Object message, Throwable t) { + getLogger().log(FQCN, traceLevel, message, t); + } + + /** + * Logs a message with org.apache.log4j.Priority.DEBUG. + * + * @param message to log + * @see org.apache.commons.logging.Log#debug(Object) + */ + public void debug(Object message) { + getLogger().log(FQCN, Level.DEBUG, message, null); + } + + /** + * Logs a message with org.apache.log4j.Priority.DEBUG. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public void debug(Object message, Throwable t) { + getLogger().log(FQCN, Level.DEBUG, message, t); + } + + /** + * Logs a message with org.apache.log4j.Priority.INFO. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public void info(Object message) { + getLogger().log(FQCN, Level.INFO, message, null); + } + + /** + * Logs a message with org.apache.log4j.Priority.INFO. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public void info(Object message, Throwable t) { + getLogger().log(FQCN, Level.INFO, message, t); + } + + /** + * Logs a message with org.apache.log4j.Priority.WARN. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public void warn(Object message) { + getLogger().log(FQCN, Level.WARN, message, null); + } + + /** + * Logs a message with org.apache.log4j.Priority.WARN. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public void warn(Object message, Throwable t) { + getLogger().log(FQCN, Level.WARN, message, t); + } + + /** + * Logs a message with org.apache.log4j.Priority.ERROR. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public void error(Object message) { + getLogger().log(FQCN, Level.ERROR, message, null); + } + + /** + * Logs a message with org.apache.log4j.Priority.ERROR. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public void error(Object message, Throwable t) { + getLogger().log(FQCN, Level.ERROR, message, t); + } + + /** + * Logs a message with org.apache.log4j.Priority.FATAL. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public void fatal(Object message) { + getLogger().log(FQCN, Level.FATAL, message, null); + } + + /** + * Logs a message with org.apache.log4j.Priority.FATAL. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public void fatal(Object message, Throwable t) { + getLogger().log(FQCN, Level.FATAL, message, t); + } + + /** + * Return the native Logger instance we are using. + */ + public Logger getLogger() { + Logger result = logger; + if (result == null) { + synchronized(this) { + result = logger; + if (result == null) { + logger = result = Logger.getLogger(name); + } + } + } + return result; + } + + /** + * Check whether the Log4j Logger used is enabled for DEBUG priority. + */ + public boolean isDebugEnabled() { + return getLogger().isDebugEnabled(); + } + + /** + * Check whether the Log4j Logger used is enabled for ERROR priority. + */ + public boolean isErrorEnabled() { + return getLogger().isEnabledFor(Level.ERROR); + } + + /** + * Check whether the Log4j Logger used is enabled for FATAL priority. + */ + public boolean isFatalEnabled() { + return getLogger().isEnabledFor(Level.FATAL); + } + + /** + * Check whether the Log4j Logger used is enabled for INFO priority. + */ + public boolean isInfoEnabled() { + return getLogger().isInfoEnabled(); + } + + /** + * Check whether the Log4j Logger used is enabled for TRACE priority. + * When using a log4j version that does not support the TRACE level, this call + * will report whether DEBUG is enabled or not. + */ + public boolean isTraceEnabled() { + return getLogger().isEnabledFor(traceLevel); + } + + /** + * Check whether the Log4j Logger used is enabled for WARN priority. + */ + public boolean isWarnEnabled() { + return getLogger().isEnabledFor(Level.WARN); + } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/LogFactoryImpl.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/LogFactoryImpl.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/LogFactoryImpl.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/LogFactoryImpl.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,1393 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Hashtable; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogConfigurationException; +import org.apache.commons.logging.LogFactory; + +/** + * Concrete subclass of {@link LogFactory} that implements the + * following algorithm to dynamically select a logging implementation + * class to instantiate a wrapper for: + *
    + *
  • Use a factory configuration attribute named + * org.apache.commons.logging.Log to identify the + * requested implementation class.
  • + *
  • Use the org.apache.commons.logging.Log system property + * to identify the requested implementation class.
  • + *
  • If Log4J is available, return an instance of + * org.apache.commons.logging.impl.Log4JLogger.
  • + *
  • If JDK 1.4 or later is available, return an instance of + * org.apache.commons.logging.impl.Jdk14Logger.
  • + *
  • Otherwise, return an instance of + * org.apache.commons.logging.impl.SimpleLog.
  • + *
+ *

+ * If the selected {@link Log} implementation class has a + * setLogFactory() method that accepts a {@link LogFactory} + * parameter, this method will be called on each newly created instance + * to identify the associated factory. This makes factory configuration + * attributes available to the Log instance, if it so desires. + *

+ * This factory will remember previously created Log instances + * for the same name, and will return them on repeated requests to the + * getInstance() method. + * + * @version $Id: LogFactoryImpl.java 1449064 2013-02-22 14:49:22Z tn $ + */ +public class LogFactoryImpl extends LogFactory { + + /** Log4JLogger class name */ + private static final String LOGGING_IMPL_LOG4J_LOGGER = "org.apache.commons.logging.impl.Log4JLogger"; + /** Jdk14Logger class name */ + private static final String LOGGING_IMPL_JDK14_LOGGER = "org.apache.commons.logging.impl.Jdk14Logger"; + /** Jdk13LumberjackLogger class name */ + private static final String LOGGING_IMPL_LUMBERJACK_LOGGER = + "org.apache.commons.logging.impl.Jdk13LumberjackLogger"; + + /** SimpleLog class name */ + private static final String LOGGING_IMPL_SIMPLE_LOGGER = "org.apache.commons.logging.impl.SimpleLog"; + + private static final String PKG_IMPL="org.apache.commons.logging.impl."; + private static final int PKG_LEN = PKG_IMPL.length(); + + // ----------------------------------------------------------- Constructors + + /** + * Public no-arguments constructor required by the lookup mechanism. + */ + public LogFactoryImpl() { + super(); + initDiagnostics(); // method on this object + if (isDiagnosticsEnabled()) { + logDiagnostic("Instance created."); + } + } + + // ----------------------------------------------------- Manifest Constants + + /** + * The name (org.apache.commons.logging.Log) of the system + * property identifying our {@link Log} implementation class. + */ + public static final String LOG_PROPERTY = "org.apache.commons.logging.Log"; + + /** + * The deprecated system property used for backwards compatibility with + * old versions of JCL. + */ + protected static final String LOG_PROPERTY_OLD = "org.apache.commons.logging.log"; + + /** + * The name (org.apache.commons.logging.Log.allowFlawedContext) + * of the system property which can be set true/false to + * determine system behaviour when a bad context-classloader is encountered. + * When set to false, a LogConfigurationException is thrown if + * LogFactoryImpl is loaded via a child classloader of the TCCL (this + * should never happen in sane systems). + * + * Default behaviour: true (tolerates bad context classloaders) + * + * See also method setAttribute. + */ + public static final String ALLOW_FLAWED_CONTEXT_PROPERTY = + "org.apache.commons.logging.Log.allowFlawedContext"; + + /** + * The name (org.apache.commons.logging.Log.allowFlawedDiscovery) + * of the system property which can be set true/false to + * determine system behaviour when a bad logging adapter class is + * encountered during logging discovery. When set to false, an + * exception will be thrown and the app will fail to start. When set + * to true, discovery will continue (though the user might end up + * with a different logging implementation than they expected). + *

+ * Default behaviour: true (tolerates bad logging adapters) + * + * See also method setAttribute. + */ + public static final String ALLOW_FLAWED_DISCOVERY_PROPERTY = + "org.apache.commons.logging.Log.allowFlawedDiscovery"; + + /** + * The name (org.apache.commons.logging.Log.allowFlawedHierarchy) + * of the system property which can be set true/false to + * determine system behaviour when a logging adapter class is + * encountered which has bound to the wrong Log class implementation. + * When set to false, an exception will be thrown and the app will fail + * to start. When set to true, discovery will continue (though the user + * might end up with a different logging implementation than they expected). + *

+ * Default behaviour: true (tolerates bad Log class hierarchy) + * + * See also method setAttribute. + */ + public static final String ALLOW_FLAWED_HIERARCHY_PROPERTY = + "org.apache.commons.logging.Log.allowFlawedHierarchy"; + + /** + * The names of classes that will be tried (in order) as logging + * adapters. Each class is expected to implement the Log interface, + * and to throw NoClassDefFound or ExceptionInInitializerError when + * loaded if the underlying logging library is not available. Any + * other error indicates that the underlying logging library is available + * but broken/unusable for some reason. + */ + private static final String[] classesToDiscover = { + LOGGING_IMPL_LOG4J_LOGGER, + "org.apache.commons.logging.impl.Jdk14Logger", + "org.apache.commons.logging.impl.Jdk13LumberjackLogger", + "org.apache.commons.logging.impl.SimpleLog" + }; + + // ----------------------------------------------------- Instance Variables + + /** + * Determines whether logging classes should be loaded using the thread-context + * classloader, or via the classloader that loaded this LogFactoryImpl class. + */ + private boolean useTCCL = true; + + /** + * The string prefixed to every message output by the logDiagnostic method. + */ + private String diagnosticPrefix; + + /** + * Configuration attributes. + */ + protected Hashtable attributes = new Hashtable(); + + /** + * The {@link org.apache.commons.logging.Log} instances that have + * already been created, keyed by logger name. + */ + protected Hashtable instances = new Hashtable(); + + /** + * Name of the class implementing the Log interface. + */ + private String logClassName; + + /** + * The one-argument constructor of the + * {@link org.apache.commons.logging.Log} + * implementation class that will be used to create new instances. + * This value is initialized by getLogConstructor(), + * and then returned repeatedly. + */ + protected Constructor logConstructor = null; + + /** + * The signature of the Constructor to be used. + */ + protected Class logConstructorSignature[] = { java.lang.String.class }; + + /** + * The one-argument setLogFactory method of the selected + * {@link org.apache.commons.logging.Log} method, if it exists. + */ + protected Method logMethod = null; + + /** + * The signature of the setLogFactory method to be used. + */ + protected Class logMethodSignature[] = { LogFactory.class }; + + /** + * See getBaseClassLoader and initConfiguration. + */ + private boolean allowFlawedContext; + + /** + * See handleFlawedDiscovery and initConfiguration. + */ + private boolean allowFlawedDiscovery; + + /** + * See handleFlawedHierarchy and initConfiguration. + */ + private boolean allowFlawedHierarchy; + + // --------------------------------------------------------- Public Methods + + /** + * Return the configuration attribute with the specified name (if any), + * or null if there is no such attribute. + * + * @param name Name of the attribute to return + */ + public Object getAttribute(String name) { + return attributes.get(name); + } + + /** + * Return an array containing the names of all currently defined + * configuration attributes. If there are no such attributes, a zero + * length array is returned. + */ + public String[] getAttributeNames() { + return (String[]) attributes.keySet().toArray(new String[attributes.size()]); + } + + /** + * Convenience method to derive a name from the specified class and + * call getInstance(String) with it. + * + * @param clazz Class for which a suitable Log name will be derived + * + * @exception LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public Log getInstance(Class clazz) throws LogConfigurationException { + return getInstance(clazz.getName()); + } + + /** + *

Construct (if necessary) and return a Log instance, + * using the factory's current set of configuration attributes.

+ * + *

NOTE - Depending upon the implementation of + * the LogFactory you are using, the Log + * instance you are returned may or may not be local to the current + * application, and may or may not be returned again on a subsequent + * call with the same name argument.

+ * + * @param name Logical name of the Log instance to be + * returned (the meaning of this name is only known to the underlying + * logging implementation that is being wrapped) + * + * @exception LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public Log getInstance(String name) throws LogConfigurationException { + Log instance = (Log) instances.get(name); + if (instance == null) { + instance = newInstance(name); + instances.put(name, instance); + } + return instance; + } + + /** + * Release any internal references to previously created + * {@link org.apache.commons.logging.Log} + * instances returned by this factory. This is useful in environments + * like servlet containers, which implement application reloading by + * throwing away a ClassLoader. Dangling references to objects in that + * class loader would prevent garbage collection. + */ + public void release() { + + logDiagnostic("Releasing all known loggers"); + instances.clear(); + } + + /** + * Remove any configuration attribute associated with the specified name. + * If there is no such attribute, no action is taken. + * + * @param name Name of the attribute to remove + */ + public void removeAttribute(String name) { + attributes.remove(name); + } + + /** + * Set the configuration attribute with the specified name. Calling + * this with a null value is equivalent to calling + * removeAttribute(name). + *

+ * This method can be used to set logging configuration programmatically + * rather than via system properties. It can also be used in code running + * within a container (such as a webapp) to configure behaviour on a + * per-component level instead of globally as system properties would do. + * To use this method instead of a system property, call + *

+     * LogFactory.getFactory().setAttribute(...)
+     * 
+ * This must be done before the first Log object is created; configuration + * changes after that point will be ignored. + *

+ * This method is also called automatically if LogFactory detects a + * commons-logging.properties file; every entry in that file is set + * automatically as an attribute here. + * + * @param name Name of the attribute to set + * @param value Value of the attribute to set, or null + * to remove any setting for this attribute + */ + public void setAttribute(String name, Object value) { + if (logConstructor != null) { + logDiagnostic("setAttribute: call too late; configuration already performed."); + } + + if (value == null) { + attributes.remove(name); + } else { + attributes.put(name, value); + } + + if (name.equals(TCCL_KEY)) { + useTCCL = value != null && Boolean.valueOf(value.toString()).booleanValue(); + } + } + + // ------------------------------------------------------ + // Static Methods + // + // These methods only defined as workarounds for a java 1.2 bug; + // theoretically none of these are needed. + // ------------------------------------------------------ + + /** + * Gets the context classloader. + * This method is a workaround for a java 1.2 compiler bug. + * @since 1.1 + */ + protected static ClassLoader getContextClassLoader() throws LogConfigurationException { + return LogFactory.getContextClassLoader(); + } + + /** + * Workaround for bug in Java1.2; in theory this method is not needed. + * See LogFactory.isDiagnosticsEnabled. + */ + protected static boolean isDiagnosticsEnabled() { + return LogFactory.isDiagnosticsEnabled(); + } + + /** + * Workaround for bug in Java1.2; in theory this method is not needed. + * See LogFactory.getClassLoader. + * @since 1.1 + */ + protected static ClassLoader getClassLoader(Class clazz) { + return LogFactory.getClassLoader(clazz); + } + + // ------------------------------------------------------ Protected Methods + + /** + * Calculate and cache a string that uniquely identifies this instance, + * including which classloader the object was loaded from. + *

+ * This string will later be prefixed to each "internal logging" message + * emitted, so that users can clearly see any unexpected behaviour. + *

+ * Note that this method does not detect whether internal logging is + * enabled or not, nor where to output stuff if it is; that is all + * handled by the parent LogFactory class. This method just computes + * its own unique prefix for log messages. + */ + private void initDiagnostics() { + // It would be nice to include an identifier of the context classloader + // that this LogFactoryImpl object is responsible for. However that + // isn't possible as that information isn't available. It is possible + // to figure this out by looking at the logging from LogFactory to + // see the context & impl ids from when this object was instantiated, + // in order to link the impl id output as this object's prefix back to + // the context it is intended to manage. + // Note that this prefix should be kept consistent with that + // in LogFactory. + Class clazz = this.getClass(); + ClassLoader classLoader = getClassLoader(clazz); + String classLoaderName; + try { + if (classLoader == null) { + classLoaderName = "BOOTLOADER"; + } else { + classLoaderName = objectId(classLoader); + } + } catch (SecurityException e) { + classLoaderName = "UNKNOWN"; + } + diagnosticPrefix = "[LogFactoryImpl@" + System.identityHashCode(this) + " from " + classLoaderName + "] "; + } + + /** + * Output a diagnostic message to a user-specified destination (if the + * user has enabled diagnostic logging). + * + * @param msg diagnostic message + * @since 1.1 + */ + protected void logDiagnostic(String msg) { + if (isDiagnosticsEnabled()) { + logRawDiagnostic(diagnosticPrefix + msg); + } + } + + /** + * Return the fully qualified Java classname of the {@link Log} + * implementation we will be using. + * + * @deprecated Never invoked by this class; subclasses should not assume + * it will be. + */ + protected String getLogClassName() { + if (logClassName == null) { + discoverLogImplementation(getClass().getName()); + } + + return logClassName; + } + + + /** + *

Return the Constructor that can be called to instantiate + * new {@link org.apache.commons.logging.Log} instances.

+ * + *

IMPLEMENTATION NOTE - Race conditions caused by + * calling this method from more than one thread are ignored, because + * the same Constructor instance will ultimately be derived + * in all circumstances.

+ * + * @exception LogConfigurationException if a suitable constructor + * cannot be returned + * + * @deprecated Never invoked by this class; subclasses should not assume + * it will be. + */ + protected Constructor getLogConstructor() + throws LogConfigurationException { + + // Return the previously identified Constructor (if any) + if (logConstructor == null) { + discoverLogImplementation(getClass().getName()); + } + + return logConstructor; + } + + /** + * Is JDK 1.3 with Lumberjack logging available? + * + * @deprecated Never invoked by this class; subclasses should not assume + * it will be. + */ + protected boolean isJdk13LumberjackAvailable() { + return isLogLibraryAvailable( + "Jdk13Lumberjack", + "org.apache.commons.logging.impl.Jdk13LumberjackLogger"); + } + + /** + * Return true if JDK 1.4 or later logging + * is available. Also checks that the Throwable class + * supports getStackTrace(), which is required by + * Jdk14Logger. + * + * @deprecated Never invoked by this class; subclasses should not assume + * it will be. + */ + protected boolean isJdk14Available() { + return isLogLibraryAvailable( + "Jdk14", + "org.apache.commons.logging.impl.Jdk14Logger"); + } + + /** + * Is a Log4J implementation available? + * + * @deprecated Never invoked by this class; subclasses should not assume + * it will be. + */ + protected boolean isLog4JAvailable() { + return isLogLibraryAvailable( + "Log4J", + LOGGING_IMPL_LOG4J_LOGGER); + } + + /** + * Create and return a new {@link org.apache.commons.logging.Log} + * instance for the specified name. + * + * @param name Name of the new logger + * + * @exception LogConfigurationException if a new instance cannot + * be created + */ + protected Log newInstance(String name) throws LogConfigurationException { + Log instance; + try { + if (logConstructor == null) { + instance = discoverLogImplementation(name); + } + else { + Object params[] = { name }; + instance = (Log) logConstructor.newInstance(params); + } + + if (logMethod != null) { + Object params[] = { this }; + logMethod.invoke(instance, params); + } + + return instance; + + } catch (LogConfigurationException lce) { + + // this type of exception means there was a problem in discovery + // and we've already output diagnostics about the issue, etc.; + // just pass it on + throw lce; + + } catch (InvocationTargetException e) { + // A problem occurred invoking the Constructor or Method + // previously discovered + Throwable c = e.getTargetException(); + throw new LogConfigurationException(c == null ? e : c); + } catch (Throwable t) { + handleThrowable(t); // may re-throw t + // A problem occurred invoking the Constructor or Method + // previously discovered + throw new LogConfigurationException(t); + } + } + + // ------------------------------------------------------ Private Methods + + /** + * Calls LogFactory.directGetContextClassLoader under the control of an + * AccessController class. This means that java code running under a + * security manager that forbids access to ClassLoaders will still work + * if this class is given appropriate privileges, even when the caller + * doesn't have such privileges. Without using an AccessController, the + * the entire call stack must have the privilege before the call is + * allowed. + * + * @return the context classloader associated with the current thread, + * or null if security doesn't allow it. + * + * @throws LogConfigurationException if there was some weird error while + * attempting to get the context classloader. + * + * @throws SecurityException if the current java security policy doesn't + * allow this class to access the context classloader. + */ + private static ClassLoader getContextClassLoaderInternal() + throws LogConfigurationException { + return (ClassLoader)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return LogFactory.directGetContextClassLoader(); + } + }); + } + + /** + * Read the specified system property, using an AccessController so that + * the property can be read if JCL has been granted the appropriate + * security rights even if the calling code has not. + *

+ * Take care not to expose the value returned by this method to the + * calling application in any way; otherwise the calling app can use that + * info to access data that should not be available to it. + */ + private static String getSystemProperty(final String key, final String def) + throws SecurityException { + return (String) AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return System.getProperty(key, def); + } + }); + } + + /** + * Fetch the parent classloader of a specified classloader. + *

+ * If a SecurityException occurs, null is returned. + *

+ * Note that this method is non-static merely so logDiagnostic is available. + */ + private ClassLoader getParentClassLoader(final ClassLoader cl) { + try { + return (ClassLoader)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return cl.getParent(); + } + }); + } catch (SecurityException ex) { + logDiagnostic("[SECURITY] Unable to obtain parent classloader"); + return null; + } + + } + + /** + * Utility method to check whether a particular logging library is + * present and available for use. Note that this does not + * affect the future behaviour of this class. + */ + private boolean isLogLibraryAvailable(String name, String classname) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Checking for '" + name + "'."); + } + try { + Log log = createLogFromClass( + classname, + this.getClass().getName(), // dummy category + false); + + if (log == null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Did not find '" + name + "'."); + } + return false; + } else { + if (isDiagnosticsEnabled()) { + logDiagnostic("Found '" + name + "'."); + } + return true; + } + } catch (LogConfigurationException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Logging system '" + name + "' is available but not useable."); + } + return false; + } + } + + /** + * Attempt to find an attribute (see method setAttribute) or a + * system property with the provided name and return its value. + *

+ * The attributes associated with this object are checked before + * system properties in case someone has explicitly called setAttribute, + * or a configuration property has been set in a commons-logging.properties + * file. + * + * @return the value associated with the property, or null. + */ + private String getConfigurationValue(String property) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] Trying to get configuration for item " + property); + } + + Object valueObj = getAttribute(property); + if (valueObj != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] Found LogFactory attribute [" + valueObj + "] for " + property); + } + return valueObj.toString(); + } + + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] No LogFactory attribute found for " + property); + } + + try { + // warning: minor security hole here, in that we potentially read a system + // property that the caller cannot, then output it in readable form as a + // diagnostic message. However it's only ever JCL-specific properties + // involved here, so the harm is truly trivial. + String value = getSystemProperty(property, null); + if (value != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] Found system property [" + value + "] for " + property); + } + return value; + } + + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] No system property found for property " + property); + } + } catch (SecurityException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] Security prevented reading system property " + property); + } + } + + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] No configuration defined for item " + property); + } + + return null; + } + + /** + * Get the setting for the user-configurable behaviour specified by key. + * If nothing has explicitly been set, then return dflt. + */ + private boolean getBooleanConfiguration(String key, boolean dflt) { + String val = getConfigurationValue(key); + if (val == null) { + return dflt; + } + return Boolean.valueOf(val).booleanValue(); + } + + /** + * Initialize a number of variables that control the behaviour of this + * class and that can be tweaked by the user. This is done when the first + * logger is created, not in the constructor of this class, because we + * need to give the user a chance to call method setAttribute in order to + * configure this object. + */ + private void initConfiguration() { + allowFlawedContext = getBooleanConfiguration(ALLOW_FLAWED_CONTEXT_PROPERTY, true); + allowFlawedDiscovery = getBooleanConfiguration(ALLOW_FLAWED_DISCOVERY_PROPERTY, true); + allowFlawedHierarchy = getBooleanConfiguration(ALLOW_FLAWED_HIERARCHY_PROPERTY, true); + } + + /** + * Attempts to create a Log instance for the given category name. + * Follows the discovery process described in the class javadoc. + * + * @param logCategory the name of the log category + * + * @throws LogConfigurationException if an error in discovery occurs, + * or if no adapter at all can be instantiated + */ + private Log discoverLogImplementation(String logCategory) + throws LogConfigurationException { + if (isDiagnosticsEnabled()) { + logDiagnostic("Discovering a Log implementation..."); + } + + initConfiguration(); + + Log result = null; + + // See if the user specified the Log implementation to use + String specifiedLogClassName = findUserSpecifiedLogClassName(); + + if (specifiedLogClassName != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Attempting to load user-specified log class '" + + specifiedLogClassName + "'..."); + } + + result = createLogFromClass(specifiedLogClassName, + logCategory, + true); + if (result == null) { + StringBuffer messageBuffer = new StringBuffer("User-specified log class '"); + messageBuffer.append(specifiedLogClassName); + messageBuffer.append("' cannot be found or is not useable."); + + // Mistyping or misspelling names is a common fault. + // Construct a good error message, if we can + informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LOG4J_LOGGER); + informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_JDK14_LOGGER); + informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LUMBERJACK_LOGGER); + informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_SIMPLE_LOGGER); + throw new LogConfigurationException(messageBuffer.toString()); + } + + return result; + } + + // No user specified log; try to discover what's on the classpath + // + // Note that we deliberately loop here over classesToDiscover and + // expect method createLogFromClass to loop over the possible source + // classloaders. The effect is: + // for each discoverable log adapter + // for each possible classloader + // see if it works + // + // It appears reasonable at first glance to do the opposite: + // for each possible classloader + // for each discoverable log adapter + // see if it works + // + // The latter certainly has advantages for user-installable logging + // libraries such as log4j; in a webapp for example this code should + // first check whether the user has provided any of the possible + // logging libraries before looking in the parent classloader. + // Unfortunately, however, Jdk14Logger will always work in jvm>=1.4, + // and SimpleLog will always work in any JVM. So the loop would never + // ever look for logging libraries in the parent classpath. Yet many + // users would expect that putting log4j there would cause it to be + // detected (and this is the historical JCL behaviour). So we go with + // the first approach. A user that has bundled a specific logging lib + // in a webapp should use a commons-logging.properties file or a + // service file in META-INF to force use of that logging lib anyway, + // rather than relying on discovery. + + if (isDiagnosticsEnabled()) { + logDiagnostic( + "No user-specified Log implementation; performing discovery" + + " using the standard supported logging implementations..."); + } + for(int i=0; iStringBuffer the message should be appended to, + * not null + * @param name the (trimmed) name to be test against the candidate, not null + * @param candidate the candidate name (not null) + */ + private void informUponSimilarName(final StringBuffer messageBuffer, final String name, + final String candidate) { + if (name.equals(candidate)) { + // Don't suggest a name that is exactly the same as the one the + // user tried... + return; + } + + // If the user provides a name that is in the right package, and gets + // the first 5 characters of the adapter class right (ignoring case), + // then suggest the candidate adapter class name. + if (name.regionMatches(true, 0, candidate, 0, PKG_LEN + 5)) { + messageBuffer.append(" Did you mean '"); + messageBuffer.append(candidate); + messageBuffer.append("'?"); + } + } + + /** + * Checks system properties and the attribute map for + * a Log implementation specified by the user under the + * property names {@link #LOG_PROPERTY} or {@link #LOG_PROPERTY_OLD}. + * + * @return classname specified by the user, or null + */ + private String findUserSpecifiedLogClassName() { + if (isDiagnosticsEnabled()) { + logDiagnostic("Trying to get log class from attribute '" + LOG_PROPERTY + "'"); + } + String specifiedClass = (String) getAttribute(LOG_PROPERTY); + + if (specifiedClass == null) { // @deprecated + if (isDiagnosticsEnabled()) { + logDiagnostic("Trying to get log class from attribute '" + + LOG_PROPERTY_OLD + "'"); + } + specifiedClass = (String) getAttribute(LOG_PROPERTY_OLD); + } + + if (specifiedClass == null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Trying to get log class from system property '" + + LOG_PROPERTY + "'"); + } + try { + specifiedClass = getSystemProperty(LOG_PROPERTY, null); + } catch (SecurityException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("No access allowed to system property '" + + LOG_PROPERTY + "' - " + e.getMessage()); + } + } + } + + if (specifiedClass == null) { // @deprecated + if (isDiagnosticsEnabled()) { + logDiagnostic("Trying to get log class from system property '" + + LOG_PROPERTY_OLD + "'"); + } + try { + specifiedClass = getSystemProperty(LOG_PROPERTY_OLD, null); + } catch (SecurityException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("No access allowed to system property '" + + LOG_PROPERTY_OLD + "' - " + e.getMessage()); + } + } + } + + // Remove any whitespace; it's never valid in a classname so its + // presence just means a user mistake. As we know what they meant, + // we may as well strip the spaces. + if (specifiedClass != null) { + specifiedClass = specifiedClass.trim(); + } + + return specifiedClass; + } + + /** + * Attempts to load the given class, find a suitable constructor, + * and instantiate an instance of Log. + * + * @param logAdapterClassName classname of the Log implementation + * @param logCategory argument to pass to the Log implementation's constructor + * @param affectState true if this object's state should + * be affected by this method call, false otherwise. + * @return an instance of the given class, or null if the logging + * library associated with the specified adapter is not available. + * @throws LogConfigurationException if there was a serious error with + * configuration and the handleFlawedDiscovery method decided this + * problem was fatal. + */ + private Log createLogFromClass(String logAdapterClassName, + String logCategory, + boolean affectState) + throws LogConfigurationException { + + if (isDiagnosticsEnabled()) { + logDiagnostic("Attempting to instantiate '" + logAdapterClassName + "'"); + } + + Object[] params = { logCategory }; + Log logAdapter = null; + Constructor constructor = null; + + Class logAdapterClass = null; + ClassLoader currentCL = getBaseClassLoader(); + + for(;;) { + // Loop through the classloader hierarchy trying to find + // a viable classloader. + logDiagnostic("Trying to load '" + logAdapterClassName + "' from classloader " + objectId(currentCL)); + try { + if (isDiagnosticsEnabled()) { + // Show the location of the first occurrence of the .class file + // in the classpath. This is the location that ClassLoader.loadClass + // will load the class from -- unless the classloader is doing + // something weird. + URL url; + String resourceName = logAdapterClassName.replace('.', '/') + ".class"; + if (currentCL != null) { + url = currentCL.getResource(resourceName ); + } else { + url = ClassLoader.getSystemResource(resourceName + ".class"); + } + + if (url == null) { + logDiagnostic("Class '" + logAdapterClassName + "' [" + resourceName + "] cannot be found."); + } else { + logDiagnostic("Class '" + logAdapterClassName + "' was found at '" + url + "'"); + } + } + + Class c; + try { + c = Class.forName(logAdapterClassName, true, currentCL); + } catch (ClassNotFoundException originalClassNotFoundException) { + // The current classloader was unable to find the log adapter + // in this or any ancestor classloader. There's no point in + // trying higher up in the hierarchy in this case.. + String msg = originalClassNotFoundException.getMessage(); + logDiagnostic("The log adapter '" + logAdapterClassName + "' is not available via classloader " + + objectId(currentCL) + ": " + msg.trim()); + try { + // Try the class classloader. + // This may work in cases where the TCCL + // does not contain the code executed or JCL. + // This behaviour indicates that the application + // classloading strategy is not consistent with the + // Java 1.2 classloading guidelines but JCL can + // and so should handle this case. + c = Class.forName(logAdapterClassName); + } catch (ClassNotFoundException secondaryClassNotFoundException) { + // no point continuing: this adapter isn't available + msg = secondaryClassNotFoundException.getMessage(); + logDiagnostic("The log adapter '" + logAdapterClassName + + "' is not available via the LogFactoryImpl class classloader: " + msg.trim()); + break; + } + } + + constructor = c.getConstructor(logConstructorSignature); + Object o = constructor.newInstance(params); + + // Note that we do this test after trying to create an instance + // [rather than testing Log.class.isAssignableFrom(c)] so that + // we don't complain about Log hierarchy problems when the + // adapter couldn't be instantiated anyway. + if (o instanceof Log) { + logAdapterClass = c; + logAdapter = (Log) o; + break; + } + + // Oops, we have a potential problem here. An adapter class + // has been found and its underlying lib is present too, but + // there are multiple Log interface classes available making it + // impossible to cast to the type the caller wanted. We + // certainly can't use this logger, but we need to know whether + // to keep on discovering or terminate now. + // + // The handleFlawedHierarchy method will throw + // LogConfigurationException if it regards this problem as + // fatal, and just return if not. + handleFlawedHierarchy(currentCL, c); + } catch (NoClassDefFoundError e) { + // We were able to load the adapter but it had references to + // other classes that could not be found. This simply means that + // the underlying logger library is not present in this or any + // ancestor classloader. There's no point in trying higher up + // in the hierarchy in this case.. + String msg = e.getMessage(); + logDiagnostic("The log adapter '" + logAdapterClassName + + "' is missing dependencies when loaded via classloader " + objectId(currentCL) + + ": " + msg.trim()); + break; + } catch (ExceptionInInitializerError e) { + // A static initializer block or the initializer code associated + // with a static variable on the log adapter class has thrown + // an exception. + // + // We treat this as meaning the adapter's underlying logging + // library could not be found. + String msg = e.getMessage(); + logDiagnostic("The log adapter '" + logAdapterClassName + + "' is unable to initialize itself when loaded via classloader " + objectId(currentCL) + + ": " + msg.trim()); + break; + } catch (LogConfigurationException e) { + // call to handleFlawedHierarchy above must have thrown + // a LogConfigurationException, so just throw it on + throw e; + } catch (Throwable t) { + handleThrowable(t); // may re-throw t + // handleFlawedDiscovery will determine whether this is a fatal + // problem or not. If it is fatal, then a LogConfigurationException + // will be thrown. + handleFlawedDiscovery(logAdapterClassName, currentCL, t); + } + + if (currentCL == null) { + break; + } + + // try the parent classloader + // currentCL = currentCL.getParent(); + currentCL = getParentClassLoader(currentCL); + } + + if (logAdapterClass != null && affectState) { + // We've succeeded, so set instance fields + this.logClassName = logAdapterClassName; + this.logConstructor = constructor; + + // Identify the setLogFactory method (if there is one) + try { + this.logMethod = logAdapterClass.getMethod("setLogFactory", logMethodSignature); + logDiagnostic("Found method setLogFactory(LogFactory) in '" + logAdapterClassName + "'"); + } catch (Throwable t) { + handleThrowable(t); // may re-throw t + this.logMethod = null; + logDiagnostic("[INFO] '" + logAdapterClassName + "' from classloader " + objectId(currentCL) + + " does not declare optional method " + "setLogFactory(LogFactory)"); + } + + logDiagnostic("Log adapter '" + logAdapterClassName + "' from classloader " + + objectId(logAdapterClass.getClassLoader()) + " has been selected for use."); + } + + return logAdapter; + } + + /** + * Return the classloader from which we should try to load the logging + * adapter classes. + *

+ * This method usually returns the context classloader. However if it + * is discovered that the classloader which loaded this class is a child + * of the context classloader and the allowFlawedContext option + * has been set then the classloader which loaded this class is returned + * instead. + *

+ * The only time when the classloader which loaded this class is a + * descendant (rather than the same as or an ancestor of the context + * classloader) is when an app has created custom classloaders but + * failed to correctly set the context classloader. This is a bug in + * the calling application; however we provide the option for JCL to + * simply generate a warning rather than fail outright. + * + */ + private ClassLoader getBaseClassLoader() throws LogConfigurationException { + ClassLoader thisClassLoader = getClassLoader(LogFactoryImpl.class); + + if (!useTCCL) { + return thisClassLoader; + } + + ClassLoader contextClassLoader = getContextClassLoaderInternal(); + + ClassLoader baseClassLoader = getLowestClassLoader( + contextClassLoader, thisClassLoader); + + if (baseClassLoader == null) { + // The two classloaders are not part of a parent child relationship. + // In some classloading setups (e.g. JBoss with its + // UnifiedLoaderRepository) this can still work, so if user hasn't + // forbidden it, just return the contextClassLoader. + if (allowFlawedContext) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[WARNING] the context classloader is not part of a" + + " parent-child relationship with the classloader that" + + " loaded LogFactoryImpl."); + } + // If contextClassLoader were null, getLowestClassLoader() would + // have returned thisClassLoader. The fact we are here means + // contextClassLoader is not null, so we can just return it. + return contextClassLoader; + } + else { + throw new LogConfigurationException("Bad classloader hierarchy; LogFactoryImpl was loaded via" + + " a classloader that is not related to the current context" + + " classloader."); + } + } + + if (baseClassLoader != contextClassLoader) { + // We really should just use the contextClassLoader as the starting + // point for scanning for log adapter classes. However it is expected + // that there are a number of broken systems out there which create + // custom classloaders but fail to set the context classloader so + // we handle those flawed systems anyway. + if (allowFlawedContext) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "Warning: the context classloader is an ancestor of the" + + " classloader that loaded LogFactoryImpl; it should be" + + " the same or a descendant. The application using" + + " commons-logging should ensure the context classloader" + + " is used correctly."); + } + } else { + throw new LogConfigurationException( + "Bad classloader hierarchy; LogFactoryImpl was loaded via" + + " a classloader that is not related to the current context" + + " classloader."); + } + } + + return baseClassLoader; + } + + /** + * Given two related classloaders, return the one which is a child of + * the other. + *

+ * @param c1 is a classloader (including the null classloader) + * @param c2 is a classloader (including the null classloader) + * + * @return c1 if it has c2 as an ancestor, c2 if it has c1 as an ancestor, + * and null if neither is an ancestor of the other. + */ + private ClassLoader getLowestClassLoader(ClassLoader c1, ClassLoader c2) { + // TODO: use AccessController when dealing with classloaders here + + if (c1 == null) { + return c2; + } + + if (c2 == null) { + return c1; + } + + ClassLoader current; + + // scan c1's ancestors to find c2 + current = c1; + while (current != null) { + if (current == c2) { + return c1; + } + // current = current.getParent(); + current = getParentClassLoader(current); + } + + // scan c2's ancestors to find c1 + current = c2; + while (current != null) { + if (current == c1) { + return c2; + } + // current = current.getParent(); + current = getParentClassLoader(current); + } + + return null; + } + + /** + * Generates an internal diagnostic logging of the discovery failure and + * then throws a LogConfigurationException that wraps + * the passed Throwable. + * + * @param logAdapterClassName is the class name of the Log implementation + * that could not be instantiated. Cannot be null. + * + * @param classLoader is the classloader that we were trying to load the + * logAdapterClassName from when the exception occurred. + * + * @param discoveryFlaw is the Throwable created by the classloader + * + * @throws LogConfigurationException ALWAYS + */ + private void handleFlawedDiscovery(String logAdapterClassName, + ClassLoader classLoader, // USED? + Throwable discoveryFlaw) { + + if (isDiagnosticsEnabled()) { + logDiagnostic("Could not instantiate Log '" + + logAdapterClassName + "' -- " + + discoveryFlaw.getClass().getName() + ": " + + discoveryFlaw.getLocalizedMessage()); + + if (discoveryFlaw instanceof InvocationTargetException ) { + // Ok, the lib is there but while trying to create a real underlying + // logger something failed in the underlying lib; display info about + // that if possible. + InvocationTargetException ite = (InvocationTargetException)discoveryFlaw; + Throwable cause = ite.getTargetException(); + if (cause != null) { + logDiagnostic("... InvocationTargetException: " + + cause.getClass().getName() + ": " + + cause.getLocalizedMessage()); + + if (cause instanceof ExceptionInInitializerError) { + ExceptionInInitializerError eiie = (ExceptionInInitializerError)cause; + Throwable cause2 = eiie.getException(); + if (cause2 != null) { + final StringWriter sw = new StringWriter(); + cause2.printStackTrace(new PrintWriter(sw, true)); + logDiagnostic("... ExceptionInInitializerError: " + sw.toString()); + } + } + } + } + } + + if (!allowFlawedDiscovery) { + throw new LogConfigurationException(discoveryFlaw); + } + } + + /** + * Report a problem loading the log adapter, then either return + * (if the situation is considered recoverable) or throw a + * LogConfigurationException. + *

+ * There are two possible reasons why we successfully loaded the + * specified log adapter class then failed to cast it to a Log object: + *

    + *
  1. the specific class just doesn't implement the Log interface + * (user screwed up), or + *
  2. the specified class has bound to a Log class loaded by some other + * classloader; Log@classloaderX cannot be cast to Log@classloaderY. + *
+ *

+ * Here we try to figure out which case has occurred so we can give the + * user some reasonable feedback. + * + * @param badClassLoader is the classloader we loaded the problem class from, + * ie it is equivalent to badClass.getClassLoader(). + * + * @param badClass is a Class object with the desired name, but which + * does not implement Log correctly. + * + * @throws LogConfigurationException when the situation + * should not be recovered from. + */ + private void handleFlawedHierarchy(ClassLoader badClassLoader, Class badClass) + throws LogConfigurationException { + + boolean implementsLog = false; + String logInterfaceName = Log.class.getName(); + Class interfaces[] = badClass.getInterfaces(); + for (int i = 0; i < interfaces.length; i++) { + if (logInterfaceName.equals(interfaces[i].getName())) { + implementsLog = true; + break; + } + } + + if (implementsLog) { + // the class does implement an interface called Log, but + // it is in the wrong classloader + if (isDiagnosticsEnabled()) { + try { + ClassLoader logInterfaceClassLoader = getClassLoader(Log.class); + logDiagnostic("Class '" + badClass.getName() + "' was found in classloader " + + objectId(badClassLoader) + ". It is bound to a Log interface which is not" + + " the one loaded from classloader " + objectId(logInterfaceClassLoader)); + } catch (Throwable t) { + handleThrowable(t); // may re-throw t + logDiagnostic("Error while trying to output diagnostics about" + " bad class '" + badClass + "'"); + } + } + + if (!allowFlawedHierarchy) { + StringBuffer msg = new StringBuffer(); + msg.append("Terminating logging for this context "); + msg.append("due to bad log hierarchy. "); + msg.append("You have more than one version of '"); + msg.append(Log.class.getName()); + msg.append("' visible."); + if (isDiagnosticsEnabled()) { + logDiagnostic(msg.toString()); + } + throw new LogConfigurationException(msg.toString()); + } + + if (isDiagnosticsEnabled()) { + StringBuffer msg = new StringBuffer(); + msg.append("Warning: bad log hierarchy. "); + msg.append("You have more than one version of '"); + msg.append(Log.class.getName()); + msg.append("' visible."); + logDiagnostic(msg.toString()); + } + } else { + // this is just a bad adapter class + if (!allowFlawedDiscovery) { + StringBuffer msg = new StringBuffer(); + msg.append("Terminating logging for this context. "); + msg.append("Log class '"); + msg.append(badClass.getName()); + msg.append("' does not implement the Log interface."); + if (isDiagnosticsEnabled()) { + logDiagnostic(msg.toString()); + } + + throw new LogConfigurationException(msg.toString()); + } + + if (isDiagnosticsEnabled()) { + StringBuffer msg = new StringBuffer(); + msg.append("[WARNING] Log class '"); + msg.append(badClass.getName()); + msg.append("' does not implement the Log interface."); + logDiagnostic(msg.toString()); + } + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/LogKitLogger.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/LogKitLogger.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/LogKitLogger.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/LogKitLogger.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,269 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + +import java.io.Serializable; +import org.apache.log.Logger; +import org.apache.log.Hierarchy; +import org.apache.commons.logging.Log; + +/** + * Implementation of org.apache.commons.logging.Log + * that wraps the avalon-logkit + * logging system. Configuration of LogKit is left to the user. + *

+ * LogKit accepts only String messages. + * Therefore, this implementation converts object messages into strings + * by called their toString() method before logging them. + * + * @version $Id: LogKitLogger.java 1448119 2013-02-20 12:28:04Z tn $ + */ +public class LogKitLogger implements Log, Serializable { + + /** Serializable version identifier. */ + private static final long serialVersionUID = 3768538055836059519L; + + // ------------------------------------------------------------- Attributes + + /** Logging goes to this LogKit logger */ + protected transient volatile Logger logger = null; + + /** Name of this logger */ + protected String name = null; + + // ------------------------------------------------------------ Constructor + + /** + * Construct LogKitLogger which wraps the LogKit + * logger with given name. + * + * @param name log name + */ + public LogKitLogger(String name) { + this.name = name; + this.logger = getLogger(); + } + + // --------------------------------------------------------- Public Methods + + /** + * Return the underlying Logger we are using. + */ + public Logger getLogger() { + Logger result = logger; + if (result == null) { + synchronized(this) { + result = logger; + if (result == null) { + logger = result = Hierarchy.getDefaultHierarchy().getLoggerFor(name); + } + } + } + return result; + } + + // ----------------------------------------------------- Log Implementation + + /** + * Logs a message with org.apache.log.Priority.DEBUG. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public void trace(Object message) { + debug(message); + } + + /** + * Logs a message with org.apache.log.Priority.DEBUG. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public void trace(Object message, Throwable t) { + debug(message, t); + } + + /** + * Logs a message with org.apache.log.Priority.DEBUG. + * + * @param message to log + * @see org.apache.commons.logging.Log#debug(Object) + */ + public void debug(Object message) { + if (message != null) { + getLogger().debug(String.valueOf(message)); + } + } + + /** + * Logs a message with org.apache.log.Priority.DEBUG. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public void debug(Object message, Throwable t) { + if (message != null) { + getLogger().debug(String.valueOf(message), t); + } + } + + /** + * Logs a message with org.apache.log.Priority.INFO. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public void info(Object message) { + if (message != null) { + getLogger().info(String.valueOf(message)); + } + } + + /** + * Logs a message with org.apache.log.Priority.INFO. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public void info(Object message, Throwable t) { + if (message != null) { + getLogger().info(String.valueOf(message), t); + } + } + + /** + * Logs a message with org.apache.log.Priority.WARN. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public void warn(Object message) { + if (message != null) { + getLogger().warn(String.valueOf(message)); + } + } + + /** + * Logs a message with org.apache.log.Priority.WARN. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public void warn(Object message, Throwable t) { + if (message != null) { + getLogger().warn(String.valueOf(message), t); + } + } + + /** + * Logs a message with org.apache.log.Priority.ERROR. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public void error(Object message) { + if (message != null) { + getLogger().error(String.valueOf(message)); + } + } + + /** + * Logs a message with org.apache.log.Priority.ERROR. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public void error(Object message, Throwable t) { + if (message != null) { + getLogger().error(String.valueOf(message), t); + } + } + + /** + * Logs a message with org.apache.log.Priority.FATAL_ERROR. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public void fatal(Object message) { + if (message != null) { + getLogger().fatalError(String.valueOf(message)); + } + } + + /** + * Logs a message with org.apache.log.Priority.FATAL_ERROR. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public void fatal(Object message, Throwable t) { + if (message != null) { + getLogger().fatalError(String.valueOf(message), t); + } + } + + /** + * Checks whether the LogKit logger will log messages of priority DEBUG. + */ + public boolean isDebugEnabled() { + return getLogger().isDebugEnabled(); + } + + /** + * Checks whether the LogKit logger will log messages of priority ERROR. + */ + public boolean isErrorEnabled() { + return getLogger().isErrorEnabled(); + } + + /** + * Checks whether the LogKit logger will log messages of priority FATAL_ERROR. + */ + public boolean isFatalEnabled() { + return getLogger().isFatalErrorEnabled(); + } + + /** + * Checks whether the LogKit logger will log messages of priority INFO. + */ + public boolean isInfoEnabled() { + return getLogger().isInfoEnabled(); + } + + /** + * Checks whether the LogKit logger will log messages of priority DEBUG. + */ + public boolean isTraceEnabled() { + return getLogger().isDebugEnabled(); + } + + /** + * Checks whether the LogKit logger will log messages of priority WARN. + */ + public boolean isWarnEnabled() { + return getLogger().isWarnEnabled(); + } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/NoOpLog.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/NoOpLog.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/NoOpLog.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/NoOpLog.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + +import java.io.Serializable; +import org.apache.commons.logging.Log; + +/** + * Trivial implementation of Log that throws away all messages. No + * configurable system properties are supported. + * + * @version $Id: NoOpLog.java 1432663 2013-01-13 17:24:18Z tn $ + */ +public class NoOpLog implements Log, Serializable { + + /** Serializable version identifier. */ + private static final long serialVersionUID = 561423906191706148L; + + /** Convenience constructor */ + public NoOpLog() { } + /** Base constructor */ + public NoOpLog(String name) { } + /** Do nothing */ + public void trace(Object message) { } + /** Do nothing */ + public void trace(Object message, Throwable t) { } + /** Do nothing */ + public void debug(Object message) { } + /** Do nothing */ + public void debug(Object message, Throwable t) { } + /** Do nothing */ + public void info(Object message) { } + /** Do nothing */ + public void info(Object message, Throwable t) { } + /** Do nothing */ + public void warn(Object message) { } + /** Do nothing */ + public void warn(Object message, Throwable t) { } + /** Do nothing */ + public void error(Object message) { } + /** Do nothing */ + public void error(Object message, Throwable t) { } + /** Do nothing */ + public void fatal(Object message) { } + /** Do nothing */ + public void fatal(Object message, Throwable t) { } + + /** + * Debug is never enabled. + * + * @return false + */ + public final boolean isDebugEnabled() { return false; } + + /** + * Error is never enabled. + * + * @return false + */ + public final boolean isErrorEnabled() { return false; } + + /** + * Fatal is never enabled. + * + * @return false + */ + public final boolean isFatalEnabled() { return false; } + + /** + * Info is never enabled. + * + * @return false + */ + public final boolean isInfoEnabled() { return false; } + + /** + * Trace is never enabled. + * + * @return false + */ + public final boolean isTraceEnabled() { return false; } + + /** + * Warn is never enabled. + * + * @return false + */ + public final boolean isWarnEnabled() { return false; } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/ServletContextCleaner.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/ServletContextCleaner.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/ServletContextCleaner.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/ServletContextCleaner.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.apache.commons.logging.LogFactory; + +/** + * This class is capable of receiving notifications about the undeployment of + * a webapp, and responds by ensuring that commons-logging releases all + * memory associated with the undeployed webapp. + *

+ * In general, the WeakHashtable support added in commons-logging release 1.1 + * ensures that logging classes do not hold references that prevent an + * undeployed webapp's memory from being garbage-collected even when multiple + * copies of commons-logging are deployed via multiple classloaders (a + * situation that earlier versions had problems with). However there are + * some rare cases where the WeakHashtable approach does not work; in these + * situations specifying this class as a listener for the web application will + * ensure that all references held by commons-logging are fully released. + *

+ * To use this class, configure the webapp deployment descriptor to call + * this class on webapp undeploy; the contextDestroyed method will tell + * every accessible LogFactory class that the entry in its map for the + * current webapp's context classloader should be cleared. + * + * @version $Id: ServletContextCleaner.java 1432580 2013-01-13 10:41:05Z tn $ + * @since 1.1 + */ +public class ServletContextCleaner implements ServletContextListener { + + private static final Class[] RELEASE_SIGNATURE = {ClassLoader.class}; + + /** + * Invoked when a webapp is undeployed, this tells the LogFactory + * class to release any logging information related to the current + * contextClassloader. + */ + public void contextDestroyed(ServletContextEvent sce) { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + + Object[] params = new Object[1]; + params[0] = tccl; + + // Walk up the tree of classloaders, finding all the available + // LogFactory classes and releasing any objects associated with + // the tccl (ie the webapp). + // + // When there is only one LogFactory in the classpath, and it + // is within the webapp being undeployed then there is no problem; + // garbage collection works fine. + // + // When there are multiple LogFactory classes in the classpath but + // parent-first classloading is used everywhere, this loop is really + // short. The first instance of LogFactory found will + // be the highest in the classpath, and then no more will be found. + // This is ok, as with this setup this will be the only LogFactory + // holding any data associated with the tccl being released. + // + // When there are multiple LogFactory classes in the classpath and + // child-first classloading is used in any classloader, then multiple + // LogFactory instances may hold info about this TCCL; whenever the + // webapp makes a call into a class loaded via an ancestor classloader + // and that class calls LogFactory the tccl gets registered in + // the LogFactory instance that is visible from the ancestor + // classloader. However the concrete logging library it points + // to is expected to have been loaded via the TCCL, so the + // underlying logging lib is only initialised/configured once. + // These references from ancestor LogFactory classes down to + // TCCL classloaders are held via weak references and so should + // be released but there are circumstances where they may not. + // Walking up the classloader ancestry ladder releasing + // the current tccl at each level tree, though, will definitely + // clear any problem references. + ClassLoader loader = tccl; + while (loader != null) { + // Load via the current loader. Note that if the class is not accessible + // via this loader, but is accessible via some ancestor then that class + // will be returned. + try { + Class logFactoryClass = loader.loadClass("org.apache.commons.logging.LogFactory"); + Method releaseMethod = logFactoryClass.getMethod("release", RELEASE_SIGNATURE); + releaseMethod.invoke(null, params); + loader = logFactoryClass.getClassLoader().getParent(); + } catch(ClassNotFoundException ex) { + // Neither the current classloader nor any of its ancestors could find + // the LogFactory class, so we can stop now. + loader = null; + } catch(NoSuchMethodException ex) { + // This is not expected; every version of JCL has this method + System.err.println("LogFactory instance found which does not support release method!"); + loader = null; + } catch(IllegalAccessException ex) { + // This is not expected; every ancestor class should be accessible + System.err.println("LogFactory instance found which is not accessable!"); + loader = null; + } catch(InvocationTargetException ex) { + // This is not expected + System.err.println("LogFactory instance release method failed!"); + loader = null; + } + } + + // Just to be sure, invoke release on the LogFactory that is visible from + // this ServletContextCleaner class too. This should already have been caught + // by the above loop but just in case... + LogFactory.release(tccl); + } + + /** + * Invoked when a webapp is deployed. Nothing needs to be done here. + */ + public void contextInitialized(ServletContextEvent sce) { + // do nothing + } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/SimpleLog.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/SimpleLog.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/SimpleLog.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/SimpleLog.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,649 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + +import java.io.InputStream; +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogConfigurationException; + +/** + * Simple implementation of Log that sends all enabled log messages, + * for all defined loggers, to System.err. The following system properties + * are supported to configure the behavior of this logger: + *

    + *
  • org.apache.commons.logging.simplelog.defaultlog - + * Default logging detail level for all instances of SimpleLog. + * Must be one of ("trace", "debug", "info", "warn", "error", or "fatal"). + * If not specified, defaults to "info".
  • + *
  • org.apache.commons.logging.simplelog.log.xxxxx - + * Logging detail level for a SimpleLog instance named "xxxxx". + * Must be one of ("trace", "debug", "info", "warn", "error", or "fatal"). + * If not specified, the default logging detail level is used.
  • + *
  • org.apache.commons.logging.simplelog.showlogname - + * Set to true if you want the Log instance name to be + * included in output messages. Defaults to false.
  • + *
  • org.apache.commons.logging.simplelog.showShortLogname - + * Set to true if you want the last component of the name to be + * included in output messages. Defaults to true.
  • + *
  • org.apache.commons.logging.simplelog.showdatetime - + * Set to true if you want the current date and time + * to be included in output messages. Default is false.
  • + *
  • org.apache.commons.logging.simplelog.dateTimeFormat - + * The date and time format to be used in the output messages. + * The pattern describing the date and time format is the same that is + * used in java.text.SimpleDateFormat. If the format is not + * specified or is invalid, the default format is used. + * The default format is yyyy/MM/dd HH:mm:ss:SSS zzz.
  • + *
+ *

+ * In addition to looking for system properties with the names specified + * above, this implementation also checks for a class loader resource named + * "simplelog.properties", and includes any matching definitions + * from this resource (if it exists). + * + * @version $Id: SimpleLog.java 1435115 2013-01-18 12:40:19Z tn $ + */ +public class SimpleLog implements Log, Serializable { + + /** Serializable version identifier. */ + private static final long serialVersionUID = 136942970684951178L; + + // ------------------------------------------------------- Class Attributes + + /** All system properties used by SimpleLog start with this */ + static protected final String systemPrefix = "org.apache.commons.logging.simplelog."; + + /** Properties loaded from simplelog.properties */ + static protected final Properties simpleLogProps = new Properties(); + + /** The default format to use when formating dates */ + static protected final String DEFAULT_DATE_TIME_FORMAT = "yyyy/MM/dd HH:mm:ss:SSS zzz"; + + /** Include the instance name in the log message? */ + static volatile protected boolean showLogName = false; + + /** Include the short name ( last component ) of the logger in the log + * message. Defaults to true - otherwise we'll be lost in a flood of + * messages without knowing who sends them. + */ + static volatile protected boolean showShortName = true; + + /** Include the current time in the log message */ + static volatile protected boolean showDateTime = false; + + /** The date and time format to use in the log message */ + static volatile protected String dateTimeFormat = DEFAULT_DATE_TIME_FORMAT; + + /** + * Used to format times. + *

+ * Any code that accesses this object should first obtain a lock on it, + * ie use synchronized(dateFormatter); this requirement was introduced + * in 1.1.1 to fix an existing thread safety bug (SimpleDateFormat.format + * is not thread-safe). + */ + static protected DateFormat dateFormatter = null; + + // ---------------------------------------------------- Log Level Constants + + /** "Trace" level logging. */ + public static final int LOG_LEVEL_TRACE = 1; + /** "Debug" level logging. */ + public static final int LOG_LEVEL_DEBUG = 2; + /** "Info" level logging. */ + public static final int LOG_LEVEL_INFO = 3; + /** "Warn" level logging. */ + public static final int LOG_LEVEL_WARN = 4; + /** "Error" level logging. */ + public static final int LOG_LEVEL_ERROR = 5; + /** "Fatal" level logging. */ + public static final int LOG_LEVEL_FATAL = 6; + + /** Enable all logging levels */ + public static final int LOG_LEVEL_ALL = LOG_LEVEL_TRACE - 1; + + /** Enable no logging levels */ + public static final int LOG_LEVEL_OFF = LOG_LEVEL_FATAL + 1; + + // ------------------------------------------------------------ Initializer + + private static String getStringProperty(String name) { + String prop = null; + try { + prop = System.getProperty(name); + } catch (SecurityException e) { + // Ignore + } + return prop == null ? simpleLogProps.getProperty(name) : prop; + } + + private static String getStringProperty(String name, String dephault) { + String prop = getStringProperty(name); + return prop == null ? dephault : prop; + } + + private static boolean getBooleanProperty(String name, boolean dephault) { + String prop = getStringProperty(name); + return prop == null ? dephault : "true".equalsIgnoreCase(prop); + } + + // Initialize class attributes. + // Load properties file, if found. + // Override with system properties. + static { + // Add props from the resource simplelog.properties + InputStream in = getResourceAsStream("simplelog.properties"); + if(null != in) { + try { + simpleLogProps.load(in); + in.close(); + } catch(java.io.IOException e) { + // ignored + } + } + + showLogName = getBooleanProperty(systemPrefix + "showlogname", showLogName); + showShortName = getBooleanProperty(systemPrefix + "showShortLogname", showShortName); + showDateTime = getBooleanProperty(systemPrefix + "showdatetime", showDateTime); + + if(showDateTime) { + dateTimeFormat = getStringProperty(systemPrefix + "dateTimeFormat", + dateTimeFormat); + try { + dateFormatter = new SimpleDateFormat(dateTimeFormat); + } catch(IllegalArgumentException e) { + // If the format pattern is invalid - use the default format + dateTimeFormat = DEFAULT_DATE_TIME_FORMAT; + dateFormatter = new SimpleDateFormat(dateTimeFormat); + } + } + } + + // ------------------------------------------------------------- Attributes + + /** The name of this simple log instance */ + protected volatile String logName = null; + /** The current log level */ + protected volatile int currentLogLevel; + /** The short name of this simple log instance */ + private volatile String shortLogName = null; + + // ------------------------------------------------------------ Constructor + + /** + * Construct a simple log with given name. + * + * @param name log name + */ + public SimpleLog(String name) { + logName = name; + + // Set initial log level + // Used to be: set default log level to ERROR + // IMHO it should be lower, but at least info ( costin ). + setLevel(SimpleLog.LOG_LEVEL_INFO); + + // Set log level from properties + String lvl = getStringProperty(systemPrefix + "log." + logName); + int i = String.valueOf(name).lastIndexOf("."); + while(null == lvl && i > -1) { + name = name.substring(0,i); + lvl = getStringProperty(systemPrefix + "log." + name); + i = String.valueOf(name).lastIndexOf("."); + } + + if(null == lvl) { + lvl = getStringProperty(systemPrefix + "defaultlog"); + } + + if("all".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_ALL); + } else if("trace".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_TRACE); + } else if("debug".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_DEBUG); + } else if("info".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_INFO); + } else if("warn".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_WARN); + } else if("error".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_ERROR); + } else if("fatal".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_FATAL); + } else if("off".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_OFF); + } + } + + // -------------------------------------------------------- Properties + + /** + * Set logging level. + * + * @param currentLogLevel new logging level + */ + public void setLevel(int currentLogLevel) { + this.currentLogLevel = currentLogLevel; + } + + /** + * Get logging level. + */ + public int getLevel() { + return currentLogLevel; + } + + // -------------------------------------------------------- Logging Methods + + /** + * Do the actual logging. + *

+ * This method assembles the message and then calls write() + * to cause it to be written. + * + * @param type One of the LOG_LEVEL_XXX constants defining the log level + * @param message The message itself (typically a String) + * @param t The exception whose stack trace should be logged + */ + protected void log(int type, Object message, Throwable t) { + // Use a string buffer for better performance + final StringBuffer buf = new StringBuffer(); + + // Append date-time if so configured + if(showDateTime) { + final Date now = new Date(); + String dateText; + synchronized(dateFormatter) { + dateText = dateFormatter.format(now); + } + buf.append(dateText); + buf.append(" "); + } + + // Append a readable representation of the log level + switch(type) { + case SimpleLog.LOG_LEVEL_TRACE: buf.append("[TRACE] "); break; + case SimpleLog.LOG_LEVEL_DEBUG: buf.append("[DEBUG] "); break; + case SimpleLog.LOG_LEVEL_INFO: buf.append("[INFO] "); break; + case SimpleLog.LOG_LEVEL_WARN: buf.append("[WARN] "); break; + case SimpleLog.LOG_LEVEL_ERROR: buf.append("[ERROR] "); break; + case SimpleLog.LOG_LEVEL_FATAL: buf.append("[FATAL] "); break; + } + + // Append the name of the log instance if so configured + if(showShortName) { + if(shortLogName == null) { + // Cut all but the last component of the name for both styles + final String slName = logName.substring(logName.lastIndexOf(".") + 1); + shortLogName = slName.substring(slName.lastIndexOf("/") + 1); + } + buf.append(String.valueOf(shortLogName)).append(" - "); + } else if(showLogName) { + buf.append(String.valueOf(logName)).append(" - "); + } + + // Append the message + buf.append(String.valueOf(message)); + + // Append stack trace if not null + if(t != null) { + buf.append(" <"); + buf.append(t.toString()); + buf.append(">"); + + final java.io.StringWriter sw = new java.io.StringWriter(1024); + final java.io.PrintWriter pw = new java.io.PrintWriter(sw); + t.printStackTrace(pw); + pw.close(); + buf.append(sw.toString()); + } + + // Print to the appropriate destination + write(buf); + } + + /** + * Write the content of the message accumulated in the specified + * StringBuffer to the appropriate output destination. The + * default implementation writes to System.err. + * + * @param buffer A StringBuffer containing the accumulated + * text to be logged + */ + protected void write(StringBuffer buffer) { + System.err.println(buffer.toString()); + } + + /** + * Is the given log level currently enabled? + * + * @param logLevel is this level enabled? + */ + protected boolean isLevelEnabled(int logLevel) { + // log level are numerically ordered so can use simple numeric + // comparison + return logLevel >= currentLogLevel; + } + + // -------------------------------------------------------- Log Implementation + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG. + * + * @param message to log + * @see org.apache.commons.logging.Log#debug(Object) + */ + public final void debug(Object message) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) { + log(SimpleLog.LOG_LEVEL_DEBUG, message, null); + } + } + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public final void debug(Object message, Throwable t) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) { + log(SimpleLog.LOG_LEVEL_DEBUG, message, t); + } + } + + /** + * Logs a message with org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public final void trace(Object message) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) { + log(SimpleLog.LOG_LEVEL_TRACE, message, null); + } + } + + /** + * Logs a message with org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public final void trace(Object message, Throwable t) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) { + log(SimpleLog.LOG_LEVEL_TRACE, message, t); + } + } + + /** + * Logs a message with org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public final void info(Object message) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) { + log(SimpleLog.LOG_LEVEL_INFO,message,null); + } + } + + /** + * Logs a message with org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public final void info(Object message, Throwable t) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) { + log(SimpleLog.LOG_LEVEL_INFO, message, t); + } + } + + /** + * Logs a message with org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public final void warn(Object message) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) { + log(SimpleLog.LOG_LEVEL_WARN, message, null); + } + } + + /** + * Logs a message with org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public final void warn(Object message, Throwable t) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) { + log(SimpleLog.LOG_LEVEL_WARN, message, t); + } + } + + /** + * Logs a message with org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public final void error(Object message) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) { + log(SimpleLog.LOG_LEVEL_ERROR, message, null); + } + } + + /** + * Logs a message with org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public final void error(Object message, Throwable t) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) { + log(SimpleLog.LOG_LEVEL_ERROR, message, t); + } + } + + /** + * Log a message with org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public final void fatal(Object message) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) { + log(SimpleLog.LOG_LEVEL_FATAL, message, null); + } + } + + /** + * Logs a message with org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public final void fatal(Object message, Throwable t) { + if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) { + log(SimpleLog.LOG_LEVEL_FATAL, message, t); + } + } + + /** + * Are debug messages currently enabled? + *

+ * This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger. + */ + public final boolean isDebugEnabled() { + return isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG); + } + + /** + * Are error messages currently enabled? + *

+ * This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger. + */ + public final boolean isErrorEnabled() { + return isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR); + } + + /** + * Are fatal messages currently enabled? + *

+ * This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger. + */ + public final boolean isFatalEnabled() { + return isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL); + } + + /** + * Are info messages currently enabled? + *

+ * This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger. + */ + public final boolean isInfoEnabled() { + return isLevelEnabled(SimpleLog.LOG_LEVEL_INFO); + } + + /** + * Are trace messages currently enabled? + *

+ * This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger. + */ + public final boolean isTraceEnabled() { + return isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE); + } + + /** + * Are warn messages currently enabled? + *

+ * This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger. + */ + public final boolean isWarnEnabled() { + return isLevelEnabled(SimpleLog.LOG_LEVEL_WARN); + } + + /** + * Return the thread context class loader if available. + * Otherwise return null. + * + * The thread context class loader is available for JDK 1.2 + * or later, if certain security conditions are met. + * + * @exception LogConfigurationException if a suitable class loader + * cannot be identified. + */ + private static ClassLoader getContextClassLoader() { + ClassLoader classLoader = null; + + try { + // Are we running on a JDK 1.2 or later system? + final Method method = Thread.class.getMethod("getContextClassLoader", (Class[]) null); + + // Get the thread context class loader (if there is one) + try { + classLoader = (ClassLoader)method.invoke(Thread.currentThread(), (Class[]) null); + } catch (IllegalAccessException e) { + // ignore + } catch (InvocationTargetException e) { + /** + * InvocationTargetException is thrown by 'invoke' when + * the method being invoked (getContextClassLoader) throws + * an exception. + * + * getContextClassLoader() throws SecurityException when + * the context class loader isn't an ancestor of the + * calling class's class loader, or if security + * permissions are restricted. + * + * In the first case (not related), we want to ignore and + * keep going. We cannot help but also ignore the second + * with the logic below, but other calls elsewhere (to + * obtain a class loader) will trigger this exception where + * we can make a distinction. + */ + if (e.getTargetException() instanceof SecurityException) { + // ignore + } else { + // Capture 'e.getTargetException()' exception for details + // alternate: log 'e.getTargetException()', and pass back 'e'. + throw new LogConfigurationException + ("Unexpected InvocationTargetException", e.getTargetException()); + } + } + } catch (NoSuchMethodException e) { + // Assume we are running on JDK 1.1 + // ignore + } + + if (classLoader == null) { + classLoader = SimpleLog.class.getClassLoader(); + } + + // Return the selected class loader + return classLoader; + } + + private static InputStream getResourceAsStream(final String name) { + return (InputStream)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + ClassLoader threadCL = getContextClassLoader(); + + if (threadCL != null) { + return threadCL.getResourceAsStream(name); + } else { + return ClassLoader.getSystemResourceAsStream(name); + } + } + }); + } +} + diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/WeakHashtable.java libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/WeakHashtable.java --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/WeakHashtable.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/WeakHashtable.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,482 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Implementation of Hashtable that uses WeakReference's + * to hold its keys thus allowing them to be reclaimed by the garbage collector. + * The associated values are retained using strong references. + *

+ * This class follows the semantics of Hashtable as closely as + * possible. It therefore does not accept null values or keys. + *

+ * Note: + * This is not intended to be a general purpose hash table replacement. + * This implementation is also tuned towards a particular purpose: for use as a replacement + * for Hashtable in LogFactory. This application requires + * good liveliness for get and put. Various tradeoffs + * have been made with this in mind. + *

+ * Usage: typical use case is as a drop-in replacement + * for the Hashtable used in LogFactory for J2EE environments + * running 1.3+ JVMs. Use of this class in most cases (see below) will + * allow classloaders to be collected by the garbage collector without the need + * to call {@link org.apache.commons.logging.LogFactory#release(ClassLoader) LogFactory.release(ClassLoader)}. + *

+ * org.apache.commons.logging.LogFactory checks whether this class + * can be supported by the current JVM, and if so then uses it to store + * references to the LogFactory implementation it loads + * (rather than using a standard Hashtable instance). + * Having this class used instead of Hashtable solves + * certain issues related to dynamic reloading of applications in J2EE-style + * environments. However this class requires java 1.3 or later (due to its use + * of java.lang.ref.WeakReference and associates). + * And by the way, this extends Hashtable rather than HashMap + * for backwards compatibility reasons. See the documentation + * for method LogFactory.createFactoryStore for more details. + *

+ * The reason all this is necessary is due to a issue which + * arises during hot deploy in a J2EE-like containers. + * Each component running in the container owns one or more classloaders; when + * the component loads a LogFactory instance via the component classloader + * a reference to it gets stored in the static LogFactory.factories member, + * keyed by the component's classloader so different components don't + * stomp on each other. When the component is later unloaded, the container + * sets the component's classloader to null with the intent that all the + * component's classes get garbage-collected. However there's still a + * reference to the component's classloader from a key in the "global" + * LogFactory's factories member! If LogFactory.release() + * is called whenever component is unloaded, the classloaders will be correctly + * garbage collected; this should be done by any container that + * bundles commons-logging by default. However, holding the classloader + * references weakly ensures that the classloader will be garbage collected + * without the container performing this step. + *

+ * Limitations: + * There is still one (unusual) scenario in which a component will not + * be correctly unloaded without an explicit release. Though weak references + * are used for its keys, it is necessary to use strong references for its values. + *

+ * If the abstract class LogFactory is + * loaded by the container classloader but a subclass of + * LogFactory [LogFactory1] is loaded by the component's + * classloader and an instance stored in the static map associated with the + * base LogFactory class, then there is a strong reference from the LogFactory + * class to the LogFactory1 instance (as normal) and a strong reference from + * the LogFactory1 instance to the component classloader via + * getClass().getClassLoader(). This chain of references will prevent + * collection of the child classloader. + *

+ * Such a situation occurs when the commons-logging.jar is + * loaded by a parent classloader (e.g. a server level classloader in a + * servlet container) and a custom LogFactory implementation is + * loaded by a child classloader (e.g. a web app classloader). + *

+ * To avoid this scenario, ensure + * that any custom LogFactory subclass is loaded by the same classloader as + * the base LogFactory. Creating custom LogFactory subclasses is, + * however, rare. The standard LogFactoryImpl class should be sufficient + * for most or all users. + * + * @version $Id: WeakHashtable.java 1435077 2013-01-18 10:51:35Z tn $ + * @since 1.1 + */ +public final class WeakHashtable extends Hashtable { + + /** Serializable version identifier. */ + private static final long serialVersionUID = -1546036869799732453L; + + /** + * The maximum number of times put() or remove() can be called before + * the map will be purged of all cleared entries. + */ + private static final int MAX_CHANGES_BEFORE_PURGE = 100; + + /** + * The maximum number of times put() or remove() can be called before + * the map will be purged of one cleared entry. + */ + private static final int PARTIAL_PURGE_COUNT = 10; + + /* ReferenceQueue we check for gc'd keys */ + private final ReferenceQueue queue = new ReferenceQueue(); + /* Counter used to control how often we purge gc'd entries */ + private int changeCount = 0; + + /** + * Constructs a WeakHashtable with the Hashtable default + * capacity and load factor. + */ + public WeakHashtable() {} + + /** + *@see Hashtable + */ + public boolean containsKey(Object key) { + // purge should not be required + Referenced referenced = new Referenced(key); + return super.containsKey(referenced); + } + + /** + *@see Hashtable + */ + public Enumeration elements() { + purge(); + return super.elements(); + } + + /** + *@see Hashtable + */ + public Set entrySet() { + purge(); + Set referencedEntries = super.entrySet(); + Set unreferencedEntries = new HashSet(); + for (Iterator it=referencedEntries.iterator(); it.hasNext();) { + Map.Entry entry = (Map.Entry) it.next(); + Referenced referencedKey = (Referenced) entry.getKey(); + Object key = referencedKey.getValue(); + Object value = entry.getValue(); + if (key != null) { + Entry dereferencedEntry = new Entry(key, value); + unreferencedEntries.add(dereferencedEntry); + } + } + return unreferencedEntries; + } + + /** + *@see Hashtable + */ + public Object get(Object key) { + // for performance reasons, no purge + Referenced referenceKey = new Referenced(key); + return super.get(referenceKey); + } + + /** + *@see Hashtable + */ + public Enumeration keys() { + purge(); + final Enumeration enumer = super.keys(); + return new Enumeration() { + public boolean hasMoreElements() { + return enumer.hasMoreElements(); + } + public Object nextElement() { + Referenced nextReference = (Referenced) enumer.nextElement(); + return nextReference.getValue(); + } + }; + } + + /** + *@see Hashtable + */ + public Set keySet() { + purge(); + Set referencedKeys = super.keySet(); + Set unreferencedKeys = new HashSet(); + for (Iterator it=referencedKeys.iterator(); it.hasNext();) { + Referenced referenceKey = (Referenced) it.next(); + Object keyValue = referenceKey.getValue(); + if (keyValue != null) { + unreferencedKeys.add(keyValue); + } + } + return unreferencedKeys; + } + + /** + *@see Hashtable + */ + public synchronized Object put(Object key, Object value) { + // check for nulls, ensuring semantics match superclass + if (key == null) { + throw new NullPointerException("Null keys are not allowed"); + } + if (value == null) { + throw new NullPointerException("Null values are not allowed"); + } + + // for performance reasons, only purge every + // MAX_CHANGES_BEFORE_PURGE times + if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) { + purge(); + changeCount = 0; + } + // do a partial purge more often + else if (changeCount % PARTIAL_PURGE_COUNT == 0) { + purgeOne(); + } + + Referenced keyRef = new Referenced(key, queue); + return super.put(keyRef, value); + } + + /** + *@see Hashtable + */ + public void putAll(Map t) { + if (t != null) { + Set entrySet = t.entrySet(); + for (Iterator it=entrySet.iterator(); it.hasNext();) { + Map.Entry entry = (Map.Entry) it.next(); + put(entry.getKey(), entry.getValue()); + } + } + } + + /** + *@see Hashtable + */ + public Collection values() { + purge(); + return super.values(); + } + + /** + *@see Hashtable + */ + public synchronized Object remove(Object key) { + // for performance reasons, only purge every + // MAX_CHANGES_BEFORE_PURGE times + if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) { + purge(); + changeCount = 0; + } + // do a partial purge more often + else if (changeCount % PARTIAL_PURGE_COUNT == 0) { + purgeOne(); + } + return super.remove(new Referenced(key)); + } + + /** + *@see Hashtable + */ + public boolean isEmpty() { + purge(); + return super.isEmpty(); + } + + /** + *@see Hashtable + */ + public int size() { + purge(); + return super.size(); + } + + /** + *@see Hashtable + */ + public String toString() { + purge(); + return super.toString(); + } + + /** + * @see Hashtable + */ + protected void rehash() { + // purge here to save the effort of rehashing dead entries + purge(); + super.rehash(); + } + + /** + * Purges all entries whose wrapped keys + * have been garbage collected. + */ + private void purge() { + final List toRemove = new ArrayList(); + synchronized (queue) { + WeakKey key; + while ((key = (WeakKey) queue.poll()) != null) { + toRemove.add(key.getReferenced()); + } + } + + // LOGGING-119: do the actual removal of the keys outside the sync block + // to prevent deadlock scenarios as purge() may be called from + // non-synchronized methods too + final int size = toRemove.size(); + for (int i = 0; i < size; i++) { + super.remove(toRemove.get(i)); + } + } + + /** + * Purges one entry whose wrapped key + * has been garbage collected. + */ + private void purgeOne() { + synchronized (queue) { + WeakKey key = (WeakKey) queue.poll(); + if (key != null) { + super.remove(key.getReferenced()); + } + } + } + + /** Entry implementation */ + private final static class Entry implements Map.Entry { + + private final Object key; + private final Object value; + + private Entry(Object key, Object value) { + this.key = key; + this.value = value; + } + + public boolean equals(Object o) { + boolean result = false; + if (o != null && o instanceof Map.Entry) { + Map.Entry entry = (Map.Entry) o; + result = (getKey()==null ? + entry.getKey() == null : + getKey().equals(entry.getKey())) && + (getValue()==null ? + entry.getValue() == null : + getValue().equals(entry.getValue())); + } + return result; + } + + public int hashCode() { + return (getKey()==null ? 0 : getKey().hashCode()) ^ + (getValue()==null ? 0 : getValue().hashCode()); + } + + public Object setValue(Object value) { + throw new UnsupportedOperationException("Entry.setValue is not supported."); + } + + public Object getValue() { + return value; + } + + public Object getKey() { + return key; + } + } + + /** Wrapper giving correct symantics for equals and hashcode */ + private final static class Referenced { + + private final WeakReference reference; + private final int hashCode; + + /** + * + * @throws NullPointerException if referant is null + */ + private Referenced(Object referant) { + reference = new WeakReference(referant); + // Calc a permanent hashCode so calls to Hashtable.remove() + // work if the WeakReference has been cleared + hashCode = referant.hashCode(); + } + + /** + * + * @throws NullPointerException if key is null + */ + private Referenced(Object key, ReferenceQueue queue) { + reference = new WeakKey(key, queue, this); + // Calc a permanent hashCode so calls to Hashtable.remove() + // work if the WeakReference has been cleared + hashCode = key.hashCode(); + + } + + public int hashCode() { + return hashCode; + } + + private Object getValue() { + return reference.get(); + } + + public boolean equals(Object o) { + boolean result = false; + if (o instanceof Referenced) { + Referenced otherKey = (Referenced) o; + Object thisKeyValue = getValue(); + Object otherKeyValue = otherKey.getValue(); + if (thisKeyValue == null) { + result = otherKeyValue == null; + + // Since our hashcode was calculated from the original + // non-null referant, the above check breaks the + // hashcode/equals contract, as two cleared Referenced + // objects could test equal but have different hashcodes. + // We can reduce (not eliminate) the chance of this + // happening by comparing hashcodes. + result = result && this.hashCode() == otherKey.hashCode(); + // In any case, as our c'tor does not allow null referants + // and Hashtable does not do equality checks between + // existing keys, normal hashtable operations should never + // result in an equals comparison between null referants + } + else + { + result = thisKeyValue.equals(otherKeyValue); + } + } + return result; + } + } + + /** + * WeakReference subclass that holds a hard reference to an + * associated value and also makes accessible + * the Referenced object holding it. + */ + private final static class WeakKey extends WeakReference { + + private final Referenced referenced; + + private WeakKey(Object key, + ReferenceQueue queue, + Referenced referenced) { + super(key, queue); + this.referenced = referenced; + } + + private Referenced getReferenced() { + return referenced; + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/package.html libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/package.html --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/impl/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/impl/package.html 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,22 @@ + + + +

Concrete implementations of commons-logging wrapper APIs.

+ diff -Nru libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/package.html libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/package.html --- libcommons-logging-java-1.1.1/src/main/java/org/apache/commons/logging/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/org/apache/commons/logging/package.html 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,255 @@ + + + +

Simple wrapper API around multiple logging APIs.

+ + +

Overview

+ +

This package provides an API for logging in server-based applications that +can be used around a variety of different logging implementations, including +prebuilt support for the following:

+
    +
  • Log4J (version 1.2 or later) + from Apache's Logging project. Each named Log + instance is connected to a corresponding Log4J Logger.
  • +
  • + JDK Logging API, included in JDK 1.4 or later systems. Each named + Log instance is connected to a corresponding + java.util.logging.Logger instance.
  • +
  • LogKit from Apache's + Avalon project. Each named Log instance is + connected to a corresponding LogKit Logger.
  • +
  • NoOpLog implementation that simply swallows + all log output, for all named Log instances.
  • +
  • SimpleLog implementation that writes all + log output, for all named Log instances, to + System.err.
  • +
+ + +

Quick Start Guide

+ +

For those impatient to just get on with it, the following example +illustrates the typical declaration and use of a logger that is named (by +convention) after the calling class: + +

+    import org.apache.commons.logging.Log;
+    import org.apache.commons.logging.LogFactory;
+
+    public class Foo {
+
+        private Log log = LogFactory.getLog(Foo.class);
+
+        public void foo() {
+            ...
+            try {
+                if (log.isDebugEnabled()) {
+                    log.debug("About to do something to object " + name);
+                }
+                name.bar();
+            } catch (IllegalStateException e) {
+                log.error("Something bad happened to " + name, e);
+            }
+            ...
+        }
+
+ +

Unless you configure things differently, all log output will be written +to System.err. Therefore, you really will want to review the remainder of +this page in order to understand how to configure logging for your +application.

+ + +

Configuring the Commons Logging Package

+ + +

Choosing a LogFactory Implementation

+ +

From an application perspective, the first requirement is to retrieve an +object reference to the LogFactory instance that will be used +to create Log instances for this +application. This is normally accomplished by calling the static +getFactory() method. This method implements the following +discovery algorithm to select the name of the LogFactory +implementation class this application wants to use:

+
    +
  • Check for a system property named + org.apache.commons.logging.LogFactory.
  • +
  • Use the JDK 1.3 JAR Services Discovery mechanism (see + + http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html for + more information) to look for a resource named + META-INF/services/org.apache.commons.logging.LogFactory + whose first line is assumed to contain the desired class name.
  • +
  • Look for a properties file named commons-logging.properties + visible in the application class path, with a property named + org.apache.commons.logging.LogFactory defining the + desired implementation class name.
  • +
  • Fall back to a default implementation, which is described + further below.
  • +
+ +

If a commons-logging.properties file is found, all of the +properties defined there are also used to set configuration attributes on +the instantiated LogFactory instance.

+ +

Once an implementation class name is selected, the corresponding class is +loaded from the current Thread context class loader (if there is one), or +from the class loader that loaded the LogFactory class itself +otherwise. This allows a copy of commons-logging.jar to be +shared in a multiple class loader environment (such as a servlet container), +but still allow each web application to provide its own LogFactory +implementation, if it so desires. An instance of this class will then be +created, and cached per class loader. + + +

The Default LogFactory Implementation

+ +

The Logging Package APIs include a default LogFactory +implementation class ( +org.apache.commons.logging.impl.LogFactoryImpl) that is selected if no +other implementation class name can be discovered. Its primary purpose is +to create (as necessary) and return Log instances +in response to calls to the getInstance() method. The default +implementation uses the following rules:

+
    +
  • At most one Log instance of the same name will be created. + Subsequent getInstance() calls to the same + LogFactory instance, with the same name or Class + parameter, will return the same Log instance.
  • +
  • When a new Log instance must be created, the default + LogFactory implementation uses the following discovery + process: +
      +
    • Look for a configuration attribute of this factory named + org.apache.commons.logging.Log (for backwards + compatibility to pre-1.0 versions of this API, an attribute + org.apache.commons.logging.log is also consulted).
    • +
    • Look for a system property named + org.apache.commons.logging.Log (for backwards + compatibility to pre-1.0 versions of this API, a system property + org.apache.commons.logging.log is also consulted).
    • +
    • If the Log4J logging system is available in the application + class path, use the corresponding wrapper class + (Log4JLogger).
    • +
    • If the application is executing on a JDK 1.4 system, use + the corresponding wrapper class + (Jdk14Logger).
    • +
    • Fall back to the default simple logging implementation + (SimpleLog).
    • +
  • +
  • Load the class of the specified name from the thread context class + loader (if any), or from the class loader that loaded the + LogFactory class otherwise.
  • +
  • Instantiate an instance of the selected Log + implementation class, passing the specified name as the single + argument to its constructor.
  • +
+ +

See the SimpleLog JavaDocs for detailed +configuration information for this default implementation.

+ + +

Configuring the Underlying Logging System

+ +

The basic principle is that the user is totally responsible for the +configuration of the underlying logging system. +Commons-logging should not change the existing configuration.

+ +

Each individual Log implementation may +support its own configuration properties. These will be documented in the +class descriptions for the corresponding implementation class.

+ +

Finally, some Log implementations (such as the one for Log4J) +require an external configuration file for the entire logging environment. +This file should be prepared in a manner that is specific to the actual logging +technology being used.

+ + +

Using the Logging Package APIs

+ +

Use of the Logging Package APIs, from the perspective of an application +component, consists of the following steps:

+
    +
  1. Acquire a reference to an instance of + org.apache.commons.logging.Log, by calling the + factory method + + LogFactory.getInstance(String name). Your application can contain + references to multiple loggers that are used for different + purposes. A typical scenario for a server application is to have each + major component of the server use its own Log instance.
  2. +
  3. Cause messages to be logged (if the corresponding detail level is enabled) + by calling appropriate methods (trace(), debug(), + info(), warn(), error, and + fatal()).
  4. +
+ +

For convenience, LogFactory also offers a static method +getLog() that combines the typical two-step pattern:

+
+  Log log = LogFactory.getFactory().getInstance(Foo.class);
+
+

into a single method call:

+
+  Log log = LogFactory.getLog(Foo.class);
+
+ +

For example, you might use the following technique to initialize and +use a Log instance in an application component:

+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class MyComponent {
+
+  protected Log log =
+    LogFactory.getLog(MyComponent.class);
+
+  // Called once at startup time
+  public void start() {
+    ...
+    log.info("MyComponent started");
+    ...
+  }
+
+  // Called once at shutdown time
+  public void stop() {
+    ...
+    log.info("MyComponent stopped");
+    ...
+  }
+
+  // Called repeatedly to process a particular argument value
+  // which you want logged if debugging is enabled
+  public void process(String value) {
+    ...
+    // Do the string concatenation only if logging is enabled
+    if (log.isDebugEnabled())
+      log.debug("MyComponent processing " + value);
+    ...
+  }
+
+}
+
+ + diff -Nru libcommons-logging-java-1.1.1/src/main/java/overview.html libcommons-logging-java-1.1.3/src/main/java/overview.html --- libcommons-logging-java-1.1.1/src/main/java/overview.html 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/main/java/overview.html 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,35 @@ + + + + +Overview Documentation for COMMONS-LOGGING + + +

The Logging Wrapper Library component of the Apache Commons +subproject offers wrappers around an extensible set of concrete logging +implementations, so that application code based on it does not need to be +modified in order to select a different logging implementation.

+ +

See the + +Package Description for the org.apache.commons.logging +package for more information.

+ + Binary files /tmp/QIYUuSPeoV/libcommons-logging-java-1.1.1/src/site/resources/images/logo.png and /tmp/U4WicrDbVX/libcommons-logging-java-1.1.3/src/site/resources/images/logo.png differ diff -Nru libcommons-logging-java-1.1.1/src/site/site.xml libcommons-logging-java-1.1.3/src/site/site.xml --- libcommons-logging-java-1.1.1/src/site/site.xml 2007-11-21 23:27:52.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/site/site.xml 2013-05-16 20:04:22.000000000 +0000 @@ -1,84 +1,64 @@ - - - - - - - Commons Logging - http://commons.apache.org/logging/images/logo.png - http://commons.apache.org/logging/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + Commons Logging + /images/logo.png + http://commons.apache.org/logging/ + + + + + + + + + + + + + + + + + + + + + + + diff -Nru libcommons-logging-java-1.1.1/src/site/xdoc/building.xml libcommons-logging-java-1.1.3/src/site/xdoc/building.xml --- libcommons-logging-java-1.1.1/src/site/xdoc/building.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/site/xdoc/building.xml 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,74 @@ + + + + + Building + Commons Documentation Team + + + +
+

+ Commons Logging uses Maven 2.0.x as its + primary build system. Ant can also be used. +

+
+ +
+

+ To build the full website, run +

+ mvn site +

+ The result will be in the target/site folder. + You must be online and using JDK 1.4 or higher to successfully complete this target. +

+

+ To build the jar files, run +

+ mvn package +

+ The resulting 4 jar files will be in the target folder. + You must use JDK 1.4 or higher to successfully complete this target. +

+

+ To create a full distribution, run +

+ mvn clean site assembly:assembly +

+ The resulting .zip and .tar.gz files will be in the target folder. + You must use JDK 1.4 or higher to successfully complete this target. +

+

+ Further details can be found in the + commons build instructions. +

+
+ +
+

+ We still use Ant to test the artifacts built my Maven. + Please follow the instructions in the file build-testing.xml. +

+

+ Note: A 1.2 JDK is needed to run the tests. +

+
+ + +
diff -Nru libcommons-logging-java-1.1.1/src/site/xdoc/download_logging.xml libcommons-logging-java-1.1.3/src/site/xdoc/download_logging.xml --- libcommons-logging-java-1.1.1/src/site/xdoc/download_logging.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/site/xdoc/download_logging.xml 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,138 @@ + + + + + + Download Commons Logging + Commons Documentation Team + + +
+ +

+ We recommend you use a mirror to download our release + builds, but you must verify the integrity of + the downloaded files using signatures downloaded from our main + distribution directories. Recent releases (48 hours) may not yet + be available from the mirrors. +

+ +

+ You are currently using [preferred]. If you + encounter a problem with this mirror, please select another + mirror. If all mirrors are failing, there are backup + mirrors (at the end of the mirrors list) that should be + available. +

+ [if-any logo][end] +

+ +
+

+ Other mirrors: + + +

+
+ +

+ The KEYS + link links to the code signing keys used to sign the product. + The PGP link downloads the OpenPGP compatible signature from our main site. + The MD5 link downloads the checksum from the main site. +

+
+
+
+ + + + + + + + + + + + +
commons-logging-1.1.3-bin.tar.gzmd5pgp
commons-logging-1.1.3-bin.zipmd5pgp
+
+ + + + + + + + + + + + +
commons-logging-1.1.3-src.tar.gzmd5pgp
commons-logging-1.1.3-src.zipmd5pgp
+
+
+
+

+ Older releases can be obtained from the archives. +

+ +
+ +
diff -Nru libcommons-logging-java-1.1.1/src/site/xdoc/guide.xml libcommons-logging-java-1.1.3/src/site/xdoc/guide.xml --- libcommons-logging-java-1.1.1/src/site/xdoc/guide.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/site/xdoc/guide.xml 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,850 @@ + + + + + + + + User Guide + Commons Documentation Team + + + +
+

+

    +
  1. Introduction
  2. +
  3. Quick Start +
      +
    1. Configuration
    2. +
    3. +Configuring The Underlying Logging System +
    4. +
    5. +Configuring Log4J +
    6. +
    +
  4. +
  5. Developing With JCL +
      +
    1. Obtaining a Log Object
    2. +
    3. Logging a Message
    4. +
    5. Serialization Issues
    6. +
    +
  6. +
  7. Jars Included in the Standard Distribution +
      +
    1. commons-logging.jar
    2. +
    3. commons-logging-api.jar
    4. +
    5. commons-logging-adapters.jar
    6. +
    +
  8. +
  9. JCL Best Practices
  10. +
  11. Best Practices (General) +
      +
    1. Code Guards
    2. +
    3. Message Priorities/Levels
    4. +
    5. Default Message Priority/Level
    6. +
    +
  12. +
  13. Best Practices (Enterprise) +
      +
    1. Logging Exceptions
    2. +
    3. When Info Level Instead of Debug?
    4. +
    5. More Control of Enterprise Exception Logging
    6. +
    7. National Language Support And Internationalization
    8. +
    9. Classloader and Memory Management
    10. +
    +
  14. +
  15. Extending Commons Logging +
      +
    1. Contract
    2. +
    3. Creating a Log Implementation
    4. +
    5. Creating A LogFactory Implementation
    6. +
    +
  16. +
  17. A Quick Guide To Simple Log +
  18. +
  19. Frequently Asked Questions +
  20. +
+

+
+
+

+The Apache Commons Logging (JCL) provides a Log interface that +is intended to be both light-weight and an independent abstraction of other logging toolkits. +It provides the middleware/tooling developer with a simple +logging abstraction, that allows the user (application developer) to plug in +a specific logging implementation. +

+

JCL provides thin-wrapper Log implementations for +other logging tools, including +Log4J, +Avalon LogKit +(the Avalon Framework's logging infrastructure), +JDK 1.4, and an implementation of JDK 1.4 logging APIs (JSR-47) for pre-1.4 +systems. +The interface maps closely to Log4J and LogKit. +

+

+Familiarity with high-level details of the relevant Logging implementations is presumed. +

+
+
+

+As far as possible, JCL tries to be as unobtrusive as possible. +In most cases, including the (full) commons-logging.jar in the classpath +should result in JCL configuring itself in a reasonable manner. +There's a good chance that it'll guess (discover) your preferred logging system and you won't +need to do any configuration of JCL at all! +

+Note, however, that if you have a particular preference then providing a simple +commons-logging.properties file which specifies the concrete logging library to be +used is recommended, since (in this case) JCL will log only to that system +and will report any configuration problems that prevent that system being used. +

+

+When no particular logging library is specified then JCL will silently ignore any logging library +that it finds but cannot initialise and continue to look for other alternatives. This is a deliberate +design decision; no application should fail to run because a "guessed" logging library cannot be +used. To ensure an exception is reported when a particular logging library cannot be used, use one +of the available JCL configuration mechanisms to force that library to be selected (ie disable +JCL's discovery process). +

+ +

+There are two base abstractions used by JCL: Log +(the basic logger) and LogFactory (which knows how to create Log +instances). Specifying a particular Log implementation is very useful (whether that is +one provided by commons-logging or a user-defined one). Specifying a +LogFactory implementation other than the default is a subject for +advanced users only, so will not be addressed here. +

+

+The default LogFactory implementation uses the following discovery process +to determine what type of Log implementation it should use +(the process terminates when the first positive match - in order - is found): +

+ +
    +
  1. +Look for a configuration attribute of this factory named +org.apache.commons.logging.Log (for backwards compatibility to +pre-1.0 versions of this API, an attribute +org.apache.commons.logging.log is also consulted). +

    +Configuration attributes can be set explicitly by java code, but they are more +commonly set by placing a file named commons-logging.properties in the classpath. +When such a file exists, every entry in the properties file becomes an "attribute" +of the LogFactory. When there is more than one such file in the classpath, releases +of commons-logging prior to 1.1 simply use the first one found. From release 1.1, +each file may define a priority key, and the file with +the highest priority is used (no priority definition implies priority of zero). +When multiple files have the same priority, the first one found is used. +

    +

    +Defining this property in a commons-logging.properties file is the recommended +way of explicitly selecting a Log implementation. +

    +
  2. +
  3. +Look for a system property named +org.apache.commons.logging.Log (for backwards +compatibility to pre-1.0 versions of this API, a system property +org.apache.commons.logging.log is also consulted). +
  4. +
  5. +If the Log4J logging system is available in the application +class path, use the corresponding wrapper class +(Log4JLogger). +
  6. +
  7. +If the application is executing on a JDK 1.4 system, use +the corresponding wrapper class +(Jdk14Logger). +
  8. +
  9. +Fall back to the default simple logging wrapper +(SimpleLog). +
  10. +
+

+Consult the JCL javadocs for details of the various Log +implementations that ship with the component. (The discovery process is also covered in more +detail there.) +

+
+ +

+The JCL SPI +can be configured to use different logging toolkits (see above). +JCL provides only a bridge for writing log messages. It does not (and will not) support any +sort of configuration API for the underlying logging system. +

+

+Configuration of the behavior of the JCL ultimately depends upon the +logging toolkit being used. Please consult the documentation for the chosen logging system. +

+

+JCL is NOT responsible for initialisation, configuration or shutdown of the underlying logging library. +In many cases logging libraries will automatically initialise/configure themselves when first used, and +need no explicit shutdown process. In these situations an application can simply use JCL and not depend +directly on the API of the underlying logging system in any way. However if the logging library being used +requires special initialisation, configuration or shutdown then some logging-library-specific code will +be required in the application. JCL simply forwards logging method calls to the correct underlying +implementation. When writing library code this issue is of course not relevant as the calling application +is responsible for handling such issues. +

+ +

+Log4J is a very commonly used logging implementation (as well as being the JCL primary default), +so a few details are presented herein to get the developer/integrator going. +Please see the Log4J Home for more details +on Log4J and it's configuration. +

+

+Configure Log4J using system properties and/or a properties file: +

+
    +
  • +log4j.configuration=log4j.properties +Use this system property to specify the name of a Log4J configuration file. +If not specified, the default configuration file is log4j.properties. +
  • +
  • +log4j.rootCategory=priority [, appender]* +
  • +Set the default (root) logger priority. +
  • +log4j.logger.logger.name=priority +Set the priority for the named logger +and all loggers hierarchically lower than, or below, the +named logger. +logger.name corresponds to the parameter of +LogFactory.getLog(logger.name), +used to create the logger instance. Priorities are: +DEBUG, +INFO, +WARN, +ERROR, +or FATAL. +
    +Log4J understands hierarchical names, +enabling control by package or high-level qualifiers: +log4j.logger.org.apache.component=DEBUG +will enable debug messages for all classes in both +org.apache.component +and +org.apache.component.sub. +Likewise, setting +log4j.logger.org.apache.component=DEBUG +will enable debug message for all 'component' classes, +but not for other Apache projects. +
  • +
  • +log4j.appender.appender.Threshold=priority +
  • +Log4J appenders correspond to different output devices: +console, files, sockets, and others. +If appender's threshold +is less than or equal to the message priority then +the message is written by that appender. +This allows different levels of detail to be appear +at different log destinations. +For example: one can capture DEBUG (and higher) level information in a logfile, +while limiting console output to INFO (and higher). +
+
+
+
+
+ +

+To use the JCL SPI from a Java class, +include the following import statements: +

+
    + +import org.apache.commons.logging.Log; +
    +import org.apache.commons.logging.LogFactory; +
    +
    +
+

+Note that some components using JCL may +either extend Log, +or provide a component-specific LogFactory implementation. +Review the component documentation for guidelines +on how commons-logging should be used in such components. +

+

+For each class definition, declare and initialize a +log attribute as follows: +

+
    + +public class CLASS +{ + private Log log = LogFactory.getLog(CLASS.class); + ... + ; + +
+

+Note that for application code, declaring the log member as "static" is more +efficient as one Log object is created per class, and is recommended. +However this is not safe to do for a class which may be deployed via a "shared" +classloader in a servlet or j2ee container or similar environment. If the class +may end up invoked with different thread-context-classloader values set then the +member must not be declared static. The use of "static" should therefore +be avoided in code within any "library" type project. +

+
+ +

+Messages are logged to a logger, such as log +by invoking a method corresponding to priority. +The org.apache.commons.logging.Log interface defines the +following methods for use +in writing log/trace messages to the log: +

+
    + + log.fatal(Object message); + log.fatal(Object message, Throwable t); + log.error(Object message); + log.error(Object message, Throwable t); + log.warn(Object message); + log.warn(Object message, Throwable t); + log.info(Object message); + log.info(Object message, Throwable t); + log.debug(Object message); + log.debug(Object message, Throwable t); + log.trace(Object message); + log.trace(Object message, Throwable t); + +
+

+Semantics for these methods are such that it is expected +that the severity, from highest to lowest, of messages is ordered as above. +

+

+In addition to the logging methods, the following are provided for code guards: +

+
    + + log.isFatalEnabled(); + log.isErrorEnabled(); + log.isWarnEnabled(); + log.isInfoEnabled(); + log.isDebugEnabled(); + log.isTraceEnabled(); + +
+
+ +

Prior to release 1.0.4, none of the standard Log implementations were + Serializable. If you are using such a release and have a Serializable class + with a member that is of type Log then it is necessary to declare + that member to be transient and to ensure that the value is restored on + deserialization. The recommended approach is to define a custom + readObject method on the class which reinitializes that member.

+

In release 1.0.4, all standard Log implementations are Serializable. This + means that class members of type Log do not need to be declared transient; + on deserialization the Log object will "rebind" to the same category for the + same logging library. Note that the same underlying logging library will be + used on deserialization as was used in the original object, even if the + application the object was deserialized into is using a different logging + library. There is one exception; LogKitLogger (adapter for the Avalon LogKit + library) is not Serializable for technical reasons.

+

Custom Log implementations not distributed with commons-logging may + or may not be Serializable. If you wish your code to be compatible with + any arbitrary log adapter then you should follow the advice given above + for pre-1.0.4 releases.

+
+
+
+ +

+The commons-logging.jar file includes the JCL API, the default +LogFactory implementation and thin-wrapper Log +implementations for +Log4J, +Avalon LogKit, +the Avalon Framework's logging infrastructure, +JDK 1.4, as well as an implementation of JDK 1.4 logging APIs (JSR-47) for +pre-1.4 systems. +

+

+In most cases, including commons-logging.jar and your preferred +logging implementation in the classpath should be all that is required to +use JCL. +

+
+ +

+The commons-logging-api.jar file includes the JCL API and the +default LogFactory implementation as well as the built-in +Log implementations SimpleLog and NoOpLog. However it does not +include the wrapper Log implementations that require additional +libraries such as Log4j, Avalon and +Lumberjack. +

+

+This jar is intended for use by projects that recompile the commons-logging +source using alternate java environments, and cannot compile against all of +the optional libraries that the Apache release of commons-logging supports. +Because of the reduced dependencies of this jarfile, such projects should be +able to create an equivalent of this library with fewer difficulties. +

+

+This jar is also useful for build environments that automatically track +dependencies, and thus have difficulty with the concept that the main +commons-logging.jar has "optional" dependencies on various logging +implementations that can safely go unsatisfied at runtime. +

+
+ +

+The commons-logging-adapters.jar file includes only adapters +to third-party logging implementations, and none of the core commons-logging +framework. As such, it cannot be used alone; either commons-logging.jar or +commons-logging-api.jar must also be present in the classpath. +

+

+This library will not often be used; it is only intended for situations where +a container has deployed commons-logging-api.jar in a shared classpath but a +webapp wants to bind logging to one of the external logging implementations +that the api jar does not include. In this situation, deploying the +commons-logging.jar file within the webapp can cause problems as this leads to +duplicates of the core commons-logging classes (Log, LogFactory, etc) in +the classpath which in turn can cause unpleasant ClassCastException exceptions +to occur. Deploying only the adapters avoids this problem. +

+
+
+
+

+Best practices for JCL are presented in two categories: +General and Enterprise. +The general principles are fairly clear.Enterprise practices are a bit more involved +and it is not always as clear as to why they are important. +

+

+Enterprise best-practice principles apply to middleware components +and tooling that is expected to execute in an "Enterprise" level +environment. +These issues relate to Logging as Internationalization, +and fault detection. +Enterprise requires more effort and planning, but are strongly encouraged (if not required) +in production level systems. Different corporate enterprises/environments have different +requirements, so being flexible always helps. +

+
+
+ +

+Code guards are typically used to guard code that +only needs to execute in support of logging, +that otherwise introduces undesirable runtime overhead +in the general case (logging disabled). +Examples are multiple parameters, or expressions (e.g. string + " more") for parameters. +Use the guard methods of the form log.is<Priority>() to verify +that logging should be performed, before incurring the overhead of the logging method call. +Yes, the logging methods will perform the same check, but only after resolving parameters. +

+
+ +

+It is important to ensure that log message are +appropriate in content and severity. +The following guidelines are suggested: +

+
    +
  • +fatal - Severe errors that cause premature termination. +Expect these to be immediately visible on a status console. +See also +Internationalization. +
  • +
  • +error - Other runtime errors or unexpected conditions. +Expect these to be immediately visible on a status console. +See also +Internationalization. +
  • +
  • +warn - Use of deprecated APIs, poor use of API, 'almost' errors, +other runtime situations that are undesirable or unexpected, but not +necessarily "wrong". +Expect these to be immediately visible on a status console. +See also +Internationalization. +
  • +
  • +info - Interesting runtime events (startup/shutdown). +Expect these to be immediately visible on a console, +so be conservative and keep to a minimum. +See also +Internationalization. +
  • +
  • +debug - detailed information on the flow through the system. +Expect these to be written to logs only. +
  • +
  • +trace - more detailed information. +Expect these to be written to logs only. +
  • +
+
+ +

+By default the message priority should be no lower than info. +That is, by default debug message should not be seen in the logs. +

+
+
+
+ +

+The general rule in dealing with exceptions is to assume that +the user (developer using a tooling/middleware API) isn't going +to follow the rules. +Since any problems that result are going to be assigned to you, +it's in your best interest to be prepared with the proactive +tools necessary to demonstrate that your component works correctly, +or at worst that the problem can be analyzed from your logs. +For this discussion, we must make a distinction between different types of exceptions +based on what kind of boundaries they cross: +

+
    +
  • +External Boundaries - Expected Exceptions. +This classification includes exceptions such as FileNotFoundException +that cross API/SPI boundaries, and are exposed to the user of a component/toolkit. +These are listed in the 'throws' clause of a method signature. +
    +Appropriate handling of these exceptions depends upon the type +of code you are developing. +API's for utility functions and tools should log these at the debug level, +if they are caught at all by internal code. +
    +For higher level frameworks and middleware components, +these exceptions should be caught immediately prior to crossing +the API/SPI interface back to user code-space, +logged with full stack trace at info level, +and rethrown. +The assures that the log contains a record of the root cause for +future analysis in the event that the exception is not caught and resolved +as expected by the user's code. +
    +
  • +
  • +External Boundaries - Unexpected Exceptions. +This classification includes exceptions such as NullPointerException +that cross API/SPI boundaries, and are exposed to the user of a component/toolkit. +These are runtime exceptions/error that are NOT +listed in the 'throws' clause of a method signature. +
    +Appropriate handling of these exceptions depends upon the type +of code you are developing. +APIs for utility functions and tools should log these at the debug level, +if they are caught at all. +
    +For higher level frameworks and middleware components, +these exceptions should be caught immediately prior to crossing +the API/SPI interface back to user code-space, +logged with full stack trace at info level, +and rethrown/wrapped as ComponentInternalError. +This ensures that the log contains a record of the root cause for +future analysis in the event that the exception is not caught and +logged/reported as expected by the user's code. +
  • +
  • +Internal Boundaries. +Exceptions that occur internally and are resolved internally. +These should be logged when caught as debug or info messages, +at the programmer's discretion. +
  • +
  • +Significant Internal Boundaries. +This typically only applies to middleware components that span networks or runtime processes. +Exceptions that cross over significant internal component boundaries such as networks +should be logged when caught as info messages. +Do not assume that such a (process/network) boundary will deliver exceptions to the 'other side'. +
  • +
+
+ +

+You want to have exception/problem information available for +first-pass problem determination in a production level +enterprise application without turning on debug +as a default log level. There is simply too much information +in debug to be appropriate for day-to-day operations. +

+
+ +

+If more control is desired for the level of detail of these +'enterprise' exceptions, then consider creating a special +logger just for these exceptions: +

+
    + + Log log = LogFactory.getLog("org.apache.component.enterprise"); + +
+

+This allows the 'enterprise' level information to be turned on/off explicitly +by most logger implementations. +

+
+ +

+NLS internationalization involves looking up messages from +a message file by a message key, and using that message for logging. +There are various tools in Java, and provided by other components, +for working with NLS messages. +

+

+NLS enabled components are particularly appreciated +(that's an open-source-correct term for 'required by corporate end-users' :-) +for tooling and middleware components. +

+

+NLS internationalization SHOULD be strongly considered for used for +fatal, error, warn, and info messages. +It is generally considered optional for debug and trace messages. +

+

+Perhaps more direct support for internationalizing log messages +can be introduced in a future or alternate version of the Log interface. +

+
+ +

+The LogFactory discovery process (see +Configuration above) is a fairly expensive +operation, so JCL certainly should not perform it each time user code +invokes: +

+LogFactory.getLog() +

+Instead JCL caches the +LogFactory implementation created as a result of the discovery +process and uses the cached factory to return Log objects. +Since in J2EE and similar multi-classloader environments, the result of the +discovery process can vary depending on the thread context classloader +(e.g. one webapp in a web container may be configured to use Log4j and +another to use JDK 1.4 logging), JCL internally caches the +LogFactory instances in a static hashtable, keyed by classloader. +

+

+While this approach is efficient, it can lead to memory leaks if container +implementors are not careful to call +

+LogFactory.release() +

+whenever a classloader that has utilized JCL is undeployed. If +release() is not called, a reference to the undeployed +classloader (and thus to all the classes loaded by it) will be +held in LogFactory's static hashtable. +

+

+Beginning with JCL 1.1, LogFactory caches factory implementations in a +"WeakHashtable". This class is similar to java.util.WeakHashMap in +that it holds a WeakReference to each key (but a strong reference +to each value), thus allowing classloaders to be GC'd even if +LogFactory.release() is never invoked. +

+

+Because WeakHashtable depends on JDK 1.3+ features, it is dynamically +loaded depending on the JVM version; when commons-logging is run on java versions +prior to 1.3 the code defaults to a standard Hashtable instead. +

+

+If a custom LogFactory implementation is used, however, then a +WeakHashtable alone can be insufficient to allow garbage collection +of a classloader without a call to release. If the abstract class +LogFactory is loaded by a parent classloader and a concrete +subclass implementation of LogFactory is loaded by a child +classloader, the WeakHashtable's key is a weak reference to the TCCL (child +classloader), but the value is a strong reference to the LogFactory instance, +which in turn contains a strong reference to its class and thus loading +classloader - the child classloader. This chain of strong references prevents +the child loader from being garbage collected. +

+

+If use of a custom LogFactory subclass is desired, ensuring that +the custom subclass is loaded by the same classloader as LogFactory +will prevent problems. In normal deployments, the standard implementations +of LogFactory found in package org.apache.commons.logging.impl +will be loaded by the same classloader that loads LogFactory +itself, so use of the standard LogFactory implementation +should not pose problems. Alternatively, use the provided ServletContextCleaner +to ensure this reference is explicitly released on webapp unload. +

+
+
+
+

+JCL is designed to encourage extensions to be created that add functionality. +Typically, extensions to JCL fall into two categories: +

+
    +
  • new Log implementations that provide new bridges to logging systems
  • +
  • +new LogFactory implementations that provide alternative discovery strategies +
  • +
+ +

+When creating new implementations for Log and LogFactory, +it is important to understand the implied contract between the factory +and the log implementations: +

    +
  • Life cycle +
    +The JCL LogFactory implementation must assume responsibility for +either connecting/disconnecting to a logging toolkit, +or instantiating/initializing/destroying a logging toolkit. +
    +
  • +
  • Exception handling +
    +The JCL Log interface doesn't specify any exceptions to be handled, +the implementation must catch any exceptions. +
    +
  • +
  • Multiple threads +
    +The JCL Log and LogFactory implementations must ensure +that any synchronization required by the logging toolkit +is met. +
    +
  • +
+

+
+ +

+The minimum requirement to integrate with another logger +is to provide an implementation of the +org.apache.commons.logging.Log interface. +In addition, an implementation of the +org.apache.commons.logging.LogFactory interface +can be provided to meet +specific requirements for connecting to, or instantiating, a logger. +

+

+The default LogFactory provided by JCL +can be configured to instantiate a specific implementation of the +org.apache.commons.logging.Log interface +by setting the property of the same name (org.apache.commons.logging.Log). +This property can be specified as a system property, +or in the commons-logging.properties file, +which must exist in the CLASSPATH. +

+
+ +

+If desired, the default implementation of the +org.apache.commons.logging.LogFactory +interface can be overridden, +allowing the JDK 1.3 Service Provider discovery process +to locate and create a LogFactory specific to the needs of the application. +Review the Javadoc for the LogFactoryImpl.java +for details. +

+
+
+
+

+JCL is distributed with a very simple Log implementation named +org.apache.commons.logging.impl.SimpleLog. This is intended to be a minimal +implementation and those requiring a fully functional open source logging system are +directed to Log4J. +

+

+ SimpleLog sends all (enabled) log messages, + for all defined loggers, to System.err. The following system properties + are supported to configure the behavior of this logger:

+
    +
  • org.apache.commons.logging.simplelog.defaultlog - + Default logging detail level for all instances of SimpleLog. + Must be one of: +
      +
    • trace
    • +
    • debug
    • +
    • info
    • +
    • warn
    • +
    • error
    • +
    • fatal
    • +
    + If not specified, defaults to info.
  • +
  • org.apache.commons.logging.simplelog.log.xxxxx - + Logging detail level for a SimpleLog instance named "xxxxx". + Must be one of: +
      +
    • trace
    • +
    • debug
    • +
    • info
    • +
    • warn
    • +
    • error
    • +
    • fatal
    • +
    + If not specified, the default logging detail level is used.
  • +
  • org.apache.commons.logging.simplelog.showlogname - + Set to true if you want the Log instance name to be + included in output messages. Defaults to false.
  • +
  • org.apache.commons.logging.simplelog.showShortLogname - + Set to true if you want the last component of the name to be + included in output messages. Defaults to true.
  • +
  • org.apache.commons.logging.simplelog.showdatetime - + Set to true if you want the current date and time + to be included in output messages. Default is false.
  • +
  • org.apache.commons.logging.simplelog.dateTimeFormat - + The date and time format to be used in the output messages. + The pattern describing the date and time format is the same that is + used in java.text.SimpleDateFormat. If the format is not + specified or is invalid, the default format is used. + The default format is yyyy/MM/dd HH:mm:ss:SSS zzz.
  • +
+ +

+In addition to looking for system properties with the names specified +above, this implementation also checks for a class loader resource named +"simplelog.properties", and includes any matching definitions +from this resource (if it exists). +

+
+
+

+See the FAQ document +on the commons-logging wiki site +

+
+ + +
diff -Nru libcommons-logging-java-1.1.1/src/site/xdoc/index.xml libcommons-logging-java-1.1.3/src/site/xdoc/index.xml --- libcommons-logging-java-1.1.1/src/site/xdoc/index.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/site/xdoc/index.xml 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,139 @@ + + + + + + + + Overview + Commons Documentation Team + + + + +
+ +

When writing a library it is very useful to log information. However there +are many logging implementations out there, and a library cannot impose the use +of a particular one on the overall application that the library is a part of.

+ +

The Logging package is an ultra-thin bridge between different logging +implementations. A library that uses the commons-logging API can be used with +any logging implementation at runtime. Commons-logging comes with support for a +number of popular logging implementations, and writing adapters for others is a +reasonably simple task.

+ +

Applications (rather than libraries) may also choose to use commons-logging. +While logging-implementation independence is not as important for applications +as it is for libraries, using commons-logging does allow the application to +change to a different logging implementation without recompiling code. +

+Note that commons-logging does not attempt to initialise or terminate the underlying +logging implementation that is used at runtime; that is the responsibility of +the application. However many popular logging implementations do automatically +initialise themselves; in this case an application may be able to avoid +containing any code that is specific to the logging implementation used.

+ +
+ + +
+ +

The +Release Notes document the new features and bug fixes that have been +included in the latest release.

+ +

The +JavaDoc API documents for the latest release are available online. +In particular, you should read the package overview of the org.apache.commons.logging +package. In addition, there is a (short) +User Guide.

+ +

The Wiki site has +the latest updates, an FAQ and much other useful information.

+

+Users needing to become experts or wanting to help develop JCL should +(in addition) consult the Tech Guide. +This gives short introductions to topics such as advanced class loading. +

+
+ + +
+

+Binary and source distributions are available + here. +

+ +

The 1.1.3 release only updates the Bundle-SymbolicName in the manifest + to "org.apache.commons.logging".

+

For a full list of changes since the 1.1.1 release, please refer to the + change-report.

+
+ +

The 1.1.2 release is a packaging of bug fixes since release 1.1.1.

+

For the full details, see the release notes for this version.

+
+ +

+ This release is a minor update to the 1.1 release that fixes a number of bugs, and + resolves packaging issues for maven 1.x and maven 2.x users. +

+

For the full details, see the release notes for this version.

+
+ +

This release makes several changes that are intended to resolve issues that + have been encountered when using commons-logging in servlet containers or j2ee + containers where complex classpaths are present and multiple copies of + commons-logging libraries are present at different levels.

+

This release also adds support for the TRACE level added to log4j in the + 1.2.12 release. In former commons-logging versions, the log.trace method + caused log4j to output the message at the DEBUG level (the lowest level + supported by log4j at that time).

+

For the full details, see the release notes for this version.

+
+ +

+ Note: the 1.0.5 release was abandoned at alpha status. +

+

+ The next JCL release will be designated 1.1 since we feel this more + accurately reflects the improvements made to the codebase.

+
+ +

The 1.0.4 release of commons-logging is a service release containing support + for both the 1.2.x and 1.3.x series of Log4J releases.

+
+ +

The 1.0.3 release is primarily a maintenance and code cleanup release with minimal new features.

+
+ +

The 1.0.2 release is a packaging of bug fixes since release 1.0.1.

+
+ +

The 1.0.1 release is a packaging of bug fixes and minor enhancements since release 1.0.

+
+
+
+

Regular builds of the current SVN HEAD code are made available. See the + wiki for details.

+
+ +
diff -Nru libcommons-logging-java-1.1.1/src/site/xdoc/issue-tracking.xml libcommons-logging-java-1.1.3/src/site/xdoc/issue-tracking.xml --- libcommons-logging-java-1.1.1/src/site/xdoc/issue-tracking.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/site/xdoc/issue-tracking.xml 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,102 @@ + + + + + + Commons Logging Issue tracking + Commons Documentation Team + + + +
+

+ Commons Logging uses ASF JIRA for tracking issues. + See the Commons Logging JIRA project page. +

+ +

+ To use JIRA you may need to create an account + (if you have previously created/updated Commons issues using Bugzilla an account will have been automatically + created and you can use the Forgot Password + page to get a new password). +

+ +

+ If you would like to report a bug, or raise an enhancement request with + Commons Logging please do the following: +

    +
  1. Search existing open bugs. + If you find your issue listed then please add a comment with your details.
  2. +
  3. Search the mailing list archive(s). + You may find your issue or idea has already been discussed.
  4. +
  5. Decide if your issue is a bug or an enhancement.
  6. +
  7. Submit either a bug report + or enhancement request.
  8. +
+

+ +

+ Please also remember these points: +

    +
  • the more information you provide, the better we can help you
  • +
  • test cases are vital, particularly for any proposed enhancements
  • +
  • the developers of Commons Logging are all unpaid volunteers
  • +
+

+ +

+ For more information on subversion and creating patches see the + Apache Contributors Guide. +

+ +

+ You may also find these links useful: +

+

+
+ +
diff -Nru libcommons-logging-java-1.1.1/src/site/xdoc/junit-report.xml libcommons-logging-java-1.1.3/src/site/xdoc/junit-report.xml --- libcommons-logging-java-1.1.1/src/site/xdoc/junit-report.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/site/xdoc/junit-report.xml 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,39 @@ + + + + + + JUnit Test Results + Commons Documentation Team + + + + +
+

+ The Apache Commons Logging test cases make extensive use of + sophisticated classloader configurations in order to simulate the + behaviour of various containers. It is difficult to run these tests + under Maven in the default "test" phase. As a consequence the tests + are executed via the failsafe-plugin as part of the "integration-test" + phase. The reports are available here. +

+
+ + +
diff -Nru libcommons-logging-java-1.1.1/src/site/xdoc/mail-lists.xml libcommons-logging-java-1.1.3/src/site/xdoc/mail-lists.xml --- libcommons-logging-java-1.1.1/src/site/xdoc/mail-lists.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/site/xdoc/mail-lists.xml 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,202 @@ + + + + + + Commons Logging Mailing Lists + Commons Documentation Team + + + +
+

+ Commons Logging shares mailing lists with all the other + Commons Components. + To make it easier for people to only read messages related to components they are interested in, + the convention in Commons is to prefix the subject line of messages with the component's name, + for example: +

    +
  • [logging] Problem with the ...
  • +
+

+

+ Questions related to the usage of Commons Logging should be posted to the + User List. +
+ The Developer List + is for questions and discussion related to the development of Commons Logging. +
+ Please do not cross-post; developers are also subscribed to the user list. +

+

+ Note: please don't send patches or attachments to any of the mailing lists. + Patches are best handled via the Issue Tracking system. + Otherwise, please upload the file to a public server and include the URL in the mail. +

+
+ +
+

+ Please prefix the subject line of any messages for Commons Logging + with [logging] - thanks! +
+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameSubscribeUnsubscribePostArchiveOther Archives
+ Commons User List +

+ Questions on using Commons Logging. +

+
SubscribeUnsubscribePostmail-archives.apache.orgmarkmail.org
+ www.mail-archive.com
+ news.gmane.org +
+ Commons Developer List +

+ Discussion of development of Commons Logging. +

+
SubscribeUnsubscribePostmail-archives.apache.orgmarkmail.org
+ www.mail-archive.com
+ news.gmane.org +
+ Commons Issues List +

+ Only for e-mails automatically generated by the issue tracking system. +

+
SubscribeUnsubscriberead onlymail-archives.apache.orgmarkmail.org
+ www.mail-archive.com +
+ Commons Commits List +

+ Only for e-mails automatically generated by the source control sytem. +

+
SubscribeUnsubscriberead onlymail-archives.apache.orgmarkmail.org
+ www.mail-archive.com +
+ +
+
+

+ Other mailing lists which you may find useful include: +

+ + + + + + + + + + + + + + + + + + +
NameSubscribeUnsubscribePostArchiveOther Archives
+ Apache Announce List +

+ General announcements of Apache project releases. +

+
SubscribeUnsubscriberead onlymail-archives.apache.orgmarkmail.org
+ old.nabble.com
+ www.mail-archive.com
+ news.gmane.org +
+ +
+ +
diff -Nru libcommons-logging-java-1.1.1/src/site/xdoc/proposal.xml libcommons-logging-java-1.1.3/src/site/xdoc/proposal.xml --- libcommons-logging-java-1.1.1/src/site/xdoc/proposal.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/site/xdoc/proposal.xml 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,127 @@ + + + + +Proposal for Logging Library Package + + + + +
+ + + + + +

There is a great need for debugging and logging information inside of +Commons components such as HTTPClient and dbcp. However, there are many +logging APIs out there and it is difficult to choose among them. +

+ +

The Logging package will be an ultra-thin bridge between different logging +libraries. Commons components may use the Logging JAR to remove +compile-time/runtime dependencies on any particular logging package, +and contributors may write Log implementations for the library of their choice. +

+ +
+ + +

The package shall create and maintain a package that provides extremely +basic logging functionality and bridges to other, more sophisticated logging +implementations. +

+ +

+The package should : +

    +
  • Have an API which should be as simple to use as possible
  • +
  • Provide support for log4j
  • +
  • Provide pluggable support for other logging APIs
  • +
+

+ +

+Non-goals: +

    +
  • This package will not perform logging itself, except at the most basic + level.
  • +
  • We do not seek to become a "standard" API.
  • +
+

+ +
+ + +

Logging relies on: +

+ +
    +
  • Java Development Kit (Version 1.1 or later)
  • +
  • Avalon Framework (compile-time dependency only unless this Log + implementation is selected at runtime)
  • +
  • Avalon LogKit (compile-time dependency only unless this Log + implementation is selected at runtime)
  • +
  • JDK 1.4 (compile-time dependency only unless this log implementation + is selected at runtime).
  • +
  • Log4J (compile-time dependency only unless this Log + implementation is selected at runtime)
  • +
  • Lumberjack + (compile-time dependency only unless this Log + implementation is selected at runtime)
  • +
+ +
+ + +
    +
  • CVS Repository - New directory logging in the +jakarta-commons CVS repository.
  • + +
  • Initial Committers - The list is provided below.
  • + +
  • Mailing List - Discussions will take place on the general +dev@commons.apache.org mailing list. To help list +subscribers identify messages of interest, it is suggested that the +message subject of messages about this component be prefixed with +[Logging].
  • + +
  • Bugzilla - New component "Logging" under the "Commons" product +category, with appropriate version identifiers as needed.
  • + +
  • Jyve FAQ - New category "commons-logging" (when available).
  • +
+ + +
+ + +

The initial committers on the Logging component shall be:

+ +
    +
  • Morgan Delagrange
  • +
  • Rodney Waldhoff
  • +
  • Craig McClanahan
  • +
+ +
+
+ +
diff -Nru libcommons-logging-java-1.1.1/src/site/xdoc/tech.xml libcommons-logging-java-1.1.3/src/site/xdoc/tech.xml --- libcommons-logging-java-1.1.1/src/site/xdoc/tech.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/site/xdoc/tech.xml 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,653 @@ + + + + + + + + Technology Guide + Commons Documentation Team + + + +
+ + + + +

+ This guide is aimed at describing the technologies that JCL developers and expert users + (and users who need to become experts) + should be familiar with. The aim is to give an understanding whilst being precise but brief. + Details which are not relevant for JCL have been suppressed. + References have been included. +

+

+ These topics are a little difficult and it's easy for even experienced developers to make + mistakes. We need you to help us get it right! Please submit corrections, comments, additional references + and requests for clarification + by either: +

+ +

+ TIA +

+
+ +
+
+ +

+ This is intended to present a guide to the process by which Java bytecode uses bytecode in other classes + from the perspective of the language and virtual machine specifications. The focus will be on deciding + which bytecode will be used (rather than the mechanics of the usage). It focuses on facts and terminology. +

+

+ The process is recursive: it is therefore difficult to pick a starting point. + Sun's documentation starts from the perspective of the startup of a new application. + This guide starts from the perspective of an executing application. +

+

+ During this discussion, please assume that each time that class is mentioned, + the comments applied equally well to interfaces. +

+

+ This document is targeted at Java 1.2 and above. +

+
+ +

+ (LangSpec 12.3.3) + The bytecode representation of a class contains symbolic names for other classes referenced. +

+

+ + In practical development terms: If a class is imported (either explicitly in the list of imports at the top of + the source file or implicitly through a fully qualified name in the source code) it is referenced symbolically. + +

+

+ (VMSpec 5.4.3) + Resolution of a symbolic reference occurs dynamically at runtime and is carried out by + the Java Virtual Machine. Resolution of a symbolic reference requires loading and linking of the new class. +

+

+ + Note: references are not statically resolved at compile time. + +

+
+ +

+ (VMSpec 2.17.2) + Loading is the name given to the process by which a binary form of a class is obtained + by the Java Virtual Machine. + Java classes are always loaded and linked dynamically by the Java Virtual Machine + (rather than statically by the compiler). +

+

+ + In practical development terms: + This means that the developer has no certain knowledge about the actual + bytecode that will be used to execute any external call (one made outside the class). This is determined only + at execution time and is affected by the way that the code is deployed. + +

+
+ +

+ (VMSpec 2.17.3) + Linking is the name used for combining the + binary form of a class into the Java Virtual Machine. This must happen before the class can be used. +

+

+ (VMSpec 2.17.3) + Linking is composed of verification, preparation and resolution (of symbolic references). + Flexibility is allowed over the timing of resolution. (Within limit) this may happen at any time after + preparation and before that reference is used. +

+

+ + In practical development terms: This means that different JVMs may realize that a reference cannot be + resolved at different times during execution. Consequently, the actual behaviour cannot be precisely predicted + without intimate knowledge of the JVM (on which the bytecode will be executed). + This makes it hard to give universal guidance to users. + +

+
+ + +

+ (VMSpec 2.17.2) + The loading process is performed by a ClassLoader. +

+

+ (VMSpec 5.3) + A classloader may create a class either by delegation or by defining it directly. + The classloader that initiates loading of a class is known as the initiating loader. + The classloader that defines the class is known as the defining loader. +

+

+ + In practical terms: understanding and appreciating this distinction is crucial when debugging issues + concerning classloaders. + +

+
+ + +

+ (VMSPEC 5.3) + The bootstrap is the base ClassLoader supplied by the Java Virtual Machine. + All others are user (also known as application) ClassLoader instances. +

+

+ + In practical development terms: The System classloader returned by Classloader.getSystemClassLoader() + will be either the bootstrap classloader or a direct descendant of the bootstrap classloader. + Only when debugging issues concerning the system classloader should there be any need to consider the detailed + differences between the bootstrap classloader and the system classloader. + +

+
+ +

+ (VMSpec 5.3) + At runtime, a class (or interface) is determined by its fully qualified name + and by the classloader that defines it. This is known as the class's runtime package. +

+

+ (VMSpec 5.4.4) + Only classes in the same runtime package are mutually accessible. +

+

+ + In practical development terms: two classes with the same symbolic name can only be used interchangeably + if they are defined by the same classloader. A classic symptom indicative of a classloader issue is that + two classes with the same fully qualified name are found to be incompatible during a method call. + This may happen when a member is expecting an interface which is (seemingly) implemented by a class + but the class is in a different runtime package after being defined by a different classloader. This is a + fundamental java language security feature. + +

+
+ + +

+ (VMSpec 5.3) + The classloader which defines the class (whose reference is being resolved) is the one + used to initiate loading of the class referred to. +

+

+ + In practical development terms: This is very important to bear in mind when trying to solve classloader issues. + A classic misunderstanding is this: suppose class A defined by classloader C has a symbolic reference to + class B and further that when C initiates loading of B, this is delegated to classloader D which defines B. + Class B can now only resolve symbols that can be loaded by D, rather than all those which can be loaded by C. + This is a classic recipe for classloader problems. + +

+
+ + +
    +
  • + VMSpec The Java Virtual Machine Specification, Second Edition +
  • +
  • + LangSpec The Java Language Specification, Second Edition +
  • +
+
+
+
+ +

+ When asked to load a class, a class loader may either define the class itself or delegate. + The base ClassLoader class insists that every implementation has a parent class loader. + This delegation model therefore naturally forms a tree structure rooted in the bootstrap classloader. +

+

+ Containers (i.e. applications such as servlet engines or application servers + that manage and provide support services for a number of "contained" applications + that run inside of them) often use complex trees to allow isolation of different applications + running within the container. This is particularly true of J2EE containers. +

+
+ + +

+ When a classloader is asked to load a class, a question presents itself: should it immediately + delegate the loading to its parent (and thus only define those classes not defined by its parent) + or should it try to define it first itself (and only delegate to its parent those classes it does + not itself define). Classloaders which universally adopt the first approach are termed parent-first + and the second child-first. +

+

+ Note: the term child-first (though commonly used) is misleading. + A better term (and one which may be encountered on the mailing list) is parent-last. + This more accurately describes the actual process of classloading performed + by such a classloader. +

+

+ Parent-first loading has been the standard mechanism in the JDK + class loader, at least since Java 1.2 introduced hierarchical classloaders. +

+

+ Child-first classloading has the advantage of helping to improve isolation + between containers and the applications inside them. If an application + uses a library jar that is also used by the container, but the version of + the jar used by the two is different, child-first classloading allows the + contained application to load its version of the jar without affecting the + container. +

+

+ The ability for a servlet container to offer child-first classloading + is made available, as an option, by language in the servlet spec (Section + 9.7.2) that allows a container to offer child-first loading with + certain restrictions, such as not allowing replacement of java.* or + javax.* classes, or the container's implementation classes. +

+

+ Though child-first and parent-first are not the only strategies possible, + they are by far the most common. + All other strategies are rare. + However, it is not uncommon to be faced with a mixture of parent-first and child-first + classloaders within the same hierarchy. +

+
+ + +

+ The class loader used to define a class is available programmatically by calling + the getClassLoader method + on the class in question. This is often known as the class classloader. +

+
+ + +

+ Java 1.2 introduces a mechanism which allows code to access classloaders + which are not the class classloader or one of its parents. + A thread may have a class loader associated with it by its creator for use + by code running in the thread when loading resources and classes. + This classloader is accessed by the getContextClassLoader + method on Thread. It is therefore often known as the context classloader. +

+

+ Note that the quality and appropriateness of the context classloader depends on the + care with which the thread's owner manages it. +

+
+ + +

+ The Javadoc for + + Thread.setContextClassLoader emphasizes the setting of the + context classloader as an aspect of thread creation. However, in many + applications the context classloader is not fixed at thread creation but + rather is changed throughout the life of a thread as thread execution moves + from one context to another. This usage of the context classloader is + particularly important in container applications. +

+

+ For example, in a hypothetical servlet container, a pool of threads + is created to handle HTTP requests. When created these threads have their + context classloader set to a classloader that loads container classes. + After the thread is assigned to handle a request, container code parses + the request and then determines which of the deployed web applications + should handle it. Only when the container is about to call code associated + with a particular web application (i.e. is about to cross an "application + boundary") is the context classloader set to the classloader used to load + the web app's classes. When the web application finishes handling the + request and the call returns, the context classloader is set back to the + container classloader. +

+

+ In a properly managed container, changes in the context classloader are + made when code execution crosses an application boundary. When contained + application A is handling a request, the context classloader + should be the one used to load A's resources. When application + B is handling a request, the context classloader should be + B's. +

+

+ While a contained application is handling a request, it is not + unusual for it to call system or library code loaded by the container. + For example, a contained application may wish to call a utility function + provided by a shared library. This kind of call is considered to be + within the "application boundary", so the context classloader remains + the contained application's classloader. If the system or library code + needs to load classes or other resources only visible to the contained + application's classloader, it can use the context classloader to access + these resources. +

+

+ If the context classloader is properly managed, system and library code + that can be accessed by multiple applications can not only use it to load + application-specific resources, but also can use it to detect which + application is making a call and thereby provided services tailored to the + caller. +

+
+ + +

+ In practice, context classloaders vary in quality and issues sometimes arise + when using them. + The owner of the thread is responsible for setting the classloader. + If the context classloader is not set then it will default to the system + classloader. + Any container doing so will cause difficulties for any code using the context classloader. +

+

+ The owner is also at liberty to set the classloader as they wish. + Containers may set the context classloader so that it is neither a child nor a parent + of the classloader that defines the class using that loader. + Again, this will cause difficulties. +

+

+ Introduced in Java J2EE 1.3 + is a requirement for vendors to appropriately set the context classloader. + Section 6.2.4.8 (1.4 text): +

+ +This specification requires that J2EE containers provide a per thread +context class loader for the use of system or library classes in +dynamically loading classes provided by the application. The EJB +specification requires that all EJB client containers provide a per +thread context class loader for dynamically loading system value classes. +The per thread context class loader is accessed using the Thread method +getContextClassLoader. + +The classes used by an application will typically be loaded by a +hierarchy of class loaders. There may be a top level application class +loader, an extension class loader, and so on, down to a system class +loader. The top level application class loader delegates to the lower +class loaders as needed. Classes loaded by lower class loaders, such as +portable EJB system value classes, need to be able to discover the top +level application class loader used to dynamically load application +classes. + +We require that containers provide a per thread context class loader +that can be used to load top level application classes as described +above. + +

+ This specification leaves quite a lot of freedom for vendors. + (As well as using unconventional terminology and containing the odd typo.) + It is a difficult passage (to say the least). +

+
+ + +

+ Reflection cannot bypass restrictions imposed by the java language security model, but, by avoiding symbolic + references, reflection can be used to load classes which could not otherwise be loaded. Another ClassLoader + can be used to load a class and then reflection used to create an instance. +

+

+ Recall that the runtime packaging is used to determine accessibility. + Reflection cannot be used to avoid basic java security. + Therefore, the runtime packaging becomes an issue when attempting to cast classes + created by reflection using other class loaders. + When using this strategy, various modes of failure are possible + when common class references are defined by the different class loaders. +

+

+ Reflection is often used with the context classloader. In theory, this allows a class defined in + a parent classloader to load any class that is loadable by the application. + In practice, this only works well when the context classloader is set carefully. +

+
+ + + + +
+ +
+ +

+ JCL takes the view that different context class loader indicate boundaries between applications + running in a container environment. Isolation requires that JCL honours these boundaries + and therefore allows different isolated applications to configure their logging systems + independently. +

+
+ +

+ Performance dictates that symbolic references to these classes are present in the calling application code + (reflection would simply be too slow). Therefore, these classes must be loadable by the classloader + that loads the application code. +

+
+ +

+ Performance dictates that symbolic references to the logging systems are present in the implementation + classes (again, reflection would simply be too slow). So, for an implementation to be able to function, + it is necessary for the logging system to be loadable by the classloader that defines the implementing class. +

+
+ + +

+ However, there is actually no reason why LogFactory requires symbolic references to particular Log + implementations. Reflection can be used to load these from an appropriate classloader + without unacceptable performance degradation. + This is the strategy adopted by JCL. +

+

+ JCL uses the context classloader to load the Log implementation. +

+
+
+ +
diff -Nru libcommons-logging-java-1.1.1/src/site/xdoc/troubleshooting.xml libcommons-logging-java-1.1.3/src/site/xdoc/troubleshooting.xml --- libcommons-logging-java-1.1.1/src/site/xdoc/troubleshooting.xml 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/site/xdoc/troubleshooting.xml 2013-05-16 20:04:22.000000000 +0000 @@ -0,0 +1,467 @@ + + + + + + + + Troubleshooting Guide + Commons Documentation Team + + + +
+
+
+

+Diagnostics is a feature introduced in JCL 1.1 as an aid to debugging problems +with JCL configurations. When diagnostics are switched on, messages are logged +to a stream (specified by the user) by the two main classes involved in discovery +in JCL (LogFactory and LogFactoryImpl). +

+

+Diagnostics are intended to be used in conjunction with the source. The source +contains numerous and lengthy comments. Often these are intended to help explain +the meaning of the messages. +

+ +

+Diagnostic logging is intended only to be used when debugging a problematic +configuration. It should be switched off for production. +

+
+ +

+Diagnostic logging is controlled through the system property +org.apache.commons.logging.diagnostics.dest. Setting the property value +to the special strings STDOUT or STDERR (case-sensitive) +will output messages to System.out and System.err respectively. +Setting the property value to a valid file name will result in the messages being logged +to that file. +

+
+ +

+Diagnostics uses the concept of an Object ID (OID). This allows the identity of objects +to be tracked without relying on useful toString implementations. +These are of the form: +

+
+classname@system identity hash code
+
+

+The system identity hash code is found by calling System.identityHashCode() +which should uniquely identify a particular instance. The classname is usually the fully qualified +class name though in a few cases, org.apache.commons.logging.impl.LogFactoryImpl may be +shortened to LogFactoryImpl to increase ease of reading. For example: +

+
+sun.misc.Launcher$AppClassLoader@20120943
+LogFactoryImpl@1671711
+
+

+OIDs are intended to be used to cross-reference. They allow particular instances of classloaders +and JCL classes to be tracked in different contexts. This plays a vital role in building +up the understanding of the classloader environment required to diagnose JCL problems. +

+
+ +

+Each diagnostic message is prefixed with details of the relevant class in a standard format. +This takes the form: +

+
+[class-identifier from ClassLoader OID]
+
+

+ClassLoader OID is the OID of a classloader which loaded +the class issuing the message. +class-identifier identifies the object issuing the message. +

+

+In the case of +LogFactory, this is just LogFactory. For example (line split): +

+
+[LogFactory 
+   from sun.misc.Launcher$AppClassLoader@20120943] BOOTSTRAP COMPLETED
+
+

+In the case of +LogFactoryImpl, the prefix is the instance OID. This can be cross referenced +to discover the details of the TCCL used to manage this instance. For example (line split): +

+
+[LogFactoryImpl@1671711 
+   from sun.misc.Launcher$AppClassLoader@20120943] Instance created.
+
+
+ +

+Understanding the relationships between classloaders is vital when debugging JCL. +At various points, JCL will print to the diagnostic log the hierarchy for important +classloaders. This is obtained by walking the tree using getParent. +Each classloader is represented (visually) by an OID (to allow cross referencing) +and the relationship indicated in child --> parent fashion. +For example (line split for easy reading): +

+
+ClassLoader tree:java.net.URLClassLoader@3526198  
+      --> sun.misc.Launcher$AppClassLoader@20120943 (SYSTEM) 
+      --> sun.misc.Launcher$ExtClassLoader@11126876 
+      --> BOOT
+
+

+Represents a hierarchy with four elements ending in the boot classloader. +

+
+ +

+Whenever the LogFactory class is initialized, diagnostic messages about +the classloader environment are logged. The content of each of these messages is prefixed by +[ENV] to help distinguish them. The extension directories, application classpath, +details of the classloader (including the OID and toString +value) used to load LogFactory and the +classloader tree for that classloader +are logged. +

+

+Many Sun classloaders have confusing toString values. For example, the OID may be +

+
+sun.misc.Launcher$AppClassLoader@20120943
+
+

+with a toString value of +

+
+sun.misc.Launcher$AppClassLoader@133056f
+
+

+Other classloader implementations may give very useful information (such as the local classpath). +

+

+Finally, once initialization is complete a BOOTSTRAP COMPLETED message is issued. +

+
+ +

+LogFactoryImpl is the standard and default LogFactory implementation. +This section obviously only applies to configurations using this implementation. +

+

+Before assigning a Log instance, LogFactory loads a +LogFactory implementation. The content is prefixed by [LOOKUP] +for each diagnostic message logged by this process. +

+

+The implementation used can vary per Thread context classloader (TCCL). If this is the first time +that a Log has been requested for a particular TCCL a new instance will be created. +

+

+Information of particular interest is logged at this stage. Details of the TCCL are logged +allowing the OID later to be cross-referenced to the toString value +and the classloader tree. For example, the +following log snippet details the TCCL (lines split): +

+
+[LogFactory from sun.misc.Launcher$AppClassLoader@20120943] 
+    [LOOKUP] LogFactory implementation requested for the first time for context 
+        classloader java.net.URLClassLoader@3526198
+[LogFactory from sun.misc.Launcher$AppClassLoader@20120943] 
+    [LOOKUP] java.net.URLClassLoader@3526198 == 'java.net.URLClassLoader@35ce36'
+[LogFactory from sun.misc.Launcher$AppClassLoader@20120943] 
+    [LOOKUP] ClassLoader tree:java.net.URLClassLoader@3526198 
+        --> sun.misc.Launcher$AppClassLoader@20120943 (SYSTEM)  
+          --> sun.misc.Launcher$ExtClassLoader@11126876 
+            --> BOOT
+
+
+ +

+The standard LogFactoryImpl issues many diagnostic messages when discovering +the Log implementation to be used. +

+

+During discovery, environment variables are loaded and values set. This content is prefixed by +[ENV] to make it easier to distinguish this material. +

+

+The possible messages issued during discovery are numerous. To understand them, the source +should be consulted. Attention should be paid to the classloader hierarchy trees for the +classloader used to load LogFactory and to the TCCL. +

+
+
+
+

+ Some containers use a custom LogFactory implementation to adapt JCL to their particular + logging system. This has some important consequences for the deployment of applications using JCL within + these containers. +

+

+ Containers known to use this mechanism: +

+ +

+ Containers suspected to use this mechanism: +

+
    +
  • WebSphere Application Server (other versions).
  • +
+

+The Apache Commons team would be grateful if reports were posted to the development list +of other containers using a custom implementation. +

+ + +

+ An exception is thrown by JCL with a message similar to: +

+
+  The chosen LogFactory implementation does not extend LogFactory. Please check your configuration. 
+  (Caused by java.lang.ClassCastException: The application has specified that a custom LogFactory 
+  implementation should be used but Class 'com.ibm.ws.commons.logging.TrLogFactory' cannot be converted 
+  to 'org.apache.commons.logging.LogFactory'. The conflict is caused by the presence of multiple 
+  LogFactory classes in incompatible classloaders. Background can be found in 
+  http://commons.apache.org/logging/tech.html. If you have not explicitly specified a custom
+  LogFactory then it is likely that the container has set one without your knowledge. 
+  In this case, consider using the commons-logging-adapters.jar file or specifying the standard 
+  LogFactory from the command line. Help can be found @http://commons.apache.org/logging.
+  
+

+ This is a WebSphere example so the name of the custom LogFactory is + com.ibm.ws.commons.logging.TrLogFactory. For other containers, this class name will + differ. +

+
+ +

+ A custom LogFactory implementation can only be used if the implementation class loaded + dynamically at runtime can be cast to the LogFactory class that loaded it. There are + several ways in which this cast can fail. The most obvious is that the source code may not actually + extend LogFactory. The source may be compatible but if the LogFactory class + against which the source is compiled is not binary compatible then the cast will also fail. +

+

+ There is also another more unusual way in which this cast can fail: even when the binary is compatible, + the implementation class loaded at runtime may be linked to a different instance of the + LogFactory class. For more information, see the tech guide. +

+

+ This situation may be encountered in containers which use a custom LogFactory implementation. + The implementation will typically be provided in a shared, high level classloader together with JCL. + When an application classloader contains LogFactory, the implementation will be loaded + from that higher level classloader. The implementation class will be linked to the LogFactory + class loaded by the higher level classloader. Even if the + LogFactory implementations are binary compatible, since they are loaded by different classloaders + the two LogFactory Class instances are not equal and so the cast must fail. +

+

+The policy adopted by JCL in this situation is to re-throw this exception. Additional information +is included in the message to help diagnosis. The reasoning behind this choice is that a +particular LogFactory implementation has been actively specified and this +choice should not be ignored. This policy has unfortunate consequences when running in +containers which have custom implementations: the above runtime exception may be thrown +under certain classloading policies without the user knowingly specifying a custom +implementation. +

+
+ +

+ There are various ways to fix this problem. Which fix is right depends on the circumstances. +

+

+ If you are happy using another classloading policy for the application, select a + classloading policy which ensures that LogFactory will be loaded from the + shared classloader containing the custom implementation. +

+

+ If you want to bypass the container adaption mechanism then set the appropriate system property + to the default value when the container is started: +

+
+ -Dorg.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
+ 
+

+ If you want to continue to use the default container mechanism then: +

+
    +
  • + Find and replace the commons-logging implementation used by the container with + the most modern release +
  • +
  • + Replace the commons-logging jar in the application with the commons-logging-adapters jar. + This will ensure that application classloader will delegate to it's parent when loading + LogFactory. +
  • +
+

+ If you encounter difficulties when applying the fixes recommended, please turn on + diagnostics and consult the logs. +

+
+
+
+
+

+ Because commons-logging is such a fundamental library, some containers modify the way + in which classloading behaves for commons-logging classes. +

+ +

+ At the current date, Tomcat 5.5.16 is the current release. All releases from version + 4.1.x through 5.5.16 have a startup process that places jarfile + ${tomcat.home}/bin/commons-logging-api.jar in the system classpath and then + prevents any webapp from overriding the classes in that jarfile. Effectively, all + webapps behave as if "parent-first" classloading were enabled for those classes. +

+

+ This has some benefits; in particular it means that there are no problems in + these Tomcat versions with having multiple copies of the commons-logging Log + interface in the classpath (which avoids the "Log does not implement Log" + problem described elsewhere). +

+

+ However it also means that no webapp can override the core commons-logging + classes by including an updated commons-logging jarfile in WEB-INF/lib; any + class already loaded via the container takes priority. In particular, as + Tomcat bundles logging 1.0.4 only, the new diagnostics and memory-leak-prevention + features of the 1.1 release will not be available unless the container's + library version is updated. +

+

+ Because the commons-logging-api.jar in the container does not contain any + log-library-adapter classes, updated behaviour for these will be + seen when logging 1.1 is bundled in WEB-INF/lib. In particular, the + support for log4j's TRACE level will take effect without having to update + the container. +

+

+ If you do wish to update Tomcat's version of commons-logging, then you + must use the commons-logging-1.1-api jar only, not the full jar. + Classes in the webapp cannot override classes loaded from the system + classpath set up during Tomcat's startup process, and logging adapters + can only see their matching concrete logging library if that library is + available in the same classpath. Bundling the full commons-logging jarfile + (with adapters) into the system classpath therefore means that logging + libraries (eg log4j) within WEB-INF/lib are not accessible. +

+

+ Note that the behaviour described here only applies if the standard Tomcat + startup process is run. When Tomcat is embedded in a larger + framework (eg run embedded within an IDE) this may not apply. +

+
+ +

+ The JBoss Application Server can be configured to prevent deployed + code from overriding classes higher in the hierarchy, effectively + forcing "parent-first" behaviour for selected classes. By default, + commons-logging is in this list (at least for some JBoss versions + starting with 4.0.2), and therefore including an updated version + of commons-logging in WEB-INF/lib or similar will have no effect. + See the JBoss classloading documentation for more details. +

+
+ +

+ As more information becomes available on this topic, it may be added + to the commons-logging wiki site. +

+
+
+ +
diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/AbstractLogTest.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/AbstractLogTest.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/AbstractLogTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/AbstractLogTest.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging; + +import junit.framework.TestCase; + + +/** + * Generic tests that can be applied to any log adapter by + * subclassing this class and defining method getLogObject + * appropriately. + * + * @author Sean C. Sullivan + * @version $Revision: 1432587 $ + */ +public abstract class AbstractLogTest extends TestCase { + + public abstract Log getLogObject(); + + public void testLoggingWithNullParameters() + { + Log log = this.getLogObject(); + + assertNotNull(log); + + + log.debug(null); + + log.debug(null, null); + + log.debug(log.getClass().getName() + ": debug statement"); + + log.debug(log.getClass().getName() + ": debug statement w/ null exception", new RuntimeException()); + + + log.error(null); + + log.error(null, null); + + log.error(log.getClass().getName() + ": error statement"); + + log.error(log.getClass().getName() + ": error statement w/ null exception", new RuntimeException()); + + + log.fatal(null); + + log.fatal(null, null); + + log.fatal(log.getClass().getName() + ": fatal statement"); + + log.fatal(log.getClass().getName() + ": fatal statement w/ null exception", new RuntimeException()); + + + log.info(null); + + log.info(null, null); + + log.info(log.getClass().getName() + ": info statement"); + + log.info(log.getClass().getName() + ": info statement w/ null exception", new RuntimeException()); + + + log.trace(null); + + log.trace(null, null); + + log.trace(log.getClass().getName() + ": trace statement"); + + log.trace(log.getClass().getName() + ": trace statement w/ null exception", new RuntimeException()); + + + log.warn(null); + + log.warn(null, null); + + log.warn(log.getClass().getName() + ": warn statement"); + + log.warn(log.getClass().getName() + ": warn statement w/ null exception", new RuntimeException()); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/AltHashtable.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/AltHashtable.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/AltHashtable.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/AltHashtable.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging; + +import java.util.Hashtable; + +public class AltHashtable extends Hashtable { + + /** + * Generated serial version ID. + */ + private static final long serialVersionUID = 8927996458633688095L; + + public static Object lastKey; + public static Object lastValue; + + public Object put(Object key, Object value) { + lastKey = key; + lastValue = value; + return super.put(key, value); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/AltHashtableTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/AltHashtableTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/AltHashtableTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/AltHashtableTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging; + +import junit.framework.Test; +import junit.framework.TestCase; + +/** + * Test the ability to force the LogFactory class to use some + * arbitrary Hashtable implementation to store its mapping from + * context-classloader -> LogFactory object. + */ +public class AltHashtableTestCase extends TestCase { + + public static Test suite() throws Exception { + Class thisClass = AltHashtableTestCase.class; + ClassLoader thisClassLoader = thisClass.getClassLoader(); + + PathableClassLoader loader = new PathableClassLoader(null); + loader.useExplicitLoader("junit.", thisClassLoader); + loader.addLogicalLib("testclasses"); + loader.addLogicalLib("commons-logging"); + + Class testClass = loader.loadClass(thisClass.getName()); + return new PathableTestSuite(testClass, loader); + } + + /** + * Set up before each test. + *

+ * This method ensures that the appropriate system property is defined + * to force the LogFactory class to use the AltHashtable class as its + * Hashtable implementation for storing factories in. + *

+ * This does make the assumption that whatever JVM we are running in + * doesn't initialise classes until they are actually referenced (ie the + * LogFactory class hasn't been initialised before this method is called). + * This is true of all JVMs I know of; and if it isn't then this test will + * fail and someone will tell us. + */ + public void setUp() { + System.setProperty( + "org.apache.commons.logging.LogFactory.HashtableImpl", + AltHashtable.class.getName()); + } + + /** + * Verify that initialising the LogFactory class will cause it + * to instantiate an object of type specified in system property + * "org.apache.commons.logging.LogFactory.HashtableImpl". + */ + public void testType() { + // Here, the reference to the LogFactory class should cause the + // class to be loaded and initialised. It will see the property + // set and use the AltHashtable class. If other tests in this + // class have already been run within the same classloader then + // LogFactory will already have been initialised, but that + // doesn't change the effectiveness of this test. + assertTrue(LogFactory.factories instanceof AltHashtable); + } + + /** + * Verify that when LogFactory sees a context-classloader for the + * first time that it creates a new entry in the LogFactory.factories + * hashmap. In particular, this checks that this process works ok when + * a system property has been used to specify an alternative Hashtable + * implementation for LogFactory to use. + */ + public void testPutCalled() throws Exception { + AltHashtable.lastKey = null; + AltHashtable.lastValue = null; + + LogFactory.getLog(AltHashtableTestCase.class); + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + assertEquals(contextLoader, AltHashtable.lastKey); + assertNotNull(AltHashtable.lastValue); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/BadHashtablePropertyTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/BadHashtablePropertyTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/BadHashtablePropertyTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/BadHashtablePropertyTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging; + +import junit.framework.TestCase; +import java.util.Hashtable; + +/** + * Tests behaviour when the property is misconfigured. + */ +public class BadHashtablePropertyTestCase extends TestCase { + + public void testType() { + assertTrue(LogFactory.factories instanceof Hashtable); + } + + public void testPutCalled() throws Exception { + LogFactory.getLog(BadHashtablePropertyTestCase.class); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/BasicOperationsTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/BasicOperationsTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/BasicOperationsTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/BasicOperationsTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging; + +import junit.framework.TestCase; + +/** + * Tests the basic logging operations to ensure that they all function + * without exception failure. In other words, that they do no fail by + * throwing exceptions. + * This is the minimum requirement for any well behaved logger + * and so this test should be run for each kind. + */ +public class BasicOperationsTestCase extends TestCase +{ + public void testIsEnabledClassLog() + { + Log log = LogFactory.getLog(BasicOperationsTestCase.class); + executeIsEnabledTest(log); + } + + public void testIsEnabledNamedLog() + { + Log log = LogFactory.getLog(BasicOperationsTestCase.class.getName()); + executeIsEnabledTest(log); + } + + public void executeIsEnabledTest(Log log) + { + try + { + log.isTraceEnabled(); + log.isDebugEnabled(); + log.isInfoEnabled(); + log.isWarnEnabled(); + log.isErrorEnabled(); + log.isFatalEnabled(); + } + catch (Throwable t) + { + t.printStackTrace(); + fail("Exception thrown: " + t); + } + } + + public void testMessageWithoutExceptionClassLog() + { + Log log = LogFactory.getLog(BasicOperationsTestCase.class); + executeMessageWithoutExceptionTest(log); + } + + public void testMessageWithoutExceptionNamedLog() + { + Log log = LogFactory.getLog(BasicOperationsTestCase.class.getName()); + executeMessageWithoutExceptionTest(log); + } + + public void executeMessageWithoutExceptionTest(Log log) + { + try + { + log.trace("Hello, Mum"); + log.debug("Hello, Mum"); + log.info("Hello, Mum"); + log.warn("Hello, Mum"); + log.error("Hello, Mum"); + log.fatal("Hello, Mum"); + } + catch (Throwable t) + { + t.printStackTrace(); + fail("Exception thrown: " + t); + } + } + + public void testMessageWithExceptionClassLog() + { + Log log = LogFactory.getLog(BasicOperationsTestCase.class); + executeMessageWithExceptionTest(log); + } + + public void testMessageWithExceptionNamedLog() + { + Log log = LogFactory.getLog(BasicOperationsTestCase.class.getName()); + executeMessageWithExceptionTest(log); + } + + public void executeMessageWithExceptionTest(Log log) + { + try + { + log.trace("Hello, Mum", new ArithmeticException()); + log.debug("Hello, Mum", new ArithmeticException()); + log.info("Hello, Mum", new ArithmeticException()); + log.warn("Hello, Mum", new ArithmeticException()); + log.error("Hello, Mum", new ArithmeticException()); + log.fatal("Hello, Mum", new ArithmeticException()); + } + catch (Throwable t) + { + t.printStackTrace(); + fail("Exception thrown: " + t); + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/DummyException.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/DummyException.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/DummyException.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/DummyException.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging; + +/** + * Dummy exception that unit tests create instances of when they want to test + * logging of an Exception object. + */ +public class DummyException extends Exception { + private static final long serialVersionUID = 1L; + public DummyException() { + // super("Dummy Exception for unit testing"); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/LoadTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/LoadTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/LoadTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/LoadTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,225 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging; + +import junit.framework.TestCase; + +/** + * testcase to emulate container and application isolated from container + * @author baliuka + * @version $Id: LoadTestCase.java 1432587 2013-01-13 11:11:32Z tn $ + */ +public class LoadTestCase extends TestCase{ + //TODO: need some way to add service provider packages + static private String LOG_PCKG[] = {"org.apache.commons.logging", + "org.apache.commons.logging.impl"}; + + /** + * A custom classloader which "duplicates" logging classes available + * in the parent classloader into itself. + *

+ * When asked to load a class that is in one of the LOG_PCKG packages, + * it loads the class itself (child-first). This class doesn't need + * to be set up with a classpath, as it simply uses the same classpath + * as the classloader that loaded it. + */ + static class AppClassLoader extends ClassLoader{ + + java.util.Map classes = new java.util.HashMap(); + + AppClassLoader(ClassLoader parent){ + super(parent); + } + + private Class def(String name)throws ClassNotFoundException{ + + Class result = (Class)classes.get(name); + if(result != null){ + return result; + } + + try{ + + ClassLoader cl = this.getClass().getClassLoader(); + String classFileName = name.replace('.','/') + ".class"; + java.io.InputStream is = cl.getResourceAsStream(classFileName); + java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream(); + + while(is.available() > 0){ + out.write(is.read()); + } + + byte data [] = out.toByteArray(); + + result = super.defineClass(name, data, 0, data.length ); + classes.put(name,result); + + return result; + + }catch(java.io.IOException ioe){ + + throw new ClassNotFoundException( name + " caused by " + + ioe.getMessage() ); + } + + + } + + // not very trivial to emulate we must implement "findClass", + // but it will delegete to junit class loder first + public Class loadClass(String name)throws ClassNotFoundException{ + + //isolates all logging classes, application in the same classloader too. + //filters exeptions to simlify handling in test + for(int i = 0; i < LOG_PCKG.length; i++ ){ + if( name.startsWith( LOG_PCKG[i] ) && + name.indexOf("Exception") == -1 ){ + return def(name); + } + } + return super.loadClass(name); + } + + } + + + /** + * Call the static setAllowFlawedContext method on the specified class + * (expected to be a UserClass loaded via a custom classloader), passing + * it the specified state parameter. + */ + private void setAllowFlawedContext(Class c, String state) throws Exception { + Class[] params = {String.class}; + java.lang.reflect.Method m = c.getDeclaredMethod("setAllowFlawedContext", params); + m.invoke(null, new Object[] {state}); + } + + /** + * Test what happens when we play various classloader tricks like those + * that happen in web and j2ee containers. + *

+ * Note that this test assumes that commons-logging.jar and log4j.jar + * are available via the system classpath. + */ + public void testInContainer()throws Exception{ + + //problem can be in this step (broken app container or missconfiguration) + //1. Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); + //2. Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); + // we expect this : + // 1. Thread.currentThread().setContextClassLoader(appLoader); + // 2. Thread.currentThread().setContextClassLoader(null); + + // Context classloader is same as class calling into log + Class cls = reload(); + Thread.currentThread().setContextClassLoader(cls.getClassLoader()); + execute(cls); + + // Context classloader is the "bootclassloader". This is technically + // bad, but LogFactoryImpl.ALLOW_FLAWED_CONTEXT defaults to true so + // this test should pass. + cls = reload(); + Thread.currentThread().setContextClassLoader(null); + execute(cls); + + // Context classloader is the "bootclassloader". This is same as above + // except that ALLOW_FLAWED_CONTEXT is set to false; an error should + // now be reported. + cls = reload(); + Thread.currentThread().setContextClassLoader(null); + try { + setAllowFlawedContext(cls, "false"); + execute(cls); + fail("Logging config succeeded when context classloader was null!"); + } catch(LogConfigurationException ex) { + // expected; the boot classloader doesn't *have* JCL available + } + + // Context classloader is the system classloader. + // + // This is expected to cause problems, as LogFactoryImpl will attempt + // to use the system classloader to load the Log4JLogger class, which + // will then be unable to cast that object to the Log interface loaded + // via the child classloader. However as ALLOW_FLAWED_CONTEXT defaults + // to true this test should pass. + cls = reload(); + Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); + execute(cls); + + // Context classloader is the system classloader. This is the same + // as above except that ALLOW_FLAWED_CONTEXT is set to false; an error + // should now be reported. + cls = reload(); + Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); + try { + setAllowFlawedContext(cls, "false"); + execute(cls); + fail("Error: somehow downcast a Logger loaded via system classloader" + + " to the Log interface loaded via a custom classloader"); + } catch(LogConfigurationException ex) { + // expected + } + } + + /** + * Load class UserClass via a temporary classloader which is a child of + * the classloader used to load this test class. + */ + private Class reload()throws Exception{ + + Class testObjCls = null; + + AppClassLoader appLoader = new AppClassLoader( + this.getClass().getClassLoader()); + try{ + + testObjCls = appLoader.loadClass(UserClass.class.getName()); + + }catch(ClassNotFoundException cnfe){ + throw cnfe; + }catch(Throwable t){ + t.printStackTrace(); + fail("AppClassLoader failed "); + } + + assertTrue( "app isolated" ,testObjCls.getClassLoader() == appLoader ); + + + return testObjCls; + + + } + + + private void execute(Class cls)throws Exception{ + + cls.newInstance(); + + } + + public void setUp() { + // save state before test starts so we can restore it when test ends + origContextClassLoader = Thread.currentThread().getContextClassLoader(); + } + + public void tearDown() { + // restore original state so a test can't stuff up later tests. + Thread.currentThread().setContextClassLoader(origContextClassLoader); + } + + private ClassLoader origContextClassLoader; +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/LogTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/LogTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/LogTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/LogTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging; + + +public class LogTestCase extends AbstractLogTest +{ + + public Log getLogObject() + { + /** + * Pickup whatever is found/configured! + */ + return LogFactory.getLog(this.getClass().getName()); + } + +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/NullClassLoaderTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/NullClassLoaderTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/NullClassLoaderTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/NullClassLoaderTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging; + +import junit.framework.TestCase; + +/** + * Test cases for situations where getClassLoader or getContextClassLoader + * return null. This can happen when using JDK 1.1. It can also happen when + * JCL is deployed via the bootclassloader - something that could be done when + * using java in embedded systems. + */ +public class NullClassLoaderTestCase extends TestCase { + + //---------------------- unit tests --------------------------------- + + /** + * This tests that when getContextClassLoader returns null, the + * LogFactory.getLog(name) method still correctly returns the same + * log object when called multiple times with the same name. + */ + public void testSameLogObject() throws Exception { + // unfortunately, there just isn't any way to emulate JCL being + // accessable via the null classloader in "standard" systems, so + // we can't include this test in our standard unit tests. + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/PathableClassLoader.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/PathableClassLoader.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/PathableClassLoader.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/PathableClassLoader.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,436 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * A ClassLoader which sees only specified classes, and which can be + * set to do parent-first or child-first path lookup. + *

+ * Note that this classloader is not "industrial strength"; users + * looking for such a class may wish to look at the Tomcat sourcecode + * instead. In particular, this class may not be threadsafe. + *

+ * Note that the ClassLoader.getResources method isn't overloaded here. + * It would be nice to ensure that when child-first lookup is set the + * resources from the child are returned earlier in the list than the + * resources from the parent. However overriding this method isn't possible + * as the java 1.4 version of ClassLoader declares this method final + * (though the java 1.5 version has removed the final qualifier). As the + * ClassLoader javadoc doesn't specify the order in which resources + * are returned, it's valid to return the resources in any order (just + * untidy) so the inherited implementation is technically ok. + */ + +public class PathableClassLoader extends URLClassLoader { + + private static final URL[] NO_URLS = new URL[0]; + + /** + * A map of package-prefix to ClassLoader. Any class which is in + * this map is looked up via the specified classloader instead of + * the classpath associated with this classloader or its parents. + *

+ * This is necessary in order for the rest of the world to communicate + * with classes loaded via a custom classloader. As an example, junit + * testcases which are loaded via a custom classloader needs to see + * the same junit classes as the code invoking the testcase, otherwise + * they can't pass result objects back. + *

+ * Normally, only a classloader created with a null parent needs to + * have any lookasides defined. + */ + private HashMap lookasides = null; + + /** + * See setParentFirst. + */ + private boolean parentFirst = true; + + /** + * Constructor. + *

+ * Often, null is passed as the parent, ie the parent of the new + * instance is the bootloader. This ensures that the classpath is + * totally clean; nothing but the standard java library will be + * present. + *

+ * When using a null parent classloader with a junit testcase, it *is* + * necessary for the junit library to also be visible. In this case, it + * is recommended that the following code be used: + *

+     * pathableLoader.useExplicitLoader(
+     *   "junit.",
+     *   junit.framework.Test.class.getClassLoader());
+     * 
+ * Note that this works regardless of whether junit is on the system + * classpath, or whether it has been loaded by some test framework that + * creates its own classloader to run unit tests in (eg maven2's + * Surefire plugin). + */ + public PathableClassLoader(ClassLoader parent) { + super(NO_URLS, parent); + } + + /** + * Allow caller to explicitly add paths. Generally this not a good idea; + * use addLogicalLib instead, then define the location for that logical + * library in the build.xml file. + */ + public void addURL(URL url) { + super.addURL(url); + } + + /** + * Specify whether this classloader should ask the parent classloader + * to resolve a class first, before trying to resolve it via its own + * classpath. + *

+ * Checking with the parent first is the normal approach for java, but + * components within containers such as servlet engines can use + * child-first lookup instead, to allow the components to override libs + * which are visible in shared classloaders provided by the container. + *

+ * Note that the method getResources always behaves as if parentFirst=true, + * because of limitations in java 1.4; see the javadoc for method + * getResourcesInOrder for details. + *

+ * This value defaults to true. + */ + public void setParentFirst(boolean state) { + parentFirst = state; + } + + /** + * For classes with the specified prefix, get them from the system + * classpath which is active at the point this method is called. + *

+ * This method is just a shortcut for + *

+     * useExplicitLoader(prefix, ClassLoader.getSystemClassLoader());
+     * 
+ *

+ * Of course, this assumes that the classes of interest are already + * in the classpath of the system classloader. + */ + public void useSystemLoader(String prefix) { + useExplicitLoader(prefix, ClassLoader.getSystemClassLoader()); + + } + + /** + * Specify a classloader to use for specific java packages. + *

+ * The specified classloader is normally a loader that is NOT + * an ancestor of this classloader. In particular, this loader + * may have the bootloader as its parent, but be configured to + * see specific other classes (eg the junit library loaded + * via the system classloader). + *

+ * The differences between using this method, and using + * addLogicalLib are: + *

    + *
  • If code calls getClassLoader on a class loaded via + * "lookaside", then traces up its inheritance chain, it + * will see the "real" classloaders. When the class is remapped + * into this classloader via addLogicalLib, the classloader + * chain seen is this object plus ancestors. + *
  • If two different jars contain classes in the same + * package, then it is not possible to load both jars into + * the same "lookaside" classloader (eg the system classloader) + * then map one of those subsets from here. Of course they could + * be loaded into two different "lookaside" classloaders and + * then a prefix used to map from here to one of those classloaders. + *
+ */ + public void useExplicitLoader(String prefix, ClassLoader loader) { + if (lookasides == null) { + lookasides = new HashMap(); + } + lookasides.put(prefix, loader); + } + + /** + * Specify a collection of logical libraries. See addLogicalLib. + */ + public void addLogicalLib(String[] logicalLibs) { + for(int i=0; i + * The specified lib name is used as a key into the system properties; + * there is expected to be a system property defined with that name + * whose value is a url that indicates where that logical library can + * be found. Typically this is the name of a jar file, or a directory + * containing class files. + *

+ * If there is no system property, but the classloader that loaded + * this class is a URLClassLoader then the set of URLs that the + * classloader uses for its classpath is scanned; any jar in the + * URL set whose name starts with the specified string is added to + * the classpath managed by this instance. + *

+ * Using logical library names allows the calling code to specify its + * desired classpath without knowing the exact location of the necessary + * classes. + */ + public void addLogicalLib(String logicalLib) { + // first, check the system properties + String filename = System.getProperty(logicalLib); + if (filename != null) { + try { + URL libUrl = new File(filename).toURL(); + addURL(libUrl); + return; + } catch(java.net.MalformedURLException e) { + throw new UnknownError( + "Invalid file [" + filename + "] for logical lib [" + logicalLib + "]"); + } + } + + // now check the classpath for a similar-named lib + URL libUrl = libFromClasspath(logicalLib); + if (libUrl != null) { + addURL(libUrl); + return; + } + + // lib not found + throw new UnknownError( + "Logical lib [" + logicalLib + "] is not defined" + + " as a System property."); + } + + /** + * If the classloader that loaded this class has this logical lib in its + * path, then return the matching URL otherwise return null. + *

+ * This only works when the classloader loading this class is an instance + * of URLClassLoader and thus has a getURLs method that returns the classpath + * it uses when loading classes. However in practice, the vast majority of the + * time this type is the classloader used. + *

+ * The classpath of the classloader for this instance is scanned, and any + * jarfile in the path whose name starts with the logicalLib string is + * considered a match. For example, passing "foo" will match a url + * of file:///some/where/foo-2.7.jar. + *

+ * When multiple classpath entries match the specified logicalLib string, + * the one with the shortest filename component is returned. This means that + * if "foo-1.1.jar" and "foobar-1.1.jar" are in the path, then a logicalLib + * name of "foo" will match the first entry above. + */ + private URL libFromClasspath(String logicalLib) { + ClassLoader cl = this.getClass().getClassLoader(); + if (cl instanceof URLClassLoader == false) { + return null; + } + + URLClassLoader ucl = (URLClassLoader) cl; + URL[] path = ucl.getURLs(); + URL shortestMatch = null; + int shortestMatchLen = Integer.MAX_VALUE; + for(int i=0; i= 0) { + filename = filename.substring(lastSlash+1); + } + + if (filename.startsWith(logicalLib)) { + // ok, this is a candidate + if (filename.length() < shortestMatchLen) { + shortestMatch = u; + shortestMatchLen = filename.length(); + } + } + } + + return shortestMatch; + } + + /** + * Override ClassLoader method. + *

+ * For each explicitly mapped package prefix, if the name matches the + * prefix associated with that entry then attempt to load the class via + * that entries' classloader. + */ + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + // just for performance, check java and javax + if (name.startsWith("java.") || name.startsWith("javax.")) { + return super.loadClass(name, resolve); + } + + if (lookasides != null) { + for(Iterator i = lookasides.entrySet().iterator(); i.hasNext(); ) { + Map.Entry entry = (Map.Entry) i.next(); + String prefix = (String) entry.getKey(); + if (name.startsWith(prefix) == true) { + ClassLoader loader = (ClassLoader) entry.getValue(); + Class clazz = Class.forName(name, resolve, loader); + return clazz; + } + } + } + + if (parentFirst) { + return super.loadClass(name, resolve); + } else { + // Implement child-first. + // + // It appears that the findClass method doesn't check whether the + // class has already been loaded. This seems odd to me, but without + // first checking via findLoadedClass we can get java.lang.LinkageError + // with message "duplicate class definition" which isn't good. + + try { + Class clazz = findLoadedClass(name); + if (clazz == null) { + clazz = super.findClass(name); + } + if (resolve) { + resolveClass(clazz); + } + return clazz; + } catch(ClassNotFoundException e) { + return super.loadClass(name, resolve); + } + } + } + + /** + * Same as parent class method except that when parentFirst is false + * the resource is looked for in the local classpath before the parent + * loader is consulted. + */ + public URL getResource(String name) { + if (parentFirst) { + return super.getResource(name); + } else { + URL local = super.findResource(name); + if (local != null) { + return local; + } + return super.getResource(name); + } + } + + /** + * Emulate a proper implementation of getResources which respects the + * setting for parentFirst. + *

+ * Note that it's not possible to override the inherited getResources, as + * it's declared final in java1.4 (thought that's been removed for 1.5). + * The inherited implementation always behaves as if parentFirst=true. + */ + public Enumeration getResourcesInOrder(String name) throws IOException { + if (parentFirst) { + return super.getResources(name); + } else { + Enumeration localUrls = super.findResources(name); + + ClassLoader parent = getParent(); + if (parent == null) { + // Alas, there is no method to get matching resources + // from a null (BOOT) parent classloader. Calling + // ClassLoader.getSystemClassLoader isn't right. Maybe + // calling Class.class.getResources(name) would do? + // + // However for the purposes of unit tests, we can + // simply assume that no relevant resources are + // loadable from the parent; unit tests will never be + // putting any of their resources in a "boot" classloader + // path! + return localUrls; + } + Enumeration parentUrls = parent.getResources(name); + + ArrayList localItems = toList(localUrls); + ArrayList parentItems = toList(parentUrls); + localItems.addAll(parentItems); + return Collections.enumeration(localItems); + } + } + + /** + * + * Clean implementation of list function of + * {@link java.utils.Collection} added in JDK 1.4 + * @param en Enumeration, possibly null + * @return ArrayList containing the enumerated + * elements in the enumerated order, not null + */ + private ArrayList toList(Enumeration en) { + ArrayList results = new ArrayList(); + if (en != null) { + while (en.hasMoreElements()){ + Object element = en.nextElement(); + results.add(element); + } + } + return results; + } + + /** + * Same as parent class method except that when parentFirst is false + * the resource is looked for in the local classpath before the parent + * loader is consulted. + */ + public InputStream getResourceAsStream(String name) { + if (parentFirst) { + return super.getResourceAsStream(name); + } else { + URL local = super.findResource(name); + if (local != null) { + try { + return local.openStream(); + } catch(IOException e) { + // TODO: check if this is right or whether we should + // fall back to trying parent. The javadoc doesn't say... + return null; + } + } + return super.getResourceAsStream(name); + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/PathableTestSuite.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/PathableTestSuite.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/PathableTestSuite.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/PathableTestSuite.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging; + +import java.util.Properties; + +import junit.framework.Test; +import junit.framework.TestResult; +import junit.framework.TestSuite; + +/** + * Custom TestSuite class that can be used to control the context classloader + * in operation when a test runs. + *

+ * For tests that need to control exactly what the classloader hierarchy is + * like when the test is run, something like the following is recommended: + *

+ * class SomeTestCase extends TestCase {
+ *  public static Test suite() throws Exception {
+ *   PathableClassLoader parent = new PathableClassLoader(null);
+ *   parent.useSystemLoader("junit.");
+ * 
+ *   PathableClassLoader child = new PathableClassLoader(parent);
+ *   child.addLogicalLib("testclasses");
+ *   child.addLogicalLib("log4j12");
+ *   child.addLogicalLib("commons-logging");
+ * 
+ *   Class testClass = child.loadClass(SomeTestCase.class.getName());
+ *   ClassLoader contextClassLoader = child;
+ * 
+ *   PathableTestSuite suite = new PathableTestSuite(testClass, child);
+ *   return suite;
+ *  }
+ * 
+ *  // test methods go here
+ * }
+ * 
+ * Note that if the suite method throws an exception then this will be handled + * reasonable gracefully by junit; it will report that the suite method for + * a test case failed with exception yyy. + *

+ * The use of PathableClassLoader is not required to use this class, but it + * is expected that using the two classes together is common practice. + *

+ * This class will run each test methods within the specified TestCase using + * the specified context classloader and system classloader. If different + * tests within the same class require different context classloaders, + * then the context classloader passed to the constructor should be the + * "lowest" one available, and tests that need the context set to some parent + * of this "lowest" classloader can call + *

+ *  // NB: pseudo-code only
+ *  setContextClassLoader(getContextClassLoader().getParent());
+ * 
+ * This class ensures that any context classloader changes applied by a test + * is undone after the test is run, so tests don't need to worry about + * restoring the context classloader on exit. This class also ensures that + * the system properties are restored to their original settings after each + * test, so tests that manipulate those don't need to worry about resetting them. + *

+ * This class does not provide facilities for manipulating system properties; + * tests that need specific system properties can simply set them in the + * fixture or at the start of a test method. + *

+ * Important! When the test case is run, "this.getClass()" refers of + * course to the Class object passed to the constructor of this class - which + * is different from the class whose suite() method was executed to determine + * the classpath. This means that the suite method cannot communicate with + * the test cases simply by setting static variables (for example to make the + * custom classloaders available to the test methods or setUp/tearDown fixtures). + * If this is really necessary then it is possible to use reflection to invoke + * static methods on the class object passed to the constructor of this class. + *

+ *

Limitations

+ *

+ * This class cannot control the system classloader (ie what method + * ClassLoader.getSystemClassLoader returns) because Java provides no + * mechanism for setting the system classloader. In this case, the only + * option is to invoke the unit test in a separate JVM with the appropriate + * settings. + *

+ * The effect of using this approach in a system that uses junit's + * "reloading classloader" behaviour is unknown. This junit feature is + * intended for junit GUI apps where a test may be run multiple times + * within the same JVM - and in particular, when the .class file may + * be modified between runs of the test. How junit achieves this is + * actually rather weird (the whole junit code is rather weird in fact) + * and it is not clear whether this approach will work as expected in + * such situations. + */ +public class PathableTestSuite extends TestSuite { + + /** + * The classloader that should be set as the context classloader + * before each test in the suite is run. + */ + private final ClassLoader contextLoader; + + /** + * Constructor. + * + * @param testClass is the TestCase that is to be run, as loaded by + * the appropriate ClassLoader. + * + * @param contextClassLoader is the loader that should be returned by + * calls to Thread.currentThread.getContextClassLoader from test methods + * (or any method called by test methods). + */ + public PathableTestSuite(Class testClass, ClassLoader contextClassLoader) { + super(testClass); + contextLoader = contextClassLoader; + } + + /** + * This method is invoked once for each Test in the current TestSuite. + * Note that a Test may itself be a TestSuite object (ie a collection + * of tests). + *

+ * The context classloader and system properties are saved before each + * test, and restored after the test completes to better isolate tests. + */ + public void runTest(Test test, TestResult result) { + ClassLoader origContext = Thread.currentThread().getContextClassLoader(); + Properties oldSysProps = (Properties) System.getProperties().clone(); + try { + Thread.currentThread().setContextClassLoader(contextLoader); + test.run(result); + } finally { + System.setProperties(oldSysProps); + Thread.currentThread().setContextClassLoader(origContext); + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/SimpleLogTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/SimpleLogTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/SimpleLogTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/SimpleLogTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging; + +import org.apache.commons.logging.impl.SimpleLog; + +public class SimpleLogTestCase extends AbstractLogTest +{ + public Log getLogObject() + { + return new SimpleLog(this.getClass().getName()); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/UserClass.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/UserClass.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/UserClass.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/UserClass.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging; + +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.impl.LogFactoryImpl; + +public class UserClass { + + /** + * Set the ALLOW_FLAWED_CONTEXT feature on the LogFactoryImpl object + * associated with this class' classloader. + *

+ * Don't forget to set the context classloader to whatever it will be + * when an instance of this class is actually created before calling + * this method! + */ + public static void setAllowFlawedContext(String state) { + LogFactory f = LogFactory.getFactory(); + f.setAttribute(LogFactoryImpl.ALLOW_FLAWED_CONTEXT_PROPERTY, state); + } + + public UserClass() { + Log log = LogFactory.getLog(LoadTestCase.class); + } + +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/avalon/AvalonLoggerTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/avalon/AvalonLoggerTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/avalon/AvalonLoggerTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/avalon/AvalonLoggerTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging.avalon; + +import org.apache.avalon.framework.logger.NullLogger; +import org.apache.commons.logging.impl.AvalonLogger; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.AbstractLogTest; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * @author Neeme Praks + * @version $Revision: 1432587 $ $Date: 2013-01-13 12:11:32 +0100 (Sun, 13 Jan 2013) $ + */ +public class AvalonLoggerTestCase extends AbstractLogTest { + + public static Test suite() { + TestSuite suite = new TestSuite(); + suite.addTestSuite(AvalonLoggerTestCase.class); + return suite; + } + + public Log getLogObject() { + // Output does not seem to be used, so don't display it. + Log log = new AvalonLogger(new NullLogger()); + return log; + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/config/FirstPriorityConfigTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/config/FirstPriorityConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/config/FirstPriorityConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/config/FirstPriorityConfigTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.config; + + +import java.net.URL; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + * Tests that verify that the process of configuring logging on startup + * works correctly by selecting the file with the highest priority. + *

+ * This test sets up a classpath where: + *

    + *
  • first file found has priority=20 + *
  • second file found has priority=10 + *
+ * The result should be that the first file is used. + */ +public class FirstPriorityConfigTestCase extends TestCase { + + // ------------------------------------------- JUnit Infrastructure Methods + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + Class thisClass = FirstPriorityConfigTestCase.class; + + // Determine the URL to this .class file, so that we can then + // append the priority dirs to it. For tidiness, load this + // class through a dummy loader though this is not absolutely + // necessary... + PathableClassLoader dummy = new PathableClassLoader(null); + dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); + dummy.addLogicalLib("testclasses"); + dummy.addLogicalLib("commons-logging"); + + String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; + URL baseUrl = dummy.findResource(thisClassPath); + + // Now set up the desired classloader hierarchy. We'll put JCL + // in the container path, the testcase in a webapp path, and + // both config files into the webapp path too. + PathableClassLoader containerLoader = new PathableClassLoader(null); + containerLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); + containerLoader.addLogicalLib("commons-logging"); + + PathableClassLoader webappLoader = new PathableClassLoader(containerLoader); + webappLoader.addLogicalLib("testclasses"); + + URL pri20URL = new URL(baseUrl, "priority20/"); + webappLoader.addURL(pri20URL); + + URL pri10URL = new URL(baseUrl, "priority10/"); + webappLoader.addURL(pri10URL); + + // load the test class via webapp loader, and use the webapp loader + // as the tccl loader too. + Class testClass = webappLoader.loadClass(thisClass.getName()); + return new PathableTestSuite(testClass, webappLoader); + } + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + LogFactory.releaseAll(); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + LogFactory.releaseAll(); + } + + // ----------------------------------------------------------- Test Methods + + /** + * Verify that the config file being used is the one containing + * the desired configId value. + */ + public void testPriority() throws Exception { + LogFactory instance = LogFactory.getFactory(); + + ClassLoader thisClassLoader = this.getClass().getClassLoader(); + ClassLoader lfClassLoader = instance.getClass().getClassLoader(); + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + + // context classloader should be thisClassLoader + assertEquals(thisClassLoader, contextClassLoader); + + // lfClassLoader should be parent of this classloader + assertEquals(lfClassLoader, thisClassLoader.getParent()); + assertEquals(PathableClassLoader.class.getName(), + lfClassLoader.getClass().getName()); + + String id = (String) instance.getAttribute("configId"); + assertEquals("Correct config file loaded", "priority20", id ); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/config/PriorityConfigTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/config/PriorityConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/config/PriorityConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/config/PriorityConfigTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.config; + + +import java.net.URL; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + * Tests that verify that the process of configuring logging on startup + * works correctly by selecting the file with the highest priority. + *

+ * This test sets up a classpath where: + *

    + *
  • first file (in parent loader) has priority=10 (parentFirst=true) + *
  • second file found has no priority set + *
  • third file found has priority=20 + *
  • fourth file found also has priority=20 + *
+ * The result should be that the third file is used. + *

+ * Note that parentFirst=true is used in this test because method + * PathableClassLoader.getResources always behaves as if + * parentFirst=true; see the PathableClassLoader javadoc for details. + */ + +public class PriorityConfigTestCase extends TestCase { + + // ------------------------------------------- JUnit Infrastructure Methods + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + Class thisClass = PriorityConfigTestCase.class; + + // Determine the URL to this .class file, so that we can then + // append the priority dirs to it. For tidiness, load this + // class through a dummy loader though this is not absolutely + // necessary... + PathableClassLoader dummy = new PathableClassLoader(null); + dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); + dummy.addLogicalLib("testclasses"); + dummy.addLogicalLib("commons-logging"); + + String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; + URL baseUrl = dummy.findResource(thisClassPath); + + // Now set up the desired classloader hierarchy. We'll put a config + // file of priority=10 in the container path, and ones of both + // "no priority" and priority=20 in the webapp path. + // + // A second properties file with priority=20 is also added, + // so we can check that the first one in the classpath is + // used. + PathableClassLoader containerLoader = new PathableClassLoader(null); + containerLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); + containerLoader.addLogicalLib("commons-logging"); + + URL pri10URL = new URL(baseUrl, "priority10/"); + containerLoader.addURL(pri10URL); + + PathableClassLoader webappLoader = new PathableClassLoader(containerLoader); + webappLoader.setParentFirst(true); + webappLoader.addLogicalLib("testclasses"); + + URL noPriorityURL = new URL(baseUrl, "nopriority/"); + webappLoader.addURL(noPriorityURL); + + URL pri20URL = new URL(baseUrl, "priority20/"); + webappLoader.addURL(pri20URL); + + URL pri20aURL = new URL(baseUrl, "priority20a/"); + webappLoader.addURL(pri20aURL); + + // load the test class via webapp loader, and use the webapp loader + // as the tccl loader too. + Class testClass = webappLoader.loadClass(thisClass.getName()); + return new PathableTestSuite(testClass, webappLoader); + } + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + LogFactory.releaseAll(); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + LogFactory.releaseAll(); + } + + // ----------------------------------------------------------- Test Methods + + /** + * Verify that the config file being used is the one containing + * the desired configId value. + */ + public void testPriority() throws Exception { + LogFactory instance = LogFactory.getFactory(); + String id = (String) instance.getAttribute("configId"); + assertEquals("Correct config file loaded", "priority20", id ); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/impl/WeakHashtableTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/impl/WeakHashtableTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/impl/WeakHashtableTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/impl/WeakHashtableTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,313 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.commons.logging.impl; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import junit.framework.TestCase; + +public class WeakHashtableTestCase extends TestCase { + + private static final int WAIT_FOR_THREAD_COMPLETION = 5000; // 5 seconds + private static final int RUN_LOOPS = 3000; + private static final int OUTER_LOOP = 400; + private static final int THREAD_COUNT = 10; + + private static WeakHashtable hashtable; + + /** Maximum number of iterations before our test fails */ + private static final int MAX_GC_ITERATIONS = 50; + + private WeakHashtable weakHashtable; + private Long keyOne; + private Long keyTwo; + private Long keyThree; + private Long valueOne; + private Long valueTwo; + private Long valueThree; + + public WeakHashtableTestCase(String testName) { + super(testName); + } + + protected void setUp() throws Exception { + super.setUp(); + weakHashtable = new WeakHashtable(); + + keyOne = new Long(1); + keyTwo = new Long(2); + keyThree = new Long(3); + valueOne = new Long(100); + valueTwo = new Long(200); + valueThree = new Long(300); + + weakHashtable.put(keyOne, valueOne); + weakHashtable.put(keyTwo, valueTwo); + weakHashtable.put(keyThree, valueThree); + } + + /** Tests public boolean contains(Object value) */ + public void testContains() throws Exception { + assertFalse(weakHashtable.contains(new Long(1))); + assertFalse(weakHashtable.contains(new Long(2))); + assertFalse(weakHashtable.contains(new Long(3))); + assertTrue(weakHashtable.contains(new Long(100))); + assertTrue(weakHashtable.contains(new Long(200))); + assertTrue(weakHashtable.contains(new Long(300))); + assertFalse(weakHashtable.contains(new Long(400))); + } + + /** Tests public boolean containsKey(Object key) */ + public void testContainsKey() throws Exception { + assertTrue(weakHashtable.containsKey(new Long(1))); + assertTrue(weakHashtable.containsKey(new Long(2))); + assertTrue(weakHashtable.containsKey(new Long(3))); + assertFalse(weakHashtable.containsKey(new Long(100))); + assertFalse(weakHashtable.containsKey(new Long(200))); + assertFalse(weakHashtable.containsKey(new Long(300))); + assertFalse(weakHashtable.containsKey(new Long(400))); + } + + /** Tests public boolean containsValue(Object value) */ + public void testContainsValue() throws Exception { + assertFalse(weakHashtable.containsValue(new Long(1))); + assertFalse(weakHashtable.containsValue(new Long(2))); + assertFalse(weakHashtable.containsValue(new Long(3))); + assertTrue(weakHashtable.containsValue(new Long(100))); + assertTrue(weakHashtable.containsValue(new Long(200))); + assertTrue(weakHashtable.containsValue(new Long(300))); + assertFalse(weakHashtable.containsValue(new Long(400))); + } + + /** Tests public Enumeration elements() */ + public void testElements() throws Exception { + ArrayList elements = new ArrayList(); + for (Enumeration e = weakHashtable.elements(); e.hasMoreElements();) { + elements.add(e.nextElement()); + } + assertEquals(3, elements.size()); + assertTrue(elements.contains(valueOne)); + assertTrue(elements.contains(valueTwo)); + assertTrue(elements.contains(valueThree)); + } + + /** Tests public Set entrySet() */ + public void testEntrySet() throws Exception { + Set entrySet = weakHashtable.entrySet(); + for (Iterator it = entrySet.iterator(); it.hasNext();) { + Map.Entry entry = (Map.Entry) it.next(); + Object key = entry.getKey(); + if (keyOne.equals(key)) { + assertEquals(valueOne, entry.getValue()); + } else if (keyTwo.equals(key)) { + assertEquals(valueTwo, entry.getValue()); + } else if (keyThree.equals(key)) { + assertEquals(valueThree, entry.getValue()); + } else { + fail("Unexpected key"); + } + } + } + + /** Tests public Object get(Object key) */ + public void testGet() throws Exception { + assertEquals(valueOne, weakHashtable.get(keyOne)); + assertEquals(valueTwo, weakHashtable.get(keyTwo)); + assertEquals(valueThree, weakHashtable.get(keyThree)); + assertNull(weakHashtable.get(new Long(50))); + } + + /** Tests public Enumeration keys() */ + public void testKeys() throws Exception { + ArrayList keys = new ArrayList(); + for (Enumeration e = weakHashtable.keys(); e.hasMoreElements();) { + keys.add(e.nextElement()); + } + assertEquals(3, keys.size()); + assertTrue(keys.contains(keyOne)); + assertTrue(keys.contains(keyTwo)); + assertTrue(keys.contains(keyThree)); + } + + /** Tests public Set keySet() */ + public void testKeySet() throws Exception { + Set keySet = weakHashtable.keySet(); + assertEquals(3, keySet.size()); + assertTrue(keySet.contains(keyOne)); + assertTrue(keySet.contains(keyTwo)); + assertTrue(keySet.contains(keyThree)); + } + + /** Tests public Object put(Object key, Object value) */ + public void testPut() throws Exception { + Long anotherKey = new Long(2004); + weakHashtable.put(anotherKey, new Long(1066)); + + assertEquals(new Long(1066), weakHashtable.get(anotherKey)); + + // Test compliance with the hashtable API re nulls + Exception caught = null; + try { + weakHashtable.put(null, new Object()); + } + catch (Exception e) { + caught = e; + } + assertNotNull("did not throw an exception adding a null key", caught); + caught = null; + try { + weakHashtable.put(new Object(), null); + } + catch (Exception e) { + caught = e; + } + assertNotNull("did not throw an exception adding a null value", caught); + } + + /** Tests public void putAll(Map t) */ + public void testPutAll() throws Exception { + Map newValues = new HashMap(); + Long newKey = new Long(1066); + Long newValue = new Long(1415); + newValues.put(newKey, newValue); + Long anotherNewKey = new Long(1645); + Long anotherNewValue = new Long(1815); + newValues.put(anotherNewKey, anotherNewValue); + weakHashtable.putAll(newValues); + + assertEquals(5, weakHashtable.size()); + assertEquals(newValue, weakHashtable.get(newKey)); + assertEquals(anotherNewValue, weakHashtable.get(anotherNewKey)); + } + + /** Tests public Object remove(Object key) */ + public void testRemove() throws Exception { + weakHashtable.remove(keyOne); + assertEquals(2, weakHashtable.size()); + assertNull(weakHashtable.get(keyOne)); + } + + /** Tests public Collection values() */ + public void testValues() throws Exception { + Collection values = weakHashtable.values(); + assertEquals(3, values.size()); + assertTrue(values.contains(valueOne)); + assertTrue(values.contains(valueTwo)); + assertTrue(values.contains(valueThree)); + } + + /** + * Disabled this test as it makes wrong assumptions wrt the GC. + * This test especially fails with: + * + * Java(TM) SE Runtime Environment (build pxi3260sr12-20121025_01(SR12)) + * IBM J9 VM (build 2.4, JRE 1.6.0 IBM J9 2.4 Linux x86-32 jvmxi3260sr12-20121024_1 + */ + public void xxxIgnoretestRelease() throws Exception { + assertNotNull(weakHashtable.get(new Long(1))); + ReferenceQueue testQueue = new ReferenceQueue(); + WeakReference weakKeyOne = new WeakReference(keyOne, testQueue); + + // lose our references + keyOne = null; + keyTwo = null; + keyThree = null; + valueOne = null; + valueTwo = null; + valueThree = null; + + int iterations = 0; + int bytz = 2; + while(true) { + System.gc(); + if(iterations++ > MAX_GC_ITERATIONS){ + fail("Max iterations reached before resource released."); + } + + if(weakHashtable.get(new Long(1)) == null) { + break; + + } else { + // create garbage: + byte[] b = new byte[bytz]; + bytz = bytz * 2; + } + } + + // some JVMs seem to take a little time to put references on + // the reference queue once the reference has been collected + // need to think about whether this is enough to justify + // stepping through the collection each time... + while(testQueue.poll() == null) {} + + // Test that the released objects are not taking space in the table + assertEquals("underlying table not emptied", 0, weakHashtable.size()); + } + + public static class StupidThread extends Thread { + + public StupidThread(String name) { + super(name); + } + + public void run() { + for (int i = 0; i < RUN_LOOPS; i++) { + hashtable.put("key" + ":" + i%10, Boolean.TRUE); + if(i%50 == 0) { + yield(); + } + } + } + } + + public void testLOGGING_119() throws Exception { + Thread [] t = new Thread[THREAD_COUNT]; + for (int j=1; j <= OUTER_LOOP; j++) { + hashtable = new WeakHashtable(); + for (int i = 0; i < t.length; i++) { + t[i] = new StupidThread("Thread:" + i); + t[i].setDaemon(true); // Otherwise we cannot exit + t[i].start(); + } + for (int i = 0; i < t.length; i++) { + t[i].join(WAIT_FOR_THREAD_COMPLETION); + if (t[i].isAlive()) { + break; // at least one thread is stuck + } + } + int active=0; + for (int i = 0; i < t.length; i++) { + if (t[i].isAlive()) { + active++; + } + } + if (active > 0) { + fail("Attempt: " + j + " Stuck threads: " + active); + } + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.jdk14; + +import junit.framework.Test; + +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + * TestCase for Jdk14 logging when the commons-logging-api jar file is in + * the parent classpath and commons-logging.jar is in the child. + */ + +public class CustomConfigAPITestCase extends CustomConfigTestCase { + + public CustomConfigAPITestCase(String name) { + super(name); + } + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useExplicitLoader("junit.", Test.class.getClassLoader()); + + // the TestHandler class must be accessable from the System classloader + // in order for java.util.logging.LogManager.readConfiguration to + // be able to instantiate it. And this test case must see the same + // class in order to be able to access its data. Yes this is ugly + // but the whole jdk14 API is a ******* mess anyway. + ClassLoader scl = ClassLoader.getSystemClassLoader(); + loadTestHandler(HANDLER_NAME, scl); + parent.useExplicitLoader(HANDLER_NAME, scl); + parent.addLogicalLib("commons-logging-api"); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("testclasses"); + child.addLogicalLib("commons-logging"); + + Class testClass = child.loadClass(CustomConfigAPITestCase.class.getName()); + return new PathableTestSuite(testClass, child); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.jdk14; + + +import junit.framework.Test; + +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.PathableClassLoader; + + +/** + * TestCase for Jdk14 logging when the commons-logging jar file is in + * the parent classpath. + */ + +public class CustomConfigFullTestCase extends CustomConfigTestCase { + + + public CustomConfigFullTestCase(String name) { + super(name); + } + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useExplicitLoader("junit.", Test.class.getClassLoader()); + + // the TestHandler class must be accessable from the System classloader + // in order for java.util.logging.LogManager.readConfiguration to + // be able to instantiate it. And this test case must see the same + // class in order to be able to access its data. Yes this is ugly + // but the whole jdk14 API is a ******* mess anyway. + ClassLoader scl = ClassLoader.getSystemClassLoader(); + loadTestHandler(HANDLER_NAME, scl); + parent.useExplicitLoader(HANDLER_NAME, scl); + parent.addLogicalLib("commons-logging"); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("testclasses"); + + Class testClass = child.loadClass(CustomConfigFullTestCase.class.getName()); + return new PathableTestSuite(testClass, child); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/jdk14/CustomConfigTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/jdk14/CustomConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/jdk14/CustomConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/jdk14/CustomConfigTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,395 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.jdk14; + + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import junit.framework.Test; + +import org.apache.commons.logging.DummyException; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + *

TestCase for JDK 1.4 logging when running on a JDK 1.4 system with + * custom configuration, so that JDK 1.4 should be selected and an appropriate + * logger configured per the configuration properties.

+ * + * @author Craig R. McClanahan + * @version $Revision: 1448063 $ $Date: 2013-02-20 11:01:41 +0100 (Wed, 20 Feb 2013) $ + */ + +public class CustomConfigTestCase extends DefaultConfigTestCase { + + protected static final String HANDLER_NAME = "org.apache.commons.logging.jdk14.TestHandler"; + + // ----------------------------------------------------------- Constructors + + + /** + *

Construct a new instance of this test case.

+ * + * @param name Name of the test case + */ + public CustomConfigTestCase(String name) { + super(name); + } + + + // ----------------------------------------------------- Instance Variables + + + /** + *

The customized Handler we will be using.

+ */ + protected TestHandler handler = null; + + + /** + *

The underlying Handlers we will be using.

+ */ + protected Handler handlers[] = null; + + + /** + *

The underlying Logger we will be using.

+ */ + protected Logger logger = null; + + + /** + *

The underlying LogManager we will be using.

+ */ + protected LogManager manager = null; + + + /** + *

The message levels that should have been logged.

+ */ + protected Level testLevels[] = + { Level.FINE, Level.INFO, Level.WARNING, Level.SEVERE, Level.SEVERE }; + + + /** + *

The message strings that should have been logged.

+ */ + protected String testMessages[] = + { "debug", "info", "warn", "error", "fatal" }; + + + // ------------------------------------------- JUnit Infrastructure Methods + + + /** + * Given the name of a class that is somewhere in the classpath of the provided + * classloader, return the contents of the corresponding .class file. + */ + protected static byte[] readClass(String name, ClassLoader srcCL) throws Exception { + String resName = name.replace('.', '/') + ".class"; + System.err.println("Trying to load resource [" + resName + "]"); + InputStream is = srcCL.getResourceAsStream(resName); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + System.err.println("Reading resource [" + resName + "]"); + byte[] buf = new byte[1000]; + for(;;) { + int read = is.read(buf); + if (read <= 0) { + break; + } + baos.write(buf, 0, read); + } + is.close(); + return baos.toByteArray(); + } + + /** + * Make a class available in the system classloader even when its classfile is + * not present in the classpath configured for that classloader. This only + * works for classes for which all dependencies are already loaded in + * that classloader. + */ + protected static void loadTestHandler(String className, ClassLoader targetCL) { + try { + targetCL.loadClass(className); + // fail("Class already in target classloader"); + return; + } catch(ClassNotFoundException ex) { + // ok, go ahead and load it + } + + try { + ClassLoader srcCL = CustomConfigAPITestCase.class.getClassLoader(); + byte[] classData = readClass(className, srcCL); + + Class[] params = new Class[] { String.class, classData.getClass(), Integer.TYPE, Integer.TYPE }; + Method m = ClassLoader.class.getDeclaredMethod("defineClass", params); + + Object[] args = new Object[4]; + args[0] = className; + args[1] = classData; + args[2] = new Integer(0); + args[3] = new Integer(classData.length); + m.setAccessible(true); + m.invoke(targetCL, args); + } catch(Exception e) { + e.printStackTrace(); + fail("Unable to load class " + className); + } + } + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + setUpManager + ("org/apache/commons/logging/jdk14/CustomConfig.properties"); + setUpLogger(this.getClass().getName()); + setUpHandlers(); + setUpFactory(); + setUpLog(this.getClass().getName()); + } + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader cl = new PathableClassLoader(null); + cl.useExplicitLoader("junit.", Test.class.getClassLoader()); + + // the TestHandler class must be accessable from the System classloader + // in order for java.util.logging.LogManager.readConfiguration to + // be able to instantiate it. And this test case must see the same + // class in order to be able to access its data. Yes this is ugly + // but the whole jdk14 API is a ******* mess anyway. + ClassLoader scl = ClassLoader.getSystemClassLoader(); + loadTestHandler(HANDLER_NAME, scl); + cl.useExplicitLoader(HANDLER_NAME, scl); + cl.addLogicalLib("commons-logging"); + cl.addLogicalLib("testclasses"); + + Class testClass = cl.loadClass(CustomConfigTestCase.class.getName()); + return new PathableTestSuite(testClass, cl); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + super.tearDown(); + handlers = null; + logger = null; + manager = null; + } + + + // ----------------------------------------------------------- Test Methods + + + // Test logging message strings with exceptions + public void testExceptionMessages() throws Exception { + + logExceptionMessages(); + checkLogRecords(true); + + } + + + // Test logging plain message strings + public void testPlainMessages() throws Exception { + + logPlainMessages(); + checkLogRecords(false); + + } + + + // Test pristine Handlers instances + public void testPristineHandlers() { + + assertNotNull(handlers); + assertEquals(1, handlers.length); + assertTrue(handlers[0] instanceof TestHandler); + assertNotNull(handler); + + } + + + // Test pristine Logger instance + public void testPristineLogger() { + + assertNotNull("Logger exists", logger); + assertEquals("Logger name", this.getClass().getName(), logger.getName()); + + // Assert which logging levels have been enabled + assertTrue(logger.isLoggable(Level.SEVERE)); + assertTrue(logger.isLoggable(Level.WARNING)); + assertTrue(logger.isLoggable(Level.INFO)); + assertTrue(logger.isLoggable(Level.CONFIG)); + assertTrue(logger.isLoggable(Level.FINE)); + assertTrue(!logger.isLoggable(Level.FINER)); + assertTrue(!logger.isLoggable(Level.FINEST)); + + } + + + // Test Serializability of Log instance + public void testSerializable() throws Exception { + + super.testSerializable(); + testExceptionMessages(); + + } + + + // -------------------------------------------------------- Support Methods + + + // Check the log instance + protected void checkLog() { + + assertNotNull("Log exists", log); + assertEquals("Log class", + "org.apache.commons.logging.impl.Jdk14Logger", + log.getClass().getName()); + + // Assert which logging levels have been enabled + assertTrue(log.isFatalEnabled()); + assertTrue(log.isErrorEnabled()); + assertTrue(log.isWarnEnabled()); + assertTrue(log.isInfoEnabled()); + assertTrue(log.isDebugEnabled()); + assertTrue(!log.isTraceEnabled()); + + } + + + // Check the recorded messages + protected void checkLogRecords(boolean thrown) { + Iterator records = handler.records(); + for (int i = 0; i < testMessages.length; i++) { + assertTrue(records.hasNext()); + LogRecord record = (LogRecord) records.next(); + assertEquals("LogRecord level", + testLevels[i], record.getLevel()); + assertEquals("LogRecord message", + testMessages[i], record.getMessage()); + assertTrue("LogRecord class", + record.getSourceClassName().startsWith( + "org.apache.commons.logging.jdk14.CustomConfig")); + if (thrown) { + assertEquals("LogRecord method", + "logExceptionMessages", + record.getSourceMethodName()); + } else { + assertEquals("LogRecord method", + "logPlainMessages", + record.getSourceMethodName()); + } + if (thrown) { + assertNotNull("LogRecord thrown", record.getThrown()); + assertTrue("LogRecord thrown type", + record.getThrown() instanceof DummyException); + } else { + assertNull("LogRecord thrown", + record.getThrown()); + } + } + assertTrue(!records.hasNext()); + handler.flush(); + } + + + // Log the messages with exceptions + protected void logExceptionMessages() { + Throwable t = new DummyException(); + log.trace("trace", t); // Should not actually get logged + log.debug("debug", t); + log.info("info", t); + log.warn("warn", t); + log.error("error", t); + log.fatal("fatal", t); + } + + + // Log the plain messages + protected void logPlainMessages() { + log.trace("trace"); // Should not actually get logged + log.debug("debug"); + log.info("info"); + log.warn("warn"); + log.error("error"); + log.fatal("fatal"); + } + + + // Set up handlers instance + protected void setUpHandlers() throws Exception { + Logger parent = logger; + while (parent.getParent() != null) { + parent = parent.getParent(); + } + handlers = parent.getHandlers(); + + // The CustomConfig.properties file explicitly defines one handler class + // to be attached to the root logger, so if it isn't there then + // something is badly wrong... + // + // Yes this testing is also done in testPristineHandlers but + // unfortunately: + // * we need to set up the handlers variable here, + // * we don't want that to be set up incorrectly, as that can + // produce weird error messages in other tests, and + // * we can't rely on testPristineHandlers being the first + // test to run. + // so we need to test things here too. + assertNotNull("No Handlers defined for JDK14 logging", handlers); + assertEquals("Unexpected number of handlers for JDK14 logging", 1, handlers.length); + assertNotNull("Handler is null", handlers[0]); + assertTrue("Handler not of expected type", handlers[0] instanceof TestHandler); + handler = (TestHandler) handlers[0]; + } + + + // Set up logger instance + protected void setUpLogger(String name) throws Exception { + logger = Logger.getLogger(name); + } + + + // Set up LogManager instance + protected void setUpManager(String config) throws Exception { + manager = LogManager.getLogManager(); + InputStream is = + this.getClass().getClassLoader().getResourceAsStream(config); + manager.readConfiguration(is); + is.close(); + } + + +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.jdk14; + + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + *

TestCase for JDK 1.4 logging when running on a JDK 1.4 system with + * zero configuration, and with Log4J not present (so JDK 1.4 logging + * should be automatically configured.

+ * + * @author Craig R. McClanahan + * @version $Revision: 1432587 $ $Date: 2013-01-13 12:11:32 +0100 (Sun, 13 Jan 2013) $ + */ + +public class DefaultConfigTestCase extends TestCase { + + + // ----------------------------------------------------------- Constructors + + + /** + *

Construct a new instance of this test case.

+ * + * @param name Name of the test case + */ + public DefaultConfigTestCase(String name) { + super(name); + } + + + // ----------------------------------------------------- Instance Variables + + + /** + *

The {@link LogFactory} implementation we have selected.

+ */ + protected LogFactory factory = null; + + + /** + *

The {@link Log} implementation we have selected.

+ */ + protected Log log = null; + + + // ------------------------------------------- JUnit Infrastructure Methods + + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + setUpFactory(); + setUpLog("TestLogger"); + } + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader loader = new PathableClassLoader(null); + loader.useExplicitLoader("junit.", Test.class.getClassLoader()); + loader.addLogicalLib("testclasses"); + loader.addLogicalLib("commons-logging"); + + Class testClass = loader.loadClass(DefaultConfigTestCase.class.getName()); + return new PathableTestSuite(testClass, loader); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + log = null; + factory = null; + LogFactory.releaseAll(); + } + + + // ----------------------------------------------------------- Test Methods + + + // Test pristine Log instance + public void testPristineLog() { + + checkLog(); + + } + + + // Test pristine LogFactory instance + public void testPristineFactory() { + + assertNotNull("LogFactory exists", factory); + assertEquals("LogFactory class", + "org.apache.commons.logging.impl.LogFactoryImpl", + factory.getClass().getName()); + + String names[] = factory.getAttributeNames(); + assertNotNull("Names exists", names); + assertEquals("Names empty", 0, names.length); + + } + + + // Test Serializability of Log instance + public void testSerializable() throws Exception { + + // Serialize and deserialize the instance + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(log); + oos.close(); + ByteArrayInputStream bais = + new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + log = (Log) ois.readObject(); + ois.close(); + + // Check the characteristics of the resulting object + checkLog(); + + } + + + // -------------------------------------------------------- Support Methods + + + + // Check the log instance + protected void checkLog() { + + assertNotNull("Log exists", log); + assertEquals("Log class", + "org.apache.commons.logging.impl.Jdk14Logger", + log.getClass().getName()); + + // Can we call level checkers with no exceptions? + log.isDebugEnabled(); + log.isErrorEnabled(); + log.isFatalEnabled(); + log.isInfoEnabled(); + log.isTraceEnabled(); + log.isWarnEnabled(); + + } + + + // Set up factory instance + protected void setUpFactory() throws Exception { + factory = LogFactory.getFactory(); + } + + + // Set up log instance + protected void setUpLog(String name) throws Exception { + log = LogFactory.getLog(name); + } + + +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/jdk14/TestHandler.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/jdk14/TestHandler.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/jdk14/TestHandler.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/jdk14/TestHandler.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging.jdk14; + + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Handler; +import java.util.logging.LogRecord; + + +/** + *

Test implementation of java.util.logging.Handler.

+ * + * @author Craig R. McClanahan + * @version $Revision: 1432587 $ $Date: 2013-01-13 12:11:32 +0100 (Sun, 13 Jan 2013) $ + */ + +public class TestHandler extends Handler { + + + + // ----------------------------------------------------- Instance Variables + + + // The set of logged records for this handler + private final List records = new ArrayList(); + + + // --------------------------------------------------------- Public Methods + + + public Iterator records() { + return records.iterator(); + } + + + // -------------------------------------------------------- Handler Methods + + + public void close() { + } + + + public void flush() { + records.clear(); + } + + + public void publish(LogRecord record) { + records.add(record); + } + + +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/StandardTests.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/StandardTests.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/StandardTests.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/StandardTests.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.log4j; + + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.commons.logging.DummyException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * Abstract set of tests that can be executed with various classpaths set. + *

+ * The tests verify that when running on a system with Log4J present, + * Log4J is selected and that the logger basically works. + */ + +public abstract class StandardTests extends TestCase { + + /** + * Simple structure to store information about messages that actually get + * logged by the underlying logging library. + */ + public static class LogEvent { + public String msg; + public String level; + public Throwable throwable; + } + + // ------------------------------------------------------------------- + // JUnit Infrastructure Methods + // ------------------------------------------------------------------- + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + LogFactory.releaseAll(); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + LogFactory.releaseAll(); + } + + // ----------------------------------------------------------- + // abstract methods + // ----------------------------------------------------------- + + /** + * Modify log4j's setup so that all messages actually logged get redirected + * into the specified list. + *

+ * This method also sets the logging level to INFO so that we + * can test whether messages are getting properly filtered. + */ + public abstract void setUpTestAppender(List logEvents) throws Exception; + + // ----------------------------------------------------------- Test Methods + + /** + * Test that a LogFactory gets created as expected. + */ + public void testCreateFactory() { + LogFactory factory = LogFactory.getFactory(); + assertNotNull("LogFactory exists", factory); + assertEquals("LogFactory class", + "org.apache.commons.logging.impl.LogFactoryImpl", + factory.getClass().getName()); + + String names[] = factory.getAttributeNames(); + assertNotNull("Names exists", names); + assertEquals("Names empty", 0, names.length); + } + + /** + * Verify that we can log messages without exceptions. + */ + public void testPlainMessages() throws Exception { + List logEvents = new ArrayList(); + setUpTestAppender(logEvents); + Log log = LogFactory.getLog("test-category"); + logPlainMessages(log); + checkLoggingEvents(logEvents, false); + } + + /** + * Verify that we can log exception messages. + */ + public void testExceptionMessages() throws Exception { + List logEvents = new ArrayList(); + setUpTestAppender(logEvents); + Log log = LogFactory.getLog("test-category"); + logExceptionMessages(log); + checkLoggingEvents(logEvents, true); + } + + /** + * Test Serializability of Log instance + */ + public void testSerializable() throws Exception { + List logEvents = new ArrayList(); + setUpTestAppender(logEvents); + Log log = LogFactory.getLog("test-category"); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(log); + oos.close(); + ByteArrayInputStream bais = + new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + Log newLog = (Log) ois.readObject(); + ois.close(); + + // Check the characteristics of the resulting object + logExceptionMessages(newLog); + checkLoggingEvents(logEvents, true); + } + + // -------------------------------------------------------- Support Methods + + /** + * Verify that the TestAppender has received the expected + * number of messages. This assumes that: + *

    + *
  • setUpTestAppender has been called + *
  • logPlainMessages or logExceptionMessages has been + * called to log a known number of messages at known levels. + *
+ * + * @param logEvents is the list of log events received. + * + * @param thrown False if logPlainMessages was called + * (ie the TestAppender is expected to have received + * logevents with no associated exception info). True if + * logExceptionMessages was called. + */ + private void checkLoggingEvents(List logEvents, boolean thrown) { + LogEvent ev; + + assertEquals("Unexpected number of log events", 4, logEvents.size()); + + ev = (LogEvent) logEvents.get(0); + assertEquals("Info message expected", "info", ev.msg); + assertEquals("Info level expected", "INFO", ev.level); + assertEquals("Exception data incorrect", ev.throwable!=null, thrown); + + ev = (LogEvent) logEvents.get(1); + assertEquals("Warn message expected", "warn", ev.msg); + assertEquals("Warn level expected", "WARN", ev.level); + assertEquals("Exception data incorrect", ev.throwable!=null, thrown); + + ev = (LogEvent) logEvents.get(2); + assertEquals("Error message expected", "error", ev.msg); + assertEquals("Error level expected", "ERROR", ev.level); + assertEquals("Exception data incorrect", ev.throwable!=null, thrown); + + ev = (LogEvent) logEvents.get(3); + assertEquals("Fatal message expected", "fatal", ev.msg); + assertEquals("Fatal level expected", "FATAL", ev.level); + assertEquals("Exception data incorrect", ev.throwable!=null, thrown); + } + + + /** + * Log plain messages. + */ + private void logPlainMessages(Log log) { + log.trace("trace"); // Should not actually get logged + log.debug("debug"); // Should not actually get logged + log.info("info"); + log.warn("warn"); + log.error("error"); + log.fatal("fatal"); + } + + /** + * Log messages with exceptions + */ + private void logExceptionMessages(Log log) { + Throwable t = new DummyException(); + log.trace("trace", t); // Should not actually get logged + log.debug("debug", t); // Should not actually get logged + log.info("info", t); + log.warn("warn", t); + log.error("error", t); + log.fatal("fatal", t); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.log4j.log4j12; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + * Tests for Log4J logging that emulate a webapp running within + * a container where the commons-logging-api jar file is in + * the parent classpath and commons-logging.jar is in the child. + */ + +public class ApiClasspathStandardTestCase extends TestCase { + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useExplicitLoader("junit.", Test.class.getClassLoader()); + parent.addLogicalLib("commons-logging-api"); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("log4j12"); + child.addLogicalLib("commons-logging"); + child.addLogicalLib("testclasses"); + + Class testClass = child.loadClass( + "org.apache.commons.logging.log4j.log4j12.Log4j12StandardTests"); + return new PathableTestSuite(testClass, child); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.log4j.log4j12; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + +/** + * Tests for Log4J logging when there is only one classloader and everything + * is in it, as would be the situation for a standalone application. + */ + +public class AppClasspathStandardTestCase extends TestCase { + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader loader = new PathableClassLoader(null); + loader.useExplicitLoader("junit.", Test.class.getClassLoader()); + loader.addLogicalLib("testclasses"); + loader.addLogicalLib("log4j12"); + loader.addLogicalLib("commons-logging"); + + Class testClass = loader.loadClass( + "org.apache.commons.logging.log4j.log4j12.Log4j12StandardTests"); + return new PathableTestSuite(testClass, loader); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.log4j.log4j12; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + * Tests for Log4J logging that emulate a webapp running within + * a container where all the necessary libs are in the child. + */ + +public class ChildClasspathStandardTestCase extends TestCase { + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useExplicitLoader("junit.", Test.class.getClassLoader()); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("testclasses"); + child.addLogicalLib("log4j12"); + child.addLogicalLib("commons-logging"); + + Class testClass = child.loadClass( + "org.apache.commons.logging.log4j.log4j12.Log4j12StandardTests"); + return new PathableTestSuite(testClass, child); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/Log4j12StandardTests.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/Log4j12StandardTests.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/Log4j12StandardTests.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/Log4j12StandardTests.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.log4j.log4j12; + +import java.util.List; + +import org.apache.commons.logging.log4j.StandardTests; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; + +/** + * A concrete class that runs the standard tests, and is compiled + * specifically against log4j12. The parent class can't call any + * log4j methods at all as that would mean it has to be compiled + * against a particular version of log4j. + */ + +public class Log4j12StandardTests extends StandardTests { + + public void setUpTestAppender(List logEvents) { + TestAppender appender = new TestAppender(logEvents); + Logger rootLogger = Logger.getRootLogger(); + rootLogger.removeAllAppenders(); + rootLogger.addAppender(appender); + rootLogger.setLevel(Level.INFO); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.log4j.log4j12; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + +/** + * Tests for Log4J logging that emulate a webapp running within + * a container where all the necessary libs are in the parent. + */ + +public class ParentClasspathStandardTestCase extends TestCase { + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useExplicitLoader("junit.", Test.class.getClassLoader()); + parent.addLogicalLib("commons-logging"); + parent.addLogicalLib("log4j12"); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("testclasses"); + + Class testClass = child.loadClass( + "org.apache.commons.logging.log4j.log4j12.Log4j12StandardTests"); + return new PathableTestSuite(testClass, child); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/TestAppender.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/TestAppender.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/log4j/log4j12/TestAppender.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/log4j/log4j12/TestAppender.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.log4j.log4j12; + + +import java.util.List; + +import org.apache.commons.logging.log4j.StandardTests; +import org.apache.log4j.AppenderSkeleton; +import org.apache.log4j.spi.LoggingEvent; + +/** + * A custom implementation of org.apache.log4j.Appender which + * converts the log4j-specific log event record into a representation that + * doesn't have a dependency on log4j and stores that new representation into + * an external list. + */ + +public class TestAppender extends AppenderSkeleton { + + /** + * Constructor. + */ + public TestAppender(List logEvents) { + events = logEvents; + } + + // ----------------------------------------------------- Instance Variables + + + // The set of logged events for this appender + private final List events; + + + // ------------------------------------------------------- Appender Methods + + protected void append(LoggingEvent event) { + StandardTests.LogEvent lev = new StandardTests.LogEvent(); + + lev.level = event.getLevel().toString(); + + if (event.getMessage() == null) { + lev.msg = null; + } else { + lev.msg = event.getMessage().toString(); + } + + if (event.getThrowableInformation() == null) { + lev.throwable = null; + } else { + lev.throwable = event.getThrowableInformation().getThrowable(); + } + + events.add(lev); + } + + + public void close() { + } + + + public boolean requiresLayout() { + return false; + } + + +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/logkit/StandardTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/logkit/StandardTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/logkit/StandardTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/logkit/StandardTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.logkit; + + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import junit.framework.Test; + +import org.apache.commons.logging.AbstractLogTest; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.impl.LogKitLogger; + +/** + * Basic tests for Avalon LogKit logger adapter. + */ + +public class StandardTestCase extends AbstractLogTest { + + + // ----------------------------------------------------- Instance Variables + + + /** + *

The {@link LogFactory} implementation we have selected.

+ */ + protected LogFactory factory = null; + + + /** + *

The {@link Log} implementation we have selected.

+ */ + protected Log log = null; + + + // ------------------------------------------- JUnit Infrastructure Methods + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + Class thisClass = StandardTestCase.class; + + PathableClassLoader loader = new PathableClassLoader(null); + loader.useExplicitLoader("junit.", Test.class.getClassLoader()); + loader.addLogicalLib("testclasses"); + loader.addLogicalLib("commons-logging"); + loader.addLogicalLib("logkit"); + + Class testClass = loader.loadClass(thisClass.getName()); + return new PathableTestSuite(testClass, loader); + } + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + LogFactory.releaseAll(); + + System.setProperty( + "org.apache.commons.logging.Log", + "org.apache.commons.logging.impl.LogKitLogger"); + + factory = LogFactory.getFactory(); + log = LogFactory.getLog("TestLogger"); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + log = null; + factory = null; + LogFactory.releaseAll(); + } + + // ----------------------------------------------------------- Test Methods + + /** + * Override the abstract method from the parent class so that the + * inherited tests can access the right Log object type. + */ + public Log getLogObject() + { + return new LogKitLogger(this.getClass().getName()); + } + + // Test pristine LogFactory instance + public void testPristineFactory() { + + assertNotNull("LogFactory exists", factory); + assertEquals("LogFactory class", + "org.apache.commons.logging.impl.LogFactoryImpl", + factory.getClass().getName()); + + String names[] = factory.getAttributeNames(); + assertNotNull("Names exists", names); + assertEquals("Names empty", 0, names.length); + } + + // Test pristine Log instance + public void testPristineLog() { + checkStandard(); + } + + // Test Serializability of standard instance + public void testSerializable() throws Exception { + checkStandard(); + + // Serialize and deserialize the instance + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(log); + oos.close(); + ByteArrayInputStream bais = + new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + log = (Log) ois.readObject(); + ois.close(); + + checkStandard(); + } + + + // -------------------------------------------------------- Support Methods + + // Check the standard log instance + protected void checkStandard() { + + assertNotNull("Log exists", log); + assertEquals("Log class", + "org.apache.commons.logging.impl.LogKitLogger", + log.getClass().getName()); + + // Can we call level checkers with no exceptions? + // Note that by default *everything* is enabled for LogKit + assertTrue(log.isTraceEnabled()); + assertTrue(log.isDebugEnabled()); + assertTrue(log.isInfoEnabled()); + assertTrue(log.isWarnEnabled()); + assertTrue(log.isErrorEnabled()); + assertTrue(log.isFatalEnabled()); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/noop/NoOpLogTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/noop/NoOpLogTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/noop/NoOpLogTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/noop/NoOpLogTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.noop; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.impl.NoOpLog; +import org.apache.commons.logging.AbstractLogTest; + +/** + * Tests for NoOpLog logging adapter. + *

+ * This simply applies the tests defined in AbstractLogTest to this class. + */ +public class NoOpLogTestCase extends AbstractLogTest +{ + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + LogFactory.releaseAll(); + + System.setProperty( + "org.apache.commons.logging.Log", + "org.apache.commons.logging.impl.NoOpLog"); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + LogFactory.releaseAll(); + System.getProperties().remove("org.apache.commons.logging.Log"); + } + + /** + * Override the abstract method from the parent class so that the + * inherited tests can access the right Log object type. + */ + public Log getLogObject() + { + return new NoOpLog(this.getClass().getName()); + } + + // Test Serializability of standard instance + public void testSerializable() throws Exception { + Log log = LogFactory.getLog(this.getClass().getName()); + checkLog(log); + + // Serialize and deserialize the instance + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(log); + oos.close(); + ByteArrayInputStream bais = + new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + log = (Log) ois.readObject(); + ois.close(); + + checkLog(log); + } + + + // -------------------------------------------------------- Support Methods + + private void checkLog(Log log) { + + assertNotNull("Log exists", log); + assertEquals("Log class", + "org.apache.commons.logging.impl.NoOpLog", + log.getClass().getName()); + + // Can we call level checkers with no exceptions? + // Note that *everything* is permanently disabled for NoOpLog + assertFalse(log.isTraceEnabled()); + assertFalse(log.isDebugEnabled()); + assertFalse(log.isInfoEnabled()); + assertFalse(log.isWarnEnabled()); + assertFalse(log.isErrorEnabled()); + assertFalse(log.isFatalEnabled()); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/pathable/ChildFirstTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/pathable/ChildFirstTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/pathable/ChildFirstTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/pathable/ChildFirstTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,317 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging.pathable; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + +/** + * Tests for the PathableTestSuite and PathableClassLoader functionality, + * where lookup order for the PathableClassLoader is child-first. + *

+ * These tests assume: + *

    + *
  • junit is in system classpath + *
  • nothing else is in system classpath + *
+ */ + +public class ChildFirstTestCase extends TestCase { + + /** + * Set up a custom classloader hierarchy for this test case. + * The hierarchy is: + *
    + *
  • contextloader: child-first. + *
  • childloader: child-first, used to load test case. + *
  • parentloader: child-first, parent is the bootclassloader. + *
+ */ + public static Test suite() throws Exception { + Class thisClass = ChildFirstTestCase.class; + ClassLoader thisClassLoader = thisClass.getClassLoader(); + + // Make the parent a direct child of the bootloader to hide all + // other classes in the system classpath + PathableClassLoader parent = new PathableClassLoader(null); + parent.setParentFirst(false); + + // Make the junit classes visible as a special case, as junit + // won't be able to call this class at all without this. The + // junit classes must be visible from the classloader that loaded + // this class, so use that as the source for future access to classes + // from the junit package. + parent.useExplicitLoader("junit.", thisClassLoader); + + // Make the commons-logging.jar classes visible via the parent + parent.addLogicalLib("commons-logging"); + + // Create a child classloader to load the test case through + PathableClassLoader child = new PathableClassLoader(parent); + child.setParentFirst(false); + + // Obviously, the child classloader needs to have the test classes + // in its path! + child.addLogicalLib("testclasses"); + child.addLogicalLib("commons-logging-adapters"); + + // Create a third classloader to be the context classloader. + PathableClassLoader context = new PathableClassLoader(child); + context.setParentFirst(false); + + // reload this class via the child classloader + Class testClass = child.loadClass(thisClass.getName()); + + // and return our custom TestSuite class + return new PathableTestSuite(testClass, context); + } + + /** + * Utility method to return the set of all classloaders in the + * parent chain starting from the one that loaded the class for + * this object instance. + */ + private Set getAncestorCLs() { + Set s = new HashSet(); + ClassLoader cl = this.getClass().getClassLoader(); + while (cl != null) { + s.add(cl); + cl = cl.getParent(); + } + return s; + } + + /** + * Test that the classloader hierarchy is as expected, and that + * calling loadClass() on various classloaders works as expected. + * Note that for this test case, parent-first classloading is + * in effect. + */ + public void testPaths() throws Exception { + // the context classloader is not expected to be null + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + assertNotNull("Context classloader is null", contextLoader); + assertEquals("Context classloader has unexpected type", + PathableClassLoader.class.getName(), + contextLoader.getClass().getName()); + + // the classloader that loaded this class is obviously not null + ClassLoader thisLoader = this.getClass().getClassLoader(); + assertNotNull("thisLoader is null", thisLoader); + assertEquals("thisLoader has unexpected type", + PathableClassLoader.class.getName(), + thisLoader.getClass().getName()); + + // the suite method specified that the context classloader's parent + // is the loader that loaded this test case. + assertSame("Context classloader is not child of thisLoader", + thisLoader, contextLoader.getParent()); + + // thisLoader's parent should be available + ClassLoader parentLoader = thisLoader.getParent(); + assertNotNull("Parent classloader is null", parentLoader); + assertEquals("Parent classloader has unexpected type", + PathableClassLoader.class.getName(), + parentLoader.getClass().getName()); + + // parent should have a parent of null + assertNull("Parent classloader has non-null parent", parentLoader.getParent()); + + // getSystemClassloader is not a PathableClassLoader; it's of a + // built-in type. This also verifies that system classloader is none of + // (context, child, parent). + ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); + assertNotNull("System classloader is null", systemLoader); + assertFalse("System classloader has unexpected type", + PathableClassLoader.class.getName().equals( + systemLoader.getClass().getName())); + + // junit classes should be visible; their classloader is not + // in the hierarchy of parent classloaders for this class, + // though it is accessable due to trickery in the PathableClassLoader. + Class junitTest = contextLoader.loadClass("junit.framework.Test"); + Set ancestorCLs = getAncestorCLs(); + assertFalse("Junit not loaded by ancestor classloader", + ancestorCLs.contains(junitTest.getClassLoader())); + + // jcl api classes should be visible only via the parent + Class logClass = contextLoader.loadClass("org.apache.commons.logging.Log"); + assertSame("Log class not loaded via parent", + logClass.getClassLoader(), parentLoader); + + // jcl adapter classes should be visible via both parent and child. However + // as the classloaders are child-first we should see the child one. + Class log4jClass = contextLoader.loadClass("org.apache.commons.logging.impl.Log4JLogger"); + assertSame("Log4JLogger not loaded via child", + log4jClass.getClassLoader(), thisLoader); + + // test classes should be visible via the child only + Class testClass = contextLoader.loadClass("org.apache.commons.logging.PathableTestSuite"); + assertSame("PathableTestSuite not loaded via child", + testClass.getClassLoader(), thisLoader); + + // test loading of class that is not available + try { + Class noSuchClass = contextLoader.loadClass("no.such.class"); + fail("Class no.such.class is unexpectedly available"); + assertNotNull(noSuchClass); // silence warning about unused var + } catch(ClassNotFoundException ex) { + // ok + } + + // String class classloader is null + Class stringClass = contextLoader.loadClass("java.lang.String"); + assertNull("String class classloader is not null!", + stringClass.getClassLoader()); + } + + /** + * Test that the various flavours of ClassLoader.getResource work as expected. + */ + public void testResource() { + URL resource; + + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader childLoader = contextLoader.getParent(); + + // getResource where it doesn't exist + resource = childLoader.getResource("nosuchfile"); + assertNull("Non-null URL returned for invalid resource name", resource); + + // getResource where it is accessable only to parent classloader + resource = childLoader.getResource("org/apache/commons/logging/Log.class"); + assertNotNull("Unable to locate Log.class resource", resource); + + // getResource where it is accessable only to child classloader + resource = childLoader.getResource("org/apache/commons/logging/PathableTestSuite.class"); + assertNotNull("Unable to locate PathableTestSuite.class resource", resource); + + // getResource where it is accessable to both classloaders. The one visible + // to the child should be returned. The URL returned will be of form + // jar:file:/x/y.jar!path/to/resource. The filename part should include the jarname + // of form commons-logging-adapters-nnnn.jar, not commons-logging-nnnn.jar + resource = childLoader.getResource("org/apache/commons/logging/impl/Log4JLogger.class"); + assertNotNull("Unable to locate Log4JLogger.class resource", resource); + assertTrue("Incorrect source for Log4JLogger class", + resource.toString().indexOf("/commons-logging-adapters-1.") > 0); + } + + /** + * Test that the various flavours of ClassLoader.getResources work as expected. + */ + public void testResources() throws Exception { + Enumeration resources; + URL[] urls; + + // verify the classloader hierarchy + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader childLoader = contextLoader.getParent(); + ClassLoader parentLoader = childLoader.getParent(); + ClassLoader bootLoader = parentLoader.getParent(); + assertNull("Unexpected classloader hierarchy", bootLoader); + + // getResources where no instances exist + resources = childLoader.getResources("nosuchfile"); + urls = toURLArray(resources); + assertEquals("Non-null URL returned for invalid resource name", 0, urls.length); + + // getResources where the resource only exists in the parent + resources = childLoader.getResources("org/apache/commons/logging/Log.class"); + urls = toURLArray(resources); + assertEquals("Unexpected number of Log.class resources found", 1, urls.length); + + // getResources where the resource only exists in the child + resources = childLoader.getResources("org/apache/commons/logging/PathableTestSuite.class"); + urls = toURLArray(resources); + assertEquals("Unexpected number of PathableTestSuite.class resources found", 1, urls.length); + + // getResources where the resource exists in both. + // resources should be returned in order (child-resource, parent-resource). + // + // IMPORTANT: due to the fact that in java 1.4 and earlier method + // ClassLoader.getResources is final it isn't possible for PathableClassLoader + // to override this. So even when child-first is enabled the resource order + // is still (parent-resources, child-resources). This test verifies the expected + // behaviour - even though it's not the desired behaviour. + + resources = childLoader.getResources("org/apache/commons/logging/impl/Log4JLogger.class"); + urls = toURLArray(resources); + assertEquals("Unexpected number of Log4JLogger.class resources found", 2, urls.length); + + // There is no guarantee about the ordering of results returned from getResources + // To make this test portable across JVMs, sort the string to give them a known order + String[] urlsToStrings = new String[2]; + urlsToStrings[0] = urls[0].toString(); + urlsToStrings[1] = urls[1].toString(); + Arrays.sort(urlsToStrings); + assertTrue("Incorrect source for Log4JLogger class", + urlsToStrings[0].indexOf("/commons-logging-1.") > 0); + assertTrue("Incorrect source for Log4JLogger class", + urlsToStrings[1].indexOf("/commons-logging-adapters-1.") > 0); + } + + /** + * Utility method to convert an enumeration-of-URLs into an array of URLs. + */ + private static URL[] toURLArray(Enumeration e) { + ArrayList l = new ArrayList(); + while (e.hasMoreElements()) { + URL u = (URL) e.nextElement(); + l.add(u); + } + URL[] tmp = new URL[l.size()]; + return (URL[]) l.toArray(tmp); + } + + /** + * Test that getResourceAsStream works. + */ + public void testResourceAsStream() throws Exception { + java.io.InputStream is; + + // verify the classloader hierarchy + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader childLoader = contextLoader.getParent(); + ClassLoader parentLoader = childLoader.getParent(); + ClassLoader bootLoader = parentLoader.getParent(); + assertNull("Unexpected classloader hierarchy", bootLoader); + + // getResourceAsStream where no instances exist + is = childLoader.getResourceAsStream("nosuchfile"); + assertNull("Invalid resource returned non-null stream", is); + + // getResourceAsStream where resource does exist + is = childLoader.getResourceAsStream("org/apache/commons/logging/Log.class"); + assertNotNull("Null returned for valid resource", is); + is.close(); + + // It would be nice to test parent-first ordering here, but that would require + // having a resource with the same name in both the parent and child loaders, + // but with different contents. That's a little tricky to set up so we'll + // skip that for now. + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/pathable/GeneralTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/pathable/GeneralTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/pathable/GeneralTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/pathable/GeneralTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging.pathable; + +import java.net.URL; +import java.net.URLClassLoader; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + +/** + * Tests for the PathableTestSuite class. + */ + +public class GeneralTestCase extends TestCase { + + /** + * Set up a custom classloader hierarchy for this test case. + */ + public static Test suite() throws Exception { + Class thisClass = GeneralTestCase.class; + ClassLoader thisClassLoader = thisClass.getClassLoader(); + + PathableClassLoader loader = new PathableClassLoader(null); + loader.useExplicitLoader("junit.", thisClassLoader); + loader.addLogicalLib("testclasses"); + + // reload this class via the child classloader + Class testClass = loader.loadClass(thisClass.getName()); + + // and return our custom TestSuite class + return new PathableTestSuite(testClass, loader); + } + + /** + * Verify that a certain system property is not set, then set it. + */ + private static void checkAndSetProperties() { + String prop = System.getProperty("no.such.property"); + assertNull("no.such.property is unexpectedly defined", prop); + System.setProperty("no.such.property", "dummy value"); + prop = System.getProperty("no.such.property"); + assertNotNull("no.such.property is unexpectedly undefined", prop); + } + + /** + * Verify that when a test method modifies the system properties they are + * reset before the next test is run. + *

+ * This method works in conjunction with testResetProps2. There is no + * way of knowing which test method junit will run first, but it doesn't + * matter; whichever one of them runs first will modify the system properties. + * If the PathableTestSuite isn't resetting the system properties then whichever + * of them runs second will fail. Of course if other methods are run in-between + * then those methods might also fail... + */ + public void testResetProps1() { + checkAndSetProperties(); + } + + /** + * See testResetProps1. + */ + public void testResetProps2() { + checkAndSetProperties(); + } + + /** + * Verify that the context classloader is a custom one, then reset it to + * a non-custom one. + */ + private static void checkAndSetContext() { + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + assertEquals("ContextLoader is of unexpected type", + contextLoader.getClass().getName(), + PathableClassLoader.class.getName()); + + URL[] noUrls = new URL[0]; + Thread.currentThread().setContextClassLoader(new URLClassLoader(noUrls)); + } + + /** + * Verify that when a test method modifies the context classloader it is + * reset before the next test is run. + *

+ * This method works in conjunction with testResetContext2. There is no + * way of knowing which test method junit will run first, but it doesn't + * matter; whichever one of them runs first will modify the contextClassloader. + * If the PathableTestSuite isn't resetting the contextClassLoader then whichever + * of them runs second will fail. Of course if other methods are run in-between + * then those methods might also fail... + */ + public void testResetContext1() { + checkAndSetContext(); + } + + /** + * See testResetContext1. + */ + public void testResetContext2() { + checkAndSetContext(); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/pathable/ParentFirstTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/pathable/ParentFirstTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/pathable/ParentFirstTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/pathable/ParentFirstTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,308 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging.pathable; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + +/** + * Tests for the PathableTestSuite and PathableClassLoader functionality, + * where lookup order for the PathableClassLoader is parent-first. + *

+ * These tests assume: + *

    + *
  • junit is in system classpath + *
  • nothing else is in system classpath + *
+ */ + +public class ParentFirstTestCase extends TestCase { + + /** + * Set up a custom classloader hierarchy for this test case. + * The hierarchy is: + *
    + *
  • contextloader: parent-first. + *
  • childloader: parent-first, used to load test case. + *
  • parentloader: parent-first, parent is the bootclassloader. + *
+ */ + public static Test suite() throws Exception { + Class thisClass = ParentFirstTestCase.class; + ClassLoader thisClassLoader = thisClass.getClassLoader(); + + // Make the parent a direct child of the bootloader to hide all + // other classes in the system classpath + PathableClassLoader parent = new PathableClassLoader(null); + + // Make the junit classes visible as a special case, as junit + // won't be able to call this class at all without this. The + // junit classes must be visible from the classloader that loaded + // this class, so use that as the source for future access to classes + // from the junit package. + parent.useExplicitLoader("junit.", thisClassLoader); + + // make the commons-logging.jar classes visible via the parent + parent.addLogicalLib("commons-logging"); + + // create a child classloader to load the test case through + PathableClassLoader child = new PathableClassLoader(parent); + + // obviously, the child classloader needs to have the test classes + // in its path! + child.addLogicalLib("testclasses"); + child.addLogicalLib("commons-logging-adapters"); + + // create a third classloader to be the context classloader. + PathableClassLoader context = new PathableClassLoader(child); + + // reload this class via the child classloader + Class testClass = child.loadClass(thisClass.getName()); + + // and return our custom TestSuite class + return new PathableTestSuite(testClass, context); + } + + /** + * Utility method to return the set of all classloaders in the + * parent chain starting from the one that loaded the class for + * this object instance. + */ + private Set getAncestorCLs() { + Set s = new HashSet(); + ClassLoader cl = this.getClass().getClassLoader(); + while (cl != null) { + s.add(cl); + cl = cl.getParent(); + } + return s; + } + + /** + * Test that the classloader hierarchy is as expected, and that + * calling loadClass() on various classloaders works as expected. + * Note that for this test case, parent-first classloading is + * in effect. + */ + public void testPaths() throws Exception { + // the context classloader is not expected to be null + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + assertNotNull("Context classloader is null", contextLoader); + assertEquals("Context classloader has unexpected type", + PathableClassLoader.class.getName(), + contextLoader.getClass().getName()); + + // the classloader that loaded this class is obviously not null + ClassLoader thisLoader = this.getClass().getClassLoader(); + assertNotNull("thisLoader is null", thisLoader); + assertEquals("thisLoader has unexpected type", + PathableClassLoader.class.getName(), + thisLoader.getClass().getName()); + + // the suite method specified that the context classloader's parent + // is the loader that loaded this test case. + assertSame("Context classloader is not child of thisLoader", + thisLoader, contextLoader.getParent()); + + // thisLoader's parent should be available + ClassLoader parentLoader = thisLoader.getParent(); + assertNotNull("Parent classloader is null", parentLoader); + assertEquals("Parent classloader has unexpected type", + PathableClassLoader.class.getName(), + parentLoader.getClass().getName()); + + // parent should have a parent of null + assertNull("Parent classloader has non-null parent", parentLoader.getParent()); + + // getSystemClassloader is not a PathableClassLoader; it's of a + // built-in type. This also verifies that system classloader is none of + // (context, child, parent). + ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); + assertNotNull("System classloader is null", systemLoader); + assertFalse("System classloader has unexpected type", + PathableClassLoader.class.getName().equals( + systemLoader.getClass().getName())); + + // junit classes should be visible; their classloader is not + // in the hierarchy of parent classloaders for this class, + // though it is accessable due to trickery in the PathableClassLoader. + Class junitTest = contextLoader.loadClass("junit.framework.Test"); + Set ancestorCLs = getAncestorCLs(); + assertFalse("Junit not loaded by ancestor classloader", + ancestorCLs.contains(junitTest.getClassLoader())); + + // jcl api classes should be visible only via the parent + Class logClass = contextLoader.loadClass("org.apache.commons.logging.Log"); + assertSame("Log class not loaded via parent", + logClass.getClassLoader(), parentLoader); + + // jcl adapter classes should be visible via both parent and child. However + // as the classloaders are parent-first we should see the parent one. + Class log4jClass = contextLoader.loadClass("org.apache.commons.logging.impl.Log4JLogger"); + assertSame("Log4JLogger not loaded via parent", + log4jClass.getClassLoader(), parentLoader); + + // test classes should be visible via the child only + Class testClass = contextLoader.loadClass("org.apache.commons.logging.PathableTestSuite"); + assertSame("PathableTestSuite not loaded via child", + testClass.getClassLoader(), thisLoader); + + // test loading of class that is not available + try { + Class noSuchClass = contextLoader.loadClass("no.such.class"); + fail("Class no.such.class is unexpectedly available"); + assertNotNull(noSuchClass); // silence warning about unused var + } catch(ClassNotFoundException ex) { + // ok + } + + // String class classloader is null + Class stringClass = contextLoader.loadClass("java.lang.String"); + assertNull("String class classloader is not null!", + stringClass.getClassLoader()); + } + + /** + * Test that the various flavours of ClassLoader.getResource work as expected. + */ + public void testResource() { + URL resource; + + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader childLoader = contextLoader.getParent(); + + // getResource where it doesn't exist + resource = childLoader.getResource("nosuchfile"); + assertNull("Non-null URL returned for invalid resource name", resource); + + // getResource where it is accessable only to parent classloader + resource = childLoader.getResource("org/apache/commons/logging/Log.class"); + assertNotNull("Unable to locate Log.class resource", resource); + + // getResource where it is accessable only to child classloader + resource = childLoader.getResource("org/apache/commons/logging/PathableTestSuite.class"); + assertNotNull("Unable to locate PathableTestSuite.class resource", resource); + + // getResource where it is accessable to both classloaders. The one visible + // to the parent should be returned. The URL returned will be of form + // jar:file:/x/y.jar!path/to/resource. The filename part should include the jarname + // of form commons-logging-nnnn.jar, not commons-logging-adapters-nnnn.jar + resource = childLoader.getResource("org/apache/commons/logging/impl/Log4JLogger.class"); + assertNotNull("Unable to locate Log4JLogger.class resource", resource); + assertTrue("Incorrect source for Log4JLogger class", + resource.toString().indexOf("/commons-logging-1.") > 0); + } + + /** + * Test that the various flavours of ClassLoader.getResources work as expected. + */ + public void testResources() throws Exception { + Enumeration resources; + URL[] urls; + + // verify the classloader hierarchy + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader childLoader = contextLoader.getParent(); + ClassLoader parentLoader = childLoader.getParent(); + ClassLoader bootLoader = parentLoader.getParent(); + assertNull("Unexpected classloader hierarchy", bootLoader); + + // getResources where no instances exist + resources = childLoader.getResources("nosuchfile"); + urls = toURLArray(resources); + assertEquals("Non-null URL returned for invalid resource name", 0, urls.length); + + // getResources where the resource only exists in the parent + resources = childLoader.getResources("org/apache/commons/logging/Log.class"); + urls = toURLArray(resources); + assertEquals("Unexpected number of Log.class resources found", 1, urls.length); + + // getResources where the resource only exists in the child + resources = childLoader.getResources("org/apache/commons/logging/PathableTestSuite.class"); + urls = toURLArray(resources); + assertEquals("Unexpected number of PathableTestSuite.class resources found", 1, urls.length); + + // getResources where the resource exists in both. + // resources should be returned in order (parent-resource, child-resource) + resources = childLoader.getResources("org/apache/commons/logging/impl/Log4JLogger.class"); + urls = toURLArray(resources); + assertEquals("Unexpected number of Log4JLogger.class resources found", 2, urls.length); + + // There is no gaurantee about the ordering of results returned from getResources + // To make this test portable across JVMs, sort the string to give them a known order + String[] urlsToStrings = new String[2]; + urlsToStrings[0] = urls[0].toString(); + urlsToStrings[1] = urls[1].toString(); + Arrays.sort(urlsToStrings); + assertTrue("Incorrect source for Log4JLogger class", + urlsToStrings[0].indexOf("/commons-logging-1.") > 0); + assertTrue("Incorrect source for Log4JLogger class", + urlsToStrings[1].indexOf("/commons-logging-adapters-1.") > 0); + + } + + /** + * Utility method to convert an enumeration-of-URLs into an array of URLs. + */ + private static URL[] toURLArray(Enumeration e) { + ArrayList l = new ArrayList(); + while (e.hasMoreElements()) { + URL u = (URL) e.nextElement(); + l.add(u); + } + URL[] tmp = new URL[l.size()]; + return (URL[]) l.toArray(tmp); + } + + /** + * Test that getResourceAsStream works. + */ + public void testResourceAsStream() throws Exception { + java.io.InputStream is; + + // verify the classloader hierarchy + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader childLoader = contextLoader.getParent(); + ClassLoader parentLoader = childLoader.getParent(); + ClassLoader bootLoader = parentLoader.getParent(); + assertNull("Unexpected classloader hierarchy", bootLoader); + + // getResourceAsStream where no instances exist + is = childLoader.getResourceAsStream("nosuchfile"); + assertNull("Invalid resource returned non-null stream", is); + + // getResourceAsStream where resource does exist + is = childLoader.getResourceAsStream("org/apache/commons/logging/Log.class"); + assertNotNull("Null returned for valid resource", is); + is.close(); + + // It would be nice to test parent-first ordering here, but that would require + // having a resource with the same name in both the parent and child loaders, + // but with different contents. That's a little tricky to set up so we'll + // skip that for now. + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/security/MockSecurityManager.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/security/MockSecurityManager.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/security/MockSecurityManager.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/security/MockSecurityManager.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.security; + +import java.io.FilePermission; +import java.security.Permission; +import java.security.Permissions; + + +/** + * Custom implementation of a security manager, so we can control the + * security environment for tests in this package. + */ +public class MockSecurityManager extends SecurityManager { + + private final Permissions permissions = new Permissions(); + private static final Permission setSecurityManagerPerm = + new RuntimePermission("setSecurityManager"); + + private int untrustedCodeCount = 0; + + public MockSecurityManager() { + permissions.add(setSecurityManagerPerm); + } + + /** + * Define the set of permissions to be granted to classes in the o.a.c.l package, + * but NOT to unit-test classes in o.a.c.l.security package. + */ + public void addPermission(Permission p) { + permissions.add(p); + } + + /** + * This returns the number of times that a check of a permission failed + * due to stack-walking tracing up into untrusted code. Any non-zero + * value indicates a bug in JCL, ie a situation where code was not + * correctly wrapped in an AccessController block. The result of such a + * bug is that signing JCL is not sufficient to allow JCL to perform + * the operation; the caller would need to be signed too. + */ + public int getUntrustedCodeCount() { + return untrustedCodeCount; + } + + public void checkPermission(Permission p) throws SecurityException { + if (setSecurityManagerPerm.implies(p)) { + // ok, allow this; we don't want to block any calls to setSecurityManager + // otherwise this custom security manager cannot be reset to the original. + // System.out.println("setSecurityManager: granted"); + return; + } + + // Allow read-only access to files, as this is needed to load classes! + // Ideally, we would limit this to just .class and .jar files. + if (p instanceof FilePermission) { + FilePermission fp = (FilePermission) p; + if (fp.getActions().equals("read")) { + // System.out.println("Permit read of files"); + return; + } + } + + System.out.println("\n\ntesting permission:" + p.getClass() + ":"+ p); + + Exception e = new Exception(); + e.fillInStackTrace(); + StackTraceElement[] stack = e.getStackTrace(); + + // scan the call stack from most recent to oldest. + // start at 1 to skip the entry in the stack for this method + for(int i=1; i + * This class has only one unit test, as we are (in part) checking behaviour in + * the static block of the LogFactory class. As that class cannot be unloaded after + * being loaded into a classloader, the only workaround is to use the + * PathableClassLoader approach to ensure each test is run in its own + * classloader, and use a separate testcase class for each test. + */ +public class SecurityAllowedTestCase extends TestCase +{ + private SecurityManager oldSecMgr; + + // Dummy special hashtable, so we can tell JCL to use this instead of + // the standard one. + public static class CustomHashtable extends Hashtable { + + /** + * Generated serial version ID. + */ + private static final long serialVersionUID = 8941017300059246720L; + } + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useExplicitLoader("junit.", Test.class.getClassLoader()); + parent.addLogicalLib("commons-logging"); + parent.addLogicalLib("testclasses"); + + Class testClass = parent.loadClass( + "org.apache.commons.logging.security.SecurityAllowedTestCase"); + return new PathableTestSuite(testClass, parent); + } + + public void setUp() { + // save security manager so it can be restored in tearDown + oldSecMgr = System.getSecurityManager(); + } + + public void tearDown() { + // Restore, so other tests don't get stuffed up if a test + // sets a custom security manager. + System.setSecurityManager(oldSecMgr); + } + + /** + * Test what happens when JCL is run with all permissions enabled. Custom + * overrides should take effect. + */ + public void testAllAllowed() { + System.setProperty( + LogFactory.HASHTABLE_IMPLEMENTATION_PROPERTY, + CustomHashtable.class.getName()); + MockSecurityManager mySecurityManager = new MockSecurityManager(); + mySecurityManager.addPermission(new AllPermission()); + System.setSecurityManager(mySecurityManager); + + try { + // Use reflection so that we can control exactly when the static + // initialiser for the LogFactory class is executed. + Class c = this.getClass().getClassLoader().loadClass( + "org.apache.commons.logging.LogFactory"); + Method m = c.getMethod("getLog", new Class[] {Class.class}); + Log log = (Log) m.invoke(null, new Object[] {this.getClass()}); + + // Check whether we had any security exceptions so far (which were + // caught by the code). We should not, as every secure operation + // should be wrapped in an AccessController. Any security exceptions + // indicate a path that is missing an appropriate AccessController. + // + // We don't wait until after the log.info call to get this count + // because java.util.logging tries to load a resource bundle, which + // requires permission accessClassInPackage. JCL explicitly does not + // wrap calls to log methods in AccessControllers because writes to + // a log file *should* only be permitted if the original caller is + // trusted to access that file. + int untrustedCodeCount = mySecurityManager.getUntrustedCodeCount(); + log.info("testing"); + + // check that the default map implementation was loaded, as JCL was + // forbidden from reading the HASHTABLE_IMPLEMENTATION_PROPERTY property. + System.setSecurityManager(null); + Field factoryField = c.getDeclaredField("factories"); + factoryField.setAccessible(true); + Object factoryTable = factoryField.get(null); + assertNotNull(factoryTable); + assertEquals(CustomHashtable.class.getName(), factoryTable.getClass().getName()); + + // we better compare that we have no security exception during the call to log + // IBM JVM tries to load bundles during the invoke call, which increase the count + assertEquals(untrustedCodeCount, mySecurityManager.getUntrustedCodeCount()); + } catch(Throwable t) { + // Restore original security manager so output can be generated; the + // PrintWriter constructor tries to read the line.separator + // system property. + System.setSecurityManager(oldSecMgr); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + t.printStackTrace(pw); + fail("Unexpected exception:" + t.getMessage() + ":" + sw.toString()); + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/security/SecurityForbiddenTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/security/SecurityForbiddenTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/security/SecurityForbiddenTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/security/SecurityForbiddenTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.security; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Hashtable; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + +/** + * Tests for logging with a security policy that forbids JCL access to anything. + *

+ * Performing tests with security permissions disabled is tricky, as building error + * messages on failure requires certain security permissions. If the security manager + * blocks these, then the test can fail without the error messages being output. + *

+ * This class has only one unit test, as we are (in part) checking behaviour in + * the static block of the LogFactory class. As that class cannot be unloaded after + * being loaded into a classloader, the only workaround is to use the + * PathableClassLoader approach to ensure each test is run in its own + * classloader, and use a separate testcase class for each test. + */ +public class SecurityForbiddenTestCase extends TestCase +{ + private SecurityManager oldSecMgr; + + // Dummy special hashtable, so we can tell JCL to use this instead of + // the standard one. + public static class CustomHashtable extends Hashtable { + + /** + * Generated serial version ID. + */ + private static final long serialVersionUID = 7224652794746236024L; + } + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useExplicitLoader("junit.", Test.class.getClassLoader()); + parent.addLogicalLib("commons-logging"); + parent.addLogicalLib("testclasses"); + + Class testClass = parent.loadClass( + "org.apache.commons.logging.security.SecurityForbiddenTestCase"); + return new PathableTestSuite(testClass, parent); + } + + public void setUp() { + // save security manager so it can be restored in tearDown + oldSecMgr = System.getSecurityManager(); + } + + public void tearDown() { + // Restore, so other tests don't get stuffed up if a test + // sets a custom security manager. + System.setSecurityManager(oldSecMgr); + } + + /** + * Test what happens when JCL is run with absolutely no security + * privileges at all, including reading system properties. Everything + * should fall back to the built-in defaults. + */ + public void testAllForbidden() { + System.setProperty( + LogFactory.HASHTABLE_IMPLEMENTATION_PROPERTY, + CustomHashtable.class.getName()); + MockSecurityManager mySecurityManager = new MockSecurityManager(); + + System.setSecurityManager(mySecurityManager); + + try { + // Use reflection so that we can control exactly when the static + // initialiser for the LogFactory class is executed. + Class c = this.getClass().getClassLoader().loadClass( + "org.apache.commons.logging.LogFactory"); + Method m = c.getMethod("getLog", new Class[] {Class.class}); + Log log = (Log) m.invoke(null, new Object[] {this.getClass()}); + log.info("testing"); + + // check that the default map implementation was loaded, as JCL was + // forbidden from reading the HASHTABLE_IMPLEMENTATION_PROPERTY property. + // + // The default is either the java Hashtable class (java < 1.2) or the + // JCL WeakHashtable (java >= 1.3). + System.setSecurityManager(oldSecMgr); + Field factoryField = c.getDeclaredField("factories"); + factoryField.setAccessible(true); + Object factoryTable = factoryField.get(null); + assertNotNull(factoryTable); + String ftClassName = factoryTable.getClass().getName(); + assertTrue("Custom hashtable unexpectedly used", + !CustomHashtable.class.getName().equals(ftClassName)); + + assertEquals(0, mySecurityManager.getUntrustedCodeCount()); + } catch(Throwable t) { + // Restore original security manager so output can be generated; the + // PrintWriter constructor tries to read the line.separator + // system property. + System.setSecurityManager(oldSecMgr); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + t.printStackTrace(pw); + fail("Unexpected exception:" + t.getMessage() + ":" + sw.toString()); + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/servlet/BasicServletTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/servlet/BasicServletTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/servlet/BasicServletTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/servlet/BasicServletTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.servlet; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.impl.ServletContextCleaner; + + +/** + * Tests for ServletContextCleaner utility class. + */ + +public class BasicServletTestCase extends TestCase { + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + // LogFactory in parent + // LogFactory in child (loads test) + // LogFactory in tccl + // + // Having the test loaded via a loader above the tccl emulates the situation + // where a web.xml file specifies ServletContextCleaner as a listener, and + // that class is deployed via a shared classloader. + + PathableClassLoader parent = new PathableClassLoader(null); + parent.useExplicitLoader("junit.", Test.class.getClassLoader()); + parent.addLogicalLib("commons-logging"); + parent.addLogicalLib("servlet-api"); + + PathableClassLoader child = new PathableClassLoader(parent); + child.setParentFirst(false); + child.addLogicalLib("commons-logging"); + child.addLogicalLib("testclasses"); + + PathableClassLoader tccl = new PathableClassLoader(child); + tccl.setParentFirst(false); + tccl.addLogicalLib("commons-logging"); + + Class testClass = child.loadClass(BasicServletTestCase.class.getName()); + return new PathableTestSuite(testClass, tccl); + } + + /** + * Test that calling ServletContextCleaner.contextDestroyed doesn't crash. + * Testing anything else is rather difficult... + */ + public void testBasics() { + ServletContextCleaner scc = new ServletContextCleaner(); + scc.contextDestroyed(null); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/simple/CustomConfigTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/simple/CustomConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/simple/CustomConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/simple/CustomConfigTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,277 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.simple; + + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import junit.framework.Test; + +import org.apache.commons.logging.DummyException; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.impl.SimpleLog; + + +/** + *

TestCase for simple logging when running with custom configuration + * properties.

+ * + * @author Craig R. McClanahan + * @version $Revision: 1432587 $ $Date: 2013-01-13 12:11:32 +0100 (Sun, 13 Jan 2013) $ + */ +public class CustomConfigTestCase extends DefaultConfigTestCase { + + + // ----------------------------------------------------- Instance Variables + + + /** + *

The expected log records.

+ */ + protected List expected; + + + /** + *

The message levels that should have been logged.

+ */ + /* + protected Level testLevels[] = + { Level.FINE, Level.INFO, Level.WARNING, Level.SEVERE, Level.SEVERE }; + */ + + + /** + *

The message strings that should have been logged.

+ */ + protected String testMessages[] = + { "debug", "info", "warn", "error", "fatal" }; + + + // ------------------------------------------- JUnit Infrastructure Methods + + /** + * Set system properties that will control the LogFactory/Log objects + * when they are created. Subclasses can override this method to + * define properties that suit them. + */ + public void setProperties() { + System.setProperty( + "org.apache.commons.logging.Log", + "org.apache.commons.logging.simple.DecoratedSimpleLog"); + System.setProperty( + "org.apache.commons.logging.simplelog.defaultlog", + "debug"); + } + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + LogFactory.releaseAll(); + setProperties(); + expected = new ArrayList(); + setUpFactory(); + setUpLog("DecoratedLogger"); + } + + + /** + * Return the tests included in this test suite. + *

+ * We need to use a PathableClassLoader here because the SimpleLog class + * is a pile of junk and chock-full of static variables. Any other test + * (like simple.CustomConfigTestCase) that has used the SimpleLog class + * will already have caused it to do once-only initialisation that we + * can't reset, even by calling LogFactory.releaseAll, because of those + * ugly statics. The only clean solution is to load a clean copy of + * commons-logging including SimpleLog via a nice clean classloader. + * Or we could fix SimpleLog to be sane... + */ + public static Test suite() throws Exception { + Class thisClass = CustomConfigTestCase.class; + + PathableClassLoader loader = new PathableClassLoader(null); + loader.useExplicitLoader("junit.", Test.class.getClassLoader()); + loader.addLogicalLib("testclasses"); + loader.addLogicalLib("commons-logging"); + + Class testClass = loader.loadClass(thisClass.getName()); + return new PathableTestSuite(testClass, loader); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + super.tearDown(); + expected = null; + } + + + // ----------------------------------------------------------- Test Methods + + + // Test logging message strings with exceptions + public void testExceptionMessages() throws Exception { + + ((DecoratedSimpleLog) log).clearCache(); + logExceptionMessages(); + checkExpected(); + + } + + + // Test logging plain message strings + public void testPlainMessages() throws Exception { + + ((DecoratedSimpleLog) log).clearCache(); + logPlainMessages(); + checkExpected(); + + } + + + // Test Serializability of standard instance + public void testSerializable() throws Exception { + + ((DecoratedSimpleLog) log).clearCache(); + logPlainMessages(); + super.testSerializable(); + logExceptionMessages(); + checkExpected(); + + } + + + // -------------------------------------------------------- Support Methods + + + // Check the decorated log instance + protected void checkDecorated() { + + assertNotNull("Log exists", log); + assertEquals("Log class", + "org.apache.commons.logging.simple.DecoratedSimpleLog", + log.getClass().getName()); + + // Can we call level checkers with no exceptions? + assertTrue(log.isDebugEnabled()); + assertTrue(log.isErrorEnabled()); + assertTrue(log.isFatalEnabled()); + assertTrue(log.isInfoEnabled()); + assertTrue(!log.isTraceEnabled()); + assertTrue(log.isWarnEnabled()); + + // Can we retrieve the current log level? + assertEquals(SimpleLog.LOG_LEVEL_DEBUG, ((SimpleLog) log).getLevel()); + + // Can we validate the extra exposed properties? + checkDecoratedDateTime(); + assertEquals("DecoratedLogger", + ((DecoratedSimpleLog) log).getLogName()); + checkShowDateTime(); + assertTrue(((DecoratedSimpleLog) log).getShowShortName()); + + } + + /** Hook for subclassses */ + protected void checkShowDateTime() { + assertTrue(!((DecoratedSimpleLog) log).getShowDateTime()); + } + + /** Hook for subclasses */ + protected void checkDecoratedDateTime() { + assertEquals("yyyy/MM/dd HH:mm:ss:SSS zzz", + ((DecoratedSimpleLog) log).getDateTimeFormat()); + } + + + + // Check the actual log records against the expected ones + protected void checkExpected() { + + List acts = ((DecoratedSimpleLog) log).getCache(); + Iterator exps = expected.iterator(); + int n = 0; + while (exps.hasNext()) { + LogRecord exp = (LogRecord) exps.next(); + LogRecord act = (LogRecord) acts.get(n++); + assertEquals("Row " + n + " type", exp.type, act.type); + assertEquals("Row " + n + " message", exp.message, act.message); + assertEquals("Row " + n + " throwable", exp.t, act.t); + } + + } + + + // Check the standard log instance + protected void checkStandard() { + + checkDecorated(); + + } + + + // Log the messages with exceptions + protected void logExceptionMessages() { + + // Generate log records + Throwable t = new DummyException(); + log.trace("trace", t); // Should not actually get logged + log.debug("debug", t); + log.info("info", t); + log.warn("warn", t); + log.error("error", t); + log.fatal("fatal", t); + + // Record the log records we expect + expected.add(new LogRecord(SimpleLog.LOG_LEVEL_DEBUG, "debug", t)); + expected.add(new LogRecord(SimpleLog.LOG_LEVEL_INFO, "info", t)); + expected.add(new LogRecord(SimpleLog.LOG_LEVEL_WARN, "warn", t)); + expected.add(new LogRecord(SimpleLog.LOG_LEVEL_ERROR, "error", t)); + expected.add(new LogRecord(SimpleLog.LOG_LEVEL_FATAL, "fatal", t)); + + } + + + // Log the plain messages + protected void logPlainMessages() { + + // Generate log records + log.trace("trace"); // Should not actually get logged + log.debug("debug"); + log.info("info"); + log.warn("warn"); + log.error("error"); + log.fatal("fatal"); + + // Record the log records we expect + expected.add(new LogRecord(SimpleLog.LOG_LEVEL_DEBUG, "debug", null)); + expected.add(new LogRecord(SimpleLog.LOG_LEVEL_INFO, "info", null)); + expected.add(new LogRecord(SimpleLog.LOG_LEVEL_WARN, "warn", null)); + expected.add(new LogRecord(SimpleLog.LOG_LEVEL_ERROR, "error", null)); + expected.add(new LogRecord(SimpleLog.LOG_LEVEL_FATAL, "fatal", null)); + + } + + +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/simple/DateTimeCustomConfigTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/simple/DateTimeCustomConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/simple/DateTimeCustomConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/simple/DateTimeCustomConfigTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.simple; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import junit.framework.Test; + +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + * Tests custom date time format configuration + */ +public class DateTimeCustomConfigTestCase extends CustomConfigTestCase { + + // ----------------------------------------------------------- Constructors + + /** + * Return the tests included in this test suite. + *

+ * We need to use a PathableClassLoader here because the SimpleLog class + * is a pile of junk and chock-full of static variables. Any other test + * (like simple.CustomConfigTestCase) that has used the SimpleLog class + * will already have caused it to do once-only initialisation that we + * can't reset, even by calling LogFactory.releaseAll, because of those + * ugly statics. The only clean solution is to load a clean copy of + * commons-logging including SimpleLog via a nice clean classloader. + * Or we could fix SimpleLog to be sane... + */ + public static Test suite() throws Exception { + Class thisClass = DateTimeCustomConfigTestCase.class; + + PathableClassLoader loader = new PathableClassLoader(null); + loader.useExplicitLoader("junit.", Test.class.getClassLoader()); + loader.addLogicalLib("testclasses"); + loader.addLogicalLib("commons-logging"); + + Class testClass = loader.loadClass(thisClass.getName()); + return new PathableTestSuite(testClass, loader); + } + + + /** + * Set up system properties required by this unit test. Here, we + * set up the props defined in the parent class setProperties method, + * and add a few to configure the SimpleLog class date/time output. + */ + public void setProperties() { + super.setProperties(); + + System.setProperty( + "org.apache.commons.logging.simplelog.dateTimeFormat", + "dd.mm.yyyy"); + System.setProperty( + "org.apache.commons.logging.simplelog.showdatetime", + "true"); + } + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + super.setUp(); + } + + + // ----------------------------------------------------------- Methods + + /** Checks that the date time format has been successfully set */ + protected void checkDecoratedDateTime() { + assertEquals("Expected date format to be set", "dd.mm.yyyy", + ((DecoratedSimpleLog) log).getDateTimeFormat()); + // try the formatter + Date now = new Date(); + DateFormat formatter = ((DecoratedSimpleLog) log).getDateTimeFormatter(); + SimpleDateFormat sampleFormatter = new SimpleDateFormat("dd.mm.yyyy"); + assertEquals("Date should be formatters to pattern dd.mm.yyyy", + sampleFormatter.format(now), formatter.format(now)); + } + + /** Hook for subclassses */ + protected void checkShowDateTime() { + assertTrue(((DecoratedSimpleLog) log).getShowDateTime()); + } + +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/simple/DecoratedSimpleLog.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/simple/DecoratedSimpleLog.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/simple/DecoratedSimpleLog.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/simple/DecoratedSimpleLog.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.simple; + + +import java.util.ArrayList; +import java.util.List; +import java.text.DateFormat; +import org.apache.commons.logging.impl.SimpleLog; + + +/** + *

Decorated instance of SimpleLog to expose internal state and + * support buffered output.

+ */ + +public class DecoratedSimpleLog extends SimpleLog { + + + // ------------------------------------------------------------ Constructor + + + /** + * Generated serial version ID. + */ + private static final long serialVersionUID = 196544280770017153L; + + public DecoratedSimpleLog(String name) { + super(name); + } + + + // ------------------------------------------------------------- Properties + + public DateFormat getDateTimeFormatter() { + return dateFormatter; + } + + + public String getDateTimeFormat() { + return dateTimeFormat; + } + + + public String getLogName() { + return logName; + } + + + public boolean getShowDateTime() { + return showDateTime; + } + + + public boolean getShowShortName() { + return showShortName; + } + + + // ------------------------------------------------------- Protected Methods + + + // Cache logged messages + protected void log(int type, Object message, Throwable t) { + + super.log(type, message, t); + cache.add(new LogRecord(type, message, t)); + + } + + + // ---------------------------------------------------------- Public Methods + + + // Cache of logged records + protected ArrayList cache = new ArrayList(); + + + // Clear cache + public void clearCache() { + cache.clear(); + } + + + // Return cache + public List getCache() { + return this.cache; + } + + +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/simple/DefaultConfigTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/simple/DefaultConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/simple/DefaultConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/simple/DefaultConfigTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,249 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.simple; + + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.impl.SimpleLog; + + +/** + *

TestCase for simple logging when running with zero configuration + * other than selecting the SimpleLog implementation.

+ * + * @author Craig R. McClanahan + * @version $Revision: 1432587 $ $Date: 2013-01-13 12:11:32 +0100 (Sun, 13 Jan 2013) $ + */ + +public class DefaultConfigTestCase extends TestCase { + + + // ----------------------------------------------------- Instance Variables + + + /** + *

The {@link LogFactory} implementation we have selected.

+ */ + protected LogFactory factory = null; + + + /** + *

The {@link Log} implementation we have selected.

+ */ + protected Log log = null; + + + // ------------------------------------------- JUnit Infrastructure Methods + + + /** + * Return the tests included in this test suite. + *

+ * We need to use a PathableClassLoader here because the SimpleLog class + * is a pile of junk and chock-full of static variables. Any other test + * (like simple.CustomConfigTestCase) that has used the SimpleLog class + * will already have caused it to do once-only initialisation that we + * can't reset, even by calling LogFactory.releaseAll, because of those + * ugly statics. The only clean solution is to load a clean copy of + * commons-logging including SimpleLog via a nice clean classloader. + * Or we could fix SimpleLog to be sane... + */ + public static Test suite() throws Exception { + Class thisClass = DefaultConfigTestCase.class; + + PathableClassLoader loader = new PathableClassLoader(null); + loader.useExplicitLoader("junit.", Test.class.getClassLoader()); + loader.addLogicalLib("testclasses"); + loader.addLogicalLib("commons-logging"); + + Class testClass = loader.loadClass(thisClass.getName()); + return new PathableTestSuite(testClass, loader); + } + + /** + * Set system properties that will control the LogFactory/Log objects + * when they are created. Subclasses can override this method to + * define properties that suit them. + */ + public void setProperties() { + System.setProperty( + "org.apache.commons.logging.Log", + "org.apache.commons.logging.impl.SimpleLog"); + } + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + LogFactory.releaseAll(); + setProperties(); + setUpFactory(); + setUpLog("TestLogger"); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + log = null; + factory = null; + LogFactory.releaseAll(); + } + + + // ----------------------------------------------------------- Test Methods + + + // Test pristine DecoratedSimpleLog instance + public void testPristineDecorated() { + + setUpDecorated("DecoratedLogger"); + checkDecorated(); + + } + + + // Test pristine Log instance + public void testPristineLog() { + + checkStandard(); + + } + + + // Test pristine LogFactory instance + public void testPristineFactory() { + + assertNotNull("LogFactory exists", factory); + assertEquals("LogFactory class", + "org.apache.commons.logging.impl.LogFactoryImpl", + factory.getClass().getName()); + + String names[] = factory.getAttributeNames(); + assertNotNull("Names exists", names); + assertEquals("Names empty", 0, names.length); + + } + + + // Test Serializability of standard instance + public void testSerializable() throws Exception { + + // Serialize and deserialize the instance + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(log); + oos.close(); + ByteArrayInputStream bais = + new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + log = (Log) ois.readObject(); + ois.close(); + + // Check the characteristics of the resulting object + checkStandard(); + + } + + + // -------------------------------------------------------- Support Methods + + + + // Check the decorated log instance + protected void checkDecorated() { + + assertNotNull("Log exists", log); + assertEquals("Log class", + "org.apache.commons.logging.simple.DecoratedSimpleLog", + log.getClass().getName()); + + // Can we call level checkers with no exceptions? + assertTrue(!log.isDebugEnabled()); + assertTrue(log.isErrorEnabled()); + assertTrue(log.isFatalEnabled()); + assertTrue(log.isInfoEnabled()); + assertTrue(!log.isTraceEnabled()); + assertTrue(log.isWarnEnabled()); + + // Can we retrieve the current log level? + assertEquals(SimpleLog.LOG_LEVEL_INFO, ((SimpleLog) log).getLevel()); + + // Can we validate the extra exposed properties? + assertEquals("yyyy/MM/dd HH:mm:ss:SSS zzz", + ((DecoratedSimpleLog) log).getDateTimeFormat()); + assertEquals("DecoratedLogger", + ((DecoratedSimpleLog) log).getLogName()); + assertTrue(!((DecoratedSimpleLog) log).getShowDateTime()); + assertTrue(((DecoratedSimpleLog) log).getShowShortName()); + + } + + + // Check the standard log instance + protected void checkStandard() { + + assertNotNull("Log exists", log); + assertEquals("Log class", + "org.apache.commons.logging.impl.SimpleLog", + log.getClass().getName()); + + // Can we call level checkers with no exceptions? + assertTrue(!log.isDebugEnabled()); + assertTrue(log.isErrorEnabled()); + assertTrue(log.isFatalEnabled()); + assertTrue(log.isInfoEnabled()); + assertTrue(!log.isTraceEnabled()); + assertTrue(log.isWarnEnabled()); + + // Can we retrieve the current log level? + assertEquals(SimpleLog.LOG_LEVEL_INFO, ((SimpleLog) log).getLevel()); + + } + + + // Set up decorated log instance + protected void setUpDecorated(String name) { + log = new DecoratedSimpleLog(name); + } + + + // Set up factory instance + protected void setUpFactory() throws Exception { + factory = LogFactory.getFactory(); + } + + + // Set up log instance + protected void setUpLog(String name) throws Exception { + log = LogFactory.getLog(name); + } + + +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/simple/LogRecord.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/simple/LogRecord.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/simple/LogRecord.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/simple/LogRecord.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.commons.logging.simple; + + +import java.io.Serializable; + + +public class LogRecord implements Serializable { + + + /** + * Generated serial version ID. + */ + private static final long serialVersionUID = -5254831759209770665L; + + public LogRecord(int type, Object message, Throwable t) { + this.type = type; + this.message = message; + this.t = t; + } + + public int type; + public Object message; + public Throwable t; + +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/BadTCCLTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/BadTCCLTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/BadTCCLTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/BadTCCLTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging.tccl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + +import junit.framework.Test; +import junit.framework.TestCase; + +/** + * Simulates the case when TCCL is badly set and cannot load JCL. + */ +public class BadTCCLTestCase extends TestCase { + + public static Test suite() throws Exception { + PathableClassLoader contextClassLoader = new PathableClassLoader(null); + contextClassLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); + PathableTestSuite suite = new PathableTestSuite(BadTCCLTestCase.class, contextClassLoader); + return suite; + } + + // test methods + + /** + * This test just tests that a log implementation can be found + * by the LogFactory. + */ + public void testGetLog() { + Log log = LogFactory.getLog(BadTCCLTestCase.class); + log.debug("Hello, Mum"); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/NullTCCLTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/NullTCCLTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/NullTCCLTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/NullTCCLTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging.tccl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableTestSuite; + +import junit.framework.Test; +import junit.framework.TestCase; + +/** + * Simulates the case when TCCL is set to NULL. + */ +public class NullTCCLTestCase extends TestCase { + + public static Test suite() throws Exception { + PathableTestSuite suite = new PathableTestSuite(NullTCCLTestCase.class, null); + return suite; + } + + // test methods + + /** + * This test just tests that a log implementation can be found + * by the LogFactory. + */ + public void testGetLog() { + Log log = LogFactory.getLog(NullTCCLTestCase.class); + log.debug("Hello, Mum"); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/custom/MyLog.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/custom/MyLog.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/custom/MyLog.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/custom/MyLog.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.logging.tccl.custom; + +import org.apache.commons.logging.Log; + +public class MyLog implements Log { + + public MyLog(String category) {} + + public boolean isDebugEnabled() { return false; } + public boolean isErrorEnabled() { return false; } + public boolean isFatalEnabled() { return false; } + public boolean isInfoEnabled() { return false; } + public boolean isTraceEnabled() { return false; } + public boolean isWarnEnabled() { return false; } + + public void trace(Object message) {} + public void trace(Object message, Throwable t) {} + public void debug(Object message) {} + public void debug(Object message, Throwable t) {} + public void info(Object message) {} + public void info(Object message, Throwable t) {} + public void warn(Object message) {} + public void warn(Object message, Throwable t) {} + public void error(Object message) {} + public void error(Object message, Throwable t) {} + public void fatal(Object message) {} + public void fatal(Object message, Throwable t) {} +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/custom/MyLogFactoryImpl.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/custom/MyLogFactoryImpl.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/custom/MyLogFactoryImpl.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/custom/MyLogFactoryImpl.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.tccl.custom; + + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class MyLogFactoryImpl extends LogFactory { + public Object getAttribute(String name) { return null; } + public String[] getAttributeNames() { return null; } + public Log getInstance(Class clazz) { return null; } + public Log getInstance(String name) { return null; } + public void release() {} + public void removeAttribute(String name) {} + public void setAttribute(String name, Object value) {} +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/log/TcclDisabledTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/log/TcclDisabledTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/log/TcclDisabledTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/log/TcclDisabledTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,160 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.tccl.log; + + +import java.net.URL; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogConfigurationException; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + * Verify that by default LogFactoryImpl is loaded from the tccl classloader. + */ + +public class TcclDisabledTestCase extends TestCase { + + public static final String MY_LOG_PKG = + "org.apache.commons.logging.tccl.custom"; + + public static final String MY_LOG_IMPL = + MY_LOG_PKG + ".MyLog"; + + // ------------------------------------------- JUnit Infrastructure Methods + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + Class thisClass = TcclDisabledTestCase.class; + + // Determine the URL to this .class file, so that we can then + // append the priority dirs to it. For tidiness, load this + // class through a dummy loader though this is not absolutely + // necessary... + PathableClassLoader dummy = new PathableClassLoader(null); + dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); + dummy.addLogicalLib("testclasses"); + dummy.addLogicalLib("commons-logging"); + + String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; + URL baseUrl = dummy.findResource(thisClassPath); + + // Now set up the desired classloader hierarchy. Everything goes into + // the parent classpath, but we exclude the custom Log class. + // + // We then create a tccl classloader that can see the custom + // Log class. Therefore if that class can be found, then the + // TCCL must have been used to load it. + PathableClassLoader emptyLoader = new PathableClassLoader(null); + + PathableClassLoader parentLoader = new PathableClassLoader(null); + parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); + parentLoader.addLogicalLib("commons-logging"); + parentLoader.addLogicalLib("testclasses"); + // hack to ensure that the testcase classloader can't see + // the custom MyLog + parentLoader.useExplicitLoader(MY_LOG_PKG + ".", emptyLoader); + + URL propsEnableUrl = new URL(baseUrl, "props_disable_tccl/"); + parentLoader.addURL(propsEnableUrl); + + PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader); + tcclLoader.addLogicalLib("testclasses"); + + Class testClass = parentLoader.loadClass(thisClass.getName()); + return new PathableTestSuite(testClass, tcclLoader); + } + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + LogFactory.releaseAll(); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + LogFactory.releaseAll(); + } + + // ----------------------------------------------------------- Test Methods + + /** + * Verify that MyLog is only loadable via the tccl. + */ + public void testLoader() throws Exception { + + ClassLoader thisClassLoader = this.getClass().getClassLoader(); + ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader(); + + // the tccl loader should NOT be the same as the loader that loaded this test class. + assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader); + + // MyLog should not be loadable via parent loader + try { + Class clazz = thisClassLoader.loadClass(MY_LOG_IMPL); + fail("Unexpectedly able to load MyLog via test class classloader"); + assertNotNull(clazz); // silence warnings about unused var + } catch(ClassNotFoundException ex) { + // ok, expected + } + + // MyLog should be loadable via tccl loader + try { + Class clazz = tcclLoader.loadClass(MY_LOG_IMPL); + assertNotNull(clazz); + } catch(ClassNotFoundException ex) { + fail("Unexpectedly unable to load MyLog via tccl classloader"); + } + } + + /** + * Verify that the custom Log implementation which is only accessable + * via the TCCL has NOT been loaded. Because this is only accessable via the + * TCCL, and we've use a commons-logging.properties that disables TCCL loading, + * we should see the default Log rather than the custom one. + */ + public void testTcclLoading() throws Exception { + LogFactory instance = LogFactory.getFactory(); + assertEquals( + "Correct LogFactory loaded", + "org.apache.commons.logging.impl.LogFactoryImpl", + instance.getClass().getName()); + + try { + Log log = instance.getInstance("test"); + fail("Unexpectedly succeeded in loading a custom Log class" + + " that is only accessable via the tccl."); + assertNotNull(log); // silence compiler warning about unused var + } catch(LogConfigurationException ex) { + // ok, expected + int index = ex.getMessage().indexOf(MY_LOG_IMPL); + assertTrue("MyLog not found", index >= 0); + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/log/TcclEnabledTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/log/TcclEnabledTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/log/TcclEnabledTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/log/TcclEnabledTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.tccl.log; + + +import java.net.URL; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + * Verify that by default the standard LogFactoryImpl class loads a + * custom Log implementation via the TCCL. + */ + +public class TcclEnabledTestCase extends TestCase { + + public static final String MY_LOG_PKG = + "org.apache.commons.logging.tccl.custom"; + + public static final String MY_LOG_IMPL = + MY_LOG_PKG + ".MyLog"; + + // ------------------------------------------- JUnit Infrastructure Methods + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + Class thisClass = TcclEnabledTestCase.class; + + // Determine the URL to this .class file, so that we can then + // append the priority dirs to it. For tidiness, load this + // class through a dummy loader though this is not absolutely + // necessary... + PathableClassLoader dummy = new PathableClassLoader(null); + dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); + dummy.addLogicalLib("testclasses"); + dummy.addLogicalLib("commons-logging"); + + String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; + URL baseUrl = dummy.findResource(thisClassPath); + + // Now set up the desired classloader hierarchy. Everything goes into + // the parent classpath, but we exclude the custom Log class. + // + // We then create a tccl classloader that can see the custom + // Log class. Therefore if that class can be found, then the + // TCCL must have been used to load it. + PathableClassLoader emptyLoader = new PathableClassLoader(null); + + PathableClassLoader parentLoader = new PathableClassLoader(null); + parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); + parentLoader.addLogicalLib("commons-logging"); + parentLoader.addLogicalLib("testclasses"); + // hack to ensure that the testcase classloader can't see + // the custom MyLogFactoryImpl + parentLoader.useExplicitLoader(MY_LOG_PKG + ".", emptyLoader); + + URL propsEnableUrl = new URL(baseUrl, "props_enable_tccl/"); + parentLoader.addURL(propsEnableUrl); + + PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader); + tcclLoader.addLogicalLib("testclasses"); + + Class testClass = parentLoader.loadClass(thisClass.getName()); + return new PathableTestSuite(testClass, tcclLoader); + } + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + LogFactory.releaseAll(); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + LogFactory.releaseAll(); + } + + // ----------------------------------------------------------- Test Methods + + /** + * Verify that MyLogFactoryImpl is only loadable via the tccl. + */ + public void testLoader() throws Exception { + + ClassLoader thisClassLoader = this.getClass().getClassLoader(); + ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader(); + + // the tccl loader should NOT be the same as the loader that loaded this test class. + assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader); + + // MyLog should not be loadable via parent loader + try { + Class clazz = thisClassLoader.loadClass(MY_LOG_IMPL); + fail("Unexpectedly able to load MyLog via test class classloader"); + assertNotNull(clazz); // silence warnings about unused var + } catch(ClassNotFoundException ex) { + // ok, expected + } + + // MyLog should be loadable via tccl loader + try { + Class clazz = tcclLoader.loadClass(MY_LOG_IMPL); + assertNotNull(clazz); + } catch(ClassNotFoundException ex) { + fail("Unexpectedly unable to load MyLog via tccl classloader"); + } + } + + /** + * Verify that the custom Log implementation which is only accessable + * via the TCCL has successfully been loaded as specified in the config file. + * This proves that the TCCL was used to load that class. + */ + public void testTcclLoading() throws Exception { + LogFactory instance = LogFactory.getFactory(); + + assertEquals( + "Correct LogFactory loaded", + "org.apache.commons.logging.impl.LogFactoryImpl", + instance.getClass().getName()); + + Log log = instance.getInstance("test"); + assertEquals( + "Correct Log loaded", + MY_LOG_IMPL, + log.getClass().getName()); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/logfactory/TcclDisabledTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/logfactory/TcclDisabledTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/logfactory/TcclDisabledTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/logfactory/TcclDisabledTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.tccl.logfactory; + + +import java.net.URL; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + * Verify that a commons-logging.properties file can prevent a custom + * LogFactoryImpl being loaded from the tccl classloader. + */ + +public class TcclDisabledTestCase extends TestCase { + + public static final String MY_LOG_FACTORY_PKG = + "org.apache.commons.logging.tccl.custom"; + + public static final String MY_LOG_FACTORY_IMPL = + MY_LOG_FACTORY_PKG + ".MyLogFactoryImpl"; + + // ------------------------------------------- JUnit Infrastructure Methods + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + Class thisClass = TcclDisabledTestCase.class; + + // Determine the URL to this .class file, so that we can then + // append the priority dirs to it. For tidiness, load this + // class through a dummy loader though this is not absolutely + // necessary... + PathableClassLoader dummy = new PathableClassLoader(null); + dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); + dummy.addLogicalLib("testclasses"); + dummy.addLogicalLib("commons-logging"); + + String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; + URL baseUrl = dummy.findResource(thisClassPath); + + // Now set up the desired classloader hierarchy. Everything goes into + // the parent classpath, but we exclude the custom LogFactoryImpl + // class. + // + // We then create a tccl classloader that can see the custom + // LogFactory class. Therefore if that class can be found, then the + // TCCL must have been used to load it. + PathableClassLoader emptyLoader = new PathableClassLoader(null); + + PathableClassLoader parentLoader = new PathableClassLoader(null); + parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); + parentLoader.addLogicalLib("commons-logging"); + parentLoader.addLogicalLib("testclasses"); + // hack to ensure that the testcase classloader can't see + // the custom MyLogFactoryImpl + parentLoader.useExplicitLoader( + MY_LOG_FACTORY_PKG + ".", emptyLoader); + + URL propsEnableUrl = new URL(baseUrl, "props_disable_tccl/"); + parentLoader.addURL(propsEnableUrl); + + PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader); + tcclLoader.addLogicalLib("testclasses"); + + Class testClass = parentLoader.loadClass(thisClass.getName()); + return new PathableTestSuite(testClass, tcclLoader); + } + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + LogFactory.releaseAll(); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + LogFactory.releaseAll(); + } + + // ----------------------------------------------------------- Test Methods + + /** + * Verify that MyLogFactoryImpl is only loadable via the tccl. + */ + public void testLoader() throws Exception { + + ClassLoader thisClassLoader = this.getClass().getClassLoader(); + ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader(); + + // the tccl loader should NOT be the same as the loader that loaded this test class. + assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader); + + // MyLogFactoryImpl should not be loadable via parent loader + try { + Class clazz = thisClassLoader.loadClass(MY_LOG_FACTORY_IMPL); + fail("Unexpectedly able to load MyLogFactoryImpl via test class classloader"); + assertNotNull(clazz); // silence warning about unused var + } catch(ClassNotFoundException ex) { + // ok, expected + } + + // MyLogFactoryImpl should be loadable via tccl loader + try { + Class clazz = tcclLoader.loadClass(MY_LOG_FACTORY_IMPL); + assertNotNull(clazz); + } catch(ClassNotFoundException ex) { + fail("Unexpectedly unable to load MyLogFactoryImpl via tccl classloader"); + } + } + + /** + * Verify that the custom LogFactory implementation which is only accessable + * via the TCCL has NOT been loaded. Because this is only accessable via the + * TCCL, and we've use a commons-logging.properties that disables TCCL loading, + * we should see the default LogFactoryImpl rather than the custom one. + */ + public void testTcclLoading() throws Exception { + try { + LogFactory instance = LogFactory.getFactory(); + fail("Unexpectedly succeeded in loading custom factory, though TCCL disabled."); + assertNotNull(instance); // silence warning about unused var + } catch(org.apache.commons.logging.LogConfigurationException ex) { + // ok, custom MyLogFactoryImpl as specified in props_disable_tccl + // could not be found. + int index = ex.getMessage().indexOf(MY_LOG_FACTORY_IMPL); + assertTrue("MylogFactoryImpl not found", index >= 0); + } + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/logfactory/TcclEnabledTestCase.java libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/logfactory/TcclEnabledTestCase.java --- libcommons-logging-java-1.1.1/src/test/java/org/apache/commons/logging/tccl/logfactory/TcclEnabledTestCase.java 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/java/org/apache/commons/logging/tccl/logfactory/TcclEnabledTestCase.java 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.tccl.logfactory; + + +import java.net.URL; + +import junit.framework.Test; +import junit.framework.TestCase; + +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableClassLoader; +import org.apache.commons.logging.PathableTestSuite; + + +/** + * Verify that by default a custom LogFactoryImpl is loaded from the + * tccl classloader. + */ + +public class TcclEnabledTestCase extends TestCase { + + // ------------------------------------------- JUnit Infrastructure Methods + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + Class thisClass = TcclEnabledTestCase.class; + + // Determine the URL to this .class file, so that we can then + // append the priority dirs to it. For tidiness, load this + // class through a dummy loader though this is not absolutely + // necessary... + PathableClassLoader dummy = new PathableClassLoader(null); + dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); + dummy.addLogicalLib("testclasses"); + dummy.addLogicalLib("commons-logging"); + + String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; + URL baseUrl = dummy.findResource(thisClassPath); + + // Now set up the desired classloader hierarchy. Everything goes into + // the parent classpath, but we exclude the custom LogFactoryImpl + // class. + // + // We then create a tccl classloader that can see the custom + // LogFactory class. Therefore if that class can be found, then the + // TCCL must have been used to load it. + PathableClassLoader emptyLoader = new PathableClassLoader(null); + + PathableClassLoader parentLoader = new PathableClassLoader(null); + parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); + parentLoader.addLogicalLib("commons-logging"); + parentLoader.addLogicalLib("testclasses"); + // hack to ensure that the testcase classloader can't see + // the cust MyLogFactoryImpl + parentLoader.useExplicitLoader( + "org.apache.commons.logging.tccl.custom.", emptyLoader); + + URL propsEnableUrl = new URL(baseUrl, "props_enable_tccl/"); + parentLoader.addURL(propsEnableUrl); + + PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader); + tcclLoader.addLogicalLib("testclasses"); + + Class testClass = parentLoader.loadClass(thisClass.getName()); + return new PathableTestSuite(testClass, tcclLoader); + } + + /** + * Set up instance variables required by this test case. + */ + public void setUp() throws Exception { + LogFactory.releaseAll(); + } + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + LogFactory.releaseAll(); + } + + // ----------------------------------------------------------- Test Methods + + /** + * Verify that MyLogFactoryImpl is only loadable via the tccl. + */ + public void testLoader() throws Exception { + + ClassLoader thisClassLoader = this.getClass().getClassLoader(); + ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader(); + + // the tccl loader should NOT be the same as the loader that loaded this test class. + assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader); + + // MyLogFactoryImpl should not be loadable via parent loader + try { + Class clazz = thisClassLoader.loadClass( + "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl"); + fail("Unexpectedly able to load MyLogFactoryImpl via test class classloader"); + assertNotNull(clazz); // silence warning about unused var + } catch(ClassNotFoundException ex) { + // ok, expected + } + + // MyLogFactoryImpl should be loadable via tccl loader + try { + Class clazz = tcclLoader.loadClass( + "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl"); + assertNotNull(clazz); + } catch(ClassNotFoundException ex) { + fail("Unexpectedly unable to load MyLogFactoryImpl via tccl classloader"); + } + } + + /** + * Verify that the custom LogFactory implementation which is only accessable + * via the TCCL has successfully been loaded as specified in the config file. + * This proves that the TCCL was used to load that class. + */ + public void testTcclLoading() throws Exception { + LogFactory instance = LogFactory.getFactory(); + + assertEquals( + "Correct LogFactory loaded", + "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl", + instance.getClass().getName()); + } +} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/AbstractLogTest.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/AbstractLogTest.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/AbstractLogTest.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/AbstractLogTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging; - -import junit.framework.TestCase; - - -/** - * Generic tests that can be applied to any log adapter by - * subclassing this class and defining method getLogObject - * appropriately. - * - * @author Sean C. Sullivan - * @version $Revision: 581090 $ - */ -public abstract class AbstractLogTest extends TestCase { - - public abstract Log getLogObject(); - - public void testLoggingWithNullParameters() - { - Log log = this.getLogObject(); - - assertNotNull(log); - - - log.debug(null); - - log.debug(null, null); - - log.debug(log.getClass().getName() + ": debug statement"); - - log.debug(log.getClass().getName() + ": debug statement w/ null exception", new RuntimeException()); - - - log.error(null); - - log.error(null, null); - - log.error(log.getClass().getName() + ": error statement"); - - log.error(log.getClass().getName() + ": error statement w/ null exception", new RuntimeException()); - - - log.fatal(null); - - log.fatal(null, null); - - log.fatal(log.getClass().getName() + ": fatal statement"); - - log.fatal(log.getClass().getName() + ": fatal statement w/ null exception", new RuntimeException()); - - - log.info(null); - - log.info(null, null); - - log.info(log.getClass().getName() + ": info statement"); - - log.info(log.getClass().getName() + ": info statement w/ null exception", new RuntimeException()); - - - log.trace(null); - - log.trace(null, null); - - log.trace(log.getClass().getName() + ": trace statement"); - - log.trace(log.getClass().getName() + ": trace statement w/ null exception", new RuntimeException()); - - - log.warn(null); - - log.warn(null, null); - - log.warn(log.getClass().getName() + ": warn statement"); - - log.warn(log.getClass().getName() + ": warn statement w/ null exception", new RuntimeException()); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/AltHashtable.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/AltHashtable.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/AltHashtable.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/AltHashtable.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - -import java.util.Hashtable; - -public class AltHashtable extends Hashtable { - - public static Object lastKey; - public static Object lastValue; - - public Object put(Object key, Object value) { - lastKey = key; - lastValue = value; - return super.put(key, value); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/AltHashtableTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/AltHashtableTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/AltHashtableTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/AltHashtableTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - -import junit.framework.*; - -/** - * Test the ability to force the LogFactory class to use some - * arbitrary Hashtable implementation to store its mapping from - * context-classloader -> LogFactory object. - *

- * This is done by - */ -public class AltHashtableTestCase extends TestCase { - - public static Test suite() throws Exception { - Class thisClass = AltHashtableTestCase.class; - ClassLoader thisClassLoader = thisClass.getClassLoader(); - - PathableClassLoader loader = new PathableClassLoader(null); - loader.useExplicitLoader("junit.", thisClassLoader); - loader.addLogicalLib("testclasses"); - loader.addLogicalLib("commons-logging"); - - Class testClass = loader.loadClass(thisClass.getName()); - return new PathableTestSuite(testClass, loader); - } - - /** - * Set up before each test. - *

- * This method ensures that the appropriate system property is defined - * to force the LogFactory class to use the AltHashtable class as its - * Hashtable implementation for storing factories in. - *

- * This does make the assumption that whatever JVM we are running in - * doesn't initialise classes until they are actually referenced (ie the - * LogFactory class hasn't been initialised before this method is called). - * This is true of all JVMs I know of; and if it isn't then this test will - * fail and someone will tell us. - */ - public void setUp() { - System.setProperty( - "org.apache.commons.logging.LogFactory.HashtableImpl", - AltHashtable.class.getName()); - } - - /** - * Verify that initialising the LogFactory class will cause it - * to instantiate an object of type specified in system property - * "org.apache.commons.logging.LogFactory.HashtableImpl". - */ - public void testType() { - // Here, the reference to the LogFactory class should cause the - // class to be loaded and initialised. It will see the property - // set and use the AltHashtable class. If other tests in this - // class have already been run within the same classloader then - // LogFactory will already have been initialised, but that - // doesn't change the effectiveness of this test. - assertTrue(LogFactory.factories instanceof AltHashtable); - } - - /** - * Verify that when LogFactory sees a context-classloader for the - * first time that it creates a new entry in the LogFactory.factories - * hashmap. In particular, this checks that this process works ok when - * a system property has been used to specify an alternative Hashtable - * implementation for LogFactory to use. - */ - public void testPutCalled() throws Exception { - AltHashtable.lastKey = null; - AltHashtable.lastValue = null; - - LogFactory.getLog(AltHashtableTestCase.class); - ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - assertEquals(contextLoader, AltHashtable.lastKey); - assertNotNull(AltHashtable.lastValue); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/BadHashtablePropertyTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/BadHashtablePropertyTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/BadHashtablePropertyTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/BadHashtablePropertyTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - -import junit.framework.*; -import java.util.Hashtable; - -/** - * Tests behaviour when the property is misconfigured. - */ -public class BadHashtablePropertyTestCase extends TestCase { - - public void testType() { - assertTrue(LogFactory.factories instanceof Hashtable); - } - - public void testPutCalled() throws Exception { - Log log = LogFactory.getLog(BadHashtablePropertyTestCase.class); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/BasicOperationsTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/BasicOperationsTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/BasicOperationsTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/BasicOperationsTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,121 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - -import junit.framework.TestCase; - -/** - * Tests the basic logging operations to ensure that they all function - * without exception failure. In other words, that they do no fail by - * throwing exceptions. - * This is the minimum requirement for any well behaved logger - * and so this test should be run for each kind. - */ -public class BasicOperationsTestCase extends TestCase -{ - public void testIsEnabledClassLog() - { - Log log = LogFactory.getLog(BasicOperationsTestCase.class); - executeIsEnabledTest(log); - } - - public void testIsEnabledNamedLog() - { - Log log = LogFactory.getLog(BasicOperationsTestCase.class.getName()); - executeIsEnabledTest(log); - } - - public void executeIsEnabledTest(Log log) - { - try - { - log.isTraceEnabled(); - log.isDebugEnabled(); - log.isInfoEnabled(); - log.isWarnEnabled(); - log.isErrorEnabled(); - log.isFatalEnabled(); - } - catch (Throwable t) - { - t.printStackTrace(); - fail("Exception thrown: " + t); - } - } - - - public void testMessageWithoutExceptionClassLog() - { - Log log = LogFactory.getLog(BasicOperationsTestCase.class); - executeMessageWithoutExceptionTest(log); - } - - public void testMessageWithoutExceptionNamedLog() - { - Log log = LogFactory.getLog(BasicOperationsTestCase.class.getName()); - executeMessageWithoutExceptionTest(log); - } - - public void executeMessageWithoutExceptionTest(Log log) - { - try - { - log.trace("Hello, Mum"); - log.debug("Hello, Mum"); - log.info("Hello, Mum"); - log.warn("Hello, Mum"); - log.error("Hello, Mum"); - log.fatal("Hello, Mum"); - } - catch (Throwable t) - { - t.printStackTrace(); - fail("Exception thrown: " + t); - } - } - - public void testMessageWithExceptionClassLog() - { - Log log = LogFactory.getLog(BasicOperationsTestCase.class); - executeMessageWithExceptionTest(log); - } - - public void testMessageWithExceptionNamedLog() - { - Log log = LogFactory.getLog(BasicOperationsTestCase.class.getName()); - executeMessageWithExceptionTest(log); - } - - public void executeMessageWithExceptionTest(Log log) - { - try - { - log.trace("Hello, Mum", new ArithmeticException()); - log.debug("Hello, Mum", new ArithmeticException()); - log.info("Hello, Mum", new ArithmeticException()); - log.warn("Hello, Mum", new ArithmeticException()); - log.error("Hello, Mum", new ArithmeticException()); - log.fatal("Hello, Mum", new ArithmeticException()); - } - catch (Throwable t) - { - t.printStackTrace(); - fail("Exception thrown: " + t); - } - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/DummyException.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/DummyException.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/DummyException.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/DummyException.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - -/** - * Dummy exception that unit tests create instances of when they want to test - * logging of an Exception object. - */ -public class DummyException extends Exception { - private static final long serialVersionUID = 1L; - public DummyException() { - // super("Dummy Exception for unit testing"); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/LoadTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/LoadTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/LoadTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/LoadTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,231 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.logging; - -import junit.framework.TestCase; - -/** - * testcase to emulate container and application isolated from container - * @author baliuka - * @version $Id: LoadTestCase.java 424108 2006-07-20 23:19:55Z skitching $ - */ -public class LoadTestCase extends TestCase{ - //TODO: need some way to add service provider packages - static private String LOG_PCKG[] = {"org.apache.commons.logging", - "org.apache.commons.logging.impl"}; - - /** - * A custom classloader which "duplicates" logging classes available - * in the parent classloader into itself. - *

- * When asked to load a class that is in one of the LOG_PCKG packages, - * it loads the class itself (child-first). This class doesn't need - * to be set up with a classpath, as it simply uses the same classpath - * as the classloader that loaded it. - */ - static class AppClassLoader extends ClassLoader{ - - java.util.Map classes = new java.util.HashMap(); - - AppClassLoader(ClassLoader parent){ - super(parent); - } - - private Class def(String name)throws ClassNotFoundException{ - - Class result = (Class)classes.get(name); - if(result != null){ - return result; - } - - try{ - - ClassLoader cl = this.getClass().getClassLoader(); - String classFileName = name.replace('.','/') + ".class"; - java.io.InputStream is = cl.getResourceAsStream(classFileName); - java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream(); - - while(is.available() > 0){ - out.write(is.read()); - } - - byte data [] = out.toByteArray(); - - result = super.defineClass(name, data, 0, data.length ); - classes.put(name,result); - - return result; - - }catch(java.io.IOException ioe){ - - throw new ClassNotFoundException( name + " caused by " - + ioe.getMessage() ); - } - - - } - - // not very trivial to emulate we must implement "findClass", - // but it will delegete to junit class loder first - public Class loadClass(String name)throws ClassNotFoundException{ - - //isolates all logging classes, application in the same classloader too. - //filters exeptions to simlify handling in test - for(int i = 0; i < LOG_PCKG.length; i++ ){ - if( name.startsWith( LOG_PCKG[i] ) && - name.indexOf("Exception") == -1 ){ - return def(name); - } - } - return super.loadClass(name); - } - - } - - - /** - * Call the static setAllowFlawedContext method on the specified class - * (expected to be a UserClass loaded via a custom classloader), passing - * it the specified state parameter. - */ - private void setAllowFlawedContext(Class c, String state) throws Exception { - Class[] params = {String.class}; - java.lang.reflect.Method m = c.getDeclaredMethod("setAllowFlawedContext", params); - m.invoke(null, new Object[] {state}); - } - - /** - * Test what happens when we play various classloader tricks like those - * that happen in web and j2ee containers. - *

- * Note that this test assumes that commons-logging.jar and log4j.jar - * are available via the system classpath. - */ - public void testInContainer()throws Exception{ - - //problem can be in this step (broken app container or missconfiguration) - //1. Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); - //2. Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); - // we expect this : - // 1. Thread.currentThread().setContextClassLoader(appLoader); - // 2. Thread.currentThread().setContextClassLoader(null); - - // Context classloader is same as class calling into log - Class cls = reload(); - Thread.currentThread().setContextClassLoader(cls.getClassLoader()); - execute(cls); - - // Context classloader is the "bootclassloader". This is technically - // bad, but LogFactoryImpl.ALLOW_FLAWED_CONTEXT defaults to true so - // this test should pass. - cls = reload(); - Thread.currentThread().setContextClassLoader(null); - execute(cls); - - // Context classloader is the "bootclassloader". This is same as above - // except that ALLOW_FLAWED_CONTEXT is set to false; an error should - // now be reported. - cls = reload(); - Thread.currentThread().setContextClassLoader(null); - try { - setAllowFlawedContext(cls, "false"); - execute(cls); - fail("Logging config succeeded when context classloader was null!"); - } catch(LogConfigurationException ex) { - // expected; the boot classloader doesn't *have* JCL available - } - - // Context classloader is the system classloader. - // - // This is expected to cause problems, as LogFactoryImpl will attempt - // to use the system classloader to load the Log4JLogger class, which - // will then be unable to cast that object to the Log interface loaded - // via the child classloader. However as ALLOW_FLAWED_CONTEXT defaults - // to true this test should pass. - cls = reload(); - Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); - execute(cls); - - // Context classloader is the system classloader. This is the same - // as above except that ALLOW_FLAWED_CONTEXT is set to false; an error - // should now be reported. - cls = reload(); - Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); - try { - setAllowFlawedContext(cls, "false"); - execute(cls); - fail("Error: somehow downcast a Logger loaded via system classloader" - + " to the Log interface loaded via a custom classloader"); - } catch(LogConfigurationException ex) { - // expected - } - } - - /** - * Load class UserClass via a temporary classloader which is a child of - * the classloader used to load this test class. - */ - private Class reload()throws Exception{ - - Class testObjCls = null; - - AppClassLoader appLoader = new AppClassLoader( - this.getClass().getClassLoader()); - try{ - - testObjCls = appLoader.loadClass(UserClass.class.getName()); - - }catch(ClassNotFoundException cnfe){ - throw cnfe; - }catch(Throwable t){ - t.printStackTrace(); - fail("AppClassLoader failed "); - } - - assertTrue( "app isolated" ,testObjCls.getClassLoader() == appLoader ); - - - return testObjCls; - - - } - - - private void execute(Class cls)throws Exception{ - - cls.newInstance(); - - } - - - public static void main(String[] args){ - String[] testCaseName = { LoadTestCase.class.getName() }; - junit.textui.TestRunner.main(testCaseName); - } - - public void setUp() { - // save state before test starts so we can restore it when test ends - origContextClassLoader = Thread.currentThread().getContextClassLoader(); - } - - public void tearDown() { - // restore original state so a test can't stuff up later tests. - Thread.currentThread().setContextClassLoader(origContextClassLoader); - } - - private ClassLoader origContextClassLoader; -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/LogTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/LogTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/LogTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/LogTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - - -/** - * - * - * - * - * - * - */ -public class LogTestCase extends AbstractLogTest -{ - - /** - * - * - * - */ - public Log getLogObject() - { - /** - * Pickup whatever is found/configured! - */ - return LogFactory.getLog(this.getClass().getName()); - } - - public static void main(String[] args) - { - String[] testCaseName = { LogTestCase.class.getName() }; - junit.textui.TestRunner.main(testCaseName); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/NullClassLoaderTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/NullClassLoaderTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/NullClassLoaderTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/NullClassLoaderTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.logging; - -import junit.framework.TestCase; - -/** - * Test cases for situations where getClassLoader or getContextClassLoader - * return null. This can happen when using JDK 1.1. It can also happen when - * JCL is deployed via the bootclassloader - something that could be done when - * using java in embedded systems. - */ -public class NullClassLoaderTestCase extends TestCase { - - //---------------------- Main --------------------------------- - - /** - * Main method so this test case can be run direct from the command line. - */ - public static void main(String[] args){ - String[] testCaseName = { NullClassLoaderTestCase.class.getName() }; - junit.textui.TestRunner.main(testCaseName); - } - - //---------------------- unit tests --------------------------------- - - /** - * This tests that when getContextClassLoader returns null, the - * LogFactory.getLog(name) method still correctly returns the same - * log object when called multiple times with the same name. - */ - public void testSameLogObject() throws Exception { - // unfortunately, there just isn't any way to emulate JCL being - // accessable via the null classloader in "standard" systems, so - // we can't include this test in our standard unit tests. - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/PathableClassLoader.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/PathableClassLoader.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/PathableClassLoader.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/PathableClassLoader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,437 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -/** - * A ClassLoader which sees only specified classes, and which can be - * set to do parent-first or child-first path lookup. - *

- * Note that this classloader is not "industrial strength"; users - * looking for such a class may wish to look at the Tomcat sourcecode - * instead. In particular, this class may not be threadsafe. - *

- * Note that the ClassLoader.getResources method isn't overloaded here. - * It would be nice to ensure that when child-first lookup is set the - * resources from the child are returned earlier in the list than the - * resources from the parent. However overriding this method isn't possible - * as the java 1.4 version of ClassLoader declares this method final - * (though the java 1.5 version has removed the final qualifier). As the - * ClassLoader javadoc doesn't specify the order in which resources - * are returned, it's valid to return the resources in any order (just - * untidy) so the inherited implementation is technically ok. - */ - -public class PathableClassLoader extends URLClassLoader { - - private static final URL[] NO_URLS = new URL[0]; - - /** - * A map of package-prefix to ClassLoader. Any class which is in - * this map is looked up via the specified classloader instead of - * the classpath associated with this classloader or its parents. - *

- * This is necessary in order for the rest of the world to communicate - * with classes loaded via a custom classloader. As an example, junit - * testcases which are loaded via a custom classloader needs to see - * the same junit classes as the code invoking the testcase, otherwise - * they can't pass result objects back. - *

- * Normally, only a classloader created with a null parent needs to - * have any lookasides defined. - */ - private HashMap lookasides = null; - - /** - * See setParentFirst. - */ - private boolean parentFirst = true; - - /** - * Constructor. - *

- * Often, null is passed as the parent, ie the parent of the new - * instance is the bootloader. This ensures that the classpath is - * totally clean; nothing but the standard java library will be - * present. - *

- * When using a null parent classloader with a junit testcase, it *is* - * necessary for the junit library to also be visible. In this case, it - * is recommended that the following code be used: - *

-     * pathableLoader.useExplicitLoader(
-     *   "junit.",
-     *   junit.framework.Test.class.getClassLoader());
-     * 
- * Note that this works regardless of whether junit is on the system - * classpath, or whether it has been loaded by some test framework that - * creates its own classloader to run unit tests in (eg maven2's - * Surefire plugin). - */ - public PathableClassLoader(ClassLoader parent) { - super(NO_URLS, parent); - } - - /** - * Allow caller to explicitly add paths. Generally this not a good idea; - * use addLogicalLib instead, then define the location for that logical - * library in the build.xml file. - */ - public void addURL(URL url) { - super.addURL(url); - } - - /** - * Specify whether this classloader should ask the parent classloader - * to resolve a class first, before trying to resolve it via its own - * classpath. - *

- * Checking with the parent first is the normal approach for java, but - * components within containers such as servlet engines can use - * child-first lookup instead, to allow the components to override libs - * which are visible in shared classloaders provided by the container. - *

- * Note that the method getResources always behaves as if parentFirst=true, - * because of limitations in java 1.4; see the javadoc for method - * getResourcesInOrder for details. - *

- * This value defaults to true. - */ - public void setParentFirst(boolean state) { - parentFirst = state; - } - - /** - * For classes with the specified prefix, get them from the system - * classpath which is active at the point this method is called. - *

- * This method is just a shortcut for - *

-     * useExplicitLoader(prefix, ClassLoader.getSystemClassLoader());
-     * 
- *

- * Of course, this assumes that the classes of interest are already - * in the classpath of the system classloader. - */ - public void useSystemLoader(String prefix) { - useExplicitLoader(prefix, ClassLoader.getSystemClassLoader()); - - } - - /** - * Specify a classloader to use for specific java packages. - *

- * The specified classloader is normally a loader that is NOT - * an ancestor of this classloader. In particular, this loader - * may have the bootloader as its parent, but be configured to - * see specific other classes (eg the junit library loaded - * via the system classloader). - *

- * The differences between using this method, and using - * addLogicalLib are: - *

    - *
  • If code calls getClassLoader on a class loaded via - * "lookaside", then traces up its inheritance chain, it - * will see the "real" classloaders. When the class is remapped - * into this classloader via addLogicalLib, the classloader - * chain seen is this object plus ancestors. - *
  • If two different jars contain classes in the same - * package, then it is not possible to load both jars into - * the same "lookaside" classloader (eg the system classloader) - * then map one of those subsets from here. Of course they could - * be loaded into two different "lookaside" classloaders and - * then a prefix used to map from here to one of those classloaders. - *
- */ - public void useExplicitLoader(String prefix, ClassLoader loader) { - if (lookasides == null) { - lookasides = new HashMap(); - } - lookasides.put(prefix, loader); - } - - /** - * Specify a collection of logical libraries. See addLogicalLib. - */ - public void addLogicalLib(String[] logicalLibs) { - for(int i=0; i - * The specified lib name is used as a key into the system properties; - * there is expected to be a system property defined with that name - * whose value is a url that indicates where that logical library can - * be found. Typically this is the name of a jar file, or a directory - * containing class files. - *

- * If there is no system property, but the classloader that loaded - * this class is a URLClassLoader then the set of URLs that the - * classloader uses for its classpath is scanned; any jar in the - * URL set whose name starts with the specified string is added to - * the classpath managed by this instance. - *

- * Using logical library names allows the calling code to specify its - * desired classpath without knowing the exact location of the necessary - * classes. - */ - public void addLogicalLib(String logicalLib) { - // first, check the system properties - String filename = System.getProperty(logicalLib); - if (filename != null) { - try { - URL libUrl = new File(filename).toURL(); - addURL(libUrl); - return; - } catch(java.net.MalformedURLException e) { - throw new UnknownError( - "Invalid file [" + filename + "] for logical lib [" + logicalLib + "]"); - } - } - - // now check the classpath for a similar-named lib - URL libUrl = libFromClasspath(logicalLib); - if (libUrl != null) { - addURL(libUrl); - return; - } - - // lib not found - throw new UnknownError( - "Logical lib [" + logicalLib + "] is not defined" - + " as a System property."); - } - - /** - * If the classloader that loaded this class has this logical lib in its - * path, then return the matching URL otherwise return null. - *

- * This only works when the classloader loading this class is an instance - * of URLClassLoader and thus has a getURLs method that returns the classpath - * it uses when loading classes. However in practice, the vast majority of the - * time this type is the classloader used. - *

- * The classpath of the classloader for this instance is scanned, and any - * jarfile in the path whose name starts with the logicalLib string is - * considered a match. For example, passing "foo" will match a url - * of file:///some/where/foo-2.7.jar. - *

- * When multiple classpath entries match the specified logicalLib string, - * the one with the shortest filename component is returned. This means that - * if "foo-1.1.jar" and "foobar-1.1.jar" are in the path, then a logicalLib - * name of "foo" will match the first entry above. - */ - private URL libFromClasspath(String logicalLib) { - ClassLoader cl = this.getClass().getClassLoader(); - if (cl instanceof URLClassLoader == false) { - return null; - } - - URLClassLoader ucl = (URLClassLoader) cl; - URL[] path = ucl.getURLs(); - URL shortestMatch = null; - int shortestMatchLen = Integer.MAX_VALUE; - for(int i=0; i= 0) { - filename = filename.substring(lastSlash+1); - } - - if (filename.startsWith(logicalLib)) { - // ok, this is a candidate - if (filename.length() < shortestMatchLen) { - shortestMatch = u; - shortestMatchLen = filename.length(); - } - } - } - - return shortestMatch; - } - - /** - * Override ClassLoader method. - *

- * For each explicitly mapped package prefix, if the name matches the - * prefix associated with that entry then attempt to load the class via - * that entries' classloader. - */ - protected Class loadClass(String name, boolean resolve) - throws ClassNotFoundException { - // just for performance, check java and javax - if (name.startsWith("java.") || name.startsWith("javax.")) { - return super.loadClass(name, resolve); - } - - if (lookasides != null) { - for(Iterator i = lookasides.entrySet().iterator(); i.hasNext(); ) { - Map.Entry entry = (Map.Entry) i.next(); - String prefix = (String) entry.getKey(); - if (name.startsWith(prefix) == true) { - ClassLoader loader = (ClassLoader) entry.getValue(); - Class clazz = Class.forName(name, resolve, loader); - return clazz; - } - } - } - - if (parentFirst) { - return super.loadClass(name, resolve); - } else { - // Implement child-first. - // - // It appears that the findClass method doesn't check whether the - // class has already been loaded. This seems odd to me, but without - // first checking via findLoadedClass we can get java.lang.LinkageError - // with message "duplicate class definition" which isn't good. - - try { - Class clazz = findLoadedClass(name); - if (clazz == null) { - clazz = super.findClass(name); - } - if (resolve) { - resolveClass(clazz); - } - return clazz; - } catch(ClassNotFoundException e) { - return super.loadClass(name, resolve); - } - } - } - - /** - * Same as parent class method except that when parentFirst is false - * the resource is looked for in the local classpath before the parent - * loader is consulted. - */ - public URL getResource(String name) { - if (parentFirst) { - return super.getResource(name); - } else { - URL local = super.findResource(name); - if (local != null) { - return local; - } - return super.getResource(name); - } - } - - /** - * Emulate a proper implementation of getResources which respects the - * setting for parentFirst. - *

- * Note that it's not possible to override the inherited getResources, as - * it's declared final in java1.4 (thought that's been removed for 1.5). - * The inherited implementation always behaves as if parentFirst=true. - */ - public Enumeration getResourcesInOrder(String name) throws IOException { - if (parentFirst) { - return super.getResources(name); - } else { - Enumeration localUrls = super.findResources(name); - - ClassLoader parent = getParent(); - if (parent == null) { - // Alas, there is no method to get matching resources - // from a null (BOOT) parent classloader. Calling - // ClassLoader.getSystemClassLoader isn't right. Maybe - // calling Class.class.getResources(name) would do? - // - // However for the purposes of unit tests, we can - // simply assume that no relevant resources are - // loadable from the parent; unit tests will never be - // putting any of their resources in a "boot" classloader - // path! - return localUrls; - } - Enumeration parentUrls = parent.getResources(name); - - ArrayList localItems = toList(localUrls); - ArrayList parentItems = toList(parentUrls); - localItems.addAll(parentItems); - return Collections.enumeration(localItems); - } - } - - /** - * - * Clean implementation of list function of - * {@link java.utils.Collection} added in JDK 1.4 - * @param en Enumeration, possibly null - * @return ArrayList containing the enumerated - * elements in the enumerated order, not null - */ - private ArrayList toList(Enumeration en) { - ArrayList results = new ArrayList(); - if (en != null) { - while (en.hasMoreElements()){ - Object element = en.nextElement(); - results.add(element); - } - } - return results; - } - - /** - * Same as parent class method except that when parentFirst is false - * the resource is looked for in the local classpath before the parent - * loader is consulted. - */ - public InputStream getResourceAsStream(String name) { - if (parentFirst) { - return super.getResourceAsStream(name); - } else { - URL local = super.findResource(name); - if (local != null) { - try { - return local.openStream(); - } catch(IOException e) { - // TODO: check if this is right or whether we should - // fall back to trying parent. The javadoc doesn't say... - return null; - } - } - return super.getResourceAsStream(name); - } - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/PathableTestSuite.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/PathableTestSuite.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/PathableTestSuite.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/PathableTestSuite.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,148 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - -import java.util.Properties; - -import junit.framework.Test; -import junit.framework.TestResult; -import junit.framework.TestSuite; - -/** - * Custom TestSuite class that can be used to control the context classloader - * in operation when a test runs. - *

- * For tests that need to control exactly what the classloader hierarchy is - * like when the test is run, something like the following is recommended: - *

- * class SomeTestCase extends TestCase {
- *  public static Test suite() throws Exception {
- *   PathableClassLoader parent = new PathableClassLoader(null);
- *   parent.useSystemLoader("junit.");
- * 
- *   PathableClassLoader child = new PathableClassLoader(parent);
- *   child.addLogicalLib("testclasses");
- *   child.addLogicalLib("log4j12");
- *   child.addLogicalLib("commons-logging");
- * 
- *   Class testClass = child.loadClass(SomeTestCase.class.getName());
- *   ClassLoader contextClassLoader = child;
- * 
- *   PathableTestSuite suite = new PathableTestSuite(testClass, child);
- *   return suite;
- *  }
- * 
- *  // test methods go here
- * }
- * 
- * Note that if the suite method throws an exception then this will be handled - * reasonable gracefully by junit; it will report that the suite method for - * a test case failed with exception yyy. - *

- * The use of PathableClassLoader is not required to use this class, but it - * is expected that using the two classes together is common practice. - *

- * This class will run each test methods within the specified TestCase using - * the specified context classloader and system classloader. If different - * tests within the same class require different context classloaders, - * then the context classloader passed to the constructor should be the - * "lowest" one available, and tests that need the context set to some parent - * of this "lowest" classloader can call - *

- *  // NB: pseudo-code only
- *  setContextClassLoader(getContextClassLoader().getParent());
- * 
- * This class ensures that any context classloader changes applied by a test - * is undone after the test is run, so tests don't need to worry about - * restoring the context classloader on exit. This class also ensures that - * the system properties are restored to their original settings after each - * test, so tests that manipulate those don't need to worry about resetting them. - *

- * This class does not provide facilities for manipulating system properties; - * tests that need specific system properties can simply set them in the - * fixture or at the start of a test method. - *

- * Important! When the test case is run, "this.getClass()" refers of - * course to the Class object passed to the constructor of this class - which - * is different from the class whose suite() method was executed to determine - * the classpath. This means that the suite method cannot communicate with - * the test cases simply by setting static variables (for example to make the - * custom classloaders available to the test methods or setUp/tearDown fixtures). - * If this is really necessary then it is possible to use reflection to invoke - * static methods on the class object passed to the constructor of this class. - *

- *

Limitations

- *

- * This class cannot control the system classloader (ie what method - * ClassLoader.getSystemClassLoader returns) because Java provides no - * mechanism for setting the system classloader. In this case, the only - * option is to invoke the unit test in a separate JVM with the appropriate - * settings. - *

- * The effect of using this approach in a system that uses junit's - * "reloading classloader" behaviour is unknown. This junit feature is - * intended for junit GUI apps where a test may be run multiple times - * within the same JVM - and in particular, when the .class file may - * be modified between runs of the test. How junit achieves this is - * actually rather weird (the whole junit code is rather weird in fact) - * and it is not clear whether this approach will work as expected in - * such situations. - */ -public class PathableTestSuite extends TestSuite { - - /** - * The classloader that should be set as the context classloader - * before each test in the suite is run. - */ - private ClassLoader contextLoader; - - /** - * Constructor. - * - * @param testClass is the TestCase that is to be run, as loaded by - * the appropriate ClassLoader. - * - * @param contextClassLoader is the loader that should be returned by - * calls to Thread.currentThread.getContextClassLoader from test methods - * (or any method called by test methods). - */ - public PathableTestSuite(Class testClass, ClassLoader contextClassLoader) { - super(testClass); - contextLoader = contextClassLoader; - } - - /** - * This method is invoked once for each Test in the current TestSuite. - * Note that a Test may itself be a TestSuite object (ie a collection - * of tests). - *

- * The context classloader and system properties are saved before each - * test, and restored after the test completes to better isolate tests. - */ - public void runTest(Test test, TestResult result) { - ClassLoader origContext = Thread.currentThread().getContextClassLoader(); - Properties oldSysProps = (Properties) System.getProperties().clone(); - try { - Thread.currentThread().setContextClassLoader(contextLoader); - test.run(result); - } finally { - System.setProperties(oldSysProps); - Thread.currentThread().setContextClassLoader(origContext); - } - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/SimpleLogTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/SimpleLogTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/SimpleLogTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/SimpleLogTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - -import org.apache.commons.logging.impl.SimpleLog; - -/** - * - * - * - * - * - * - */ -public class SimpleLogTestCase extends AbstractLogTest -{ - /** - * - * - * - */ - public Log getLogObject() - { - return (Log) new SimpleLog(this.getClass().getName()); - } - - public static void main(String[] args) { - String[] testCaseName = { SimpleLogTestCase.class.getName() }; - junit.textui.TestRunner.main(testCaseName); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/UserClass.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/UserClass.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/UserClass.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/UserClass.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.impl.LogFactoryImpl; - -public class UserClass { - - - /** - * Set the ALLOW_FLAWED_CONTEXT feature on the LogFactoryImpl object - * associated with this class' classloader. - *

- * Don't forget to set the context classloader to whatever it will be - * when an instance of this class is actually created before calling - * this method! - */ - public static void setAllowFlawedContext(String state) { - LogFactory f = LogFactory.getFactory(); - f.setAttribute(LogFactoryImpl.ALLOW_FLAWED_CONTEXT_PROPERTY, state); - } - - public UserClass() { - Log log = LogFactory.getLog(LoadTestCase.class); - } - -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/avalon/AvalonLoggerTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/avalon/AvalonLoggerTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/avalon/AvalonLoggerTestCase.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/avalon/AvalonLoggerTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.logging.avalon; - -import org.apache.avalon.framework.logger.ConsoleLogger; -import org.apache.commons.logging.impl.AvalonLogger; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.AbstractLogTest; - -import junit.framework.Test; -import junit.framework.TestSuite; - -/** - * @author Neeme Praks - * @version $Revision: 581090 $ $Date: 2007-10-02 00:01:06 +0200 (ti, 02 okt 2007) $ - */ -public class AvalonLoggerTestCase extends AbstractLogTest { - - public static void main(String[] args) { - String[] testCaseName = { AvalonLoggerTestCase.class.getName() }; - junit.textui.TestRunner.main(testCaseName); - } - - public static Test suite() { - TestSuite suite = new TestSuite(); - suite.addTestSuite(AvalonLoggerTestCase.class); - return suite; - } - - public Log getLogObject() { - Log log = new AvalonLogger(new ConsoleLogger()); - return log; - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/FirstPriorityConfigTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/FirstPriorityConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/FirstPriorityConfigTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/FirstPriorityConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,125 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.config; - - -import java.net.URL; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - * Tests that verify that the process of configuring logging on startup - * works correctly by selecting the file with the highest priority. - *

- * This test sets up a classpath where: - *

    - *
  • first file found has priority=20 - *
  • second file found has priority=10 - *
- * The result should be that the first file is used. - */ -public class FirstPriorityConfigTestCase extends TestCase { - - // ------------------------------------------- JUnit Infrastructure Methods - - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - Class thisClass = FirstPriorityConfigTestCase.class; - - // Determine the URL to this .class file, so that we can then - // append the priority dirs to it. For tidiness, load this - // class through a dummy loader though this is not absolutely - // necessary... - PathableClassLoader dummy = new PathableClassLoader(null); - dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); - dummy.addLogicalLib("testclasses"); - dummy.addLogicalLib("commons-logging"); - - String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; - URL baseUrl = dummy.findResource(thisClassPath); - - // Now set up the desired classloader hierarchy. We'll put JCL - // in the container path, the testcase in a webapp path, and - // both config files into the webapp path too. - PathableClassLoader containerLoader = new PathableClassLoader(null); - containerLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); - containerLoader.addLogicalLib("commons-logging"); - - PathableClassLoader webappLoader = new PathableClassLoader(containerLoader); - webappLoader.addLogicalLib("testclasses"); - - URL pri20URL = new URL(baseUrl, "priority20/"); - webappLoader.addURL(pri20URL); - - URL pri10URL = new URL(baseUrl, "priority10/"); - webappLoader.addURL(pri10URL); - - // load the test class via webapp loader, and use the webapp loader - // as the tccl loader too. - Class testClass = webappLoader.loadClass(thisClass.getName()); - return new PathableTestSuite(testClass, webappLoader); - } - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - LogFactory.releaseAll(); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - LogFactory.releaseAll(); - } - - // ----------------------------------------------------------- Test Methods - - /** - * Verify that the config file being used is the one containing - * the desired configId value. - */ - public void testPriority() throws Exception { - LogFactory instance = LogFactory.getFactory(); - - ClassLoader thisClassLoader = this.getClass().getClassLoader(); - ClassLoader lfClassLoader = instance.getClass().getClassLoader(); - ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); - - // context classloader should be thisClassLoader - assertEquals(thisClassLoader, contextClassLoader); - - // lfClassLoader should be parent of this classloader - assertEquals(lfClassLoader, thisClassLoader.getParent()); - assertEquals(PathableClassLoader.class.getName(), - lfClassLoader.getClass().getName()); - - String id = (String) instance.getAttribute("configId"); - assertEquals("Correct config file loaded", "priority20", id ); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/PriorityConfigTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/PriorityConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/PriorityConfigTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/PriorityConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,130 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.config; - - -import java.net.URL; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - * Tests that verify that the process of configuring logging on startup - * works correctly by selecting the file with the highest priority. - *

- * This test sets up a classpath where: - *

    - *
  • first file (in parent loader) has priority=10 (parentFirst=true) - *
  • second file found has no priority set - *
  • third file found has priority=20 - *
  • fourth file found also has priority=20 - *
- * The result should be that the third file is used. - *

- * Note that parentFirst=true is used in this test because method - * PathableClassLoader.getResources always behaves as if - * parentFirst=true; see the PathableClassLoader javadoc for details. - */ - -public class PriorityConfigTestCase extends TestCase { - - // ------------------------------------------- JUnit Infrastructure Methods - - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - Class thisClass = PriorityConfigTestCase.class; - - // Determine the URL to this .class file, so that we can then - // append the priority dirs to it. For tidiness, load this - // class through a dummy loader though this is not absolutely - // necessary... - PathableClassLoader dummy = new PathableClassLoader(null); - dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); - dummy.addLogicalLib("testclasses"); - dummy.addLogicalLib("commons-logging"); - - String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; - URL baseUrl = dummy.findResource(thisClassPath); - - // Now set up the desired classloader hierarchy. We'll put a config - // file of priority=10 in the container path, and ones of both - // "no priority" and priority=20 in the webapp path. - // - // A second properties file with priority=20 is also added, - // so we can check that the first one in the classpath is - // used. - PathableClassLoader containerLoader = new PathableClassLoader(null); - containerLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); - containerLoader.addLogicalLib("commons-logging"); - - URL pri10URL = new URL(baseUrl, "priority10/"); - containerLoader.addURL(pri10URL); - - PathableClassLoader webappLoader = new PathableClassLoader(containerLoader); - webappLoader.setParentFirst(true); - webappLoader.addLogicalLib("testclasses"); - - URL noPriorityURL = new URL(baseUrl, "nopriority/"); - webappLoader.addURL(noPriorityURL); - - URL pri20URL = new URL(baseUrl, "priority20/"); - webappLoader.addURL(pri20URL); - - URL pri20aURL = new URL(baseUrl, "priority20a/"); - webappLoader.addURL(pri20aURL); - - // load the test class via webapp loader, and use the webapp loader - // as the tccl loader too. - Class testClass = webappLoader.loadClass(thisClass.getName()); - return new PathableTestSuite(testClass, webappLoader); - } - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - LogFactory.releaseAll(); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - LogFactory.releaseAll(); - } - - // ----------------------------------------------------------- Test Methods - - /** - * Verify that the config file being used is the one containing - * the desired configId value. - */ - public void testPriority() throws Exception { - LogFactory instance = LogFactory.getFactory(); - String id = (String) instance.getAttribute("configId"); - assertEquals("Correct config file loaded", "priority20", id ); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/nopriority/commons-logging.properties libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/nopriority/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/nopriority/commons-logging.properties 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/nopriority/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -configId=nopriority diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/priority10/commons-logging.properties libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/priority10/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/priority10/commons-logging.properties 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/priority10/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -priority=10.5 -configId=priority10 diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/priority20/commons-logging.properties libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/priority20/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/priority20/commons-logging.properties 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/priority20/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -priority=20.6 -configId=priority20 diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/priority20a/commons-logging.properties libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/priority20a/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/config/priority20a/commons-logging.properties 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/config/priority20a/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -priority=20.6 -configId=priority20a diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/impl/WeakHashtableTest.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/impl/WeakHashtableTest.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/impl/WeakHashtableTest.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/impl/WeakHashtableTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,250 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - -import java.lang.ref.*; -import junit.framework.*; -import java.util.*; - -public class WeakHashtableTest extends TestCase { - - - /** Maximum number of iterations before our test fails */ - private static final int MAX_GC_ITERATIONS = 50; - - private WeakHashtable weakHashtable; - private Long keyOne; - private Long keyTwo; - private Long keyThree; - private Long valueOne; - private Long valueTwo; - private Long valueThree; - - public WeakHashtableTest(String testName) { - super(testName); - } - - - protected void setUp() throws Exception { - super.setUp(); - weakHashtable = new WeakHashtable(); - - keyOne = new Long(1); - keyTwo = new Long(2); - keyThree = new Long(3); - valueOne = new Long(100); - valueTwo = new Long(200); - valueThree = new Long(300); - - weakHashtable.put(keyOne, valueOne); - weakHashtable.put(keyTwo, valueTwo); - weakHashtable.put(keyThree, valueThree); - } - - /** Tests public boolean contains(Object value) */ - public void testContains() throws Exception { - assertFalse(weakHashtable.contains(new Long(1))); - assertFalse(weakHashtable.contains(new Long(2))); - assertFalse(weakHashtable.contains(new Long(3))); - assertTrue(weakHashtable.contains(new Long(100))); - assertTrue(weakHashtable.contains(new Long(200))); - assertTrue(weakHashtable.contains(new Long(300))); - assertFalse(weakHashtable.contains(new Long(400))); - } - - /** Tests public boolean containsKey(Object key) */ - public void testContainsKey() throws Exception { - assertTrue(weakHashtable.containsKey(new Long(1))); - assertTrue(weakHashtable.containsKey(new Long(2))); - assertTrue(weakHashtable.containsKey(new Long(3))); - assertFalse(weakHashtable.containsKey(new Long(100))); - assertFalse(weakHashtable.containsKey(new Long(200))); - assertFalse(weakHashtable.containsKey(new Long(300))); - assertFalse(weakHashtable.containsKey(new Long(400))); - } - - /** Tests public boolean containsValue(Object value) */ - public void testContainsValue() throws Exception { - assertFalse(weakHashtable.containsValue(new Long(1))); - assertFalse(weakHashtable.containsValue(new Long(2))); - assertFalse(weakHashtable.containsValue(new Long(3))); - assertTrue(weakHashtable.containsValue(new Long(100))); - assertTrue(weakHashtable.containsValue(new Long(200))); - assertTrue(weakHashtable.containsValue(new Long(300))); - assertFalse(weakHashtable.containsValue(new Long(400))); - } - - /** Tests public Enumeration elements() */ - public void testElements() throws Exception { - ArrayList elements = new ArrayList(); - for (Enumeration e = weakHashtable.elements(); e.hasMoreElements();) { - elements.add(e.nextElement()); - } - assertEquals(3, elements.size()); - assertTrue(elements.contains(valueOne)); - assertTrue(elements.contains(valueTwo)); - assertTrue(elements.contains(valueThree)); - } - - /** Tests public Set entrySet() */ - public void testEntrySet() throws Exception { - Set entrySet = weakHashtable.entrySet(); - for (Iterator it = entrySet.iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - Object key = entry.getKey(); - if (keyOne.equals(key)) { - assertEquals(valueOne, entry.getValue()); - } else if (keyTwo.equals(key)) { - assertEquals(valueTwo, entry.getValue()); - } else if (keyThree.equals(key)) { - assertEquals(valueThree, entry.getValue()); - } else { - fail("Unexpected key"); - } - } - } - - /** Tests public Object get(Object�key) */ - public void testGet() throws Exception { - assertEquals(valueOne, weakHashtable.get(keyOne)); - assertEquals(valueTwo, weakHashtable.get(keyTwo)); - assertEquals(valueThree, weakHashtable.get(keyThree)); - assertNull(weakHashtable.get(new Long(50))); - } - - /** Tests public Enumeration keys() */ - public void testKeys() throws Exception { - ArrayList keys = new ArrayList(); - for (Enumeration e = weakHashtable.keys(); e.hasMoreElements();) { - keys.add(e.nextElement()); - } - assertEquals(3, keys.size()); - assertTrue(keys.contains(keyOne)); - assertTrue(keys.contains(keyTwo)); - assertTrue(keys.contains(keyThree)); - } - - /** Tests public Set keySet() */ - public void testKeySet() throws Exception { - Set keySet = weakHashtable.keySet(); - assertEquals(3, keySet.size()); - assertTrue(keySet.contains(keyOne)); - assertTrue(keySet.contains(keyTwo)); - assertTrue(keySet.contains(keyThree)); - } - - /** Tests public Object put(Object key, Object value) */ - public void testPut() throws Exception { - Long anotherKey = new Long(2004); - weakHashtable.put(anotherKey, new Long(1066)); - - assertEquals(new Long(1066), weakHashtable.get(anotherKey)); - - // Test compliance with the hashtable API re nulls - Exception caught = null; - try { - weakHashtable.put(null, new Object()); - } - catch (Exception e) { - caught = e; - } - assertNotNull("did not throw an exception adding a null key", caught); - caught = null; - try { - weakHashtable.put(new Object(), null); - } - catch (Exception e) { - caught = e; - } - assertNotNull("did not throw an exception adding a null value", caught); - } - - /** Tests public void putAll(Map t) */ - public void testPutAll() throws Exception { - Map newValues = new HashMap(); - Long newKey = new Long(1066); - Long newValue = new Long(1415); - newValues.put(newKey, newValue); - Long anotherNewKey = new Long(1645); - Long anotherNewValue = new Long(1815); - newValues.put(anotherNewKey, anotherNewValue); - weakHashtable.putAll(newValues); - - assertEquals(5, weakHashtable.size()); - assertEquals(newValue, weakHashtable.get(newKey)); - assertEquals(anotherNewValue, weakHashtable.get(anotherNewKey)); - } - - /** Tests public Object remove(Object�key) */ - public void testRemove() throws Exception { - weakHashtable.remove(keyOne); - assertEquals(2, weakHashtable.size()); - assertNull(weakHashtable.get(keyOne)); - } - - /** Tests public Collection values() */ - public void testValues() throws Exception { - Collection values = weakHashtable.values(); - assertEquals(3, values.size()); - assertTrue(values.contains(valueOne)); - assertTrue(values.contains(valueTwo)); - assertTrue(values.contains(valueThree)); - } - - public void testRelease() throws Exception { - assertNotNull(weakHashtable.get(new Long(1))); - ReferenceQueue testQueue = new ReferenceQueue(); - WeakReference weakKeyOne = new WeakReference(keyOne, testQueue); - - // lose our references - keyOne = null; - keyTwo = null; - keyThree = null; - valueOne = null; - valueTwo = null; - valueThree = null; - - int iterations = 0; - int bytz = 2; - while(true) { - System.gc(); - if(iterations++ > MAX_GC_ITERATIONS){ - fail("Max iterations reached before resource released."); - } - - if(weakHashtable.get(new Long(1)) == null) { - break; - - } else { - // create garbage: - byte[] b = new byte[bytz]; - bytz = bytz * 2; - } - } - - // some JVMs seem to take a little time to put references on - // the reference queue once the reference has been collected - // need to think about whether this is enough to justify - // stepping through the collection each time... - while(testQueue.poll() == null) {} - - // Test that the released objects are not taking space in the table - assertEquals("underlying table not emptied", 0, weakHashtable.size()); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/CustomConfig.properties libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/CustomConfig.properties --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/CustomConfig.properties 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/CustomConfig.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -# This is the custom configuration properties for the JDK 1.4 logger tests -# in CustomConfigTestCase. - -# Configure the Handler so we can examine the logged messages -handlers = org.apache.commons.logging.jdk14.TestHandler - -# Configre the default logging level to be FINE so we should get -# everything except trace messages -.level = FINE diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.jdk14; - -import junit.framework.Test; - -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - * TestCase for Jdk14 logging when the commons-logging-api jar file is in - * the parent classpath and commons-logging.jar is in the child. - */ - -public class CustomConfigAPITestCase extends CustomConfigTestCase { - - public CustomConfigAPITestCase(String name) { - super(name); - } - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - PathableClassLoader parent = new PathableClassLoader(null); - parent.useExplicitLoader("junit.", Test.class.getClassLoader()); - - // the TestHandler class must be accessable from the System classloader - // in order for java.util.logging.LogManager.readConfiguration to - // be able to instantiate it. And this test case must see the same - // class in order to be able to access its data. Yes this is ugly - // but the whole jdk14 API is a ******* mess anyway. - ClassLoader scl = ClassLoader.getSystemClassLoader(); - loadTestHandler(HANDLER_NAME, scl); - parent.useExplicitLoader(HANDLER_NAME, scl); - parent.addLogicalLib("commons-logging-api"); - - PathableClassLoader child = new PathableClassLoader(parent); - child.addLogicalLib("testclasses"); - child.addLogicalLib("commons-logging"); - - Class testClass = child.loadClass(CustomConfigAPITestCase.class.getName()); - return new PathableTestSuite(testClass, child); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.jdk14; - - -import junit.framework.Test; - -import org.apache.commons.logging.PathableTestSuite; -import org.apache.commons.logging.PathableClassLoader; - - -/** - * TestCase for Jdk14 logging when the commons-logging jar file is in - * the parent classpath. - */ - -public class CustomConfigFullTestCase extends CustomConfigTestCase { - - - public CustomConfigFullTestCase(String name) { - super(name); - } - - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - PathableClassLoader parent = new PathableClassLoader(null); - parent.useExplicitLoader("junit.", Test.class.getClassLoader()); - - // the TestHandler class must be accessable from the System classloader - // in order for java.util.logging.LogManager.readConfiguration to - // be able to instantiate it. And this test case must see the same - // class in order to be able to access its data. Yes this is ugly - // but the whole jdk14 API is a ******* mess anyway. - ClassLoader scl = ClassLoader.getSystemClassLoader(); - loadTestHandler(HANDLER_NAME, scl); - parent.useExplicitLoader(HANDLER_NAME, scl); - parent.addLogicalLib("commons-logging"); - - PathableClassLoader child = new PathableClassLoader(parent); - child.addLogicalLib("testclasses"); - - Class testClass = child.loadClass(CustomConfigFullTestCase.class.getName()); - return new PathableTestSuite(testClass, child); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,398 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.jdk14; - - -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.util.Iterator; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogManager; -import java.util.logging.LogRecord; -import java.util.logging.Logger; - -import junit.framework.Test; - -import org.apache.commons.logging.DummyException; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - *

TestCase for JDK 1.4 logging when running on a JDK 1.4 system with - * custom configuration, so that JDK 1.4 should be selected and an appropriate - * logger configured per the configuration properties.

- * - * @author Craig R. McClanahan - * @version $Revision: 568760 $ $Date: 2007-08-23 00:19:45 +0200 (to, 23 aug 2007) $ - */ - -public class CustomConfigTestCase extends DefaultConfigTestCase { - - protected static final String HANDLER_NAME - = "org.apache.commons.logging.jdk14.TestHandler"; - - // ----------------------------------------------------------- Constructors - - - /** - *

Construct a new instance of this test case.

- * - * @param name Name of the test case - */ - public CustomConfigTestCase(String name) { - super(name); - } - - - // ----------------------------------------------------- Instance Variables - - - /** - *

The customized Handler we will be using.

- */ - protected TestHandler handler = null; - - - /** - *

The underlying Handlers we will be using.

- */ - protected Handler handlers[] = null; - - - /** - *

The underlying Logger we will be using.

- */ - protected Logger logger = null; - - - /** - *

The underlying LogManager we will be using.

- */ - protected LogManager manager = null; - - - /** - *

The message levels that should have been logged.

- */ - protected Level testLevels[] = - { Level.FINE, Level.INFO, Level.WARNING, Level.SEVERE, Level.SEVERE }; - - - /** - *

The message strings that should have been logged.

- */ - protected String testMessages[] = - { "debug", "info", "warn", "error", "fatal" }; - - - // ------------------------------------------- JUnit Infrastructure Methods - - - /** - * Given the name of a class that is somewhere in the classpath of the provided - * classloader, return the contents of the corresponding .class file. - */ - protected static byte[] readClass(String name, ClassLoader srcCL) throws Exception { - String resName = name.replace('.', '/') + ".class"; - System.err.println("Trying to load resource [" + resName + "]"); - InputStream is = srcCL.getResourceAsStream(resName); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - System.err.println("Reading resource [" + resName + "]"); - byte[] buf = new byte[1000]; - for(;;) { - int read = is.read(buf); - if (read <= 0) { - break; - } - baos.write(buf, 0, read); - } - is.close(); - return baos.toByteArray(); - } - - /** - * Make a class available in the system classloader even when its classfile is - * not present in the classpath configured for that classloader. This only - * works for classes for which all dependencies are already loaded in - * that classloader. - */ - protected static void loadTestHandler(String className, ClassLoader targetCL) { - try { - targetCL.loadClass(className); - // fail("Class already in target classloader"); - return; - } catch(ClassNotFoundException ex) { - // ok, go ahead and load it - } - - try { - ClassLoader srcCL = CustomConfigAPITestCase.class.getClassLoader(); - byte[] classData = readClass(className, srcCL); - - Class[] params = new Class[] { - String.class, classData.getClass(), - Integer.TYPE, Integer.TYPE}; - Method m = ClassLoader.class.getDeclaredMethod("defineClass", params); - - Object[] args = new Object[4]; - args[0] = className; - args[1] = classData; - args[2] = new Integer(0); - args[3] = new Integer(classData.length); - m.setAccessible(true); - m.invoke(targetCL, args); - } catch(Exception e) { - e.printStackTrace(); - fail("Unable to load class " + className); - } - } - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - setUpManager - ("org/apache/commons/logging/jdk14/CustomConfig.properties"); - setUpLogger("TestLogger"); - setUpHandlers(); - setUpFactory(); - setUpLog("TestLogger"); - } - - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - PathableClassLoader cl = new PathableClassLoader(null); - cl.useExplicitLoader("junit.", Test.class.getClassLoader()); - - // the TestHandler class must be accessable from the System classloader - // in order for java.util.logging.LogManager.readConfiguration to - // be able to instantiate it. And this test case must see the same - // class in order to be able to access its data. Yes this is ugly - // but the whole jdk14 API is a ******* mess anyway. - ClassLoader scl = ClassLoader.getSystemClassLoader(); - loadTestHandler(HANDLER_NAME, scl); - cl.useExplicitLoader(HANDLER_NAME, scl); - cl.addLogicalLib("commons-logging"); - cl.addLogicalLib("testclasses"); - - Class testClass = cl.loadClass(CustomConfigTestCase.class.getName()); - return new PathableTestSuite(testClass, cl); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - super.tearDown(); - handlers = null; - logger = null; - manager = null; - } - - - // ----------------------------------------------------------- Test Methods - - - // Test logging message strings with exceptions - public void testExceptionMessages() throws Exception { - - logExceptionMessages(); - checkLogRecords(true); - - } - - - // Test logging plain message strings - public void testPlainMessages() throws Exception { - - logPlainMessages(); - checkLogRecords(false); - - } - - - // Test pristine Handlers instances - public void testPristineHandlers() { - - assertNotNull(handlers); - assertEquals(1, handlers.length); - assertTrue(handlers[0] instanceof TestHandler); - assertNotNull(handler); - - } - - - // Test pristine Logger instance - public void testPristineLogger() { - - assertNotNull("Logger exists", logger); - assertEquals("Logger name", "TestLogger", logger.getName()); - - // Assert which logging levels have been enabled - assertTrue(logger.isLoggable(Level.SEVERE)); - assertTrue(logger.isLoggable(Level.WARNING)); - assertTrue(logger.isLoggable(Level.INFO)); - assertTrue(logger.isLoggable(Level.CONFIG)); - assertTrue(logger.isLoggable(Level.FINE)); - assertTrue(!logger.isLoggable(Level.FINER)); - assertTrue(!logger.isLoggable(Level.FINEST)); - - } - - - // Test Serializability of Log instance - public void testSerializable() throws Exception { - - super.testSerializable(); - testExceptionMessages(); - - } - - - // -------------------------------------------------------- Support Methods - - - // Check the log instance - protected void checkLog() { - - assertNotNull("Log exists", log); - assertEquals("Log class", - "org.apache.commons.logging.impl.Jdk14Logger", - log.getClass().getName()); - - // Assert which logging levels have been enabled - assertTrue(log.isFatalEnabled()); - assertTrue(log.isErrorEnabled()); - assertTrue(log.isWarnEnabled()); - assertTrue(log.isInfoEnabled()); - assertTrue(log.isDebugEnabled()); - assertTrue(!log.isTraceEnabled()); - - } - - - // Check the recorded messages - protected void checkLogRecords(boolean thrown) { - Iterator records = handler.records(); - for (int i = 0; i < testMessages.length; i++) { - assertTrue(records.hasNext()); - LogRecord record = (LogRecord) records.next(); - assertEquals("LogRecord level", - testLevels[i], record.getLevel()); - assertEquals("LogRecord message", - testMessages[i], record.getMessage()); - assertTrue("LogRecord class", - record.getSourceClassName().startsWith( - "org.apache.commons.logging.jdk14.CustomConfig")); - if (thrown) { - assertEquals("LogRecord method", - "logExceptionMessages", - record.getSourceMethodName()); - } else { - assertEquals("LogRecord method", - "logPlainMessages", - record.getSourceMethodName()); - } - if (thrown) { - assertNotNull("LogRecord thrown", record.getThrown()); - assertTrue("LogRecord thrown type", - record.getThrown() instanceof DummyException); - } else { - assertNull("LogRecord thrown", - record.getThrown()); - } - } - assertTrue(!records.hasNext()); - handler.flush(); - } - - - // Log the messages with exceptions - protected void logExceptionMessages() { - Throwable t = new DummyException(); - log.trace("trace", t); // Should not actually get logged - log.debug("debug", t); - log.info("info", t); - log.warn("warn", t); - log.error("error", t); - log.fatal("fatal", t); - } - - - // Log the plain messages - protected void logPlainMessages() { - log.trace("trace"); // Should not actually get logged - log.debug("debug"); - log.info("info"); - log.warn("warn"); - log.error("error"); - log.fatal("fatal"); - } - - - // Set up handlers instance - protected void setUpHandlers() throws Exception { - Logger parent = logger; - while (parent.getParent() != null) { - parent = parent.getParent(); - } - handlers = parent.getHandlers(); - - // The CustomConfig.properties file explicitly defines one handler class - // to be attached to the root logger, so if it isn't there then - // something is badly wrong... - // - // Yes this testing is also done in testPristineHandlers but - // unfortunately: - // * we need to set up the handlers variable here, - // * we don't want that to be set up incorrectly, as that can - // produce weird error messages in other tests, and - // * we can't rely on testPristineHandlers being the first - // test to run. - // so we need to test things here too. - assertNotNull("No Handlers defined for JDK14 logging", handlers); - assertEquals("Unexpected number of handlers for JDK14 logging", 1, handlers.length); - assertNotNull("Handler is null", handlers[0]); - assertTrue("Handler not of expected type", handlers[0] instanceof TestHandler); - handler = (TestHandler) handlers[0]; - } - - - // Set up logger instance - protected void setUpLogger(String name) throws Exception { - logger = Logger.getLogger(name); - } - - - // Set up LogManager instance - protected void setUpManager(String config) throws Exception { - manager = LogManager.getLogManager(); - InputStream is = - this.getClass().getClassLoader().getResourceAsStream(config); - manager.readConfiguration(is); - is.close(); - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,192 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.jdk14; - - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - *

TestCase for JDK 1.4 logging when running on a JDK 1.4 system with - * zero configuration, and with Log4J not present (so JDK 1.4 logging - * should be automatically configured.

- * - * @author Craig R. McClanahan - * @version $Revision: 427808 $ $Date: 2006-08-02 02:08:20 +0200 (on, 02 aug 2006) $ - */ - -public class DefaultConfigTestCase extends TestCase { - - - // ----------------------------------------------------------- Constructors - - - /** - *

Construct a new instance of this test case.

- * - * @param name Name of the test case - */ - public DefaultConfigTestCase(String name) { - super(name); - } - - - // ----------------------------------------------------- Instance Variables - - - /** - *

The {@link LogFactory} implementation we have selected.

- */ - protected LogFactory factory = null; - - - /** - *

The {@link Log} implementation we have selected.

- */ - protected Log log = null; - - - // ------------------------------------------- JUnit Infrastructure Methods - - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - setUpFactory(); - setUpLog("TestLogger"); - } - - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - PathableClassLoader loader = new PathableClassLoader(null); - loader.useExplicitLoader("junit.", Test.class.getClassLoader()); - loader.addLogicalLib("testclasses"); - loader.addLogicalLib("commons-logging"); - - Class testClass = loader.loadClass(DefaultConfigTestCase.class.getName()); - return new PathableTestSuite(testClass, loader); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - log = null; - factory = null; - LogFactory.releaseAll(); - } - - - // ----------------------------------------------------------- Test Methods - - - // Test pristine Log instance - public void testPristineLog() { - - checkLog(); - - } - - - // Test pristine LogFactory instance - public void testPristineFactory() { - - assertNotNull("LogFactory exists", factory); - assertEquals("LogFactory class", - "org.apache.commons.logging.impl.LogFactoryImpl", - factory.getClass().getName()); - - String names[] = factory.getAttributeNames(); - assertNotNull("Names exists", names); - assertEquals("Names empty", 0, names.length); - - } - - - // Test Serializability of Log instance - public void testSerializable() throws Exception { - - // Serialize and deserialize the instance - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(log); - oos.close(); - ByteArrayInputStream bais = - new ByteArrayInputStream(baos.toByteArray()); - ObjectInputStream ois = new ObjectInputStream(bais); - log = (Log) ois.readObject(); - ois.close(); - - // Check the characteristics of the resulting object - checkLog(); - - } - - - // -------------------------------------------------------- Support Methods - - - - // Check the log instance - protected void checkLog() { - - assertNotNull("Log exists", log); - assertEquals("Log class", - "org.apache.commons.logging.impl.Jdk14Logger", - log.getClass().getName()); - - // Can we call level checkers with no exceptions? - log.isDebugEnabled(); - log.isErrorEnabled(); - log.isFatalEnabled(); - log.isInfoEnabled(); - log.isTraceEnabled(); - log.isWarnEnabled(); - - } - - - // Set up factory instance - protected void setUpFactory() throws Exception { - factory = LogFactory.getFactory(); - } - - - // Set up log instance - protected void setUpLog(String name) throws Exception { - log = LogFactory.getLog(name); - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/TestHandler.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/TestHandler.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/jdk14/TestHandler.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/jdk14/TestHandler.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.logging.jdk14; - - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.logging.Handler; -import java.util.logging.LogRecord; - - -/** - *

Test implementation of java.util.logging.Handler.

- * - * @author Craig R. McClanahan - * @version $Revision: 424108 $ $Date: 2006-07-21 01:19:55 +0200 (fr, 21 jul 2006) $ - */ - -public class TestHandler extends Handler { - - - - // ----------------------------------------------------- Instance Variables - - - // The set of logged records for this handler - private List records = new ArrayList(); - - - // --------------------------------------------------------- Public Methods - - - public Iterator records() { - return (records.iterator()); - } - - - // -------------------------------------------------------- Handler Methods - - - public void close() { - } - - - public void flush() { - records.clear(); - } - - - public void publish(LogRecord record) { - records.add(record); - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/StandardTests.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/StandardTests.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/StandardTests.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/StandardTests.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,216 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.log4j; - - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.ArrayList; -import java.util.List; - -import junit.framework.TestCase; - -import org.apache.commons.logging.DummyException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - - -/** - * Abstract set of tests that can be executed with various classpaths set. - *

- * The tests verify that when running on a system with Log4J present, - * Log4J is selected and that the logger basically works. - */ - -public abstract class StandardTests extends TestCase { - - /** - * Simple structure to store information about messages that actually get - * logged by the underlying logging library. - */ - public static class LogEvent { - public String msg; - public String level; - public Throwable throwable; - } - - // ------------------------------------------------------------------- - // JUnit Infrastructure Methods - // ------------------------------------------------------------------- - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - LogFactory.releaseAll(); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - LogFactory.releaseAll(); - } - - // ----------------------------------------------------------- - // abstract methods - // ----------------------------------------------------------- - - /** - * Modify log4j's setup so that all messages actually logged get redirected - * into the specified list. - *

- * This method also sets the logging level to INFO so that we - * can test whether messages are getting properly filtered. - */ - public abstract void setUpTestAppender(List logEvents) throws Exception; - - // ----------------------------------------------------------- Test Methods - - /** - * Test that a LogFactory gets created as expected. - */ - public void testCreateFactory() { - LogFactory factory = LogFactory.getFactory(); - assertNotNull("LogFactory exists", factory); - assertEquals("LogFactory class", - "org.apache.commons.logging.impl.LogFactoryImpl", - factory.getClass().getName()); - - String names[] = factory.getAttributeNames(); - assertNotNull("Names exists", names); - assertEquals("Names empty", 0, names.length); - } - - /** - * Verify that we can log messages without exceptions. - */ - public void testPlainMessages() throws Exception { - List logEvents = new ArrayList(); - setUpTestAppender(logEvents); - Log log = LogFactory.getLog("test-category"); - logPlainMessages(log); - checkLoggingEvents(logEvents, false); - } - - /** - * Verify that we can log exception messages. - */ - public void testExceptionMessages() throws Exception { - List logEvents = new ArrayList(); - setUpTestAppender(logEvents); - Log log = LogFactory.getLog("test-category"); - logExceptionMessages(log); - checkLoggingEvents(logEvents, true); - } - - /** - * Test Serializability of Log instance - */ - public void testSerializable() throws Exception { - List logEvents = new ArrayList(); - setUpTestAppender(logEvents); - Log log = LogFactory.getLog("test-category"); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(log); - oos.close(); - ByteArrayInputStream bais = - new ByteArrayInputStream(baos.toByteArray()); - ObjectInputStream ois = new ObjectInputStream(bais); - Log newLog = (Log) ois.readObject(); - ois.close(); - - // Check the characteristics of the resulting object - logExceptionMessages(newLog); - checkLoggingEvents(logEvents, true); - } - - // -------------------------------------------------------- Support Methods - - /** - * Verify that the TestAppender has received the expected - * number of messages. This assumes that: - *

    - *
  • setUpTestAppender has been called - *
  • logPlainMessages or logExceptionMessages has been - * called to log a known number of messages at known levels. - *
- * - * @param logEvents is the list of log events received. - * - * @param thrown False if logPlainMessages was called - * (ie the TestAppender is expected to have received - * logevents with no associated exception info). True if - * logExceptionMessages was called. - */ - private void checkLoggingEvents(List logEvents, boolean thrown) { - LogEvent ev; - - assertEquals("Unexpected number of log events", 4, logEvents.size()); - - ev = (LogEvent) logEvents.get(0); - assertEquals("Info message expected", "info", ev.msg); - assertEquals("Info level expected", "INFO", ev.level); - assertEquals("Exception data incorrect", (ev.throwable!=null), thrown); - - ev = (LogEvent) logEvents.get(1); - assertEquals("Warn message expected", "warn", ev.msg); - assertEquals("Warn level expected", "WARN", ev.level); - assertEquals("Exception data incorrect", (ev.throwable!=null), thrown); - - ev = (LogEvent) logEvents.get(2); - assertEquals("Error message expected", "error", ev.msg); - assertEquals("Error level expected", "ERROR", ev.level); - assertEquals("Exception data incorrect", (ev.throwable!=null), thrown); - - ev = (LogEvent) logEvents.get(3); - assertEquals("Fatal message expected", "fatal", ev.msg); - assertEquals("Fatal level expected", "FATAL", ev.level); - assertEquals("Exception data incorrect", (ev.throwable!=null), thrown); - } - - - /** - * Log plain messages. - */ - private void logPlainMessages(Log log) { - log.trace("trace"); // Should not actually get logged - log.debug("debug"); // Should not actually get logged - log.info("info"); - log.warn("warn"); - log.error("error"); - log.fatal("fatal"); - } - - /** - * Log messages with exceptions - */ - private void logExceptionMessages(Log log) { - Throwable t = new DummyException(); - log.trace("trace", t); // Should not actually get logged - log.debug("debug", t); // Should not actually get logged - log.info("info", t); - log.warn("warn", t); - log.error("error", t); - log.fatal("fatal", t); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.log4j.log4j12; - -import junit.framework.Test; - -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - * Tests for Log4J logging that emulate a webapp running within - * a container where the commons-logging-api jar file is in - * the parent classpath and commons-logging.jar is in the child. - */ - -public class ApiClasspathStandardTestCase { - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - PathableClassLoader parent = new PathableClassLoader(null); - parent.useExplicitLoader("junit.", Test.class.getClassLoader()); - parent.addLogicalLib("commons-logging-api"); - - PathableClassLoader child = new PathableClassLoader(parent); - child.addLogicalLib("log4j12"); - child.addLogicalLib("commons-logging"); - child.addLogicalLib("testclasses"); - - Class testClass = child.loadClass( - "org.apache.commons.logging.log4j.log4j12.Log4j12StandardTests"); - return new PathableTestSuite(testClass, child); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.log4j.log4j12; - -import junit.framework.Test; - -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - -/** - * Tests for Log4J logging when there is only one classloader and everything - * is in it, as would be the situation for a standalone application. - */ - -public class AppClasspathStandardTestCase { - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - PathableClassLoader loader = new PathableClassLoader(null); - loader.useExplicitLoader("junit.", Test.class.getClassLoader()); - loader.addLogicalLib("testclasses"); - loader.addLogicalLib("log4j12"); - loader.addLogicalLib("commons-logging"); - - Class testClass = loader.loadClass( - "org.apache.commons.logging.log4j.log4j12.Log4j12StandardTests"); - return new PathableTestSuite(testClass, loader); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.log4j.log4j12; - -import junit.framework.Test; - -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - * Tests for Log4J logging that emulate a webapp running within - * a container where all the necessary libs are in the child. - */ - -public class ChildClasspathStandardTestCase { - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - PathableClassLoader parent = new PathableClassLoader(null); - parent.useExplicitLoader("junit.", Test.class.getClassLoader()); - - PathableClassLoader child = new PathableClassLoader(parent); - child.addLogicalLib("testclasses"); - child.addLogicalLib("log4j12"); - child.addLogicalLib("commons-logging"); - - Class testClass = child.loadClass( - "org.apache.commons.logging.log4j.log4j12.Log4j12StandardTests"); - return new PathableTestSuite(testClass, child); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/Log4j12StandardTests.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/Log4j12StandardTests.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/Log4j12StandardTests.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/Log4j12StandardTests.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.log4j.log4j12; - -import java.util.List; - -import org.apache.commons.logging.log4j.StandardTests; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; - -/** - * A concrete class that runs the standard tests, and is compiled - * specifically against log4j12. The parent class can't call any - * log4j methods at all as that would mean it has to be compiled - * against a particular version of log4j. - */ - -public class Log4j12StandardTests extends StandardTests { - - public void setUpTestAppender(List logEvents) { - TestAppender appender = new TestAppender(logEvents); - Logger rootLogger = Logger.getRootLogger(); - rootLogger.removeAllAppenders(); - rootLogger.addAppender(appender); - rootLogger.setLevel(Level.INFO); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.log4j.log4j12; - -import junit.framework.Test; - -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - -/** - * Tests for Log4J logging that emulate a webapp running within - * a container where all the necessary libs are in the parent. - */ - -public class ParentClasspathStandardTestCase { - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - PathableClassLoader parent = new PathableClassLoader(null); - parent.useExplicitLoader("junit.", Test.class.getClassLoader()); - parent.addLogicalLib("commons-logging"); - parent.addLogicalLib("log4j12"); - - PathableClassLoader child = new PathableClassLoader(parent); - child.addLogicalLib("testclasses"); - - Class testClass = child.loadClass( - "org.apache.commons.logging.log4j.log4j12.Log4j12StandardTests"); - return new PathableTestSuite(testClass, child); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/TestAppender.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/TestAppender.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/log4j/log4j12/TestAppender.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/log4j/log4j12/TestAppender.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.log4j.log4j12; - - -import java.util.List; - -import org.apache.commons.logging.log4j.StandardTests; -import org.apache.log4j.AppenderSkeleton; -import org.apache.log4j.spi.LoggingEvent; - -/** - * A custom implementation of org.apache.log4j.Appender which - * converts the log4j-specific log event record into a representation that - * doesn't have a dependency on log4j and stores that new representation into - * an external list. - */ - -public class TestAppender extends AppenderSkeleton { - - /** - * Constructor. - */ - public TestAppender(List logEvents) { - events = logEvents; - } - - // ----------------------------------------------------- Instance Variables - - - // The set of logged events for this appender - private List events; - - - // ------------------------------------------------------- Appender Methods - - protected void append(LoggingEvent event) { - StandardTests.LogEvent lev = new StandardTests.LogEvent(); - - lev.level = event.getLevel().toString(); - - if (event.getMessage() == null) - lev.msg = null; - else - lev.msg = event.getMessage().toString(); - - if (event.getThrowableInformation() == null) - lev.throwable = null; - else - lev.throwable = event.getThrowableInformation().getThrowable(); - - events.add(lev); - } - - - public void close() { - } - - - public boolean requiresLayout() { - return (false); - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/logkit/StandardTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/logkit/StandardTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/logkit/StandardTestCase.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/logkit/StandardTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,166 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.logkit; - - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import junit.framework.Test; - -import org.apache.commons.logging.AbstractLogTest; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; -import org.apache.commons.logging.impl.LogKitLogger; - -/** - * Basic tests for Avalon LogKit logger adapter. - */ - -public class StandardTestCase extends AbstractLogTest { - - - // ----------------------------------------------------- Instance Variables - - - /** - *

The {@link LogFactory} implementation we have selected.

- */ - protected LogFactory factory = null; - - - /** - *

The {@link Log} implementation we have selected.

- */ - protected Log log = null; - - - // ------------------------------------------- JUnit Infrastructure Methods - - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - Class thisClass = StandardTestCase.class; - - PathableClassLoader loader = new PathableClassLoader(null); - loader.useExplicitLoader("junit.", Test.class.getClassLoader()); - loader.addLogicalLib("testclasses"); - loader.addLogicalLib("commons-logging"); - loader.addLogicalLib("logkit"); - - Class testClass = loader.loadClass(thisClass.getName()); - return new PathableTestSuite(testClass, loader); - } - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - LogFactory.releaseAll(); - - System.setProperty( - "org.apache.commons.logging.Log", - "org.apache.commons.logging.impl.LogKitLogger"); - - factory = LogFactory.getFactory(); - log = LogFactory.getLog("TestLogger"); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - log = null; - factory = null; - LogFactory.releaseAll(); - } - - // ----------------------------------------------------------- Test Methods - - /** - * Override the abstract method from the parent class so that the - * inherited tests can access the right Log object type. - */ - public Log getLogObject() - { - return new LogKitLogger(this.getClass().getName()); - } - - // Test pristine LogFactory instance - public void testPristineFactory() { - - assertNotNull("LogFactory exists", factory); - assertEquals("LogFactory class", - "org.apache.commons.logging.impl.LogFactoryImpl", - factory.getClass().getName()); - - String names[] = factory.getAttributeNames(); - assertNotNull("Names exists", names); - assertEquals("Names empty", 0, names.length); - } - - // Test pristine Log instance - public void testPristineLog() { - checkStandard(); - } - - // Test Serializability of standard instance - public void testSerializable() throws Exception { - checkStandard(); - - // Serialize and deserialize the instance - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(log); - oos.close(); - ByteArrayInputStream bais = - new ByteArrayInputStream(baos.toByteArray()); - ObjectInputStream ois = new ObjectInputStream(bais); - log = (Log) ois.readObject(); - ois.close(); - - checkStandard(); - } - - - // -------------------------------------------------------- Support Methods - - // Check the standard log instance - protected void checkStandard() { - - assertNotNull("Log exists", log); - assertEquals("Log class", - "org.apache.commons.logging.impl.LogKitLogger", - log.getClass().getName()); - - // Can we call level checkers with no exceptions? - // Note that by default *everything* is enabled for LogKit - assertTrue(log.isTraceEnabled()); - assertTrue(log.isDebugEnabled()); - assertTrue(log.isInfoEnabled()); - assertTrue(log.isWarnEnabled()); - assertTrue(log.isErrorEnabled()); - assertTrue(log.isFatalEnabled()); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/noop/NoOpLogTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/noop/NoOpLogTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/noop/NoOpLogTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/noop/NoOpLogTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.noop; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.impl.NoOpLog; -import org.apache.commons.logging.AbstractLogTest; - -/** - * Tests for NoOpLog logging adapter. - *

- * This simply applies the tests defined in AbstractLogTest to this class. - */ -public class NoOpLogTestCase extends AbstractLogTest -{ - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - LogFactory.releaseAll(); - - System.setProperty( - "org.apache.commons.logging.Log", - "org.apache.commons.logging.impl.NoOpLog"); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - LogFactory.releaseAll(); - System.getProperties().remove("org.apache.commons.logging.Log"); - } - - /** - * Override the abstract method from the parent class so that the - * inherited tests can access the right Log object type. - */ - public Log getLogObject() - { - return (Log) new NoOpLog(this.getClass().getName()); - } - - // Test Serializability of standard instance - public void testSerializable() throws Exception { - Log log = LogFactory.getLog(this.getClass().getName()); - checkLog(log); - - // Serialize and deserialize the instance - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(log); - oos.close(); - ByteArrayInputStream bais = - new ByteArrayInputStream(baos.toByteArray()); - ObjectInputStream ois = new ObjectInputStream(bais); - log = (Log) ois.readObject(); - ois.close(); - - checkLog(log); - } - - - // -------------------------------------------------------- Support Methods - - private void checkLog(Log log) { - - assertNotNull("Log exists", log); - assertEquals("Log class", - "org.apache.commons.logging.impl.NoOpLog", - log.getClass().getName()); - - // Can we call level checkers with no exceptions? - // Note that *everything* is permanently disabled for NoOpLog - assertFalse(log.isTraceEnabled()); - assertFalse(log.isDebugEnabled()); - assertFalse(log.isInfoEnabled()); - assertFalse(log.isWarnEnabled()); - assertFalse(log.isErrorEnabled()); - assertFalse(log.isFatalEnabled()); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/pathable/ChildFirstTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/pathable/ChildFirstTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/pathable/ChildFirstTestCase.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/pathable/ChildFirstTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,317 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.logging.pathable; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Set; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - -/** - * Tests for the PathableTestSuite and PathableClassLoader functionality, - * where lookup order for the PathableClassLoader is child-first. - *

- * These tests assume: - *

    - *
  • junit is in system classpath - *
  • nothing else is in system classpath - *
- */ - -public class ChildFirstTestCase extends TestCase { - - /** - * Set up a custom classloader hierarchy for this test case. - * The hierarchy is: - *
    - *
  • contextloader: child-first. - *
  • childloader: child-first, used to load test case. - *
  • parentloader: child-first, parent is the bootclassloader. - *
- */ - public static Test suite() throws Exception { - Class thisClass = ChildFirstTestCase.class; - ClassLoader thisClassLoader = thisClass.getClassLoader(); - - // Make the parent a direct child of the bootloader to hide all - // other classes in the system classpath - PathableClassLoader parent = new PathableClassLoader(null); - parent.setParentFirst(false); - - // Make the junit classes visible as a special case, as junit - // won't be able to call this class at all without this. The - // junit classes must be visible from the classloader that loaded - // this class, so use that as the source for future access to classes - // from the junit package. - parent.useExplicitLoader("junit.", thisClassLoader); - - // Make the commons-logging.jar classes visible via the parent - parent.addLogicalLib("commons-logging"); - - // Create a child classloader to load the test case through - PathableClassLoader child = new PathableClassLoader(parent); - child.setParentFirst(false); - - // Obviously, the child classloader needs to have the test classes - // in its path! - child.addLogicalLib("testclasses"); - child.addLogicalLib("commons-logging-adapters"); - - // Create a third classloader to be the context classloader. - PathableClassLoader context = new PathableClassLoader(child); - context.setParentFirst(false); - - // reload this class via the child classloader - Class testClass = child.loadClass(thisClass.getName()); - - // and return our custom TestSuite class - return new PathableTestSuite(testClass, context); - } - - /** - * Utility method to return the set of all classloaders in the - * parent chain starting from the one that loaded the class for - * this object instance. - */ - private Set getAncestorCLs() { - Set s = new HashSet(); - ClassLoader cl = this.getClass().getClassLoader(); - while (cl != null) { - s.add(cl); - cl = cl.getParent(); - } - return s; - } - - /** - * Test that the classloader hierarchy is as expected, and that - * calling loadClass() on various classloaders works as expected. - * Note that for this test case, parent-first classloading is - * in effect. - */ - public void testPaths() throws Exception { - // the context classloader is not expected to be null - ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - assertNotNull("Context classloader is null", contextLoader); - assertEquals("Context classloader has unexpected type", - PathableClassLoader.class.getName(), - contextLoader.getClass().getName()); - - // the classloader that loaded this class is obviously not null - ClassLoader thisLoader = this.getClass().getClassLoader(); - assertNotNull("thisLoader is null", thisLoader); - assertEquals("thisLoader has unexpected type", - PathableClassLoader.class.getName(), - thisLoader.getClass().getName()); - - // the suite method specified that the context classloader's parent - // is the loader that loaded this test case. - assertSame("Context classloader is not child of thisLoader", - thisLoader, contextLoader.getParent()); - - // thisLoader's parent should be available - ClassLoader parentLoader = thisLoader.getParent(); - assertNotNull("Parent classloader is null", parentLoader); - assertEquals("Parent classloader has unexpected type", - PathableClassLoader.class.getName(), - parentLoader.getClass().getName()); - - // parent should have a parent of null - assertNull("Parent classloader has non-null parent", parentLoader.getParent()); - - // getSystemClassloader is not a PathableClassLoader; it's of a - // built-in type. This also verifies that system classloader is none of - // (context, child, parent). - ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); - assertNotNull("System classloader is null", systemLoader); - assertFalse("System classloader has unexpected type", - PathableClassLoader.class.getName().equals( - systemLoader.getClass().getName())); - - // junit classes should be visible; their classloader is not - // in the hierarchy of parent classloaders for this class, - // though it is accessable due to trickery in the PathableClassLoader. - Class junitTest = contextLoader.loadClass("junit.framework.Test"); - Set ancestorCLs = getAncestorCLs(); - assertFalse("Junit not loaded by ancestor classloader", - ancestorCLs.contains(junitTest.getClassLoader())); - - // jcl api classes should be visible only via the parent - Class logClass = contextLoader.loadClass("org.apache.commons.logging.Log"); - assertSame("Log class not loaded via parent", - logClass.getClassLoader(), parentLoader); - - // jcl adapter classes should be visible via both parent and child. However - // as the classloaders are child-first we should see the child one. - Class log4jClass = contextLoader.loadClass("org.apache.commons.logging.impl.Log4JLogger"); - assertSame("Log4JLogger not loaded via child", - log4jClass.getClassLoader(), thisLoader); - - // test classes should be visible via the child only - Class testClass = contextLoader.loadClass("org.apache.commons.logging.PathableTestSuite"); - assertSame("PathableTestSuite not loaded via child", - testClass.getClassLoader(), thisLoader); - - // test loading of class that is not available - try { - Class noSuchClass = contextLoader.loadClass("no.such.class"); - fail("Class no.such.class is unexpectedly available"); - assertNotNull(noSuchClass); // silence warning about unused var - } catch(ClassNotFoundException ex) { - // ok - } - - // String class classloader is null - Class stringClass = contextLoader.loadClass("java.lang.String"); - assertNull("String class classloader is not null!", - stringClass.getClassLoader()); - } - - /** - * Test that the various flavours of ClassLoader.getResource work as expected. - */ - public void testResource() { - URL resource; - - ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - ClassLoader childLoader = contextLoader.getParent(); - - // getResource where it doesn't exist - resource = childLoader.getResource("nosuchfile"); - assertNull("Non-null URL returned for invalid resource name", resource); - - // getResource where it is accessable only to parent classloader - resource = childLoader.getResource("org/apache/commons/logging/Log.class"); - assertNotNull("Unable to locate Log.class resource", resource); - - // getResource where it is accessable only to child classloader - resource = childLoader.getResource("org/apache/commons/logging/PathableTestSuite.class"); - assertNotNull("Unable to locate PathableTestSuite.class resource", resource); - - // getResource where it is accessable to both classloaders. The one visible - // to the child should be returned. The URL returned will be of form - // jar:file:/x/y.jar!path/to/resource. The filename part should include the jarname - // of form commons-logging-adapters-nnnn.jar, not commons-logging-nnnn.jar - resource = childLoader.getResource("org/apache/commons/logging/impl/Log4JLogger.class"); - assertNotNull("Unable to locate Log4JLogger.class resource", resource); - assertTrue("Incorrect source for Log4JLogger class", - resource.toString().indexOf("/commons-logging-adapters-1.") > 0); - } - - /** - * Test that the various flavours of ClassLoader.getResources work as expected. - */ - public void testResources() throws Exception { - Enumeration resources; - URL[] urls; - - // verify the classloader hierarchy - ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - ClassLoader childLoader = contextLoader.getParent(); - ClassLoader parentLoader = childLoader.getParent(); - ClassLoader bootLoader = parentLoader.getParent(); - assertNull("Unexpected classloader hierarchy", bootLoader); - - // getResources where no instances exist - resources = childLoader.getResources("nosuchfile"); - urls = toURLArray(resources); - assertEquals("Non-null URL returned for invalid resource name", 0, urls.length); - - // getResources where the resource only exists in the parent - resources = childLoader.getResources("org/apache/commons/logging/Log.class"); - urls = toURLArray(resources); - assertEquals("Unexpected number of Log.class resources found", 1, urls.length); - - // getResources where the resource only exists in the child - resources = childLoader.getResources("org/apache/commons/logging/PathableTestSuite.class"); - urls = toURLArray(resources); - assertEquals("Unexpected number of PathableTestSuite.class resources found", 1, urls.length); - - // getResources where the resource exists in both. - // resources should be returned in order (child-resource, parent-resource). - // - // IMPORTANT: due to the fact that in java 1.4 and earlier method - // ClassLoader.getResources is final it isn't possible for PathableClassLoader - // to override this. So even when child-first is enabled the resource order - // is still (parent-resources, child-resources). This test verifies the expected - // behaviour - even though it's not the desired behaviour. - - resources = childLoader.getResources("org/apache/commons/logging/impl/Log4JLogger.class"); - urls = toURLArray(resources); - assertEquals("Unexpected number of Log4JLogger.class resources found", 2, urls.length); - - // There is no gaurantee about the ordering of results returned from getResources - // To make this test portable across JVMs, sort the string to give them a known order - String[] urlsToStrings = new String[2]; - urlsToStrings[0] = urls[0].toString(); - urlsToStrings[1] = urls[1].toString(); - Arrays.sort(urlsToStrings); - assertTrue("Incorrect source for Log4JLogger class", - urlsToStrings[0].indexOf("/commons-logging-1.") > 0); - assertTrue("Incorrect source for Log4JLogger class", - urlsToStrings[1].indexOf("/commons-logging-adapters-1.") > 0); - } - - /** - * Utility method to convert an enumeration-of-URLs into an array of URLs. - */ - private static URL[] toURLArray(Enumeration e) { - ArrayList l = new ArrayList(); - while (e.hasMoreElements()) { - URL u = (URL) e.nextElement(); - l.add(u); - } - URL[] tmp = new URL[l.size()]; - return (URL[]) l.toArray(tmp); - } - - /** - * Test that getResourceAsStream works. - */ - public void testResourceAsStream() throws Exception { - java.io.InputStream is; - - // verify the classloader hierarchy - ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - ClassLoader childLoader = contextLoader.getParent(); - ClassLoader parentLoader = childLoader.getParent(); - ClassLoader bootLoader = parentLoader.getParent(); - assertNull("Unexpected classloader hierarchy", bootLoader); - - // getResourceAsStream where no instances exist - is = childLoader.getResourceAsStream("nosuchfile"); - assertNull("Invalid resource returned non-null stream", is); - - // getResourceAsStream where resource does exist - is = childLoader.getResourceAsStream("org/apache/commons/logging/Log.class"); - assertNotNull("Null returned for valid resource", is); - is.close(); - - // It would be nice to test parent-first ordering here, but that would require - // having a resource with the same name in both the parent and child loaders, - // but with different contents. That's a little tricky to set up so we'll - // skip that for now. - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/pathable/GeneralTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/pathable/GeneralTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/pathable/GeneralTestCase.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/pathable/GeneralTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.logging.pathable; - -import java.net.URL; -import java.net.URLClassLoader; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - -/** - * Tests for the PathableTestSuite class. - */ - -public class GeneralTestCase extends TestCase { - - /** - * Set up a custom classloader hierarchy for this test case. - */ - public static Test suite() throws Exception { - Class thisClass = GeneralTestCase.class; - ClassLoader thisClassLoader = thisClass.getClassLoader(); - - PathableClassLoader loader = new PathableClassLoader(null); - loader.useExplicitLoader("junit.", thisClassLoader); - loader.addLogicalLib("testclasses"); - - // reload this class via the child classloader - Class testClass = loader.loadClass(thisClass.getName()); - - // and return our custom TestSuite class - return new PathableTestSuite(testClass, loader); - } - - /** - * Verify that a certain system property is not set, then set it. - */ - private static void checkAndSetProperties() { - String prop = System.getProperty("no.such.property"); - assertNull("no.such.property is unexpectedly defined", prop); - System.setProperty("no.such.property", "dummy value"); - prop = System.getProperty("no.such.property"); - assertNotNull("no.such.property is unexpectedly undefined", prop); - } - - /** - * Verify that when a test method modifies the system properties they are - * reset before the next test is run. - *

- * This method works in conjunction with testResetProps2. There is no - * way of knowing which test method junit will run first, but it doesn't - * matter; whichever one of them runs first will modify the system properties. - * If the PathableTestSuite isn't resetting the system properties then whichever - * of them runs second will fail. Of course if other methods are run in-between - * then those methods might also fail... - */ - public void testResetProps1() { - checkAndSetProperties(); - } - - /** - * See testResetProps1. - */ - public void testResetProps2() { - checkAndSetProperties(); - } - - /** - * Verify that the context classloader is a custom one, then reset it to - * a non-custom one. - */ - private static void checkAndSetContext() { - ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - assertEquals("ContextLoader is of unexpected type", - contextLoader.getClass().getName(), - PathableClassLoader.class.getName()); - - URL[] noUrls = new URL[0]; - Thread.currentThread().setContextClassLoader(new URLClassLoader(noUrls)); - } - - /** - * Verify that when a test method modifies the context classloader it is - * reset before the next test is run. - *

- * This method works in conjunction with testResetContext2. There is no - * way of knowing which test method junit will run first, but it doesn't - * matter; whichever one of them runs first will modify the contextClassloader. - * If the PathableTestSuite isn't resetting the contextClassLoader then whichever - * of them runs second will fail. Of course if other methods are run in-between - * then those methods might also fail... - */ - public void testResetContext1() { - checkAndSetContext(); - } - - /** - * See testResetContext1. - */ - public void testResetContext2() { - checkAndSetContext(); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/pathable/ParentFirstTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/pathable/ParentFirstTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/pathable/ParentFirstTestCase.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/pathable/ParentFirstTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,308 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.logging.pathable; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Set; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - -/** - * Tests for the PathableTestSuite and PathableClassLoader functionality, - * where lookup order for the PathableClassLoader is parent-first. - *

- * These tests assume: - *

    - *
  • junit is in system classpath - *
  • nothing else is in system classpath - *
- */ - -public class ParentFirstTestCase extends TestCase { - - /** - * Set up a custom classloader hierarchy for this test case. - * The hierarchy is: - *
    - *
  • contextloader: parent-first. - *
  • childloader: parent-first, used to load test case. - *
  • parentloader: parent-first, parent is the bootclassloader. - *
- */ - public static Test suite() throws Exception { - Class thisClass = ParentFirstTestCase.class; - ClassLoader thisClassLoader = thisClass.getClassLoader(); - - // Make the parent a direct child of the bootloader to hide all - // other classes in the system classpath - PathableClassLoader parent = new PathableClassLoader(null); - - // Make the junit classes visible as a special case, as junit - // won't be able to call this class at all without this. The - // junit classes must be visible from the classloader that loaded - // this class, so use that as the source for future access to classes - // from the junit package. - parent.useExplicitLoader("junit.", thisClassLoader); - - // make the commons-logging.jar classes visible via the parent - parent.addLogicalLib("commons-logging"); - - // create a child classloader to load the test case through - PathableClassLoader child = new PathableClassLoader(parent); - - // obviously, the child classloader needs to have the test classes - // in its path! - child.addLogicalLib("testclasses"); - child.addLogicalLib("commons-logging-adapters"); - - // create a third classloader to be the context classloader. - PathableClassLoader context = new PathableClassLoader(child); - - // reload this class via the child classloader - Class testClass = child.loadClass(thisClass.getName()); - - // and return our custom TestSuite class - return new PathableTestSuite(testClass, context); - } - - /** - * Utility method to return the set of all classloaders in the - * parent chain starting from the one that loaded the class for - * this object instance. - */ - private Set getAncestorCLs() { - Set s = new HashSet(); - ClassLoader cl = this.getClass().getClassLoader(); - while (cl != null) { - s.add(cl); - cl = cl.getParent(); - } - return s; - } - - /** - * Test that the classloader hierarchy is as expected, and that - * calling loadClass() on various classloaders works as expected. - * Note that for this test case, parent-first classloading is - * in effect. - */ - public void testPaths() throws Exception { - // the context classloader is not expected to be null - ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - assertNotNull("Context classloader is null", contextLoader); - assertEquals("Context classloader has unexpected type", - PathableClassLoader.class.getName(), - contextLoader.getClass().getName()); - - // the classloader that loaded this class is obviously not null - ClassLoader thisLoader = this.getClass().getClassLoader(); - assertNotNull("thisLoader is null", thisLoader); - assertEquals("thisLoader has unexpected type", - PathableClassLoader.class.getName(), - thisLoader.getClass().getName()); - - // the suite method specified that the context classloader's parent - // is the loader that loaded this test case. - assertSame("Context classloader is not child of thisLoader", - thisLoader, contextLoader.getParent()); - - // thisLoader's parent should be available - ClassLoader parentLoader = thisLoader.getParent(); - assertNotNull("Parent classloader is null", parentLoader); - assertEquals("Parent classloader has unexpected type", - PathableClassLoader.class.getName(), - parentLoader.getClass().getName()); - - // parent should have a parent of null - assertNull("Parent classloader has non-null parent", parentLoader.getParent()); - - // getSystemClassloader is not a PathableClassLoader; it's of a - // built-in type. This also verifies that system classloader is none of - // (context, child, parent). - ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); - assertNotNull("System classloader is null", systemLoader); - assertFalse("System classloader has unexpected type", - PathableClassLoader.class.getName().equals( - systemLoader.getClass().getName())); - - // junit classes should be visible; their classloader is not - // in the hierarchy of parent classloaders for this class, - // though it is accessable due to trickery in the PathableClassLoader. - Class junitTest = contextLoader.loadClass("junit.framework.Test"); - Set ancestorCLs = getAncestorCLs(); - assertFalse("Junit not loaded by ancestor classloader", - ancestorCLs.contains(junitTest.getClassLoader())); - - // jcl api classes should be visible only via the parent - Class logClass = contextLoader.loadClass("org.apache.commons.logging.Log"); - assertSame("Log class not loaded via parent", - logClass.getClassLoader(), parentLoader); - - // jcl adapter classes should be visible via both parent and child. However - // as the classloaders are parent-first we should see the parent one. - Class log4jClass = contextLoader.loadClass("org.apache.commons.logging.impl.Log4JLogger"); - assertSame("Log4JLogger not loaded via parent", - log4jClass.getClassLoader(), parentLoader); - - // test classes should be visible via the child only - Class testClass = contextLoader.loadClass("org.apache.commons.logging.PathableTestSuite"); - assertSame("PathableTestSuite not loaded via child", - testClass.getClassLoader(), thisLoader); - - // test loading of class that is not available - try { - Class noSuchClass = contextLoader.loadClass("no.such.class"); - fail("Class no.such.class is unexpectedly available"); - assertNotNull(noSuchClass); // silence warning about unused var - } catch(ClassNotFoundException ex) { - // ok - } - - // String class classloader is null - Class stringClass = contextLoader.loadClass("java.lang.String"); - assertNull("String class classloader is not null!", - stringClass.getClassLoader()); - } - - /** - * Test that the various flavours of ClassLoader.getResource work as expected. - */ - public void testResource() { - URL resource; - - ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - ClassLoader childLoader = contextLoader.getParent(); - - // getResource where it doesn't exist - resource = childLoader.getResource("nosuchfile"); - assertNull("Non-null URL returned for invalid resource name", resource); - - // getResource where it is accessable only to parent classloader - resource = childLoader.getResource("org/apache/commons/logging/Log.class"); - assertNotNull("Unable to locate Log.class resource", resource); - - // getResource where it is accessable only to child classloader - resource = childLoader.getResource("org/apache/commons/logging/PathableTestSuite.class"); - assertNotNull("Unable to locate PathableTestSuite.class resource", resource); - - // getResource where it is accessable to both classloaders. The one visible - // to the parent should be returned. The URL returned will be of form - // jar:file:/x/y.jar!path/to/resource. The filename part should include the jarname - // of form commons-logging-nnnn.jar, not commons-logging-adapters-nnnn.jar - resource = childLoader.getResource("org/apache/commons/logging/impl/Log4JLogger.class"); - assertNotNull("Unable to locate Log4JLogger.class resource", resource); - assertTrue("Incorrect source for Log4JLogger class", - resource.toString().indexOf("/commons-logging-1.") > 0); - } - - /** - * Test that the various flavours of ClassLoader.getResources work as expected. - */ - public void testResources() throws Exception { - Enumeration resources; - URL[] urls; - - // verify the classloader hierarchy - ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - ClassLoader childLoader = contextLoader.getParent(); - ClassLoader parentLoader = childLoader.getParent(); - ClassLoader bootLoader = parentLoader.getParent(); - assertNull("Unexpected classloader hierarchy", bootLoader); - - // getResources where no instances exist - resources = childLoader.getResources("nosuchfile"); - urls = toURLArray(resources); - assertEquals("Non-null URL returned for invalid resource name", 0, urls.length); - - // getResources where the resource only exists in the parent - resources = childLoader.getResources("org/apache/commons/logging/Log.class"); - urls = toURLArray(resources); - assertEquals("Unexpected number of Log.class resources found", 1, urls.length); - - // getResources where the resource only exists in the child - resources = childLoader.getResources("org/apache/commons/logging/PathableTestSuite.class"); - urls = toURLArray(resources); - assertEquals("Unexpected number of PathableTestSuite.class resources found", 1, urls.length); - - // getResources where the resource exists in both. - // resources should be returned in order (parent-resource, child-resource) - resources = childLoader.getResources("org/apache/commons/logging/impl/Log4JLogger.class"); - urls = toURLArray(resources); - assertEquals("Unexpected number of Log4JLogger.class resources found", 2, urls.length); - - // There is no gaurantee about the ordering of results returned from getResources - // To make this test portable across JVMs, sort the string to give them a known order - String[] urlsToStrings = new String[2]; - urlsToStrings[0] = urls[0].toString(); - urlsToStrings[1] = urls[1].toString(); - Arrays.sort(urlsToStrings); - assertTrue("Incorrect source for Log4JLogger class", - urlsToStrings[0].indexOf("/commons-logging-1.") > 0); - assertTrue("Incorrect source for Log4JLogger class", - urlsToStrings[1].indexOf("/commons-logging-adapters-1.") > 0); - - } - - /** - * Utility method to convert an enumeration-of-URLs into an array of URLs. - */ - private static URL[] toURLArray(Enumeration e) { - ArrayList l = new ArrayList(); - while (e.hasMoreElements()) { - URL u = (URL) e.nextElement(); - l.add(u); - } - URL[] tmp = new URL[l.size()]; - return (URL[]) l.toArray(tmp); - } - - /** - * Test that getResourceAsStream works. - */ - public void testResourceAsStream() throws Exception { - java.io.InputStream is; - - // verify the classloader hierarchy - ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - ClassLoader childLoader = contextLoader.getParent(); - ClassLoader parentLoader = childLoader.getParent(); - ClassLoader bootLoader = parentLoader.getParent(); - assertNull("Unexpected classloader hierarchy", bootLoader); - - // getResourceAsStream where no instances exist - is = childLoader.getResourceAsStream("nosuchfile"); - assertNull("Invalid resource returned non-null stream", is); - - // getResourceAsStream where resource does exist - is = childLoader.getResourceAsStream("org/apache/commons/logging/Log.class"); - assertNotNull("Null returned for valid resource", is); - is.close(); - - // It would be nice to test parent-first ordering here, but that would require - // having a resource with the same name in both the parent and child loaders, - // but with different contents. That's a little tricky to set up so we'll - // skip that for now. - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/security/MockSecurityManager.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/security/MockSecurityManager.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/security/MockSecurityManager.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/security/MockSecurityManager.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.commons.logging.security; - -import java.io.FilePermission; -import java.security.Permission; -import java.security.Permissions; - - -/** - * Custom implementation of a security manager, so we can control the - * security environment for tests in this package. - */ -public class MockSecurityManager extends SecurityManager { - - private Permissions permissions = new Permissions(); - private static final Permission setSecurityManagerPerm = - new RuntimePermission("setSecurityManager"); - - private int untrustedCodeCount = 0; - - public MockSecurityManager() { - permissions.add(setSecurityManagerPerm); - } - - /** - * Define the set of permissions to be granted to classes in the o.a.c.l package, - * but NOT to unit-test classes in o.a.c.l.security package. - */ - public void addPermission(Permission p) { - permissions.add(p); - } - - /** - * This returns the number of times that a check of a permission failed - * due to stack-walking tracing up into untrusted code. Any non-zero - * value indicates a bug in JCL, ie a situation where code was not - * correctly wrapped in an AccessController block. The result of such a - * bug is that signing JCL is not sufficient to allow JCL to perform - * the operation; the caller would need to be signed too. - */ - public int getUntrustedCodeCount() { - return untrustedCodeCount; - } - - public void checkPermission(Permission p) throws SecurityException { - if (setSecurityManagerPerm.implies(p)) { - // ok, allow this; we don't want to block any calls to setSecurityManager - // otherwise this custom security manager cannot be reset to the original. - // System.out.println("setSecurityManager: granted"); - return; - } - - // Allow read-only access to files, as this is needed to load classes! - // Ideally, we would limit this to just .class and .jar files. - if (p instanceof FilePermission) { - FilePermission fp = (FilePermission) p; - if (fp.getActions().equals("read")) { - // System.out.println("Permit read of files"); - return; - } - } - - System.out.println("\n\ntesting permission:" + p.getClass() + ":"+ p); - - Exception e = new Exception(); - e.fillInStackTrace(); - StackTraceElement[] stack = e.getStackTrace(); - - // scan the call stack from most recent to oldest. - // start at 1 to skip the entry in the stack for this method - for(int i=1; i - * This class has only one unit test, as we are (in part) checking behaviour in - * the static block of the LogFactory class. As that class cannot be unloaded after - * being loaded into a classloader, the only workaround is to use the - * PathableClassLoader approach to ensure each test is run in its own - * classloader, and use a separate testcase class for each test. - */ -public class SecurityAllowedTestCase extends TestCase -{ - private SecurityManager oldSecMgr; - - // Dummy special hashtable, so we can tell JCL to use this instead of - // the standard one. - public static class CustomHashtable extends Hashtable { - } - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - PathableClassLoader parent = new PathableClassLoader(null); - parent.useExplicitLoader("junit.", Test.class.getClassLoader()); - parent.addLogicalLib("commons-logging"); - parent.addLogicalLib("testclasses"); - - Class testClass = parent.loadClass( - "org.apache.commons.logging.security.SecurityAllowedTestCase"); - return new PathableTestSuite(testClass, parent); - } - - public void setUp() { - // save security manager so it can be restored in tearDown - oldSecMgr = System.getSecurityManager(); - } - - public void tearDown() { - // Restore, so other tests don't get stuffed up if a test - // sets a custom security manager. - System.setSecurityManager(oldSecMgr); - } - - /** - * Test what happens when JCL is run with all permissions enabled. Custom - * overrides should take effect. - */ - public void testAllAllowed() { - System.setProperty( - LogFactory.HASHTABLE_IMPLEMENTATION_PROPERTY, - CustomHashtable.class.getName()); - MockSecurityManager mySecurityManager = new MockSecurityManager(); - mySecurityManager.addPermission(new AllPermission()); - System.setSecurityManager(mySecurityManager); - - try { - // Use reflection so that we can control exactly when the static - // initialiser for the LogFactory class is executed. - Class c = this.getClass().getClassLoader().loadClass( - "org.apache.commons.logging.LogFactory"); - Method m = c.getMethod("getLog", new Class[] {Class.class}); - Log log = (Log) m.invoke(null, new Object[] {this.getClass()}); - - // Check whether we had any security exceptions so far (which were - // caught by the code). We should not, as every secure operation - // should be wrapped in an AccessController. Any security exceptions - // indicate a path that is missing an appropriate AccessController. - // - // We don't wait until after the log.info call to get this count - // because java.util.logging tries to load a resource bundle, which - // requires permission accessClassInPackage. JCL explicitly does not - // wrap calls to log methods in AccessControllers because writes to - // a log file *should* only be permitted if the original caller is - // trusted to access that file. - int untrustedCodeCount = mySecurityManager.getUntrustedCodeCount(); - log.info("testing"); - - // check that the default map implementation was loaded, as JCL was - // forbidden from reading the HASHTABLE_IMPLEMENTATION_PROPERTY property. - System.setSecurityManager(null); - Field factoryField = c.getDeclaredField("factories"); - factoryField.setAccessible(true); - Object factoryTable = factoryField.get(null); - assertNotNull(factoryTable); - assertEquals(CustomHashtable.class.getName(), factoryTable.getClass().getName()); - - assertEquals(0, untrustedCodeCount); - } catch(Throwable t) { - // Restore original security manager so output can be generated; the - // PrintWriter constructor tries to read the line.separator - // system property. - System.setSecurityManager(oldSecMgr); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - t.printStackTrace(pw); - fail("Unexpected exception:" + t.getMessage() + ":" + sw.toString()); - } - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/security/SecurityForbiddenTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/security/SecurityForbiddenTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/security/SecurityForbiddenTestCase.java 2007-11-21 23:27:51.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/security/SecurityForbiddenTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,130 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.commons.logging.security; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Hashtable; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - -/** - * Tests for logging with a security policy that forbids JCL access to anything. - *

- * Performing tests with security permissions disabled is tricky, as building error - * messages on failure requires certain security permissions. If the security manager - * blocks these, then the test can fail without the error messages being output. - *

- * This class has only one unit test, as we are (in part) checking behaviour in - * the static block of the LogFactory class. As that class cannot be unloaded after - * being loaded into a classloader, the only workaround is to use the - * PathableClassLoader approach to ensure each test is run in its own - * classloader, and use a separate testcase class for each test. - */ -public class SecurityForbiddenTestCase extends TestCase -{ - private SecurityManager oldSecMgr; - - // Dummy special hashtable, so we can tell JCL to use this instead of - // the standard one. - public static class CustomHashtable extends Hashtable { - } - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - PathableClassLoader parent = new PathableClassLoader(null); - parent.useExplicitLoader("junit.", Test.class.getClassLoader()); - parent.addLogicalLib("commons-logging"); - parent.addLogicalLib("testclasses"); - - Class testClass = parent.loadClass( - "org.apache.commons.logging.security.SecurityForbiddenTestCase"); - return new PathableTestSuite(testClass, parent); - } - - public void setUp() { - // save security manager so it can be restored in tearDown - oldSecMgr = System.getSecurityManager(); - } - - public void tearDown() { - // Restore, so other tests don't get stuffed up if a test - // sets a custom security manager. - System.setSecurityManager(oldSecMgr); - } - - /** - * Test what happens when JCL is run with absolutely no security - * priveleges at all, including reading system properties. Everything - * should fall back to the built-in defaults. - */ - public void testAllForbidden() { - System.setProperty( - LogFactory.HASHTABLE_IMPLEMENTATION_PROPERTY, - CustomHashtable.class.getName()); - MockSecurityManager mySecurityManager = new MockSecurityManager(); - System.setSecurityManager(mySecurityManager); - - try { - // Use reflection so that we can control exactly when the static - // initialiser for the LogFactory class is executed. - Class c = this.getClass().getClassLoader().loadClass( - "org.apache.commons.logging.LogFactory"); - Method m = c.getMethod("getLog", new Class[] {Class.class}); - Log log = (Log) m.invoke(null, new Object[] {this.getClass()}); - log.info("testing"); - - // check that the default map implementation was loaded, as JCL was - // forbidden from reading the HASHTABLE_IMPLEMENTATION_PROPERTY property. - // - // The default is either the java Hashtable class (java < 1.2) or the - // JCL WeakHashtable (java >= 1.3). - System.setSecurityManager(oldSecMgr); - Field factoryField = c.getDeclaredField("factories"); - factoryField.setAccessible(true); - Object factoryTable = factoryField.get(null); - assertNotNull(factoryTable); - String ftClassName = factoryTable.getClass().getName(); - assertTrue("Custom hashtable unexpectedly used", - !CustomHashtable.class.getName().equals(ftClassName)); - - assertEquals(0, mySecurityManager.getUntrustedCodeCount()); - } catch(Throwable t) { - // Restore original security manager so output can be generated; the - // PrintWriter constructor tries to read the line.separator - // system property. - System.setSecurityManager(oldSecMgr); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - t.printStackTrace(pw); - fail("Unexpected exception:" + t.getMessage() + ":" + sw.toString()); - } - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/servlet/BasicServletTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/servlet/BasicServletTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/servlet/BasicServletTestCase.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/servlet/BasicServletTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.servlet; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; -import org.apache.commons.logging.impl.ServletContextCleaner; - - -/** - * Tests for ServletContextCleaner utility class. - */ - -public class BasicServletTestCase extends TestCase { - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - // LogFactory in parent - // LogFactory in child (loads test) - // LogFactory in tccl - // - // Having the test loaded via a loader above the tccl emulates the situation - // where a web.xml file specifies ServletContextCleaner as a listener, and - // that class is deployed via a shared classloader. - - PathableClassLoader parent = new PathableClassLoader(null); - parent.useExplicitLoader("junit.", Test.class.getClassLoader()); - parent.addLogicalLib("commons-logging"); - parent.addLogicalLib("servlet-api"); - - PathableClassLoader child = new PathableClassLoader(parent); - child.setParentFirst(false); - child.addLogicalLib("commons-logging"); - child.addLogicalLib("testclasses"); - - PathableClassLoader tccl = new PathableClassLoader(child); - tccl.setParentFirst(false); - tccl.addLogicalLib("commons-logging"); - - Class testClass = child.loadClass(BasicServletTestCase.class.getName()); - return new PathableTestSuite(testClass, tccl); - } - - /** - * Test that calling ServletContextCleaner.contextDestroyed doesn't crash. - * Testing anything else is rather difficult... - */ - public void testBasics() { - ServletContextCleaner scc = new ServletContextCleaner(); - scc.contextDestroyed(null); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/simple/CustomConfigTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/simple/CustomConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/simple/CustomConfigTestCase.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/simple/CustomConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,277 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.simple; - - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import junit.framework.Test; - -import org.apache.commons.logging.DummyException; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; -import org.apache.commons.logging.impl.SimpleLog; - - -/** - *

TestCase for simple logging when running with custom configuration - * properties.

- * - * @author Craig R. McClanahan - * @version $Revision: 563165 $ $Date: 2007-08-06 17:08:05 +0200 $ - */ -public class CustomConfigTestCase extends DefaultConfigTestCase { - - - // ----------------------------------------------------- Instance Variables - - - /** - *

The expected log records.

- */ - protected List expected; - - - /** - *

The message levels that should have been logged.

- */ - /* - protected Level testLevels[] = - { Level.FINE, Level.INFO, Level.WARNING, Level.SEVERE, Level.SEVERE }; - */ - - - /** - *

The message strings that should have been logged.

- */ - protected String testMessages[] = - { "debug", "info", "warn", "error", "fatal" }; - - - // ------------------------------------------- JUnit Infrastructure Methods - - /** - * Set system properties that will control the LogFactory/Log objects - * when they are created. Subclasses can override this method to - * define properties that suit them. - */ - public void setProperties() { - System.setProperty( - "org.apache.commons.logging.Log", - "org.apache.commons.logging.simple.DecoratedSimpleLog"); - System.setProperty( - "org.apache.commons.logging.simplelog.defaultlog", - "debug"); - } - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - LogFactory.releaseAll(); - setProperties(); - expected = new ArrayList(); - setUpFactory(); - setUpLog("DecoratedLogger"); - } - - - /** - * Return the tests included in this test suite. - *

- * We need to use a PathableClassLoader here because the SimpleLog class - * is a pile of junk and chock-full of static variables. Any other test - * (like simple.CustomConfigTestCase) that has used the SimpleLog class - * will already have caused it to do once-only initialisation that we - * can't reset, even by calling LogFactory.releaseAll, because of those - * ugly statics. The only clean solution is to load a clean copy of - * commons-logging including SimpleLog via a nice clean classloader. - * Or we could fix SimpleLog to be sane... - */ - public static Test suite() throws Exception { - Class thisClass = CustomConfigTestCase.class; - - PathableClassLoader loader = new PathableClassLoader(null); - loader.useExplicitLoader("junit.", Test.class.getClassLoader()); - loader.addLogicalLib("testclasses"); - loader.addLogicalLib("commons-logging"); - - Class testClass = loader.loadClass(thisClass.getName()); - return new PathableTestSuite(testClass, loader); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - super.tearDown(); - expected = null; - } - - - // ----------------------------------------------------------- Test Methods - - - // Test logging message strings with exceptions - public void testExceptionMessages() throws Exception { - - ((DecoratedSimpleLog) log).clearCache(); - logExceptionMessages(); - checkExpected(); - - } - - - // Test logging plain message strings - public void testPlainMessages() throws Exception { - - ((DecoratedSimpleLog) log).clearCache(); - logPlainMessages(); - checkExpected(); - - } - - - // Test Serializability of standard instance - public void testSerializable() throws Exception { - - ((DecoratedSimpleLog) log).clearCache(); - logPlainMessages(); - super.testSerializable(); - logExceptionMessages(); - checkExpected(); - - } - - - // -------------------------------------------------------- Support Methods - - - // Check the decorated log instance - protected void checkDecorated() { - - assertNotNull("Log exists", log); - assertEquals("Log class", - "org.apache.commons.logging.simple.DecoratedSimpleLog", - log.getClass().getName()); - - // Can we call level checkers with no exceptions? - assertTrue(log.isDebugEnabled()); - assertTrue(log.isErrorEnabled()); - assertTrue(log.isFatalEnabled()); - assertTrue(log.isInfoEnabled()); - assertTrue(!log.isTraceEnabled()); - assertTrue(log.isWarnEnabled()); - - // Can we retrieve the current log level? - assertEquals(SimpleLog.LOG_LEVEL_DEBUG, ((SimpleLog) log).getLevel()); - - // Can we validate the extra exposed properties? - checkDecoratedDateTime(); - assertEquals("DecoratedLogger", - ((DecoratedSimpleLog) log).getLogName()); - checkShowDateTime(); - assertTrue(((DecoratedSimpleLog) log).getShowShortName()); - - } - - /** Hook for subclassses */ - protected void checkShowDateTime() { - assertTrue(!((DecoratedSimpleLog) log).getShowDateTime()); - } - - /** Hook for subclasses */ - protected void checkDecoratedDateTime() { - assertEquals("yyyy/MM/dd HH:mm:ss:SSS zzz", - ((DecoratedSimpleLog) log).getDateTimeFormat()); - } - - - - // Check the actual log records against the expected ones - protected void checkExpected() { - - List acts = ((DecoratedSimpleLog) log).getCache(); - Iterator exps = expected.iterator(); - int n = 0; - while (exps.hasNext()) { - LogRecord exp = (LogRecord) exps.next(); - LogRecord act = (LogRecord) acts.get(n++); - assertEquals("Row " + n + " type", exp.type, act.type); - assertEquals("Row " + n + " message", exp.message, act.message); - assertEquals("Row " + n + " throwable", exp.t, act.t); - } - - } - - - // Check the standard log instance - protected void checkStandard() { - - checkDecorated(); - - } - - - // Log the messages with exceptions - protected void logExceptionMessages() { - - // Generate log records - Throwable t = new DummyException(); - log.trace("trace", t); // Should not actually get logged - log.debug("debug", t); - log.info("info", t); - log.warn("warn", t); - log.error("error", t); - log.fatal("fatal", t); - - // Record the log records we expect - expected.add(new LogRecord(SimpleLog.LOG_LEVEL_DEBUG, "debug", t)); - expected.add(new LogRecord(SimpleLog.LOG_LEVEL_INFO, "info", t)); - expected.add(new LogRecord(SimpleLog.LOG_LEVEL_WARN, "warn", t)); - expected.add(new LogRecord(SimpleLog.LOG_LEVEL_ERROR, "error", t)); - expected.add(new LogRecord(SimpleLog.LOG_LEVEL_FATAL, "fatal", t)); - - } - - - // Log the plain messages - protected void logPlainMessages() { - - // Generate log records - log.trace("trace"); // Should not actually get logged - log.debug("debug"); - log.info("info"); - log.warn("warn"); - log.error("error"); - log.fatal("fatal"); - - // Record the log records we expect - expected.add(new LogRecord(SimpleLog.LOG_LEVEL_DEBUG, "debug", null)); - expected.add(new LogRecord(SimpleLog.LOG_LEVEL_INFO, "info", null)); - expected.add(new LogRecord(SimpleLog.LOG_LEVEL_WARN, "warn", null)); - expected.add(new LogRecord(SimpleLog.LOG_LEVEL_ERROR, "error", null)); - expected.add(new LogRecord(SimpleLog.LOG_LEVEL_FATAL, "fatal", null)); - - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/simple/DateTimeCustomConfigTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/simple/DateTimeCustomConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/simple/DateTimeCustomConfigTestCase.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/simple/DateTimeCustomConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.simple; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -import junit.framework.Test; - -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - * Tests custom date time format configuration - */ -public class DateTimeCustomConfigTestCase extends CustomConfigTestCase { - - // ----------------------------------------------------------- Constructors - - /** - * Return the tests included in this test suite. - *

- * We need to use a PathableClassLoader here because the SimpleLog class - * is a pile of junk and chock-full of static variables. Any other test - * (like simple.CustomConfigTestCase) that has used the SimpleLog class - * will already have caused it to do once-only initialisation that we - * can't reset, even by calling LogFactory.releaseAll, because of those - * ugly statics. The only clean solution is to load a clean copy of - * commons-logging including SimpleLog via a nice clean classloader. - * Or we could fix SimpleLog to be sane... - */ - public static Test suite() throws Exception { - Class thisClass = DateTimeCustomConfigTestCase.class; - - PathableClassLoader loader = new PathableClassLoader(null); - loader.useExplicitLoader("junit.", Test.class.getClassLoader()); - loader.addLogicalLib("testclasses"); - loader.addLogicalLib("commons-logging"); - - Class testClass = loader.loadClass(thisClass.getName()); - return new PathableTestSuite(testClass, loader); - } - - - /** - * Set up system properties required by this unit test. Here, we - * set up the props defined in the parent class setProperties method, - * and add a few to configure the SimpleLog class date/time output. - */ - public void setProperties() { - super.setProperties(); - - System.setProperty( - "org.apache.commons.logging.simplelog.dateTimeFormat", - "dd.mm.yyyy"); - System.setProperty( - "org.apache.commons.logging.simplelog.showdatetime", - "true"); - } - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - super.setUp(); - } - - - // ----------------------------------------------------------- Methods - - /** Checks that the date time format has been successfully set */ - protected void checkDecoratedDateTime() { - assertEquals("Expected date format to be set", "dd.mm.yyyy", - ((DecoratedSimpleLog) log).getDateTimeFormat()); - - // try the formatter - Date now = new Date(); - DateFormat formatter = ((DecoratedSimpleLog) log).getDateTimeFormatter(); - SimpleDateFormat sampleFormatter = new SimpleDateFormat("dd.mm.yyyy"); - assertEquals("Date should be formatters to pattern dd.mm.yyyy", sampleFormatter.format(now), formatter.format(now)); - } - - /** Hook for subclassses */ - protected void checkShowDateTime() { - assertTrue(((DecoratedSimpleLog) log).getShowDateTime()); - } - -} \ No newline at end of file diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/simple/DecoratedSimpleLog.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/simple/DecoratedSimpleLog.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/simple/DecoratedSimpleLog.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/simple/DecoratedSimpleLog.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.simple; - - -import java.util.ArrayList; -import java.util.List; -import java.text.DateFormat; -import org.apache.commons.logging.impl.SimpleLog; - - -/** - *

Decorated instance of SimpleLog to expose internal state and - * support buffered output.

- */ - -public class DecoratedSimpleLog extends SimpleLog { - - - // ------------------------------------------------------------ Constructor - - - public DecoratedSimpleLog(String name) { - super(name); - } - - - // ------------------------------------------------------------- Properties - - public DateFormat getDateTimeFormatter() { - return (dateFormatter); - } - - - public String getDateTimeFormat() { - return (dateTimeFormat); - } - - - public String getLogName() { - return (logName); - } - - - public boolean getShowDateTime() { - return (showDateTime); - } - - - public boolean getShowShortName() { - return (showShortName); - } - - - // ------------------------------------------------------- Protected Methods - - - // Cache logged messages - protected void log(int type, Object message, Throwable t) { - - super.log(type, message, t); - cache.add(new LogRecord(type, message, t)); - - } - - - // ---------------------------------------------------------- Public Methods - - - // Cache of logged records - protected ArrayList cache = new ArrayList(); - - - // Clear cache - public void clearCache() { - cache.clear(); - } - - - // Return cache - public List getCache() { - return (this.cache); - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/simple/DefaultConfigTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/simple/DefaultConfigTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/simple/DefaultConfigTestCase.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/simple/DefaultConfigTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,249 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.simple; - - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; -import org.apache.commons.logging.impl.SimpleLog; - - -/** - *

TestCase for simple logging when running with zero configuration - * other than selecting the SimpleLog implementation.

- * - * @author Craig R. McClanahan - * @version $Revision: 425249 $ $Date: 2006-07-25 03:30:16 +0200 (ti, 25 jul 2006) $ - */ - -public class DefaultConfigTestCase extends TestCase { - - - // ----------------------------------------------------- Instance Variables - - - /** - *

The {@link LogFactory} implementation we have selected.

- */ - protected LogFactory factory = null; - - - /** - *

The {@link Log} implementation we have selected.

- */ - protected Log log = null; - - - // ------------------------------------------- JUnit Infrastructure Methods - - - /** - * Return the tests included in this test suite. - *

- * We need to use a PathableClassLoader here because the SimpleLog class - * is a pile of junk and chock-full of static variables. Any other test - * (like simple.CustomConfigTestCase) that has used the SimpleLog class - * will already have caused it to do once-only initialisation that we - * can't reset, even by calling LogFactory.releaseAll, because of those - * ugly statics. The only clean solution is to load a clean copy of - * commons-logging including SimpleLog via a nice clean classloader. - * Or we could fix SimpleLog to be sane... - */ - public static Test suite() throws Exception { - Class thisClass = DefaultConfigTestCase.class; - - PathableClassLoader loader = new PathableClassLoader(null); - loader.useExplicitLoader("junit.", Test.class.getClassLoader()); - loader.addLogicalLib("testclasses"); - loader.addLogicalLib("commons-logging"); - - Class testClass = loader.loadClass(thisClass.getName()); - return new PathableTestSuite(testClass, loader); - } - - /** - * Set system properties that will control the LogFactory/Log objects - * when they are created. Subclasses can override this method to - * define properties that suit them. - */ - public void setProperties() { - System.setProperty( - "org.apache.commons.logging.Log", - "org.apache.commons.logging.impl.SimpleLog"); - } - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - LogFactory.releaseAll(); - setProperties(); - setUpFactory(); - setUpLog("TestLogger"); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - log = null; - factory = null; - LogFactory.releaseAll(); - } - - - // ----------------------------------------------------------- Test Methods - - - // Test pristine DecoratedSimpleLog instance - public void testPristineDecorated() { - - setUpDecorated("DecoratedLogger"); - checkDecorated(); - - } - - - // Test pristine Log instance - public void testPristineLog() { - - checkStandard(); - - } - - - // Test pristine LogFactory instance - public void testPristineFactory() { - - assertNotNull("LogFactory exists", factory); - assertEquals("LogFactory class", - "org.apache.commons.logging.impl.LogFactoryImpl", - factory.getClass().getName()); - - String names[] = factory.getAttributeNames(); - assertNotNull("Names exists", names); - assertEquals("Names empty", 0, names.length); - - } - - - // Test Serializability of standard instance - public void testSerializable() throws Exception { - - // Serialize and deserialize the instance - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(log); - oos.close(); - ByteArrayInputStream bais = - new ByteArrayInputStream(baos.toByteArray()); - ObjectInputStream ois = new ObjectInputStream(bais); - log = (Log) ois.readObject(); - ois.close(); - - // Check the characteristics of the resulting object - checkStandard(); - - } - - - // -------------------------------------------------------- Support Methods - - - - // Check the decorated log instance - protected void checkDecorated() { - - assertNotNull("Log exists", log); - assertEquals("Log class", - "org.apache.commons.logging.simple.DecoratedSimpleLog", - log.getClass().getName()); - - // Can we call level checkers with no exceptions? - assertTrue(!log.isDebugEnabled()); - assertTrue(log.isErrorEnabled()); - assertTrue(log.isFatalEnabled()); - assertTrue(log.isInfoEnabled()); - assertTrue(!log.isTraceEnabled()); - assertTrue(log.isWarnEnabled()); - - // Can we retrieve the current log level? - assertEquals(SimpleLog.LOG_LEVEL_INFO, ((SimpleLog) log).getLevel()); - - // Can we validate the extra exposed properties? - assertEquals("yyyy/MM/dd HH:mm:ss:SSS zzz", - ((DecoratedSimpleLog) log).getDateTimeFormat()); - assertEquals("DecoratedLogger", - ((DecoratedSimpleLog) log).getLogName()); - assertTrue(!((DecoratedSimpleLog) log).getShowDateTime()); - assertTrue(((DecoratedSimpleLog) log).getShowShortName()); - - } - - - // Check the standard log instance - protected void checkStandard() { - - assertNotNull("Log exists", log); - assertEquals("Log class", - "org.apache.commons.logging.impl.SimpleLog", - log.getClass().getName()); - - // Can we call level checkers with no exceptions? - assertTrue(!log.isDebugEnabled()); - assertTrue(log.isErrorEnabled()); - assertTrue(log.isFatalEnabled()); - assertTrue(log.isInfoEnabled()); - assertTrue(!log.isTraceEnabled()); - assertTrue(log.isWarnEnabled()); - - // Can we retrieve the current log level? - assertEquals(SimpleLog.LOG_LEVEL_INFO, ((SimpleLog) log).getLevel()); - - } - - - // Set up decorated log instance - protected void setUpDecorated(String name) { - log = new DecoratedSimpleLog(name); - } - - - // Set up factory instance - protected void setUpFactory() throws Exception { - factory = LogFactory.getFactory(); - } - - - // Set up log instance - protected void setUpLog(String name) throws Exception { - log = LogFactory.getLog(name); - } - - -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/simple/LogRecord.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/simple/LogRecord.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/simple/LogRecord.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/simple/LogRecord.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.simple; - - -import java.io.Serializable; - - -public class LogRecord implements Serializable { - - - public LogRecord(int type, Object message, Throwable t) { - this.type = type; - this.message = message; - this.t = t; - } - - public int type; - public Object message; - public Throwable t; - -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/BadTCCLTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/BadTCCLTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/BadTCCLTestCase.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/BadTCCLTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.logging.tccl; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - -import junit.framework.Test; -import junit.framework.TestCase; - -/** - * Simulates the case when TCCL is badly set and cannot load JCL. - */ -public class BadTCCLTestCase extends TestCase { - - public static Test suite() throws Exception { - PathableClassLoader contextClassLoader = new PathableClassLoader(null); - contextClassLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); - PathableTestSuite suite = new PathableTestSuite(BadTCCLTestCase.class, contextClassLoader); - return suite; - } - - // test methods - - /** - * This test just tests that a log implementation can be found - * by the LogFactory. - */ - public void testGetLog() { - Log log = LogFactory.getLog(BadTCCLTestCase.class); - log.debug("Hello, Mum"); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/NullTCCLTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/NullTCCLTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/NullTCCLTestCase.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/NullTCCLTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.logging.tccl; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableTestSuite; - -import junit.framework.Test; -import junit.framework.TestCase; - -/** - * Simulates the case when TCCL is set to NULL. - */ -public class NullTCCLTestCase extends TestCase { - - public static Test suite() throws Exception {; - PathableTestSuite suite = new PathableTestSuite(NullTCCLTestCase.class, null); - return suite; - } - - // test methods - - /** - * This test just tests that a log implementation can be found - * by the LogFactory. - */ - public void testGetLog() { - Log log = LogFactory.getLog(NullTCCLTestCase.class); - log.debug("Hello, Mum"); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/custom/MyLog.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/custom/MyLog.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/custom/MyLog.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/custom/MyLog.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.logging.tccl.custom; - -import org.apache.commons.logging.Log; - -public class MyLog implements Log { - - public MyLog(String category) {} - - public boolean isDebugEnabled() { return false; } - public boolean isErrorEnabled() { return false; } - public boolean isFatalEnabled() { return false; } - public boolean isInfoEnabled() { return false; } - public boolean isTraceEnabled() { return false; } - public boolean isWarnEnabled() { return false; } - - public void trace(Object message) {} - public void trace(Object message, Throwable t) {} - public void debug(Object message) {} - public void debug(Object message, Throwable t) {} - public void info(Object message) {} - public void info(Object message, Throwable t) {} - public void warn(Object message) {} - public void warn(Object message, Throwable t) {} - public void error(Object message) {} - public void error(Object message, Throwable t) {} - public void fatal(Object message) {} - public void fatal(Object message, Throwable t) {} -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/custom/MyLogFactoryImpl.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/custom/MyLogFactoryImpl.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/custom/MyLogFactoryImpl.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/custom/MyLogFactoryImpl.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.tccl.custom; - - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -public class MyLogFactoryImpl extends LogFactory { - public Object getAttribute(String name) { return null; } - public String[] getAttributeNames() { return null; } - public Log getInstance(Class clazz) { return null; } - public Log getInstance(String name) { return null; } - public void release() {} - public void removeAttribute(String name) {} - public void setAttribute(String name, Object value) {} -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/log/TcclDisabledTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/log/TcclDisabledTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/log/TcclDisabledTestCase.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/log/TcclDisabledTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,160 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.tccl.log; - - -import java.net.URL; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogConfigurationException; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - * Verify that by default LogFactoryImpl is loaded from the tccl classloader. - */ - -public class TcclDisabledTestCase extends TestCase { - - public static final String MY_LOG_PKG = - "org.apache.commons.logging.tccl.custom"; - - public static final String MY_LOG_IMPL = - MY_LOG_PKG + ".MyLog"; - - // ------------------------------------------- JUnit Infrastructure Methods - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - Class thisClass = TcclDisabledTestCase.class; - - // Determine the URL to this .class file, so that we can then - // append the priority dirs to it. For tidiness, load this - // class through a dummy loader though this is not absolutely - // necessary... - PathableClassLoader dummy = new PathableClassLoader(null); - dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); - dummy.addLogicalLib("testclasses"); - dummy.addLogicalLib("commons-logging"); - - String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; - URL baseUrl = dummy.findResource(thisClassPath); - - // Now set up the desired classloader hierarchy. Everything goes into - // the parent classpath, but we exclude the custom Log class. - // - // We then create a tccl classloader that can see the custom - // Log class. Therefore if that class can be found, then the - // TCCL must have been used to load it. - PathableClassLoader emptyLoader = new PathableClassLoader(null); - - PathableClassLoader parentLoader = new PathableClassLoader(null); - parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); - parentLoader.addLogicalLib("commons-logging"); - parentLoader.addLogicalLib("testclasses"); - // hack to ensure that the testcase classloader can't see - // the custom MyLog - parentLoader.useExplicitLoader(MY_LOG_PKG + ".", emptyLoader); - - URL propsEnableUrl = new URL(baseUrl, "props_disable_tccl/"); - parentLoader.addURL(propsEnableUrl); - - PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader); - tcclLoader.addLogicalLib("testclasses"); - - Class testClass = parentLoader.loadClass(thisClass.getName()); - return new PathableTestSuite(testClass, tcclLoader); - } - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - LogFactory.releaseAll(); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - LogFactory.releaseAll(); - } - - // ----------------------------------------------------------- Test Methods - - /** - * Verify that MyLog is only loadable via the tccl. - */ - public void testLoader() throws Exception { - - ClassLoader thisClassLoader = this.getClass().getClassLoader(); - ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader(); - - // the tccl loader should NOT be the same as the loader that loaded this test class. - assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader); - - // MyLog should not be loadable via parent loader - try { - Class clazz = thisClassLoader.loadClass(MY_LOG_IMPL); - fail("Unexpectedly able to load MyLog via test class classloader"); - assertNotNull(clazz); // silence warnings about unused var - } catch(ClassNotFoundException ex) { - // ok, expected - } - - // MyLog should be loadable via tccl loader - try { - Class clazz = tcclLoader.loadClass(MY_LOG_IMPL); - assertNotNull(clazz); - } catch(ClassNotFoundException ex) { - fail("Unexpectedly unable to load MyLog via tccl classloader"); - } - } - - /** - * Verify that the custom Log implementation which is only accessable - * via the TCCL has NOT been loaded. Because this is only accessable via the - * TCCL, and we've use a commons-logging.properties that disables TCCL loading, - * we should see the default Log rather than the custom one. - */ - public void testTcclLoading() throws Exception { - LogFactory instance = LogFactory.getFactory(); - assertEquals( - "Correct LogFactory loaded", - "org.apache.commons.logging.impl.LogFactoryImpl", - instance.getClass().getName()); - - try { - Log log = instance.getInstance("test"); - fail("Unexpectedly succeeded in loading a custom Log class" - + " that is only accessable via the tccl."); - assertNotNull(log); // silence compiler warning about unused var - } catch(LogConfigurationException ex) { - // ok, expected - int index = ex.getMessage().indexOf(MY_LOG_IMPL); - assertTrue("MyLog not found", index >= 0); - } - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/log/TcclEnabledTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/log/TcclEnabledTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/log/TcclEnabledTestCase.java 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/log/TcclEnabledTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,155 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.tccl.log; - - -import java.net.URL; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - * Verify that by default the standard LogFactoryImpl class loads a - * custom Log implementation via the TCCL. - */ - -public class TcclEnabledTestCase extends TestCase { - - public static final String MY_LOG_PKG = - "org.apache.commons.logging.tccl.custom"; - - public static final String MY_LOG_IMPL = - MY_LOG_PKG + ".MyLog"; - - // ------------------------------------------- JUnit Infrastructure Methods - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - Class thisClass = TcclEnabledTestCase.class; - - // Determine the URL to this .class file, so that we can then - // append the priority dirs to it. For tidiness, load this - // class through a dummy loader though this is not absolutely - // necessary... - PathableClassLoader dummy = new PathableClassLoader(null); - dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); - dummy.addLogicalLib("testclasses"); - dummy.addLogicalLib("commons-logging"); - - String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; - URL baseUrl = dummy.findResource(thisClassPath); - - // Now set up the desired classloader hierarchy. Everything goes into - // the parent classpath, but we exclude the custom Log class. - // - // We then create a tccl classloader that can see the custom - // Log class. Therefore if that class can be found, then the - // TCCL must have been used to load it. - PathableClassLoader emptyLoader = new PathableClassLoader(null); - - PathableClassLoader parentLoader = new PathableClassLoader(null); - parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); - parentLoader.addLogicalLib("commons-logging"); - parentLoader.addLogicalLib("testclasses"); - // hack to ensure that the testcase classloader can't see - // the custom MyLogFactoryImpl - parentLoader.useExplicitLoader(MY_LOG_PKG + ".", emptyLoader); - - URL propsEnableUrl = new URL(baseUrl, "props_enable_tccl/"); - parentLoader.addURL(propsEnableUrl); - - PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader); - tcclLoader.addLogicalLib("testclasses"); - - Class testClass = parentLoader.loadClass(thisClass.getName()); - return new PathableTestSuite(testClass, tcclLoader); - } - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - LogFactory.releaseAll(); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - LogFactory.releaseAll(); - } - - // ----------------------------------------------------------- Test Methods - - /** - * Verify that MyLogFactoryImpl is only loadable via the tccl. - */ - public void testLoader() throws Exception { - - ClassLoader thisClassLoader = this.getClass().getClassLoader(); - ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader(); - - // the tccl loader should NOT be the same as the loader that loaded this test class. - assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader); - - // MyLog should not be loadable via parent loader - try { - Class clazz = thisClassLoader.loadClass(MY_LOG_IMPL); - fail("Unexpectedly able to load MyLog via test class classloader"); - assertNotNull(clazz); // silence warnings about unused var - } catch(ClassNotFoundException ex) { - // ok, expected - } - - // MyLog should be loadable via tccl loader - try { - Class clazz = tcclLoader.loadClass(MY_LOG_IMPL); - assertNotNull(clazz); - } catch(ClassNotFoundException ex) { - fail("Unexpectedly unable to load MyLog via tccl classloader"); - } - } - - /** - * Verify that the custom Log implementation which is only accessable - * via the TCCL has successfully been loaded as specified in the config file. - * This proves that the TCCL was used to load that class. - */ - public void testTcclLoading() throws Exception { - LogFactory instance = LogFactory.getFactory(); - - assertEquals( - "Correct LogFactory loaded", - "org.apache.commons.logging.impl.LogFactoryImpl", - instance.getClass().getName()); - - Log log = instance.getInstance("test"); - assertEquals( - "Correct Log loaded", - MY_LOG_IMPL, - log.getClass().getName()); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/log/props_disable_tccl/commons-logging.properties libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/log/props_disable_tccl/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/log/props_disable_tccl/commons-logging.properties 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/log/props_disable_tccl/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -use_tccl=false -org.apache.commons.logging.Log=org.apache.commons.logging.tccl.custom.MyLog -org.apache.commons.logging.diagnostics.dest=STDERR \ No newline at end of file diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/log/props_enable_tccl/commons-logging.properties libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/log/props_enable_tccl/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/log/props_enable_tccl/commons-logging.properties 2007-11-21 23:27:49.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/log/props_enable_tccl/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -org.apache.commons.logging.Log=org.apache.commons.logging.tccl.custom.MyLog -org.apache.commons.logging.diagnostics.dest=STDERR \ No newline at end of file diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/logfactory/TcclDisabledTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/logfactory/TcclDisabledTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/logfactory/TcclDisabledTestCase.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/logfactory/TcclDisabledTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,156 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.tccl.logfactory; - - -import java.net.URL; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - * Verify that a commons-logging.properties file can prevent a custom - * LogFactoryImpl being loaded from the tccl classloader. - */ - -public class TcclDisabledTestCase extends TestCase { - - public static final String MY_LOG_FACTORY_PKG = - "org.apache.commons.logging.tccl.custom"; - - public static final String MY_LOG_FACTORY_IMPL = - MY_LOG_FACTORY_PKG + ".MyLogFactoryImpl"; - - // ------------------------------------------- JUnit Infrastructure Methods - - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - Class thisClass = TcclDisabledTestCase.class; - - // Determine the URL to this .class file, so that we can then - // append the priority dirs to it. For tidiness, load this - // class through a dummy loader though this is not absolutely - // necessary... - PathableClassLoader dummy = new PathableClassLoader(null); - dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); - dummy.addLogicalLib("testclasses"); - dummy.addLogicalLib("commons-logging"); - - String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; - URL baseUrl = dummy.findResource(thisClassPath); - - // Now set up the desired classloader hierarchy. Everything goes into - // the parent classpath, but we exclude the custom LogFactoryImpl - // class. - // - // We then create a tccl classloader that can see the custom - // LogFactory class. Therefore if that class can be found, then the - // TCCL must have been used to load it. - PathableClassLoader emptyLoader = new PathableClassLoader(null); - - PathableClassLoader parentLoader = new PathableClassLoader(null); - parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); - parentLoader.addLogicalLib("commons-logging"); - parentLoader.addLogicalLib("testclasses"); - // hack to ensure that the testcase classloader can't see - // the custom MyLogFactoryImpl - parentLoader.useExplicitLoader( - MY_LOG_FACTORY_PKG + ".", emptyLoader); - - URL propsEnableUrl = new URL(baseUrl, "props_disable_tccl/"); - parentLoader.addURL(propsEnableUrl); - - PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader); - tcclLoader.addLogicalLib("testclasses"); - - Class testClass = parentLoader.loadClass(thisClass.getName()); - return new PathableTestSuite(testClass, tcclLoader); - } - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - LogFactory.releaseAll(); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - LogFactory.releaseAll(); - } - - // ----------------------------------------------------------- Test Methods - - /** - * Verify that MyLogFactoryImpl is only loadable via the tccl. - */ - public void testLoader() throws Exception { - - ClassLoader thisClassLoader = this.getClass().getClassLoader(); - ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader(); - - // the tccl loader should NOT be the same as the loader that loaded this test class. - assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader); - - // MyLogFactoryImpl should not be loadable via parent loader - try { - Class clazz = thisClassLoader.loadClass(MY_LOG_FACTORY_IMPL); - fail("Unexpectedly able to load MyLogFactoryImpl via test class classloader"); - assertNotNull(clazz); // silence warning about unused var - } catch(ClassNotFoundException ex) { - // ok, expected - } - - // MyLogFactoryImpl should be loadable via tccl loader - try { - Class clazz = tcclLoader.loadClass(MY_LOG_FACTORY_IMPL); - assertNotNull(clazz); - } catch(ClassNotFoundException ex) { - fail("Unexpectedly unable to load MyLogFactoryImpl via tccl classloader"); - } - } - - /** - * Verify that the custom LogFactory implementation which is only accessable - * via the TCCL has NOT been loaded. Because this is only accessable via the - * TCCL, and we've use a commons-logging.properties that disables TCCL loading, - * we should see the default LogFactoryImpl rather than the custom one. - */ - public void testTcclLoading() throws Exception { - try { - LogFactory instance = LogFactory.getFactory(); - fail("Unexpectedly succeeded in loading custom factory, though TCCL disabled."); - assertNotNull(instance); // silence warning about unused var - } catch(org.apache.commons.logging.LogConfigurationException ex) { - // ok, custom MyLogFactoryImpl as specified in props_disable_tccl - // could not be found. - int index = ex.getMessage().indexOf(MY_LOG_FACTORY_IMPL); - assertTrue("MylogFactoryImpl not found", index >= 0); - } - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/logfactory/TcclEnabledTestCase.java libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/logfactory/TcclEnabledTestCase.java --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/logfactory/TcclEnabledTestCase.java 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/logfactory/TcclEnabledTestCase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,147 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.tccl.logfactory; - - -import java.net.URL; - -import junit.framework.Test; -import junit.framework.TestCase; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.PathableClassLoader; -import org.apache.commons.logging.PathableTestSuite; - - -/** - * Verify that by default a custom LogFactoryImpl is loaded from the - * tccl classloader. - */ - -public class TcclEnabledTestCase extends TestCase { - - // ------------------------------------------- JUnit Infrastructure Methods - - - /** - * Return the tests included in this test suite. - */ - public static Test suite() throws Exception { - Class thisClass = TcclEnabledTestCase.class; - - // Determine the URL to this .class file, so that we can then - // append the priority dirs to it. For tidiness, load this - // class through a dummy loader though this is not absolutely - // necessary... - PathableClassLoader dummy = new PathableClassLoader(null); - dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); - dummy.addLogicalLib("testclasses"); - dummy.addLogicalLib("commons-logging"); - - String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; - URL baseUrl = dummy.findResource(thisClassPath); - - // Now set up the desired classloader hierarchy. Everything goes into - // the parent classpath, but we exclude the custom LogFactoryImpl - // class. - // - // We then create a tccl classloader that can see the custom - // LogFactory class. Therefore if that class can be found, then the - // TCCL must have been used to load it. - PathableClassLoader emptyLoader = new PathableClassLoader(null); - - PathableClassLoader parentLoader = new PathableClassLoader(null); - parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); - parentLoader.addLogicalLib("commons-logging"); - parentLoader.addLogicalLib("testclasses"); - // hack to ensure that the testcase classloader can't see - // the cust MyLogFactoryImpl - parentLoader.useExplicitLoader( - "org.apache.commons.logging.tccl.custom.", emptyLoader); - - URL propsEnableUrl = new URL(baseUrl, "props_enable_tccl/"); - parentLoader.addURL(propsEnableUrl); - - PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader); - tcclLoader.addLogicalLib("testclasses"); - - Class testClass = parentLoader.loadClass(thisClass.getName()); - return new PathableTestSuite(testClass, tcclLoader); - } - - /** - * Set up instance variables required by this test case. - */ - public void setUp() throws Exception { - LogFactory.releaseAll(); - } - - /** - * Tear down instance variables required by this test case. - */ - public void tearDown() { - LogFactory.releaseAll(); - } - - // ----------------------------------------------------------- Test Methods - - /** - * Verify that MyLogFactoryImpl is only loadable via the tccl. - */ - public void testLoader() throws Exception { - - ClassLoader thisClassLoader = this.getClass().getClassLoader(); - ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader(); - - // the tccl loader should NOT be the same as the loader that loaded this test class. - assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader); - - // MyLogFactoryImpl should not be loadable via parent loader - try { - Class clazz = thisClassLoader.loadClass( - "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl"); - fail("Unexpectedly able to load MyLogFactoryImpl via test class classloader"); - assertNotNull(clazz); // silence warning about unused var - } catch(ClassNotFoundException ex) { - // ok, expected - } - - // MyLogFactoryImpl should be loadable via tccl loader - try { - Class clazz = tcclLoader.loadClass( - "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl"); - assertNotNull(clazz); - } catch(ClassNotFoundException ex) { - fail("Unexpectedly unable to load MyLogFactoryImpl via tccl classloader"); - } - } - - /** - * Verify that the custom LogFactory implementation which is only accessable - * via the TCCL has successfully been loaded as specified in the config file. - * This proves that the TCCL was used to load that class. - */ - public void testTcclLoading() throws Exception { - LogFactory instance = LogFactory.getFactory(); - - assertEquals( - "Correct LogFactory loaded", - "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl", - instance.getClass().getName()); - } -} diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/logfactory/props_disable_tccl/commons-logging.properties libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/logfactory/props_disable_tccl/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/logfactory/props_disable_tccl/commons-logging.properties 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/logfactory/props_disable_tccl/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -use_tccl=false -org.apache.commons.logging.LogFactory=org.apache.commons.logging.tccl.custom.MyLogFactoryImpl diff -Nru libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/logfactory/props_enable_tccl/commons-logging.properties libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/logfactory/props_enable_tccl/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/org/apache/commons/logging/tccl/logfactory/props_enable_tccl/commons-logging.properties 2007-11-21 23:27:50.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/org/apache/commons/logging/tccl/logfactory/props_enable_tccl/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -org.apache.commons.logging.LogFactory=org.apache.commons.logging.tccl.custom.MyLogFactoryImpl diff -Nru libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/config/nopriority/commons-logging.properties libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/config/nopriority/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/config/nopriority/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/config/nopriority/commons-logging.properties 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +configId=nopriority diff -Nru libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/config/priority10/commons-logging.properties libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/config/priority10/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/config/priority10/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/config/priority10/commons-logging.properties 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +priority=10.5 +configId=priority10 diff -Nru libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/config/priority20/commons-logging.properties libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/config/priority20/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/config/priority20/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/config/priority20/commons-logging.properties 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +priority=20.6 +configId=priority20 diff -Nru libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/config/priority20a/commons-logging.properties libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/config/priority20a/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/config/priority20a/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/config/priority20a/commons-logging.properties 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +priority=20.6 +configId=priority20a diff -Nru libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/jdk14/CustomConfig.properties libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/jdk14/CustomConfig.properties --- libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/jdk14/CustomConfig.properties 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/jdk14/CustomConfig.properties 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,25 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# This is the custom configuration properties for the JDK 1.4 logger tests +# in CustomConfigTestCase. + +# Configure the Handler so we can examine the logged messages +handlers = org.apache.commons.logging.jdk14.TestHandler + +# Configre the default logging level to be FINE so we should get +# everything except trace messages +.level = FINE diff -Nru libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/tccl/log/props_disable_tccl/commons-logging.properties libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/tccl/log/props_disable_tccl/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/tccl/log/props_disable_tccl/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/tccl/log/props_disable_tccl/commons-logging.properties 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +use_tccl=false +org.apache.commons.logging.Log=org.apache.commons.logging.tccl.custom.MyLog +org.apache.commons.logging.diagnostics.dest=STDERR \ No newline at end of file diff -Nru libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/tccl/log/props_enable_tccl/commons-logging.properties libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/tccl/log/props_enable_tccl/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/tccl/log/props_enable_tccl/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/tccl/log/props_enable_tccl/commons-logging.properties 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +org.apache.commons.logging.Log=org.apache.commons.logging.tccl.custom.MyLog +org.apache.commons.logging.diagnostics.dest=STDERR \ No newline at end of file diff -Nru libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/tccl/logfactory/props_disable_tccl/commons-logging.properties libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/tccl/logfactory/props_disable_tccl/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/tccl/logfactory/props_disable_tccl/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/tccl/logfactory/props_disable_tccl/commons-logging.properties 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +use_tccl=false +org.apache.commons.logging.LogFactory=org.apache.commons.logging.tccl.custom.MyLogFactoryImpl diff -Nru libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/tccl/logfactory/props_enable_tccl/commons-logging.properties libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/tccl/logfactory/props_enable_tccl/commons-logging.properties --- libcommons-logging-java-1.1.1/src/test/resources/org/apache/commons/logging/tccl/logfactory/props_enable_tccl/commons-logging.properties 1970-01-01 00:00:00.000000000 +0000 +++ libcommons-logging-java-1.1.3/src/test/resources/org/apache/commons/logging/tccl/logfactory/props_enable_tccl/commons-logging.properties 2013-05-16 20:04:21.000000000 +0000 @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +org.apache.commons.logging.LogFactory=org.apache.commons.logging.tccl.custom.MyLogFactoryImpl diff -Nru libcommons-logging-java-1.1.1/xdocs/building.xml libcommons-logging-java-1.1.3/xdocs/building.xml --- libcommons-logging-java-1.1.1/xdocs/building.xml 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/xdocs/building.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ - - - - - Building - Commons Documentation Team - - - -

-

- Commons Logging uses Maven 2.0.x as its - primary build system. Ant can also be used. -

-
- -
-

- To build the full website, run -

- mvn site -

- The result will be in the target/site folder. - You must be online and using JDK 1.4 or higher to successfully complete this target. -

-

- To build the jar files, run -

- mvn package -

- The resulting 4 jar files will be in the target folder. - You must use JDK 1.4 or higher to successfully complete this target. -

-

- To create a full distribution, run -

- mvn clean site assembly:assembly -

- The resulting .zip and .tar.gz files will be in the target folder. - You must use JDK 1.4 or higher to successfully complete this target. -

-

- Further details can be found in the - commons build instructions. -

-
- -
-

- We still use Ant to test the artifacts built my Maven. - Please follow the instructions in the file build-testing.xml. -

-

- Note: A 1.2 JDK is needed to run the tests. -

-
- - - diff -Nru libcommons-logging-java-1.1.1/xdocs/cvs-usage.xml libcommons-logging-java-1.1.3/xdocs/cvs-usage.xml --- libcommons-logging-java-1.1.1/xdocs/cvs-usage.xml 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/xdocs/cvs-usage.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ - - - - - - Source repository - Commons Documentation Team - - - - -
-

- Apcahe Commons Logging is hosted on the Apache - subversion repository. -

-

- The project URL is:
- http://svn.apache.org/repos/asf/commons/proper/logging/trunk -

-

- The best way to view the repository is via the - subversion viewer. -

-

- The alternative is to use the - native subversion display. -

-
- - -
diff -Nru libcommons-logging-java-1.1.1/xdocs/guide.xml libcommons-logging-java-1.1.3/xdocs/guide.xml --- libcommons-logging-java-1.1.1/xdocs/guide.xml 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/xdocs/guide.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,850 +0,0 @@ - - - - - - - - User Guide - Commons Documentation Team - - - -
-

-

    -
  1. Introduction
  2. -
  3. Quick Start -
      -
    1. Configuration
    2. -
    3. -Configuring The Underlying Logging System -
    4. -
    5. -Configuring Log4J -
    6. -
    -
  4. -
  5. Developing With JCL -
      -
    1. Obtaining a Log Object
    2. -
    3. Logging a Message
    4. -
    5. Serialization Issues
    6. -
    -
  6. -
  7. Jars Included in the Standard Distribution -
      -
    1. commons-logging.jar
    2. -
    3. commons-logging-api.jar
    4. -
    5. commons-logging-adapters.jar
    6. -
    -
  8. -
  9. JCL Best Practices
  10. -
  11. Best Practices (General) -
      -
    1. Code Guards
    2. -
    3. Message Priorities/Levels
    4. -
    5. Default Message Priority/Level
    6. -
    -
  12. -
  13. Best Practices (Enterprise) -
      -
    1. Logging Exceptions
    2. -
    3. When Info Level Instead of Debug?
    4. -
    5. More Control of Enterprise Exception Logging
    6. -
    7. National Language Support And Internationalization
    8. -
    9. Classloader and Memory Management
    10. -
    -
  14. -
  15. Extending Commons Logging -
      -
    1. Contract
    2. -
    3. Creating a Log Implementation
    4. -
    5. Creating A LogFactory Implementation
    6. -
    -
  16. -
  17. A Quick Guide To Simple Log -
  18. -
  19. Frequently Asked Questions -
  20. -
-

-
-
-

-The Apache Commons Logging (JCL) provides a Log interface that -is intended to be both light-weight and an independent abstraction of other logging toolkits. -It provides the middleware/tooling developer with a simple -logging abstraction, that allows the user (application developer) to plug in -a specific logging implementation. -

-

JCL provides thin-wrapper Log implementations for -other logging tools, including -Log4J, -Avalon LogKit -(the Avalon Framework's logging infrastructure), -JDK 1.4, and an implementation of JDK 1.4 logging APIs (JSR-47) for pre-1.4 -systems. -The interface maps closely to Log4J and LogKit. -

-

-Familiarity with high-level details of the relevant Logging implementations is presumed. -

-
-
-

-As far as possible, JCL tries to be as unobtrusive as possible. -In most cases, including the (full) commons-logging.jar in the classpath -should result in JCL configuring itself in a reasonable manner. -There's a good chance that it'll guess (discover) your preferred logging system and you won't -need to do any configuration of JCL at all! -

-Note, however, that if you have a particular preference then providing a simple -commons-logging.properties file which specifies the concrete logging library to be -used is recommended, since (in this case) JCL will log only to that system -and will report any configuration problems that prevent that system being used. -

-

-When no particular logging library is specified then JCL will silently ignore any logging library -that it finds but cannot initialise and continue to look for other alternatives. This is a deliberate -design decision; no application should fail to run because a "guessed" logging library cannot be -used. To ensure an exception is reported when a particular logging library cannot be used, use one -of the available JCL configuration mechanisms to force that library to be selected (ie disable -JCL's discovery process). -

- -

-There are two base abstractions used by JCL: Log -(the basic logger) and LogFactory (which knows how to create Log -instances). Specifying a particular Log implementation is very useful (whether that is -one provided by commons-logging or a user-defined one). Specifying a -LogFactory implementation other than the default is a subject for -advanced users only, so will not be addressed here. -

-

-The default LogFactory implementation uses the following discovery process -to determine what type of Log implementation it should use -(the process terminates when the first positive match - in order - is found): -

- -
    -
  1. -Look for a configuration attribute of this factory named -org.apache.commons.logging.Log (for backwards compatibility to -pre-1.0 versions of this API, an attribute -org.apache.commons.logging.log is also consulted). -

    -Configuration attributes can be set explicitly by java code, but they are more -commonly set by placing a file named commons-logging.properties in the classpath. -When such a file exists, every entry in the properties file becomes an "attribute" -of the LogFactory. When there is more than one such file in the classpath, releases -of commons-logging prior to 1.1 simply use the first one found. From release 1.1, -each file may define a priority key, and the file with -the highest priority is used (no priority definition implies priority of zero). -When multiple files have the same priority, the first one found is used. -

    -

    -Defining this property in a commons-logging.properties file is the recommended -way of explicitly selecting a Log implementation. -

    -
  2. -
  3. -Look for a system property named -org.apache.commons.logging.Log (for backwards -compatibility to pre-1.0 versions of this API, a system property -org.apache.commons.logging.log is also consulted). -
  4. -
  5. -If the Log4J logging system is available in the application -class path, use the corresponding wrapper class -(Log4JLogger). -
  6. -
  7. -If the application is executing on a JDK 1.4 system, use -the corresponding wrapper class -(Jdk14Logger). -
  8. -
  9. -Fall back to the default simple logging wrapper -(SimpleLog). -
  10. -
-

-Consult the JCL javadocs for details of the various Log -implementations that ship with the component. (The discovery process is also covered in more -detail there.) -

-
- -

-The JCL SPI -can be configured to use different logging toolkits (see above). -JCL provides only a bridge for writing log messages. It does not (and will not) support any -sort of configuration API for the underlying logging system. -

-

-Configuration of the behavior of the JCL ultimately depends upon the -logging toolkit being used. Please consult the documentation for the chosen logging system. -

-

-JCL is NOT responsible for initialisation, configuration or shutdown of the underlying logging library. -In many cases logging libraries will automatically initialise/configure themselves when first used, and -need no explicit shutdown process. In these situations an application can simply use JCL and not depend -directly on the API of the underlying logging system in any way. However if the logging library being used -requires special initialisation, configuration or shutdown then some logging-library-specific code will -be required in the application. JCL simply forwards logging method calls to the correct underlying -implementation. When writing library code this issue is of course not relevant as the calling application -is responsible for handling such issues. -

- -

-Log4J is a very commonly used logging implementation (as well as being the JCL primary default), -so a few details are presented herein to get the developer/integrator going. -Please see the Log4J Home for more details -on Log4J and it's configuration. -

-

-Configure Log4J using system properties and/or a properties file: -

-
    -
  • -log4j.configuration=log4j.properties -Use this system property to specify the name of a Log4J configuration file. -If not specified, the default configuration file is log4j.properties. -
  • -
  • -log4j.rootCategory=priority [, appender]* -
  • -Set the default (root) logger priority. -
  • -log4j.logger.logger.name=priority -Set the priority for the named logger -and all loggers hierarchically lower than, or below, the -named logger. -logger.name corresponds to the parameter of -LogFactory.getLog(logger.name), -used to create the logger instance. Priorities are: -DEBUG, -INFO, -WARN, -ERROR, -or FATAL. -
    -Log4J understands hierarchical names, -enabling control by package or high-level qualifiers: -log4j.logger.org.apache.component=DEBUG -will enable debug messages for all classes in both -org.apache.component -and -org.apache.component.sub. -Likewise, setting -log4j.logger.org.apache.component=DEBUG -will enable debug message for all 'component' classes, -but not for other Apache projects. -
  • -
  • -log4j.appender.appender.Threshold=priority -
  • -Log4J appenders correspond to different output devices: -console, files, sockets, and others. -If appender's threshold -is less than or equal to the message priority then -the message is written by that appender. -This allows different levels of detail to be appear -at different log destinations. -For example: one can capture DEBUG (and higher) level information in a logfile, -while limiting console output to INFO (and higher). -
-
-
-
-
- -

-To use the JCL SPI from a Java class, -include the following import statements: -

-
    - -import org.apache.commons.logging.Log; -
    -import org.apache.commons.logging.LogFactory; -
    -
    -
-

-Note that some components using JCL may -either extend Log, -or provide a component-specific LogFactory implementation. -Review the component documentation for guidelines -on how commons-logging should be used in such components. -

-

-For each class definition, declare and initialize a -log attribute as follows: -

-
    - -public class CLASS -{ - private Log log = LogFactory.getLog(CLASS.class); - ... - ; - -
-

-Note that for application code, declaring the log member as "static" is more -efficient as one Log object is created per class, and is recommended. -However this is not safe to do for a class which may be deployed via a "shared" -classloader in a servlet or j2ee container or similar environment. If the class -may end up invoked with different thread-context-classloader values set then the -member must not be declared static. The use of "static" should therefore -be avoided in code within any "library" type project. -

-
- -

-Messages are logged to a logger, such as log -by invoking a method corresponding to priority. -The org.apache.commons.logging.Log interface defines the -following methods for use -in writing log/trace messages to the log: -

-
    - - log.fatal(Object message); - log.fatal(Object message, Throwable t); - log.error(Object message); - log.error(Object message, Throwable t); - log.warn(Object message); - log.warn(Object message, Throwable t); - log.info(Object message); - log.info(Object message, Throwable t); - log.debug(Object message); - log.debug(Object message, Throwable t); - log.trace(Object message); - log.trace(Object message, Throwable t); - -
-

-Semantics for these methods are such that it is expected -that the severity, from highest to lowest, of messages is ordered as above. -

-

-In addition to the logging methods, the following are provided for code guards: -

-
    - - log.isFatalEnabled(); - log.isErrorEnabled(); - log.isWarnEnabled(); - log.isInfoEnabled(); - log.isDebugEnabled(); - log.isTraceEnabled(); - -
-
- -

Prior to release 1.0.4, none of the standard Log implementations were - Serializable. If you are using such a release and have a Serializable class - with a member that is of type Log then it is necessary to declare - that member to be transient and to ensure that the value is restored on - deserialization. The recommended approach is to define a custom - readObject method on the class which reinitializes that member.

-

In release 1.0.4, all standard Log implementations are Serializable. This - means that class members of type Log do not need to be declared transient; - on deserialization the Log object will "rebind" to the same category for the - same logging library. Note that the same underlying logging library will be - used on deserialization as was used in the original object, even if the - application the object was deserialized into is using a different logging - library. There is one exception; LogKitLogger (adapter for the Avalon LogKit - library) is not Serializable for technical reasons.

-

Custom Log implementations not distributed with commons-logging may - or may not be Serializable. If you wish your code to be compatible with - any arbitrary log adapter then you should follow the advice given above - for pre-1.0.4 releases.

-
-
-
- -

-The commons-logging.jar file includes the JCL API, the default -LogFactory implemenation and thin-wrapper Log -implementations for -Log4J, -Avalon LogKit, -the Avalon Framework's logging infrastructure, -JDK 1.4, as well as an implementation of JDK 1.4 logging APIs (JSR-47) for -pre-1.4 systems. -

-

-In most cases, including commons-logging.jar and your preferred -logging implementation in the classpath should be all that is required to -use JCL. -

-
- -

-The commons-logging-api.jar file includes the JCL API and the -default LogFactory implementation as well as the built-in -Log implementations SimpleLog and NoOpLog. However it does not -include the wrapper Log implementations that require additional -libraries such as Log4j, Avalon and -Lumberjack. -

-

-This jar is intended for use by projects that recompile the commons-logging -source using alternate java environments, and cannot compile against all of -the optional libraries that the Apache release of commons-logging supports. -Because of the reduced dependencies of this jarfile, such projects should be -able to create an equivalent of this library with fewer difficulties. -

-

-This jar is also useful for build environments that automatically track -dependencies, and thus have difficulty with the concept that the main -commons-logging.jar has "optional" dependencies on various logging -implementations that can safely go unsatisfied at runtime. -

-
- -

-The commons-logging-adapters.jar file includes only adapters -to third-party logging implementations, and none of the core commons-logging -framework. As such, it cannot be used alone; either commons-logging.jar or -commons-logging-api.jar must also be present in the classpath. -

-

-This library will not often be used; it is only intended for situations where -a container has deployed commons-logging-api.jar in a shared classpath but a -webapp wants to bind logging to one of the external logging implementations -that the api jar does not include. In this situation, deploying the -commons-logging.jar file within the webapp can cause problems as this leads to -duplicates of the core commons-logging classes (Log, LogFactory, etc) in -the classpath which in turn can cause unpleasant ClassCastException exceptions -to occur. Deploying only the adapters avoids this problem. -

-
-
-
-

-Best practices for JCL are presented in two categories: -General and Enterprise. -The general principles are fairly clear.Enterprise practices are a bit more involved -and it is not always as clear as to why they are important. -

-

-Enterprise best-practice principles apply to middleware components -and tooling that is expected to execute in an "Enterprise" level -environment. -These issues relate to Logging as Internationalization, -and fault detection. -Enterprise requires more effort and planning, but are strongly encouraged (if not required) -in production level systems. Different corporate enterprises/environments have different -requirements, so being flexible always helps. -

-
-
- -

-Code guards are typically used to guard code that -only needs to execute in support of logging, -that otherwise introduces undesirable runtime overhead -in the general case (logging disabled). -Examples are multiple parameters, or expressions (e.g. string + " more") for parameters. -Use the guard methods of the form log.is<Priority>() to verify -that logging should be performed, before incurring the overhead of the logging method call. -Yes, the logging methods will perform the same check, but only after resolving parameters. -

-
- -

-It is important to ensure that log message are -appropriate in content and severity. -The following guidelines are suggested: -

-
    -
  • -fatal - Severe errors that cause premature termination. -Expect these to be immediately visible on a status console. -See also -Internationalization. -
  • -
  • -error - Other runtime errors or unexpected conditions. -Expect these to be immediately visible on a status console. -See also -Internationalization. -
  • -
  • -warn - Use of deprecated APIs, poor use of API, 'almost' errors, -other runtime situations that are undesirable or unexpected, but not -necessarily "wrong". -Expect these to be immediately visible on a status console. -See also -Internationalization. -
  • -
  • -info - Interesting runtime events (startup/shutdown). -Expect these to be immediately visible on a console, -so be conservative and keep to a minimum. -See also -Internationalization. -
  • -
  • -debug - detailed information on the flow through the system. -Expect these to be written to logs only. -
  • -
  • -trace - more detailed information. -Expect these to be written to logs only. -
  • -
-
- -

-By default the message priority should be no lower than info. -That is, by default debug message should not be seen in the logs. -

-
-
-
- -

-The general rule in dealing with exceptions is to assume that -the user (developer using a tooling/middleware API) isn't going -to follow the rules. -Since any problems that result are going to be assigned to you, -it's in your best interest to be prepared with the proactive -tools necessary to demonstrate that your component works correctly, -or at worst that the problem can be analyzed from your logs. -For this discussion, we must make a distinction between different types of exceptions -based on what kind of boundaries they cross: -

-
    -
  • -External Boundaries - Expected Exceptions. -This classification includes exceptions such as FileNotFoundException -that cross API/SPI boundaries, and are exposed to the user of a component/toolkit. -These are listed in the 'throws' clause of a method signature. -
    -Appropriate handling of these exceptions depends upon the type -of code you are developing. -API's for utility functions and tools should log these at the debug level, -if they are caught at all by internal code. -
    -For higher level frameworks and middleware components, -these exceptions should be caught immediatly prior to crossing -the API/SPI interface back to user code-space, -logged with full stack trace at info level, -and rethrown. -The assures that the log contains a record of the root cause for -future analysis in the event that the exception is not caught and resolved -as expected by the user's code. -
    -
  • -
  • -External Boundaries - Unexpected Exceptions. -This classification includes exceptions such as NullPointerException -that cross API/SPI boundaries, and are exposed to the user of a component/toolkit. -These are runtime exceptions/error that are NOT -listed in the 'throws' clause of a method signature. -
    -Appropriate handling of these exceptions depends upon the type -of code you are developing. -APIs for utility functions and tools should log these at the debug level, -if they are caught at all. -
    -For higher level frameworks and middleware components, -these exceptions should be caught immediately prior to crossing -the API/SPI interface back to user code-space, -logged with full stack trace at info level, -and rethrown/wrapped as ComponentInternalError. -This ensures that the log contains a record of the root cause for -future analysis in the event that the exception is not caught and -logged/reported as expected by the user's code. -
  • -
  • -Internal Boundaries. -Exceptions that occur internally and are resolved internally. -These should be logged when caught as debug or info messages, -at the programmer's discretion. -
  • -
  • -Significant Internal Boundaries. -This typically only applies to middleware components that span networks or runtime processes. -Exceptions that cross over significant internal component boundaries such as networks -should be logged when caught as info messages. -Do not assume that such a (process/network) boundary will deliver exceptions to the 'other side'. -
  • -
-
- -

-You want to have exception/problem information available for -first-pass problem determination in a production level -enterprise application without turning on debug -as a default log level. There is simply too much information -in debug to be appropriate for day-to-day operations. -

-
- -

-If more control is desired for the level of detail of these -'enterprise' exceptions, then consider creating a special -logger just for these exceptions: -

-
    - - Log log = LogFactory.getLog("org.apache.component.enterprise"); - -
-

-This allows the 'enterprise' level information to be turned on/off explicitly -by most logger implementations. -

-
- -

-NLS internationalization involves looking up messages from -a message file by a message key, and using that message for logging. -There are various tools in Java, and provided by other components, -for working with NLS messages. -

-

-NLS enabled components are particularly appreciated -(that's an open-source-correct term for 'required by corporate end-users' :-) -for tooling and middleware components. -

-

-NLS internationalization SHOULD be strongly considered for used for -fatal, error, warn, and info messages. -It is generally considered optional for debug and trace messages. -

-

-Perhaps more direct support for internationalizing log messages -can be introduced in a future or alternate version of the Log interface. -

-
- -

-The LogFactory discovery process (see -Configuration above) is a fairly expensive -operation, so JCL certainly should not perform it each time user code -invokes: -

-LogFactory.getLog() -

-Instead JCL caches the -LogFactory implementation created as a result of the discovery -process and uses the cached factory to return Log objects. -Since in J2EE and similar multi-classloader environments, the result of the -discovery process can vary depending on the thread context classloader -(e.g. one webapp in a web container may be configured to use Log4j and -another to use JDK 1.4 logging), JCL internally caches the -LogFactory instances in a static hashtable, keyed by classloader. -

-

-While this approach is efficient, it can lead to memory leaks if container -implementors are not careful to call -

-LogFactory.release() -

-whenever a classloader that has utilized JCL is undeployed. If -release() is not called, a reference to the undeployed -classloader (and thus to all the classes loaded by it) will be -held in LogFactory's static hashtable. -

-

-Beginning with JCL 1.1, LogFactory caches factory implementations in a -"WeakHashtable". This class is similar to java.util.WeakHashMap in -that it holds a WeakReference to each key (but a strong reference -to each value), thus allowing classloaders to be GC'd even if -LogFactory.release() is never invoked. -

-

-Because WeakHashtable depends on JDK 1.3+ features, it is dynamically -loaded depending on the JVM version; when commons-logging is run on java versions -prior to 1.3 the code defaults to a standard Hashtable instead. -

-

-If a custom LogFactory implementation is used, however, then a -WeakHashtable alone can be insufficent to allow garbage collection -of a classloader without a call to release. If the abstract class -LogFactory is loaded by a parent classloader and a concrete -subclass implementation of LogFactory is loaded by a child -classloader, the WeakHashtable's key is a weak reference to the TCCL (child -classloader), but the value is a strong reference to the LogFactory instance, -which in turn contains a strong reference to its class and thus loading -classloader - the child classloader. This chain of strong references prevents -the child loader from being garbage collected. -

-

-If use of a custom LogFactory subclass is desired, ensuring that -the custom subclass is loaded by the same classloader as LogFactory -will prevent problems. In normal deployments, the standard implementations -of LogFactory found in package org.apache.commons.logging.impl -will be loaded by the same classloader that loads LogFactory -itself, so use of the standard LogFactory implementation -should not pose problems. Alternatively, use the provided ServletContextCleaner -to ensure this reference is explicitly released on webapp unload. -

-
-
-
-

-JCL is designed to encourage extensions to be created that add functionality. -Typically, extensions to JCL fall into two categories: -

-
    -
  • new Log implementations that provide new bridges to logging systems
  • -
  • -new LogFactory implementations that provide alternative discovery strategies -
  • -
- -

-When creating new implementations for Log and LogFactory, -it is important to understand the implied contract between the factory -and the log implementations: -

    -
  • Life cycle -
    -The JCL LogFactory implementation must assume responsibility for -either connecting/disconnecting to a logging toolkit, -or instantiating/initializing/destroying a logging toolkit. -
    -
  • -
  • Exception handling -
    -The JCL Log interface doesn't specify any exceptions to be handled, -the implementation must catch any exceptions. -
    -
  • -
  • Multiple threads -
    -The JCL Log and LogFactory implementations must ensure -that any synchronization required by the logging toolkit -is met. -
    -
  • -
-

-
- -

-The minimum requirement to integrate with another logger -is to provide an implementation of the -org.apache.commons.logging.Log interface. -In addition, an implementation of the -org.apache.commons.logging.LogFactory interface -can be provided to meet -specific requirements for connecting to, or instantiating, a logger. -

-

-The default LogFactory provided by JCL -can be configured to instantiate a specific implementation of the -org.apache.commons.logging.Log interface -by setting the property of the same name (org.apache.commons.logging.Log). -This property can be specified as a system property, -or in the commons-logging.properties file, -which must exist in the CLASSPATH. -

-
- -

-If desired, the default implementation of the -org.apache.commons.logging.LogFactory -interface can be overridden, -allowing the JDK 1.3 Service Provider discovery process -to locate and create a LogFactory specific to the needs of the application. -Review the Javadoc for the LogFactoryImpl.java -for details. -

-
-
-
-

-JCL is distributed with a very simple Log implementation named -org.apache.commons.logging.impl.SimpleLog. This is intended to be a minimal -implementation and those requiring a fully functional open source logging system are -directed to Log4J. -

-

- SimpleLog sends all (enabled) log messages, - for all defined loggers, to System.err. The following system properties - are supported to configure the behavior of this logger:

-
    -
  • org.apache.commons.logging.simplelog.defaultlog - - Default logging detail level for all instances of SimpleLog. - Must be one of: -
      -
    • trace
    • -
    • debug
    • -
    • info
    • -
    • warn
    • -
    • error
    • -
    • fatal
    • -
    - If not specified, defaults to info.
  • -
  • org.apache.commons.logging.simplelog.log.xxxxx - - Logging detail level for a SimpleLog instance named "xxxxx". - Must be one of: -
      -
    • trace
    • -
    • debug
    • -
    • info
    • -
    • warn
    • -
    • error
    • -
    • fatal
    • -
    - If not specified, the default logging detail level is used.
  • -
  • org.apache.commons.logging.simplelog.showlogname - - Set to true if you want the Log instance name to be - included in output messages. Defaults to false.
  • -
  • org.apache.commons.logging.simplelog.showShortLogname - - Set to true if you want the last component of the name to be - included in output messages. Defaults to true.
  • -
  • org.apache.commons.logging.simplelog.showdatetime - - Set to true if you want the current date and time - to be included in output messages. Default is false.
  • -
  • org.apache.commons.logging.simplelog.dateTimeFormat - - The date and time format to be used in the output messages. - The pattern describing the date and time format is the same that is - used in java.text.SimpleDateFormat. If the format is not - specified or is invalid, the default format is used. - The default format is yyyy/MM/dd HH:mm:ss:SSS zzz.
  • -
- -

-In addition to looking for system properties with the names specified -above, this implementation also checks for a class loader resource named -"simplelog.properties", and includes any matching definitions -from this resource (if it exists). -

-
-
-

-See the FAQ document -on the commons-logging wiki site -

-
- - -
Binary files /tmp/QIYUuSPeoV/libcommons-logging-java-1.1.1/xdocs/images/logo.png and /tmp/U4WicrDbVX/libcommons-logging-java-1.1.3/xdocs/images/logo.png differ diff -Nru libcommons-logging-java-1.1.1/xdocs/index.xml libcommons-logging-java-1.1.3/xdocs/index.xml --- libcommons-logging-java-1.1.1/xdocs/index.xml 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/xdocs/index.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,139 +0,0 @@ - - - - - - - - Overview - Commons Documentation Team - - - - -
- -

When writing a library it is very useful to log information. However there -are many logging implementations out there, and a library cannot impose the use -of a particular one on the overall application that the library is a part of.

- -

The Logging package is an ultra-thin bridge between different logging -implementations. A library that uses the commons-logging API can be used with -any logging implementation at runtime. Commons-logging comes with support for a -number of popular logging implementations, and writing adapters for others is a -reasonably simple task.

- -

Applications (rather than libraries) may also choose to use commons-logging. -While logging-implementation independence is not as important for applications -as it is for libraries, using commons-logging does allow the application to -change to a different logging implementation without recompiling code. -

-Note that commons-logging does not attempt to initialise or terminate the underlying -logging implementation that is used at runtime; that is the responsibility of -the application. However many popular logging implementations do automatically -initialise themselves; in this case an application may be able to avoid -containing any code that is specific to the logging implementation used.

- -
- - -
- -

The -Release Notes document the new features and bug fixes that have been -included in the latest release.

- -

The -JavaDoc API documents for the latest release are available online. -In particular, you should read the package overview of the org.apache.commons.logging -package. In addition, there is a (short) -User Guide.

- -

The Wiki site has -the latest updates, an FAQ and much other useful information.

-

-Users needing to become experts or wanting to help develop JCL should -(in addition) consult the Tech Guide. -This gives short introductions to topics such as advanced class loading. -

-
- - -
-

-Binary and source distributions are available - here. -

- -

- This release is a minor update to the 1.1 release that fixes a number of bugs, and - resolves packaging issues for maven 1.x and maven 2.x users. -

-

For the full details, see the release notes for this version.

-
- -

This release makes several changes that are intended to resolve issues that - have been encountered when using commons-logging in servlet containers or j2ee - containers where complex classpaths are present and multiple copies of - commons-logging libraries are present at different levels.

-

This release also adds support for the TRACE level added to log4j in the - 1.2.12 release. In former commons-logging versions, the log.trace method - caused log4j to output the message at the DEBUG level (the lowest level - supported by log4j at that time).

-

For the full details, see the release notes for this version.

-
- -

- Note: the 1.0.5 release was abandoned at alpha status. -

-

- The next JCL release will be designated 1.1 since we feel this more - accurately reflects the improvements made to the codebase.

-
- -

-The 1.0.4 release of commons-logging is a service -release containing support for both the 1.2.x and 1.3.x series of Log4J releases. -

-
- -

-The 1.0.3 release is primarily a maintenance and code cleanup release with minimal new features. -

-
- -

-The 1.0.2 release is a packaging of bug fixes since release 1.0.1. -

-
- -

-The 1.0.1 release is a packaging of bug fixes and minor enhancements since release 1.0. -

-
-
-
-

-Regular builds of the current SVN HEAD code are made available. See the -wiki for details. -

-
- -
diff -Nru libcommons-logging-java-1.1.1/xdocs/issue-tracking.xml.bak libcommons-logging-java-1.1.3/xdocs/issue-tracking.xml.bak --- libcommons-logging-java-1.1.1/xdocs/issue-tracking.xml.bak 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/xdocs/issue-tracking.xml.bak 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ - - - - - - Issue tracking - Commons Documentation Team - - - - -
-

- Commons Logging uses ASF JIRA for tracking issues. -

-

- To use JIRA you may need to create an account - (if you have previously created/updated Commons issues using Bugzilla an account will have been automatically - created and you can use the Forgot Password - page to get a new password). -

-

- If you would like to report a bug, or raise an enhancement request with - Commons Logging please do the following: -

    -
  1. Search existing open bugs. - If you find your issue listed then please add a comment with your details.
  2. -
  3. Search the mailing list archive. - You may find your issue or idea has already been discussed.
  4. -
  5. Submit a bug report or enhancement request.
  6. -
-

-

- Please also remember these points: -

    -
  • the more information you provide, the better we can help you
  • -
  • test cases are vital, particularly for any proposed enhancements
  • -
  • the developers of Commons Logging are all unpaid volunteers
  • -
-

-

- You may also find these links useful: -

-

-
- - -
diff -Nru libcommons-logging-java-1.1.1/xdocs/junit-report.xml libcommons-logging-java-1.1.3/xdocs/junit-report.xml --- libcommons-logging-java-1.1.1/xdocs/junit-report.xml 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/xdocs/junit-report.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ - - - - - - JUnit Test Results - Commons Documentation Team - - - - -
-

- The Apache Commons Logging test cases make extensive use of - sophisticated classloader configurations in order to simulate the - behaviour of various containers. It is difficult to run these tests - under Maven (which is used to generate the website). Once JCL is - upgraded to Maven 2 it is hoped that we will be able to display a report - on the unit tests. -

-
- - -
diff -Nru libcommons-logging-java-1.1.1/xdocs/navigation.xml libcommons-logging-java-1.1.3/xdocs/navigation.xml --- libcommons-logging-java-1.1.1/xdocs/navigation.xml 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/xdocs/navigation.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ - - - - - - - Logging - - Apache Commons - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - &commons; - - - - diff -Nru libcommons-logging-java-1.1.1/xdocs/proposal.xml libcommons-logging-java-1.1.3/xdocs/proposal.xml --- libcommons-logging-java-1.1.1/xdocs/proposal.xml 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/xdocs/proposal.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,127 +0,0 @@ - - - - -Proposal for Logging Library Package - - - - -
- - - - - -

There is a great need for debugging and logging information inside of -Commons components such as HTTPClient and dbcp. However, there are many -logging APIs out there and it is difficult to choose among them. -

- -

The Logging package will be an ultra-thin bridge between different logging -libraries. Commons components may use the Logging JAR to remove -compile-time/runtime dependencies on any particular logging package, -and contributors may write Log implementations for the library of their choice. -

- -
- - -

The package shall create and maintain a package that provides extremely -basic logging functionality and bridges to other, more sophisticated logging -implementations. -

- -

-The package should : -

    -
  • Have an API which should be as simple to use as possible
  • -
  • Provide support for log4j
  • -
  • Provide pluggable support for other logging APIs
  • -
-

- -

-Non-goals: -

    -
  • This package will not perform logging itself, except at the most basic - level.
  • -
  • We do not seek to become a "standard" API.
  • -
-

- -
- - -

Logging relies on: -

- -
    -
  • Java Development Kit (Version 1.1 or later)
  • -
  • Avalon Framework (compile-time dependency only unless this Log - implementation is selected at runtime)
  • -
  • Avalon LogKit (compile-time dependency only unless this Log - implementation is selected at runtime)
  • -
  • JDK 1.4 (compile-time dependency only unless this log implementation - is selected at runtime).
  • -
  • Log4J (compile-time dependency only unless this Log - implementation is selected at runtime)
  • -
  • Lumberjack - (compile-time dependency only unless this Log - implementation is selected at runtime)
  • -
- -
- - -
    -
  • CVS Repository - New directory logging in the -jakarta-commons CVS repository.
  • - -
  • Initial Committers - The list is provided below.
  • - -
  • Mailing List - Discussions will take place on the general -dev@commons.apache.org mailing list. To help list -subscribers identify messages of interest, it is suggested that the -message subject of messages about this component be prefixed with -[Logging].
  • - -
  • Bugzilla - New component "Logging" under the "Commons" product -category, with appropriate version identifiers as needed.
  • - -
  • Jyve FAQ - New category "commons-logging" (when available).
  • -
- - -
- - -

The initial committers on the Logging component shall be:

- -
    -
  • Morgan Delagrange
  • -
  • Rodney Waldhoff
  • -
  • Craig McClanahan
  • -
- -
-
- -
diff -Nru libcommons-logging-java-1.1.1/xdocs/style/project.css libcommons-logging-java-1.1.3/xdocs/style/project.css --- libcommons-logging-java-1.1.1/xdocs/style/project.css 2007-11-21 23:27:45.000000000 +0000 +++ libcommons-logging-java-1.1.3/xdocs/style/project.css 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -@import url("http://commons.apache.org/style/commons-maven.css"); diff -Nru libcommons-logging-java-1.1.1/xdocs/tech.xml libcommons-logging-java-1.1.3/xdocs/tech.xml --- libcommons-logging-java-1.1.1/xdocs/tech.xml 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/xdocs/tech.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,653 +0,0 @@ - - - - - - - - Technology Guide - Commons Documentation Team - - - -
- - - - -

- This guide is aimed at describing the technologies that JCL developers and expert users - (and users who need to become experts) - should be familiar with. The aim is to give an understanding whilst being precise but brief. - Details which are not relevant for JCL have been suppressed. - References have been included. -

-

- These topics are a little difficult and it's easy for even experienced developers to make - mistakes. We need you to help us get it right! Please submit corrections, comments, additional references - and requests for clarification - by either: -

- -

- TIA -

-
- -
-
- -

- This is intended to present a guide to the process by which Java bytecode uses bytecode in other classes - from the perspective of the language and virtual machine specifications. The focus will be on deciding - which bytecode will be used (rather than the mechanics of the usage). It focusses on facts and terminology. -

-

- The process is recursive: it is therefore difficult to pick a starting point. - Sun's documentation starts from the persective of the startup of a new application. - This guide starts from the perspective of an executing application. -

-

- During this discussion, please assume that each time that class is mentioned, - the comments applied equally well to interfaces. -

-

- This document is targeted at Java 1.2 and above. -

-
- -

- (LangSpec 12.3.3) - The bytecode representation of a class contains symbolic names for other classes referenced. -

-

- - In practical development terms: If a class is imported (either explicitly in the list of imports at the top of - the source file or implicitly through a fully qualified name in the source code) it is referenced symbolically. - -

-

- (VMSpec 5.4.3) - Resolution of a symbolic reference occurs dynamically at runtime and is carried out by - the Java Virtual Machine. Resolution of a symbolic reference requires loading and linking of the new class. -

-

- - Note: references are not statically resolved at compile time. - -

-
- -

- (VMSpec 2.17.2) - Loading is the name given to the process by which a binary form of a class is obtained - by the Java Virtual Machine. - Java classes are always loaded and linked dynamically by the Java Virtual Machine - (rather than statically by the compiler). -

-

- - In practical development terms: - This means that the developer has no certain knowledge about the actual - bytecode that will be used to execute any external call (one made outside the class). This is determined only - at execution time and is affected by the way that the code is deployed. - -

-
- -

- (VMSpec 2.17.3) - Linking is the name used for combining the - binary form of a class into the Java Virtual Machine. This must happen before the class can be used. -

-

- (VMSpec 2.17.3) - Linking is composed of verification, preparation and resolution (of symbolic references). - Flexibility is allowed over the timing of resolution. (Within limit) this may happen at any time after - preparation and before that reference is used. -

-

- - In practical development terms: This means that different JVMs may realize that a reference cannot be - resolved at different times during execution. Consequently, the actual behaviour cannot be precisely predicted - without intimate knowledge of the JVM (on which the bytecode will be executed). - This makes it hard to give universal guidance to users. - -

-
- - -

- (VMSpec 2.17.2) - The loading process is performed by a ClassLoader. -

-

- (VMSpec 5.3) - A classloader may create a class either by delegation or by defining it directly. - The classloader that initiates loading of a class is known as the initiating loader. - The classloader that defines the class is known as the defining loader. -

-

- - In practical terms: understanding and appreciating this distinction is crucial when debugging issues - concerning classloaders. - -

-
- - -

- (VMSPEC 5.3) - The bootstrap is the base ClassLoader supplied by the Java Virtual Machine. - All others are user (also known as application) ClassLoader instances. -

-

- - In practical development terms: The System classloader returned by Classloader.getSystemClassLoader() - will be either the bootstrap classloader or a direct descendent of the bootstrap classloader. - Only when debugging issues concerning the system classloader should there be any need to consider the detailed - differences between the bootstrap classloader and the system classloader. - -

-
- -

- (VMSpec 5.3) - At runtime, a class (or interface) is determined by its fully qualified name - and by the classloader that defines it. This is known as the class's runtime package. -

-

- (VMSpec 5.4.4) - Only classes in the same runtime package are mutually accessible. -

-

- - In practical development terms: two classes with the same symbolic name can only be used interchangably - if they are defined by the same classloader. A classic symptom indicative of a classloader issue is that - two classes with the same fully qualified name are found to be incompatible during a method call. - This may happen when a member is expecting an interface which is (seemingly) implemented by a class - but the class is in a different runtime package after being defined by a different classloader. This is a - fundamental java language security feature. - -

-
- - -

- (VMSpec 5.3) - The classloader which defines the class (whose reference is being resolved) is the one - used to initiate loading of the class referred to. -

-

- - In practial development terms: This is very important to bear in mind when trying to solve classloader issues. - A classic misunderstanding is this: suppose class A defined by classloader C has a symbolic reference to - class B and further that when C initiates loading of B, this is delegated to classloader D which defines B. - Class B can now only resolve symbols that can be loaded by D, rather than all those which can be loaded by C. - This is a classic recipe for classloader problems. - -

-
- - -
    -
  • - VMSpec The Java Virtual Machine Specification, Second Edition -
  • -
  • - LangSpec The Java Language Specification, Second Edition -
  • -
-
-
-
- -

- When asked to load a class, a class loader may either define the class itself or delegate. - The base ClassLoader class insists that every implementation has a parent class loader. - This delegation model therefore naturally forms a tree structure rooted in the bootstrap classloader. -

-

- Containers (i.e. applications such as servlet engines or application servers - that manage and provide support services for a number of "contained" applications - that run inside of them) often use complex trees to allow isolation of different applications - running within the container. This is particularly true of J2EE containers. -

-
- - -

- When a classloader is asked to load a class, a question presents itself: should it immediately - delegate the loading to its parent (and thus only define those classes not defined by its parent) - or should it try to define it first itself (and only delegate to its parent those classes it does - not itself define). Classloaders which universally adopt the first approach are termed parent-first - and the second child-first. -

-

- Note: the term child-first (though commonly used) is misleading. - A better term (and one which may be encountered on the mailing list) is parent-last. - This more accurately describes the actual process of classloading performed - by such a classloader. -

-

- Parent-first loading has been the standard mechanism in the JDK - class loader, at least since Java 1.2 introduced hierarchical classloaders. -

-

- Child-first classloading has the advantage of helping to improve isolation - between containers and the applications inside them. If an application - uses a library jar that is also used by the container, but the version of - the jar used by the two is different, child-first classloading allows the - contained application to load its version of the jar without affecting the - container. -

-

- The ability for a servlet container to offer child-first classloading - is made available, as an option, by language in the servlet spec (Section - 9.7.2) that allows a container to offer child-first loading with - certain restrictions, such as not allowing replacement of java.* or - javax.* classes, or the container's implementation classes. -

-

- Though child-first and parent-first are not the only strategies possible, - they are by far the most common. - All other strategies are rare. - However, it is not uncommon to be faced with a mixture of parent-first and child-first - classloaders within the same hierarchy. -

-
- - -

- The class loader used to define a class is available programmatically by calling - the getClassLoader method - on the class in question. This is often known as the class classloader. -

-
- - -

- Java 1.2 introduces a mechanism which allows code to access classloaders - which are not the class classloader or one of its parents. - A thread may have a class loader associated with it by its creator for use - by code running in the thread when loading resources and classes. - This classloader is accessed by the getContextClassLoader - method on Thread. It is therefore often known as the context classloader. -

-

- Note that the quality and appropriateness of the context classloader depends on the - care with which the thread's owner manages it. -

-
- - -

- The Javadoc for - - Thread.setContextClassLoader emphasizes the setting of the - context classloader as an aspect of thread creation. However, in many - applications the context classloader is not fixed at thread creation but - rather is changed throughout the life of a thread as thread execution moves - from one context to another. This usage of the context classloader is - particularly important in container applications. -

-

- For example, in a hypothetical servlet container, a pool of threads - is created to handle HTTP requests. When created these threads have their - context classloader set to a classloader that loads container classes. - After the thread is assigned to handle a request, container code parses - the request and then determines which of the deployed web applications - should handle it. Only when the container is about to call code associated - with a particular web application (i.e. is about to cross an "application - boundary") is the context classloader set to the classloader used to load - the web app's classes. When the web application finishes handling the - request and the call returns, the context classloader is set back to the - container classloader. -

-

- In a properly managed container, changes in the context classloader are - made when code execution crosses an application boundary. When contained - application A is handling a request, the context classloader - should be the one used to load A's resources. When application - B is handling a request, the context classloader should be - B's. -

-

- While a contained application is handling a request, it is not - unusual for it to call system or library code loaded by the container. - For example, a contained application may wish to call a utility function - provided by a shared library. This kind of call is considered to be - within the "application boundary", so the context classloader remains - the contained application's classloader. If the system or library code - needs to load classes or other resources only visible to the contained - application's classloader, it can use the context classloader to access - these resources. -

-

- If the context classloader is properly managed, system and library code - that can be accessed by multiple applications can not only use it to load - application-specific resources, but also can use it to detect which - application is making a call and thereby provided services tailored to the - caller. -

-
- - -

- In practice, context classloaders vary in quality and issues sometimes arise - when using them. - The owner of the thread is responsible for setting the classloader. - If the context classloader is not set then it will default to the system - classloader. - Any container doing so will cause difficulties for any code using the context classloader. -

-

- The owner is also at liberty to set the classloader as they wish. - Containers may set the context classloader so that it is neither a child nor a parent - of the classloader that defines the class using that loader. - Again, this will cause difficulties. -

-

- Introduced in Java J2EE 1.3 - is a requirement for vendors to appropriately set the context classloader. - Section 6.2.4.8 (1.4 text): -

- -This specification requires that J2EE containers provide a per thread -context class loader for the use of system or library classes in -dynamicly loading classes provided by the application. The EJB -specification requires that all EJB client containers provide a per -thread context class loader for dynamicly loading system value classes. -The per thread context class loader is accessed using the Thread method -getContextClassLoader. - -The classes used by an application will typically be loaded by a -hierarchy of class loaders. There may be a top level application class -loader, an extension class loader, and so on, down to a system class -loader. The top level application class loader delegates to the lower -class loaders as needed. Classes loaded by lower class loaders, such as -portable EJB system value classes, need to be able to discover the top -level application class loader used to dynamicly load application -classes. - -We require that containers provide a per thread context class loader -that can be used to load top level application classes as described -above. - -

- This specification leaves quite a lot of freedom for vendors. - (As well as using unconventional terminology and containing the odd typo.) - It is a difficult passage (to say the least). -

-
- - -

- Reflection cannot bypass restrictions imposed by the java language security model, but, by avoiding symbolic - references, reflection can be used to load classes which could not otherwise be loaded. Another ClassLoader - can be used to load a class and then reflection used to create an instance. -

-

- Recall that the runtime packaging is used to determine accessibility. - Reflection cannot be used to avoid basic java security. - Therefore, the runtime packaging becomes an issue when attempting to cast classes - created by reflection using other class loaders. - When using this strategy, various modes of failure are possible - when common class references are defined by the different class loaders. -

-

- Reflection is often used with the context classloader. In theory, this allows a class defined in - a parent classloader to load any class that is loadable by the application. - In practice, this only works well when the context classloader is set carefully. -

-
- - - - -
- -
- -

- JCL takes the view that different context class loader indicate boundaries between applications - running in a container environment. Isolation requires that JCL honours these boundaries - and therefore allows different isolated applications to configure their logging systems - independently. -

-
- -

- Performance dictates that symbolic references to these classes are present in the calling application code - (reflection would simply be too slow). Therefore, these classes must be loadable by the classloader - that loads the application code. -

-
- -

- Performance dictates that symbolic references to the logging systems are present in the implementation - classes (again, reflection would simply be too slow). So, for an implementation to be able to function, - it is neccessary for the logging system to be loadable by the classloader that defines the implementing class. -

-
- - -

- However, there is actually no reason why LogFactory requires symbolic references to particular Log - implementations. Reflection can be used to load these from an appropriate classloader - without unacceptable performance degradation. - This is the strategy adopted by JCL. -

-

- JCL uses the context classloader to load the Log implementation. -

-
-
- -
diff -Nru libcommons-logging-java-1.1.1/xdocs/troubleshooting.xml libcommons-logging-java-1.1.3/xdocs/troubleshooting.xml --- libcommons-logging-java-1.1.1/xdocs/troubleshooting.xml 2007-11-21 23:27:47.000000000 +0000 +++ libcommons-logging-java-1.1.3/xdocs/troubleshooting.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,467 +0,0 @@ - - - - - - - - Troubleshooting Guide - Commons Documentation Team - - - -
-
-
-

-Diagnostics is a feature introduced in JCL 1.1 as an aid to debugging problems -with JCL configurations. When diagnostics are switched on, messages are logged -to a stream (specified by the user) by the two main classes involved in discovery -in JCL (LogFactory and LogFactoryImpl). -

-

-Diagnostics are intended to be used in conjunction with the source. The source -contains numerous and lengthy comments. Often these are intended to help explain -the meaning of the messages. -

- -

-Diagnostic logging is intended only to be used when debugging a problematic -configuration. It should be switched off for production. -

-
- -

-Diagnostic logging is controlled through the system property -org.apache.commons.logging.diagnostics.dest. Setting the property value -to the special strings STDOUT or STDERR (case-sensitive) -will output messages to System.out and System.err respectively. -Setting the property value to a valid file name will result in the messages being logged -to that file. -

-
- -

-Diagnostics uses the concept of an Object ID (OID). This allows the identity of objects -to be tracked without relying on useful toString implementations. -These are of the form: -

-
-classname@system identity hash code
-
-

-The system identity hash code is found by calling System.identityHashCode() -which should uniquely identify a particular instance. The classname is usually the fully qualified -class name though in a few cases, org.apache.commons.logging.impl.LogFactoryImpl may be -shortened to LogFactoryImpl to increase ease of reading. For example: -

-
-sun.misc.Launcher$AppClassLoader@20120943
-LogFactoryImpl@1671711
-
-

-OIDs are intended to be used to cross-reference. They allow particular instances of classloaders -and JCL classes to be tracked in different contexts. This plays a vital role in building -up the understanding of the classloader environment required to diagnose JCL problems. -

-
- -

-Each diagnostic message is prefixed with details of the relevant class in a standard format. -This takes the form: -

-
-[class-identifier from ClassLoader OID]
-
-

-ClassLoader OID is the OID of a classloader which loaded -the class issuing the message. -class-identifier identifies the object issuing the message. -

-

-In the case of -LogFactory, this is just LogFactory. For example (line split): -

-
-[LogFactory 
-   from sun.misc.Launcher$AppClassLoader@20120943] BOOTSTRAP COMPLETED
-
-

-In the case of -LogFactoryImpl, the prefix is the instance OID. This can be cross referenced -to discover the details of the TCCL used to manage this instance. For example (line split): -

-
-[LogFactoryImpl@1671711 
-   from sun.misc.Launcher$AppClassLoader@20120943] Instance created.
-
-
- -

-Understanding the relationships between classloaders is vital when debugging JCL. -At various points, JCL will print to the diagnostic log the hierarchy for important -classloaders. This is obtained by walking the tree using getParent. -Each classloader is represented (visually) by an OID (to allow cross referencing) -and the relationship indicated in child --> parent fashion. -For example (line split for easy reading): -

-
-ClassLoader tree:java.net.URLClassLoader@3526198  
-      --> sun.misc.Launcher$AppClassLoader@20120943 (SYSTEM) 
-      --> sun.misc.Launcher$ExtClassLoader@11126876 
-      --> BOOT
-
-

-Represents a hierarchy with four elements ending in the boot classloader. -

-
- -

-Whenever the LogFactory class is initialized, diagnostic messages about -the classloader environment are logged. The content of each of these messages is prefixed by -[ENV] to help distinguish them. The extension directories, application classpath, -details of the classloader (including the OID and toString -value) used to load LogFactory and the -classloader tree for that classloader -are logged. -

-

-Many Sun classloaders have confusing toString values. For example, the OID may be -

-
-sun.misc.Launcher$AppClassLoader@20120943
-
-

-with a toString value of -

-
-sun.misc.Launcher$AppClassLoader@133056f
-
-

-Other classloader implementations may give very useful information (such as the local classpath). -

-

-Finally, once initialization is complete a BOOTSTRAP COMPLETED message is issued. -

-
- -

-LogFactoryImpl is the standard and default LogFactory implementation. -This section obviously only applies to configurations using this implementation. -

-

-Before assigning a Log instance, LogFactory loads a -LogFactory implementation. The content is prefixed by [LOOKUP] -for each diagnostic message logged by this process. -

-

-The implementation used can vary per Thread context classloader (TCCL). If this is the first time -that a Log has been requested for a particular TCCL a new instance will be created. -

-

-Information of particular interest is logged at this stage. Details of the TCCL are logged -allowing the OID later to be cross-referenced to the toString value -and the classloader tree. For example, the -following log snippet details the TCCL (lines split): -

-
-[LogFactory from sun.misc.Launcher$AppClassLoader@20120943] 
-    [LOOKUP] LogFactory implementation requested for the first time for context 
-        classloader java.net.URLClassLoader@3526198
-[LogFactory from sun.misc.Launcher$AppClassLoader@20120943] 
-    [LOOKUP] java.net.URLClassLoader@3526198 == 'java.net.URLClassLoader@35ce36'
-[LogFactory from sun.misc.Launcher$AppClassLoader@20120943] 
-    [LOOKUP] ClassLoader tree:java.net.URLClassLoader@3526198 
-        --> sun.misc.Launcher$AppClassLoader@20120943 (SYSTEM)  
-          --> sun.misc.Launcher$ExtClassLoader@11126876 
-            --> BOOT
-
-
- -

-The standard LogFactoryImpl issues many diagnostic messages when discovering -the Log implementation to be used. -

-

-During discovery, environment variables are loaded and values set. This content is prefixed by -[ENV] to make it easier to distinguish this material. -

-

-The possible messages issued during discovery are numerous. To understand them, the source -should be consulted. Attention should be paid to the classloader hierarchy trees for the -classloader used to load LogFactory and to the TCCL. -

-
-
-
-

- Some containers use a custom LogFactory implementation to adapt JCL to their particular - logging system. This has some important consequences for the deployment of applications using JCL within - these containers. -

-

- Containers known to use this mechanism: -

- -

- Containers suspected to use this mechanism: -

-
    -
  • WebSphere Application Server (other versions).
  • -
-

-The Apache Commons team would be grateful if reports were posted to the development list -of other containers using a custom implementation. -

- - -

- An exception is thrown by JCL with a message similar to: -

-
-  The chosen LogFactory implementation does not extend LogFactory. Please check your configuration. 
-  (Caused by java.lang.ClassCastException: The application has specified that a custom LogFactory 
-  implementation should be used but Class 'com.ibm.ws.commons.logging.TrLogFactory' cannot be converted 
-  to 'org.apache.commons.logging.LogFactory'. The conflict is caused by the presence of multiple 
-  LogFactory classes in incompatible classloaders. Background can be found in 
-  http://commons.apache.org/logging/tech.html. If you have not explicitly specified a custom
-  LogFactory then it is likely that the container has set one without your knowledge. 
-  In this case, consider using the commons-logging-adapters.jar file or specifying the standard 
-  LogFactory from the command line. Help can be found @http://commons.apache.org/logging.
-  
-

- This is a WebSphere example so the name of the custom LogFactory is - com.ibm.ws.commons.logging.TrLogFactory. For other containers, this class name will - differ. -

-
- -

- A custom LogFactory implementation can only be used if the implementation class loaded - dynamically at runtime can be cast to the LogFactory class that loaded it. There are - several ways in which this cast can fail. The most obvious is that the source code may not actually - extend LogFactory. The source may be compatible but if the LogFactory class - against which the source is compiled is not binary compatible then the cast will also fail. -

-

- There is also another more unusual way in which this cast can fail: even when the binary is compatible, - the implementation class loaded at runtime may be linked to a different instance of the - LogFactory class. For more information, see the tech guide. -

-

- This situation may be encountered in containers which use a custom LogFactory implementation. - The implementation will typically be provided in a shared, high level classloader together with JCL. - When an application classloader contains LogFactory, the implementation will be loaded - from that higher level classloader. The implementation class will be linked to the LogFactory - class loaded by the higher level classloader. Even if the - LogFactory implementations are binary compatible, since they are loaded by different classloaders - the two LogFactory Class instances are not equal and so the cast must fail. -

-

-The policy adopted by JCL in this situation is to re-throw this exception. Additional information -is included in the message to help diagnosis. The reasoning behind this choice is that a -particular LogFactory implementation has been actively specified and this -choice should not be ignored. This policy has unfortunate consequences when running in -containers which have custom implementations: the above runtime exception may be thrown -under certain classloading policies without the user knowingly specifying a custom -implementation. -

-
- -

- There are various ways to fix this problem. Which fix is right depends on the circumstances. -

-

- If you are happy using another classloading policy for the application, select a - classloading policy which ensures that LogFactory will be loaded from the - shared classloader containing the custom implementation. -

-

- If you want to bypass the container adaption mechanism then set the appropriate system property - to the default value when the container is started: -

-
- -Dorg.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
- 
-

- If you want to continue to use the default container mechanism then: -

-
    -
  • - Find and replace the commons-logging implementation used by the container with - the most modern release -
  • -
  • - Replace the commons-logging jar in the application with the commons-logging-adapters jar. - This will ensure that application classloader will delegate to it's parent when loading - LogFactory. -
  • -
-

- If you encounter difficulties when applying the fixes recommended, please turn on - diagnostics and consult the logs. -

-
-
-
-
-

- Because commons-logging is such a fundamental library, some containers modify the way - in which classloading behaves for commons-logging classes. -

- -

- At the current date, Tomcat 5.5.16 is the current release. All releases from version - 4.1.x through 5.5.16 have a startup process that places jarfile - ${tomcat.home}/bin/commons-logging-api.jar in the system classpath and then - prevents any webapp from overriding the classes in that jarfile. Effectively, all - webapps behave as if "parent-first" classloading were enabled for those classes. -

-

- This has some benefits; in particular it means that there are no problems in - these Tomcat versions with having multiple copies of the commons-logging Log - interface in the classpath (which avoids the "Log does not implement Log" - problem described elsewhere). -

-

- However it also means that no webapp can override the core commons-logging - classes by including an updated commons-logging jarfile in WEB-INF/lib; any - class already loaded via the container takes priority. In particular, as - Tomcat bundles logging 1.0.4 only, the new diagnostics and memory-leak-prevention - features of the 1.1 release will not be available unless the container's - library version is updated. -

-

- Because the commons-logging-api.jar in the container does not contain any - log-library-adapter classes, updated behaviour for these will be - seen when logging 1.1 is bundled in WEB-INF/lib. In particular, the - support for log4j's TRACE level will take effect without having to update - the container. -

-

- If you do wish to update Tomcat's version of commons-logging, then you - must use the commons-logging-1.1-api jar only, not the full jar. - Classes in the webapp cannot override classes loaded from the system - classpath set up during Tomcat's startup process, and logging adapters - can only see their matching concrete logging library if that library is - available in the same classpath. Bundling the full commons-logging jarfile - (with adapters) into the system classpath therefore means that logging - libraries (eg log4j) within WEB-INF/lib are not accessable. -

-

- Note that the behaviour described here only applies if the standard Tomcat - startup process is run. When Tomcat is embedded in a larger - framework (eg run embedded within an IDE) this may not apply. -

-
- -

- The JBoss Application Server can be configured to prevent deployed - code from overriding classes higher in the hierarchy, effectively - forcing "parent-first" behaviour for selected classes. By default, - commons-logging is in this list (at least for some JBoss versions - starting with 4.0.2), and therefore including an updated version - of commons-logging in WEB-INF/lib or similar will have no effect. - See the JBoss classloading documentation for more details. -

-
- -

- As more information becomes available on this topic, it may be added - to the commons-logging wiki site. -

-
-
- -