diff options
author | Andreas L. Delmelle <adelmelle@apache.org> | 2011-02-01 20:20:02 +0000 |
---|---|---|
committer | Andreas L. Delmelle <adelmelle@apache.org> | 2011-02-01 20:20:02 +0000 |
commit | d8261a197b2d8cd10c3f171f2a3ca7e9f04f1302 (patch) | |
tree | 50697e53d839c603592ccdaee6fcbec25e43a35e | |
parent | 3c839549f3deefeba13214cf950aee3b5b832523 (diff) | |
download | xmlgraphics-fop-d8261a197b2d8cd10c3f171f2a3ca7e9f04f1302.tar.gz xmlgraphics-fop-d8261a197b2d8cd10c3f171f2a3ca7e9f04f1302.zip |
Bugzilla 48334: Added implementation for xml:base
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1066190 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | src/java/org/apache/fop/fo/Constants.java | 4 | ||||
-rw-r--r-- | src/java/org/apache/fop/fo/FOPropertyMapping.java | 9 | ||||
-rw-r--r-- | src/java/org/apache/fop/fo/PropertyList.java | 3 | ||||
-rw-r--r-- | src/java/org/apache/fop/fo/properties/URIProperty.java | 148 | ||||
-rw-r--r-- | status.xml | 4 | ||||
-rw-r--r-- | test/fotree/testcases/xml_base.fo | 82 |
6 files changed, 247 insertions, 3 deletions
diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java index 5f23502f3..726d4d89e 100644 --- a/src/java/org/apache/fop/fo/Constants.java +++ b/src/java/org/apache/fop/fo/Constants.java @@ -778,9 +778,11 @@ public interface Constants { * Used for accessibility. */ int PR_X_ALT_TEXT = 275; + /** Property constant - FOP proprietary prototype (in XSL-FO 2.0 Requirements) */ + int PR_X_XML_BASE = 276; /** Number of property constants defined */ - int PROPERTY_COUNT = 275; + int PROPERTY_COUNT = 276; // compound property constants diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index b1e851ea4..c32aca0f0 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -64,6 +64,7 @@ import org.apache.fop.fo.properties.StringProperty; import org.apache.fop.fo.properties.TableBorderPrecedence; import org.apache.fop.fo.properties.TextDecorationProperty; import org.apache.fop.fo.properties.ToBeImplementedProperty; +import org.apache.fop.fo.properties.URIProperty; import org.apache.fop.fo.properties.VerticalAlignShorthandParser; import org.apache.fop.fo.properties.WhiteSpaceShorthandParser; import org.apache.fop.fo.properties.XMLLangShorthandParser; @@ -2572,7 +2573,7 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("score-spaces", m); // src - m = new StringProperty.Maker(PR_SRC); + m = new URIProperty.Maker(PR_SRC); m.setInherited(false); m.setDefault(""); addPropertyMaker("src", m); @@ -2819,6 +2820,12 @@ public final class FOPropertyMapping implements Constants { m.setDatatypeParser(new XMLLangShorthandParser()); addPropertyMaker("xml:lang", m); + // xml:base + m = new URIProperty.Maker(PR_X_XML_BASE); + m.setInherited(true); + m.setDefault(""); + addPropertyMaker("xml:base", m); + } } diff --git a/src/java/org/apache/fop/fo/PropertyList.java b/src/java/org/apache/fop/fo/PropertyList.java index 8d5a4311f..a1634e868 100644 --- a/src/java/org/apache/fop/fo/PropertyList.java +++ b/src/java/org/apache/fop/fo/PropertyList.java @@ -312,7 +312,8 @@ public abstract class PropertyList { attributeName = attributes.getQName(i); attributeValue = attributes.getValue(i); if (attributeNS == null || attributeNS.length() == 0 - || "xml:lang".equals(attributeName)) { + || "xml:lang".equals(attributeName) + || "xml:base".equals(attributeName)) { convertAttributeToProperty(attributes, attributeName, attributeValue); } else if (!factory.isNamespaceIgnored(attributeNS)) { ElementMapping mapping = factory.getElementMappingRegistry().getElementMapping( diff --git a/src/java/org/apache/fop/fo/properties/URIProperty.java b/src/java/org/apache/fop/fo/properties/URIProperty.java new file mode 100644 index 000000000..6465fafdb --- /dev/null +++ b/src/java/org/apache/fop/fo/properties/URIProperty.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo.properties; + +import org.apache.fop.datatypes.URISpecification; +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.expr.PropertyException; + +import java.net.URI; +import java.net.URISyntaxException; + +import static org.apache.fop.fo.Constants.PR_X_XML_BASE; + +/** + * Class modeling a property that has a value of type <uri-specification>. + * The purpose is mainly to support resolution of a specified + * relative URI against a specified or inherited <code>xml:base</code> + * during the property refinement stage. + * If no <code>xml:base</code> has been specified, only the original URI, as + * it appears in the source document, is stored as the property's specified + * value. + */ +public class URIProperty extends Property { + + /** will be null if the URI is not resolved against an xml:base */ + private URI resolvedURI; + + /** + * Default constructor, to create a {@link URIProperty} from a + * {@code java.net.URI} directly. + * @param uri a resolved {@code java.net.URI} + */ + protected URIProperty(URI uri) { + this.resolvedURI = uri; + } + + /** + * Alternate constructor, to create a {@link URIProperty} from a + * string representation. + * @param uri a {@code java.lang.String} representing the URI + * @param resolve flag indicating whether this URI was the result of resolution + * @throws IllegalArgumentException if the URI should be resolved, but is not valid. + */ + private URIProperty(String uri, boolean resolve) { + if (resolve && !(uri == null || "".equals(uri))) { + this.resolvedURI = URI.create(uri); + } else { + setSpecifiedValue(uri); + } + } + + /** + * Return a string representing the resolved URI, or the + * specified value if the URI is not resolved against + * an <code>xml:base</code> + * @return a string representing the URI + */ + @Override + public String getString() { + if (resolvedURI == null) { + return getSpecifiedValue(); + } else { + return resolvedURI.toString(); + } + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return this.getString(); + } + + /** + * Inner {@link PropertyMaker} subclass responsible + * for making instances of this type. + */ + public static class Maker extends PropertyMaker { + + /** + * Create a maker for the given property id + * + * @param propId the id of the property for which a Maker should be created + */ + public Maker(int propId) { + super(propId); + } + + /** + * {@inheritDoc} + * Check if {@code xml:base} has been specified and whether the + * given {@code value} represents a relative URI. If so, create + * a property representing the resolved URI. + */ + @Override + public Property make(PropertyList propertyList, String value, + FObj fo) throws PropertyException { + + Property p = null; + //special treament for data: URIs + if (value.matches("(?s)^(url\\(('|\")?)?data:.*$")) { + p = new URIProperty(value, false); + } else { + try { + URI specifiedURI = new URI(URISpecification.escapeURI(value)); + URIProperty xmlBase = (URIProperty)propertyList.get(PR_X_XML_BASE, true, false); + if (xmlBase == null) { + //xml:base undefined + if (this.propId == PR_X_XML_BASE) { + //if current property is xml:base, define a new one + p = new URIProperty(specifiedURI); + p.setSpecifiedValue(value); + } else { + //otherwise, just store the specified value (for backward compatibility) + p = new URIProperty(value, false); + } + } else { + //xml:base defined, so resolve + p = new URIProperty(xmlBase.resolvedURI.resolve(specifiedURI)); + p.setSpecifiedValue(value); + } + } catch (URISyntaxException use) { + // Let PropertyList propagate the exception + throw new PropertyException("Invalid URI specified"); + } + } + return p; + } + } + +} diff --git a/status.xml b/status.xml index 8afa69af4..c0c759763 100644 --- a/status.xml +++ b/status.xml @@ -59,6 +59,10 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> <release version="FOP Trunk" date="TBD"> + <action context="Code" dev="AD" type="add" fixes-bug="48334"> + Added support for resolution of relative URIs against a specified xml:base during + property refinement. + </action> <action context="Renderers" dev="JM" type="add"> Allow afp:no-operation to also appear under fo:page-sequence and fo:declarations. </action> diff --git a/test/fotree/testcases/xml_base.fo b/test/fotree/testcases/xml_base.fo new file mode 100644 index 000000000..fa4858d7c --- /dev/null +++ b/test/fotree/testcases/xml_base.fo @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<!-- $Id$ --> +<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:test="http://xmlgraphics.apache.org/fop/test"> + <fo:layout-master-set> + <fo:simple-page-master master-name="simple" page-width="5in" page-height="5in"> + <fo:region-body /> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="simple" id="simple-cases"> + <fo:flow flow-name="xsl-region-body"> + <fo:block xml:base="http://foo.bar.com/resources/index.html?p=1"> + <fo:external-graphic src="url(images/image-1.png)"> + <!-- should be resolved against xml:base of the parent --> + <test:assert property="src" expected="http://foo.bar.com/resources/images/image-1.png" /> + </fo:external-graphic> + <fo:block xml:base="images/"> + <fo:external-graphic src="image-1.png"> + <!-- should be resolved against resolved xml:base of the parent --> + <test:assert property="src" expected="http://foo.bar.com/resources/images/image-1.png" /> + </fo:external-graphic> + </fo:block> + <fo:block xml:base="/resources/images/"> + <fo:external-graphic src="image-1.png"> + <!-- xml:base is a relative URI starting at the root, should resolve to the same as the above two --> + <test:assert property="src" expected="http://foo.bar.com/resources/images/image-1.png" /> + </fo:external-graphic> + </fo:block> + </fo:block> + <fo:block> + <fo:external-graphic src="images/image-1.png"> + <!-- no xml:base, so should stay a relative URI --> + <test:assert property="src" expected="images/image-1.png" /> + </fo:external-graphic> + </fo:block> + <fo:block xml:base="./resources/"> + <fo:external-graphic src="images/image-1.png"> + <!-- relative xml:base without inherited value, should stay a relative URI --> + <test:assert property="src" expected="resources/images/image-1.png" /> + </fo:external-graphic> + </fo:block> + <fo:block xml:base="http://foo.bar.com/resources with spaces/images/index.html?p=1"> + <fo:external-graphic src="image-1.png"> + <!-- resolved absolute URI with spaces, should yield the normalized string representation --> + <test:assert property="src" expected="http://foo.bar.com/resources%20with%20spaces/images/image-1.png" /> + </fo:external-graphic> + </fo:block> + <fo:block xml:base="./resources with spaces/images/"> + <fo:external-graphic src="image-1.png"> + <!-- resolved relative URI with spaces, should yield the normalized string representation --> + <test:assert property="src" expected="resources%20with%20spaces/images/image-1.png" /> + </fo:external-graphic> + </fo:block> + <fo:block> + <fo:external-graphic src="http://foo.bar.com/resources with spaces/images/image-1.png"> + <!-- unresolved URI with spaces, should yield the specified value (for backward compatibility) --> + <test:assert property="src" expected="http://foo.bar.com/resources with spaces/images/image-1.png" /> + </fo:external-graphic> + <fo:external-graphic src="url('./resources with spaces/images/image-1.png')"> + <!-- unresolved URI with spaces, should yield the specified value (for backward compatibility) --> + <test:assert property="src" expected="url('./resources with spaces/images/image-1.png')" /> + </fo:external-graphic> + </fo:block> + </fo:flow> + </fo:page-sequence> +</fo:root> + |