    001    package escjava.ant;
    002
    003    import org.apache.tools.ant.BuildException;
    004    import org.apache.tools.ant.Project;
    005    import org.apache.tools.ant.taskdefs.Execute;
    006    import org.apache.tools.ant.taskdefs.Javac;
    007    import org.apache.tools.ant.taskdefs.LogStreamHandler;
    008    import org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter;
    009    import org.apache.tools.ant.types.Commandline;
    010    import org.apache.tools.ant.types.Path;
    011    import org.apache.tools.ant.util.FileUtils;
    012
    013    import java.io.File;
    014    import java.io.FileWriter;
    015    import java.io.IOException;
    016    import java.io.PrintWriter;
    017
    018    /**
    019     * Define an Escj compiler adapter.  This class is only a very simple
    020     * wrapper and does not try to implement of the command line options
    021     * of escj.
    022     *
    023     * @author wsargent
    024     * @version $Revision: 1.3 $
    025     *
    026     * @since May 16, 2004
    027     */
    028    public class ESCJavaTask extends DefaultCompilerAdapter
    029    {
    030      private FileUtils fileUtils = FileUtils.newFileUtils();
    031
    032      /* (non-Javadoc)
    033       * @see org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter#execute()
    034       */
    035      public boolean execute() throws BuildException
    036      {
    037        if (super.attributes == null)
    038          {
    039            throw new BuildException("Null attributes");
    040          }
    041
    042        if (super.project == null)
    043          {
    044            throw new BuildException("Null project");
    045          }
    046
    047        Javac javac = getJavac();
    048
    049        if (javac == null)
    050          {
    051            throw new BuildException("null javac");
    052          }
    053
    054        super.attributes.log("Using escj compiler", 3);
    055
    056        Path classpath = new Path(super.project);
    057
    058        if (super.bootclasspath != null)
    059          {
    060            classpath.append(super.bootclasspath);
    061          }
    062
    063        classpath.addExtdirs(super.extdirs);
    064
    065        if ((super.bootclasspath == null) || (super.bootclasspath.size() == 0))
    066          {
    067            super.includeJavaRuntime = true;
    068          }
    069
    070        classpath.append(getCompileClasspath());
    071
    072        if (super.compileSourcepath != null)
    073          {
    074            classpath.append(super.compileSourcepath);
    075          } else
    076            {
    077              classpath.append(super.src);
    078            }
    079
    080        Commandline cmd = new Commandline();
    081        String exec = javac.getExecutable();
    082        cmd.setExecutable((exec != null) ? exec : "java");
    083
    084        String simplifyProperty = super.project.getProperty(
    085                                                            "build.compiler.simplify");
    086
    087        // Make sure the simplify argument comes before...
    088        if (simplifyProperty != null)
    089          {
    090            cmd.createArgument().setValue("-Dsimplify=" + simplifyProperty);
    091          }
    092
    093        cmd.createArgument().setValue("-classpath");
    094        cmd.createArgument().setPath(classpath);
    095
    096        cmd.createArgument().setValue("escjava.Main");
    097
    098        cmd.createArgument().setValue("-classpath");
    099        cmd.createArgument().setPath(classpath);
    100
    101        /*
    102          if (super.deprecation)
    103          {
    104          cmd.createArgument().setValue("-deprecation");
    105          }
    106        */
    107        /*
    108          if (super.destDir != null)
    109          {
    110          cmd.createArgument().setValue("-d");
    111          cmd.createArgument().setFile(super.destDir);
    112          }
    113        */
    114        /*
    115          if (super.encoding != null)
    116          {
    117          cmd.createArgument().setValue("-encoding");
    118          cmd.createArgument().setValue(super.encoding);
    119          }
    120        */
    121        /*
    122          if (super.debug)
    123          {
    124          cmd.createArgument().setValue("-g");
    125          }
    126        */
    127        /*
    128          if (super.optimize)
    129          {
    130          cmd.createArgument().setValue("-O");
    131          }
    132        */
    133        setCounterExample(cmd);
    134        setDepend(cmd);
    135        setEajava(cmd);
    136        setEajml(cmd);
    137        setEnableAssertions(cmd);
    138        setLoopsafe(cmd);
    139        setLoop(cmd);
    140        setNoCheck(cmd);
    141        setNoCautions(cmd);
    142        setNoRedundancy(cmd);
    143        setNoTrace(cmd);
    144        setNoWarn(cmd);
    145        setPxLog(cmd);
    146        setPlainWarning(cmd);
    147        setQuiet(cmd);
    148        setRoutine(cmd);
    149        setRoutineIndirect(cmd);
    150        setSource(cmd);
    151        setSourcePath(cmd);
    152        setSuggest(cmd);
    153        setSxLog(cmd);
    154        setTarget(cmd);
    155        setTypeCheck(cmd);
    156        setUseVars(cmd);
    157        setUseFcns(cmd);
    158        setUseVarsForModelVars(cmd);
    159        setUseFcnsForModelVars(cmd);
    160        setWarn(cmd);
    161        setVerbose(cmd);
    162
    163        // Set the -f value to use the files following.
    164        cmd.createArgument().setValue("-f");
    165
    166        addCurrentCompilerArgs(cmd);
    167
    168        int firstFileName = cmd.size();
    169        logAndAddFilesToCompile(cmd);
    170
    171        return executeExternalCompile(cmd.getCommandline(), firstFileName) == 0;
    172      }
    173
    174      /**
    175       * @param cmd
    176       */
    177      private void setUseFcnsForModelVars(/*@ non_null @*/ Commandline cmd) throws BuildException
    178      {
    179        setTextArgument(cmd, "usefcnsformodelvars", "useFcnsForModelVars");
    180      }
    181
    182      /**
    183       * @param cmd
    184       */
    185      private void setUseVarsForModelVars(/*@ non_null @*/ Commandline cmd) throws BuildException
    186      {
    187        setTextArgument(cmd, "usevarsformodelvars", "useVarsForModelVars");
    188      }
    189
    190      /**
    191       * @param cmd
    192       */
    193      private void setWarn(/*@ non_null @*/ Commandline cmd) throws BuildException
    194      {
    195        setTextArgument(cmd, "warn", "warn");
    196      }
    197
    198      /**
    199       * @param cmd
    200       */
    201      private void setUseFcns(/*@ non_null @*/ Commandline cmd) throws BuildException
    202      {
    203        setArgument(cmd, "usefcns", "useFcns");
    204      }
    205
    206      /**
    207       * @param cmd
    208       */
    209      private void setRoutineIndirect(/*@ non_null @*/ Commandline cmd) throws BuildException
    210      {
    211        setTextArgument(cmd, "routineindirect", "routineIndirect");
    212      }
    213
    214      /**
    215       * @param cmd
    216       */
    217      private void setPlainWarning(/*@ non_null @*/ Commandline cmd) throws BuildException
    218      {
    219        setArgument(cmd, "plainwarning", "plainwarning");
    220      }
    221
    222      /**
    223       * @param cmd
    224       */
    225      private void setRoutine(/*@ non_null @*/ Commandline cmd) throws BuildException
    226      {
    227        String arg = "routine";
    228        setTextArgument(cmd, arg, arg);
    229      }
    230
    231      /**
    232       * @param cmd
    233       */
    234      private void setLoop(/*@ non_null @*/ Commandline cmd) throws BuildException
    235      {
    236        String arg = "loop";
    237        setTextArgument(cmd, arg, arg);
    238      }
    239
    240      /**
    241       * Sets the -quiet option.
    242       *
    243       * @param cmd
    244       */
    245      private void setQuiet(/*@ non_null @*/ Commandline cmd) throws BuildException
    246      {
    247        String arg = "quiet";
    248        setArgument(cmd, arg, arg);
    249      }
    250
    251      private void setVerbose(/*@ non_null @*/ Commandline cmd)
    252      {
    253        if (super.verbose)
    254          {
    255            cmd.createArgument().setValue("-v");
    256          }
    257      }
    258
    259      private void setDepend(/*@ non_null @*/ Commandline cmd)
    260      {
    261        if (super.depend)
    262          {
    263            cmd.createArgument().setValue("-depend");
    264          }
    265      }
    266
    267      private void setTarget(/*@ non_null @*/ Commandline cmd)
    268      {
    269        if (super.target != null)
    270          {
    271            cmd.createArgument().setValue("-target");
    272            cmd.createArgument().setValue(super.target);
    273          }
    274      }
    275
    276      private void setNoWarn(/*@ non_null @*/ Commandline cmd) throws BuildException
    277      {
    278        if (super.attributes == null)
    279          {
    280            throw new BuildException("Null attributes");
    281          }
    282
    283        if (super.attributes.getNowarn())
    284          {
    285            cmd.createArgument().setValue("-nowarn");
    286          }
    287      }
    288
    289      private void setSource(/*@ non_null @*/ Commandline cmd) throws BuildException
    290      {
    291        if (super.attributes == null)
    292          {
    293            throw new BuildException("Null attributes");
    294          }
    295
    296        if (super.attributes.getSource() != null)
    297          {
    298            cmd.createArgument().setValue("-source");
    299            cmd.createArgument().setValue(super.attributes.getSource());
    300          }
    301      }
    302
    303      private void setSourcePath(/*@ non_null @*/ Commandline cmd) throws BuildException
    304      {
    305        if (super.attributes == null)
    306          {
    307            throw new BuildException("Null attributes");
    308          }
    309
    310        if (super.attributes.getSourcepath() != null)
    311          {
    312            cmd.createArgument().setValue("-sourcepath");
    313
    314            Path path = super.attributes.getSourcepath();
    315            String pathString = (path == null) ? null : path.toString();
    316            cmd.createArgument().setValue(pathString);
    317          }
    318      }
    319
    320      private void setSxLog(/*@ non_null @*/ Commandline cmd) throws BuildException
    321      {
    322        setTextArgument(cmd, "sxlog", "sxLog");
    323      }
    324
    325      private void setPxLog(/*@ non_null @*/ Commandline cmd) throws BuildException
    326      {
    327        setTextArgument(cmd, "pxlog", "pxLog");
    328      }
    329
    330      private void setCounterExample(/*@ non_null @*/ Commandline cmd) throws BuildException
    331      {
    332        String arg = "counterexample";
    333        setArgument(cmd, arg, arg);
    334      }
    335
    336      private void setEajava(/*@ non_null @*/ Commandline cmd) throws BuildException
    337      {
    338        String arg = "eajava";
    339        setArgument(cmd, arg, arg);
    340      }
    341
    342      private void setEajml(/*@ non_null @*/ Commandline cmd) throws BuildException
    343      {
    344        String arg = "eajml";
    345        setArgument(cmd, arg, arg);
    346      }
    347
    348      private void setEnableAssertions(/*@ non_null @*/ Commandline cmd) throws BuildException
    349      {
    350        String arg = "enableassertions";
    351        setArgument(cmd, arg, arg);
    352      }
    353
    354      private void setUseVars(/*@ non_null @*/ Commandline cmd) throws BuildException
    355      {
    356        String arg = "usevars";
    357        setArgument(cmd, arg, "useVars");
    358      }
    359
    360      private void setTypeCheck(/*@ non_null @*/ Commandline cmd) throws BuildException
    361      {
    362        String arg = "typecheck";
    363        setArgument(cmd, arg, arg);
    364      }
    365
    366      private void setSuggest(/*@ non_null @*/ Commandline cmd) throws BuildException
    367      {
    368        String arg = "suggest";
    369        setArgument(cmd, arg, arg);
    370      }
    371
    372      private void setNoTrace(/*@ non_null @*/ Commandline cmd) throws BuildException
    373      {
    374        String arg = "notrace";
    375        setArgument(cmd, arg, arg);
    376      }
    377
    378      private void setNoRedundancy(/*@ non_null @*/ Commandline cmd) throws BuildException
    379      {
    380        String arg = "noredundancy";
    381        setArgument(cmd, arg, arg);
    382      }
    383
    384      private void setNoCautions(/*@ non_null @*/ Commandline cmd) throws BuildException
    385      {
    386        String arg = "nocautions";
    387        setArgument(cmd, arg, "noCautions");
    388      }
    389
    390      private void setNoCheck(/*@ non_null @*/ Commandline cmd) throws BuildException
    391      {
    392        String arg = "nocheck";
    393        setArgument(cmd, arg, arg);
    394      }
    395
    396      private void setLoopsafe(/*@ non_null @*/ Commandline cmd) throws BuildException
    397      {
    398        String arg = "loopsafe";
    399        setArgument(cmd, arg, arg);
    400      }
    401
    402      /**
    403       * Do the compile with the specified arguments.
    404       *
    405       * @param args - arguments to pass to process on command line
    406       * @param firstFileName - index of the first source file in args, if the
    407       *        index is negative, no temporary file will ever be created, but
    408       *        this may hit the command line length limit on your system.
    409       * @param quoteFiles - if set to true, filenames containing spaces will be
    410       *        quoted when they appear in the external file. This is necessary
    411       *        when running JDK 1.4's javac and probably others.
    412       *
    413       * @return DOCUMENT ME!
    414       *
    415       * @throws BuildException DOCUMENT ME!
    416       *
    417       * @since Ant 1.6
    418       */
    419      //@ also
    420      //@   requires args != null;
    421      protected int executeExternalCompile(String[] args,
    422                                           int firstFileName,
    423                                           boolean quoteFiles)
    424      {
    425        String[] commandArray = null;
    426        File tmpFile = null;
    427
    428        try
    429          {
    430
    431            /*
    432             * Many system have been reported to get into trouble with
    433             * long command lines - no, not only Windows ;-).
    434             *
    435             * POSIX seems to define a lower limit of 4k, so use a temporary
    436             * file if the total length of the command line exceeds this limit.
    437             */
    438            if ((Commandline.toString(args).length() > 4096) && (firstFileName >= 0))
    439              {
    440                PrintWriter out = null;
    441
    442                try
    443                  {
    444                    File userDir = getJavac().getTempdir();
    445
    446                    if (userDir == null)
    447                      {
    448                        String userDirName = System.getProperty("user.dir");
    449                        userDir = new File(userDirName);
    450                      }
    451
    452                    tmpFile = fileUtils.createTempFile("files", "", userDir);
    453                    tmpFile.deleteOnExit();
    454                    out = new PrintWriter(new FileWriter(tmpFile));
    455
    456                    for (int i = firstFileName; i < args.length; i++)
    457                      {
    458                        if (quoteFiles && (args[i].indexOf(" ") > -1))
    459                          {
    460                            args[i] = args[i].replace('\\', '/');
    461                            out.println("\"" + args[i] + "\"");
    462                          } else
    463                            {
    464                              out.println(args[i]);
    465                            }
    466                      }
    467
    468                    out.flush();
    469                    commandArray = new String[firstFileName + 1];
    470                    System.arraycopy(args, 0, commandArray, 0, firstFileName);
    471                    commandArray[firstFileName] = tmpFile.toString();
    472                  } catch (IOException e)
    473                    {
    474                      throw new BuildException("Error creating temporary file",
    475                                               e, location);
    476                    } finally
    477                      {
    478                        if (out != null)
    479                          {
    480                            try
    481                              {
    482                                out.close();
    483                              } catch (Throwable t)
    484                                {
    485                                  // ignore
    486                                }
    487                          }
    488                      }
    489              } else
    490                {
    491                  commandArray = args;
    492                }
    493
    494            try
    495              {
    496                Execute exe = new Execute(new LogStreamHandler(attributes,
    497                                                               Project.MSG_INFO, Project.MSG_WARN));
    498                exe.setAntRun(project);
    499                exe.setWorkingDirectory(project.getBaseDir());
    500                exe.setCommandline(commandArray);
    501                exe.execute();
    502
    503                return exe.getExitValue();
    504              } catch (IOException e)
    505                {
    506                  throw new BuildException("Error running " + args[0] +
    507                                           " compiler", e, location);
    508                }
    509          } finally
    510            {
    511              if (tmpFile != null)
    512                {
    513                  tmpFile.delete();
    514                }
    515            }
    516      }
    517
    518      /**
    519       * Sets an argument with a text value from a property.
    520       *
    521       * @param cmd
    522       * @param pPropertyName
    523       * @param pArgumentName
    524       *
    525       * @throws BuildException if one of the arguments is null.
    526       */
    527      private void setTextArgument(/*@ non_null @*/ Commandline cmd,
    528                                   /*@ non_null @*/ String pPropertyName,
    529                                   /*@ non_null @*/ String pArgumentName) throws BuildException
    530      {
    531        if (cmd == null)
    532          {
    533            throw new BuildException("null cmd");
    534          }
    535
    536        if (pPropertyName == null)
    537          {
    538            throw new BuildException("null pName");
    539          }
    540
    541        if (pArgumentName == null)
    542          {
    543            throw new BuildException("null pArgument");
    544          }
    545
    546        if (super.project == null)
    547          {
    548            throw new BuildException("null project");
    549          }
    550
    551        String propertyValue = super.project.getProperty("build.compiler." +
    552                                                         pPropertyName);
    553
    554        if (propertyValue != null)
    555          {
    556            cmd.createArgument().setValue("-" + pArgumentName + "=" +
    557                                          propertyValue);
    558          }
    559      }
    560
    561      /**
    562       * Sets an argument on the commandline from a boolean property.
    563       *
    564       * @param cmd
    565       * @param pPropertyName
    566       * @param pArgumentName
    567       *
    568       * @throws BuildException DOCUMENT ME!
    569       */
    570      private void setArgument(/*@ non_null @*/ Commandline cmd,
    571                               /*@ non_null @*/ String pPropertyName,
    572                               /*@ non_null @*/ String pArgumentName) throws BuildException
    573      {
    574        if (cmd == null)
    575          {
    576            throw new BuildException("null cmd");
    577          }
    578
    579        if (pPropertyName == null)
    580          {
    581            throw new BuildException("null pName");
    582          }
    583
    584        if (pArgumentName == null)
    585          {
    586            throw new BuildException("null pArgument");
    587          }
    588
    589        if (super.project == null)
    590          {
    591            throw new BuildException("null super.project");
    592          }
    593
    594        String propertyName = super.project.getProperty("build.compiler." +
    595                                                        pPropertyName);
    596
    597        if ((propertyName != null) && Project.toBoolean(propertyName))
    598          {
    599            cmd.createArgument().setValue("-" + pArgumentName);
    600          }
    601      }
    602    }