/*
 * 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.builder;

import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.dataretrieval.SchemaSupplier;
import org.apache.axis2.dataretrieval.WSDLSupplier;
import org.apache.axis2.deployment.util.Utils;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.java.security.AccessController;
import org.apache.axis2.jaxws.catalog.JAXWSCatalogManager;
import org.apache.axis2.jaxws.catalog.impl.OASISCatalogManager;
import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.util.CatalogURIResolver;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.util.SchemaUtil;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaCollection;
import org.xml.sax.InputSource;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.soap.SOAPBinding;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;

/**
 * This class will implement an interface that is defined by the
 * MDQ code. It will be registered within the MDQ framework, and the
 * MDQ code will call this when it finds an application that was
 * deployed without WSDL. This class will use the WsGen tool to
 * generate a WSDL Definition based on the Java source for the application.
 */
public class JAXWSRIWSDLGenerator implements SchemaSupplier, WSDLSupplier {

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

    private String classPath;

    private AxisService axisService;
    private boolean init = false;
    private HashMap<String, XmlSchema> docMap;
    private HashMap<String, Definition> wsdlDefMap;

    public JAXWSRIWSDLGenerator(AxisService axisService) {
        this.axisService = axisService;
    }

    /**
     * This method will drive the call to WsGen to generate a WSDL file for
     * applications deployed without WSDL. We will then read this file in from
     * disk and create a Definition. After we are done with the file we will
     * remove it from disk.
     */
    public void generateWsdl(String className, String bindingType) throws WebServiceException {
    	generateWsdl(className, bindingType, null);
    }
    
    /**
     * This method will drive the call to WsGen to generate a WSDL file for
     * applications deployed without WSDL. We will then read this file in from
     * disk and create a Definition. After we are done with the file we will
     * remove it from disk.  This method accepts a CatalogManager as a parameter
     * for the eventual use in by an XMLSchemaCollection.
     */
    public void generateWsdl(String className, String bindingType, JAXWSCatalogManager catalogManager) throws
            WebServiceException {

        AxisConfiguration axisConfiguration = axisService.getAxisConfiguration();
        File tempFile = (File) axisConfiguration.getParameterValue(
                Constants.Configuration.ARTIFACTS_TEMP_DIR);
        if (tempFile == null) {
            tempFile = new File(getProperty_doPriv("java.io.tmpdir"), "_axis2");
        }

        Parameter servletConfigParam = axisConfiguration
                .getParameter(HTTPConstants.HTTP_SERVLETCONFIG);

        String webBase = null;
        if (servletConfigParam != null) {
            Object obj = servletConfigParam.getValue();
            ServletContext servletContext;
    
            if (obj instanceof ServletConfig) {
                ServletConfig servletConfig = (ServletConfig) obj;
                servletContext = servletConfig.getServletContext();
                webBase = servletContext.getRealPath("/WEB-INF");
            } 
        }

        if(classPath == null) {
            this.classPath = getDefaultClasspath(webBase);
        }
        if (log.isDebugEnabled()) {
            log.debug("For implementation class " + className +
                    " WsGen classpath: " +
                    classPath);
        }
        String localOutputDirectory = tempFile.getAbsolutePath() + className;
        if (log.isDebugEnabled()) {
            log.debug("Output directory for generated WSDL file: " + localOutputDirectory);
        }
        boolean errorOnRead = false;
        try {

            if (log.isDebugEnabled()) {
                log.debug("Generating new WSDL Definition");
            }

            createOutputDirectory(localOutputDirectory);
            Class clazz;
            try {
                // Try the one in JDK16
                clazz = Class.forName("com.sun.tools.internal.ws.spi.WSToolsObjectFactory");
            } catch (Throwable t){
                // Look for the RI
                clazz = Class.forName("com.sun.tools.ws.spi.WSToolsObjectFactory");
            }
            Method m1 = clazz.getMethod("newInstance", new Class[]{});
            Object factory = m1.invoke(new Object[]{});
            String[] arguments = getWsGenArguments(className, bindingType, localOutputDirectory);
            OutputStream os = new ByteArrayOutputStream();
            Method m2 = clazz.getMethod("wsgen", new Class[]{OutputStream.class, String[].class});
            m2.invoke(factory, os, arguments);
            os.close();
            wsdlDefMap = readInWSDL(localOutputDirectory);
            if (wsdlDefMap.isEmpty()) {
                throw new Exception("A WSDL Definition could not be generated for " +
                        "the implementation class: " + className);
            }
            docMap = readInSchema(localOutputDirectory, catalogManager);
        }
        catch (Throwable t) {
            String msg =
                    "Error occurred generating WSDL file for Web service implementation class " +
                            "{" + className + "}: {" + t + "}";
            log.error(msg, t);
            throw new WebServiceException(msg, t);
        }
    }

