[ https://issues.apache.org/jira/browse/SIS-387?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17799444#comment-17799444 ]
Martin Desruisseaux edited comment on SIS-387 at 12/21/23 2:57 PM: ------------------------------------------------------------------- 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. was (Author: desruisseaux): 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)