/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2003-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: ModifierFactory.java 17993 2009-07-21 21:30:03Z loris $
 * --------------------------------------------------------------------------
 */
package org.ow2.jonas.generators.wsgen.modifier;

import java.io.File;

import org.ow2.jonas.generators.genbase.GenBaseException;
import org.ow2.jonas.generators.genbase.archive.Application;
import org.ow2.jonas.generators.genbase.archive.Archive;
import org.ow2.jonas.generators.genbase.archive.Client;
import org.ow2.jonas.generators.genbase.archive.EjbJar;
import org.ow2.jonas.generators.genbase.archive.FileArchive;
import org.ow2.jonas.generators.genbase.archive.J2EEArchive;
import org.ow2.jonas.generators.genbase.archive.JarArchive;
import org.ow2.jonas.generators.genbase.archive.WebApp;
import org.ow2.jonas.generators.genbase.modifier.AbsModifierFactory;
import org.ow2.jonas.generators.genbase.modifier.ArchiveModifier;
import org.ow2.jonas.generators.wsgen.WsGenException;
import org.ow2.jonas.lib.util.I18n;
import org.ow2.util.archive.api.IArchive;
import org.ow2.util.archive.impl.ArchiveManager;
import org.ow2.util.ee.deploy.api.deployable.CARDeployable;
import org.ow2.util.ee.deploy.api.deployable.EARDeployable;
import org.ow2.util.ee.deploy.api.deployable.EJBDeployable;
import org.ow2.util.ee.deploy.api.deployable.IDeployable;
import org.ow2.util.ee.deploy.api.deployable.WARDeployable;
import org.ow2.util.ee.deploy.impl.helper.DeployableHelper;
import org.ow2.util.ee.deploy.impl.helper.UnpackDeployableHelper;
import org.ow2.util.url.URLUtils;

/**
 * Used to create the right ArchiveModifier from a given filename (ear, jar,
 * war, ...
 * @author Guillaume Sauthier
 */
public class ModifierFactory extends AbsModifierFactory {

    /**
     * I18n.
     */
    private static I18n i18n = I18n.getInstance(ModifierFactory.class);

    /**
     * Empty Constructor for utility class.
     */
    private ModifierFactory() {
    }

    /**
     * Returns an <code>ArchiveModifier</code> according to archive type
     * (application, ejbjar, webapp or client).
     * @param filename input filename.
     * @return an <code>ArchiveModifier</code>.
     * @exception GenBaseException when archive creation fails.
     */
    public static ArchiveModifier getModifier(final String filename) throws GenBaseException {
        return getModifier(filename, true, null);
    }

    /**
     * Returns an <code>ArchiveModifier</code> according to archive type (application, ejbjar, webapp or client).
     * @param filename input filename.
     * @param init Initialize the archive.
     * @param deployable the current deployable (can be null)
     * @return an <code>ArchiveModifier</code>.
     * @exception GenBaseException when archive creation fails.
     */
    public static ArchiveModifier getModifier(final String filename, final boolean init, final IDeployable<?> deployable)
            throws GenBaseException {
        Archive archive = null;
        J2EEArchive j2eeArchive = null;
        ArchiveModifier modifier = null;
        int mode;
        IDeployable<?> localDeployable = null;

        File file = new File(filename);

        if (file.exists()) {
            if (file.isFile()) {
                // Create the inner Archive
                archive = new JarArchive(file);
            } else {
                // directory unpacked
                // Create the inner Archive
                archive = new FileArchive(file);
            }

            try {
                if (deployable == null) {
                    // Build Archive
                    IArchive fileArchive = ArchiveManager.getInstance().getArchive(file);
                    localDeployable = DeployableHelper.getDeployable(fileArchive);
                } else {
                    localDeployable = deployable;
                }
            } catch (Exception e) {
                throw new WsGenException("Cannot get a deployable for the archive '" + archive + "'", e);
            }

            // now we are sure that filename is a correct jar
            // Workaround for http://bugs.sun.com/view_bug.do?bug_id=6548436
            if (EARDeployable.class.isInstance(localDeployable)) {
                if (archive  instanceof JarArchive) {
                    try {
                        localDeployable = UnpackDeployableHelper.unpack(EARDeployable.class.cast(localDeployable), "genbase");
                        archive = new FileArchive(URLUtils.urlToFile(localDeployable.getArchive().getURL()));
                    } catch (Exception e) {
                        throw new GenBaseException("Cannot unpack the deployable '" + deployable + "'.", e);
                    }
                }

                // Application J2EE Archive
                j2eeArchive = new Application(archive, localDeployable);
                mode = APPLICATION;
            } else if (EJBDeployable.class.isInstance(localDeployable)) {
                // EjbJar J2EE Archive
                j2eeArchive = new EjbJar(archive);
                mode = EJBJAR;

            } else if (WARDeployable.class.isInstance(localDeployable)) {
                // WebApp J2EE Archive
                j2eeArchive = new WebApp(archive);
                mode = WEBAPP;

            } else if (CARDeployable.class.isInstance(localDeployable)) {
                // Client J2EE Archive
                j2eeArchive = new Client(archive);
                mode = CLIENT;

            } else {
                // unsupported archive type
                String err = i18n.getMessage("ModifierFactory.getModifier.unsupported", filename);
                throw new WsGenException(err);
            }
        } else {
            String err = i18n.getMessage("ModifierFactory.getModifier.notfound", filename);
            throw new WsGenException(err);
        }

        // init the archive
        if (init) {
            j2eeArchive.initialize();
        }

        // create the modifier
        switch (mode) {
            case APPLICATION:
                modifier = new ApplicationModifier((Application) j2eeArchive);
                break;
            case EJBJAR:
                modifier = new EjbJarModifier((EjbJar) j2eeArchive);
                break;
            case WEBAPP:
                modifier = new WebAppModifier((WebApp) j2eeArchive);
                break;
            case CLIENT:
                modifier = new ClientModifier((Client) j2eeArchive);
                break;
            default:
                // cannot happen
        }

        return modifier;
    }
}
