/*
 * 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.toURI().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();
    }
}
