/*******************************************************************************
 * 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.galileo.tests;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.PatternSyntaxException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

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;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * @since 3.3
 */
public class TestLayoutTest extends TestCase {

	private static final String EXTENSION_JAR = ".jar";
	private static final String EXTENSION_PACEKD_JAR = ".pack.gz";
	private static final String EXTENSION_ZIP = ".zip";
	private static final String PROPERTY_BUNDLE_ID = "Bundle-SymbolicName";
	private String configFilename = "config.properties";
	private static final String KEY_DFT_BIN_JAR = "default.binary.jar";
	private static final String KEY_DFT_SRC_JAR = "default.source.jar";
	private static final String KEY_DFT_BIN_ZIP = "default.binary.zip";
	private static final String KEY_DFT_SRC_ZIP = "default.source.zip";
	private static final String KEY_DFT_FEATURE = "default.feature";
	private Properties config;
	private List errors = new ArrayList();
	private String directoryToCheck;
	private String tempWorkingDir;

	public static void main(String[] args) {
		System.out.println("start TestLayoutTest main");
		TestLayoutTest testlayout = new TestLayoutTest();
		testlayout.setDirectoryToCheck("D:\\temptest");
		testlayout.setTempWorkingDir("D:/temp");
		testlayout.testFeatureLayout();
		testlayout.testBundleLayout();

	}

	public static Test suite() {
		return new TestSuite(TestLayoutTest.class);
	}

	private void addError(String message) {
		errors.add(message);
	}

	public boolean testBundleLayout() {

		errors = new ArrayList();
		boolean failuresOccured = false;
		String property = getDirectoryToCheck();
		assertNotNull("Need to set input directory to check against.", property);
		String bundleDirectory = null;
		if (property.endsWith("/")) {
			bundleDirectory = property + "plugins";
		}
		else {
			bundleDirectory = property + "/plugins";
		}
		File inputdir = new File(bundleDirectory);
		assertTrue("bundle direcotry (" + bundleDirectory + ") must be an existing directory.", inputdir.exists() && inputdir.isDirectory());
		File[] children = inputdir.listFiles();
		int totalsize = children.length;
		int checked = 0;
		for (int i = 0; i < children.length; i++) {
			File child = children[i];
			if (child.getName().toLowerCase().endsWith(EXTENSION_PACEKD_JAR)) {
				child = getFileFromPACKEDJAR(child);
			}
			if (child != null) {
				String id = getBundleId(child);
				if (id != null) {
					if (id.endsWith(".source") || id.endsWith(".infopop") || id.endsWith(".doc.user") || id.endsWith(".doc") || id.endsWith(".doc.isv") || id.endsWith(".doc.dev") || id.endsWith(".doc.api") || id.endsWith("standard.schemas") || id.endsWith(".branding")) {
						processBundle(child, getExpected(id, true, child.getName().endsWith(EXTENSION_ZIP)));
						checked++;
					}
					else {
						processBundle(child, getExpected(id, false, child.getName().endsWith(EXTENSION_ZIP)));
						checked++;
					}
				}
			}
		}
		System.out.println("   Checked " + checked + " of " + totalsize + ".");
		System.out.println("   Errors found: " + errors.size());
		
		if (errors.size() > 0) {
			Collections.sort(errors);
			for (Iterator iter = errors.iterator(); iter.hasNext();) {
				System.out.println(iter.next());
			}
			System.out.println("Errors in bundle layout. Check error log for details.");
			failuresOccured = true;
		}
		return failuresOccured;
	}

	/*
	 * Check the configuration file and return a set of regular expressions
	 * which match the list of files that are expected to be in the bundle.
	 */
	private Set getExpected(String id, boolean source, boolean zip) {
		// is the config cached?
		if (config == null) {
			getConfig();
		}
		String line = config.getProperty(id);
		if (line == null) {
			if (source)
				line = zip ? config.getProperty(KEY_DFT_SRC_ZIP) : config.getProperty(KEY_DFT_SRC_JAR);
			else
				line = zip ? config.getProperty(KEY_DFT_BIN_ZIP) : config.getProperty(KEY_DFT_BIN_JAR);
		}
		if (line == null)
			fail("Unable to load settings for: " + id);
		Set result = new HashSet();
		for (StringTokenizer tokenizer = new StringTokenizer(line, ","); tokenizer.hasMoreTokens();)
			result.add(tokenizer.nextToken().trim());
		return result;
	}