    /**
     * This will set up the arguments that will be used by the WsGen tool.
     */
    private String[] getWsGenArguments(String className, String bindingType, String localOutputDirectory) throws
            WebServiceException {
        String[] arguments = null;
        if (bindingType == null || bindingType.equals("") || bindingType.equals(
                SOAPBinding.SOAP11HTTP_BINDING) || bindingType.equals(
                SOAPBinding.SOAP11HTTP_MTOM_BINDING)) {
            if (log.isDebugEnabled()) {
                log.debug("Generating WSDL with SOAP 1.1 binding type");
            }
            arguments = new String[]{"-cp", classPath, className, "-keep", "-wsdl:soap1.1", "-d",
                    localOutputDirectory};
        } else if (bindingType.equals(SOAPBinding.SOAP12HTTP_BINDING) || bindingType.equals(
                SOAPBinding.SOAP12HTTP_MTOM_BINDING)) {
            if (log.isDebugEnabled()) {
                log.debug("Generating WSDL with SOAP 1.2 binding type");
            }
            arguments = new String[]{"-cp", classPath, className, "-keep", "-extension",
                    "-wsdl:Xsoap1.2", "-d", localOutputDirectory};
        } else {
            throw new WebServiceException("The binding " + bindingType + " specified by the " +
                    "class " + className + " cannot be used to generate a WSDL. Please choose " +
                    "a supported binding type.");
        }
        return arguments;
    }

    /**
     * This method will be used to create a Definition based on the
     * WSDL file generated by WsGen.
     */
    private HashMap<String, Definition> readInWSDL(String localOutputDirectory) throws Exception {
        List<File> wsdlFiles = getWSDLFiles(localOutputDirectory);
        HashMap<String, Definition> wsdlDefMap = new HashMap<String, Definition>();
        for (File wsdlFile : wsdlFiles) {
            if (wsdlFile != null) {
                try {
                    WSDLFactory wsdlFactory = WSDLFactory.newInstance();
                    WSDLReader wsdlReader = wsdlFactory.newWSDLReader();
                    InputStream is = wsdlFile.toURL().openStream();
                    Definition definition = wsdlReader.readWSDL(localOutputDirectory,
                            new InputSource(is));
                    try {
                        definition.setDocumentBaseURI(wsdlFile.toURI().toString());
                        if (log.isDebugEnabled()) {
                            log.debug("Set base document URI for generated WSDL: " +
                                    wsdlFile.toURI().toString());
                        }
                    }
                    catch (Throwable t) {
                        if (log.isDebugEnabled()) {
                            log.debug("Could not set base document URI for generated " +
                                    "WSDL: " + wsdlFile.getAbsolutePath() + " : " +
                                    t.toString());
                        }
                    }
                    wsdlDefMap.put(wsdlFile.getName().toLowerCase(), definition);
                }
                catch (WSDLException e) {
                    String msg = "Error occurred while attempting to create Definition from " +
                            "generated WSDL file {" + wsdlFile.getName() + "}: {" + e + "}";
                    log.error(msg);
                    throw new Exception(msg);
                }
                catch (IOException e) {
                    String msg = "Error occurred while attempting to create Definition from " +
                            "generated WSDL file  {" + wsdlFile.getName() + "}: {" + e + "}";
                    log.error(msg);
                    throw new Exception(msg);
                }
            }
        }
        return wsdlDefMap;
    }

