You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@sis.apache.org by "Martin Desruisseaux (Jira)" <ji...@apache.org> on 2023/12/21 14:58:00 UTC

[jira] [Resolved] (SIS-387) Automatically resolve links in metadata document

     [ https://issues.apache.org/jira/browse/SIS-387?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Martin Desruisseaux resolved SIS-387.
-------------------------------------
    Resolution: Fixed

Done on the `geoapi-4.0` development branch (will be merged to the `main` branch later). The redirection in above issue description has also been ported.

> Automatically resolve links in metadata document
> ------------------------------------------------
>
>                 Key: SIS-387
>                 URL: https://issues.apache.org/jira/browse/SIS-387
>             Project: Spatial Information Systems
>          Issue Type: Task
>          Components: Metadata
>    Affects Versions: 0.7, 0.8, 1.0, 1.1, 1.2, 1.3, 1.4
>            Reporter: Martin Desruisseaux
>            Assignee: Martin Desruisseaux
>            Priority: Minor
>             Fix For: 1.5
>
>
> 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.
> {code:java}
> package org.apache.sis.xml;
> import java.io.IOException;
> import java.net.HttpURLConnection;
> import java.net.MalformedURLException;
> import java.net.URL;
> 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 null
>  * 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 {
>         super();
>         this.metadataVersion = metadataVersion;
>     }
>     @Override
>     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));
>                     pool.recycle(unmarshaller);
>                 } // Otherwise, unmarshal the original URL.
>                 else if (href != null) {
>                     content = type.cast(unmarshaller.unmarshal(href));
>                     pool.recycle(unmarshaller);
>                 }
>             }
>             // If any sort of exception occurred, just return whatever the parent class found.
>         } catch (MalformedURLException e) {
>             return content;
>         } catch (JAXBException e) {
>             return content;
>         } catch (IOException e) {
>             return content;
>         }
>         return content;
>     }
>     /**
>      * Get an unmarshaller with its own AllReferenceResolver that operates on the given metadata version.
>      *
>      * @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;
>     }
> }
> {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)