org.apache.axis2.jaxws.util.BaseWSDLLocator.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.axis2.jaxws.util.BaseWSDLLocator.java

Source

/*
 * 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 org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.InputSource;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.util.StringTokenizer;

/**
 * This class is the base for an implementation of a WSDL4J interface that 
 * will be supplied to a WSDLReader instance. Its primary goal is to assist 
 * with locating imported WSDL documents.
 */
public abstract class BaseWSDLLocator {

    private static Log log = LogFactory.getLog(BaseWSDLLocator.class);

    protected String baseURI, lastestImportURI;
    protected InputStream baseInputStream;

    /**
     * Returns an InputStream pointed at an imported wsdl pathname relative
     * to the parent resource or loadStrategy.
     * 
     * @param importPath identifies the WSDL file within the context 
     * @return an stream of the WSDL file
     */
    abstract protected InputStream getInputStream(String importPath) throws IOException;

    /**
     * Allows for a level of indirection, such as a catalog, when importing URIs.
     * 
     * @param importURI a URI specifying the document to import
     * @param parent a URI specifying the location of the parent document doing
     * the importing
     * @return the resolved import location, or null if no indirection is performed
     */
    abstract protected String getRedirectedURI(String importURI, String parent);

    /**
      * Returns an InputSource "pointed at" the base document.
      */
    public InputSource getBaseInputSource() {
        return new InputSource(baseInputStream);
    }

    /**
     * Returns an InputSource pointed at an imported wsdl document whose
     * parent document was located at parentLocation and whose
     * relative location to the parent document is specified by
     * relativeLocation.
     *
     * @param parentLocation a URI specifying the location of the
     * document doing the importing.
     * @param relativeLocation a URI specifying the location of the
     * document to import, relative to the parent document's location.
     */
    public InputSource getImportInputSource(String parentLocation, String relativeLocation) {
        if (log.isDebugEnabled()) {
            log.debug("getImportInputSource, parentLocation= " + parentLocation + " relativeLocation= "
                    + relativeLocation);
        }
        InputStream is = null;
        URL absoluteURL = null;

        String redirectedURI = getRedirectedURI(relativeLocation, parentLocation);
        if (redirectedURI != null)
            relativeLocation = redirectedURI;

        try {
            if (isAbsoluteImport(relativeLocation)) {
                try {
                    absoluteURL = new URL(relativeLocation);
                    is = absoluteURL.openStream();
                    lastestImportURI = absoluteURL.toExternalForm();
                } catch (Throwable t) {
                    if (relativeLocation.startsWith("file://")) {
                        try {
                            relativeLocation = "file:/" + relativeLocation.substring("file://".length());
                            absoluteURL = new URL(relativeLocation);
                            is = absoluteURL.openStream();
                            lastestImportURI = absoluteURL.toExternalForm();
                        } catch (Throwable t2) {
                        }
                    }
                }
                if (is == null) {
                    try {
                        URI fileURI = new URI(relativeLocation);
                        absoluteURL = fileURI.toURL();
                        is = absoluteURL.openStream();
                        lastestImportURI = absoluteURL.toExternalForm();
                    } catch (Throwable t) {
                        //No FFDC code needed  
                    }
                }
                if (is == null) {
                    try {
                        File file = new File(relativeLocation);
                        absoluteURL = file.toURL();
                        is = absoluteURL.openStream();
                        lastestImportURI = absoluteURL.toExternalForm();
                    } catch (Throwable t) {
                        //No FFDC code needed           
                    }
                }

            } else {
                String importPath = normalizePath(parentLocation, relativeLocation);
                is = getInputStream(importPath);
                lastestImportURI = importPath;
            }
        } catch (IOException ex) {
            throw ExceptionFactory.makeWebServiceException(
                    Messages.getMessage("WSDLRelativeErr1", relativeLocation, parentLocation, ex.toString()));
        }
        if (is == null) {
            throw ExceptionFactory.makeWebServiceException(
                    Messages.getMessage("WSDLRelativeErr2", relativeLocation, parentLocation));
        }
        if (log.isDebugEnabled()) {
            log.debug("Loaded file: " + relativeLocation);
        }
        return new InputSource(is);
    }

    /**
     * Returns a URI representing the location of the base document.
     */
    public String getBaseURI() {
        return baseURI;

    }

    /**
     * Returns a URI representing the location of the last import document
     * to be resolved. This is useful when resolving nested imports.
     */
    public String getLatestImportURI() {
        return lastestImportURI;
    }

