/* | |
* 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. | |
*/ | |
package org.apache.axis2.jaxws.util; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import org.apache.axis2.jaxws.catalog.JAXWSCatalogManager; | |
import org.apache.axis2.jaxws.description.impl.URIResolverImpl; | |
import org.apache.commons.logging.Log; | |
import org.apache.commons.logging.LogFactory; | |
import org.apache.xml.resolver.Catalog; | |
import org.xml.sax.InputSource; | |
/** | |
* This resolver provides the means of resolving the imports and includes of a | |
* given schema document. It allows the use of the Apache Commons Resolver API | |
* to redirect resource requests to alternative locations. | |
*/ | |
public class CatalogURIResolver extends URIResolverImpl { | |
private static Log log = LogFactory.getLog(CatalogURIResolver.class); | |
private Catalog catalogResolver; | |
/** | |
* CatalogURIResolver constructor. Resolves WSDL URIs using Apache Commons Resolver API. | |
* @param catalogManager | |
* the OASISCatalogManager which will determine the settings for the XML catalog | |
*/ | |
public CatalogURIResolver(JAXWSCatalogManager catalogManager) { | |
this(catalogManager, null); | |
} | |
/** | |
* CatalogURIResolver constructor. Resolves WSDL URIs using Apache Commons Resolver API. | |
* @param catalogManager | |
* the OASISCatalogManager which will determine the settings for the XML catalog | |
* @param classLoader | |
*/ | |
public CatalogURIResolver(JAXWSCatalogManager catalogManager, ClassLoader classLoader) { | |
super(classLoader); | |
if (log.isDebugEnabled()) { | |
log.debug("init: catalogManager :"+ catalogManager); | |
} | |
if (catalogManager != null) { | |
this.catalogResolver = catalogManager.getCatalog(); | |
} | |
} | |
/** | |
* Resolves URIs using Apache Commons Resolver API. | |
* | |
* @param namespace a URI specifying the namespace of the document | |
* @param schemaLocation a URI specifying the document to import | |
* @param baseURI a URI specifying the location of the parent document doing | |
* the importing | |
* @return the resolved import location, or null if no indirection is performed | |
*/ | |
public String getRedirectedURI(String namespace, | |
String schemaLocation, | |
String baseUri) { | |
String resolvedImportLocation = null; | |
try { | |
resolvedImportLocation = this.catalogResolver.resolveSystem(schemaLocation); | |
if (resolvedImportLocation == null) { | |
resolvedImportLocation = catalogResolver.resolveSystem(namespace); | |
} | |
if (resolvedImportLocation == null) { | |
resolvedImportLocation = catalogResolver.resolveURI(schemaLocation); | |
} | |
if (resolvedImportLocation == null) { | |
resolvedImportLocation = catalogResolver.resolvePublic(namespace, namespace); | |
} | |
} catch (IOException e) { | |
if (log.isDebugEnabled()) { | |
log.debug("getRedirectedURI error: Catalog resolution failed"); | |
} | |
throw new RuntimeException("Catalog resolution failed", e); | |
} | |
if (log.isDebugEnabled()) { | |
log.debug("getRedirectedURI exit: redirected location: "+ resolvedImportLocation); | |
} | |
return resolvedImportLocation; | |
} | |
/** | |
* As for the resolver the public ID is the target namespace of the | |
* schema and the schemaLocation is the value of the schema location | |
* @param namespace | |
* @param schemaLocation | |
* @param baseUri | |
*/ | |
public InputSource resolveEntity(String namespace, | |
String schemaLocation, | |
String baseUri) { | |
if (log.isDebugEnabled()) { | |
log.debug("resolveEntity: ["+ namespace + "]["+ schemaLocation + "][ " + baseUri+ "]"); | |
} | |
InputSource returnInputSource = null; | |
if (this.catalogResolver != null) { | |
if(log.isDebugEnabled()) { | |
log.debug("catalogResolver found, calling CatalogURIResolver.getRedirectedURI."); | |
} | |
String redirectedURI = getRedirectedURI(namespace, schemaLocation, baseUri); | |
// first make redirectedURI is valid for retrieving an input stream | |
if (redirectedURI != null) { | |
returnInputSource = getInputSourceFromRedirectedURI(redirectedURI); | |
} | |
} | |
// If we were able to get an InputSource from the redirectedURI, just return that | |
// else call up to parent to resolve with original location | |
if (returnInputSource != null) { | |
return returnInputSource; | |
} else { | |
return super.resolveEntity(namespace, schemaLocation, baseUri); | |
} | |
} | |
/** | |
* Given a redirecteURI from a static XML catalog, attempt to get the InputSource. | |
* @param redirectedURI URI string from static XML catalog | |
* @return InputSource or null if we were not able to load the resource | |
*/ | |
private InputSource getInputSourceFromRedirectedURI(String redirectedURI) { | |
InputStream is = null; | |
String validatedURI = null; | |
InputSource returnInputSource = null; | |
// If we have an absolute path, try to get the InputStream directly | |
if (isAbsolute(redirectedURI)) { | |
is = getInputStreamForURI(redirectedURI); | |
if (is != null) { | |
validatedURI = redirectedURI; | |
} | |
} | |
// If we couldn't get the inputstream try using the classloader | |
if (is == null && classLoader != null) { | |
try { | |
is = classLoader | |
.getResourceAsStream(redirectedURI); | |
if (is != null) { | |
validatedURI = redirectedURI; | |
} | |
} catch (Throwable t) { | |
if(log.isDebugEnabled()) { | |
log.debug("Exception occured in validateRedirectedURI, ignoring exception continuing processing: "+t.getMessage()); | |
} | |
} | |
// If we failed to get an InputStream using the entire redirectedURI, | |
// try striping off the protocol. This may be necessary for some cases | |
// if a non-standard protocol is used. | |
if (is == null) { | |
redirectedURI = stripProtocol(redirectedURI); | |
if (log.isDebugEnabled()) { | |
log.debug("getInputSourceFromRedirectedURI: new redirected location: "+ redirectedURI); | |
} | |
try { | |
is = classLoader | |
.getResourceAsStream(redirectedURI); | |
if (is != null) { | |
validatedURI = redirectedURI; | |
} | |
} catch (Throwable t) { | |
if(log.isDebugEnabled()) { | |
log.debug("Exception occured in validateRedirectedURI, ignoring exception continuing processing: "+t.getMessage()); | |
} | |
} | |
} | |
} | |
if (is != null) { | |
if(log.isDebugEnabled()) { | |
log.debug("getInputSourceFromRedirectedURI: XSD input stream is not null after resolving import for: " + | |
redirectedURI); | |
} | |
returnInputSource = new InputSource(is); | |
// We need to set the systemId. XmlSchema will use this value to | |
// maintain a collection of | |
// imported XSDs that have been read. If this value is null, then | |
// circular XSDs will | |
// cause infinite recursive reads. | |
returnInputSource.setSystemId(validatedURI != null ? validatedURI : redirectedURI); | |
if (log.isDebugEnabled()) { | |
log.debug("returnInputSource :" + returnInputSource.getSystemId()); | |
} | |
} | |
return returnInputSource; | |
} | |
private String stripProtocol(String uriStr) { | |
String retURI = uriStr.replace('\\', '/'); | |
int index = retURI.indexOf("://"); | |
if (index != -1) { | |
retURI = retURI.substring(index + 3); | |
} | |
return retURI; | |
} | |
} |