	private Set getFeatureExpected(String id, boolean source, boolean zip) {
		// is the config cached?
		if (config == null) {
			getConfig();
		}
		String line = config.getProperty(id);
		if (line == null) {
			line = config.getProperty(KEY_DFT_FEATURE);
		}
		if (line == null)
			fail("Unable to load settings for: " + id);
		Set result = new HashSet();
		for (StringTokenizer tokenizer = new StringTokenizer(line, ","); tokenizer.hasMoreTokens();)
			result.add(tokenizer.nextToken().trim());
		return result;
	}

	private void getConfig() {
		config = new Properties();
		InputStream input = null;
		try {
			// if we can read this file, it's been set by caller
			File configFile = new File(getConfigFilename());
			if (configFile.exists()) {
				input = new FileInputStream(configFile);
			}
			else {
				// else, use the default we "ship"
				input = this.getClass().getResourceAsStream(getConfigFilename());
			}

			assertNotNull("Unable to load configuration file.", input);
			config.load(input);
		}
		catch (IOException e) {
			e.printStackTrace();
			fail(e.getMessage());
		}
		finally {
			try {
				if (input != null)
					input.close();
			}
			catch (IOException e) {
				// ignore
			}
		}
	}

	/*
	 * Process the bundle at the specified location, with the given set of
	 * expected results.
	 */
	private void processBundle(File file, Set expected) {
		if (file.isDirectory()) {
			String[] array = (String[]) expected.toArray(new String[expected.size()]);
			processDir("", file, array);
			for (int i = 0; i < array.length; i++)
				if (array[i] != null)
					addError("Missing pattern: " + array[i] + " in dir: " + file.getAbsolutePath());
		}
		else
			processArchive(file, (String[]) expected.toArray(new String[expected.size()]));
	}

	private void processFeature(File file, Set expected) {
		if (file.isDirectory()) {
			String[] array = (String[]) expected.toArray(new String[expected.size()]);
			processDir("", file, array);
			for (int i = 0; i < array.length; i++)
				if (array[i] != null)
					addError("Missing pattern: " + array[i] + " in dir: " + file.getAbsolutePath());
		}
		else
			processArchive(file, (String[]) expected.toArray(new String[expected.size()]));
	}

	/*
	 * The bundle is an archive. Make sure it has the right contents.
	 */
	private void processArchive(File file, String[] expected) {
		ZipFile zip = null;
		try {
			zip = new ZipFile(file, ZipFile.OPEN_READ);
			for (Enumeration e = zip.entries(); e.hasMoreElements();) {
				ZipEntry entry = (ZipEntry) e.nextElement();
				String name = entry.getName();
				for (int i = 0; i < expected.length; i++) {
					String pattern = expected[i];
					if (pattern == null)
						continue;
					try {
						if (name.matches(pattern))
							expected[i] = null;
					}
					catch (PatternSyntaxException ex) {
						ex.printStackTrace();
						fail(ex.getMessage());
					}
				}
			}
			for (int i = 0; i < expected.length; i++) {
				if (expected[i] != null)
					addError("Missing pattern: " + expected[i] + " in file: " + file.getAbsolutePath());
			}
		}
		catch (IOException e) {
			e.printStackTrace();
			fail(e.getMessage());
		}
		finally {
			if (zip != null)
				try {
					zip.close();
				}
				catch (IOException e) {
					// ignore
				}
		}
	}


	/*
	 * The bundle is in a directory.
	 */
	private void processDir(String root, File dir, String[] expected) {
		File[] children = dir.listFiles();
		for (int index = 0; index < children.length; index++) {
			File child = children[index];
			String name = root.length() == 0 ? child.getName() : root + '/' + child.getName();
			if (child.isDirectory()) {
				processDir(name, child, expected);
				continue;
			}
			for (int i = 0; i < expected.length; i++) {
				String pattern = expected[i];
				if (pattern == null)
					continue;
				try {
					if (name.matches(pattern))
						expected[i] = null;
				}
				catch (PatternSyntaxException ex) {
					// ex.printStackTrace();
					addError(ex.getMessage());
					continue;
				}
			}
		}
	}

