/*
  Copyright (c) 2001, 2003 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. */

package gnu.classpath.tools.rmi.rmic;

import java.io.InputStream;

/**
 * Subclass of Compiler that can be subclassed to invoke a process to
 * do its work.
 */
public abstract class CompilerProcess extends Compiler
{
  /** This is used to compute the command line for the process.  */
  public abstract String[] computeArguments (String filename);

   /**
    * This is used to compute the command line for the process.
    * Most compilers typically arrange their arguments as in
    * &lt;compiler name and arguments&gt; &lt;optional destination&gt; &lt;filename&gt;.
    * This method builds an argument array out that. It should be used
    * to define computeArguments for those compilers that follow the
    * argument convention described above.
    */
   public static String[] computeTypicalArguments(String[] compilerArgs,
	String destination, String filename)
   {
     /* length of compiler specific arguments */
     final int len = compilerArgs.length;

     /* length of returned array of arguments */
     final int arglen = len + (destination == null ? 0 : 2) + 1;

     /* Allocate String array for computed arguments. */
     String [] args = new String[arglen];

     /* Fill in compiler arguments. */
     System.arraycopy(compilerArgs, 0, args, 0, len);

     /* Fill in destination argument if necessary. */
     if (destination != null)
      {
	args[len] = "-d";
	args[len + 1] = destination;
      }

     /* Fill in filename */
     args[arglen - 1] = filename;

     return args;
   }

  public void compile (String name) throws Exception
  {
    String[] args = computeArguments (name);
    Process p = Runtime.getRuntime ().exec (args);

    /* Print compiler output to System.out. */
    InputStream procin = p.getInputStream();
    for (int ch = procin.read(); ch != -1; ch = procin.read())
      System.out.print((char) ch);

    /* Collect compiler error output in a buffer.
     * If compilation fails, it will be used for an error message.
     */
    StringBuffer stderr = new StringBuffer();
    InputStream procerr = p.getErrorStream();
    for (int ch = procerr.read(); ch != -1; ch = procerr.read())
      stderr.append((char) ch);

    int result;
    while (true)
      {
	try
	  {
	    result = p.waitFor ();
	    break;
	  }
	catch (InterruptedException _)
	  {
	  }
      }
    if (result != 0)
      {
	// FIXME: wrong exception class.
	throw new Exception ("compiler exited with status: " + result,
			     new RMICException(stderr.toString()));
      }
  }
}
