/*******************************************************************************
 * Copyright (c) 2001, 2006 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 com.ibm.icu.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 {
		try {
			read(is);
		} catch(Exception e){
			IOException ioe = new IOException(e.toString());
			ioe.initCause(e);
			throw ioe;
		}
	}

	/**
	 * 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 org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifest
	 */
	public void appendClassPath(java.lang.String extension) {
		String classPath = getClassPath();
		if (classPath != null)
			setClassPath(classPath + " " + extension);//$NON-NLS-1$
		else
			setClassPath(extension);
	}

	/**
	 * @see org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifest
	 */
	public java.lang.String getClassPath() {
		return ArchiveUtil.getValueIgnoreKeyCase(Attributes.Name.CLASS_PATH.toString(), getMainAttributes());
	}

	/**
	 * @see org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.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 org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.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 org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.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 org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.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 org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.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(toUtf8((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 = toUtf8(attributes.getValue(vername));
		if (version == null) {
			vername = Attributes.Name.SIGNATURE_VERSION.toString();
			version = toUtf8(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, toUtf8((String) e.getValue()));
					continue;
				}
				StringBuffer buffer = new StringBuffer(name);
				buffer.append(": "); //$NON-NLS-1$
				buffer.append(toUtf8((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;
			// bug 233801 - we are splitting every 72 bytes, but adding two bytes to the end of, 
			// and one space at the beginning of every line after the first
			while (index - 1 < length) {
				if (line.charAt(index) == ' ')
				{
					index--;
				}
				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);
	}
    
    /**
     * Encodes a double-byte string into UTF8 form. Every character in the
     * returned string represents one byte of the UTF8 encoding. 
     */
    
    private String toUtf8( final String str ) throws IOException
    {
        if( str == null )
        {
            return null;
        }
        else
        {
            final byte[] utf8 = str.getBytes( "UTF-8" );
            return new String( utf8, 0, 0, utf8.length );
        }
    }

}
