blob: 095478833d63b4d52a50d0adc29014728de719ea [file] [log] [blame]
/*
* 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.description.impl;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.java.security.AccessController;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.commons.schema.resolver.URIResolver;
import org.xml.sax.InputSource;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
/** This class is used to locate xml schemas that are imported by wsdl documents. */
public class URIResolverImpl implements URIResolver {
private static final String HTTP_PROTOCOL = "http";
private static final String HTTPS_PROTOCOL = "https";
private static final String FILE_PROTOCOL = "file";
private static final String JAR_PROTOCOL = "jar";
private static final String BUNDLE_RESOURCE_PROTOCOL = "bundleresource";
private ClassLoader classLoader;
private static final Log log = LogFactory.getLog(URIResolverImpl.class);
public URIResolverImpl() {
}
public URIResolverImpl(ClassLoader cl) {
classLoader = cl;
}
public InputSource resolveEntity(String namespace, String schemaLocation,
String baseUri) {
if (log.isDebugEnabled()) {
log.debug("resolveEntity: ["+ namespace + "]["+ schemaLocation + "][ " + baseUri+ "]");
}
InputStream is = null;
URI pathURI = null;
String pathURIStr = null;
if(log.isDebugEnabled()) {
log.debug("Import location: " + schemaLocation + " parent document: " +
baseUri);
}
if (baseUri != null) {
try {
// if the location is an absolute path, build a URL directly
// from it
if(log.isDebugEnabled()){
log.debug("Base URI not null");
}
if (isAbsolute(schemaLocation)) {
if(log.isDebugEnabled()) {
log.debug("Retrieving input stream for absolute schema location: "
+ schemaLocation);
}
is = getInputStreamForURI(schemaLocation);
}
else {
if(log.isDebugEnabled()){
log.debug("schemaLocation not in absolute path");
}
try{
pathURI = new URI(baseUri);
}catch(URISyntaxException e){
// Got URISyntaxException, Creation of URI requires
// that we use special escape characters in path.
// The URI constructor below does this for us, so lets use that.
if(log.isDebugEnabled()){
log.debug("Got URISyntaxException. Exception Message = "+e.getMessage());
log.debug("Implementing alternate way to create URI");
}
pathURI = new URI(null, null, baseUri, null);
}
pathURIStr = schemaLocation;
// If this is absolute we need to resolve the path without the
// scheme information
if (pathURI.isAbsolute()) {
if(log.isDebugEnabled()) {
log.debug("Parent document is at absolute location: " +
pathURI.toString());
}
URL url = new URL(baseUri);
if (url != null) {
URI tempURI;
try{
tempURI = new URI(url.getPath());
}catch(URISyntaxException e){
//Got URISyntaxException, Creation of URI requires
// that we use special escape characters in path.
// The URI constructor below does this for us, so lets use that.
if(log.isDebugEnabled()){
log.debug("Got URISyntaxException. Exception Message = "+e.getMessage());
log.debug("Implementing alternate way to create URI");
}
tempURI = new URI(null, null, url.getPath(), null);
}
URI resolvedURI = tempURI.resolve(schemaLocation);
// Add back the scheme to the resolved path
pathURIStr = constructPath(url, resolvedURI);
if(log.isDebugEnabled()) {
log.debug("Resolved this path to imported document: " +
pathURIStr);
}
}
} else {
if(log.isDebugEnabled()) {
log.debug("Parent document is at relative location: " +
pathURI.toString());
}
pathURI = pathURI.resolve(schemaLocation);
pathURIStr = pathURI.toString();
if(log.isDebugEnabled()) {
log.debug("Resolved this path to imported document: " +
pathURIStr);
}
}
// If path is absolute, build URL directly from it
if (isAbsolute(pathURIStr)) {
is = getInputStreamForURI(pathURIStr);
}
// if the location is relative, we need to resolve the
// location using
// the baseURI, then use the loadStrategy to gain an input
// stream
// because the URI will still be relative to the module
if(is == null) {
is = classLoader
.getResourceAsStream(pathURI.toString());
}
}
} catch (Exception e) {
if(log.isDebugEnabled()) {
log.debug("Exception occured in resolveEntity, ignoring exception continuing processing "+e.getMessage());
log.debug(e);
}
}
}
if(is == null) {
if(log.isDebugEnabled()) {
log.debug("XSD input stream is null after resolving import for: " +
schemaLocation + " from parent document: " + baseUri);
}
}
else {
if(log.isDebugEnabled()) {
log.debug("XSD input stream is not null after resolving import for: " +
schemaLocation + " from parent document: " + baseUri);
}
}
InputSource 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(pathURIStr != null ? pathURIStr : schemaLocation);
if (log.isDebugEnabled()) {
log.debug("returnInputSource :" + returnInputSource.getSystemId());
}
return returnInputSource;
}
/**
* Checks to see if the location given is an absolute (actual) or relative path.
*
* @param location
* @return
*/
private boolean isAbsolute(String location) {
boolean absolute = false;
if (location.indexOf(":/") != -1) {
absolute = true;
} else if (location.indexOf(":\\") != -1) {
absolute = true;
} else if (location.indexOf("file:") != -1) {
absolute = true;
}
return absolute;
}
/**
* Gets input stream from the uri given. If we cannot find the stream, <code>null</code> is
* returned.
*
* @param uri
* @return
*/
private InputStream getInputStreamForURI(String uri) {
URL streamURL = null;
InputStream is = null;
URI pathURI = null;
try {
streamURL = new URL(uri);
is = openStream_doPriv(streamURL);
} catch (Throwable t) {
//Exception handling not needed
}
if (is == null) {
try {
pathURI = new URI(uri);
streamURL = pathURI.toURL();
is = openStream_doPriv(streamURL);
} catch (Throwable t) {
//Exception handling not needed
}
}
if (is == null) {
try {
final File file = new File(uri);
streamURL = (URL) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws MalformedURLException {
return file.toURL();
}
}
);
is = openStream_doPriv(streamURL);
} catch (Throwable t) {
//Exception handling not needed
}
}
return is;
}
private InputStream openStream_doPriv(final URL streamURL) throws IOException {
try {
return (InputStream) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws IOException {
return streamURL.openStream();
}
}
);
} catch (PrivilegedActionException e) {
throw (IOException) e.getException();
}
}
private String constructPath(URL baseURL, URI resolvedURI) {
String importLocation = null;
URL url = null;
try {
// Allow for http or https
if (baseURL.getProtocol() != null &&
(baseURL.getProtocol().equals(HTTP_PROTOCOL) ||
baseURL.getProtocol().equals(HTTPS_PROTOCOL) ||
baseURL.getProtocol().equals(BUNDLE_RESOURCE_PROTOCOL))) {
if(log.isDebugEnabled()){
log.debug("Constructing path with http/https protocol");
}
url = new URL(baseURL.getProtocol(), baseURL.getHost(), baseURL.getPort(),
resolvedURI.toString());
if (log.isDebugEnabled()) {
log.debug("URL = " + url);
}
}
// Check for file
else if (baseURL.getProtocol() != null && baseURL.getProtocol().equals(FILE_PROTOCOL)) {
if(log.isDebugEnabled()){
log.debug("Constructing path with file protocol");
}
url = new URL(baseURL.getProtocol(), baseURL.getHost(), resolvedURI.toString());
}
//Check for jar
else if (baseURL.getProtocol() != null && baseURL.getProtocol().equals(JAR_PROTOCOL)) {
if(log.isDebugEnabled()){
log.debug("Constructing path with jar protocol");
}
url = new URL(baseURL.getProtocol(), baseURL.getHost(), resolvedURI.toString());
}
else{
if(baseURL != null) {
// try constructing it with unknown protocol
if(log.isDebugEnabled()){
log.debug("Constructing path with unknown protocol: " + baseURL.getProtocol());
}
url = new URL(baseURL.getProtocol(), baseURL.getHost(), resolvedURI.toString());
}
else {
if(log.isDebugEnabled()) {
log.debug("baseURL is NULL");
}
}
}
}
catch (MalformedURLException e) {
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("schemaImportError",
resolvedURI.toString(),
baseURL.toString()),
e);
}
if (url == null) {
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("schemaImportError",
resolvedURI.toString(),
baseURL.toString()));
}
importLocation = url.toString();
return importLocation;
}
}