Source for gnu.java.rmi.rmic.CompilerProcess

   1: /*
   2:   Copyright (c) 2001, 2003 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10:  
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.java.rmi.rmic;
  39: 
  40: import java.io.InputStream;
  41: 
  42: /**
  43:  * Subclass of Compiler that can be subclassed to invoke a process to
  44:  * do its work.
  45:  */
  46: public abstract class CompilerProcess extends Compiler
  47: {
  48:   /** This is used to compute the command line for the process.  */
  49:   public abstract String[] computeArguments (String filename);
  50: 
  51:    /**
  52:     * This is used to compute the command line for the process.
  53:     * Most compilers typically arrange their arguments as in
  54:     * <compiler name and arguments> <optional destination> <filename>.
  55:     * This method builds an argument array out that. It should be used
  56:     * to define computeArguments for those compilers that follow the
  57:     * argument convention described above.
  58:     */
  59:    public static String[] computeTypicalArguments(String[] compilerArgs,
  60:     String destination, String filename)
  61:    {
  62:      return computeTypicalArguments(compilerArgs, null, destination, filename);
  63:    }
  64:    /**
  65:     * This is used to compute the command line for the process.
  66:     * Most compilers typically arrange their arguments as in
  67:     * <compiler name and arguments> <optional destination> <filename>.
  68:     * This method builds an argument array out that. It should be used
  69:     * to define computeArguments for those compilers that follow the
  70:     * argument convention described above.
  71:     */
  72:    public static String[] computeTypicalArguments(String[] compilerArgs,
  73:                                                   String classpath,
  74:                                                   String destination,
  75:                                                   String filename)
  76:    {
  77:      /* length of compiler specific arguments */
  78:      int len = compilerArgs.length;
  79: 
  80:      /* length of returned array of arguments */
  81:      final int arglen = len + (classpath == null ? 0 : 2) +
  82:        (destination == null ? 0 : 2) + 1;
  83: 
  84:      /* Allocate String array for computed arguments. */
  85:      String [] args = new String[arglen];
  86: 
  87:      /* Fill in compiler arguments. */
  88:      System.arraycopy(compilerArgs, 0, args, 0, len);
  89: 
  90:      /* Fill in classpath argument if necessary. */
  91:      if (classpath != null)
  92:        {
  93:          args[len++] = "-classpath";
  94:          args[len++] = classpath;
  95:        }
  96: 
  97:      /* Fill in destination argument if necessary. */
  98:      if (destination != null)
  99:       {
 100:     args[len++] = "-d";
 101:     args[len++] = destination;
 102:       }
 103: 
 104:      /* Fill in filename */
 105:      args[arglen - 1] = filename;
 106: 
 107:      return args;
 108:    }
 109: 
 110:   public void compile (String name) throws Exception
 111:   {
 112:     String[] args = computeArguments (name);
 113:     Process p = Runtime.getRuntime ().exec (args);
 114: 
 115:     /* Print compiler output to System.out.  Do this asynchronously so
 116:        that the compiler never blocks writing to its stdout.  */
 117:     {
 118:       final InputStream procin = p.getInputStream();
 119:       final Thread copier = new Thread() 
 120:     {
 121:       public void run()
 122:       {
 123:         try
 124:           {
 125:         for (int ch = procin.read(); ch != -1; ch = procin.read())
 126:           System.out.print((char) ch);
 127:           }
 128:         catch (java.io.IOException _)
 129:           {
 130:           }
 131:       }
 132:     };
 133: 
 134:       copier.start();
 135:     }
 136: 
 137:     /* Collect compiler error output in a buffer.
 138:      * If compilation fails, it will be used for an error message.
 139:      */
 140:     StringBuffer stderr = new StringBuffer();
 141:     InputStream procerr = p.getErrorStream();
 142:     for (int ch = procerr.read(); ch != -1; ch = procerr.read())
 143:       stderr.append((char) ch);
 144: 
 145:     int result;
 146:     while (true)
 147:       {
 148:     try
 149:       {
 150:         result = p.waitFor ();
 151:         break;
 152:       }
 153:     catch (InterruptedException _)
 154:       {
 155:       }
 156:       }
 157:     if (result != 0)
 158:       {
 159:     // FIXME: wrong exception class.
 160:     throw new Exception ("compiler exited with status: " + result,
 161:                  new RMICException(stderr.toString()));
 162:       }
 163:   }
 164: }