From d8261a197b2d8cd10c3f171f2a3ca7e9f04f1302 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Tue, 1 Feb 2011 20:20:02 +0000 Subject: [PATCH] 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 --- src/java/org/apache/fop/fo/Constants.java | 4 +- .../org/apache/fop/fo/FOPropertyMapping.java | 9 +- src/java/org/apache/fop/fo/PropertyList.java | 3 +- .../apache/fop/fo/properties/URIProperty.java | 148 ++++++++++++++++++ status.xml | 4 + test/fotree/testcases/xml_base.fo | 82 ++++++++++ 6 files changed, 247 insertions(+), 3 deletions(-) create mode 100644 src/java/org/apache/fop/fo/properties/URIProperty.java create mode 100644 test/fotree/testcases/xml_base.fo 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 xml:base + * during the property refinement stage. + * If no xml:base 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 xml:base + * @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. --> + + Added support for resolution of relative URIs against a specified xml:base during + property refinement. + Allow afp:no-operation to also appear under fo:page-sequence and fo:declarations. 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.39.5