/**
 * Copyright (C) 2003 France Telecom R&D
 *
 * 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 of the License, or (at your option) 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
 */
package org.objectweb.util.ant;

import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.taskdefs.UpToDate;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.FileSet;

import java.io.File;
import java.io.IOException;
import java.io.FileWriter;
import java.util.Enumeration;
import java.util.Set;
import java.util.TreeSet;
import java.util.Iterator;
import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;

/**
 * Permit to build .package-list files since archive files (jar, rar, zip, ...).
 *
 * @author S.Chassande-Barrioz
 */
public class Jar2packageList extends MatchingTask {

	File jarDir =  null;
    File output = null;
    boolean flatten = false;
    boolean isolate = false;

	/**
     * The base directory containing archives
     * @param d
     */
    public void setJarDir(File d) {
		jarDir = d;
	}

    /**
     * the directory where the .package-list will be generated
     * @param o
     */
    public void setOutput(File o) {
        output = o;
    }

    public void setFlatten(boolean b) {
        flatten = b;
    }

    public void setIsolate(boolean b) {
        isolate = b;
    }

	public void execute() throws BuildException {
		String[] filenames = DirectoryScannerHelper.getSelectedFilesAsString(
		        getDirectoryScanner(jarDir), getProject());
        boolean hasGenerate = false;
		for (int i=0; i<filenames.length; i++) {
            try {
                Set packages = new TreeSet();
                File jarfile = new File(jarDir, filenames[i]);
                if (jarfile.isDirectory()) {
                    log("Ignore '" + filenames[i] + "': is a directory.", Project.MSG_DEBUG);
                    continue;
                }
                ZipFile archive = null;
                try {
                    archive = new ZipFile(jarfile);
                } catch (IOException e) {
                    log("Ignore '" + filenames[i] + "': not an archive.", Project.MSG_DEBUG);
                    continue;
                }
                log("Manage the archive '" + filenames[i] + "'.", Project.MSG_DEBUG);
                String sn = jarfile.getName();
                //remove the extension (.jar, .rar, ...)
                int idx = sn.lastIndexOf('.');
                if (idx != -1) {
                    sn = sn.substring(0,idx);
                }
                final String ext = "package-list";
                File packageList;
                String pf;
                if (flatten) {
                    if (isolate) {
                    } else {
                    }
                } else {
                    String path = filenames[i];
                    idx = path.lastIndexOf('.');
                    if (idx != -1) {
                        path = path.substring(0, idx);
                    }
                    if (isolate) {
                    } else {
                    }
                }
                if (isolate) {
                    if (flatten) {
                        pf = sn + File.separatorChar + ext;
                    } else {
                        String path = filenames[i];
                        idx = path.lastIndexOf('.');
                        if (idx != -1) {
                            path = path.substring(0, idx);
                        }
                        pf = path + File.separatorChar + ext;
                    }
                } else {
                    pf = (flatten ? ext : filenames[i]);
                }
                packageList = new File(output, pf);
                //check if it is needed to generate
                FileSet fs = new FileSet();
                fs.setDir(jarfile.getParentFile());
                fs.setIncludes(jarfile.getName());
                UpToDate u = new UpToDate();
                u.setTaskName(getTaskName());
                u.setProject(getProject());
                u.addSrcfiles(fs);
                u.setTargetFile(packageList);
                boolean generate = !u.eval();
                if (generate) {
                    File parent = packageList.getParentFile();
                    if (!parent.exists() && !parent.mkdirs()) {
                        throw new BuildException("Impossible to create the directory "
                                + parent.getAbsolutePath());
                    }
                    if (packageList.exists() && !packageList.delete()) {
                        throw new BuildException("Impossible to update the file "
                                + packageList.getAbsolutePath());
                    }
                    if (!packageList.createNewFile()) {
                        throw new BuildException("Impossible to create the file "
                                + packageList.getAbsolutePath());
                    }
                    if (!hasGenerate) {
                        hasGenerate = true;
                        log("Create " + ext + " file into the directory: '" + output.getAbsolutePath() + "'",
                                Project.MSG_INFO);
                    }
                    log("\t- " + pf, Project.MSG_INFO);

                    Enumeration en = archive.entries();
                    while(en.hasMoreElements()) {
                        ZipEntry je = (ZipEntry) en.nextElement();
                        if (je.getName().endsWith("/")
                                && !je.getName().startsWith("META-INF")) {
                            // add directory only
                            String packName = je.getName()
                                    .substring(0, je.getName().length() - 1);
                            packName = packName.replace(File.separatorChar, '.');
                            packages.add(packName);
                        }
                    }
                    FileWriter fw = new FileWriter(packageList);
                    Iterator it = packages.iterator();
                    while(it.hasNext()) {
                        String packName = (String) it.next();
                        log("\t-package: " + packName, Project.MSG_DEBUG);
                        fw.write(packName + "\n");
                    }
                    fw.close();
                }
            } catch (BuildException e) {
                e.printStackTrace();
            } catch (IOException e) {
                throw new BuildException("Impossible to manage the file "
                        + filenames[i]);
            }
		}
	}
}