    /**
     * This method will be used to locate the WSDL file that was
     * generated by WsGen. There should be only one file with the
     * ".wsdl" extension in this directory.
     */
    private List<File> getWSDLFiles(String localOutputDirectory) {
        File classDirectory = new File(localOutputDirectory);
        ArrayList<File> wsdlFiles = new ArrayList<File>();
        if (classDirectory.isDirectory()) {
            File[] files = classDirectory.listFiles();
            for (File file : files) {
                String fileName = file.getName();
                if (fileName.endsWith(".wsdl")) {
                    if (log.isDebugEnabled()) {
                        log.debug("Located generated WSDL file: " + fileName);
                    }
                    wsdlFiles.add(file);
                }
            }
        }
        return wsdlFiles;
    }

    /**
     * This file will create the directory we will use as the output
     * directory argument in our call to WsGen.
     */
    private void createOutputDirectory(String localOutputDirectory) {
        File directory = new File(localOutputDirectory);
        if (!directory.isDirectory()) {
            directory.mkdirs();
        }
    }

    /**
     * This method will read in all of the schema files that were generated
     * for a given application.
     */
    private HashMap<String, XmlSchema> readInSchema(String localOutputDirectory, 
    		                                        JAXWSCatalogManager catalogManager) throws Exception {
        try {

            XmlSchemaCollection schemaCollection = new XmlSchemaCollection();
            if (catalogManager != null)
                schemaCollection.setSchemaResolver(new CatalogURIResolver(catalogManager));
            schemaCollection.setBaseUri(new File(localOutputDirectory).getAbsolutePath());

            HashMap<String, XmlSchema> docMap = new HashMap<String, XmlSchema>();
            List<File> schemaFiles = getSchemaFiles(localOutputDirectory);
            for (File schemaFile : schemaFiles) {
                XmlSchema doc = schemaCollection.read(new InputSource(schemaFile.toURL().toString()), null);
                if (log.isDebugEnabled()) {
                    log.debug("Read in schema file: " + schemaFile.getName());
                }
                docMap.put(schemaFile.getName(), doc);
            }
            return docMap;
        }
        catch (Exception e) {
            String msg =
                    "Error occurred while attempting to read generated schema file {" + e + "}";
            log.error(msg);
            throw new Exception(msg);
        }
    }

    /**
     * This method will return a list of file objects that represent all the
     * schema files in the current directory.
     */
    private List<File> getSchemaFiles(String localOutputDirectory) {
        ArrayList<File> schemaFiles = new ArrayList<File>();
        File classDirectory = new File(localOutputDirectory);
        if (classDirectory.isDirectory()) {
            File[] files = classDirectory.listFiles();
            for (File file : files) {
                String fileName = file.getName();
                if (fileName.endsWith(".xsd")) {
                    if (log.isDebugEnabled()) {
                        log.debug("Located generated schema file: " + fileName);
                    }
                    schemaFiles.add(file);
                }
            }
        }
        return schemaFiles;
    }

    public Definition getWSDL(AxisService service) throws AxisFault {
        Parameter wsdlParameter = service.getParameter(WSDLConstants.WSDL_4_J_DEFINITION);
        if (wsdlParameter != null) {
            Object value = wsdlParameter.getValue();
            if (value != null) {
                return (Definition) value;
            }
        }
        initialize(service);
        return wsdlDefMap.values().iterator().next();
    }

    private synchronized void initialize(AxisService service) {
        String className = (String) axisService.getParameter(Constants.SERVICE_CLASS).getValue();
        if (!init) {
            generateWsdl(className, SOAPBinding.SOAP11HTTP_BINDING, getCatalogManager(service));
            init = true;
        }
    }

    public XmlSchema getSchema(AxisService service, String xsd) throws AxisFault {
        Parameter wsdlParameter = service.getParameter(WSDLConstants.WSDL_4_J_DEFINITION);
        if (wsdlParameter != null) {
            ArrayList list = service.getSchema();
            if (list.size() > 0) {
                if (xsd == null || xsd.length() == 0) {
                    return (XmlSchema) list.get(0);
                }

                for (Iterator iterator = list.iterator(); iterator.hasNext();) {
                    XmlSchema schema = (XmlSchema) iterator.next();
                    XmlSchema[] schemas = SchemaUtil.getAllSchemas(schema);
                    for (int i = 0; i < schemas.length; i++) {
                        String uri = schemas[i].getSourceURI();
                        if (uri != null && uri.endsWith(xsd)) {
                            return schemas[i];
                        }
                    }
                }
                return (XmlSchema) list.get(0);
            }
        }
        initialize(service);
        XmlSchema schema = docMap.get(xsd);
        if (schema == null) {
            docMap.values().iterator().next();
        }
        return schema;
    }

