/*******************************************************************************
 * Copyright (c) 2001, 2005 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
 *******************************************************************************/
package org.eclipse.jst.j2ee.commonarchivecore.internal.helpers;



import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.jar.Attributes;

import org.eclipse.jst.j2ee.commonarchivecore.internal.util.ArchiveUtil;


/**
 * Helper class for manifest files
 */
public class ArchiveManifestImpl extends java.util.jar.Manifest implements org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifest {
	/**
	 * ArchiveManifest constructor comment.
	 */
	public ArchiveManifestImpl() {
		super();
	}

	/**
	 * ArchiveManifest constructor comment.
	 * 
	 * @param is
	 *            java.io.InputStream
	 * @throws java.io.IOException
	 *             The exception description.
	 */
	public ArchiveManifestImpl(java.io.InputStream is) throws java.io.IOException {
		super(is);
	}

	/**
	 * ArchiveManifest constructor comment.
	 * 
	 * @param man
	 *            java.util.jar.Manifest
	 */
	public ArchiveManifestImpl(java.util.jar.Manifest man) {
		super(man);
	}

	/**
	 * Creates a new manifest entry (attributes) for the given name
	 */
	public void addEntry(String entryName) {
		Attributes attr = new Attributes();
		addEntry(entryName, attr);
	}

	public void addEntry(String entryName, Attributes attr) {
		getEntries().put(entryName, attr);
	}

	/**
	 * Adds the key/value pair to the attributes for the given entry name; if the entry does not
	 * exist, creates a new attributes
	 */
	public void addEntryAttribute(String entryName, String key, String value) {
		Attributes attr = getAttributes(entryName);
		if (attr == null)
			addEntry(entryName);
		attr = getAttributes(entryName);
		attr.putValue(key, value);
	}

	public void addVersionIfNecessary() {
		//This is a hack because of the fact that the manifest does not serialize correctly if
		//The version is not set. In addition to saves, the serialization is used for copy
		if (getManifestVersion() == null || getManifestVersion().equals(""))//$NON-NLS-1$
			setManifestVersion("1.0");//$NON-NLS-1$
	}

	/**
	 * @see com.ibm.etools.archive.ArchiveManifest
	 */
	public void appendClassPath(java.lang.String extension) {
		String classPath = getClassPath();
		if (classPath != null)
			setClassPath(classPath + " " + extension);//$NON-NLS-1$
		else
			setClassPath(extension);
	}

	/**
	 * @see com.ibm.etools.archive.ArchiveManifest
	 */
	public java.lang.String getClassPath() {
		return ArchiveUtil.getValueIgnoreKeyCase(Attributes.Name.CLASS_PATH.toString(), getMainAttributes());
	}

	/**
	 * @see com.ibm.etools.archive.ArchiveManifest
	 */
	public java.lang.String[] getClassPathTokenized() {
		String classPath = getClassPath();
		if (classPath == null)
			return new String[0];
		return org.eclipse.jst.j2ee.commonarchivecore.internal.util.ArchiveUtil.getTokens(classPath);
	}

	public String getEntryAttribute(String entryName, String key) {
		Attributes attr = getAttributes(entryName);
		if (attr == null)
			return null;
		return attr.getValue(key);
	}

	public String getMainClass() {
		return ArchiveUtil.getValueIgnoreKeyCase(Attributes.Name.MAIN_CLASS.toString(), getMainAttributes());
	}

	public String getManifestVersion() {
		return getMainAttributes().getValue(Attributes.Name.MANIFEST_VERSION);
	}

	/**
	 * @see com.ibm.etools.archive.ArchiveManifest
	 */
	public void mergeClassPath(java.lang.String[] classPathEntries) {
		StringBuffer sb = new StringBuffer();
		java.util.List existing = java.util.Arrays.asList(getClassPathTokenized());
		String cp = getClassPath();
		if (cp != null)
			sb.append(cp);
		boolean empty = cp == null || "".equals(cp); //$NON-NLS-1$
		for (int i = 0; i < classPathEntries.length; i++) {
			if (!existing.contains(classPathEntries[i])) {
				if (!empty)
					sb.append(" "); //$NON-NLS-1$
				else
					empty = false;
				sb.append(classPathEntries[i]);
			}
		}
		setClassPath(sb.toString());
	}

	public void removeEntry(String entryName) {
		getEntries().remove(entryName);
	}

	public void removeEntryAttribute(String entryName, Object key) {
		Attributes attr = getAttributes(entryName);
		if (attr != null)
			attr.remove(key);
	}

	/**
	 * @see com.ibm.etools.archive.ArchiveManifest
	 */
	public void setClassPath(java.lang.String aSpaceDelimitedPath) {
		Attributes attributes = getMainAttributes();
		if (aSpaceDelimitedPath == null)
			attributes.remove(Attributes.Name.CLASS_PATH);
		else
			attributes.putValue(Attributes.Name.CLASS_PATH.toString(), aSpaceDelimitedPath);
	}

