/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2009 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
*/

package org.ow2.jonas.ws.publish.internal.file;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.Properties;

import javax.wsdl.Definition;
import javax.wsdl.WSDLException;

import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import org.ow2.jonas.lib.bootstrap.JProp;
import org.ow2.jonas.lib.util.Log;
import org.ow2.jonas.ws.publish.AbsWSDLPublisher;
import org.ow2.jonas.ws.publish.PublicationInfo;
import org.ow2.jonas.ws.publish.PublishableDefinition;
import org.ow2.jonas.ws.publish.WSDLPublisher;
import org.ow2.jonas.ws.publish.WSDLPublisherException;

/**
 * In charge of publishing a given WSDL in a directory.
 * properties :<br/>
 * - <code>jonas.service.publish.file.directory</code> : directory name where WSDLs will be placed (default to JONAS_BASE/wsdls)<br/>
 * - <code>jonas.service.publish.file.encoding</code> : file encoding (default to UTF-8)<br/>
 *
 * use the <code>wsdl-publish-directory</code> if provided in jonas descriptors.
 * @author Xavier Delplanque
 * @author Guillaume Sauthier
 */
public class FileWSDLPublisher extends AbsWSDLPublisher implements WSDLPublisher {

    /** WSDL Directory */
    private File location;

    /** charset */
    private Charset cs;

    /** directory property name */
    private static final String OUTPUT_DIRECTORY = "jonas.service.publish.file.directory";

    /** encoding mode */
    private static final String ENCODING = "jonas.service.publish.file.encoding";

    /** logger */
    private static Logger logger = Log.getLogger("org.ow2.jonas.ws");

    /**
     * Return a new instance of FileWSDLPublisher.
     *
     * @param props Properties used to configure FileWSDLPublisher
     *
     * @throws WSDLPublisherException When Cannot create the directory
     *         (if it don't exist or not set in property file).
     */
    public FileWSDLPublisher(final Properties props) throws WSDLPublisherException {

        String directory = props.getProperty(OUTPUT_DIRECTORY);

        if (directory == null) {
            // no directory specified
            // use the default one : JONAS_BASE/wsdls
            String jonasBase = JProp.getJonasBase();
            directory = new File(jonasBase, "wsdls").getPath();
        }

        String encoding = props.getProperty(ENCODING, "UTF-8");

        try {
            location = new File(directory).getCanonicalFile();

            if (!location.exists()) {
                // if the given file doesn't exist, create it.
                location.mkdirs();
            }

            cs = Charset.forName(encoding);

        } catch (IOException ioe) {
            throw new WSDLPublisherException(
                "cannot find/create the publishing directory '" + directory + "'",
                ioe);
        } catch (IllegalCharsetNameException icsne) {
            throw new WSDLPublisherException(
                "Illegal Charset '" + encoding + "'",
                icsne);
        } catch (UnsupportedCharsetException ucse) {
            throw new WSDLPublisherException(
                "Charset '" + encoding + "' not supported on this platform.",
                ucse);
        }
    }

    /**
     * publish the given wsdl
     * @param publishableDefinition the data containing the WSDL file to be
     *        published and the publication info
     * @throws WSDLPublisherException if an error occurs at the publishing.
     */
    public void publish(final PublishableDefinition publishableDefinition) throws WSDLPublisherException {

        Definition definition = publishableDefinition.getDefinition();
        PublicationInfo info = publishableDefinition.getPublicationInfo();

       // build the fully qualified file name for the published wsdl file
       String fileName = info.getOriginalWsdlFilename();
       logger.log(BasicLevel.DEBUG, "Attempting to publish '" + fileName + "'");

        File sLoc = null;
        File pubDirectory = info.getPublicationDirectory();
        if (pubDirectory == null) {
            // No directory provided, just place the WSDL at the root of
            // the directory provided to the Handler
            sLoc = location;
        } else {
            if (pubDirectory.isAbsolute()) {
                // absolute directory
                sLoc = pubDirectory;
            } else {
                // relative directory
                sLoc = new File(location, pubDirectory.getPath());
            }
        }

        try {
            sLoc = sLoc.getCanonicalFile();

            logger.log(BasicLevel.DEBUG, "Publishing into directory '" + sLoc + "'");

            createDirIfNeeded(sLoc);
            // write the wsdl file in the directory
            JDefinitionWriter jdw = new JDefinitionWriter(definition, sLoc, cs, fileName);
            jdw.write();
        } catch (IOException ioe) {
            throw new WSDLPublisherException("Error with writer of file '"
                                         + fileName + "'", ioe);
        } catch (WSDLException we) {
            throw new WSDLPublisherException("Error with wsdl file '" + fileName
                                         + "' publishing in directory '" + location
                                         + "'", we);
        }
    }
    /**
     * Creates the parent of the given file as a directory
     * @param file with a parent that must be a directory
     * @throws IOException if directory cannot be created
     */
    private void createDirIfNeeded(final File file) throws IOException {
        if (!file.exists()) {
            if (!file.mkdirs()) {
                // cannot create directory
                throw new IOException("Cannot create directory " + file.getCanonicalPath());
            }
        } else if (!file.isDirectory()) {
            // parent exists but is not a directory
            throw new IOException("Parent " + file.getCanonicalPath() + " already exists but is not a directory.");
        }
    }


}