    /**
     * Expand a directory path or list of directory paths (File.pathSeparator
     * delimited) into a list of file paths of all the jar files in those
     * directories.
     *
     * @param dirPaths The string containing the directory path or list of
     *                 directory paths.
     * @return The file paths of the jar files in the directories. This is an
     *         empty string if no files were found, and is terminated by an
     *         additional pathSeparator in all other cases.
     */
    public static String expandDirs(String dirPaths) {
        StringTokenizer st = new StringTokenizer(dirPaths, File.pathSeparator);
        StringBuffer buffer = new StringBuffer();
        while (st.hasMoreTokens()) {
            String d = st.nextToken();
            File dir = new File(d);
            if (dir.isDirectory()) {
                File[] files = dir.listFiles(new JavaArchiveFilter());
                for (int i = 0; i < files.length; i++) {
                    buffer.append(files[i]).append(File.pathSeparator);
                }
            }
        }
        return buffer.toString();
    }

    /**
     * Check if this inputstream is a jar/zip
     *
     * @param is
     * @return true if inputstream is a jar
     */
    public static boolean isJar(InputStream is) {
        try {
            JarInputStream jis = new JarInputStream(is);
            if (jis.getNextEntry() != null) {
                return true;
            }
        } catch (IOException ioe) {
        }
        return false;
    }

    /**
     * Get the CatalogManager associated with an AxisService
     * @return the CatalogManager in use for this AxisService
     */
    public static JAXWSCatalogManager getCatalogManager(AxisService service) {
    	Parameter param = service.getParameter(EndpointDescription.AXIS_SERVICE_PARAMETER);

    	if (param != null) {
            EndpointDescription ed = (EndpointDescription)param.getValue();
            return ed.getServiceDescription().getCatalogManager();
    	} else
    	    return new OASISCatalogManager();
    }
    
