/* Copyright (C) 2004, 2005, 2006  Free Software Foundation

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

package gnu.gcj.tools.gcj_dbtool;


import gnu.gcj.runtime.PersistentByteMap;
import java.io.*;
import java.nio.channels.*;
import java.util.*;
import java.util.jar.*;
import java.security.MessageDigest;

public class Main
{
  static private boolean verbose = false;

  public static void main (String[] s)
  {
    boolean fileListFromStdin = false;
    char filenameSeparator = ' ';

    insist (s.length >= 1);

    if (s[0].equals("-") ||
	s[0].equals("-0"))
      {
	if (s[0].equals("-0"))
	  filenameSeparator = (char)0;
	fileListFromStdin = true;
	String[] newArgs = new String[s.length - 1];
	System.arraycopy(s, 1, newArgs, 0, s.length - 1);
	s = newArgs;
      }

    if (s[0].equals("-v") || s[0].equals("--version"))
      {
	insist (s.length == 1);
	System.out.println("gcj-dbtool ("
			   + System.getProperty("java.vm.name")
			   + ") "
			   + System.getProperty("java.vm.version"));
	System.out.println();
	System.out.println("Copyright 2006 Free Software Foundation, Inc.");
	System.out.println("This is free software; see the source for copying conditions.  There is NO");
	System.out.println("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
	return;
      }
    if (s[0].equals("--help"))
      {
	usage(System.out);
	return;
      }

    if (s[0].equals("-n"))
      {
	// Create a new database.
	insist (s.length >= 2 && s.length <= 3);

	int capacity = 32749;

	if (s.length == 3)
	  {	    
	    capacity = Integer.parseInt(s[2]);

	    if (capacity <= 2)
	      {
		usage(System.err);
		System.exit(1);
	      }
	  }
	    
	try
	  {
	    PersistentByteMap b 
	      = PersistentByteMap.emptyPersistentByteMap(new File(s[1]), 
							 capacity, capacity*32);
	  }
	catch (Exception e)
	  {
	    System.err.println ("error: could not create " 
				+ s[1] + ": " + e.toString());
	    System.exit(2);
	  }
	return;
      }

    if (s[0].equals("-a") || s[0].equals("-f"))
      {
	// Add a jar file to a database, creating it if necessary.
	// Copies the database, adds the jar file to the copy, and
	// then renames the new database over the old.
	try
	  {
	    insist (s.length == 4);
	    File database = new File(s[1]);
	    database = database.getAbsoluteFile();
	    File jar = new File(s[2]);	
	    PersistentByteMap map; 
	    if (database.isFile())
	      map = new PersistentByteMap(database, 
					  PersistentByteMap.AccessMode.READ_ONLY);
	    else
	      map = PersistentByteMap.emptyPersistentByteMap(database, 
							     100, 100*32);
	    File soFile = new File(s[3]);
	    if (! s[0].equals("-f") && ! soFile.isFile())
	      throw new IllegalArgumentException(s[3] + " is not a file");
 	    map = addJar(jar, map, soFile);
	  }
	catch (Exception e)
	  {
	    System.err.println ("error: could not update " + s[1] 
				+ ": " + e.toString());
	    System.exit(2);
	  }
	return;
      }

    if (s[0].equals("-t"))
      {
	// Test
	try
	  {
	    insist (s.length == 2);
	    PersistentByteMap b 
	      = new PersistentByteMap(new File(s[1]),
				      PersistentByteMap.AccessMode.READ_ONLY);
	    Iterator iterator = b.iterator(PersistentByteMap.ENTRIES);
	
	    while (iterator.hasNext())
	      {
		PersistentByteMap.MapEntry entry 
		  = (PersistentByteMap.MapEntry)iterator.next();
		byte[] key = (byte[])entry.getKey();
		byte[] value = (byte[])b.get(key);
		if (! Arrays.equals (value, (byte[])entry.getValue()))
		  {
		    String err 
		      = ("Key " + bytesToString(key) + " at bucket " 
			 + entry.getBucket());
		  
		    throw new RuntimeException(err);
		  }
	      }
	  }
	catch (Exception e)
	  {
	    e.printStackTrace();
	    System.exit(3);
	  }
	return;
      }
	 
    if (s[0].equals("-m"))
      {
	// Merge databases.
	insist (s.length >= 3
		|| fileListFromStdin && s.length == 2);
	try
	  {
	    File database = new File(s[1]);
	    database = database.getAbsoluteFile();
	    File temp = File.createTempFile(database.getName(), "", 
					    database.getParentFile());
	    	
	    int newSize = 0;
	    int newStringTableSize = 0;
	    Fileset files = getFiles(s, 2, fileListFromStdin, 
				     filenameSeparator);
	    PersistentByteMap[] sourceMaps 
	      = new PersistentByteMap[files.size()];

	    // Scan all the input files, calculating worst case string
	    // table and hash table use.
	    {
	      Iterator it = files.iterator();
	      int i = 0;
	      while (it.hasNext())
		{
		  PersistentByteMap b 
		    = new PersistentByteMap((File)it.next(),
					    PersistentByteMap.AccessMode.READ_ONLY);
		  newSize += b.size();
		  newStringTableSize += b.stringTableSize();
		  sourceMaps[i++] = b;
		}
	    }
	    
	    newSize *= 1.5; // Scaling the new size by 1.5 results in
			    // fewer collisions.
	    PersistentByteMap map 
	      = PersistentByteMap.emptyPersistentByteMap
	      (temp, newSize, newStringTableSize);

	    for (int i = 0; i < sourceMaps.length; i++)
	      {
		if (verbose)
		  System.err.println("adding " + sourceMaps[i].size() 
				     + " elements from "
				     + sourceMaps[i].getFile());
		map.putAll(sourceMaps[i]);
	      }
	    map.close();
	    temp.renameTo(database);
	  }
	catch (Exception e)
	  {
	    e.printStackTrace();
	    System.exit(3);
	  }
	return;
      }

    if (s[0].equals("-l"))
      {
	// List a database.
	insist (s.length == 2);
	try
	  {
	    PersistentByteMap b 
	      = new PersistentByteMap(new File(s[1]),
				      PersistentByteMap.AccessMode.READ_ONLY);

	    System.out.println ("Capacity: " + b.capacity());
	    System.out.println ("Size: " + b.size());
	    System.out.println ();

	    System.out.println ("Elements: ");
	    Iterator iterator = b.iterator(PersistentByteMap.ENTRIES);
    
	    while (iterator.hasNext())
	      {
		PersistentByteMap.MapEntry entry 
		  = (PersistentByteMap.MapEntry)iterator.next();
		byte[] digest = (byte[])entry.getKey();
		System.out.print ("[" + entry.getBucket() + "] " 
				  + bytesToString(digest)
				  + " -> ");
		System.out.println (new String((byte[])entry.getValue()));
	      }
	  }
	catch (Exception e)
	  {
	    System.err.println ("error: could not list " 
				+ s[1] + ": " + e.toString());
	    System.exit(2);
	  }
	return;
      }

    if (s[0].equals("-d"))
      {
	// For testing only: fill the byte map with random data.
	insist (s.length == 2);
	try
	  {    
	    MessageDigest md = MessageDigest.getInstance("MD5");
	    PersistentByteMap b 
	      = new PersistentByteMap(new File(s[1]), 
				      PersistentByteMap.AccessMode.READ_WRITE);
	    int N = b.capacity();
	    byte[] bytes = new byte[1];
	    byte digest[] = md.digest(bytes);
	    for (int i = 0; i < N; i++)
	      {
		digest = md.digest(digest);
		b.put(digest, digest);
	      }
	  }
	catch (Exception e)
	  {
	    e.printStackTrace();
	    System.exit(3);
	  }	    
	return;
      }

    if (s[0].equals("-p"))
      {
	insist (s.length == 1 || s.length == 2);
	String result;
	
	if (s.length == 1)
	  result = System.getProperty("gnu.gcj.precompiled.db.path", "");
	else 
	  result = (s[1] 
		    + (s[1].endsWith(File.separator) ? "" : File.separator)
		    + getDbPathTail ());

	System.out.println (result);
	return;
      }

    usage(System.err);
    System.exit(1);	    
  }

  private static native String getDbPathTail ();
    
  private static void insist(boolean ok)
  {
    if (! ok)
      {
	usage(System.err);
	System.exit(1);
      }	    
  }

  private static void usage(PrintStream out)
  {
    out.println
      ("gcj-dbtool: Manipulate gcj map database files\n"
       + "\n"
       + "  Usage: \n"
       + "    gcj-dbtool -n file.gcjdb [size]     - Create a new gcj map database\n"
       + "    gcj-dbtool -a file.gcjdb file.jar file.so\n"
       + "            - Add the contents of file.jar to a gcj map database\n"
       + "    gcj-dbtool -f file.gcjdb file.jar file.so\n"
       + "            - Add the contents of file.jar to a gcj map database\n"
       + "    gcj-dbtool -t file.gcjdb            - Test a gcj map database\n"
       + "    gcj-dbtool -l file.gcjdb            - List a gcj map database\n"
       + "    gcj-dbtool [-][-0] -m dest.gcjdb [source.gcjdb]...\n"
       + "            - Merge gcj map databases into dest\n"
       + "              Replaces dest\n"
       + "              To add to dest, include dest in the list of sources\n"
       + "              If the first arg is -, read the list from stdin\n"
       + "              If the first arg is -0, filenames separated by nul\n"
       + "    gcj-dbtool -p [LIBDIR]              - Print default database name"
       );
  }

  // Add a jar to a map.  This copies the map first and returns a
  // different map that contains the data.  The original map is
  // closed.

  private static PersistentByteMap 
  addJar(File f, PersistentByteMap b, File soFile)
    throws Exception
  {
    MessageDigest md = MessageDigest.getInstance("MD5");

    JarFile jar = new JarFile (f);

    int count = 0;
    {
      Enumeration entries = jar.entries();      
      while (entries.hasMoreElements())
	{
	  JarEntry classfile = (JarEntry)entries.nextElement();
	  if (classfile.getName().endsWith(".class"))
	    count++;
	}
    }

    if (verbose)
      System.err.println("adding " + count + " elements from "
			 + f + " to " + b.getFile());
    
    // Maybe resize the destination map.  We're allowing plenty of
    // extra space by using a loadFactor of 2.  
    b = resizeMap(b, (b.size() + count) * 2, true);

    Enumeration entries = jar.entries();

    byte[] soFileName = soFile.getCanonicalPath().getBytes("UTF-8");
    while (entries.hasMoreElements())
      {
	JarEntry classfile = (JarEntry)entries.nextElement();
	if (classfile.getName().endsWith(".class"))
	  {
	    InputStream str = jar.getInputStream(classfile);
	    int length = (int) classfile.getSize();
	    if (length == -1)
	      throw new EOFException();

	    byte[] data = new byte[length];
	    int pos = 0;
	    while (length - pos > 0)
	      {
		int len = str.read(data, pos, length - pos);
		if (len == -1)
		  throw new EOFException("Not enough data reading from: "
					 + classfile.getName());
		pos += len;
	      }
	    b.put(md.digest(data), soFileName);
	  }
      }
    return b;
  }    

  // Resize a map by creating a new one with the same data and
  // renaming it.  If close is true, close the original map.

  static PersistentByteMap resizeMap(PersistentByteMap m, int newCapacity, boolean close)
    throws IOException, IllegalAccessException
  {
    newCapacity = Math.max(m.capacity(), newCapacity);
    File name = m.getFile();
    File copy = File.createTempFile(name.getName(), "", name.getParentFile());
    try
      {
	PersistentByteMap dest 
	  = PersistentByteMap.emptyPersistentByteMap
	  (copy, newCapacity, newCapacity*32);
	dest.putAll(m);
	dest.force();
	if (close)
	  m.close();
	copy.renameTo(name);
	return dest;
      }
    catch (Exception e)
      {
	copy.delete();
      }
    return null;
  }
    
	 
  static String bytesToString(byte[] b)
  {
    StringBuffer hexBytes = new StringBuffer();
    int length = b.length;
    for (int i = 0; i < length; ++i)
      hexBytes.append(Integer.toHexString(b[i] & 0xff));
    return hexBytes.toString();
  }


  // Return a Fileset, either from a String array or from System.in,
  // depending on fileListFromStdin.
  private static final Fileset getFiles(String[] s, int startPos,
					boolean fileListFromStdin,
					char separator)
  {
    if (fileListFromStdin)
      return new Fileset(System.in, separator);
    else
      return new Fileset(s, startPos, s.length);
  }
}

// Parse a stream into tokens.  The separator can be any char, and
// space is equivalent to any whitepace character.
class Tokenizer
{
  final Reader r;
  final char separator;

  Tokenizer(Reader r, char separator)
  {
    this.r = r;
    this.separator = separator;
  }

  boolean isSeparator(int c)
  {
    if (Character.isWhitespace(separator))
      return Character.isWhitespace((char)c);
    else
      return c == separator;
  }

  // Parse a token from the input stream.  Return the empty string
  // when the stream is exhausted.
  String nextToken ()
  {
    StringBuffer buf = new StringBuffer();
    int c;
    try
      {
	while ((c = r.read()) != -1)
	  {
	    if (! isSeparator(c))
	      {
		buf.append((char)c);
		break;
	      }
	  }
	while ((c = r.read()) != -1)
	  {
	    if (isSeparator(c))
	      break;
	    else
	      buf.append((char)c);
	  }
      }
    catch (java.io.IOException e)
      {
      }
    return buf.toString();
  }
}

// A Fileset is a container for a set of files; it can be created
// either from a string array or from an input stream, given a
// separator character.
class Fileset
{
  LinkedHashSet files = new LinkedHashSet();
  
  Fileset (String[] s, int start, int end)
  {
    for (int i = start; i < end; i++)
      {
	files.add(new File(s[i]));
      }
  }

  Fileset (InputStream is, char separator)
  {
    Reader r = new BufferedReader(new InputStreamReader(is));
    Tokenizer st = new Tokenizer(r, separator);
    String name;
    while (! "".equals(name = st.nextToken()))
      files.add(new File(name));
  }

  Iterator iterator()
  {
    return files.iterator();
  }

  int size()
  {
    return files.size();
  }
}
