package org.deegree.commons.xml.schema;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import nl.ipo.cds.utils.UrlUtils;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.apache.xerces.xni.parser.XMLInputSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Overrides the standard deegree-provided class to work around SNI-related problems when fetching GML application schemas:
*
* http://stackoverflow.com/questions/7615645/ssl-handshake-alert-unrecognized-
* name-error-since-upgrade-to-java-1-7-0
*/
public class RedirectingEntityResolver implements XMLEntityResolver {
private static final Logger LOG = LoggerFactory
.getLogger(RedirectingEntityResolver.class);
private static final String SCHEMAS_OPENGIS_NET_URL = "http://schemas.opengis.net/";
private static final String ROOT = "/META-INF/SCHEMAS_OPENGIS_NET/";
private static final URL baseURL;
static {
baseURL = RedirectingEntityResolver.class.getResource(ROOT);
if (baseURL == null) {
LOG.warn("'"
+ ROOT
+ "' could not be found on the classpath. Schema references to 'http://schemas.opengis.net' will not be redirected, but fetched from their original location. ");
}
}
/**
* Redirects the given entity URL, returning a local URL if available.
*
* @param systemId
* entity URL, must not be <code>null</code>
* @return redirected URL, identical to input if it cannot be redirected,
* never <code>null</code>
*/
public String redirect(String systemId) {
if (systemId.startsWith(SCHEMAS_OPENGIS_NET_URL)) {
String localPart = systemId.substring(SCHEMAS_OPENGIS_NET_URL
.length());
URL u = RedirectingEntityResolver.class.getResource(ROOT
+ localPart);
if (u != null) {
LOG.debug("Local hit: " + systemId);
return u.toString();
}
} else if (systemId.equals("http://www.w3.org/2001/xml.xsd")) {
// workaround for schemas that include the xml base schema...
return RedirectingEntityResolver.class.getResource("/w3c/xml.xsd")
.toString();
} else if (systemId.equals("http://www.w3.org/1999/xlink.xsd")) {
// workaround for schemas that include the xlink schema...
return RedirectingEntityResolver.class
.getResource("/w3c/xlink.xsd").toString();
}
return systemId;
}
@Override
public XMLInputSource resolveEntity(XMLResourceIdentifier identifier)
throws XNIException, IOException {
String systemId = identifier.getExpandedSystemId();
String redirectedSystemId = systemId != null ? redirect(systemId)
: null;
LOG.debug("'" + systemId + "' -> '" + redirectedSystemId + "'");
if (redirectedSystemId != null
&& redirectedSystemId.startsWith("https:")) {
InputStream is = UrlUtils.open(new URL(redirectedSystemId));
return new XMLInputSource(null, systemId, redirectedSystemId, is,
null);
}
return new XMLInputSource(null, redirectedSystemId, null);
}
}