	/*
	 * Return the bundle id from the manifest pointed to by the given input
	 * stream.
	 */
	private String getBundleIdFromManifest(InputStream input, String path) {
		String id = null;
		try {
			Map attributes = ManifestElement.parseBundleManifest(input, null);
			id = (String) attributes.get(PROPERTY_BUNDLE_ID);
			if (id == null || id.length() == 0) {
				addError("BundleSymbolicName header not set in manifest for bundle: " + path);
			}
			else {
				// identifier can be followed by attributes such as
				// 'singleton'
				int pos = id.indexOf(';');
				if (pos > 0) {
					id = id.substring(0, pos);
				}
			}

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

		return id;
	}

	/*
	 * Return the bundle identifier for the bundle contained in the given
	 * archive/directory.
	 */
	private String getBundleId(File file) {
		String id = null;
		if (file.isDirectory())
			id = getBundleIdFromDir(file);
		else if (file.getName().toLowerCase().endsWith(EXTENSION_ZIP))
			id = getBundleIdFromZIP(file);
		else if (file.getName().toLowerCase().endsWith(EXTENSION_JAR))
			id = getBundleIdFromJAR(file);
		return id;
	}

	private String getBundleIdFromZIP(File file) {
		ZipFile zip = null;
		try {
			zip = new ZipFile(file);
			for (Enumeration e = zip.entries(); e.hasMoreElements();) {
				ZipEntry entry = (ZipEntry) e.nextElement();
				if (entry.getName().matches("^.*/" + JarFile.MANIFEST_NAME)) {
					InputStream input = zip.getInputStream(entry);
					try {
						return getBundleIdFromManifest(input, file.getAbsolutePath());
					}
					finally {
						try {
							input.close();
						}
						catch (IOException ex) {
							// ignore
						}
					}
				}
			}
		}
		catch (IOException ex) {
			// ex.printStackTrace();
			addError(ex.getMessage());
		}
		finally {
			try {
				zip.close();
			}
			catch (IOException ex) {
				// ignore
			}
		}
		addError("Bundle manifest (MANIFEST.MF) not found in bundle: " + file.getAbsolutePath());
		return null;
	}

	/*
	 * The given file points to an expanded bundle on disc. Look into the
	 * bundle manifest file to find the bundle identifier.
	 */
	private String getBundleIdFromDir(File dir) {
		String id = null;
		File manifestFile = new File(dir, JarFile.MANIFEST_NAME);
		if (!manifestFile.exists() || !manifestFile.isFile()) {
			addError("Bundle manifest (MANIFEST.MF) not found at: " + manifestFile.getAbsolutePath());
		}
		else {
			try {
				id = getBundleIdFromManifest(new FileInputStream(manifestFile), manifestFile.getAbsolutePath());
			}
			catch (FileNotFoundException e) {
				// e.printStackTrace();
				addError(e.getMessage());
			}
		}
		return id;
	}

	/*
	 * The given file points to a bundle contained in an archive. Look into
	 * the bundle manifest file to find the bundle identifier.
	 */
	private 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) {
			addError(e.getMessage());
			tmpjar = null;
		}
		return tmpjar;
	}

	public String getDirectoryToCheck() {
		return directoryToCheck;
	}

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

	public String getConfigFilename() {
		return configFilename;
	}

	public void setConfigFilename(String configFilename) {
		this.configFilename = configFilename;
	}

	/*
	 * The given file points to a bundle contained in an archive. Look into
	 * the bundle manifest file to find the bundle identifier.
	 */
	private String getBundleIdFromJAR(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 getBundleIdFromManifest(input, file.getAbsolutePath());
		}
		catch (IOException e) {
			// e.printStackTrace();
			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 String getTempWorkingDir() {
		return tempWorkingDir;
	}

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

	public boolean testFeatureLayout() {
		
		errors = new ArrayList();
		boolean failuresOccurred = false;
		String property = getDirectoryToCheck();
		assertNotNull("Need to set input directory to check against.", property);
		String featureDirectory = null;
		if (property.endsWith("/")) {
			featureDirectory = property + "features";
		}
		else {
			featureDirectory = property + "/features";
		}
		File inputdir = new File(featureDirectory);
		assertTrue("feature direcotry (" + featureDirectory + ") must be an existing directory.", inputdir.exists() && inputdir.isDirectory());
		File[] children = inputdir.listFiles();
		int totalsize = children.length;
		int checked = 0;
		for (int i = 0; i < children.length; i++) {
			File child = children[i];
			if (child.getName().toLowerCase().endsWith(EXTENSION_PACEKD_JAR)) {
				child = getFileFromPACKEDJAR(child);
			}
			if (child != null) {
				String id = getFeatureId(child);
				if (id != null) {
					processFeature(child, getFeatureExpected(id, true, child.getName().endsWith(EXTENSION_ZIP)));
					checked++;
				}
			}
		}
		System.out.println("   Checked " + checked + " of " + totalsize + ".");
		System.out.println("   Errors found: " + errors.size());
		if (errors.size() > 0) {
			Collections.sort(errors);
			for (Iterator iter = errors.iterator(); iter.hasNext();) {
				System.out.println(iter.next());
			}
			System.out.println("Errors in feature layout. Check error log for details.");
			failuresOccurred = true;
		}
		return failuresOccurred;

	}

	private String getFeatureId(File file) {
		String id = null;
		if (file.isDirectory()) {
			id = getFeatureIdFromDir(file);
		}
		else if (file.getName().toLowerCase().endsWith(EXTENSION_JAR)) {
			id = getFeatureIdFromJAR(file);
		}
		return id;
	}

	private String getFeatureIdFromJAR(File file) {
		InputStream input = null;
		JarFile jar = null;
		String id = null;
		try {
			jar = new JarFile(file, false, ZipFile.OPEN_READ);
			JarEntry entry = jar.getJarEntry("feature.xml");
			if (entry == null) {
				addError("Feature jar does not contain a feature.xml file: " + file.getAbsolutePath());
			}
			input = jar.getInputStream(entry);
			id = getFeatureFromFeatureXML(input);
		}
		catch (IOException e) {
			// e.printStackTrace();
			addError(e.getMessage());
		}
		catch (ParserConfigurationException e) {
			addError(e.getMessage());
		}
		catch (SAXException e) {
			addError(e.getMessage());
		}
		finally {
			if (input != null)
				try {
					input.close();
				}
				catch (IOException e) {
					// ignore
				}
			if (jar != null)
				try {
					jar.close();
				}
				catch (IOException e) {
					// ignore
				}
		}
		return id;
	}

	private String getFeatureIdFromDir(File dir) {
		String id = null;
		File featureFile = new File(dir, "feature.xml");
		if (!featureFile.exists() || !featureFile.isFile()) {
			addError("Feature.xml not found at: " + featureFile.getAbsolutePath());
		}
		else {
			id = getFeatureFromFeatureXML(featureFile);
		}
		return id;
	}

	private String getFeatureFromFeatureXML(File file) {
		Document document = getDOM(file);
		return getFeatureIdFromDOM(document);
	}

	private String getFeatureIdFromDOM(Document document) {
		String id = null;
		if (document != null) {
			NodeList featureElements = document.getElementsByTagName("feature");
			Element featureElement = null;
			if (featureElements.getLength() > 0) {
				Node featureNode = featureElements.item(0);
				if (featureNode instanceof Element) {
					featureElement = (Element) featureNode;
				}
			}
			if (featureElement != null) {
				NamedNodeMap aNamedNodeMap = featureElement.getAttributes();
				Node idAttribute = aNamedNodeMap.getNamedItem("id");
				id = idAttribute.getNodeValue();
			}
		}
		return id;
	}

	private String getFeatureFromFeatureXML(InputStream stream) throws ParserConfigurationException, SAXException, IOException {
		Document document = getDOM(stream);
		return getFeatureIdFromDOM(document);
	}

	private Document getDOM(File file) {

		Document aDocument = null;
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			InputSource inputSource = new InputSource(reader);
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			aDocument = builder.parse(inputSource);
		}
		catch (SAXException e) {
			e.printStackTrace();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		finally {
			if (reader != null) {
				try {
					reader.close();
				}
				catch (IOException e) {
					// ignore this one
				}
			}
		}

		if (aDocument == null) {
			String msg = "Error: could not parse xml in classpath file: " + file.getAbsolutePath();
			throw new BuildException(msg);
		}
		return aDocument;

	}

	private Document getDOM(InputStream stream) throws ParserConfigurationException, SAXException, IOException {

		Document aDocument = null;
		InputSource inputSource = new InputSource(stream);
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		aDocument = builder.parse(inputSource);

		return aDocument;

	}
}
