Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 30993 invoked from network); 28 Jul 2004 20:26:08 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 28 Jul 2004 20:26:08 -0000 Received: (qmail 50370 invoked by uid 500); 28 Jul 2004 20:25:56 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 50268 invoked by uid 500); 28 Jul 2004 20:25:54 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 50220 invoked by uid 99); 28 Jul 2004 20:25:54 -0000 X-ASF-Spam-Status: No, hits=0.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.27.1) with SMTP; Wed, 28 Jul 2004 13:25:48 -0700 Received: (qmail 30744 invoked by uid 65534); 28 Jul 2004 20:25:44 -0000 Date: 28 Jul 2004 20:25:44 -0000 Message-ID: <20040728202544.30741.qmail@minotaur.apache.org> From: ugo@apache.org To: cvs@cocoon.apache.org Subject: svn commit: rev 30863 - in cocoon/branches: . bin bin/org bin/org/apache bin/org/apache/butterfly bin/org/apache/butterfly/components bin/org/apache/butterfly/components/pipeline bin/org/apache/butterfly/components/pipeline/impl bin/org/apache/butterfly/environment bin/org/apache/butterfly/generation bin/org/apache/butterfly/reading bin/org/apache/butterfly/serialization bin/org/apache/butterfly/sitemap bin/org/apache/butterfly/source bin/org/apache/butterfly/source/impl bin/org/apache/butterfly/source/impl/validity bin/org/apache/butterfly/test bin/org/apache/butterfly/transformation bin/org/apache/butterfly/xml bin/org/apache/butterfly/xml/dom bin/org/apache/butterfly/xml/xslt lib lib/endorsed src src/java src/java/org src/java/org/apache src/java/org/apache/butterfly src/java/org/apache/butterfly/components src/java/org/apache/butterfly/components/pipeline src/java/org/apache/butterfly/components/pipeline/impl src/java/org/apache/butterfly/environment src/java/org/apache/butterfly/generation src/java/org/apache/butterfly/reading src/java/org/apache/butterfly/serialization src/java/org/apache/butterfly/sitemap src/java/org/apache/butterfly/source src/java/org/apache/butterfly/source/impl src/java/org/apache/butterfly/source/impl/validity src/java/org/apache/butterfly/transformation src/java/org/apache/butterfly/xml src/java/org/apache/butterfly/xml/dom src/java/org/apache/butterfly/xml/xslt src/test src/test/org src/test/org/apache src/test/org/apache/butterfly src/test/org/apache/butterfly/components src/test/org/apache/butterfly/components/pipeline src/test/org/apache/butterfly/components/pipeline/impl src/test/org/apache/butterfly/generation src/test/org/apache/butterfly/serialization src/test/org/apache/butterfly/source src/test/org/apache/butterfly/test src/test/org/apache/butterfly/transformation testdata tools tools/lib X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N Author: ugo Date: Wed Jul 28 13:25:41 2004 New Revision: 30863 Added: cocoon/branches/.classpath cocoon/branches/.project cocoon/branches/LICENSE.txt cocoon/branches/NOTICE.txt cocoon/branches/bin/ cocoon/branches/bin/beans.xml cocoon/branches/bin/log4j.properties cocoon/branches/bin/org/ cocoon/branches/bin/org/apache/ cocoon/branches/bin/org/apache/butterfly/ cocoon/branches/bin/org/apache/butterfly/components/ cocoon/branches/bin/org/apache/butterfly/components/pipeline/ cocoon/branches/bin/org/apache/butterfly/components/pipeline/InvalidPipelineException.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/components/pipeline/PipelineException.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/components/pipeline/PipelineProcessingException.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/components/pipeline/ProcessingPipeline.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/ cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/GroovySitemapTestCase.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/MyPipeline.groovy cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipeline.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase$1.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase$2.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase$3.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase$4.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/Pipeline.groovy cocoon/branches/bin/org/apache/butterfly/environment/ cocoon/branches/bin/org/apache/butterfly/environment/Environment.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/generation/ cocoon/branches/bin/org/apache/butterfly/generation/FileGenerator.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/generation/FileGeneratorTestCase.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/generation/Generator.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/reading/ cocoon/branches/bin/org/apache/butterfly/reading/Reader.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/serialization/ cocoon/branches/bin/org/apache/butterfly/serialization/Serializer.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/serialization/XMLSerializer.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/serialization/XMLSerializerTestCase.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/sitemap/ cocoon/branches/bin/org/apache/butterfly/sitemap/SitemapOutputComponent.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/ cocoon/branches/bin/org/apache/butterfly/source/Source.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/SourceException.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/SourceFactory.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/SourceNotFoundException.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/SourceResolver.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/SourceResolverTestCase.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/SourceUtil.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/SourceValidity.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/URIAbsolutizer.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/impl/ cocoon/branches/bin/org/apache/butterfly/source/impl/FileSource.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/impl/FileSourceFactory.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/impl/URLSource.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/impl/URLSourceFactory.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/source/impl/validity/ cocoon/branches/bin/org/apache/butterfly/source/impl/validity/FileTimeStampValidity.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/test/ cocoon/branches/bin/org/apache/butterfly/test/SitemapComponentTestCase.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/transformation/ cocoon/branches/bin/org/apache/butterfly/transformation/Transformer.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/transformation/TraxTransformer.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/transformation/TraxTransformerTestCase.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/ cocoon/branches/bin/org/apache/butterfly/xml/AbstractXMLPipe.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/AbstractXMLProducer.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/EmbeddedXMLPipe.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/Parser.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/WhitespaceFilter.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/XMLConsumer.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/XMLException.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/XMLPipe.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/XMLProducer.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/dom/ cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMBuilder$Listener.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMBuilder.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMStreamer$DefaultDOMStreamer.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMStreamer$NamespaceNormalizingDOMStreamer$ElementInfo.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMStreamer$NamespaceNormalizingDOMStreamer.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMStreamer.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/xslt/ cocoon/branches/bin/org/apache/butterfly/xml/xslt/TraxException.class (contents, props changed) cocoon/branches/bin/org/apache/butterfly/xml/xslt/TraxTransformerFactory.class (contents, props changed) cocoon/branches/lib/ cocoon/branches/lib/aopalliance.jar (contents, props changed) cocoon/branches/lib/asm-1.4.1.jar (contents, props changed) cocoon/branches/lib/asm-util-1.4.3.jar (contents, props changed) cocoon/branches/lib/commons-lang-2.0.jar (contents, props changed) cocoon/branches/lib/commons-logging-1.0.4.jar (contents, props changed) cocoon/branches/lib/endorsed/ cocoon/branches/lib/endorsed/jakarta-bcel-20040329.jar (contents, props changed) cocoon/branches/lib/endorsed/jakarta-regexp-1.3.jar (contents, props changed) cocoon/branches/lib/endorsed/xalan-2.6.0.jar (contents, props changed) cocoon/branches/lib/endorsed/xercesImpl-2.6.2.jar (contents, props changed) cocoon/branches/lib/endorsed/xml-apis.jar (contents, props changed) cocoon/branches/lib/groovy-1.0-beta-6.jar (contents, props changed) cocoon/branches/lib/log4j-1.2.8.jar (contents, props changed) cocoon/branches/lib/spring-aop.jar (contents, props changed) cocoon/branches/lib/spring-context.jar (contents, props changed) cocoon/branches/lib/spring-core.jar (contents, props changed) cocoon/branches/src/ cocoon/branches/src/java/ cocoon/branches/src/java/org/ cocoon/branches/src/java/org/apache/ cocoon/branches/src/java/org/apache/butterfly/ cocoon/branches/src/java/org/apache/butterfly/components/ cocoon/branches/src/java/org/apache/butterfly/components/pipeline/ cocoon/branches/src/java/org/apache/butterfly/components/pipeline/InvalidPipelineException.java cocoon/branches/src/java/org/apache/butterfly/components/pipeline/PipelineException.java cocoon/branches/src/java/org/apache/butterfly/components/pipeline/PipelineProcessingException.java cocoon/branches/src/java/org/apache/butterfly/components/pipeline/ProcessingPipeline.java cocoon/branches/src/java/org/apache/butterfly/components/pipeline/impl/ cocoon/branches/src/java/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipeline.java cocoon/branches/src/java/org/apache/butterfly/environment/ cocoon/branches/src/java/org/apache/butterfly/environment/Environment.java cocoon/branches/src/java/org/apache/butterfly/generation/ cocoon/branches/src/java/org/apache/butterfly/generation/FileGenerator.java cocoon/branches/src/java/org/apache/butterfly/generation/Generator.java cocoon/branches/src/java/org/apache/butterfly/reading/ cocoon/branches/src/java/org/apache/butterfly/reading/Reader.java cocoon/branches/src/java/org/apache/butterfly/serialization/ cocoon/branches/src/java/org/apache/butterfly/serialization/Serializer.java cocoon/branches/src/java/org/apache/butterfly/serialization/XMLSerializer.java cocoon/branches/src/java/org/apache/butterfly/sitemap/ cocoon/branches/src/java/org/apache/butterfly/sitemap/SitemapOutputComponent.java cocoon/branches/src/java/org/apache/butterfly/source/ cocoon/branches/src/java/org/apache/butterfly/source/Source.java cocoon/branches/src/java/org/apache/butterfly/source/SourceException.java cocoon/branches/src/java/org/apache/butterfly/source/SourceFactory.java cocoon/branches/src/java/org/apache/butterfly/source/SourceNotFoundException.java cocoon/branches/src/java/org/apache/butterfly/source/SourceResolver.java cocoon/branches/src/java/org/apache/butterfly/source/SourceUtil.java cocoon/branches/src/java/org/apache/butterfly/source/SourceValidity.java cocoon/branches/src/java/org/apache/butterfly/source/URIAbsolutizer.java cocoon/branches/src/java/org/apache/butterfly/source/impl/ cocoon/branches/src/java/org/apache/butterfly/source/impl/FileSource.java cocoon/branches/src/java/org/apache/butterfly/source/impl/FileSourceFactory.java cocoon/branches/src/java/org/apache/butterfly/source/impl/URLSource.java cocoon/branches/src/java/org/apache/butterfly/source/impl/URLSourceFactory.java cocoon/branches/src/java/org/apache/butterfly/source/impl/validity/ cocoon/branches/src/java/org/apache/butterfly/source/impl/validity/FileTimeStampValidity.java cocoon/branches/src/java/org/apache/butterfly/transformation/ cocoon/branches/src/java/org/apache/butterfly/transformation/Transformer.java cocoon/branches/src/java/org/apache/butterfly/transformation/TraxTransformer.java cocoon/branches/src/java/org/apache/butterfly/xml/ cocoon/branches/src/java/org/apache/butterfly/xml/AbstractXMLPipe.java cocoon/branches/src/java/org/apache/butterfly/xml/AbstractXMLProducer.java cocoon/branches/src/java/org/apache/butterfly/xml/EmbeddedXMLPipe.java cocoon/branches/src/java/org/apache/butterfly/xml/Parser.java cocoon/branches/src/java/org/apache/butterfly/xml/WhitespaceFilter.java cocoon/branches/src/java/org/apache/butterfly/xml/XMLConsumer.java cocoon/branches/src/java/org/apache/butterfly/xml/XMLException.java cocoon/branches/src/java/org/apache/butterfly/xml/XMLPipe.java cocoon/branches/src/java/org/apache/butterfly/xml/XMLProducer.java cocoon/branches/src/java/org/apache/butterfly/xml/dom/ cocoon/branches/src/java/org/apache/butterfly/xml/dom/DOMBuilder.java cocoon/branches/src/java/org/apache/butterfly/xml/dom/DOMStreamer.java cocoon/branches/src/java/org/apache/butterfly/xml/xslt/ cocoon/branches/src/java/org/apache/butterfly/xml/xslt/TraxException.java cocoon/branches/src/java/org/apache/butterfly/xml/xslt/TraxTransformerFactory.java cocoon/branches/src/test/ cocoon/branches/src/test/beans.xml cocoon/branches/src/test/log4j.properties cocoon/branches/src/test/org/ cocoon/branches/src/test/org/apache/ cocoon/branches/src/test/org/apache/butterfly/ cocoon/branches/src/test/org/apache/butterfly/components/ cocoon/branches/src/test/org/apache/butterfly/components/pipeline/ cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/ cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/GroovySitemapTestCase.java cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/MyPipeline.groovy cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase.java cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/Pipeline.groovy cocoon/branches/src/test/org/apache/butterfly/generation/ cocoon/branches/src/test/org/apache/butterfly/generation/FileGeneratorTestCase.java cocoon/branches/src/test/org/apache/butterfly/serialization/ cocoon/branches/src/test/org/apache/butterfly/serialization/XMLSerializerTestCase.java cocoon/branches/src/test/org/apache/butterfly/source/ cocoon/branches/src/test/org/apache/butterfly/source/SourceResolverTestCase.java cocoon/branches/src/test/org/apache/butterfly/test/ cocoon/branches/src/test/org/apache/butterfly/test/SitemapComponentTestCase.java cocoon/branches/src/test/org/apache/butterfly/transformation/ cocoon/branches/src/test/org/apache/butterfly/transformation/TraxTransformerTestCase.java cocoon/branches/testdata/ cocoon/branches/testdata/test1.xml cocoon/branches/testdata/traxtest-input.xml cocoon/branches/testdata/traxtest-result.xml cocoon/branches/testdata/traxtest-style.xsl cocoon/branches/tools/ cocoon/branches/tools/lib/ cocoon/branches/tools/lib/jmock-1.0.1.jar (contents, props changed) cocoon/branches/tools/lib/xmlunit1.0.jar (contents, props changed) Log: Initial impport of Butterfly Added: cocoon/branches/.classpath ============================================================================== --- (empty file) +++ cocoon/branches/.classpath Wed Jul 28 13:25:41 2004 @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + Added: cocoon/branches/.project ============================================================================== --- (empty file) +++ cocoon/branches/.project Wed Jul 28 13:25:41 2004 @@ -0,0 +1,17 @@ + + + Butterfly + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + Added: cocoon/branches/LICENSE.txt ============================================================================== --- (empty file) +++ cocoon/branches/LICENSE.txt Wed Jul 28 13:25:41 2004 @@ -0,0 +1,201 @@ + 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. Added: cocoon/branches/NOTICE.txt ============================================================================== --- (empty file) +++ cocoon/branches/NOTICE.txt Wed Jul 28 13:25:41 2004 @@ -0,0 +1,2 @@ +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). Added: cocoon/branches/bin/beans.xml ============================================================================== --- (empty file) +++ cocoon/branches/bin/beans.xml Wed Jul 28 13:25:41 2004 @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.apache.xerces.parsers.SAXParser + + + + + + + + + + + + + + + + + + + + + + + + UTF-8 + + + + Added: cocoon/branches/bin/log4j.properties ============================================================================== --- (empty file) +++ cocoon/branches/bin/log4j.properties Wed Jul 28 13:25:41 2004 @@ -0,0 +1,15 @@ +# Configure logging for testing + +log4j.rootCategory=WARN, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p %c - %m%n + +#log4j.category.org.springframework.aop.framework.ProxyFactoryBean=DEBUG + +log4j.category.org.springframework.enterpriseservices=DEBUG + +log4j.category.org.springframework.transaction.interceptor=INFO + +log4j.category.org.springframework.beans.factory=INFO Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/InvalidPipelineException.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/PipelineException.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/PipelineProcessingException.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/ProcessingPipeline.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/GroovySitemapTestCase.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/MyPipeline.groovy ============================================================================== --- (empty file) +++ cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/MyPipeline.groovy Wed Jul 28 13:25:41 2004 @@ -0,0 +1,13 @@ +class MyPipeline extends Pipeline { + + void define(String requestPath) { + if (requestPath =~ ".*\.html") { + generate "testdata/traxtest-input.xml" + transform "trax", "testdata/traxtest-style.xsl" + serialize "xml" + } + else { + println("No matches for " + requestPath); + } + } +} \ No newline at end of file Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipeline.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase$1.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase$2.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase$3.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase$4.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/Pipeline.groovy ============================================================================== --- (empty file) +++ cocoon/branches/bin/org/apache/butterfly/components/pipeline/impl/Pipeline.groovy Wed Jul 28 13:25:41 2004 @@ -0,0 +1,34 @@ +import org.apache.butterfly.xml.dom.DOMBuilder +import org.apache.butterfly.components.pipeline.impl.NonCachingProcessingPipeline + +class Pipeline { + public beanFactory; + private pipeline; + + protected Pipeline() { + this.pipeline = new NonCachingProcessingPipeline() + } + + protected void generate(src) { + generator = beanFactory.getBean("fileGenerator") + generator.inputSource = src + this.pipeline.generator = generator + } + + protected void transform(type, src) { + factory = beanFactory.getBean(type + "TransformerFactory") + transformer = factory.getTransformer(src) + this.pipeline.addTransformer(transformer) + } + + protected void serialize(type) { + serializer = beanFactory.getBean(type + "Serializer") + this.pipeline.serializer = serializer + } + + public void process() { + builder = new DOMBuilder() + this.pipeline.process(null, builder) + println(builder.document.documentElement) + } +} \ No newline at end of file Added: cocoon/branches/bin/org/apache/butterfly/environment/Environment.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/generation/FileGenerator.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/generation/FileGeneratorTestCase.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/generation/Generator.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/reading/Reader.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/serialization/Serializer.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/serialization/XMLSerializer.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/serialization/XMLSerializerTestCase.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/sitemap/SitemapOutputComponent.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/Source.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/SourceException.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/SourceFactory.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/SourceNotFoundException.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/SourceResolver.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/SourceResolverTestCase.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/SourceUtil.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/SourceValidity.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/URIAbsolutizer.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/impl/FileSource.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/impl/FileSourceFactory.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/impl/URLSource.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/impl/URLSourceFactory.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/source/impl/validity/FileTimeStampValidity.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/test/SitemapComponentTestCase.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/transformation/Transformer.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/transformation/TraxTransformer.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/transformation/TraxTransformerTestCase.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/AbstractXMLPipe.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/AbstractXMLProducer.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/EmbeddedXMLPipe.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/Parser.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/WhitespaceFilter.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/XMLConsumer.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/XMLException.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/XMLPipe.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/XMLProducer.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMBuilder$Listener.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMBuilder.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMStreamer$DefaultDOMStreamer.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMStreamer$NamespaceNormalizingDOMStreamer$ElementInfo.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMStreamer$NamespaceNormalizingDOMStreamer.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/dom/DOMStreamer.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/xslt/TraxException.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/bin/org/apache/butterfly/xml/xslt/TraxTransformerFactory.class ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/aopalliance.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/asm-1.4.1.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/asm-util-1.4.3.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/commons-lang-2.0.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/commons-logging-1.0.4.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/endorsed/jakarta-bcel-20040329.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/endorsed/jakarta-regexp-1.3.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/endorsed/xalan-2.6.0.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/endorsed/xercesImpl-2.6.2.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/endorsed/xml-apis.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/groovy-1.0-beta-6.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/log4j-1.2.8.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/spring-aop.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/spring-context.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/lib/spring-core.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/src/java/org/apache/butterfly/components/pipeline/InvalidPipelineException.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/components/pipeline/InvalidPipelineException.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,55 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.components.pipeline; + + +/** + * This exception is thrown whenever you try to assemble an invalid pipeline. + * + * @version CVS $Id: InvalidPipelineException.java,v 1.1 2004/07/24 20:21:33 ugo Exp $ + */ +public class InvalidPipelineException extends PipelineException { + + /** + * + */ + public InvalidPipelineException() { + super(); + } + + /** + * @param arg0 + */ + public InvalidPipelineException(String arg0) { + super(arg0); + } + + /** + * @param arg0 + * @param arg1 + */ + public InvalidPipelineException(String arg0, Throwable arg1) { + super(arg0, arg1); + } + + /** + * @param arg0 + */ + public InvalidPipelineException(Throwable arg0) { + super(arg0); + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/components/pipeline/PipelineException.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/components/pipeline/PipelineException.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,55 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.components.pipeline; + + +/** + * Base class for all exceptions thrown during pipeline processing. + * + * @version CVS $Id: PipelineException.java,v 1.1 2004/07/24 20:21:33 ugo Exp $ + */ +public abstract class PipelineException extends RuntimeException { + + /** + * + */ + public PipelineException() { + super(); + } + + /** + * @param arg0 + */ + public PipelineException(String arg0) { + super(arg0); + } + + /** + * @param arg0 + * @param arg1 + */ + public PipelineException(String arg0, Throwable arg1) { + super(arg0, arg1); + } + + /** + * @param arg0 + */ + public PipelineException(Throwable arg0) { + super(arg0); + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/components/pipeline/PipelineProcessingException.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/components/pipeline/PipelineProcessingException.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,55 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.components.pipeline; + + +/** + * This exception can be thrown when executing a pipeline. + * + * @version CVS $Id: PipelineProcessingException.java,v 1.1 2004/07/25 21:55:20 ugo Exp $ + */ +public class PipelineProcessingException extends PipelineException { + + /** + * + */ + public PipelineProcessingException() { + super(); + } + + /** + * @param arg0 + */ + public PipelineProcessingException(String arg0) { + super(arg0); + } + + /** + * @param arg0 + * @param arg1 + */ + public PipelineProcessingException(String arg0, Throwable arg1) { + super(arg0, arg1); + } + + /** + * @param arg0 + */ + public PipelineProcessingException(Throwable arg0) { + super(arg0); + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/components/pipeline/ProcessingPipeline.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/components/pipeline/ProcessingPipeline.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,132 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.components.pipeline; + +import org.apache.butterfly.environment.Environment; +import org.apache.butterfly.generation.Generator; +import org.apache.butterfly.reading.Reader; +import org.apache.butterfly.serialization.Serializer; +import org.apache.butterfly.source.SourceValidity; +import org.apache.butterfly.transformation.Transformer; +import org.apache.butterfly.xml.XMLConsumer; + + +/** + * A ProcessingPipeline produces the response for a given request. + * It is assembled according to the commands in the sitemap and can either + *
    + *
  • collect a Reader and let it produce a character stream
  • + *
  • or connect a Generator with zero or more + * Transformers and a Serializer and let them + * produce the byte stream. This pipeline uses SAX events for + * communication. + *
  • + *