	/**
	 * @see com.ibm.etools.archive.ArchiveManifest
	 */
	public void setMainClass(java.lang.String className) {
		Attributes attributes = getMainAttributes();
		if (className == null)
			attributes.remove(Attributes.Name.MAIN_CLASS);
		else
			attributes.putValue(Attributes.Name.MAIN_CLASS.toString(), className);
	}

	/**
	 * @see com.ibm.etools.archive.ArchiveManifest
	 */
	public void setManifestVersion(java.lang.String version) {
		Attributes attributes = getMainAttributes();
		attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), version);
	}

	/**
	 * Writes the Manifest to the specified OutputStream, splitting each classpath entry on a line
	 * by itself.
	 * 
	 * @param out
	 *            the output stream
	 * @exception IOException
	 *                if an I/O error has occurred
	 */
	public void writeSplittingClasspath(OutputStream out) throws IOException {
		DataOutputStream dos = new DataOutputStream(out);
		// Write out the main attributes for the manifest
		writeMainSplittingClasspath(getMainAttributes(), dos);
		// Now write out the pre-entry attributes
		Iterator it = getEntries().entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry e = (Map.Entry) it.next();
			StringBuffer buffer = new StringBuffer("Name: "); //$NON-NLS-1$
			buffer.append((String) e.getKey());
			buffer.append("\r\n"); //$NON-NLS-1$
			localMake72Safe(buffer);
			dos.writeBytes(buffer.toString());
			write((Attributes) e.getValue(), dos);
		}
		dos.flush();
	}

	/*
	 * Writes the current attributes to the specified data output stream. XXX Need to handle UTF8
	 * values and break up lines longer than 72 bytes
	 * 
	 * @see Attributes#write
	 */
	protected void write(Attributes attributes, DataOutputStream os) throws IOException {
		Iterator it = attributes.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry e = (Map.Entry) it.next();
			StringBuffer buffer = new StringBuffer(((Attributes.Name) e.getKey()).toString());
			buffer.append(": "); //$NON-NLS-1$
			buffer.append((String) e.getValue());
			buffer.append("\r\n"); //$NON-NLS-1$
			localMake72Safe(buffer);
			os.writeBytes(buffer.toString());
		}
		os.writeBytes("\r\n"); //$NON-NLS-1$
	}

	/*
	 * Writes the current attributes to the specified data output stream, make sure to write out the
	 * MANIFEST_VERSION or SIGNATURE_VERSION attributes first.
	 * 
	 * @see Attributes#writeMain
	 */
	protected void writeMainSplittingClasspath(Attributes attributes, DataOutputStream out) throws IOException {
		// write out the *-Version header first, if it exists
		String vername = Attributes.Name.MANIFEST_VERSION.toString();
		String version = attributes.getValue(vername);
		if (version == null) {
			vername = Attributes.Name.SIGNATURE_VERSION.toString();
			version = attributes.getValue(vername);
		}

		if (version != null) {
			out.writeBytes(vername + ": " + version + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$
		}

		// write out all attributes except for the version
		// we wrote out earlier
		Iterator it = attributes.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry e = (Map.Entry) it.next();
			String name = ((Attributes.Name) e.getKey()).toString();
			if ((version != null) && !(name.equalsIgnoreCase(vername))) {
				if (name.equalsIgnoreCase(Attributes.Name.CLASS_PATH.toString())) {
					writeSplit(out, name, (String) e.getValue());
					continue;
				}
				StringBuffer buffer = new StringBuffer(name);
				buffer.append(": "); //$NON-NLS-1$
				buffer.append((String) e.getValue());
				buffer.append("\r\n"); //$NON-NLS-1$
				localMake72Safe(buffer);
				out.writeBytes(buffer.toString());
			}
		}
		out.writeBytes("\r\n"); //$NON-NLS-1$
	}

	protected void writeSplit(DataOutputStream out, String name, String value) throws IOException {
		StringTokenizer tok = new StringTokenizer(value);
		int inc = 0;
		while (tok.hasMoreTokens()) {
			StringBuffer buffer = null;
			if (inc == 0) {
				buffer = new StringBuffer(name);
				buffer.append(": "); //$NON-NLS-1$
			} else {
				buffer = new StringBuffer();
				buffer.append(' ');
			}
			buffer.append(tok.nextToken());
			if (tok.countTokens() > 0)
				buffer.append(" \r\n"); //$NON-NLS-1$
			else
				buffer.append("\r\n"); //$NON-NLS-1$
			localMake72Safe(buffer);
			out.writeBytes(buffer.toString());
			inc++;
		}
	}

	/**
	 * Adds line breaks to enforce a maximum 72 bytes per line.
	 */
	protected static void localMake72Safe(StringBuffer line) {
		int length = line.length();
		if (length > 72) {
			int index = 70;
			while (index - 1 < length) {
				line.insert(index, "\r\n "); //$NON-NLS-1$
				index += 72;
				length += 3;
			}
		}
		return;
	}

	public String getImplementationVersion() {
		return getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION);
	}

	public void setImplemenationVersion(String version) {
		Attributes attributes = getMainAttributes();
		attributes.putValue(Attributes.Name.IMPLEMENTATION_VERSION.toString(), version);
	}


}
