| /* |
| * 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 java.net.URI; |
| import java.net.URISyntaxException; |
| |
| 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 org.apache.fop.util.CompareUtil; |
| |
| 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; |
| } |
| } |
| |
| @Override |
| public int hashCode() { |
| final int prime = 31; |
| int result = 1; |
| result = prime * result + CompareUtil.getHashCode(getSpecifiedValue()); |
| result = prime * result + CompareUtil.getHashCode(resolvedURI); |
| return result; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (obj == null) { |
| return false; |
| } |
| if (!(obj instanceof URIProperty)) { |
| return false; |
| } |
| URIProperty other = (URIProperty) obj; |
| return CompareUtil.equal(getSpecifiedValue(), other.getSpecifiedValue()) |
| && CompareUtil.equal(resolvedURI, other.resolvedURI); |
| } |
| |
| } |