sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Martin Desruisseaux (JIRA)" <>
Subject [jira] [Created] (SIS-387) Automatically resolve links in metadata document
Date Mon, 22 Jan 2018 15:19:01 GMT
Martin Desruisseaux created SIS-387:

             Summary: Automatically resolve links in metadata document
                 Key: SIS-387
             Project: Spatial Information Systems
          Issue Type: Task
          Components: Metadata
            Reporter: Martin Desruisseaux

The {{ReferenceResolver}} class allows user to specify what Apache SIS should do when its
unmarshal an element defined only by a link to an on-line document. Current implementation
does nothing. As a side effect of SIS-345 work, an implementation resolving all links were
provided by Image Matters. The code has been extracted in this task for allowing to handle
SIS-345 (upgrade to ISO 19115-3) and this task separately.

package org.apache.sis.xml;


import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.sis.util.Version;
import org.apache.sis.xml.MarshalContext;
import org.apache.sis.xml.MarshallerPool;
import org.apache.sis.xml.ReferenceResolver;
import org.apache.sis.xml.XLink;
import org.apache.sis.xml.XML;

 * This class is used to resolve external references in ISO metadata when unmarshalling.
 * It will <em>always</em> attempt to resolve external references, and will return
 * if it fails to do so.
 * @author Cullen Rombach (Image Matters)
public class AllReferenceResolver extends ReferenceResolver {

    private Version metadataVersion;

    private MarshallerPool pool;

     * Constructor.
     * @param metadataVersion the version of metadata to unmarshal (e.g. ISO 19139)
    public AllReferenceResolver(Version metadataVersion) throws JAXBException {
        this.metadataVersion = metadataVersion;

    public <T> T resolve(MarshalContext context, Class<T> type, XLink link) {
        T content = super.resolve(context, type, link);

        try {
            if (content == null) {
                // Cast the URI in the XLink to a URL.
                URL href = link.getHRef().toURL();

                // Used for storing a redirect URL if necessary.
                URL newHref = href;

                // Flag to see if a redirect is necessary.
                Boolean redirect = true;

                while (redirect) {
                    // Only check for redirects on HTTP and HTTPS connections.
                    if (newHref.getProtocol().contains("http")) {
                        // Open a connection to the URL to check for a redirect if it uses
HTTP protocol.
                        HttpURLConnection connection = (HttpURLConnection) newHref.openConnection();

                        // Check HTTP status for a possible redirect.
                        int status = connection.getResponseCode();

                        // If we need to redirect, do so.
                        if (status == HttpURLConnection.HTTP_MOVED_TEMP
                                || status == HttpURLConnection.HTTP_MOVED_PERM
                                || status == HttpURLConnection.HTTP_SEE_OTHER) {

                            // If we need to redirect, get the new URL.
                            newHref = new URL(connection.getHeaderField("Location"));
                        } // Otherwise, flag that no redirect is necessary.
                        else {
                            redirect = false;
                    } // If the link doesn't use HTTP protocol, don't check for a redirect.
                    else {
                        redirect = false;

                // Build an Unmarshaller (and the MarshallerPool it belongs to).
                Unmarshaller unmarshaller = acquireUnmarshaller(metadataVersion);

                // If there was a redirect, unmarshal the new URL.
                if (!newHref.equals(href)) {
                    content = type.cast(unmarshaller.unmarshal(newHref));
                } // Otherwise, unmarshal the original URL.
                else if (href != null) {
                    content = type.cast(unmarshaller.unmarshal(href));

            // If any sort of exception occurred, just return null and don't resolve the reference.
        } catch (MalformedURLException e) {
            return null;
        } catch (JAXBException e) {
            return null;
        } catch (IOException e) {
            return null;

        return content;

     * Get an unmarshaller with its own AllReferenceResolver that operates on the given metadata
     * @return a new Unmarshaller.
    private Unmarshaller acquireUnmarshaller(Version metadataVersion) throws JAXBException
        pool = new MarshallerPool(null);
        Unmarshaller unmarshaller = pool.acquireUnmarshaller();
        // Set metadata version for unmarshalling.
        unmarshaller.setProperty(XML.METADATA_VERSION, metadataVersion);
        // Set resolver for external references.
        unmarshaller.setProperty(XML.RESOLVER, new AllReferenceResolver(metadataVersion));
        return unmarshaller;

This message was sent by Atlassian JIRA

View raw message