/*******************************************************************************
 * Copyright (c) 2007, 2009 IBM Corporation and others. All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Eclipse Public License v1.0 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: IBM Corporation - initial API and implementation
 * This file originally came from 'Eclipse Orbit' project then adapted to use 
 * in WTP and improved to use 'Manifest' to read manifest.mf, instead of reading 
 * it as a properties file.
 ******************************************************************************/
package org.eclipse.helios.tests;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.tools.ant.BuildException;
import org.eclipse.internal.provisional.equinox.p2.jarprocessor.JarProcessor;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.BundleException;

/**
 * @since 3.3
 */
public class BREETest {

    private static final Object            PROPERTY_BUNDLE_REQUIRED_EXECUTION_ENVIRONMENT = "Bundle-RequiredExecutionEnvironment";
    private static final FullJarNameParser nameParser                                     = new FullJarNameParser();

    public static void main(String[] args) {

        BREETest testlayout = new BREETest();
        testlayout.setDirectoryToCheck("D:\\temp\\staging\\aggregate");
        try {
            testlayout.testBREESettingRule();
        }
        catch (IOException e) {
            e.printStackTrace();
        }

    }

    private String directoryToCheck;
    private String tempWorkingDir;
    private String outputDirectory;


    public String getDirectoryToCheck() {
        return directoryToCheck;
    }

    public void setDirectoryToCheck(String bundleDirToCheck) {
        this.directoryToCheck = bundleDirToCheck;
    }

    public boolean testBREESettingRule() throws IOException {

        String property = getDirectoryToCheck();
        if (property == null) {
            throw new BuildException("Need to set input directory to check against.");
        }
        String bundleDirectory = null;
        if (property.endsWith("/")) {
            bundleDirectory = property + "plugins";
        }
        else {
            bundleDirectory = property + "/plugins";
        }
        File inputdir = new File(bundleDirectory);
        if (!(inputdir.exists() && inputdir.isDirectory())) {
            throw new BuildException("bundle direcotry (" + bundleDirectory + ") must be an existing directory.");
        }

        boolean failuresOccured;

        failuresOccured = checkBundleBREE(inputdir);

        return failuresOccured;
    }

    private boolean checkBundleBREE(File inputdir) throws IOException {
        // reset/initialize errors
        InputStream propertyStream = this.getClass().getResourceAsStream("exceptions.properties");
        Properties breeExceptionProperties = new Properties();
        String breeExceptions = "";
        try {
            breeExceptionProperties.load(propertyStream);
            breeExceptions = breeExceptionProperties.getProperty("breeExceptions");
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if (propertyStream != null) {
                try {
                    propertyStream.close();
                }
                catch (IOException e) {
                    // would be unusual to get here?
                    e.printStackTrace();
                }
            }
        }
// List errors = new ArrayList();
        Map javaWithBree = new HashMap();
        List nonjavaWithBree = new ArrayList();
        List javaWithoutBree = new ArrayList();
        int nonJavaNoBREE = 0;
        boolean failuresOccured = false;
        File[] children = inputdir.listFiles(new JARFileNameFilter());
        int totalsize = children.length;
        int checked = 0;
        for (int i = 0; i < totalsize; i++) {
            File child = children[i];
            String name = child.getName();
            // with Helios, since we have all jars on file system, in addition to pack.gz files,
            // we do not need to check the pack.gz ones. We can assume they are idential to their .jar version.
// if (child.getName().toLowerCase().endsWith(EXTENSION_PACEKD_JAR)) {
// child = getFileFromPACKEDJAR(child);
// }
// if (child != null) {

            String bundleName = getBundleName(name);
            if ((bundleName != null) && !breeExceptions.contains(bundleName)) {
                checked++;
                String bree = getBREEFromJAR(child);
                if ((bree != null) && (bree.length() > 0)) {
                    // has BREE, confirm is java file
                    if (containsJava(child)) {
                        incrementCounts(javaWithBree, bree);
                    }
                    else {
                        trackFalseInclusions(nonjavaWithBree, child);
                        failuresOccured = true;
                    }
                }
                else {
                    // no BREE, confirm is non-java
                    if (containsJava(child)) {
                        trackOmissions(javaWithoutBree, child);
                        failuresOccured = true;
                    }
                    else {
                        nonJavaNoBREE++;
                    }
                }
            }

        }
        printreport(javaWithBree, nonjavaWithBree, javaWithoutBree, nonJavaNoBREE, totalsize, checked);

        return failuresOccured;
    }

    private void printreport(Map javaWithBree, List nonjavaWithBree, List javaWithoutBree, int nonJavaNoBREE, int totalsize, int checked) throws IOException {
        String outputFilename = "breedata.txt";

        ReportWriter reportWriter = new ReportWriter(getOutputDirectory(), outputFilename);
        try {
            reportWriter.writeln("   Checked " + checked + " of " + totalsize + ".");

            reportWriter.writeln("  Bundles with correct BREE presence");
            reportWriter.writeln("   Java with BREE: " + totalCount(javaWithBree));
            reportWriter.writeln("   Non Java without BREE:" + nonJavaNoBREE);
            reportWriter.writeln();
            reportWriter.writeln("   Distribution of BREEs in Java Bundles ");
            Set allBREEs = javaWithBree.keySet();
            for (Object object : allBREEs) {
                Integer count = (Integer) javaWithBree.get(object);
                reportWriter.writeln("   " + count.intValue() + "  " + object);
            }
            reportWriter.writeln();
            reportWriter.writeln("  Bundles with incorrect BREE");
            reportWriter.writeln();
            reportWriter.writeln("    Java Bundles without a BREE: " + javaWithoutBree.size());
            Collections.sort(javaWithoutBree);
            for (Iterator iterator = javaWithoutBree.iterator(); iterator.hasNext();) {
                Object object = iterator.next();
                reportWriter.writeln("       " + object);
            }
            reportWriter.writeln();
            reportWriter.writeln("    Non Java Bundles with a BREE: " + nonjavaWithBree.size());
            Collections.sort(nonjavaWithBree);
            for (Iterator iterator = nonjavaWithBree.iterator(); iterator.hasNext();) {
                Object object = iterator.next();
                reportWriter.writeln("       " + object);
            }
        }
        finally {
            reportWriter.close();
        }
    }

