/* Manifest.java -- Reads, writes and manipulaties jar manifest files
   Copyright (C) 2000, 2004 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.util.jar;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

/**
 * Reads, writes and manipulaties jar manifest files.
 * XXX
 * 
 * @since 1.2
 * @author Mark Wielaard (mark@klomp.org)
 */
public class Manifest implements Cloneable
{
  // Fields

  /** The main attributes of the manifest (jar file). */
  private final Attributes mainAttr;

  /** A map of atrributes for all entries described in this Manifest. */
  private final Map entries;

  // Constructors

  /**
   * Creates a new empty Manifest.
   */
  public Manifest()
  {
    mainAttr = new Attributes();
    entries = new Hashtable();
  }

  /**
   * Creates a Manifest from the supplied input stream.
   *
   * @see #read(InputStream)
   * @see #write(OutputStream)
   *
   * @param in the input stream to read the manifest from
   * @exception IOException when an i/o exception occurs or the input stream
   * does not describe a valid manifest
   */
  public Manifest(InputStream in) throws IOException
  {
    this();
    read(in);
  }

  /**
   * Creates a Manifest from another Manifest.
   * Makes a deep copy of the main attributes, but a shallow copy of
   * the other entries. This means that you can freely add, change or remove
   * the main attributes or the entries of the new manifest without effecting
   * the original manifest, but adding, changing or removing attributes from
   * a particular entry also changes the attributes of that entry in the
   * original manifest.
   *
   * @see #clone()
   * @param man the Manifest to copy from
   */
  public Manifest(Manifest man)
  {
    mainAttr = new Attributes(man.getMainAttributes());
    entries = new Hashtable(man.getEntries());
  }

  // Methods

  /**
   * Gets the main attributes of this Manifest.
   */
  public Attributes getMainAttributes()
  {
    return mainAttr;
  }

  /**
   * Gets a map of entry Strings to Attributes for all the entries described
   * in this manifest. Adding, changing or removing from this entries map
   * changes the entries of this manifest.
   */
  public Map getEntries()
  {
    return entries;
  }

  /**
   * Returns the Attributes associated with the Entry.
   * <p>
   * Implemented as:
   * <code>return (Attributes)getEntries().get(entryName)</code>
   *
   * @param entryName the name of the entry to look up
   * @return the attributes associated with the entry or null when none
   */
  public Attributes getAttributes(String entryName)
  {
    return (Attributes) getEntries().get(entryName);
  }

  /**
   * Clears the main attributes and removes all the entries from the
   * manifest.
   */
  public void clear()
  {
    mainAttr.clear();
    entries.clear();
  }

  /**
   * XXX
   */
  public void read(InputStream in) throws IOException
  {
    BufferedReader br =
      new BufferedReader(new InputStreamReader(in, "8859_1"));
    read_main_section(getMainAttributes(), br);
    read_individual_sections(getEntries(), br);
  }

  // Private Static methods for reading the Manifest file from BufferedReader

  private static void read_main_section(Attributes attr,
					BufferedReader br) throws IOException
  {
    // According to the spec we should actually call read_version_info() here.
    read_attributes(attr, br);
    // Explicitly set Manifest-Version attribute if not set in Main
    // attributes of Manifest.
    if (attr.getValue(Attributes.Name.MANIFEST_VERSION) == null)
	    attr.putValue(Attributes.Name.MANIFEST_VERSION, "0.0");
  }

  /**
   * Pedantic method that requires the next attribute in the Manifest to be
   * the "Manifest-Version". This follows the Manifest spec closely but
   * reject some jar Manifest files out in the wild.
   */
  private static void read_version_info(Attributes attr,
					BufferedReader br) throws IOException
  {
    String version_header = Attributes.Name.MANIFEST_VERSION.toString();
    try
      {
	String value = expect_header(version_header, br);
	attr.putValue(Attributes.Name.MANIFEST_VERSION, value);
      }
    catch (IOException ioe)
      {
	throw new JarException("Manifest should start with a " +
			       version_header + ": " + ioe.getMessage());
      }
  }

  private static String expect_header(String header, BufferedReader br)
    throws IOException
  {
    String s = br.readLine();
    if (s == null)
      {
	throw new JarException("unexpected end of file");
      }
    return expect_header(header, br, s);
  }

  private static String expect_header(String header, BufferedReader br,
				      String s) throws IOException
  {
    try
      {
	String name = s.substring(0, header.length() + 1);
	if (name.equalsIgnoreCase(header + ":"))
	  {
	    String value_start = s.substring(header.length() + 2);
	    return read_header_value(value_start, br);
	  }
      }
    catch (IndexOutOfBoundsException iobe)
      {
      }
    // If we arrive here, something went wrong
    throw new JarException("unexpected '" + s + "'");
  }

  private static String read_header_value(String s, BufferedReader br)
    throws IOException
  {
    boolean try_next = true;
    while (try_next)
      {
	// Lets see if there is something on the next line
	br.mark(1);
	if (br.read() == ' ')
	  {
	    s += br.readLine();
	  }
	else
	  {
	    br.reset();
	    try_next = false;
	  }
      }
    return s;
  }

  private static void read_attributes(Attributes attr,
				      BufferedReader br) throws IOException
  {
    String s = br.readLine();
    while (s != null && (!s.equals("")))
      {
	read_attribute(attr, s, br);
	s = br.readLine();
      }
  }

