You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by an...@apache.org on 2006/05/30 07:35:07 UTC
svn commit: r410192 - in /cocoon/trunk/core/cocoon-core/src:
main/java/org/apache/cocoon/transformation/
test/java/org/apache/cocoon/transformation/
test/resources/org/apache/cocoon/transformation/
Author: antonio
Date: Mon May 29 22:35:07 2006
New Revision: 410192
URL: http://svn.apache.org/viewvc?rev=410192&view=rev
Log:
Fix COCOON-1489 XIncludeTransformer: XInclude transformer does not handle fallback correctly. Thanks to Jason Johnston (cocoon@lojjic.net).
Added:
cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-input-multipleNestedFallbackTest.xml (with props)
Removed:
cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-result-nestedXincludeFallbackTest.xml
Modified:
cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/transformation/XIncludeTransformer.java
cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/transformation/XIncludeTransformerTestCase.java
cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-incl.xml
cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-result-1.xml
Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/transformation/XIncludeTransformer.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/transformation/XIncludeTransformer.java?rev=410192&r1=410191&r2=410192&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/transformation/XIncludeTransformer.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/transformation/XIncludeTransformer.java Mon May 29 22:35:07 2006
@@ -142,23 +142,32 @@
private class XIncludePipe extends AbstractXMLPipe {
/** Helper class to keep track of xml:base attributes */
private XMLBaseSupport xmlBaseSupport;
- /** Element nesting level when inside an xi:include element. */
- private int xIncludeLevel = 0;
- /** Should the content of the fallback element be inserted when it is encountered? */
- private boolean useFallback = false;
- /** Element nesting level when inside the fallback element. */
- private int fallbackLevel;
- /** In case {@link #useFallback} = true, then this should contain the exception that caused fallback to be needed. */
+ /** The nesting level of xi:include elements that have been encountered. */
+ private int xIncludeElementLevel = 0;
+
+ /** The nesting level of fallback that should be used */
+ private int useFallbackLevel = 0;
+
+ /** The nesting level of xi:fallback elements that have been encountered. */
+ private int fallbackElementLevel;
+
+ /**
+ * In case {@link #useFallbackLevel} > 0, then this should contain the
+ * exception that caused fallback to be needed. In the case of nested
+ * include elements it will contain only the deepest exception.
+ */
private Exception fallBackException;
+
/**
* Locator of the current stream, stored here so that it can be restored after
* another document send its content to the consumer.
*/
private Locator locator;
+
/**
* Value of the href attribute of the xi:include element that caused the creation of the this
* XIncludePipe. Used to detect loop inclusions.
- * */
+ */
private String href;
/**
@@ -191,6 +200,18 @@
return xpointer;
}
+ /**
+ * Determine whether the pipe is currently in a state where contents
+ * should be evaluated, i.e. xi:include elements should be resolved
+ * and elements in other namespaces should be copied through. Will
+ * return false for fallback contents within a successful xi:include,
+ * and true for contents outside any xi:include or within an xi:fallback
+ * for an unsuccessful xi:include.
+ */
+ private boolean isEvaluatingContent() {
+ return xIncludeElementLevel == 0 || (fallbackElementLevel > 0 && fallbackElementLevel == useFallbackLevel);
+ }
+
public void endDocument() throws SAXException {
// We won't be getting any more sources so mark the MultiSourceValidity as finished.
validity.close();
@@ -198,152 +219,128 @@
}
public void startElement(String uri, String name, String raw, Attributes attr) throws SAXException {
- if (xIncludeLevel == 1 && useFallback && XINCLUDE_NAMESPACE_URI.equals(uri) && XINCLUDE_FALLBACK_ELEMENT.equals(name)) {
- fallbackLevel++;
-
- // don't need these anymore
- useFallback = false;
- fallBackException = null;
-
- return;
- } else if (xIncludeLevel > 0 && fallbackLevel < 1) {
- xIncludeLevel++;
- return;
- } else if (xIncludeLevel > 0 && fallbackLevel > 0) {
- fallbackLevel++;
- }
-
+ // Track xml:base context:
xmlBaseSupport.startElement(uri, name, raw, attr);
+ // Handle elements in xinclude namespace:
if (XINCLUDE_NAMESPACE_URI.equals(uri)) {
+ // Handle xi:include:
if (XINCLUDE_INCLUDE_ELEMENT.equals(name)) {
- String href = attr.getValue("",XINCLUDE_INCLUDE_ELEMENT_HREF_ATTRIBUTE);
-
- String parse = attr.getValue("",XINCLUDE_INCLUDE_ELEMENT_PARSE_ATTRIBUTE);
- String xpointer = attr.getValue("",XINCLUDE_INCLUDE_ELEMENT_XPOINTER_ATTRIBUTE);
-
- xIncludeLevel++;
-
- try {
- processXIncludeElement(href, parse, xpointer);
- } catch (ProcessingException e) {
- getLogger().debug("Rethrowing exception", e);
- throw new SAXException(e);
- } catch (IOException e) {
- getLogger().debug("Rethrowing exception", e);
- throw new SAXException(e);
+ // Process the include, unless in an ignored fallback:
+ if (isEvaluatingContent()) {
+ String href = attr.getValue("", XINCLUDE_INCLUDE_ELEMENT_HREF_ATTRIBUTE);
+ String parse = attr.getValue("", XINCLUDE_INCLUDE_ELEMENT_PARSE_ATTRIBUTE);
+ String xpointer = attr.getValue("", XINCLUDE_INCLUDE_ELEMENT_XPOINTER_ATTRIBUTE);
+
+ try {
+ processXIncludeElement(href, parse, xpointer);
+ } catch (ProcessingException e) {
+ getLogger().debug("Rethrowing exception", e);
+ throw new SAXException(e);
+ } catch (IOException e) {
+ getLogger().debug("Rethrowing exception", e);
+ throw new SAXException(e);
+ }
}
- return;
+ xIncludeElementLevel++;
+ } else if (XINCLUDE_FALLBACK_ELEMENT.equals(name)) {
+ // Handle xi:fallback
+ fallbackElementLevel++;
+ } else {
+ // Unknown element:
+ throw new SAXException("Unknown XInclude element " + raw + " at " + getLocation());
}
-
- throw new SAXException("Unknown XInclude element " + raw + " at " + getLocation());
-
- } else {
- super.startElement(uri,name,raw,attr);
+ } else if (isEvaluatingContent()) {
+ // Copy other elements through when appropriate:
+ super.startElement(uri, name, raw, attr);
}
}
public void endElement(String uri, String name, String raw) throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1) {
- xIncludeLevel--;
- if (xIncludeLevel == 0)
- xmlBaseSupport.endElement(uri, name, raw);
- if (xIncludeLevel == 0 && useFallback) {
- // an error was encountered but a fallback element was not found: throw the error now
- useFallback = false;
- Exception localFallBackException = fallBackException;
- fallBackException = null;
- fallbackLevel = 0;
- getLogger().error("Exception occured during xinclude processing, and did not find a fallback element.", localFallBackException);
- throw new SAXException("Exception occured during xinclude processing, and did not find a fallback element.", localFallBackException);
- }
- return;
- }
+ // Track xml:base context:
+ xmlBaseSupport.endElement(uri, name, raw);
- if (fallbackLevel > 0) {
- fallbackLevel--;
- if (fallbackLevel == 0)
- return;
+ // Handle elements in xinclude namespace:
+ if (XINCLUDE_NAMESPACE_URI.equals(uri)) {
+ // Handle xi:include:
+ if (XINCLUDE_INCLUDE_ELEMENT.equals(name)) {
+ xIncludeElementLevel--;
+ if (useFallbackLevel > xIncludeElementLevel) {
+ useFallbackLevel = xIncludeElementLevel;
+ }
+ } else if (XINCLUDE_FALLBACK_ELEMENT.equals(name)) {
+ // Handle xi:fallback:
+ fallbackElementLevel--;
+ }
+ } else if (isEvaluatingContent()) {
+ // Copy other elements through when appropriate:
+ super.endElement(uri, name, raw);
}
-
- xmlBaseSupport.endElement(uri, name, raw);
- super.endElement(uri,name,raw);
}
- public void startPrefixMapping(String prefix, String uri)
- throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1)
- return;
- super.startPrefixMapping(prefix, uri);
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ if (isEvaluatingContent()) {
+ super.startPrefixMapping(prefix, uri);
+ }
}
- public void endPrefixMapping(String prefix)
- throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1)
- return;
- super.endPrefixMapping(prefix);
+ public void endPrefixMapping(String prefix) throws SAXException {
+ if (isEvaluatingContent()) {
+ super.endPrefixMapping(prefix);
+ }
}
- public void characters(char c[], int start, int len)
- throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1)
- return;
- super.characters(c, start, len);
+ public void characters(char c[], int start, int len) throws SAXException {
+ if (isEvaluatingContent()) {
+ super.characters(c, start, len);
+ }
}
- public void ignorableWhitespace(char c[], int start, int len)
- throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1)
- return;
- super.ignorableWhitespace(c, start, len);
+ public void ignorableWhitespace(char c[], int start, int len) throws SAXException {
+ if (isEvaluatingContent()) {
+ super.ignorableWhitespace(c, start, len);
+ }
}
- public void processingInstruction(String target, String data)
- throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1)
- return;
- super.processingInstruction(target, data);
+ public void processingInstruction(String target, String data) throws SAXException {
+ if (isEvaluatingContent()) {
+ super.processingInstruction(target, data);
+ }
}
- public void skippedEntity(String name)
- throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1)
- return;
- super.skippedEntity(name);
+ public void skippedEntity(String name) throws SAXException {
+ if (isEvaluatingContent()) {
+ super.skippedEntity(name);
+ }
}
- public void startEntity(String name)
- throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1)
- return;
- super.startEntity(name);
+ public void startEntity(String name) throws SAXException {
+ if (isEvaluatingContent()) {
+ super.startEntity(name);
+ }
}
- public void endEntity(String name)
- throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1)
- return;
- super.endEntity(name);
+ public void endEntity(String name) throws SAXException {
+ if (isEvaluatingContent()) {
+ super.endEntity(name);
+ }
}
- public void startCDATA()
- throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1)
- return;
- super.startCDATA();
+ public void startCDATA() throws SAXException {
+ if (isEvaluatingContent()) {
+ super.startCDATA();
+ }
}
- public void endCDATA()
- throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1)
- return;
- super.endCDATA();
+ public void endCDATA() throws SAXException {
+ if (isEvaluatingContent()) {
+ super.endCDATA();
+ }
}
- public void comment(char ch[], int start, int len)
- throws SAXException {
- if (xIncludeLevel > 0 && fallbackLevel < 1)
- return;
- super.comment(ch, start, len);
+ public void comment(char ch[], int start, int len) throws SAXException {
+ if (isEvaluatingContent()) {
+ super.comment(ch, start, len);
+ }
}
public void setDocumentLocator(Locator locator) {
@@ -373,7 +370,7 @@
}
protected void processXIncludeElement(String href, String parse, String xpointer)
- throws SAXException, ProcessingException, IOException {
+ throws SAXException,ProcessingException,IOException {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Processing XInclude element: href="+href+", parse="+parse+", xpointer="+xpointer);
}
@@ -437,7 +434,7 @@
super.characters(ary,0,read);
}
} catch (SourceNotFoundException e) {
- useFallback = true;
+ useFallbackLevel++;
fallBackException = new CascadingException("Resource not found: " + url.getURI());
getLogger().error("xIncluded resource not found: " + url.getURI(), e);
} finally {
@@ -472,12 +469,12 @@
if (locator != null)
xmlConsumer.setDocumentLocator(locator);
} catch (ResourceNotFoundException e) {
- useFallback = true;
+ useFallbackLevel++;
fallBackException = new CascadingException("Resource not found: " + url.getURI());
getLogger().error("xIncluded resource not found: " + url.getURI(), e);
} catch (ParseException e) {
// this exception is thrown in case of an invalid xpointer expression
- useFallback = true;
+ useFallbackLevel++;
fallBackException = new CascadingException("Error parsing xPointer expression", e);
fallBackException.fillInStackTrace();
getLogger().error("Error parsing XPointer expression, will try to use fallback.", e);
@@ -488,11 +485,11 @@
getLogger().error("Error in processXIncludeElement", e);
throw e;
} catch(MalformedURLException e) {
- useFallback = true;
+ useFallbackLevel++;
fallBackException = e;
getLogger().error("Error processing an xInclude, will try to use fallback.", e);
} catch(IOException e) {
- useFallback = true;
+ useFallbackLevel++;
fallBackException = e;
getLogger().error("Error processing an xInclude, will try to use fallback.", e);
}
Modified: cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/transformation/XIncludeTransformerTestCase.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/transformation/XIncludeTransformerTestCase.java?rev=410192&r1=410191&r2=410192&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/transformation/XIncludeTransformerTestCase.java (original)
+++ cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/transformation/XIncludeTransformerTestCase.java Mon May 29 22:35:07 2006
@@ -63,31 +63,40 @@
*
* @throws Exception if ComponentManager enterEnvironment fails
*/
- public void testXIncludeSimpleFallback() throws Exception {
- getLogger().debug("testXIncludeSimpleFallback");
- xincludeTest("resource://org/apache/cocoon/transformation/xinclude-input-fallbackTest.xml",
- "resource://org/apache/cocoon/transformation/xinclude-result-fallbackTest.xml");
- }
+ public void testXIncludeSimpleFallback() throws Exception {
+ getLogger().debug("testXIncludeSimpleFallback");
+ xincludeTest("resource://org/apache/cocoon/transformation/xinclude-input-fallbackTest.xml",
+ "resource://org/apache/cocoon/transformation/xinclude-result-fallbackTest.xml");
+ }
- /** Testcase for xinclude with a nested xinclude elemento into the fallback
- * Check issue: COCOON-1489
- *
- * @throws Exception if ComponentManager enterEnvironment fails
- */
- /*public void testXIncludeNestedXincludeElementInAFallback() throws Exception {
- getLogger().debug("testXIncludeNestedXincludeElementInAFallback");
- xincludeTest("resource://org/apache/cocoon/transformation/xinclude-input-nestedXincludeFallbackTest.xml",
- "resource://org/apache/cocoon/transformation/xinclude-result-fallbackTest.xml");
- }*/
+ /** Testcase for xinclude with a nested xinclude elemento into the fallback
+ * Check issue: COCOON-1489
+ *
+ * @throws Exception if ComponentManager enterEnvironment fails
+ */
+ public void testXIncludeNestedXincludeElementInAFallback() throws Exception {
+ getLogger().debug("testXIncludeNestedXincludeElementInAFallback");
+ xincludeTest("resource://org/apache/cocoon/transformation/xinclude-input-nestedXincludeFallbackTest.xml",
+ "resource://org/apache/cocoon/transformation/xinclude-result-1.xml");
+ }
- /** Testcase for xinclude simple fallback when parse attribute is 'text'
- * Check issue: COCOON-1110
- *
- * @throws Exception if ComponentManager enterEnvironment fails
- */
+ /**
+ * Testcase for xinclude with multiple nested fallbacks
+ */
+ public void testXIncludeMultipleNestedFallback() throws Exception {
+ getLogger().debug("testXIncludeMultipleNestedFallback");
+ xincludeTest("resource://org/apache/cocoon/transformation/xinclude-input-multipleNestedFallbackTest.xml",
+ "resource://org/apache/cocoon/transformation/xinclude-result-fallbackTest.xml");
+ }
+
+ /** Testcase for xinclude simple fallback when parse attribute is 'text'
+ * Check issue: COCOON-1110
+ *
+ * @throws Exception if ComponentManager enterEnvironment fails
+ */
public void testXIncludeSimpleFallbackForTextParse() throws Exception {
getLogger().debug("testXIncludeSimpleFallbackForTextParse");
xincludeTest("resource://org/apache/cocoon/transformation/xinclude-input-simpleFallbackForTextParseTest.xml",
- "resource://org/apache/cocoon/transformation/xinclude-result-fallbackTest.xml");
+ "resource://org/apache/cocoon/transformation/xinclude-result-fallbackTest.xml");
}
}
Modified: cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-incl.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-incl.xml?rev=410192&r1=410191&r2=410192&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-incl.xml (original)
+++ cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-incl.xml Mon May 29 22:35:07 2006
@@ -16,6 +16,7 @@
-->
<root-include>
+ <br/>
<p>include 1</p>
<p>include 2</p>
<p>include 3</p>
Added: cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-input-multipleNestedFallbackTest.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-input-multipleNestedFallbackTest.xml?rev=410192&view=auto
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-input-multipleNestedFallbackTest.xml (added)
+++ cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-input-multipleNestedFallbackTest.xml Mon May 29 22:35:07 2006
@@ -0,0 +1,35 @@
+<?xml version="1.0" ?>
+<!--
+ 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.
+-->
+
+<root
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>P1</p>
+ <p>P2</p>
+
+ <xi:include href="this_file_does_not_exist.xml">
+ <xi:fallback>
+ <xi:include href="neither_does_this.xml">
+ <xi:fallback>
+ <element>This should be here if the file was not found</element>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+
+ <p>P3</p>
+ <p>P4</p>
+</root>
\ No newline at end of file
Propchange: cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-input-multipleNestedFallbackTest.xml
------------------------------------------------------------------------------
svn:eol-style = native
Modified: cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-result-1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-result-1.xml?rev=410192&r1=410191&r2=410192&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-result-1.xml (original)
+++ cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/transformation/xinclude-result-1.xml Mon May 29 22:35:07 2006
@@ -21,6 +21,7 @@
<p>P2</p>
<root-include>
+ <br/>
<p>include 1</p>
<p>include 2</p>
<p>include 3</p>