/**
 * JOnAS : Java(TM) OpenSource Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * 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.generators.genbase.archive;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.jar.Manifest;

import org.ow2.jonas.generators.genbase.GenBaseException;
import org.ow2.jonas.generators.genbase.generator.Config;
import org.ow2.jonas.generators.genbase.generator.GeneratorFactories;
import org.ow2.jonas.generators.genbase.generator.GeneratorFactory;
import org.ow2.jonas.lib.util.I18n;
import org.ow2.jonas.lib.util.Log;



import org.objectweb.util.monolog.api.Logger;


/**
 * Base Class for all J2EE modules (application, ejbjar, client, webapp).
 *
 * @author Guillaume Sauthier
 * @see org.ow2.jonas.generators.genbase.archive.Archive
 */
public abstract class J2EEArchive implements Archive {
    /** i18n */
    private static I18n i18n = I18n.getInstance(J2EEArchive.class);

    /** logger */
    private static Logger logger = Log.getLogger(Log.JONAS_GENBASE_PREFIX);

    /** encapsulated archive */
    private Archive archive;

    /** J2EE Archive inner ClassLoader */
    private ClassLoader moduleClassloader = null;

    /**
     * Creates a new J2EEArchive object.
     *
     * @param archive Archive containing files
     */
    public J2EEArchive(Archive archive) {
        this.archive = archive;
    }

    /**
     * add the content of the given directory into  the root of the archive.
     *
     * @param directory directory to add
     */
    public void addDirectory(File directory) {
        archive.addDirectory(directory);
    }

    /**
     * add the content of the given directory into  the given directory of the
     * archive.
     *
     * @param dirName archive directory name.
     * @param directory directory to add.
     */
    public void addDirectoryIn(String dirName, File directory) {
        archive.addDirectoryIn(dirName, directory);
    }

    /**
     * add a lonely file into the root directory of the archive.
     *
     * @param file the file to be added.
     */
    public void addFile(File file) {
        archive.addFile(file);
    }

    /**
     * add a file into the root directory of the archive with a specified name.
     *
     * @param file the file to be added.
     * @param name filename
     */
    public void addFile(File file, String name) {
        archive.addFile(file, name);
    }

    /**
     * add a lonely file into the given directory of the archive.
     *
     * @param dirName archive directory name.
     * @param file the file to be added.
     */
    public void addFileIn(String dirName, File file) {
        archive.addFileIn(dirName, file);
    }

    /**
     * Returns the File corresponding to the root of the archive.
     *
     * @return the File corresponding to the root of the archive.
     */
    public File getRootFile() {
        return archive.getRootFile();
    }

    /**
     * Returns the Manifest of the Archive.
     *
     * @return the Manifest of the Archive.
     */
    public Manifest getManifest() {
        return archive.getManifest();
    }

    /**
     * Returns an InputStream corresponding to the given filename.
     *
     * @param filename file name source of the InputStream
     *
     * @return the InputStream corresponding to the given filename.
     *
     * @throws IOException When Cannot get InputStream from filename
     */
    public InputStream getInputStream(String filename)
        throws IOException {
        return archive.getInputStream(filename);
    }

    /**
     * Returns a List of all files contained in this archive. Original files in
     * jar, added Files are all included as String in this Enumeration.
     *
     * @return a List of all files contained in this archive.
     */
    public List getContainedFiles() {
        return archive.getContainedFiles();
    }

    /**
     * Returns true if archive is packed or false if archive is unpacked.
     *
     * @return true if archive is packed or false if archive is unpacked.
     */
    public boolean isPacked() {
        return archive.isPacked();
    }

    /**
     * Returns the name of the Archive.
     *
     * @return the name of the Archive.
     */
    public String getName() {
        return archive.getName();
    }

    /**
     * Returns a Map of name to Document for each modified Descriptor of the
     * archive.
     *
     * @return a Map of name to Document
     */
    public abstract Map getDescriptors();

    /**
     * Returns true if filename must be omitted in the archive.
     *
     * @param name filename to be tested
     *
     * @return true if filename must be omitted.
     */
    public abstract boolean omit(String name);

    /**
     * @return Returns the i18n.
     */
    public static I18n getI18n() {
        return i18n;
    }
    /**
     * @return Returns the logger.
     */
    public static Logger getLogger() {
        return logger;
    }
    /**
     * @return Returns the archive.
     */
    public Archive getArchive() {
        return archive;
    }
    /**
     * @param archive The archive to set.
     */
    public void setArchive(Archive archive) {
        this.archive = archive;
    }

    /**
     * Initialize the Archive.
     * @throws GenBaseException When initialization fails.
     */
    public abstract void initialize() throws GenBaseException;

    /**
     * @return Returns the module inner ClassLoader
     */
    public ClassLoader getModuleClassloader() {
        return moduleClassloader;
    }

    /**
     * @param moduleClassloader The moduleClassloader to set.
     */
    public void setModuleClassloader(ClassLoader moduleClassloader) {
        this.moduleClassloader = moduleClassloader;
    }

    /**
     * @return true if the use of DTDs is allowed or if we have to use only web services
     */
    protected boolean isDTDsAllowed() {
        GeneratorFactory gf = GeneratorFactories.getCurrentFactory();
        if (gf == null) {
            throw new IllegalStateException(i18n.getMessage("J2EEArchive.isDTDsAllowed.noFactory"));
        }
        Config config = gf.getConfiguration();
        if (config == null) {
            throw new IllegalStateException(i18n.getMessage("J2EEArchive.isDTDsAllowed.noConfig"));
        }
        return config.isDTDsAllowed();
    }

    /**
     * Close this archive
     */
    public void close() {
        try {
            this.archive.close();
        } catch (IOException ioe) {
            throw new RuntimeException("Cannot close file '" + archive + "'", ioe);
        }
        archive = null;
    }
}
