/*******************************************************************************
 * 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.common.internal.modulecore.util;



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

import com.ibm.icu.util.StringTokenizer;


/**
 * Helper class for manifest files
 */
public class ArchiveManifestImpl extends java.util.jar.Manifest implements 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 ManifestUtilities.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 ManifestUtilities.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 ManifestUtilities.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;
        }
        final byte[] utf8 = str.getBytes( "UTF-8" ); //$NON-NLS-1$
        return new String( utf8, 0, 0, utf8.length );
    }

}
