/* Attributes.java -- Reads, writes and manipulaties jar manifest files
   Copyright (C) 2000 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

As a special exception, if you link this library with other files to
produce an executable, this library does not by itself cause the
resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why the
executable file might be covered by the GNU General Public License. */

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.io.Reader;
import java.io.Writer;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 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 InputStream 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
  {
    read_version_info(attr, br);
    read_attributes(attr, br);
  }

  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(version_header, 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();
  }

}
