Clover coverage report - groovy - 1.0-beta-7
Coverage timestamp: Wed Sep 29 2004 16:55:52 BST
file stats: LOC: 903   Methods: 39
NCLOC: 414   Classes: 5
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
CompilationUnit.java 0% 0% 0% 0%
coverage
 1   
 /*
 2   
  $Id: CompilationUnit.java,v 1.8 2004/07/15 09:47:21 jstrachan Exp $
 3   
 
 4   
  Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
 5   
 
 6   
  Redistribution and use of this software and associated documentation
 7   
  ("Software"), with or without modification, are permitted provided
 8   
  that the following conditions are met:
 9   
 
 10   
  1. Redistributions of source code must retain copyright
 11   
     statements and notices.  Redistributions must also contain a
 12   
     copy of this document.
 13   
 
 14   
  2. Redistributions in binary form must reproduce the
 15   
     above copyright notice, this list of conditions and the
 16   
     following disclaimer in the documentation and/or other
 17   
     materials provided with the distribution.
 18   
 
 19   
  3. The name "groovy" must not be used to endorse or promote
 20   
     products derived from this Software without prior written
 21   
     permission of The Codehaus.  For written permission,
 22   
     please contact info@codehaus.org.
 23   
 
 24   
  4. Products derived from this Software may not be called "groovy"
 25   
     nor may "groovy" appear in their names without prior written
 26   
     permission of The Codehaus. "groovy" is a registered
 27   
     trademark of The Codehaus.
 28   
 
 29   
  5. Due credit should be given to The Codehaus -
 30   
     http://groovy.codehaus.org/
 31   
 
 32   
  THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
 33   
  ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 34   
  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 35   
  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 36   
  THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 37   
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 38   
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 39   
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 40   
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 41   
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 42   
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 43   
  OF THE POSSIBILITY OF SUCH DAMAGE.
 44   
 
 45   
  */
 46   
 
 47   
 package org.codehaus.groovy.control;
 48   
 
 49   
 import org.codehaus.groovy.GroovyBugError;
 50   
 import org.codehaus.groovy.ast.ClassNode;
 51   
 import org.codehaus.groovy.ast.CompileUnit;
 52   
 import org.codehaus.groovy.ast.ModuleNode;
 53   
 import org.codehaus.groovy.classgen.AsmClassGenerator2;
 54   
 import org.codehaus.groovy.classgen.ClassCompletionVerifier;
 55   
 import org.codehaus.groovy.classgen.ClassGenerator;
 56   
 import org.codehaus.groovy.classgen.GeneratorContext;
 57   
 import org.codehaus.groovy.classgen.Verifier;
 58   
 import org.codehaus.groovy.control.io.InputStreamReaderSource;
 59   
 import org.codehaus.groovy.control.io.ReaderSource;
 60   
 import org.codehaus.groovy.control.messages.ExceptionMessage;
 61   
 import org.codehaus.groovy.control.messages.Message;
 62   
 import org.codehaus.groovy.tools.GroovyClass;
 63   
 import org.objectweb.asm.ClassVisitor;
 64   
 import org.objectweb.asm.ClassWriter;
 65   
 
 66   
 import java.io.File;
 67   
 import java.io.FileOutputStream;
 68   
 import java.io.IOException;
 69   
 import java.io.InputStream;
 70   
 import java.io.PrintWriter;
 71   
 import java.net.MalformedURLException;
 72   
 import java.net.URL;
 73   
 import java.security.CodeSource;
 74   
 import java.util.ArrayList;
 75   
 import java.util.HashMap;
 76   
 import java.util.Iterator;
 77   
 import java.util.LinkedList;
 78   
 import java.util.List;
 79   
 
 80   
 
 81   
 /**
 82   
  * Collects all compilation data as it is generated by the compiler system.
 83   
  * Allows additional source units to be added and compilation run again (to
 84   
  * affect only the deltas).
 85   
  *
 86   
  * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
 87   
  * @version $Id: CompilationUnit.java,v 1.8 2004/07/15 09:47:21 jstrachan Exp $
 88   
  */
 89   
 
 90   
 public class CompilationUnit extends ProcessingUnit {
 91   
 
 92   
     //---------------------------------------------------------------------------
 93   
     // CONSTRUCTION AND SUCH
 94   
     
 95   
     protected HashMap sources;    // The SourceUnits from which this unit is built
 96   
     protected ArrayList names;      // Names for each SourceUnit in sources.
 97   
 
 98   
     protected CompileUnit ast;        // The overall AST for this CompilationUnit.
 99   
     protected ArrayList classes;    // The classes generated during classgen.
 100   
 
 101   
     protected Verifier verifier;   // For use by verify().
 102   
 
 103   
     protected ClassCompletionVerifier completionVerifier; // for use by checkClassCompletion
 104   
 
 105   
     protected boolean debug;      // Controls behaviour of classgen() and other routines.
 106   
     protected boolean configured; // Set true after the first configure() operation
 107   
 
 108   
     protected ClassgenCallback classgenCallback;  // A callback for use during classgen()
 109   
     protected ProgressCallback progressCallback;  // A callback for use during compile()
 110   
 
 111   
 
 112   
     /**
 113   
      * Initializes the CompilationUnit with defaults.
 114   
      */
 115  0
     public CompilationUnit() {
 116  0
         this(null, null, null);
 117   
     }
 118   
 
 119   
 
 120   
     /**
 121   
      * Initializes the CompilationUnit with defaults except for class loader.
 122   
      */
 123  0
     public CompilationUnit(ClassLoader loader) {
 124  0
         this(null, null, loader);
 125   
     }
 126   
 
 127   
 
 128   
     /**
 129   
      * Initializes the CompilationUnit with no security considerations.
 130   
      */
 131  0
     public CompilationUnit(CompilerConfiguration configuration) {
 132  0
         this(configuration, null, null);
 133   
     }
 134   
 
 135   
 
 136   
     /**
 137   
      * Initializes the CompilationUnit with a CodeSource for controlling
 138   
      * security stuff and a class loader for loading classes.
 139   
      */
 140   
 
 141  0
     public CompilationUnit(CompilerConfiguration configuration, CodeSource security, ClassLoader loader) {
 142  0
         super(configuration, loader);
 143   
 
 144  0
         this.names = new ArrayList();
 145  0
         this.sources = new HashMap();
 146   
 
 147  0
         this.ast = new CompileUnit(this.classLoader, security, this.configuration);
 148  0
         this.classes = new ArrayList();
 149   
 
 150  0
         this.verifier = new Verifier();
 151  0
         this.completionVerifier = new ClassCompletionVerifier();
 152   
 
 153  0
         this.classgenCallback = null;
 154   
     }
 155   
 
 156   
 
 157   
     /**
 158   
      * Reconfigures the CompilationUnit.
 159   
      */
 160   
 
 161  0
     public void configure(CompilerConfiguration configuration) {
 162  0
         super.configure(configuration);
 163  0
         this.debug = configuration.getDebug();
 164   
 
 165   
 
 166   
         //
 167   
         // Configure our class loader's classpath, if it is of
 168   
         // a configurable type.  We can't reconfigure it,
 169   
         // unfortunately, due to limitations in URLClassLoader.
 170   
 
 171  0
         if (!this.configured && this.classLoader instanceof CompilerClassLoader) {
 172  0
             CompilerClassLoader loader = (CompilerClassLoader) this.classLoader;
 173   
 
 174  0
             Iterator iterator = configuration.getClasspath().iterator();
 175  0
             while (iterator.hasNext()) {
 176  0
                 try {
 177  0
                     this.configured = true;
 178  0
                     loader.addPath((String) iterator.next());
 179   
                 }
 180   
                 catch (MalformedURLException e) {
 181  0
                     throw new ConfigurationException(e);
 182   
                 }
 183   
             }
 184   
         }
 185   
     }
 186   
 
 187   
 
 188   
     /**
 189   
      * Returns the CompileUnit that roots our AST.
 190   
      */
 191   
 
 192  0
     public CompileUnit getAST() {
 193  0
         return this.ast;
 194   
     }
 195   
 
 196   
 
 197   
     /**
 198   
      * Get the GroovyClasses generated by compile().
 199   
      */
 200   
 
 201  0
     public List getClasses() {
 202  0
         return classes;
 203   
     }
 204   
 
 205   
 
 206   
     /**
 207   
      * Convenience routine to get the first ClassNode, for
 208   
      * when you are sure there is only one.
 209   
      */
 210   
 
 211  0
     public ClassNode getFirstClassNode() {
 212  0
         return (ClassNode) ((ModuleNode) this.ast.getModules().get(0)).getClasses().get(0);
 213   
     }
 214   
 
 215   
 
 216   
     /**
 217   
      * Convenience routine to get the named ClassNode.
 218   
      */
 219   
 
 220  0
     public ClassNode getClassNode(final String name) {
 221  0
         final ClassNode[] result = new ClassNode[]{null};
 222  0
         LoopBodyForPrimaryClassNodeOperations handler = new LoopBodyForPrimaryClassNodeOperations() {
 223  0
             public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) {
 224  0
                 if (classNode.getName().equals(name)) {
 225  0
                     result[0] = classNode;
 226   
                 }
 227   
             }
 228   
         };
 229   
 
 230  0
         try {
 231  0
             applyToPrimaryClassNodes(handler);
 232   
         }
 233   
         catch (CompilationFailedException e) {
 234  0
             e.printStackTrace();
 235   
         }
 236  0
         return result[0];
 237   
     }
 238   
 
 239   
 
 240   
 
 241   
 
 242   
 
 243   
 
 244   
     //---------------------------------------------------------------------------
 245   
     // SOURCE CREATION
 246   
 
 247   
     /**
 248   
      * Adds a set of file paths to the unit.
 249   
      */
 250   
 
 251  0
     public void addSources(String[] paths) {
 252  0
         for (int i = 0; i < paths.length; i++) {
 253  0
             File file = new File(paths[i]);
 254  0
             addSource(file);
 255   
         }
 256   
     }
 257   
 
 258   
 
 259   
     /**
 260   
      * Adds a set of source files to the unit.
 261   
      */
 262   
 
 263  0
     public void addSources(File[] files) {
 264  0
         for (int i = 0; i < files.length; i++) {
 265  0
             addSource(files[i]);
 266   
         }
 267   
     }
 268   
 
 269   
 
 270   
     /**
 271   
      * Adds a source file to the unit.
 272   
      */
 273   
 
 274  0
     public SourceUnit addSource(File file) {
 275  0
         return addSource(new SourceUnit(file, configuration, classLoader));
 276   
     }
 277   
 
 278   
 
 279   
     /**
 280   
      * Adds a source file to the unit.
 281   
      */
 282   
 
 283  0
     public SourceUnit addSource(URL url) {
 284  0
         return addSource(new SourceUnit(url, configuration, classLoader));
 285   
     }
 286   
 
 287   
 
 288   
     /**
 289   
      * Adds a InputStream source to the unit.
 290   
      */
 291   
 
 292  0
     public SourceUnit addSource(String name, InputStream stream) {
 293  0
         ReaderSource source = new InputStreamReaderSource(stream, configuration);
 294  0
         return addSource(new SourceUnit(name, source, configuration, classLoader));
 295   
     }
 296   
 
 297   
 
 298   
     /**
 299   
      * Adds a SourceUnit to the unit.
 300   
      */
 301   
 
 302  0
     public SourceUnit addSource(SourceUnit source) {
 303  0
         String name = source.getName();
 304   
 
 305  0
         source.setClassLoader(this.classLoader);
 306   
 
 307  0
         names.add(name);
 308  0
         sources.put(name, source);
 309   
 
 310  0
         return source;
 311   
     }
 312   
 
 313   
 
 314   
     /**
 315   
      * Returns an iterator on the unit's SourceUnits.
 316   
      */
 317   
 
 318  0
     public Iterator iterator() {
 319  0
         return new Iterator() {
 320   
             Iterator nameIterator = names.iterator();
 321   
 
 322  0
             public boolean hasNext() {
 323  0
                 return nameIterator.hasNext();
 324   
             }
 325   
 
 326  0
             public Object next() {
 327  0
                 String name = (String) nameIterator.next();
 328  0
                 return sources.get(name);
 329   
             }
 330   
 
 331  0
             public void remove() {
 332  0
                 throw new UnsupportedOperationException();
 333   
             }
 334   
         };
 335   
     }
 336   
 
 337   
 
 338   
     /**
 339   
      * Adds a ClassNode directly to the unit (ie. without source).
 340   
      * Used primarily for testing support.
 341   
      */
 342   
 
 343  0
     public void addClassNode(ClassNode node) {
 344  0
         ModuleNode module = new ModuleNode(this.ast);
 345  0
         this.ast.addModule(module);
 346  0
         module.addClass(node);
 347   
     }
 348   
 
 349   
 
 350   
 
 351   
 
 352   
     //---------------------------------------------------------------------------
 353   
     // EXTERNAL CALLBACKS
 354   
 
 355   
     /**
 356   
      * A callback interface you can use to "accompany" the classgen()
 357   
      * code as it traverses the ClassNode tree.  You will be called-back
 358   
      * for each primary and inner class.  Use setClassgenCallback() before
 359   
      * running compile() to set your callback.
 360   
      */
 361   
 
 362   
     public static abstract class ClassgenCallback {
 363   
         public abstract void call(ClassVisitor writer, ClassNode node) throws CompilationFailedException;
 364   
     }
 365   
 
 366   
 
 367   
     /**
 368   
      * Sets a ClassgenCallback.  You can have only one, and setting
 369   
      * it to null removes any existing setting.
 370   
      */
 371   
 
 372  0
     public void setClassgenCallback(ClassgenCallback visitor) {
 373  0
         this.classgenCallback = visitor;
 374   
     }
 375   
 
 376   
 
 377   
     /**
 378   
      * A callback interface you can use to get a callback after every
 379   
      * unit of the compile process.  You will be called-back with a
 380   
      * ProcessingUnit and a phase indicator.  Use setProgressCallback()
 381   
      * before running compile() to set your callback.
 382   
      */
 383   
 
 384   
     public static abstract class ProgressCallback {
 385   
         public abstract void call(ProcessingUnit context, int phase) throws CompilationFailedException;
 386   
     }
 387   
 
 388   
 
 389   
     /**
 390   
      * Sets a ProgressCallback.  You can have only one, and setting
 391   
      * it to null removes any existing setting.
 392   
      */
 393   
 
 394  0
     public void setProgressCallback(ProgressCallback callback) {
 395  0
         this.progressCallback = callback;
 396   
     }
 397   
 
 398   
 
 399   
 
 400   
 
 401   
     //---------------------------------------------------------------------------
 402   
     // ACTIONS
 403   
 
 404   
 
 405   
     /**
 406   
      * Synonym for compile(Phases.ALL).
 407   
      */
 408   
 
 409  0
     public void compile() throws CompilationFailedException {
 410  0
         compile(Phases.ALL);
 411   
     }
 412   
 
 413   
 
 414   
     /**
 415   
      * Compiles the compilation unit from sources.
 416   
      */
 417   
 
 418  0
     public void compile(int throughPhase) throws CompilationFailedException {
 419   
         //
 420   
         // To support delta compilations, we always restart
 421   
         // the compiler.  The individual passes are responsible
 422   
         // for not reprocessing old code.
 423   
 
 424  0
         gotoPhase(Phases.INITIALIZATION);
 425   
 
 426  0
         do {
 427  0
             if (throughPhase < Phases.PARSING) {
 428  0
                 break;
 429   
             }
 430   
 
 431  0
             gotoPhase(Phases.PARSING);
 432  0
             parse();
 433   
 
 434  0
             if (throughPhase < Phases.CONVERSION) {
 435  0
                 break;
 436   
             }
 437   
 
 438  0
             gotoPhase(Phases.CONVERSION);
 439  0
             convert();
 440   
 
 441  0
             if (throughPhase < Phases.CLASS_GENERATION) {
 442  0
                 break;
 443   
             }
 444   
 
 445  0
             gotoPhase(Phases.CLASS_GENERATION);
 446  0
             classgen();
 447   
 
 448  0
             if (throughPhase < Phases.OUTPUT) {
 449  0
                 break;
 450   
             }
 451   
 
 452  0
             gotoPhase(Phases.OUTPUT);
 453  0
             output();
 454   
 
 455  0
             if (throughPhase < Phases.FINALIZATION) {
 456  0
                 break;
 457   
             }
 458   
 
 459  0
             gotoPhase(Phases.FINALIZATION);
 460   
 
 461   
         }
 462   
         while (false);
 463   
 
 464   
     }
 465   
 
 466   
 
 467   
     /**
 468   
      * Parses all sources.
 469   
      */
 470   
 
 471  0
     public void parse() throws CompilationFailedException {
 472  0
         if (this.phase != Phases.PARSING) {
 473  0
             throw new GroovyBugError("CompilationUnit not read for parse()");
 474   
         }
 475   
 
 476  0
         applyToSourceUnits(parse);
 477   
 
 478  0
         completePhase();
 479  0
         applyToSourceUnits(mark);
 480   
     }
 481   
 
 482   
 
 483   
     /**
 484   
      * Runs parse() on a single SourceUnit.
 485   
      */
 486   
 
 487   
     private LoopBodyForSourceUnitOperations parse = new LoopBodyForSourceUnitOperations() {
 488  0
         public void call(SourceUnit source) throws CompilationFailedException {
 489  0
             source.parse();
 490   
 
 491  0
             if (CompilationUnit.this.progressCallback != null) {
 492  0
                 CompilationUnit.this.progressCallback.call(source, CompilationUnit.this.phase);
 493   
             }
 494   
         }
 495   
     };
 496   
 
 497   
 
 498   
     /**
 499   
      * Builds ASTs for all parsed sources.
 500   
      */
 501   
 
 502  0
     public void convert() throws CompilationFailedException {
 503  0
         if (this.phase != Phases.CONVERSION) {
 504  0
             throw new GroovyBugError("CompilationUnit not ready for convert()");
 505   
         }
 506   
 
 507  0
         applyToSourceUnits(convert);
 508   
 
 509  0
         completePhase();
 510  0
         applyToSourceUnits(mark);
 511   
     }
 512   
 
 513   
 
 514   
     /**
 515   
      * Runs convert() on a single SourceUnit.
 516   
      */
 517   
 
 518   
     private LoopBodyForSourceUnitOperations convert = new LoopBodyForSourceUnitOperations() {
 519  0
         public void call(SourceUnit source) throws CompilationFailedException {
 520  0
             source.convert();
 521  0
             CompilationUnit.this.ast.addModule(source.getAST());
 522   
 
 523  0
             if (CompilationUnit.this.progressCallback != null) {
 524  0
                 CompilationUnit.this.progressCallback.call(source, CompilationUnit.this.phase);
 525   
             }
 526   
         }
 527   
     };
 528   
 
 529   
 
 530   
     /**
 531   
      * Expands and canonicalizes the ASTs generated during
 532   
      * parsing and conversion, then generates classes.
 533   
      */
 534   
 
 535  0
     public void classgen() throws CompilationFailedException {
 536  0
         if (this.phase != Phases.CLASS_GENERATION) {
 537  0
             throw new GroovyBugError("CompilationUnit not ready for classgen()");
 538   
         }
 539   
 
 540  0
         applyToPrimaryClassNodes(classgen);
 541   
 
 542  0
         completePhase();
 543  0
         applyToSourceUnits(mark);
 544   
 
 545   
 
 546   
         //
 547   
         // Callback progress, if necessary
 548   
 
 549  0
         if (this.progressCallback != null) {
 550  0
             this.progressCallback.call(this, CompilationUnit.this.phase);
 551   
         }
 552   
 
 553   
     }
 554   
 
 555   
 
 556   
     /**
 557   
      * Runs classgen() on a single ClassNode.
 558   
      */
 559   
 
 560   
     private LoopBodyForPrimaryClassNodeOperations classgen = new LoopBodyForPrimaryClassNodeOperations() {
 561  0
         public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
 562   
             //
 563   
             // Run the Verifier on the outer class
 564   
 
 565  0
             verifier.visitClass(classNode);
 566   
 
 567   
 
 568   
             //
 569   
             // Prep the generator machinery
 570   
 
 571  0
             ClassVisitor visitor = createClassVisitor();
 572   
 
 573  0
             String sourceName = (source == null ? classNode.getModule().getDescription() : source.getName());
 574  0
             ClassGenerator generator = new AsmClassGenerator2(context, visitor, classLoader, sourceName);
 575   
 
 576   
             //
 577   
             // Run the generation and create the class (if required)
 578   
 
 579  0
             generator.visitClass(classNode);
 580  0
             completionVerifier.visitClass(classNode);
 581   
 
 582  0
             if (!debug) {
 583  0
                 byte[] bytes = ((ClassWriter) visitor).toByteArray();
 584  0
                 /* this. */classes.add(new GroovyClass(classNode.getName(), bytes));
 585   
             }
 586   
 
 587   
 
 588   
 
 589   
 
 590   
             //
 591   
             // Handle any callback that's been set
 592   
 
 593  0
             if (CompilationUnit.this.classgenCallback != null) {
 594  0
                 if (debug) {
 595  0
                     try {
 596  0
                         classgenCallback.call(visitor, classNode);
 597   
                     }
 598   
                     catch (Throwable t) {
 599  0
                         output.println("Classgen callback threw: " + t);
 600  0
                         t.printStackTrace(output);
 601   
                     }
 602   
                 }
 603   
                 else {
 604  0
                     classgenCallback.call(visitor, classNode);
 605   
                 }
 606   
             }
 607   
 
 608   
 
 609   
             //
 610   
             // Recurse for inner classes
 611   
 
 612  0
             LinkedList innerClasses = generator.getInnerClasses();
 613  0
             while (!innerClasses.isEmpty()) {
 614  0
                 classgen.call(source, context, (ClassNode) innerClasses.removeFirst());
 615   
             }
 616   
 
 617   
         }
 618   
 
 619   
     };
 620   
 
 621  0
     protected ClassVisitor createClassVisitor() {
 622   
         /** avoid runtime dependency on asm util
 623   
          ClassVisitor visitor;
 624   
          if( debug )
 625   
          {
 626   
          visitor = new DumpClassVisitor(output);
 627   
          }
 628   
          else
 629   
 
 630   
          {
 631   
          visitor = new ClassWriter(true);
 632   
          }
 633   
          return visitor;
 634   
          */
 635  0
         return new ClassWriter(true);
 636   
     }
 637   
 
 638   
 
 639   
     /**
 640   
      * Outputs the generated class files to permanent storage.
 641   
      */
 642   
 
 643  0
     public void output() throws CompilationFailedException {
 644  0
         if (this.phase != Phases.OUTPUT && !(this.phase == Phases.CLASS_GENERATION && this.phaseComplete)) {
 645  0
             throw new GroovyBugError("CompilationUnit not ready for output()");
 646   
         }
 647   
 
 648  0
         boolean failures = false;
 649   
 
 650  0
         Iterator iterator = this.classes.iterator();
 651  0
         while (iterator.hasNext()) {
 652   
             //
 653   
             // Get the class and calculate its filesystem name
 654   
             
 655  0
             GroovyClass gclass = (GroovyClass) iterator.next();
 656  0
             String name = gclass.getName().replace('.', File.separatorChar) + ".class";
 657  0
             File path = new File(configuration.getTargetDirectory(), name);
 658   
             
 659   
             //
 660   
             // Ensure the path is ready for the file
 661   
             
 662  0
             File directory = path.getParentFile();
 663  0
             if (directory != null && !directory.exists()) {
 664  0
                 directory.mkdirs();
 665   
             }
 666   
 
 667   
             //
 668   
             // Create the file and write out the data
 669   
             
 670  0
             byte[] bytes = gclass.getBytes();
 671   
 
 672  0
             FileOutputStream stream = null;
 673  0
             try {
 674  0
                 stream = new FileOutputStream(path);
 675  0
                 stream.write(bytes, 0, bytes.length);
 676   
             }
 677   
             catch (IOException e) {
 678  0
                 addError(Message.create(e.getMessage()));
 679  0
                 failures = true;
 680   
             }
 681   
             finally {
 682  0
                 if (stream != null) {
 683  0
                     try {
 684  0
                         stream.close();
 685   
                     }
 686   
                     catch (Exception e) {
 687   
                     }
 688   
                 }
 689   
             }
 690   
         }
 691   
 
 692  0
         if (failures) {
 693  0
             fail();
 694   
         }
 695   
 
 696  0
         completePhase();
 697  0
         applyToSourceUnits(mark);
 698   
 
 699   
 
 700   
         //
 701   
         // Callback progress, if necessary
 702   
 
 703  0
         if (CompilationUnit.this.progressCallback != null) {
 704  0
             CompilationUnit.this.progressCallback.call(this, this.phase);
 705   
         }
 706   
     }
 707   
 
 708   
 
 709   
     /**
 710   
      * Returns true if there are any errors pending.
 711   
      */
 712   
 
 713  0
     public boolean hasErrors() {
 714  0
         boolean hasErrors = false;
 715   
 
 716  0
         Iterator keys = names.iterator();
 717  0
         while (keys.hasNext()) {
 718  0
             String name = (String) keys.next();
 719  0
             SourceUnit source = (SourceUnit) sources.get(name);
 720   
 
 721  0
             if (source.hasErrors()) {
 722  0
                 hasErrors = true;
 723  0
                 break;
 724   
             }
 725   
         }
 726   
 
 727  0
         return hasErrors || super.hasErrors();
 728   
     }
 729   
 
 730   
 
 731   
 
 732   
 
 733   
     //---------------------------------------------------------------------------
 734   
     // PHASE HANDLING
 735   
 
 736   
 
 737   
     /**
 738   
      * Updates the phase marker on all sources.
 739   
      */
 740   
 
 741  0
     protected void mark() throws CompilationFailedException {
 742  0
         applyToSourceUnits(mark);
 743   
     }
 744   
 
 745   
 
 746   
     /**
 747   
      * Marks a single SourceUnit with the current phase,
 748   
      * if it isn't already there yet.
 749   
      */
 750   
 
 751   
     private LoopBodyForSourceUnitOperations mark = new LoopBodyForSourceUnitOperations() {
 752  0
         public void call(SourceUnit source) throws CompilationFailedException {
 753  0
             if (source.phase < phase) {
 754  0
                 source.gotoPhase(phase);
 755   
             }
 756   
 
 757  0
             if (source.phase == phase && phaseComplete && !source.phaseComplete) {
 758  0
                 source.completePhase();
 759   
             }
 760   
         }
 761   
     };
 762   
 
 763   
 
 764   
 
 765   
 
 766   
     //---------------------------------------------------------------------------
 767   
     // LOOP SIMPLIFICATION FOR SourceUnit OPERATIONS
 768   
 
 769   
     /**
 770   
      * An callback interface for use in the applyToSourceUnits loop driver.
 771   
      */
 772   
 
 773   
     public abstract class LoopBodyForSourceUnitOperations {
 774   
         public abstract void call(SourceUnit source) throws CompilationFailedException;
 775   
     }
 776   
 
 777   
 
 778   
     /**
 779   
      * A loop driver for applying operations to all SourceUnits.
 780   
      * Automatically skips units that have already been processed
 781   
      * through the current phase.
 782   
      */
 783   
 
 784  0
     public void applyToSourceUnits(LoopBodyForSourceUnitOperations body) throws CompilationFailedException {
 785  0
         boolean failures = false;
 786   
 
 787  0
         Iterator keys = names.iterator();
 788  0
         while (keys.hasNext()) {
 789  0
             String name = (String) keys.next();
 790  0
             SourceUnit source = (SourceUnit) sources.get(name);
 791  0
             if (source.phase <= phase) {
 792  0
                 try {
 793  0
                     body.call(source);
 794   
                 }
 795   
                 catch (CompilationFailedException e) {
 796  0
                     failures = true;
 797   
                 }
 798   
                 catch (Exception e) {
 799  0
                     throw new GroovyBugError(e);
 800   
                 }
 801   
             }
 802   
         }
 803   
 
 804  0
         if (failures) {
 805  0
             fail();
 806   
         }
 807   
     }
 808   
 
 809   
 
 810   
 
 811   
 
 812   
     //---------------------------------------------------------------------------
 813   
     // LOOP SIMPLIFICATION FOR PRIMARY ClassNode OPERATIONS
 814   
 
 815   
 
 816   
     /**
 817   
      * An callback interface for use in the applyToSourceUnits loop driver.
 818   
      */
 819   
 
 820   
     public abstract class LoopBodyForPrimaryClassNodeOperations {
 821   
         public abstract void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException;
 822   
     }
 823   
 
 824   
 
 825   
     /**
 826   
      * A loop driver for applying operations to all primary ClassNodes in
 827   
      * our AST.  Automatically skips units that have already been processed
 828   
      * through the current phase.
 829   
      */
 830   
 
 831  0
     public void applyToPrimaryClassNodes(LoopBodyForPrimaryClassNodeOperations body) throws CompilationFailedException {
 832  0
         boolean failures = false;
 833   
 
 834  0
         Iterator modules = this.ast.getModules().iterator();
 835  0
         while (modules.hasNext()) {
 836  0
             ModuleNode module = (ModuleNode) modules.next();
 837   
 
 838  0
             try {
 839  0
                 Iterator classNodes = module.getClasses().iterator();
 840  0
                 while (classNodes.hasNext()) {
 841  0
                     ClassNode classNode = (ClassNode) classNodes.next();
 842  0
                     SourceUnit context = module.getContext();
 843  0
                     if (context == null || context.phase <= phase) {
 844  0
                         body.call(module.getContext(), new GeneratorContext(this.ast), classNode);
 845   
                     }
 846   
                 }
 847   
             }
 848   
             catch (CompilationFailedException e) {
 849  0
                 e.printStackTrace();
 850  0
                 failures = true;
 851  0
                 addError(new ExceptionMessage(e));
 852   
             }
 853   
             catch (Exception e) {
 854  0
                 failures = true;
 855  0
                 e.printStackTrace();
 856   
 //                String msg = e.getMessage();
 857   
 //                if (e instanceof RuntimeParserException) {
 858   
 //                    RuntimeParserException rpe = (RuntimeParserException) e;
 859   
 //                    ASTNode node = rpe.getNode();
 860   
 //                    msg += ". The probable error location: [" + node.getLineNumber() + ":" + node.getColumnNumber() + "]";
 861   
 //                }
 862  0
                 addError(new ExceptionMessage(e));
 863   
             }
 864   
         }
 865   
 
 866  0
         if (failures) {
 867  0
             fail();
 868   
         }
 869   
     }
 870   
 
 871   
 
 872   
 
 873   
 
 874   
     //---------------------------------------------------------------------------
 875   
     // OUTPUT
 876   
 
 877   
 
 878   
     /**
 879   
      * Writes error messages to the specified PrintWriter.
 880   
      */
 881   
 
 882  0
     public void write(PrintWriter writer, Janitor janitor) {
 883  0
         super.write(writer, janitor);
 884   
 
 885  0
         Iterator keys = names.iterator();
 886  0
         while (keys.hasNext()) {
 887  0
             String name = (String) keys.next();
 888  0
             SourceUnit source = (SourceUnit) sources.get(name);
 889   
 
 890  0
             if (source.hasErrors()) {
 891  0
                 source.write(writer, janitor);
 892   
             }
 893   
         }
 894   
 
 895   
     }
 896   
 
 897   
 
 898   
 }
 899   
 
 900   
 
 901   
 
 902   
 
 903