aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas L. Delmelle <adelmelle@apache.org>2011-02-01 20:20:02 +0000
committerAndreas L. Delmelle <adelmelle@apache.org>2011-02-01 20:20:02 +0000
commitd8261a197b2d8cd10c3f171f2a3ca7e9f04f1302 (patch)
tree50697e53d839c603592ccdaee6fcbec25e43a35e
parent3c839549f3deefeba13214cf950aee3b5b832523 (diff)
downloadxmlgraphics-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.java4
-rw-r--r--src/java/org/apache/fop/fo/FOPropertyMapping.java9
-rw-r--r--src/java/org/apache/fop/fo/PropertyList.java3
-rw-r--r--src/java/org/apache/fop/fo/properties/URIProperty.java148
-rw-r--r--status.xml4
-rw-r--r--test/fotree/testcases/xml_base.fo82
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 &lt;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>
+