  private static void read_attribute(Attributes attr, String s,
				     BufferedReader br) throws IOException
  {
    try
      {
	int colon = s.indexOf(": ");
	String name = s.substring(0, colon);
	String value_start = s.substring(colon + 2);
	String value = read_header_value(value_start, br);
	attr.putValue(name, value);
      }
    catch (IndexOutOfBoundsException iobe)
      {
	throw new JarException("Manifest contains a bad header: " + s);
      }
  }

  private static void read_individual_sections(Map entries,
					       BufferedReader br) throws
    IOException
  {
    String s = br.readLine();
    while (s != null && (!s.equals("")))
      {
	Attributes attr = read_section_name(s, br, entries);
	read_attributes(attr, br);
	s = br.readLine();
      }
  }

  private static Attributes read_section_name(String s, BufferedReader br,
					      Map entries) throws JarException
  {
    try
      {
	String name = expect_header("Name", br, s);
	Attributes attr = new Attributes();
	entries.put(name, attr);
	return attr;
      }
    catch (IOException ioe)
      {
	throw new JarException
	  ("Section should start with a Name header: " + ioe.getMessage());
      }
  }

  /**
   * XXX
   */
  public void write(OutputStream out) throws IOException
  {
    PrintWriter pw =
      new PrintWriter(new
		      BufferedWriter(new OutputStreamWriter(out, "8859_1")));
    write_main_section(getMainAttributes(), pw);
    pw.println();
    write_individual_sections(getEntries(), pw);
    if (pw.checkError())
      {
	throw new JarException("Error while writing manifest");
      }
  }

  // Private Static functions for writing the Manifest file to a PrintWriter

  private static void write_main_section(Attributes attr,
					 PrintWriter pw) throws JarException
  {
    write_version_info(attr, pw);
    write_main_attributes(attr, pw);
  }

  private static void write_version_info(Attributes attr, PrintWriter pw)
  {
    // First check if there is already a version attribute set
    String version = attr.getValue(Attributes.Name.MANIFEST_VERSION);
    if (version == null)
      {
	version = "1.0";
      }
    write_header(Attributes.Name.MANIFEST_VERSION.toString(), version, pw);
  }

  private static void write_header(String name, String value, PrintWriter pw)
  {
    pw.print(name + ": ");

    int last = 68 - name.length();
    if (last > value.length())
      {
	pw.println(value);
      }
    else
      {
	pw.println(value.substring(0, last));
      }
    while (last < value.length())
      {
	pw.print(" ");
	int end = (last + 69);
	if (end > value.length())
	  {
	    pw.println(value.substring(last));
	  }
	else
	  {
	    pw.println(value.substring(last, end));
	  }
	last = end;
      }
  }

  private static void write_main_attributes(Attributes attr, PrintWriter pw) 
    throws JarException
  {
    Iterator it = attr.entrySet().iterator();
    while (it.hasNext())
      {
	Map.Entry entry = (Map.Entry) it.next();
	// Don't print the manifest version again
	if (!Attributes.Name.MANIFEST_VERSION.equals(entry.getKey()))
	  {
	    write_attribute_entry(entry, pw);
	  }
      }
  }

  private static void write_attribute_entry(Map.Entry entry, PrintWriter pw) 
    throws JarException
  {
    String name = entry.getKey().toString();
    String value = entry.getValue().toString();

    if (name.equalsIgnoreCase("Name"))
      {
	throw new JarException("Attributes cannot be called 'Name'");
      }
    if (name.startsWith("From"))
      {
	throw new
	  JarException("Header cannot start with the four letters 'From'" +
		       name);
      }
    write_header(name, value, pw);
  }

  private static void write_individual_sections(Map entries, PrintWriter pw)
    throws JarException
  {

    Iterator it = entries.entrySet().iterator();
    while (it.hasNext())
      {
	Map.Entry entry = (Map.Entry) it.next();
	write_header("Name", entry.getKey().toString(), pw);
	write_entry_attributes((Attributes) entry.getValue(), pw);
	pw.println();
      }
  }

  private static void write_entry_attributes(Attributes attr, PrintWriter pw) 
    throws JarException
  {
    Iterator it = attr.entrySet().iterator();
    while (it.hasNext())
      {
	Map.Entry entry = (Map.Entry) it.next();
	write_attribute_entry(entry, pw);
      }
  }

  /**
   * Makes a deep copy of the main attributes, but a shallow copy of
   * the other entries. This means that you can freely add, change or remove
   * the main attributes or the entries of the new manifest without effecting
   * the original manifest, but adding, changing or removing attributes from
   * a particular entry also changes the attributes of that entry in the
   * original manifest. Calls <CODE>new Manifest(this)</CODE>.
   */
  public Object clone()
  {
    return new Manifest(this);
  }

  /**
   * Checks if another object is equal to this Manifest object.
   * Another Object is equal to this Manifest object if it is an instance of
   * Manifest and the main attributes and the entries of the other manifest
   * are equal to this one.
   */
  public boolean equals(Object o)
  {
    return (o instanceof Manifest) &&
      (mainAttr.equals(((Manifest) o).mainAttr)) &&
      (entries.equals(((Manifest) o).entries));
  }

  /**
   * Calculates the hash code of the manifest. Implemented by a xor of the
   * hash code of the main attributes with the hash code of the entries map.
   */
  public int hashCode()
  {
    return mainAttr.hashCode() ^ entries.hashCode();
  }

}