    public String getOutputDirectory() {
        if (outputDirectory == null) {
            outputDirectory = System.getProperty("user.dir");
        }
        return outputDirectory;
    }

    private int totalCount(Map javaWithBree) {

        Collection allCounts = javaWithBree.values();
        int total = 0;
        for (Iterator iterator = allCounts.iterator(); iterator.hasNext();) {
            Integer count = (Integer) iterator.next();
            total = total + count.intValue();
        }
        return total;
    }

    private void trackOmissions(List javaWithoutBree, File child) {
        javaWithoutBree.add(child.getName());

    }

    private void trackFalseInclusions(List list, File child) {
        list.add(child.getName());

    }

    private void incrementCounts(Map breeMap, String bree) {
        Integer count = (Integer) breeMap.get(bree);
        if (count == null) {
            breeMap.put(bree, new Integer(1));
        }
        else {
            breeMap.put(bree, increment(count));
        }

    }

    private Integer increment(Integer count) {
        return new Integer(count.intValue() + 1);
    }

    private boolean containsJava(File jarfile) {
        // We assume the file is a 'jar' file.
        boolean containsJava = false;
        JarFile jar = null;
        try {
            jar = new JarFile(jarfile, false, ZipFile.OPEN_READ);
            Enumeration<JarEntry> entries = jar.entries();
            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                if (entry.getName().endsWith(".class")) {
                    containsJava = true;
                    break;
                }
                else if (entry.getName().endsWith(".jar")) {
                    InputStream input = jar.getInputStream(entry);
                    if (containsJava(input)) {
                        containsJava = true;
                        break;
                    }
                }
            }

        }
        catch (IOException e) {
            System.out.println(e.getMessage());
        }
        finally {
            if (jar != null) {
                try {
                    jar.close();
                }
                catch (IOException e) {
                    // ignore
                }
            }
        }
        return containsJava;
    }

    private boolean containsJava(InputStream input) {
        // We assume the file is a 'jar' file.
        boolean containsJava = false;

        try {
            JarInputStream jarInputStream = new JarInputStream(input);
            while (jarInputStream.available() > 0) {
                ZipEntry entry = jarInputStream.getNextEntry();
                if (entry != null) {
                    if (entry.getName().endsWith(".class")) {
                        containsJava = true;
                        break;
                    }
                }
            }

        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if (input != null) {
                try {
                    input.close();
                }
                catch (IOException e) {
                    // ignore
                }
            }
        }
        return containsJava;
    }

    private String getBundleName(String fullname) {
        String result = null;
        boolean parsable = nameParser.parse(fullname);
        if (parsable) {
            result = nameParser.getProjectString();
        }
        return result;
    }

    /*
     * Return the bundle id from the manifest pointed to by the given input
     * stream.
     */
    private String getBREEFromManifest(InputStream input, String path) {
        String bree = null;
        try {
            Map attributes = ManifestElement.parseBundleManifest(input, null);
            bree = (String) attributes.get(PROPERTY_BUNDLE_REQUIRED_EXECUTION_ENVIRONMENT);
        }
        catch (BundleException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if (input != null) {
                try {
                    input.close();
                }
                catch (IOException e) {
                    // ignore
                }
            }
        }

        return bree;
    }

    /*
     * The given file points to a bundle contained in an archive. Look into
     * the bundle manifest file to find the bundle identifier.
     */
    File getFileFromPACKEDJAR(File file) {
// String id = null;
// JarFile jar = null;
        File tmpjar = null;
        try {
            JarProcessor jarprocessor = JarProcessor.getUnpackProcessor(null);
            jarprocessor.setWorkingDirectory(getTempWorkingDir());
            tmpjar = jarprocessor.processJar(file);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return tmpjar;
    }

    public String getTempWorkingDir() {
        return tempWorkingDir;
    }

    public void setTempWorkingDir(String tempWorkingDir) {
        this.tempWorkingDir = tempWorkingDir;
    }

    /*
     * The given file points to a bundle contained in an archive. Look into
     * the bundle manifest file to find the bundle identifier.
     */
    private String getBREEFromJAR(File file) {
        InputStream input = null;
        JarFile jar = null;
        try {
            jar = new JarFile(file, false, ZipFile.OPEN_READ);
            JarEntry entry = jar.getJarEntry(JarFile.MANIFEST_NAME);
            if (entry == null) {
                // addError("Bundle does not contain a MANIFEST.MF file: " +
                // file.getAbsolutePath());
                return null;
            }
            input = jar.getInputStream(entry);
            return getBREEFromManifest(input, file.getAbsolutePath());
        }
        catch (IOException e) {
            System.out.println(e.getMessage());
            // addError(e.getMessage());
            return null;
        }
        finally {
            if (input != null) {
                try {
                    input.close();
                }
                catch (IOException e) {
                    // ignore
                }
            }
            if (jar != null) {
                try {
                    jar.close();
                }
                catch (IOException e) {
                    // ignore
                }
            }
        }
    }

    public void setOutputDirectory(String outputDirectory) {
        this.outputDirectory = outputDirectory;
    }
}
