/* Creator.java - create a new jar file
 Copyright (C) 2006 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 gnu.classpath.tools.jar;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;

public class Creator
    extends Action
{
  JarOutputStream outputStream;
  HashSet writtenItems = new HashSet();
  // The manifest to use, or null if we don't want a manifest.
  Manifest manifest;

  private long copyFile(CRC32 crc, InputStream is, OutputStream output)
      throws IOException
  {
    byte[] buffer = new byte[1024];
    long size = 0;
    while (true)
      {
        int len = is.read(buffer);
        if (len == - 1)
          break;
        size += len;
        output.write(buffer, 0, len);
        crc.update(buffer, 0, len);
      }
    output.close();
    return size;
  }

  protected void writeFile(boolean isDirectory, InputStream inputFile,
                           String filename, boolean verbose)
    throws IOException
  {
    if (writtenItems.contains(filename))
      {
        if (verbose)
          {
            String msg = MessageFormat.format(Messages.getString("Creator.Ignoring"), //$NON-NLS-1$
                                              new Object[] { filename });
            System.err.println(msg);
          }
        return;
      }

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    CRC32 crc = new CRC32();
    long size;
    if (isDirectory)
      {
        size = 0;
      }
    else
      {
        size = copyFile(crc, inputFile, out);
      }

    ZipEntry entry = new ZipEntry(filename);
    entry.setCrc(crc.getValue());
    entry.setSize(size);

    outputStream.putNextEntry(entry);
    out.writeTo(outputStream);
    outputStream.closeEntry();
    writtenItems.add(filename);

    if (verbose)
      {
        long csize = entry.getCompressedSize();
        long perc;
        if (size == 0)
          perc = 0;
        else
          perc = 100 - (100 * csize) / size;
        String msg = MessageFormat.format(Messages.getString("Creator.Adding"), //$NON-NLS-1$
                                          new Object[]
                                            {
                                              filename,
                                              Long.valueOf(size),
                                              Long.valueOf(entry.getSize()),
                                              Long.valueOf(perc)
                                            });
        System.err.println(msg);
      }
  }

  protected void writeFile(File file, String filename, boolean verbose)
      throws IOException
  {
    boolean isDirectory = file.isDirectory();
    InputStream inputStream = null;
    if (isDirectory)
      {
        if (filename.charAt(filename.length() - 1) != '/')
          filename += '/';
      }
    else
      inputStream = new FileInputStream(file);
    writeFile(isDirectory, inputStream, filename, verbose);
  }

  private void addEntries(ArrayList result, Entry entry)
  {
    if (entry.file.isDirectory())
      {
        String name = entry.name;
        if (name.charAt(name.length() - 1) != '/')
          {
            name += '/';
            entry = new Entry(entry.file, name);
          }
        result.add(entry);
        String[] files = entry.file.list();
        for (int i = 0; i < files.length; ++i)
          addEntries(result, new Entry(new File(entry.file, files[i]),
                                       entry.name + files[i]));
      }
    else
      result.add(entry);
  }

  private ArrayList getAllEntries(Main parameters)
  {
    Iterator it = parameters.entries.iterator();
    ArrayList allEntries = new ArrayList();
    while (it.hasNext())
      {
        Entry entry = (Entry) it.next();
        addEntries(allEntries, entry);
      }
    return allEntries;
  }

  private void writeCommandLineEntries(Main parameters)
      throws IOException
  {
    // We've already written the manifest, make sure to mark it.
    writtenItems.add("META-INF/"); //$NON-NLS-1$
    writtenItems.add(JarFile.MANIFEST_NAME);

    ArrayList allEntries = getAllEntries(parameters);
    Iterator it = allEntries.iterator();
    while (it.hasNext())
      {
        Entry entry = (Entry) it.next();
        writeFile(entry.file, entry.name, parameters.verbose);
      }
  }

  protected Manifest createManifest(Main parameters)
    throws IOException
  {
    if (! parameters.wantManifest)
      return null;
    if (parameters.manifestFile != null)
      {
        // User specified a manifest file.
        InputStream contents = new FileInputStream(parameters.manifestFile);
        return new Manifest(contents);
      }
    return new Manifest();
  }

  protected void writeCommandLineEntries(Main parameters, OutputStream os)
    throws IOException
  {
    manifest = createManifest(parameters);
    outputStream = new JarOutputStream(os, manifest);
    // FIXME: in Classpath this sets the method too late for the
    // manifest file.
    outputStream.setMethod(parameters.storageMode);
    writeCommandLineEntries(parameters);
  }

  protected void close() throws IOException
  {
    outputStream.finish();
    outputStream.close();
  }

  public void run(Main parameters) throws IOException
  {
    if (parameters.archiveFile == null || parameters.archiveFile.equals("-")) //$NON-NLS-1$
      writeCommandLineEntries(parameters, System.out);
    else
      {
        OutputStream os
          = new BufferedOutputStream(new FileOutputStream(parameters.archiveFile));
        writeCommandLineEntries(parameters, os);
      }
    close();
  }
}
