/* JFox, the OpenSource J2EE Application Server
 *
 * Distributable under GNU LGPL license by gun.org
 * more details please visit http://www.huihoo.org/jfox
 */

package org.jfox.framework.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
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;
import java.util.zip.ZipEntry;

/**
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class JarUtils {

    /**
     * Dump the contents of a JarArchive to the dpecified destination.
     */
    public static void extract(File jarFile, File dest) throws IOException {
        if(!dest.exists()) {
            dest.mkdirs();
        }
        if(!dest.isDirectory()) {
            throw new IOException("Destination must be a directory.");
        }
        JarInputStream jin = new JarInputStream(new FileInputStream(jarFile));
        byte[] buffer = new byte[1024];

        ZipEntry entry = jin.getNextEntry();
        while(entry != null) {
            String fileName = entry.getName();
            if(fileName.charAt(fileName.length() - 1) == '/') {
                fileName = fileName.substring(0, fileName.length() - 1);
            }
            if(fileName.charAt(0) == '/') {
                fileName = fileName.substring(1);
            }
            if(File.separatorChar != '/') {
                fileName = fileName.replace('/', File.separatorChar);
            }
            File file = new File(dest, fileName);
            if(entry.isDirectory()) {
                // make sure the directory exists
                file.mkdirs();
                jin.closeEntry();
            }
            else {
                // make sure the directory exists
                File parent = file.getParentFile();
                if(parent != null && !parent.exists()) {
                    parent.mkdirs();
                }

                // dump the file
                OutputStream out = new FileOutputStream(file);
                int len = 0;
                while((len = jin.read(buffer, 0, buffer.length)) != -1) {
                    out.write(buffer, 0, len);
                }
                out.flush();
                out.close();
                jin.closeEntry();
                file.setLastModified(entry.getTime());
            }
            entry = jin.getNextEntry();
        }
        /* Explicity write out the META-INF/MANIFEST.MF so that any headers such
        as the Class-Path are see for the unpackaged jar
        */
        Manifest mf = jin.getManifest();
        if(mf != null) {
            File file = new File(dest, "META-INF/MANIFEST.MF");
            File parent = file.getParentFile();
            if(parent.exists() == false) {
                parent.mkdirs();
            }
            OutputStream out = new FileOutputStream(file);
            mf.write(out);
            out.flush();
            out.close();
        }
        jin.close();
    }

    /**
     * use URLClassLoader.findResource, this method will not find resource use parent
     *
     * @param loader
     * @param descriptorName
     * @return null if no such descriptor
     */
    public static URL getDescriptor(URLClassLoader loader, String descriptorName) {
        return loader.findResource(descriptorName);
    }

    public static Manifest getManifest(File jarFile) throws IOException {
        return new JarFile(jarFile).getManifest();
    }

    public static String[] getClassPathFromManifest(File jarFile) throws IOException {
        Manifest mani = getManifest(jarFile);
        Attributes attrs = mani.getMainAttributes();
        String cpString = attrs.getValue("Class-Path");
        if(cpString == null || cpString.trim().equals("")) {
            return new String[0];
        }
        else {
            StringTokenizer st = new StringTokenizer(cpString);
            List cpList = new ArrayList();
            while(st.hasMoreTokens()) {
                cpList.add(st.nextToken());
            }
            return (String[]) cpList.toArray(new String[cpList.size()]);
        }
    }

    public static void main(String[] args) {

    }
}