+ * + * @version CVS $Id: ProcessingPipeline.java,v 1.2 2004/07/24 20:21:33 ugo Exp $ + */ +public interface ProcessingPipeline { + + /** + * Setup this component + */ + // void setup(Parameters params); + + /** + * Set the generator that will be used as the initial step in the pipeline. + * The generator role is given : the actual Generator is fetched + * from the latest ComponentManager given by compose() + * or recompose(). + * + * @param role the generator role in the component manager. + * @param source the source where to produce XML from, or null if no + * source is given. + * @param param the parameters for the generator. + * @throws ProcessingException if the generator couldn't be obtained. + */ + void setGenerator(Generator generator); + + /** + * Get the generator - used for content aggregation + */ + Generator getGenerator(); + + /** + * Informs pipeline we have come across a branch point + */ + void informBranchPoint(); + + /** + * Add a transformer at the end of the pipeline. + * The transformer role is given : the actual Transformer is fetched + * from the latest ComponentManager given by compose() + * or recompose(). + * + * @param role the transformer role in the component manager. + * @param source the source used to setup the transformer (e.g. XSL file), or + * null if no source is given. + * @param param the parameters for the transfomer. + * @throws ProcessingException if the generator couldn't be obtained. + */ + void addTransformer(Transformer transformer); + + /** + * Set the serializer for this pipeline + * @param mimeType Can be null + */ + void setSerializer(Serializer serializer); + + /** + * Set the reader for this pipeline + * @param mimeType Can be null + */ + void setReader(Reader reader); + + /** + * Process the given Environment, producing the output. + */ + boolean process(Environment environment); + + /** + * Prepare an internal processing + * @param environment The current environment. + * @throws ProcessingException + */ + void prepareInternal(Environment environment); + + /** + * Process the given Environment, but do not use the + * serializer. Instead the sax events are streamed to the XMLConsumer. + * Make sure to call {@link #prepareInternal(Environment)} beforehand. + */ + boolean process(Environment environment, XMLConsumer consumer); + + /** + * Return valid validity objects for the event pipeline + * If the "event pipeline" (= the complete pipeline without the + * serializer) is cacheable and valid, return all validity objects. + * Otherwise return null + */ + SourceValidity getValidityForEventPipeline(); + + /** + * Return the key for the event pipeline + * If the "event pipeline" (= the complete pipeline without the + * serializer) is cacheable and valid, return a key. + * Otherwise return null + */ + String getKeyForEventPipeline(); +} Added: cocoon/branches/src/java/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipeline.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipeline.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,265 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.components.pipeline.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.butterfly.components.pipeline.InvalidPipelineException; +import org.apache.butterfly.components.pipeline.PipelineProcessingException; +import org.apache.butterfly.components.pipeline.ProcessingPipeline; +import org.apache.butterfly.environment.Environment; +import org.apache.butterfly.generation.Generator; +import org.apache.butterfly.reading.Reader; +import org.apache.butterfly.serialization.Serializer; +import org.apache.butterfly.source.SourceValidity; +import org.apache.butterfly.transformation.Transformer; +import org.apache.butterfly.xml.XMLConsumer; +import org.apache.butterfly.xml.XMLProducer; + + +/** + * Implementation of the non-caching pipeline. + * + * TODO: change InvalidPipelineExceptions with PipelineExceptions + * + * @version CVS $Id: NonCachingProcessingPipeline.java,v 1.7 2004/07/25 21:55:20 ugo Exp $ + */ +public class NonCachingProcessingPipeline implements ProcessingPipeline { + + /** The generator */ + protected Generator generator; + + /** The reader */ + protected Reader reader; + + /** The transformers */ + protected List transformers; + + /** The serializer */ + protected Serializer serializer; + + /** + * This is the last component in the pipeline, either the serializer + * or a custom xmlconsumer for the cocoon: protocol etc. + */ + protected XMLConsumer lastConsumer; + + /** Output Buffer Size */ + protected int outputBufferSize; + + /** + * Build a new pipeline. + */ + public NonCachingProcessingPipeline() { + transformers = new ArrayList(); + } + + /* (non-Javadoc) + * @see org.apache.butterfly.components.pipeline.ProcessingPipeline#setGenerator(org.apache.butterfly.generation.Generator) + */ + public void setGenerator(Generator generator) { + if (this.generator != null) { + throw new InvalidPipelineException("Generator already set. Cannot set generator."); + } + if (this.reader != null) { + throw new InvalidPipelineException("Reader already set. Cannot set generator."); + } + this.generator = generator; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.components.pipeline.ProcessingPipeline#setReader(org.apache.butterfly.reading.Reader) + */ + public void setReader(Reader reader) { + if (this.generator != null) { + throw new InvalidPipelineException("Generator already set. Cannot set reader."); + } + if (this.reader != null) { + throw new InvalidPipelineException("Reader already set. Cannot set reader."); + } + this.reader = reader; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.components.pipeline.ProcessingPipeline#getGenerator() + */ + public Generator getGenerator() { + return this.generator; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.components.pipeline.ProcessingPipeline#informBranchPoint() + */ + public void informBranchPoint() { + // TODO Auto-generated method stub + } + + /* (non-Javadoc) + * @see org.apache.butterfly.components.pipeline.ProcessingPipeline#addTransformer(javax.xml.transform.Transformer) + */ + public void addTransformer(Transformer transformer) { + if (this.generator == null) { + throw new InvalidPipelineException("Generator not yet set. Cannot add transformer."); + } + if (this.reader != null) { + throw new InvalidPipelineException("Reader already set. Cannot add transformer."); + } + transformers.add(transformer); + } + + /* (non-Javadoc) + * @see org.apache.butterfly.components.pipeline.ProcessingPipeline#setSerializer(org.apache.butterfly.xml.XMLPipe) + */ + public void setSerializer(Serializer serializer) { + if (this.serializer != null) { + // Should normally not happen as adding a serializer starts pipeline processing + throw new InvalidPipelineException ("Serializer already set. Cannot set serializer."); + } + if (this.reader != null) { + // Should normally never happen as setting a reader starts pipeline processing + throw new InvalidPipelineException ("Reader already set. Cannot set serializer."); + } + if (this.generator == null) { + throw new InvalidPipelineException ("Must set a generator before setting serializer"); + } + this.serializer = serializer; + this.lastConsumer = serializer; + } + + /** + * Sanity check + * @return true if the pipeline is 'sane', false otherwise. + */ + protected boolean checkPipeline() { + if (this.generator == null && this.reader == null) { + return false; + } + if (this.generator != null && this.serializer == null) { + return false; + } + return true; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.components.pipeline.ProcessingPipeline#process() + */ + public boolean process(Environment environment) { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.components.pipeline.ProcessingPipeline#prepareInternal() + */ + public void prepareInternal(Environment environment) { + // TODO Auto-generated method stub + + } + + /** + * Process the given Environment, but do not use the + * serializer. Instead the sax events are streamed to the XMLConsumer. + */ + public boolean process(Environment environment, XMLConsumer consumer) { + this.lastConsumer = consumer; + if (this.reader != null) { + throw new InvalidPipelineException("Streaming of an internal pipeline is not possible with a reader."); + } else { + connectPipeline(environment); + return processXMLPipeline(environment); + } + } + + /** + * Process the SAX event pipeline + */ + protected boolean processXMLPipeline(Environment environment) { + if (this.serializer != this.lastConsumer) { + // internal processing + this.generator.generate(); + } else { + if (this.serializer.shouldSetContentLength()) { + // set the output stream + ByteArrayOutputStream os = new ByteArrayOutputStream(); + this.serializer.setOutputStream(os); + + // execute the pipeline: + this.generator.generate(); + environment.setContentLength(os.size()); + try { + os.writeTo(environment.getOutputStream(0)); + } catch (IOException e) { + throw new PipelineProcessingException("Cannot write to output stream", e); + } + } else { + // set the output stream + this.serializer.setOutputStream(environment.getOutputStream(this.outputBufferSize)); + // execute the pipeline: + this.generator.generate(); + } + } + return true; + } + + /** + * Connect the next component + */ + protected void connect(Environment environment, + XMLProducer producer, + XMLConsumer consumer) { + XMLProducer next = producer; + // Connect next component. + next.setConsumer(consumer); + } + + /** + * Connect the XML pipeline. + */ + protected void connectPipeline(Environment environment) { + XMLProducer prev = this.generator; + + Iterator itt = this.transformers.iterator(); + while (itt.hasNext()) { + Transformer next = (Transformer) itt.next(); + connect(environment, prev, next); + prev = next; + } + + // insert the serializer + connect(environment, prev, this.lastConsumer); + } + + /* (non-Javadoc) + * @see org.apache.butterfly.components.pipeline.ProcessingPipeline#getValidityForEventPipeline() + */ + public SourceValidity getValidityForEventPipeline() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.components.pipeline.ProcessingPipeline#getKeyForEventPipeline() + */ + public String getKeyForEventPipeline() { + // TODO Auto-generated method stub + return null; + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/environment/Environment.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/environment/Environment.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,191 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.environment; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Enumeration; +import java.util.Map; + +/** + * Base interface for an environment abstraction + * + * @version CVS $Id: Environment.java,v 1.2 2004/07/25 21:55:20 ugo Exp $ + */ +public interface Environment { + + /** + * Get the URI to process. The prefix is stripped off. + */ + String getURI(); + + /** + * Get the prefix of the URI in progress. + */ + String getURIPrefix(); + + /** + * Set the URI and the prefix to process. + */ + void setURI(String prefix, String value); + + /** + * Get the view to process + */ + String getView(); + + /** + * Get the action to process + */ + String getAction(); + + /** + * Redirect to the given URL + */ + void redirect(String url, boolean global, boolean permanent) + throws IOException; + + /** + * Set the content type of the generated resource + */ + void setContentType(String mimeType); + + /** + * Get the content type of the resource + */ + String getContentType(); + + /** + * Set the length of the generated content + */ + void setContentLength(int length); + + /** + * Set the response status code + */ + void setStatus(int statusCode); + + /** + * Get the output stream where to write the generated resource. + * The returned stream is buffered by the environment. If the + * buffer size is -1 then the complete output is buffered. + * If the buffer size is 0, no buffering takes place. + */ + OutputStream getOutputStream(int bufferSize); + + /** + * Get the underlying object model + */ + Map getObjectModel(); + + /** + * Check if the response has been modified since the same + * "resource" was requested. + * The caller has to test if it is really the same "resource" + * which is requested. + * @return true if the response is modified or if the + * environment is not able to test it + */ + boolean isResponseModified(long lastModified); + + /** + * Mark the response as not modified. + */ + void setResponseIsNotModified(); + + /** + * Binds an object to this environment, using the name specified. This allows + * the pipeline assembly engine to store for its own use objects that souldn't + * be exposed to other components (generators, selectors, etc) and therefore + * cannot be put in the object model. + *

+ * If an object of the same name is already bound, the object is replaced. + * + * @param name the name to which the object is bound + * @param value the object to be bound + */ + void setAttribute(String name, Object value); + + /** + * Returns the object bound with the specified name, or null + * if no object is bound under the name. + * + * @param name a string specifying the name of the object + * @return the object with the specified name + */ + Object getAttribute(String name); + + /** + * Removes the object bound with the specified name from + * this environment. If the environment does not have an object + * bound with the specified name, this method does nothing. + * + * @param name the name of the object to remove + */ + void removeAttribute(String name); + + /** + * Returns an Enumeration of String objects + * containing the names of all the objects bound to this environment. + * + * @return an Enumeration of Strings. + */ + Enumeration getAttributeNames(); + + /** + * Reset the response if possible. This allows error handlers to have + * a higher chance to produce clean output if the pipeline that raised + * the error has already output some data. + * If a buffered output stream is used, resetting is always successful. + * + * @return true if the response was successfully reset + */ + boolean tryResetResponse() throws IOException; + + + /** + * Commit the response + */ + void commitResponse() throws IOException; + + /** + * Notify that the processing starts. + */ + void startingProcessing(); + + /** + * Notify that the processing is finished + * This can be used to cleanup the environment object + */ + void finishingProcessing(); + + /** + * Is this environment external ? An external environment is one that + * is created in response to an external request (http, commandline, etc.). + * Environments created by the "cocoon:" protocol aren't external. + * + * @return true if this environment is external + */ + boolean isExternal(); + + /** + * Is this an internal redirect? + * An environment is on internal redirect if it is an internal request + * (via the cocoon: protocol) and used for a redirect. + */ + boolean isInternalRedirect(); +} + Added: cocoon/branches/src/java/org/apache/butterfly/generation/FileGenerator.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/generation/FileGenerator.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,64 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.generation; + +import org.apache.butterfly.source.Source; +import org.apache.butterfly.source.SourceResolver; +import org.apache.butterfly.xml.Parser; +import org.apache.butterfly.xml.XMLConsumer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * Description of FileGenerator. + * + * @version CVS $Id: FileGenerator.java,v 1.2 2004/07/25 21:55:20 ugo Exp $ + */ +public class FileGenerator implements Generator { + private Source inputSource; + private SourceResolver sourceResolver; + private Parser parser; + protected static final Log logger = LogFactory.getLog(FileGenerator.class); + + public void setParser(Parser parser) { + this.parser = parser; + } + + public void setInputSource(String source) { + this.inputSource = sourceResolver.resolveURI(source); + } + + /** + * @param sourceResolver The sourceResolver to set. + */ + public void setSourceResolver(SourceResolver sourceResolver) { + this.sourceResolver = sourceResolver; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.generation.Generator#setContentHandler(org.xml.sax.ContentHandler) + */ + public void setConsumer(XMLConsumer consumer) { + parser.setContentHandler(consumer); + } + + public void generate() { + parser.parse(this.inputSource); + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/generation/Generator.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/generation/Generator.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,29 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.generation; + +import org.apache.butterfly.xml.XMLProducer; + + +/** + * Description of Generator. + * + * @version CVS $Id: Generator.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public interface Generator extends XMLProducer { + public void generate(); +} Added: cocoon/branches/src/java/org/apache/butterfly/reading/Reader.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/reading/Reader.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,41 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.reading; + +import org.apache.butterfly.sitemap.SitemapOutputComponent; + + + +/** + * A reader can be used to generate binary output for a request. + * + * @version CVS $Id: Reader.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public interface Reader extends SitemapOutputComponent { + + String ROLE = Reader.class.getName(); + + /** + * Generate the response. + */ + void generate(); + + /** + * @return the time the read source was last modified or 0 if it is not + * possible to detect + */ + long getLastModified(); +} Added: cocoon/branches/src/java/org/apache/butterfly/serialization/Serializer.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/serialization/Serializer.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,29 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.serialization; + +import org.apache.butterfly.sitemap.SitemapOutputComponent; +import org.apache.butterfly.xml.XMLConsumer; + + +/** + * Description of Serializer. + * + * @version CVS $Id: Serializer.java,v 1.1 2004/07/24 20:21:33 ugo Exp $ + */ +public interface Serializer extends XMLConsumer, SitemapOutputComponent { + +} Added: cocoon/branches/src/java/org/apache/butterfly/serialization/XMLSerializer.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/serialization/XMLSerializer.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,125 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.serialization; + +import java.io.OutputStream; +import java.util.Properties; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; + +import org.apache.butterfly.xml.AbstractXMLPipe; +import org.apache.butterfly.xml.xslt.TraxTransformerFactory; + + +/** + * Description of XMLSerializer. + * + * @version CVS $Id: XMLSerializer.java,v 1.2 2004/07/24 20:21:33 ugo Exp $ + */ +public class XMLSerializer extends AbstractXMLPipe implements Serializer { + + protected OutputStream output; + protected TraxTransformerFactory transformerFactory; + + /** + * The Properties used by this serializer. + */ + protected Properties format = new Properties(); + + /** + * + */ + public XMLSerializer() { + this.format.put(OutputKeys.METHOD, "xml"); + } + + /** + * @param transformerFactory The transformerFactory to set. + */ + public void setTraxTransformerFactory(TraxTransformerFactory transformerFactory) { + this.transformerFactory = transformerFactory; + } + + public void setCdataSectionElements(String cdataSectionElements) { + format.put(OutputKeys.CDATA_SECTION_ELEMENTS, cdataSectionElements); + } + + public void setDoctypePublic(String dtPublic) { + format.put(OutputKeys.DOCTYPE_PUBLIC, dtPublic); + } + + public void setDocTypeSystem(String dtSystem) { + format.put(OutputKeys.DOCTYPE_SYSTEM, dtSystem); + } + + public void setEncoding(String encoding) { + format.put(OutputKeys.ENCODING, encoding); + } + + public void setIndent(String indent) { + format.put(OutputKeys.INDENT, indent); + } + + public void setMediaType(String mediaType) { + format.put(OutputKeys.MEDIA_TYPE, mediaType); + } + + public void setMethod(String method) { + format.put(OutputKeys.METHOD, method); + } + + public void setOmitXMLDeclaration(String omitXMLDeclaration) { + format.put(OutputKeys.OMIT_XML_DECLARATION, omitXMLDeclaration); + } + + public void setStandAlone(String standAlone) { + format.put(OutputKeys.STANDALONE, standAlone); + } + + public void setVersion(String version) { + format.put(OutputKeys.VERSION, version); + } + + /** + * Set the {@link OutputStream} where the requested resource should + * be serialized. + */ + public void setOutputStream(OutputStream output) { + this.output = output; + TransformerHandler handler = this.transformerFactory.getTransformerHandler(); + handler.getTransformer().setOutputProperties(this.format); + handler.setResult(new StreamResult(this.output)); + this.setContentHandler(handler); + this.setLexicalHandler(handler); + } + + /* (non-Javadoc) + * @see org.apache.butterfly.sitemap.SitemapOutputComponent#getMimeType() + */ + public String getMimeType() { + return null; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.sitemap.SitemapOutputComponent#shouldSetContentLength() + */ + public boolean shouldSetContentLength() { + return false; + } +} Added: cocoon/branches/src/java/org/apache/butterfly/sitemap/SitemapOutputComponent.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/sitemap/SitemapOutputComponent.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,43 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.sitemap; + +import java.io.OutputStream; + +/** + * This interface marks a component as a sitemap component that produces + * a response, like a serializer or a reader. + * + * @version CVS $Id: SitemapOutputComponent.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public interface SitemapOutputComponent { + + /** + * Set the {@link OutputStream} where the requested resource should + * be serialized. + */ + void setOutputStream(OutputStream out); + + /** + * Get the mime-type of the output of this Component. + */ + String getMimeType(); + + /** + * Test if the component wants to set the content length + */ + boolean shouldSetContentLength(); +} Added: cocoon/branches/src/java/org/apache/butterfly/source/Source.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/Source.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,143 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source; + +import java.io.InputStream; + + +/** + * This interface provides a simple interface for accessing a source of data. + *

+ * When the Source object is no longer needed + * it must be released using the {@link SourceResolver}. This is very similar to + * looking up components from a ServiceSelector. + * In fact a source object can implement most lifecycle interfaces + * like Composable, Initializable, Disposable etc. + *

+ * The data content can be constant or change over time. + * Using the {@link #getInputStream()} method you get always the up-to-date content. + *

+ * If you want to track changes of the source object, this interface + * offers you some support for it by providing a SourceValidity object. + *

+ * How does the caching work? + * The first time you get a Source object, you simply ask + * it for it's content via getInputStream() and then get the validity + * object by invoking getValidity. (Further calls to getValidity always + * return the same object! This is not updated!) + * The caching algorithm can now store this validity object together + * with the system identifier of the source. + * The next time, the caching algorithm wants to check if the cached + * content is still valid. It has a validity object already to check + * against. + *

+ * If it is still the same Source than the first time, you + * have to call refresh() in order to discard the stored validity + * in the Source object. If it is a new Source object, + * calling refresh() should do no harm. + * After that an up-to-date validity object can retrieved by calling + * getValidity(). This can be used to test if the content is still valid + * as discribed in the source validity documentation. + * If the content is still valid, the cache knows what to do, if not, + * the new content can be get using getInputStream(). + * So either after a call to getValidity() or the getInputStream the + * validity object must be the same until refresh is called! + * + * @version CVS $Id: Source.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public interface Source { + /** + * Does this source exist ? + * + * @return true if the source exists + */ + boolean exists(); + + /** + * Return an InputStream to read from the source. + * This is the data at the point of invocation of this method, + * so if this is Modifiable, you might get different content + * from two different invocations. + * + * @return the InputStream to read data from (never null). + */ + InputStream getInputStream(); + + /** + * Get the absolute URI for this source. + * + * @return the source URI. + */ + String getURI(); + + /** + * Return the URI scheme identifier, i.e. the part preceding the fist ':' in the URI + * (see RFC 2396). + *

+ * This scheme can be used to get the {@link SourceFactory} responsible for this object. + * + * @return the URI scheme. + */ + String getScheme(); + + /** + * Get the Validity object. This can either wrap the last modification date or + * some expiry information or anything else describing this object's validity. + *

+ * If it is currently not possible to calculate such an information, + * null is returned. + * + * @return the validity, or null. + */ + SourceValidity getValidity(); + + /** + * Refresh the content of this object after the underlying data content has changed. + *

+ * Some implementations may cache some values to speedup sucessive calls. Refreshing + * ensures you get the latest information. + */ + void refresh(); + + /** + * Get the mime-type of the content described by this object. + * If the source is not able to determine the mime-type by itself + * this can be null. + * + * @return the source's mime-type or null. + */ + String getMimeType(); + + /** + * Get the content length of this source's content or -1 if the length is + * unknown. + * + * @return the source's content length or -1. + */ + long getContentLength(); + + /** + * Get the last modification date of this source. The date is + * measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970), + * and is 0 if it's unknown. + * + * @return the last modification date or 0. + */ + long getLastModified(); + + +} Added: cocoon/branches/src/java/org/apache/butterfly/source/SourceException.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/SourceException.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,42 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source; + + +/** + * Superclass of exceptions thrown by sources and source resolvers. + * + * @version CVS $Id: SourceException.java,v 1.2 2004/07/25 21:55:20 ugo Exp $ + */ +public class SourceException extends RuntimeException { + + public SourceException() { + super(); + } + + public SourceException(String arg0) { + super(arg0); + } + + public SourceException(String arg0, Throwable arg1) { + super(arg0, arg1); + } + + public SourceException(Throwable arg0) { + super(arg0); + } +} Added: cocoon/branches/src/java/org/apache/butterfly/source/SourceFactory.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/SourceFactory.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,53 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source; + +import java.io.IOException; +import java.util.Map; + + +/** + * A source factory creates new source objects. + *

+ * Source factories are used to extend the source resolving mechanism + * with new URI schemes. A new source factory is added in order to + * handle a specific prototol. The {@link SourceResolver} delegates + * the handling of a URI containing this new scheme to the factory, + * and the factory can create a corresponding {@link Source} object. + * + * @version CVS $Id: SourceFactory.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public interface SourceFactory { + + /** + * Get a {@link Source} object. + * The factory creates a new {@link Source} object that can be used + * by the application. However, when this source object is not needed + * anymore it has to be released again using the {@link #release(Source)} + * method. This is achieved by using {@link SourceResolver#release(Source)} which + * finds the appropriate SourceFactory. + * + * @param location The URI to resolve - this URI includes the scheme. + * @param parameters additionnal named parameters (optionnal and can be null) + * that drive the creation of the Source object. Each implementation + * must specify what parameters it accepts. + * @return the created source object. + * + * @throws IOException if the source couldn't be created for some reason. + */ + Source getSource(String location, Map parameters); +} Added: cocoon/branches/src/java/org/apache/butterfly/source/SourceNotFoundException.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/SourceNotFoundException.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,42 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source; + + +/** + * Description of SourceException. + * + * @version CVS $Id: SourceNotFoundException.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class SourceNotFoundException extends RuntimeException { + + public SourceNotFoundException() { + super(); + } + + public SourceNotFoundException(String arg0) { + super(arg0); + } + + public SourceNotFoundException(String arg0, Throwable arg1) { + super(arg0, arg1); + } + + public SourceNotFoundException(Throwable arg0) { + super(arg0); + } +} Added: cocoon/branches/src/java/org/apache/butterfly/source/SourceResolver.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/SourceResolver.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,120 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; + + +/** + * Description of SourceResolver. + * + * @version CVS $Id: SourceResolver.java,v 1.2 2004/07/25 21:55:20 ugo Exp $ + */ +public class SourceResolver { + private Map factories; + URL baseURL; + + public SourceResolver() { + try { + // TODO: contextualize it + baseURL = new File(System.getProperty("user.dir")).toURL(); + } catch (MalformedURLException e) { + throw new SourceException(e); + } + } + + /** + * @param factories The factories to set. + */ + public void setFactories(Map factories) { + this.factories = factories; + } + + /** + * Get a Source object. + * @throws org.apache.excalibur.source.SourceNotFoundException if the source cannot be found + */ + public Source resolveURI(String location) { + return this.resolveURI(location, null, null); + } + + /** + * Get a Source object. + */ + public Source resolveURI(String location, + String baseURI, + Map parameters) + { + if (null != baseURI && SourceUtil.indexOfSchemeColon(baseURI) == -1) { + throw new SourceException("BaseURI is not valid, it must contain a protocol: " + baseURI); + } + + if( baseURI == null ) baseURI = baseURL.toExternalForm(); + + String systemID = location; + // special handling for windows file paths + if( location.length() > 1 && location.charAt( 1 ) == ':' ) + systemID = "file:/" + location; + else if( location.length() > 2 && location.charAt(0) == '/' && location.charAt(2) == ':' ) + systemID = "file:" + location; + + // determine protocol (scheme): first try to get the one of the systemID, if that fails, take the one of the baseURI + String protocol; + int protocolPos = SourceUtil.indexOfSchemeColon(systemID); + if( protocolPos != -1 ) + { + protocol = systemID.substring( 0, protocolPos ); + } + else + { + protocolPos = SourceUtil.indexOfSchemeColon(baseURI); + if( protocolPos != -1 ) + protocol = baseURI.substring( 0, protocolPos ); + else + protocol = "*"; + } + + Source source = null; + // search for a SourceFactory implementing the protocol + SourceFactory factory = (SourceFactory) factories.get(protocol); + if (factory == null) { + factory = (SourceFactory) factories.get("*"); + if (factory == null) { + throw new SourceException("Unable to select source factory for " + systemID); + } + systemID = absolutize(factory, baseURI, systemID); + return factory.getSource(systemID, parameters); + } + systemID = absolutize(factory, baseURI, systemID); + return factory.getSource(systemID, parameters); + } + + /** + * Makes an absolute URI based on a baseURI and a relative URI. + */ + private String absolutize( SourceFactory factory, String baseURI, String systemID ) + { + if( factory instanceof URIAbsolutizer ) + systemID = ((URIAbsolutizer) factory).absolutize(baseURI, systemID); + else + systemID = SourceUtil.absolutize(baseURI, systemID); + return systemID; + } +} Added: cocoon/branches/src/java/org/apache/butterfly/source/SourceUtil.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/SourceUtil.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,473 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source; + +import java.io.UnsupportedEncodingException; + + +/** + * Utility class for source resolving. + * + * @version CVS $Id: SourceUtil.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class SourceUtil { + + /** + * Get the position of the scheme-delimiting colon in an absolute URI, as specified + * by RFC 2396, appendix A. This method is + * primarily useful for {@link Source} implementors that want to separate + * the scheme part from the specific part of an URI. + *

+ * Use this method when you need both the scheme and the scheme-specific part of an URI, + * as calling successively {@link #getScheme(String)} and {@link #getSpecificPart(String)} + * will call this method twice, and as such won't be efficient. + * + * @param uri the URI + * @return int the scheme-delimiting colon, or -1 if not found. + */ + public static int indexOfSchemeColon(String uri) + { + // absoluteURI = scheme ":" ( hier_part | opaque_part ) + // + // scheme = alpha *( alpha | digit | "+" | "-" | "." ) + // + // alpha = lowalpha | upalpha + // + // lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | + // "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | + // "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" + // + // upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | + // "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | + // "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" + // + // digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | + // "8" | "9" + + // Must have at least one character followed by a colon + if (uri == null || uri.length() < 2) + { + return -1; + } + + // Check that first character is alpha + // (lowercase first since it's the most common case) + char ch = uri.charAt(0); + if ( (ch < 'a' || ch > 'z') && + (ch < 'A' || ch > 'Z') ) + { + // Invalid first character + return -1; + } + + int pos = uri.indexOf(':'); + if (pos != -1) + { + // Check that every character before the colon is in the allowed range + // (the first one was tested above) + for (int i = 1; i < pos; i++) + { + ch = uri.charAt(i); + if ( (ch < 'a' || ch > 'z') && + (ch < 'A' || ch > 'Z') && + (ch < '0' || ch > '9') && + ch != '+' && ch != '-' && ch != '.') + { + return -1; + } + } + } + + return pos; + } + + /** + * Get the scheme of an absolute URI. + * + * @param uri the absolute URI + * @return the URI scheme + */ + public static String getScheme(String uri) + { + int pos = indexOfSchemeColon(uri); + return (pos == -1) ? null : uri.substring(0, pos); + } + + /** + * Get the scheme-specific part of an absolute URI. Note that this includes everything + * after the separating colon, including the fragment, if any (RFC 2396 separates it + * from the scheme-specific part). + * + * @param uri the absolute URI + * @return the scheme-specific part of the URI + */ + public static String getSpecificPart(String uri) + { + int pos = indexOfSchemeColon(uri); + return (pos == -1) ? null : uri.substring(pos+1); + } + + /** + * Calls absolutize(url1, url2, false). + */ + public static String absolutize(String url1, String url2) + { + return absolutize(url1, url2, false, true); + } + + /** + * Calls absolutize(url1, url2, false, true). + */ + public static String absolutize(String url1, String url2, boolean treatAuthorityAsBelongingToPath) + { + return absolutize(url1, url2, treatAuthorityAsBelongingToPath, true); + } + + /** + * Applies a location to a baseURI. This is done as described in RFC 2396 section 5.2. + * + * @param url1 the baseURI + * @param url2 the location + * @param treatAuthorityAsBelongingToPath considers the authority to belong to the path. These + * special kind of URIs are used in the Apache Cocoon project. + * @param normalizePath should the path be normalized, i.e. remove ../ and /./ etc. + */ + public static String absolutize(String url1, String url2, boolean treatAuthorityAsBelongingToPath, boolean normalizePath) + { + if (url1 == null) + return url2; + + // If the URL contains a scheme (and thus is already absolute), don't do any further work + if (getScheme(url2) != null) + return url2; + + // parse the urls into parts + // if the second url contains a scheme, it is not relative so return it right away (part 3 of the algorithm) + String[] url1Parts = parseUrl(url1); + String[] url2Parts = parseUrl(url2); + + if (treatAuthorityAsBelongingToPath) + return absolutizeWithoutAuthority(url1Parts, url2Parts); + + // check if it is a reference to the current document (part 2 of the algorithm) + if (url2Parts[PATH].equals("") && url2Parts[QUERY] == null && url2Parts[AUTHORITY] == null) + return makeUrl(url1Parts[SCHEME], url1Parts[AUTHORITY], url1Parts[PATH], url1Parts[QUERY], url2Parts[FRAGMENT]); + + // it is a network reference (part 4 of the algorithm) + if (url2Parts[AUTHORITY] != null) + return makeUrl(url1Parts[SCHEME], url2Parts[AUTHORITY], url2Parts[PATH], url2Parts[QUERY], url2Parts[QUERY]); + + String url1Path = url1Parts[PATH]; + String url2Path = url2Parts[PATH]; + + // if the path starts with a slash (part 5 of the algorithm) + if (url2Path != null && url2Path.length() > 0 && url2Path.charAt(0) == '/') + return makeUrl(url1Parts[SCHEME], url1Parts[AUTHORITY], url2Parts[PATH], url2Parts[QUERY], url2Parts[QUERY]); + + // combine the 2 paths + String path = stripLastSegment(url1Path); + path = path + (path.endsWith("/") ? "" : "/") + url2Path; + if (normalizePath) + path = normalize(path); + + return makeUrl(url1Parts[SCHEME], url1Parts[AUTHORITY], path, url2Parts[QUERY], url2Parts[FRAGMENT]); + } + + /** + * Absolutizes URIs whereby the authority part is considered to be a part of the path. + * This special kind of URIs is used in the Apache Cocoon project for the cocoon and context protocols. + * This method is internally used by {@link #absolutize}. + */ + private static String absolutizeWithoutAuthority(String[] url1Parts, String[] url2Parts) + { + String authority1 = url1Parts[AUTHORITY]; + String authority2 = url2Parts[AUTHORITY]; + + String path1 = url1Parts[PATH]; + String path2 = url2Parts[PATH]; + + if (authority1 != null) + path1 = "//" + authority1 + path1; + if (authority2 != null) + path2 = "//" + authority2 + path2; + + String path = stripLastSegment(path1); + path = path + (path.endsWith("/") ? "" : "/") + path2; + path = normalize(path); + + String scheme = url1Parts[SCHEME]; + return scheme + ":" + path; + } + + private static String stripLastSegment(String path) + { + int i = path.lastIndexOf('/'); + if(i > -1) + return path.substring(0, i + 1); + return path; + } + + /** + * Removes things like <segment>/../ or ./, as described in RFC 2396 in + * step 6 of section 5.2. + */ + private static String normalize(String path) + { + // replace all /./ with / + int i = path.indexOf("/./"); + while (i > -1) + { + path = path.substring(0, i + 1) + path.substring(i + 3); + i = path.indexOf("/./"); + } + + if (path.endsWith("/.")) + path = path.substring(0, path.length() - 1); + + int f = path.indexOf("/../"); + while (f > 0) + { + int sb = path.lastIndexOf("/", f - 1); + if (sb > - 1) + path = path.substring(0, sb + 1) + (path.length() >= f + 4 ? path.substring(f + 4) : ""); + f = path.indexOf("/../"); + } + + if (path.length() > 3 && path.endsWith("/..")) + { + int sb = path.lastIndexOf("/", path.length() - 4); + String segment = path.substring(sb, path.length() - 3); + if (!segment.equals("..")) + { + path = path.substring(0, sb + 1); + } + } + + return path; + } + + /** + * Assembles an URL from the given URL parts, each of these parts can be null. + * Used internally by {@link #absolutize}. + */ + private static String makeUrl(String scheme, String authority, String path, String query, String fragment) + { + StringBuffer url = new StringBuffer(); + if (scheme != null) + url.append(scheme).append(':'); + + if (authority != null) + url.append("//").append(authority); + + if (path != null) + url.append(path); + + if (query != null) + url.append('?').append(query); + + if (fragment != null) + url.append('#').append(fragment); + + return url.toString(); + } + + public static final int SCHEME = 0; + public static final int AUTHORITY = 1; + public static final int PATH = 2; + public static final int QUERY = 3; + public static final int FRAGMENT = 4; + + /** + * Parses an URL into the following parts: scheme, authority, path, query and fragment identifier. + * + *

The parsing is designed to be robust in the sense that it will never fail, even when an invalid + * URL is given. The parser will simply look for the most important delimiter characters. Basically + * it does the same as what would be achieved using the following regular expression (from RFC 2396): + *

+     * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+     *  12            3  4          5       6  7        8 9
+     * 
+ * but without actually using the regular expression. + * + *

The result is returned as a string array, use the constants SCHEME, AUTHORITY, PATH, + * QUERY and FRAGMENT_IDENTIFIER to access the different parts. + * + *

If a part is missing, its corresponding entry in the array will be null, except for the + * path, which will never be null. + */ + public static String[] parseUrl(String url) { + char[] urlchars = url.toCharArray(); + + int pos = 0; + + String scheme = null; + String authority = null; + String path = null; + String query = null; + String fragid = null; + + // ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? + + // the scheme + boolean keepgoing = true; + while (keepgoing && pos < urlchars.length) + { + switch (urlchars[pos]) + { + case ':': + if (pos >= 1) + { + scheme = new String(urlchars, 0, pos); + keepgoing = false; + pos++; + break; + } + case '/': + case '?': + case '#': + keepgoing = false; + break; + default: + pos++; + } + } + + if (scheme == null) + pos = 0; + + // the authority + if (pos + 1 < urlchars.length && urlchars[pos] == '/' && urlchars[pos+1] == '/') + { + pos += 2; + int authorityBeginPos = pos; + keepgoing = true; + while (keepgoing && pos < urlchars.length) + { + switch (urlchars[pos]) + { + case '/': + case '?': + case '#': + keepgoing = false; + break; + default: + pos++; + } + } + authority = new String(urlchars, authorityBeginPos, pos - authorityBeginPos); + } + + // the path + int pathBeginPos = pos; + keepgoing = true; + while (keepgoing && pos < urlchars.length) + { + switch (urlchars[pos]) + { + case '?': + case '#': + keepgoing = false; + break; + default: + pos++; + } + } + path = new String(urlchars, pathBeginPos, pos - pathBeginPos); + + // the query + if (pos < urlchars.length && urlchars[pos] == '?') + { + pos++; + int queryBeginPos = pos; + keepgoing = true; + while (keepgoing && pos < urlchars.length) + { + switch (urlchars[pos]) + { + case '#': + keepgoing = false; + break; + default: + pos++; + } + } + query = new String(urlchars, queryBeginPos, pos - queryBeginPos); + } + + // the fragment identifier + pos++; + if (pos < urlchars.length) + fragid = new String(urlchars, pos, urlchars.length - pos); + + return new String[] {scheme, authority, path, query, fragid}; + } + + /** + * Decode a path. + * + *

Interprets %XX (where XX is hexadecimal number) as UTF-8 encoded bytes. + *

The validity of the input path is not checked (i.e. characters that + * were not encoded will not be reported as errors). + *

This method differs from URLDecoder.decode in that it always uses UTF-8 + * (while URLDecoder uses the platform default encoding, often ISO-8859-1), + * and doesn't translate + characters to spaces. + * + * @param path the path to decode + * @return the decoded path + */ + public static String decodePath(String path) { + StringBuffer translatedPath = new StringBuffer(path.length()); + byte[] encodedchars = new byte[path.length() / 3]; + int i = 0; + int length = path.length(); + int encodedcharsLength = 0; + while (i < length) { + if (path.charAt(i) == '%') { + // we must process all consecutive %-encoded characters in one go, because they represent + // an UTF-8 encoded string, and in UTF-8 one character can be encoded as multiple bytes + while (i < length && path.charAt(i) == '%') { + if (i + 2 < length) { + try { + byte x = (byte)Integer.parseInt(path.substring(i + 1, i + 3), 16); + encodedchars[encodedcharsLength] = x; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Illegal hex characters in pattern %" + path.substring(i + 1, i + 3)); + } + encodedcharsLength++; + i += 3; + } else { + throw new IllegalArgumentException("% character should be followed by 2 hexadecimal characters."); + } + } + try { + String translatedPart = new String(encodedchars, 0, encodedcharsLength, "UTF-8"); + translatedPath.append(translatedPart); + } catch (UnsupportedEncodingException e) { + // the situation that UTF-8 is not supported is quite theoretical, so throw a runtime exception + throw new RuntimeException("Problem in decodePath: UTF-8 encoding not supported."); + } + encodedcharsLength = 0; + } else { + // a normal character + translatedPath.append(path.charAt(i)); + i++; + } + } + return translatedPath.toString(); + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/source/SourceValidity.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/SourceValidity.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,75 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source; + +import java.io.Serializable; + + +/** + * A SourceValidity object contains all information to check if a Source + * object is still valid. + *

+ * There are two possibilities: + *

    + *
  • The validity object has all information to check by itself if it is valid + * (e.g. given an expires date).
  • + *
  • The validity object possibility needs another (newer) validity object to compare + * against (e.g. to test a last modification date).
  • + *
+ * To avoid testing what the actual implementation of the validity object supports, + * the invocation order is to first call {@link #isValid()} and only if this result + * is 0 (i.e. "don't know"), then to call {@link #isValid(SourceValidity)}. + *

+ * Remember to call {@link #isValid(SourceValidity)} when {@link #isValid()} returned + * 0 ! + * + * @version CVS $Id: SourceValidity.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public interface SourceValidity extends Serializable { + final int VALID = +1; + final int INVALID = -1; + final int UNKNOWN = 0; + + /** + * Check if the component is still valid. The possible results are : + *

    + *
  • -1: invalid. The component isn't valid anymore.
  • + *
  • 0: don't know. This validity should be checked against a new + * validity object using {@link #isValid(SourceValidity)}.
  • + *
  • 1: valid. The component is still valid.
  • + *
+ */ + int isValid(); + + /** + * Check if the component is still valid. This is only true if the incoming Validity + * is of the same type and has the "same" values. + *

+ * The invocation order is that the isValid + * method of the old Validity object is called with the new one as a + * parameter. + * @return -1 is returned, if the validity object is not valid anymore + * +1 is returned, if the validity object is still valid + * 0 is returned, if the validity check could not be performed. + * In this case, the new validity object is not usable. Examples + * for this are: when the validity objects have different types, + * or when one validity object for any reason is not able to + * get the required information. + */ + int isValid(SourceValidity newValidity); + +} Added: cocoon/branches/src/java/org/apache/butterfly/source/URIAbsolutizer.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/URIAbsolutizer.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,33 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source; + + +/** + * Implemented by a SourceFactory when it supports applying a relative URI + * to a base URI to form an absolute URI. + * + *

If a source factory does not implement this interface, the standard + * algorithm (as described in RFC 2396) will be used. This interface only + * needs to be implemented for source-types which have a different behaviour. + * + * @version CVS $Id: URIAbsolutizer.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public interface URIAbsolutizer { + + public String absolutize(String baseURI, String location); +} Added: cocoon/branches/src/java/org/apache/butterfly/source/impl/FileSource.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/impl/FileSource.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,176 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URLConnection; + +import org.apache.butterfly.source.Source; +import org.apache.butterfly.source.SourceException; +import org.apache.butterfly.source.SourceNotFoundException; +import org.apache.butterfly.source.SourceUtil; +import org.apache.butterfly.source.SourceValidity; +import org.apache.butterfly.source.impl.validity.FileTimeStampValidity; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * Description of FileSource. + * + * @version CVS $Id: FileSource.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class FileSource implements Source { + + /** The file */ + private File file; + + /** The scheme */ + private String scheme; + + /** The URI of this source */ + private String uri; + + /** The logger */ + protected static final Log logger = LogFactory.getLog(FileSource.class); + + public FileSource(String uri) { + int pos = SourceUtil.indexOfSchemeColon(uri); + if (pos < 0) { + throw new SourceException("Invalid URI : " + uri); + } + String scheme = uri.substring(0, pos); + String fileName = uri.substring(pos + 1); + fileName = SourceUtil.decodePath(fileName); + init(scheme, new File(fileName)); + } + + /** + * Builds a FileSource, given an URI scheme and a File. + * + * @param scheme + * @param file + * @throws SourceException + */ + public FileSource(String scheme, File file) throws SourceException + { + init(scheme, file); + } + + private void init(String scheme, File file) throws SourceException + { + this.scheme = scheme; + + String uri; + try { + uri = file.toURL().toExternalForm(); + } catch (MalformedURLException mue) { + // Can this really happen ? + throw new SourceException("Failed to get URL for file " + file, mue); + } + if (!uri.startsWith(scheme)) { + // Scheme is not "file:" + uri = scheme + ':' + uri.substring(uri.indexOf(':') + 1); + } + this.uri = uri; + this.file = file; + } + + /** + * Get the associated file + */ + public File getFile() + { + return this.file; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#exists() + */ + public boolean exists() { + return getFile().exists(); + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getInputStream() + */ + public InputStream getInputStream() { + try { + return new FileInputStream(this.file); + } catch (FileNotFoundException fnfe) { + throw new SourceNotFoundException(this.uri + " doesn't exist.", fnfe); + } + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getURI() + */ + public String getURI() { + return this.uri; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getScheme() + */ + public String getScheme() { + return this.scheme; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getValidity() + */ + public SourceValidity getValidity() { + if (this.file.exists()) { + return new FileTimeStampValidity(this.file); + } else { + return null; + } + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#refresh() + */ + public void refresh() { + // Nothing to do + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getMimeType() + */ + public String getMimeType() { + return URLConnection.getFileNameMap().getContentTypeFor(this.file.getName()); + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getContentLength() + */ + public long getContentLength() { + return this.file.length(); + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getLastModified() + */ + public long getLastModified() { + return this.file.lastModified(); + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/source/impl/FileSourceFactory.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/impl/FileSourceFactory.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,50 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source.impl; + +import java.util.Map; + +import org.apache.butterfly.source.Source; +import org.apache.butterfly.source.SourceFactory; +import org.apache.butterfly.source.SourceUtil; +import org.apache.butterfly.source.URIAbsolutizer; + + +/** + * Description of FileSourceFactory. + * + * @version CVS $Id: FileSourceFactory.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class FileSourceFactory implements SourceFactory, URIAbsolutizer { + + /* (non-Javadoc) + * @see org.apache.butterfly.source.SourceFactory#getSource(java.lang.String, java.util.Map) + */ + public Source getSource(String location, Map parameters) { + return new FileSource(location); + } + + public String absolutize(String baseURI, String location) + { + // Call the absolutize utility method with false for the normalizePath argument. + // This avoids the removal of "../" from the path. + // This way, the "../" will be resolved by the operating system, which might + // do things differently e.g. in case of symbolic links. + return SourceUtil.absolutize(baseURI, location, false, false); + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/source/impl/URLSource.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/impl/URLSource.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,109 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source.impl; + +import java.io.InputStream; + +import org.apache.butterfly.source.Source; +import org.apache.butterfly.source.SourceValidity; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * Description of URLSource. + * + * @version CVS $Id: URLSource.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class URLSource implements Source { + + /** The logger */ + protected static final Log logger = LogFactory.getLog(URLSource.class); + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#exists() + */ + public boolean exists() { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getInputStream() + */ + public InputStream getInputStream() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getURI() + */ + public String getURI() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getScheme() + */ + public String getScheme() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getValidity() + */ + public SourceValidity getValidity() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#refresh() + */ + public void refresh() { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getMimeType() + */ + public String getMimeType() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getContentLength() + */ + public long getContentLength() { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see org.apache.butterfly.source.Source#getLastModified() + */ + public long getLastModified() { + // TODO Auto-generated method stub + return 0; + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/source/impl/URLSourceFactory.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/impl/URLSourceFactory.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,39 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source.impl; + +import java.util.Map; + +import org.apache.butterfly.source.Source; +import org.apache.butterfly.source.SourceFactory; + + +/** + * Description of URLSourceFactory. + * + * @version CVS $Id: URLSourceFactory.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class URLSourceFactory implements SourceFactory { + + /* (non-Javadoc) + * @see org.apache.butterfly.source.SourceFactory#getSource(java.lang.String, java.util.Map) + */ + public Source getSource(String location, Map parameters) { + return new URLSource(); + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/source/impl/validity/FileTimeStampValidity.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/source/impl/validity/FileTimeStampValidity.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,87 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source.impl.validity; + +import java.io.File; + +import org.apache.butterfly.source.SourceValidity; + + +/** + * Description of FileTimeStampValidity. + * + * @version CVS $Id: FileTimeStampValidity.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class FileTimeStampValidity implements SourceValidity { + private long timeStamp; + private File file; + + public FileTimeStampValidity( final String filename ) + { + this( new File( filename ) ); + } + + public FileTimeStampValidity( final File file ) + { + this( file, file.lastModified() ); + } + + public FileTimeStampValidity( final File file, + final long timeStamp ) + { + this.file = file; + this.timeStamp = timeStamp; + } + + /** + * Check if the component is still valid. + * If 0 is returned the isValid(SourceValidity) must be + * called afterwards! + * If -1 is returned, the component is not valid anymore and if +1 + * is returnd, the component is valid. + */ + public int isValid() + { + return ( this.file.lastModified() == this.timeStamp ? 1 : -1 ); + } + + public int isValid( final SourceValidity newValidity ) + { + if( newValidity instanceof FileTimeStampValidity ) + { + final long timeStamp = + ( (FileTimeStampValidity)newValidity ).getTimeStamp(); + return ( this.timeStamp == timeStamp ? 1 : -1); + } + return -1; + } + + public File getFile() + { + return this.file; + } + + public long getTimeStamp() + { + return this.timeStamp; + } + + public String toString() + { + return "FileTimeStampValidity: " + this.file.getPath() + ": " + this.timeStamp; + } +} Added: cocoon/branches/src/java/org/apache/butterfly/transformation/Transformer.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/transformation/Transformer.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,28 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.transformation; + +import org.apache.butterfly.xml.XMLPipe; + + +/** + * Description of Transformer. + * + * @version CVS $Id: Transformer.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public interface Transformer extends XMLPipe { + +} Added: cocoon/branches/src/java/org/apache/butterfly/transformation/TraxTransformer.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/transformation/TraxTransformer.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,68 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.transformation; + +import java.io.IOException; +import java.net.MalformedURLException; + +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.TransformerHandler; + +import org.apache.butterfly.source.Source; +import org.apache.butterfly.source.SourceResolver; +import org.apache.butterfly.xml.AbstractXMLPipe; +import org.apache.butterfly.xml.XMLConsumer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * Description of TraxTransformer. + * + * @version CVS $Id: TraxTransformer.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class TraxTransformer extends AbstractXMLPipe implements Transformer { + private Source inputSource; + protected static final Log logger = LogFactory.getLog(TraxTransformer.class); + private SourceResolver sourceResolver; + private TransformerHandler transformerHandler; + + /** + * @param handler + * @param resolver + */ + public TraxTransformer(TransformerHandler handler, SourceResolver resolver) { + this.transformerHandler = handler; + this.sourceResolver = resolver; + } + + public void setInputSource(String source) throws MalformedURLException, IOException { + this.inputSource = sourceResolver.resolveURI(source); + } + + /* (non-Javadoc) + * @see org.apache.butterfly.xml.XMLProducer#setConsumer(org.apache.butterfly.xml.XMLConsumer) + */ + public void setConsumer(XMLConsumer consumer) { + setContentHandler(this.transformerHandler); + setLexicalHandler(this.transformerHandler); + // According to TrAX specs, all TransformerHandlers are LexicalHandlers + final SAXResult result = new SAXResult(consumer); + result.setLexicalHandler(consumer); + this.transformerHandler.setResult(result); + } +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/AbstractXMLPipe.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/AbstractXMLPipe.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,230 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.xml; + +import org.xml.sax.Attributes; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; + +/** + * This class provides a bridge class to connect to existing content + * handlers and lexical handlers. + * + * @author Stefano Mazzocchi + * @version CVS $Id: AbstractXMLPipe.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public abstract class AbstractXMLPipe extends AbstractXMLProducer implements XMLPipe { + + /** + * Receive an object for locating the origin of SAX document events. + * + * @param locator An object that can return the location of any SAX + * document event. + */ + public void setDocumentLocator(Locator locator) { + if (contentHandler != null) contentHandler.setDocumentLocator(locator); + } + + /** + * Receive notification of the beginning of a document. + */ + public void startDocument() + throws SAXException { + if (contentHandler != null) contentHandler.startDocument(); + } + + /** + * Receive notification of the end of a document. + */ + public void endDocument() + throws SAXException { + if (contentHandler != null) contentHandler.endDocument(); + } + + /** + * Begin the scope of a prefix-URI Namespace mapping. + * + * @param prefix The Namespace prefix being declared. + * @param uri The Namespace URI the prefix is mapped to. + */ + public void startPrefixMapping(String prefix, String uri) + throws SAXException { + if (contentHandler != null) contentHandler.startPrefixMapping(prefix, uri); + } + + /** + * End the scope of a prefix-URI mapping. + * + * @param prefix The prefix that was being mapping. + */ + public void endPrefixMapping(String prefix) + throws SAXException { + if (contentHandler != null) contentHandler.endPrefixMapping(prefix); + } + + /** + * Receive notification of the beginning of an element. + * + * @param uri The Namespace URI, or the empty string if the element has no + * Namespace URI or if Namespace + * processing is not being performed. + * @param loc The local name (without prefix), or the empty string if + * Namespace processing is not being performed. + * @param raw The raw XML 1.0 name (with prefix), or the empty string if + * raw names are not available. + * @param a The attributes attached to the element. If there are no + * attributes, it shall be an empty Attributes object. + */ + public void startElement(String uri, String loc, String raw, Attributes a) + throws SAXException { + if (contentHandler != null) contentHandler.startElement(uri, loc, raw, a); + } + + + /** + * Receive notification of the end of an element. + * + * @param uri The Namespace URI, or the empty string if the element has no + * Namespace URI or if Namespace + * processing is not being performed. + * @param loc The local name (without prefix), or the empty string if + * Namespace processing is not being performed. + * @param raw The raw XML 1.0 name (with prefix), or the empty string if + * raw names are not available. + */ + public void endElement(String uri, String loc, String raw) + throws SAXException { + if (contentHandler != null) contentHandler.endElement(uri, loc, raw); + } + + /** + * Receive notification of character data. + * + * @param c The characters from the XML document. + * @param start The start position in the array. + * @param len The number of characters to read from the array. + */ + public void characters(char c[], int start, int len) + throws SAXException { + if (contentHandler != null) contentHandler.characters(c, start, len); + } + + /** + * Receive notification of ignorable whitespace in element content. + * + * @param c The characters from the XML document. + * @param start The start position in the array. + * @param len The number of characters to read from the array. + */ + public void ignorableWhitespace(char c[], int start, int len) + throws SAXException { + if (contentHandler != null) contentHandler.ignorableWhitespace(c, start, len); + } + + /** + * Receive notification of a processing instruction. + * + * @param target The processing instruction target. + * @param data The processing instruction data, or null if none was + * supplied. + */ + public void processingInstruction(String target, String data) + throws SAXException { + if (contentHandler != null) contentHandler.processingInstruction(target, data); + } + + /** + * Receive notification of a skipped entity. + * + * @param name The name of the skipped entity. If it is a parameter + * entity, the name will begin with '%'. + */ + public void skippedEntity(String name) + throws SAXException { + if (contentHandler != null) contentHandler.skippedEntity(name); + } + + /** + * Report the start of DTD declarations, if any. + * + * @param name The document type name. + * @param publicId The declared public identifier for the external DTD + * subset, or null if none was declared. + * @param systemId The declared system identifier for the external DTD + * subset, or null if none was declared. + */ + public void startDTD(String name, String publicId, String systemId) + throws SAXException { + if (lexicalHandler != null) lexicalHandler.startDTD(name, publicId, systemId); + } + + /** + * Report the end of DTD declarations. + */ + public void endDTD() + throws SAXException { + if (lexicalHandler != null) lexicalHandler.endDTD(); + } + + /** + * Report the beginning of an entity. + * + * @param name The name of the entity. If it is a parameter entity, the + * name will begin with '%'. + */ + public void startEntity(String name) + throws SAXException { + if (lexicalHandler != null) lexicalHandler.startEntity(name); + } + + /** + * Report the end of an entity. + * + * @param name The name of the entity that is ending. + */ + public void endEntity(String name) + throws SAXException { + if (lexicalHandler != null) lexicalHandler.endEntity(name); + } + + /** + * Report the start of a CDATA section. + */ + public void startCDATA() + throws SAXException { + if (lexicalHandler != null) lexicalHandler.startCDATA(); + } + + /** + * Report the end of a CDATA section. + */ + public void endCDATA() + throws SAXException { + if (lexicalHandler != null) lexicalHandler.endCDATA(); + } + + /** + * Report an XML comment anywhere in the document. + * + * @param ch An array holding the characters in the comment. + * @param start The starting position in the array. + * @param len The number of characters to use from the array. + */ + public void comment(char ch[], int start, int len) + throws SAXException { + if (lexicalHandler != null) lexicalHandler.comment(ch, start, len); + } +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/AbstractXMLProducer.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/AbstractXMLProducer.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,81 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.xml; + +import org.xml.sax.ContentHandler; +import org.xml.sax.ext.LexicalHandler; + +/** + * This abstract class provides default implementation of the methods specified + * by the XMLProducer interface. + * + * @author Pierpaolo Fumagalli + * (Apache Software Foundation) + * @version CVS $Id: AbstractXMLProducer.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public abstract class AbstractXMLProducer +implements XMLProducer { + + /** The XMLConsumer receiving SAX events. */ + protected XMLConsumer xmlConsumer; + + /** The ContentHandler receiving SAX events. */ + protected ContentHandler contentHandler; + + /** The LexicalHandler receiving SAX events. */ + protected LexicalHandler lexicalHandler; + + /** + * Set the XMLConsumer that will receive XML data. + *
+ * This method will simply call setContentHandler(consumer) + * and setLexicalHandler(consumer). + */ + public void setConsumer(XMLConsumer consumer) { + this.xmlConsumer = consumer; + setContentHandler(consumer); + setLexicalHandler(consumer); + } + + /** + * Set the ContentHandler that will receive XML data. + *
+ * Subclasses may retrieve this ContentHandler instance + * accessing the protected super.contentHandler field. + */ + public void setContentHandler(ContentHandler handler) { + this.contentHandler = handler; + } + + /** + * Set the LexicalHandler that will receive XML data. + *
+ * Subclasses may retrieve this LexicalHandler instance + * accessing the protected super.lexicalHandler field. + */ + public void setLexicalHandler(LexicalHandler handler) { + this.lexicalHandler = handler; + } + + /** + * Recycle the producer by removing references + */ + public void recycle() { + this.xmlConsumer = null; + this.contentHandler = null; + this.lexicalHandler = null; + } +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/EmbeddedXMLPipe.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/EmbeddedXMLPipe.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,58 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.xml; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +/** + * This class implements a ContentHandler for embedding a full SAX + * event stream into an existing stream of SAX events. An instance of + * this class will pass unmodified all the SAX events to the linked + * ContentHandler, but will ignore the startDocument and endDocument + * events. + * + * @version CVS $Id: EmbeddedXMLPipe.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class EmbeddedXMLPipe extends AbstractXMLPipe +{ + /** + * Creates an EmbeddedXMLPipe that writes into the given ContentHandler. + */ + public EmbeddedXMLPipe(ContentHandler handler) { + setContentHandler(handler); + } + + /** + * Ignore the startDocument event: this method does nothing. + * + * @exception SAXException if an error occurs + */ + public void startDocument() + throws SAXException + { + } + + /** + * Ignore the endDocument event: this method does nothing. + * + * @exception SAXException if an error occurs + */ + public void endDocument() + throws SAXException + { + } +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/Parser.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/Parser.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,214 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.xml; + +import java.io.IOException; + +import org.apache.butterfly.source.Source; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.xml.sax.ContentHandler; +import org.xml.sax.DTDHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + + +/** + * Wraps a {@link org.xml.sax.XMLReader}. + * + * TODO: wrap all exceptions in runtime exceptions. + * + * @version CVS $Id: Parser.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class Parser { + private XMLReader xmlReader; + private String saxDriver; + + protected static final Log logger = LogFactory.getLog(Parser.class); + + /** + * @param saxDriver The saxDriver to set. + */ + public void setSaxDriver(String saxDriver) { + this.saxDriver = saxDriver; + } + + public void initialize() { + try { + xmlReader = XMLReaderFactory.createXMLReader(saxDriver); + } catch (SAXException e) { + throw new XMLException("Cannot initialize XML parser", e); + } + } + + public void parse(Source source) { + try { + xmlReader.parse(new InputSource(source.getInputStream())); + } catch (IOException e) { + // TODO log + throw new XMLException("I/O error while reading '" + source + "'", e); + } catch (SAXException e) { + // TODO log + throw new XMLException("SAX error while parsing '" + source + "'", e); + } + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object arg0) { + return xmlReader.equals(arg0); + } + + /** + * @return + */ + public ContentHandler getContentHandler() { + return xmlReader.getContentHandler(); + } + + /** + * @return + */ + public DTDHandler getDTDHandler() { + return xmlReader.getDTDHandler(); + } + + /** + * @return + */ + public EntityResolver getEntityResolver() { + return xmlReader.getEntityResolver(); + } + + /** + * @return + */ + public ErrorHandler getErrorHandler() { + return xmlReader.getErrorHandler(); + } + + /** + * @param arg0 + * @return + * @throws org.xml.sax.SAXNotRecognizedException + * @throws org.xml.sax.SAXNotSupportedException + */ + public boolean getFeature(String arg0) throws SAXNotRecognizedException, + SAXNotSupportedException { + return xmlReader.getFeature(arg0); + } + + /** + * @param arg0 + * @return + * @throws org.xml.sax.SAXNotRecognizedException + * @throws org.xml.sax.SAXNotSupportedException + */ + public Object getProperty(String arg0) throws SAXNotRecognizedException, + SAXNotSupportedException { + return xmlReader.getProperty(arg0); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return xmlReader.hashCode(); + } + + /** + * @param arg0 + * @throws java.io.IOException + * @throws org.xml.sax.SAXException + */ + public void parse(String arg0) throws IOException, SAXException { + xmlReader.parse(arg0); + } + + /** + * @param arg0 + * @throws java.io.IOException + * @throws org.xml.sax.SAXException + */ + public void parse(InputSource arg0) throws IOException, SAXException { + xmlReader.parse(arg0); + } + + /** + * @param arg0 + */ + public void setContentHandler(ContentHandler arg0) { + xmlReader.setContentHandler(arg0); + } + + /** + * @param arg0 + */ + public void setDTDHandler(DTDHandler arg0) { + xmlReader.setDTDHandler(arg0); + } + + /** + * @param arg0 + */ + public void setEntityResolver(EntityResolver arg0) { + xmlReader.setEntityResolver(arg0); + } + + /** + * @param arg0 + */ + public void setErrorHandler(ErrorHandler arg0) { + xmlReader.setErrorHandler(arg0); + } + + /** + * @param arg0 + * @param arg1 + * @throws org.xml.sax.SAXNotRecognizedException + * @throws org.xml.sax.SAXNotSupportedException + */ + public void setFeature(String arg0, boolean arg1) + throws SAXNotRecognizedException, SAXNotSupportedException { + xmlReader.setFeature(arg0, arg1); + } + + /** + * @param arg0 + * @param arg1 + * @throws org.xml.sax.SAXNotRecognizedException + * @throws org.xml.sax.SAXNotSupportedException + */ + public void setProperty(String arg0, Object arg1) + throws SAXNotRecognizedException, SAXNotSupportedException { + xmlReader.setProperty(arg0, arg1); + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + return xmlReader.toString(); + } +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/WhitespaceFilter.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/WhitespaceFilter.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,136 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.xml; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +/** + * A SAX filter to remove whitespace character, which disturb the + * XML matching process. + * + * @version CVS $Id: WhitespaceFilter.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class WhitespaceFilter extends AbstractXMLPipe { + private StringBuffer buffer = null; + + /** + * Create a new WhitespaceFilter. + * + * @param handler Content handler. + */ + public WhitespaceFilter(ContentHandler handler) { + setContentHandler(handler); + } + + /** + * Receive notification of character data. + */ + public void characters(char c[], int start, int len) throws SAXException { + if (contentHandler==null) { + return; + } + + if (buffer==null) { + buffer = new StringBuffer(); + } + + buffer.append(c, start, len); + } + + /** + * Receive notification of ignorable whitespace in element content. + */ + public void ignorableWhitespace(char c[], int start, + int len) throws SAXException { + // ignore + } + + /** + * Receive notification of the beginning of an element. + */ + public void startElement(String namespaceURI, String localName, + String qName, + Attributes atts) throws SAXException { + + pushText(); + contentHandler.startElement(namespaceURI, localName, qName, atts); + } + + /** + * Receive notification of the end of an element. + */ + public void endElement(String uri, String loc, String raw) + throws SAXException { + + pushText(); + contentHandler.endElement(uri, loc, raw); + } + + /** + * Receive notification of a processing instruction. + */ + public void processingInstruction(String target, String data) + throws SAXException { + + pushText(); + contentHandler.processingInstruction(target, data); + } + + /** + * Report an XML comment anywhere in the document. + * + * @param ch An array holding the characters in the comment. + * @param start The starting position in the array. + * @param len The number of characters to use from the array. + */ + public void comment(char ch[], int start, int len) + throws SAXException { + + pushText(); + super.comment(ch, start, len); + } + + + public void pushText() throws SAXException { + + if (buffer!=null) { + String text = buffer.toString(); + + StringBuffer normalized = new StringBuffer(); + + for(int i=0; i0) { + contentHandler.characters(text.toCharArray(), 0, + text.length()); + } + + buffer = null; + } + } +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/XMLConsumer.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/XMLConsumer.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,33 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.xml; + +import org.xml.sax.ContentHandler; +import org.xml.sax.ext.LexicalHandler; + +/** + * This interfaces identifies classes that consume XML data, receiving + * notification of SAX events. + *
+ * This interface unites the idea of SAX ContentHandler and + * LexicalHandler. + * + * @author Pierpaolo Fumagalli + * (Apache Software Foundation) + * @version CVS $Id: XMLConsumer.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public interface XMLConsumer extends ContentHandler, LexicalHandler { +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/XMLException.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/XMLException.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,60 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.xml; + + +/** + * Description of XMLException. + * + * @version CVS $Id: XMLException.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class XMLException extends RuntimeException { + + /** + * + */ + public XMLException() { + super(); + // TODO Auto-generated constructor stub + } + + /** + * @param arg0 + */ + public XMLException(String arg0) { + super(arg0); + // TODO Auto-generated constructor stub + } + + /** + * @param arg0 + * @param arg1 + */ + public XMLException(String arg0, Throwable arg1) { + super(arg0, arg1); + // TODO Auto-generated constructor stub + } + + /** + * @param arg0 + */ + public XMLException(Throwable arg0) { + super(arg0); + // TODO Auto-generated constructor stub + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/XMLPipe.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/XMLPipe.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,26 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * 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. + */ +package org.apache.butterfly.xml; + +/** + * This interface glues together an XML producer and consumer to create a + * SAX pipe. + * + * @author Stefano Mazzocchi + * @version CVS $Id: XMLPipe.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ + +public interface XMLPipe extends XMLConsumer, XMLProducer {} Added: cocoon/branches/src/java/org/apache/butterfly/xml/XMLProducer.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/XMLProducer.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,39 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.xml; + + + +/** + * This interfaces identifies classes that produce XML data, sending SAX + * events to the configured XMLConsumer. + *
+ * It's beyond the scope of this interface to specify a way in which the XML + * data production is started. + * + * @author Pierpaolo Fumagalli + * (Apache Software Foundation) + * @version CVS $Id: XMLProducer.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public interface XMLProducer { + + /** + * Set the XMLConsumer that will receive XML data. + */ + void setConsumer(XMLConsumer consumer); + + +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/dom/DOMBuilder.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/dom/DOMBuilder.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,141 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.xml.dom; + +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; + +import org.apache.butterfly.xml.AbstractXMLPipe; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +/** + * The DOMBuilder is a utility class that will generate a W3C + * DOM Document from SAX events. + * + * @author Carsten Ziegeler + * @version CVS $Id: DOMBuilder.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class DOMBuilder extends AbstractXMLPipe { + + /** The transformer factory shared by all instances */ + protected static final SAXTransformerFactory factory = (SAXTransformerFactory)TransformerFactory.newInstance(); + + /** The listener */ + protected Listener listener; + + /** The result */ + protected DOMResult result; + + /** The parentNode */ + protected Node parentNode; + + /** + * Construct a new instance of this DOMBuilder. + */ + public DOMBuilder() { + this( (Listener)null, (Node)null ); + } + + /** + * Construct a new instance of this DOMBuilder. + */ + public DOMBuilder( Listener listener ) { + this(listener, null); + } + + /** + * Construct a new instance of this DOMBuilder. + */ + public DOMBuilder( Listener listener, Node parentNode ) { + super(); + this.listener = listener; + try { + TransformerHandler handler = factory.newTransformerHandler(); + this.setContentHandler(handler); + this.setLexicalHandler(handler); + this.parentNode = parentNode; + if (parentNode != null) { + this.result = new DOMResult( parentNode ); + } else { + this.result = new DOMResult(); + } + handler.setResult(this.result); + } catch (javax.xml.transform.TransformerException local) { + throw new RuntimeException("Fatal-Error: Unable to get transformer handler", local); + } + } + + /** + * Constructs a new instance that appends nodes to the given parent node.
+ * Note : you cannot use a Listener when appending to a + * Node, because the notification occurs at endDocument() + * which does not happen here. + */ + public DOMBuilder( Node parentNode ) { + this( null, parentNode); + } + + /** + * Return the newly built Document. + */ + public Document getDocument() { + if ((this.result == null) || (this.result.getNode()==null)) { + return null; + } else if (this.result.getNode().getNodeType() == Node.DOCUMENT_NODE) { + return ( (Document)this.result.getNode() ); + } else { + return ( this.result.getNode().getOwnerDocument() ); + } + } + + /** + * Receive notification of the beginning of a document. + * + * @exception SAXException If this method was not called appropriately. + */ + public void endDocument() + throws SAXException { + super.endDocument(); + + // Notify the listener + this.notifyListener(); + } + + /** + * Receive notification of a successfully completed DOM tree generation. + */ + protected void notifyListener() + throws SAXException { + if ( this.listener != null ) this.listener.notify( this.getDocument() ); + } + + /** + * The Listener interface must be implemented by those objects willing to + * be notified of a successful DOM tree generation. + */ + public interface Listener { + + /** + * Receive notification of a successfully completed DOM tree generation. + */ + void notify(Document doc) + throws SAXException; + } +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/dom/DOMStreamer.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/dom/DOMStreamer.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,720 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.xml.dom; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXResult; + +import org.apache.butterfly.xml.AbstractXMLProducer; +import org.apache.butterfly.xml.EmbeddedXMLPipe; +import org.apache.butterfly.xml.XMLConsumer; +import org.apache.butterfly.xml.XMLProducer; +import org.apache.commons.lang.StringUtils; +import org.w3c.dom.Attr; +import org.w3c.dom.Comment; +import org.w3c.dom.Element; +import org.w3c.dom.EntityReference; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.ext.LexicalHandler; +import org.xml.sax.helpers.AttributesImpl; + +/** + * The DOMStreamer is a utility class that will generate SAX + * events from a W3C DOM Document. + * + *

The DOMStreamer uses a different strategy based on the value of the + * normalizeNamespaces property: + *

    + *
  • if true (the default), the DOMStreamer will normalize namespace + * declarations (i.e. add missing xmlns attributes or correct them). See + * also {@link NamespaceNormalizingDOMStreamer}. + *
  • if false, the standard JAXP identity transformer is used. + *
+ * + * @version CVS $Id: DOMStreamer.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class DOMStreamer implements XMLProducer { + + /** Default value for normalizeNamespaces. */ + private final boolean DEFAULT_NORMALIZE_NAMESPACES = true; + + /** Indicates whether namespace normalization should happen. */ + protected boolean normalizeNamespaces = DEFAULT_NORMALIZE_NAMESPACES; + + /** DOMStreamer used in case of namespace normalization. */ + protected NamespaceNormalizingDOMStreamer namespaceNormalizingDOMStreamer = new NamespaceNormalizingDOMStreamer(); + + /** DOMStreamer used when namespace normalization should not explicitely happen. */ + protected DefaultDOMStreamer defaultDOMStreamer = new DefaultDOMStreamer(); + + /** The transformer factory shared by all instances (only used by DefaultDOMStreamer) */ + protected static TransformerFactory factory = TransformerFactory.newInstance(); + + /** + * Create a new DOMStreamer instance. + */ + public DOMStreamer() { + super(); + } + + /** + * Create a new DOMStreamer instance. + */ + public DOMStreamer(XMLConsumer consumer) { + this(consumer, consumer); + } + + /** + * Create a new DOMStreamer instance. + */ + public DOMStreamer(ContentHandler content) { + this(content, null); + if (content instanceof LexicalHandler) { + defaultDOMStreamer.setLexicalHandler((LexicalHandler) content); + namespaceNormalizingDOMStreamer.setLexicalHandler((LexicalHandler) content); + } + } + + /** + * Create a new DOMStreamer instance. + */ + public DOMStreamer(ContentHandler content, LexicalHandler lexical) { + this(); + defaultDOMStreamer.setContentHandler(content); + defaultDOMStreamer.setLexicalHandler(lexical); + namespaceNormalizingDOMStreamer.setContentHandler(content); + namespaceNormalizingDOMStreamer.setLexicalHandler(lexical); + } + + /** + * Set the XMLConsumer that will receive XML data. + */ + public void setConsumer(XMLConsumer consumer) { + defaultDOMStreamer.setContentHandler(consumer); + defaultDOMStreamer.setLexicalHandler(consumer); + namespaceNormalizingDOMStreamer.setContentHandler(consumer); + namespaceNormalizingDOMStreamer.setLexicalHandler(consumer); + } + + /** + * Set the ContentHandler that will receive XML data. + */ + public void setContentHandler(ContentHandler handler) { + defaultDOMStreamer.setContentHandler(handler); + namespaceNormalizingDOMStreamer.setContentHandler(handler); + } + + /** + * Set the LexicalHandler that will receive XML data. + */ + public void setLexicalHandler(LexicalHandler handler) { + defaultDOMStreamer.setLexicalHandler(handler); + namespaceNormalizingDOMStreamer.setLexicalHandler(handler); + } + + /** + * Start the production of SAX events. + */ + public void stream(Node node) throws SAXException { + if (normalizeNamespaces) { + namespaceNormalizingDOMStreamer.stream(node); + } else { + defaultDOMStreamer.stream(node); + } + } + + public boolean isNormalizeNamespaces() { + return normalizeNamespaces; + } + + public void setNormalizeNamespaces(boolean normalizeNamespaces) { + this.normalizeNamespaces = normalizeNamespaces; + } + + /** + * Streams a DOM tree to SAX events and normalizes namespace declarations on the way. + * + *

The code in this class is based on the org.apache.xml.utils.TreeWalker class from Xalan, + * though it differs in some important ways. + * + *

This class will automatically fix up ("normalize") namespace declarations + * while streaming to SAX. The original DOM-tree is not modified. The algorithm + * used is described in + * an appendix of the DOM Level 3 spec. + * + *

This class will NOT check the correctness of namespaces, e.g. it will not + * check that the "xml" prefix is not misused etc. + * + * @author Bruno Dumon (bruno at outerthought dot org) + * @author Xalan team + */ + public class NamespaceNormalizingDOMStreamer extends AbstractXMLProducer { + /** + * Information about the current element. Used to remember the localName, qName + * and namespaceURI for generating the endElement event, and holds the namespaces + * declared on the element. This extra class is needed because we don't want to + * modify the DOM-tree itself. The currentElementInfo has a pointer to its parent + * elementInfo. + */ + protected NamespaceNormalizingDOMStreamer.ElementInfo currentElementInfo = null; + + /** Counter used when generating new namespace prefixes. */ + protected int newPrefixCounter = 0; + + public void recycle() { + super.recycle(); + currentElementInfo = null; + newPrefixCounter = 0; + } + + /** + * Start the production of SAX events. + * + *

Perform a pre-order traversal non-recursive style. + * + *

Note that TreeWalker assumes that the subtree is intended to represent + * a complete (though not necessarily well-formed) document and, during a + * traversal, startDocument and endDocument will always be issued to the + * SAX listener. + * + * @param pos Node in the tree where to start traversal + * + */ + protected void stream(Node pos) throws SAXException { + + // Start document only if we're streaming a document + boolean isDoc = (pos.getNodeType() == Node.DOCUMENT_NODE); + if (isDoc) { + contentHandler.startDocument(); + } + + Node top = pos; + while (null != pos) { + startNode(pos); + + Node nextNode = pos.getFirstChild(); + while (null == nextNode) { + endNode(pos); + + if (top.equals(pos)) { + break; + } + + nextNode = pos.getNextSibling(); + if (null == nextNode) { + pos = pos.getParentNode(); + + if ((null == pos) || (top.equals(pos))) { + if (null != pos) { + endNode(pos); + } + nextNode = null; + + break; + } + } + } + + pos = nextNode; + } + + if (isDoc) { + contentHandler.endDocument(); + } + } + + private final void dispatchChars(Node node) throws SAXException { + String data = ((Text) node).getData(); + contentHandler.characters(data.toCharArray(), 0, data.length()); + } + + /** + * Start processing given node + * + * @param node Node to process + */ + protected void startNode(Node node) throws SAXException { + + switch (node.getNodeType()) { + case Node.COMMENT_NODE: + { + if (lexicalHandler != null) { + String data = ((Comment) node).getData(); + lexicalHandler.comment(data.toCharArray(), 0, data.length()); + } + } + break; + case Node.DOCUMENT_FRAGMENT_NODE: + + // ??; + break; + case Node.DOCUMENT_NODE: + + break; + case Node.ELEMENT_NODE: + NamedNodeMap atts = node.getAttributes(); + int nAttrs = atts.getLength(); + + // create a list of localy declared namespace prefixes + currentElementInfo = new NamespaceNormalizingDOMStreamer.ElementInfo(currentElementInfo); + for (int i = 0; i < nAttrs; i++) { + Node attr = atts.item(i); + String attrName = attr.getNodeName(); + + if (attrName.equals("xmlns") || attrName.startsWith("xmlns:")) { + int index; + String prefix = (index = attrName.indexOf(":")) < 0 + ? "" : attrName.substring(index + 1); + + currentElementInfo.put(prefix, attr.getNodeValue()); + } + } + + String namespaceURI = node.getNamespaceURI(); + String prefix = node.getPrefix(); + String localName = node.getLocalName(); + + if (localName == null) { + // this is an element created with createElement instead of createElementNS + String[] prefixAndLocalName = getPrefixAndLocalName(node.getNodeName()); + prefix = prefixAndLocalName[0]; + localName = prefixAndLocalName[1]; + // note: if prefix is null, there can still be a default namespace... + namespaceURI = getNamespaceForPrefix(prefix, (Element)node); + } + + if (namespaceURI != null) { + // no prefix means: make this the default namespace + if (prefix == null) { + prefix = ""; + } + // check that is declared + String uri = currentElementInfo.findNamespaceURI(prefix); + if (StringUtils.equals(uri, namespaceURI)) { + // System.out.println("namespace is declared"); + // prefix is declared correctly, do nothing + } else if (uri != null) { + // System.out.println("prefix is declared with other namespace, overwriting it"); + // prefix exists but is bound to another namespace, overwrite it + currentElementInfo.put(prefix, namespaceURI); + } else { + // System.out.println("prefix is not yet declared, declaring it now"); + currentElementInfo.put(prefix, namespaceURI); + } + } else { + // element has no namespace + // check if there is a default namespace, if so undeclare it + String uri = currentElementInfo.findNamespaceURI(""); + if (StringUtils.isNotEmpty(uri)) { + // System.out.println("undeclaring default namespace"); + currentElementInfo.put("", ""); + } + } + + // SAX uses empty string to denote no namespace, while DOM uses null. + if (namespaceURI == null) + namespaceURI = ""; + + String qName; + if (StringUtils.isNotEmpty(prefix)) { + qName = prefix + ":" + localName; + } else { + qName = localName; + } + + // make the attributes + AttributesImpl newAttrs = new AttributesImpl(); + for (int i = 0; i < nAttrs; i++) { + Node attr = atts.item(i); + String attrName = attr.getNodeName(); + String assignedAttrPrefix = null; + + // only do non-namespace attributes + if (!(attrName.equals("xmlns") || attrName.startsWith("xmlns:"))) { + String attrPrefix; + String attrLocalName; + String attrNsURI; + + if (attr.getLocalName() == null) { + // this is an attribute created with setAttribute instead of setAttributeNS + String[] prefixAndLocalName = getPrefixAndLocalName(attrName); + attrPrefix = prefixAndLocalName[0]; + // the statement below causes the attribute to keep its prefix even if it is not + // bound to a namespace (to support pre-namespace XML). + assignedAttrPrefix = attrPrefix; + attrLocalName = prefixAndLocalName[1]; + // note: if prefix is null, the attribute has no namespace (namespace defaulting + // does not apply to attributes) + if (attrPrefix != null) + attrNsURI = getNamespaceForPrefix(attrPrefix, (Element)node); + else + attrNsURI = null; + } else { + attrLocalName = attr.getLocalName(); + attrPrefix = attr.getPrefix(); + attrNsURI = attr.getNamespaceURI(); + } + + if (attrNsURI != null) { + String declaredUri = currentElementInfo.findNamespaceURI(attrPrefix); + // if the prefix is null, or the prefix has not been declared, or conflicts with an in-scope binding + if (declaredUri == null || !declaredUri.equals(attrNsURI)) { + String availablePrefix = currentElementInfo.findPrefix(attrNsURI); + if (availablePrefix != null) + assignedAttrPrefix = availablePrefix; + else { + if (attrPrefix != null && declaredUri == null) { + // prefix is not null and is not yet declared: declare it + assignedAttrPrefix = attrPrefix; + currentElementInfo.put(assignedAttrPrefix, attrNsURI); + } else { + // attribute has no prefix (which is not allowed for namespaced attributes) or + // the prefix is already bound to something else: generate a new prefix + newPrefixCounter++; + assignedAttrPrefix = "NS" + newPrefixCounter; + currentElementInfo.put(assignedAttrPrefix, attrNsURI); + } + } + } else { + assignedAttrPrefix = attrPrefix; + } + } + + String assignedAttrNsURI = attrNsURI != null ? attrNsURI : ""; + String attrQName; + if (assignedAttrPrefix != null) { + attrQName = assignedAttrPrefix + ":" + attrLocalName; + } else { + attrQName = attrLocalName; + } + newAttrs.addAttribute(assignedAttrNsURI, attrLocalName, attrQName, "CDATA", attr.getNodeValue()); + } + } + + // add local namespace declaration and fire startPrefixMapping events + if (currentElementInfo.namespaceDeclarations != null && currentElementInfo.namespaceDeclarations.size() > 0) { + Iterator localNsDeclIt = currentElementInfo.namespaceDeclarations.entrySet().iterator(); + while (localNsDeclIt.hasNext()) { + Map.Entry entry = (Map.Entry) localNsDeclIt.next(); + String pr = (String) entry.getKey(); + String ns = (String) entry.getValue(); + // the following lines enable the creation of explicit xmlns attributes + //String pr1 = pr.equals("") ? "xmlns" : pr; + //String qn = pr.equals("") ? "xmlns" : "xmlns:" + pr; + //newAttrs.addAttribute("", pr1, qn, "CDATA", ns); + // System.out.println("starting prefix mapping for prefix " + pr + " for " + ns); + contentHandler.startPrefixMapping(pr, ns); + } + } + + contentHandler.startElement(namespaceURI, localName, qName, newAttrs); + + currentElementInfo.localName = localName; + currentElementInfo.namespaceURI = namespaceURI; + currentElementInfo.qName = qName; + break; + case Node.PROCESSING_INSTRUCTION_NODE: + { + ProcessingInstruction pi = (ProcessingInstruction) node; + contentHandler.processingInstruction(pi.getNodeName(), pi.getData()); + } + break; + case Node.CDATA_SECTION_NODE: + { + if (lexicalHandler != null) + lexicalHandler.startCDATA(); + + dispatchChars(node); + + if (lexicalHandler != null) + lexicalHandler.endCDATA(); + } + break; + case Node.TEXT_NODE: + { + dispatchChars(node); + } + break; + case Node.ENTITY_REFERENCE_NODE: + { + EntityReference eref = (EntityReference) node; + + if (lexicalHandler != null) { + lexicalHandler.startEntity(eref.getNodeName()); + } else { + // warning("Can not output entity to a pure SAX ContentHandler"); + } + } + break; + default : + } + } + + /** + * Searches the namespace for a given namespace prefix starting from a + * given Element. + * + *

Note that this resolves the prefix in the orginal DOM-tree, not in + * the {@link ElementInfo} objects. This is used to resolve prefixes + * of elements or attributes created with createElement or setAttribute + * instead of createElementNS or setAttributeNS. + * + *

The code in this method is largely based on + * org.apache.xml.utils.DOMHelper.getNamespaceForPrefix() (from Xalan). + * + * @param prefix the prefix to look for, can be empty or null to find the + * default namespace + * + * @return the namespace, or null if not found. + */ + public String getNamespaceForPrefix(String prefix, Element namespaceContext) { + int type; + Node parent = namespaceContext; + String namespace = null; + + if (prefix == null) + prefix = ""; + + if (prefix.equals("xml")) { + namespace = "http://www.w3.org/XML/1998/namespace"; + } else if(prefix.equals("xmlns")) { + namespace = "http://www.w3.org/2000/xmlns/"; + } else { + // Attribute name for this prefix's declaration + String declname = (prefix == "") ? "xmlns" : "xmlns:" + prefix; + + // Scan until we run out of Elements or have resolved the namespace + while ((null != parent) && (null == namespace) + && (((type = parent.getNodeType()) == Node.ELEMENT_NODE) + || (type == Node.ENTITY_REFERENCE_NODE))) { + if (type == Node.ELEMENT_NODE) { + Attr attr=((Element)parent).getAttributeNode(declname); + if (attr != null) { + namespace = attr.getNodeValue(); + break; + } + } + parent = parent.getParentNode(); + } + } + return namespace; + } + + /** + * Splits a nodeName into a prefix and a localName + * + * @return an array containing two elements, the first one is the prefix (can be null), the + * second one is the localName + */ + private String[] getPrefixAndLocalName(String nodeName) { + String prefix, localName; + int colonPos = nodeName.indexOf(":"); + if (colonPos != -1) { + prefix = nodeName.substring(0, colonPos); + localName = nodeName.substring(colonPos + 1, nodeName.length()); + } else { + prefix = null; + localName = nodeName; + } + return new String[] {prefix, localName}; + } + + + /** + * End processing of given node + * + * @param node Node we just finished processing + */ + protected void endNode(Node node) throws org.xml.sax.SAXException { + + switch (node.getNodeType()) { + case Node.DOCUMENT_NODE: + break; + + case Node.ELEMENT_NODE: + contentHandler.endElement(currentElementInfo.namespaceURI, + currentElementInfo.localName, currentElementInfo.qName); + + // generate endPrefixMapping events if needed + if (currentElementInfo.namespaceDeclarations != null && currentElementInfo.namespaceDeclarations.size() > 0) { + Iterator namespaceIt = currentElementInfo.namespaceDeclarations.entrySet().iterator(); + while (namespaceIt.hasNext()) { + Map.Entry entry = (Map.Entry) namespaceIt.next(); + contentHandler.endPrefixMapping((String) entry.getKey()); + //System.out.println("ending prefix mapping " + (String) entry.getKey()); + } + } + + currentElementInfo = currentElementInfo.parent; + break; + case Node.CDATA_SECTION_NODE: + break; + case Node.ENTITY_REFERENCE_NODE: + { + EntityReference eref = (EntityReference) node; + + if (lexicalHandler != null) { + lexicalHandler.endEntity(eref.getNodeName()); + } + } + break; + default : + } + } + + public class ElementInfo { + public String localName; + public String namespaceURI; + public String qName; + public Map namespaceDeclarations = null; + public ElementInfo parent; + + public ElementInfo(ElementInfo parent) { + this.parent = parent; + } + + /** + * Declare a new namespace prefix on this element, possibly overriding + * an existing one. + */ + public void put(String prefix, String namespaceURI) { + if (namespaceDeclarations == null) + namespaceDeclarations = new HashMap(); + namespaceDeclarations.put(prefix, namespaceURI); + } + + /** + * Finds a prefix declared on this element. + */ + public String getPrefix(String namespaceURI) { + if (namespaceDeclarations == null || namespaceDeclarations.size() == 0) + return null; + // note: there could be more than one prefix for the same namespaceURI, but + // we return the first found one. + Iterator it = namespaceDeclarations.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = (Map.Entry) it.next(); + if (entry.getValue().equals(namespaceURI)) + return (String) entry.getKey(); + } + return null; + } + + /** + * Finds a namespace URI declared on this element. + */ + public String getNamespaceURI(String prefix) { + if (namespaceDeclarations == null || namespaceDeclarations.size() == 0) + return null; + + return (String) namespaceDeclarations.get(prefix); + } + + /** + * Finds a prefix declaration on this element or containing elements. + */ + public String findPrefix(String namespaceURI) { + if (namespaceDeclarations != null && namespaceDeclarations.size() != 0) { + String prefix = getPrefix(namespaceURI); + if (prefix != null) { + return prefix; + } + } + if (parent != null) { + return parent.findPrefix(namespaceURI); + } else { + return null; + } + } + + /** + * Finds a namespace declaration on this element or containing elements. + */ + public String findNamespaceURI(String prefix) { + if (namespaceDeclarations != null && namespaceDeclarations.size() != 0) { + String uri = (String) namespaceDeclarations.get(prefix); + if (uri != null) { + return uri; + } + } + if (parent != null) + return parent.findNamespaceURI(prefix); + else + return null; + } + } + } + + /** + * The DefaultDOMStreamer is a utility class that will generate SAX + * events from a W3C DOM Document. + * + * @author Carsten Ziegeler + * @author Pierpaolo Fumagalli + * (Apache Software Foundation) + */ + public class DefaultDOMStreamer extends AbstractXMLProducer { + + /** The private transformer for this instance */ + protected Transformer transformer; + + /** + * Start the production of SAX events. + */ + public void stream(Node node) + throws SAXException { + if (this.transformer == null) { + try { + this.transformer = factory.newTransformer(); + } catch (TransformerConfigurationException e) { + throw new SAXException(e); + } + } + DOMSource source = new DOMSource(node); + + ContentHandler handler; + if (node.getNodeType() == Node.DOCUMENT_NODE) { + // Pass all SAX events + handler = contentHandler; + } else { + // Strip start/endDocument + handler = new EmbeddedXMLPipe(contentHandler); + } + + SAXResult result = new SAXResult(handler); + result.setLexicalHandler(lexicalHandler); + + try { + transformer.transform(source, result); + } catch (TransformerException e) { + throw new SAXException(e); + } + } + } +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/xslt/TraxException.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/xslt/TraxException.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,60 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.xml.xslt; + + +/** + * Description of TraxException. + * + * @version CVS $Id: TraxException.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class TraxException extends RuntimeException { + + /** + * + */ + public TraxException() { + super(); + // TODO Auto-generated constructor stub + } + + /** + * @param arg0 + */ + public TraxException(String arg0) { + super(arg0); + // TODO Auto-generated constructor stub + } + + /** + * @param arg0 + * @param arg1 + */ + public TraxException(String arg0, Throwable arg1) { + super(arg0, arg1); + // TODO Auto-generated constructor stub + } + + /** + * @param arg0 + */ + public TraxException(Throwable arg0) { + super(arg0); + // TODO Auto-generated constructor stub + } + +} Added: cocoon/branches/src/java/org/apache/butterfly/xml/xslt/TraxTransformerFactory.java ============================================================================== --- (empty file) +++ cocoon/branches/src/java/org/apache/butterfly/xml/xslt/TraxTransformerFactory.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,79 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.xml.xslt; + +import javax.xml.transform.Source; +import javax.xml.transform.Templates; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamSource; + +import org.apache.butterfly.source.SourceResolver; +import org.apache.butterfly.transformation.TraxTransformer; + + +/** + * Description of TraxTransformerFactory. + * + * @version CVS $Id: TraxTransformerFactory.java,v 1.1 2004/07/23 08:47:20 ugo Exp $ + */ +public class TraxTransformerFactory { + private SourceResolver sourceResolver; + private SAXTransformerFactory transformerFactory; + + /** + * + */ + public TraxTransformerFactory() { + this.transformerFactory = (SAXTransformerFactory) TransformerFactory.newInstance(); + } + + /** + * @param sourceResolver The sourceResolver to set. + */ + public void setSourceResolver(SourceResolver sourceResolver) { + this.sourceResolver = sourceResolver; + } + + public TraxTransformer getTransformer(String src) { + Source source = new StreamSource(sourceResolver.resolveURI(src).getInputStream()); + synchronized (this.transformerFactory) { + try { + Templates stylesheet = this.transformerFactory.newTemplates(source); + // TODO: cache templates? + return new TraxTransformer(transformerFactory.newTransformerHandler(stylesheet), + this.sourceResolver); + } catch (TransformerConfigurationException e) { + // TODO log? + throw new TraxException("Cannot create a new XSLT template.", e); + } + } + } + + public TransformerHandler getTransformerHandler() { + synchronized (this.transformerFactory) { + try { + return this.transformerFactory.newTransformerHandler(); + } catch (TransformerConfigurationException e) { + // TODO log? + throw new TraxException("Cannot create a new TransformerHandler.", e); + } + } + } +} Added: cocoon/branches/src/test/beans.xml ============================================================================== --- (empty file) +++ cocoon/branches/src/test/beans.xml Wed Jul 28 13:25:41 2004 @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.apache.xerces.parsers.SAXParser + + + + + + + + + + + + + + + + + + + + + + + + UTF-8 + + + + Added: cocoon/branches/src/test/log4j.properties ============================================================================== --- (empty file) +++ cocoon/branches/src/test/log4j.properties Wed Jul 28 13:25:41 2004 @@ -0,0 +1,15 @@ +# Configure logging for testing + +log4j.rootCategory=WARN, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p %c - %m%n + +#log4j.category.org.springframework.aop.framework.ProxyFactoryBean=DEBUG + +log4j.category.org.springframework.enterpriseservices=DEBUG + +log4j.category.org.springframework.transaction.interceptor=INFO + +log4j.category.org.springframework.beans.factory=INFO Added: cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/GroovySitemapTestCase.java ============================================================================== --- (empty file) +++ cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/GroovySitemapTestCase.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,62 @@ +package org.apache.butterfly.components.pipeline.impl; +import groovy.lang.GroovyClassLoader; +import groovy.lang.GroovyObject; + +import java.io.IOException; + +import junit.framework.TestCase; + +import org.codehaus.groovy.control.CompilationFailedException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.core.io.ClassPathResource; + +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ + +/** + * Description of GroovySitemapTestCase. + * + * @version CVS $Id: GroovySitemapTestCase.java,v 1.1 2004/07/27 20:54:17 ugo Exp $ + */ +public class GroovySitemapTestCase extends TestCase { + + private BeanFactory beanFactory; + + /** + * @param name + */ + public GroovySitemapTestCase(String name) { + super(name); + } + + protected void setUp() throws Exception { + ClassPathResource res = new ClassPathResource("beans.xml"); + beanFactory = new XmlBeanFactory(res); + } + + public void testGroovySitemap() throws CompilationFailedException, IOException, InstantiationException, IllegalAccessException { + ClassLoader parent = getClass().getClassLoader(); + GroovyClassLoader loader = new GroovyClassLoader(parent); + Class pipelineClass = loader.parseClass(getClass().getResourceAsStream("Pipeline.groovy")); + Class myPipelineClass = loader.parseClass(getClass().getResourceAsStream("MyPipeline.groovy")); + GroovyObject pipeline = (GroovyObject) myPipelineClass.newInstance(); + pipeline.setProperty("beanFactory", beanFactory); + Object[] args = { "index.html" }; + pipeline.invokeMethod("define", args); + pipeline.invokeMethod("process", new Object[] {}); + } +} Added: cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/MyPipeline.groovy ============================================================================== --- (empty file) +++ cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/MyPipeline.groovy Wed Jul 28 13:25:41 2004 @@ -0,0 +1,13 @@ +class MyPipeline extends Pipeline { + + void define(String requestPath) { + if (requestPath =~ ".*\.html") { + generate "testdata/traxtest-input.xml" + transform "trax", "testdata/traxtest-style.xsl" + serialize "xml" + } + else { + println("No matches for " + requestPath); + } + } +} \ No newline at end of file Added: cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase.java ============================================================================== --- (empty file) +++ cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/NonCachingProcessingPipelineTestCase.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,398 @@ +/* + * Copyright 2004, Ugo Cei. + * + * 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. + */ +package org.apache.butterfly.components.pipeline.impl; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.butterfly.components.pipeline.InvalidPipelineException; +import org.apache.butterfly.generation.FileGenerator; +import org.apache.butterfly.generation.Generator; +import org.apache.butterfly.reading.Reader; +import org.apache.butterfly.serialization.Serializer; +import org.apache.butterfly.source.SourceResolver; +import org.apache.butterfly.source.impl.FileSourceFactory; +import org.apache.butterfly.transformation.Transformer; +import org.apache.butterfly.transformation.TraxTransformer; +import org.apache.butterfly.xml.Parser; +import org.apache.butterfly.xml.WhitespaceFilter; +import org.apache.butterfly.xml.XMLConsumer; +import org.apache.butterfly.xml.dom.DOMBuilder; +import org.apache.butterfly.xml.xslt.TraxTransformerFactory; +import org.custommonkey.xmlunit.XMLUnit; +import org.jmock.Mock; +import org.jmock.MockObjectTestCase; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; + + +/** + * test case for NonCachingProcessingPipeline. + * + * @version CVS $Id: NonCachingProcessingPipelineTestCase.java,v 1.8 2004/07/26 22:44:18 ugo Exp $ + */ +public class NonCachingProcessingPipelineTestCase extends MockObjectTestCase { + + private Generator stubGenerator; + private Reader stubReader; + private Transformer stubTransformer; + private Serializer stubSerializer; + private FileGenerator fileGenerator; + private TraxTransformerFactory transformerFactory; + + public NonCachingProcessingPipelineTestCase(String name) { + super(name); + } + + public void setUp() { + // Set up stubs + stubGenerator = new Generator() { + public void generate() {} + public void setConsumer(XMLConsumer consumer) {} + }; + + stubReader = new Reader() { + public void generate() {} + public long getLastModified() { + return 0; + } + public void setOutputStream(OutputStream out) {} + public String getMimeType() { + return null; + } + public boolean shouldSetContentLength() { + return false; + } + }; + + stubTransformer = new Transformer() { + public void setDocumentLocator(Locator arg0) {} + public void startDocument() throws SAXException {} + public void endDocument() throws SAXException {} + public void startPrefixMapping(String arg0, String arg1) throws SAXException {} + public void endPrefixMapping(String arg0) throws SAXException {} + public void startElement(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException {} + public void endElement(String arg0, String arg1, String arg2) throws SAXException {} + public void characters(char[] arg0, int arg1, int arg2) throws SAXException {} + public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException {} + public void processingInstruction(String arg0, String arg1) throws SAXException {} + public void skippedEntity(String arg0) throws SAXException {} + public void startDTD(String arg0, String arg1, String arg2) throws SAXException {} + public void endDTD() throws SAXException {} + public void startEntity(String arg0) throws SAXException {} + public void endEntity(String arg0) throws SAXException {} + public void startCDATA() throws SAXException {} + public void endCDATA() throws SAXException {} + public void comment(char[] arg0, int arg1, int arg2) throws SAXException {} + public void setConsumer(XMLConsumer consumer) {} + }; + + stubSerializer = new Serializer() { + public void setDocumentLocator(Locator arg0) {} + public void startDocument() throws SAXException {} + public void endDocument() throws SAXException {} + public void startPrefixMapping(String arg0, String arg1) throws SAXException {} + public void endPrefixMapping(String arg0) throws SAXException {} + public void startElement(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException {} + public void endElement(String arg0, String arg1, String arg2) throws SAXException {} + public void characters(char[] arg0, int arg1, int arg2) throws SAXException {} + public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException {} + public void processingInstruction(String arg0, String arg1) throws SAXException {} + public void skippedEntity(String arg0) throws SAXException {} + public void startDTD(String arg0, String arg1, String arg2) throws SAXException {} + public void endDTD() throws SAXException {} + public void startEntity(String arg0) throws SAXException {} + public void endEntity(String arg0) throws SAXException {} + public void startCDATA() throws SAXException {} + public void endCDATA() throws SAXException {} + public void comment(char[] arg0, int arg1, int arg2) throws SAXException {} + public void setConsumer(XMLConsumer consumer) {} + public void setOutputStream(OutputStream out) {} + public String getMimeType() { + return null; + } + public boolean shouldSetContentLength() { + return false; + } + }; + + // Set up real compponents + SourceResolver sourceResolver = new SourceResolver(); + Map sourceFactories = new HashMap(); + sourceFactories.put("*", new FileSourceFactory()); + sourceResolver.setFactories(sourceFactories); + Parser parser = new Parser(); + parser.setSaxDriver("org.apache.xerces.parsers.SAXParser"); + parser.initialize(); + fileGenerator = new FileGenerator(); + fileGenerator.setSourceResolver(sourceResolver); + fileGenerator.setParser(parser); + transformerFactory = new TraxTransformerFactory(); + transformerFactory.setSourceResolver(sourceResolver); + } + + /** + * Test if setting reader after having set the generator causes + * error. + */ + public void testSetReaderAfterGenerator() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + pipeline.setGenerator(stubGenerator); + try { + pipeline.setReader(stubReader); + fail("Setting reader after generator did not cause an exception."); + } catch(InvalidPipelineException e) {} + } + + /** + * Test if setting generator after having set the reader causes + * error. + */ + public void testSetGeneratorAfterReader() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + pipeline.setReader(stubReader); + try { + pipeline.setGenerator(stubGenerator); + fail("Setting generator after reader did not cause an exception."); + } catch(InvalidPipelineException e) {} + } + + /** + * Test if setting generator twice causes error. + */ + public void testSetGeneratorTwice() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + pipeline.setGenerator(stubGenerator); + try { + pipeline.setGenerator(stubGenerator); + fail("Setting generator twice did not cause an exception."); + } catch(InvalidPipelineException e) {} + } + + /** + * Test if setting reader twice causes error. + */ + public void testSetReaderTwice() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + pipeline.setReader(stubReader); + try { + pipeline.setReader(stubReader); + fail("Setting reader twice did not cause an exception."); + } catch(InvalidPipelineException e) {} + } + + /** + * Test if adding a transformer without having set the generator causes + * error. + */ + public void testAddTransformerWithoutGenerator() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + try { + pipeline.addTransformer(stubTransformer); + fail("Adding transformer without a generator did not cause an exception."); + } catch(InvalidPipelineException e) {} + } + + /** + * Test if adding a transformer after having set the reader causes + * error. + */ + public void testAddTransformerAfterReader() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + pipeline.setReader(stubReader); + try { + pipeline.addTransformer(stubTransformer); + fail("Adding transformer after reader did not cause an exception."); + } catch(InvalidPipelineException e) {} + } + + /** + * Test if setting serializer after having set the reader causes + * error. + */ + public void testSetSerializerAfterReader() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + pipeline.setReader(stubReader); + try { + pipeline.setSerializer(stubSerializer); + fail("Setting generator after reader did not cause an exception."); + } catch(InvalidPipelineException e) {} + } + + /** + * Test if setting serializer without having set the generator causes + * error. + */ + public void testSetSerializerWithoutGenerator() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + try { + pipeline.setSerializer(stubSerializer); + fail("Setting generator after reader did not cause an exception."); + } catch(InvalidPipelineException e) {} + } + + /** + * Test if setting serializer twice causes error. + */ + public void testSetSerializerTwice() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + pipeline.setGenerator(stubGenerator); + pipeline.setSerializer(stubSerializer); + try { + pipeline.setSerializer(stubSerializer); + fail("Setting serializer twice did not cause an exception."); + } catch(InvalidPipelineException e) {} + } + + /** + * Test if processing an internal pipeline with a reader causes error. + */ + public void testProcessInternalWithReader() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + pipeline.setReader(stubReader); + try { + pipeline.process(null, null); + fail("Processing an internal pipeline with a reader did not cause an exception."); + } catch(InvalidPipelineException e) {} + } + + /** + * Test if the @link{NonCachingProcessingPipeline#connect(Environment)} method + * correctly connects pipeline components. + */ + public void testConnect() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + // Setup mocks + Mock mockGenerator = new Mock(Generator.class); + Mock mockTransformer1 = new Mock(Transformer.class); + Mock mockTransformer2 = new Mock(Transformer.class); + Mock mockSerializer = new Mock(Serializer.class); + mockGenerator.expects(once()).method("setConsumer").with(same(mockTransformer1.proxy())); + mockTransformer1.expects(once()).method("setConsumer").with(same(mockTransformer2.proxy())); + mockTransformer2.expects(once()).method("setConsumer").with(same(mockSerializer.proxy())); + + pipeline.setGenerator((Generator) mockGenerator.proxy()); + pipeline.addTransformer((Transformer) mockTransformer1.proxy()); + pipeline.addTransformer((Transformer) mockTransformer2.proxy()); + pipeline.setSerializer((Serializer) mockSerializer.proxy()); + pipeline.connectPipeline(null); + + mockGenerator.verify(); + } + + /** + * Test if sane pipeline passes check. + */ + public void testCheckSanePipeline() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + pipeline.setGenerator(stubGenerator); + pipeline.addTransformer(stubTransformer); + pipeline.setSerializer(stubSerializer); + assertTrue("Pipeline should be sane.", pipeline.checkPipeline()); + } + + /** + * Test if pipeline with reader passes check. + */ + public void testCheckReaderPipeline() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + pipeline.setReader(stubReader); + assertTrue("Pipeline should be sane.", pipeline.checkPipeline()); + } + + /** + * Verify that empty pipeline does not pass check. + */ + public void testCheckEmptyPipeline() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + assertFalse("Pipeline should not be sane.", pipeline.checkPipeline()); + } + + /** + * Verify that pipeline without serializer does not pass check. + */ + public void testCheckPipelineWithoutSerializer() { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + pipeline.setGenerator(stubGenerator); + pipeline.addTransformer(stubTransformer); + assertFalse("Pipeline should not be sane.", pipeline.checkPipeline()); + } + + /** + * Test event pipeline processing with only a generator. + * @throws ParserConfigurationException + * @throws SAXException + * @throws IOException + */ + public void testProcessSimpleEventPipeline() throws IOException, SAXException, ParserConfigurationException { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + XMLUnit.setIgnoreWhitespace(true); + fileGenerator.setInputSource("testdata/test1.xml"); + pipeline.setGenerator(fileGenerator); + pipeline.setSerializer(stubSerializer); + DOMBuilder builder = new DOMBuilder(); + pipeline.process(null, new WhitespaceFilter(builder)); + assertTrue("Output from pipeline does not match input file.", + XMLUnit.compareXML( + XMLUnit.buildControlDocument(new InputSource("testdata/test1.xml")), + builder.getDocument()).similar()); + } + + /** + * Test event pipeline processing with a transformer. + * @throws ParserConfigurationException + * @throws SAXException + * @throws IOException + */ + public void testProcessEventPipeline() throws IOException, SAXException, ParserConfigurationException { + NonCachingProcessingPipeline pipeline = + new NonCachingProcessingPipeline(); + XMLUnit.setIgnoreWhitespace(true); + fileGenerator.setInputSource("testdata/traxtest-input.xml"); + pipeline.setGenerator(fileGenerator); + TraxTransformer transformer = transformerFactory.getTransformer("testdata/traxtest-style.xsl"); + pipeline.addTransformer(transformer); + pipeline.setSerializer(stubSerializer); + DOMBuilder builder = new DOMBuilder(); + pipeline.process(null, new WhitespaceFilter(builder)); + assertTrue("Output from pipeline does not match control file.", + XMLUnit.compareXML( + XMLUnit.buildControlDocument(new InputSource("testdata/traxtest-result.xml")), + builder.getDocument()).similar()); + } +} Added: cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/Pipeline.groovy ============================================================================== --- (empty file) +++ cocoon/branches/src/test/org/apache/butterfly/components/pipeline/impl/Pipeline.groovy Wed Jul 28 13:25:41 2004 @@ -0,0 +1,34 @@ +import org.apache.butterfly.xml.dom.DOMBuilder +import org.apache.butterfly.components.pipeline.impl.NonCachingProcessingPipeline + +class Pipeline { + public beanFactory; + private pipeline; + + protected Pipeline() { + this.pipeline = new NonCachingProcessingPipeline() + } + + protected void generate(src) { + generator = beanFactory.getBean("fileGenerator") + generator.inputSource = src + this.pipeline.generator = generator + } + + protected void transform(type, src) { + factory = beanFactory.getBean(type + "TransformerFactory") + transformer = factory.getTransformer(src) + this.pipeline.addTransformer(transformer) + } + + protected void serialize(type) { + serializer = beanFactory.getBean(type + "Serializer") + this.pipeline.serializer = serializer + } + + public void process() { + builder = new DOMBuilder() + this.pipeline.process(null, builder) + println(builder.document.documentElement) + } +} \ No newline at end of file Added: cocoon/branches/src/test/org/apache/butterfly/generation/FileGeneratorTestCase.java ============================================================================== --- (empty file) +++ cocoon/branches/src/test/org/apache/butterfly/generation/FileGeneratorTestCase.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,56 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.generation; + +import java.io.IOException; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.butterfly.test.SitemapComponentTestCase; +import org.apache.butterfly.xml.WhitespaceFilter; +import org.apache.butterfly.xml.dom.DOMBuilder; +import org.custommonkey.xmlunit.XMLUnit; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + + +/** + * Description of FileGeneratorTestCase. + * + * @version CVS $Id: FileGeneratorTestCase.java,v 1.2 2004/07/24 20:31:57 ugo Exp $ + */ +public class FileGeneratorTestCase extends SitemapComponentTestCase { + + /** + * @param name + */ + public FileGeneratorTestCase(String name) { + super(name); + } + + public void testSimpleXMLFile() throws IOException, SAXException, ParserConfigurationException { + XMLUnit.setIgnoreWhitespace(true); + FileGenerator generator = (FileGenerator) getBean("fileGenerator"); + generator.setInputSource("testdata/test1.xml"); + DOMBuilder builder = new DOMBuilder(); + generator.setConsumer(new WhitespaceFilter(builder)); + generator.generate(); + this.assertXMLEqual("Output from generator does not match input file.", + XMLUnit.buildControlDocument(new InputSource("testdata/test1.xml")), + builder.getDocument()); + } +} Added: cocoon/branches/src/test/org/apache/butterfly/serialization/XMLSerializerTestCase.java ============================================================================== --- (empty file) +++ cocoon/branches/src/test/org/apache/butterfly/serialization/XMLSerializerTestCase.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,58 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.serialization; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.StringReader; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.butterfly.test.SitemapComponentTestCase; +import org.apache.butterfly.xml.dom.DOMStreamer; +import org.custommonkey.xmlunit.XMLUnit; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + + +/** + * Description of XMLSerializerTestCase. + * + * @version CVS $Id: XMLSerializerTestCase.java,v 1.2 2004/07/24 20:31:57 ugo Exp $ + */ +public class XMLSerializerTestCase extends SitemapComponentTestCase { + + /** + * @param arg0 + */ + public XMLSerializerTestCase(String name) { + super(name); + } + + public void testSerialization() throws IOException, SAXException, ParserConfigurationException { + XMLSerializer serializer = (XMLSerializer) getBean("xmlSerializer"); + DOMStreamer streamer = new DOMStreamer(serializer); + Document input = XMLUnit.buildControlDocument(new InputSource("testdata/traxtest-input.xml")); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + serializer.setOutputStream(output); + streamer.stream(input); + Document test = XMLUnit.buildTestDocument(new InputSource(new StringReader(output.toString()))); + this.assertXMLEqual("Output from serializer does not match input file.", + input, test); + } +} Added: cocoon/branches/src/test/org/apache/butterfly/source/SourceResolverTestCase.java ============================================================================== --- (empty file) +++ cocoon/branches/src/test/org/apache/butterfly/source/SourceResolverTestCase.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,49 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.source; + +import java.io.IOException; +import java.net.MalformedURLException; + +import org.apache.butterfly.source.impl.FileSource; +import org.apache.butterfly.test.SitemapComponentTestCase; + + +/** + * Description of SourceResolverTestCase. + * + * @version CVS $Id: SourceResolverTestCase.java,v 1.2 2004/07/24 20:31:57 ugo Exp $ + */ +public class SourceResolverTestCase extends SitemapComponentTestCase { + + public SourceResolverTestCase(String name) { + super(name); + } + + public void testFileSourceExists() throws MalformedURLException, IOException { + SourceResolver resolver = (SourceResolver) getBean("sourceResolver"); + Source src = resolver.resolveURI("testdata/test1.xml"); + assertTrue("Source is not a FileSource", src instanceof FileSource); + assertTrue("FileSource does not exist", src.exists()); + } + + public void testFileSourceLength() throws MalformedURLException, IOException { + SourceResolver resolver = (SourceResolver) getBean("sourceResolver"); + Source src = resolver.resolveURI("testdata/test1.xml"); + assertEquals("FileSource is not of the expected length", 138, src.getContentLength()); + } +} Added: cocoon/branches/src/test/org/apache/butterfly/test/SitemapComponentTestCase.java ============================================================================== --- (empty file) +++ cocoon/branches/src/test/org/apache/butterfly/test/SitemapComponentTestCase.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,52 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.test; + +import org.custommonkey.xmlunit.XMLTestCase; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.core.io.ClassPathResource; + + +/** + * A superclass for testcases of sitemap components. + * + * @version CVS $Id: SitemapComponentTestCase.java,v 1.3 2004/07/27 20:54:17 ugo Exp $ + */ +public class SitemapComponentTestCase extends XMLTestCase { + + protected BeanFactory beanFactory; + + /** + * @param name + */ + public SitemapComponentTestCase(String name) { + super(name); + } + + /* (non-Javadoc) + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + ClassPathResource res = new ClassPathResource("beans.xml"); + beanFactory = new XmlBeanFactory(res); + } + + protected Object getBean(String name) { + return beanFactory.getBean(name); + } +} Added: cocoon/branches/src/test/org/apache/butterfly/transformation/TraxTransformerTestCase.java ============================================================================== --- (empty file) +++ cocoon/branches/src/test/org/apache/butterfly/transformation/TraxTransformerTestCase.java Wed Jul 28 13:25:41 2004 @@ -0,0 +1,61 @@ +/* + * Copyright 2004, Ugo Cei. + * 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. + */ +package org.apache.butterfly.transformation; + +import java.io.IOException; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.butterfly.test.SitemapComponentTestCase; +import org.apache.butterfly.xml.WhitespaceFilter; +import org.apache.butterfly.xml.dom.DOMBuilder; +import org.apache.butterfly.xml.dom.DOMStreamer; +import org.apache.butterfly.xml.xslt.TraxTransformerFactory; +import org.custommonkey.xmlunit.XMLUnit; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + + +/** + * Description of TraxTransformerTestCase. + * + * @version CVS $Id: TraxTransformerTestCase.java,v 1.3 2004/07/26 22:44:18 ugo Exp $ + */ +public class TraxTransformerTestCase extends SitemapComponentTestCase { + /** + * @param name + */ + public TraxTransformerTestCase(String name) { + super(name); + } + + public void testTransformation() throws IOException, SAXException, ParserConfigurationException { + XMLUnit.setIgnoreWhitespace(true); + TraxTransformerFactory factory = + (TraxTransformerFactory) getBean("traxTransformerFactory"); + TraxTransformer transformer = factory.getTransformer("testdata/traxtest-style.xsl"); + DOMBuilder builder = new DOMBuilder(); + transformer.setConsumer(new WhitespaceFilter(builder)); + DOMStreamer streamer = new DOMStreamer(transformer); + Document control = XMLUnit.buildControlDocument(new InputSource("testdata/traxtest-result.xml")); + Document input = XMLUnit.buildTestDocument(new InputSource("testdata/traxtest-input.xml")); + streamer.stream(input); + this.assertXMLEqual("Output from transformer does not match control file.", + control, builder.getDocument()); + } +} Added: cocoon/branches/testdata/test1.xml ============================================================================== --- (empty file) +++ cocoon/branches/testdata/test1.xml Wed Jul 28 13:25:41 2004 @@ -0,0 +1,7 @@ + + + + Text + Mixed content + + \ No newline at end of file Added: cocoon/branches/testdata/traxtest-input.xml ============================================================================== --- (empty file) +++ cocoon/branches/testdata/traxtest-input.xml Wed Jul 28 13:25:41 2004 @@ -0,0 +1,22 @@ + + + + Title of the example + This is a litte test file! + And will transformed into a HTML page. + + Added: cocoon/branches/testdata/traxtest-result.xml ============================================================================== --- (empty file) +++ cocoon/branches/testdata/traxtest-result.xml Wed Jul 28 13:25:41 2004 @@ -0,0 +1,26 @@ + + + + + + +

This is a litte test file!

+

And will transformed into a HTML page.

+ + + + Added: cocoon/branches/testdata/traxtest-style.xsl ============================================================================== --- (empty file) +++ cocoon/branches/testdata/traxtest-style.xsl Wed Jul 28 13:25:41 2004 @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + +

+ +

+
+ +
Added: cocoon/branches/tools/lib/jmock-1.0.1.jar ============================================================================== Binary file. No diff available. Added: cocoon/branches/tools/lib/xmlunit1.0.jar ============================================================================== Binary file. No diff available.