    /**
     * Get the default classpath from various thingies in the message context
     *
     * @param msgContext
     * @return default classpath
     */
    public String getDefaultClasspath(String webBase) {
        HashSet classpath = new HashSet();
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        fillClassPath(cl, classpath);

        // Just to be safe (the above doesn't seem to return the webapp
        // classpath in all cases), manually do this:
        if (webBase != null) {
            addPath(classpath, webBase + File.separatorChar + "classes");
            try {
                String libBase = webBase + File.separatorChar + "lib";
                File libDir = new File(libBase);
                String[] jarFiles = libDir.list();
                for (int i = 0; i < jarFiles.length; i++) {
                    String jarFile = jarFiles[i];
                    if (jarFile.endsWith(".jar")) {
                        addPath(classpath, libBase +
                                File.separatorChar +
                                jarFile);
                    }
                }
            } catch (Exception e) {
                // Oh well.  No big deal.
            }
        }
        
        URL serviceArchive = axisService.getFileName();
        if(serviceArchive != null) {
            try {
                classpath.add(Utils.toFile(serviceArchive).getCanonicalPath());
            } catch (UnsupportedEncodingException e) {
                log.error(e.getMessage(), e);
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }

        // axis.ext.dirs can be used in any appserver
        getClassPathFromDirectoryProperty(classpath, "axis.ext.dirs");

        // classpath used by Jasper 
        getClassPathFromProperty(classpath, "org.apache.catalina.jsp_classpath");

        // websphere stuff.
        getClassPathFromProperty(classpath, "ws.ext.dirs");
        getClassPathFromProperty(classpath, "com.ibm.websphere.servlet.application.classpath");

        // java class path
        getClassPathFromProperty(classpath, "java.class.path");

        // Load jars from java external directory
        getClassPathFromDirectoryProperty(classpath, "java.ext.dirs");

        // boot classpath isn't found in above search
        getClassPathFromProperty(classpath, "sun.boot.class.path");
        
        StringBuffer path = new StringBuffer();
        for (Iterator iterator = classpath.iterator(); iterator.hasNext();) {
            String s = (String) iterator.next();
            path.append(s);
            path.append(File.pathSeparatorChar);
        }
        log.debug(path);
        return path.toString();
    }

    private static void addPath(HashSet classpath, String s) {
        String path = s.replace(((File.separatorChar == '/') ? '\\' : '/'), File.separatorChar).trim();
        File file = new File(path);
        if (fileExists(file)) {
            path = file.getAbsolutePath();
            classpath.add(path);
        }
    }

    /**
     * Add all files in the specified directory to the classpath
     *
     * @param classpath
     * @param property
     */
    private static void getClassPathFromDirectoryProperty(HashSet classpath, String property) {
        String dirs = getProperty_doPriv(property);
        String path = null;
        try {
            path = expandDirs(dirs);
        } catch (Exception e) {
            // Oh well.  No big deal.
        }
        if (path != null) {
            addPath(classpath, path);
        }
    }

    private static String getProperty_doPriv(final String property) {
        return (String)
         AccessController.doPrivileged(
              new PrivilegedAction() {

                  public Object run() {
                      try {
                          return System.getProperty(property);
                      } catch (Throwable t) {
                          return null;
                      }
                  }
              });
    }
    /**
     * Add a classpath stored in a property.
     *
     * @param classpath
     * @param property
     */
    private static void getClassPathFromProperty(HashSet classpath, String property) {
        String path = getProperty_doPriv(property);
        if (path != null) {
            addPath(classpath, path);
        }
    }

    /**
     * Walk the classloader hierarchy and add to the classpath
     *
     * @param cl
     * @param classpath
     */
    private static void fillClassPath(ClassLoader cl, HashSet classpath) {
        while (cl != null) {
            if (cl instanceof URLClassLoader) {
                URL[] urls = ((URLClassLoader) cl).getURLs();
                for (int i = 0; (urls != null) && i < urls.length; i++) {
                    String path = urls[i].getPath();
                    //If it is a drive letter, adjust accordingly.
                    if (path.length() >= 3 && path.charAt(0) == '/' && path.charAt(2) == ':')
                        path = path.substring(1);
                    addPath(classpath, URLDecoder.decode(path));

                    // if its a jar extract Class-Path entries from manifest
                    File file = new File(urls[i].getFile());
                    if (file.isFile()) {
                        FileInputStream fis = null;
                        try {
                            fis = new FileInputStream(file);
                            if (isJar(fis)) {
                                JarFile jar = new JarFile(file);
                                Manifest manifest = jar.getManifest();
                                if (manifest != null) {
                                    Attributes attributes = manifest.getMainAttributes();
                                    if (attributes != null) {
                                        String s = attributes.getValue(Attributes.Name.CLASS_PATH);
                                        String base = file.getParent();
                                        if (s != null) {
                                            StringTokenizer st = new StringTokenizer(s, " ");
                                            while (st.hasMoreTokens()) {
                                                String t = st.nextToken();
                                                addPath(classpath, base + File.separatorChar + t);
                                            }
                                        }
                                    }
                                }
                            }
                        } catch (IOException ioe) {
                        } finally {
                            if (fis != null) {
                                try {
                                    fis.close();
                                } catch (IOException ioe2) {
                                }
                            }
                        }
                    }
                }
            }
            cl = cl.getParent();
        }
    }

    /**
     * Filter for zip/jar
     */
    private static class JavaArchiveFilter implements FileFilter {
        public boolean accept(File file) {
            String name = file.getName().toLowerCase();
            return (name.endsWith(".jar") || name.endsWith(".zip"));
        }
    }
    
    static private Boolean fileExists (final File file) {
        Boolean exists = (Boolean) AccessController.doPrivileged(
                new PrivilegedAction() {
                    public Object run() {
                        return new Boolean(file.exists());
                    }
                }
        );
        return exists;
    }
    
}