    /*
     * @param rawURI the uri for base wsdl file, which could be the form of
     *          META-INF/base.wsdl or just base.wsdl, but it can be /base.wsdl (no leading slash according to spec)
     * @return the uri which is one level up the raw uri with the trailing slash (if not empty)
     * 
     */
    protected String convertURI(String rawURI) {
        int idx = rawURI.lastIndexOf('/');
        if (idx > 0) {
            rawURI = rawURI.substring(0, idx + 1);
            return rawURI;
        }
        // this may be an absolute file reference
        else {
            idx = rawURI.lastIndexOf('\\');
            if (idx > 0) {
                rawURI = rawURI.substring(0, idx + 1);
                return rawURI;
            }
            return "";
        }
    }

    protected boolean isAbsoluteImport(String uri) {
        boolean absolute = false;
        if (uri != null) {
            if (uri.indexOf(":/") != -1) {
                absolute = true;
            } else if (uri.indexOf(":\\") != -1) {
                absolute = true;
            }
        }

        return absolute;
    }

    /**
     * The ZipFile can not handle relative imports of that have directory components 
     * of the form "..".  Given a 'relativeLocation' relative to 'parentLocation', replace
     * any ".." with actual path component names.
     * @param parentLocation Path relative to the module root of the file that is doing the
     *                       importing.
     * @param relativeLocation Path relative to the parentLocation of the file that is being imported.
     * @return String contatining the path to the file being imported (i.e. relativeLocation) that is
     *         relative to the module root and has all ".." and "." path components removed and replaced
     *         with the corresponding actual directory name.
    */
    private static final char WSDL_PATH_SEPERATOR_CHAR = '/';
    private static final String WSDL_PATH_SEPERATOR = (Character.valueOf(WSDL_PATH_SEPERATOR_CHAR)).toString();

    protected String normalizePath(String parentLocation, String relativeLocation) {
        if (log.isDebugEnabled()) {
            log.debug(
                    "normalizePath, parentLocation= " + parentLocation + " relativeLocation= " + relativeLocation);
        }
        // Get the path from the module root to the directory containing the importing WSDL file.
        // Note this path will end in a "/" and will not contain any ".." path components.
        String pathFromRoot = convertURI(parentLocation);

        // Construct the path to the location relative to the module root based on the parent location, 
        // removing any ".." or "." path components.
        StringBuffer pathToRelativeLocation = new StringBuffer(pathFromRoot);
        StringTokenizer tokenizedRelativeLocation = new StringTokenizer(relativeLocation, WSDL_PATH_SEPERATOR);
        if (log.isDebugEnabled()) {
            log.debug("pathFromRoot = " + pathFromRoot);
            log.debug("relativeLocation = " + relativeLocation);
        }
        while (tokenizedRelativeLocation.hasMoreTokens()) {
            String nextToken = tokenizedRelativeLocation.nextToken();
            if (nextToken.equals("..")) {
                // Relative parent directory, so chop off the last path component in the path to back
                // up to the parent directory.  First delete the trailing "/" from the path if there 
                // is one, then delete characters from the end of the path until we find the next "/".
                int charToDelete = pathToRelativeLocation.length() - 1;
                if (pathToRelativeLocation.charAt(charToDelete) == WSDL_PATH_SEPERATOR_CHAR
                        || pathToRelativeLocation.charAt(charToDelete) == '\\') {
                    pathToRelativeLocation.deleteCharAt(charToDelete--);
                }
                while (pathToRelativeLocation.charAt(charToDelete) != WSDL_PATH_SEPERATOR_CHAR
                        && pathToRelativeLocation.charAt(charToDelete) != '\\') {
                    pathToRelativeLocation.deleteCharAt(charToDelete--);
                }
            } else if (nextToken.equals(".")) {
                // Relative current directory, do not add or delete any path components
            } else {
                // Make sure the current path ends in a "/"  or "\\" then append this path component
                // This handles locations within the module and URIs
                if ((pathToRelativeLocation.indexOf(String.valueOf(WSDL_PATH_SEPERATOR_CHAR)) != -1)
                        && (pathToRelativeLocation
                                .charAt(pathToRelativeLocation.length() - 1) != WSDL_PATH_SEPERATOR_CHAR)) {
                    pathToRelativeLocation.append(WSDL_PATH_SEPERATOR_CHAR);
                }
                // This handles file based locations
                else if ((pathToRelativeLocation.indexOf("\\") != -1)
                        && (pathToRelativeLocation.charAt(pathToRelativeLocation.length() - 1) != '\\')) {
                    pathToRelativeLocation.append('\\');
                }
                pathToRelativeLocation.append(nextToken);
            }
        }
        if (log.isDebugEnabled()) {
            log.debug("Built path = " + pathToRelativeLocation.toString());
        }
        return pathToRelativeLocation.toString();
    }
}