Coverage Report - com.sun.tools.javafx.main.Main
 
Classes in this File Line Coverage Branch Coverage Complexity
Main
42%
125/297
39%
62/157
0
Main$1
22%
4/18
100%
2/2
0
Main$2
0%
0/2
N/A
0
Main$3
0%
0/2
N/A
0
Main$DiagnosticForwarder
100%
6/6
N/A
0
 
 1  
 /*
 2  
  * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
 3  
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 4  
  *
 5  
  * This code is free software; you can redistribute it and/or modify it
 6  
  * under the terms of the GNU General Public License version 2 only, as
 7  
  * published by the Free Software Foundation.  Sun designates this
 8  
  * particular file as subject to the "Classpath" exception as provided
 9  
  * by Sun in the LICENSE file that accompanied this code.
 10  
  *
 11  
  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  
  * version 2 for more details (a copy is included in the LICENSE file that
 15  
  * accompanied this code).
 16  
  *
 17  
  * You should have received a copy of the GNU General Public License version
 18  
  * 2 along with this work; if not, write to the Free Software Foundation,
 19  
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  
  *
 21  
  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 22  
  * CA 95054 USA or visit www.sun.com if you need additional information or
 23  
  * have any questions.
 24  
  */
 25  
 
 26  
 package com.sun.tools.javafx.main;
 27  
 
 28  
 import com.sun.tools.javac.util.Options;
 29  
 import java.io.File;
 30  
 import java.io.FilenameFilter;
 31  
 import java.io.Reader;
 32  
 import java.io.InputStream;
 33  
 import java.io.InputStreamReader;
 34  
 import java.io.IOException;
 35  
 import java.io.PrintWriter;
 36  
 import java.net.URL;
 37  
 import java.net.URLClassLoader;
 38  
 import java.util.ResourceBundle;
 39  
 import java.util.MissingResourceException;
 40  
 import com.sun.tools.javac.code.Source;
 41  
 import com.sun.tools.javac.jvm.Target;
 42  
 import com.sun.tools.javac.jvm.ClassReader;
 43  
 import com.sun.tools.javafx.main.JavafxOption.Option;
 44  
 import com.sun.tools.javac.util.*;
 45  
 import com.sun.tools.javafx.main.RecognizedOptions.OptionHelper;
 46  
 import com.sun.tools.javafx.util.JavafxFileManager;
 47  
 import com.sun.tools.javafx.util.PlatformPlugin;
 48  
 import com.sun.tools.javafx.util.MsgSym;
 49  
 import javax.tools.Diagnostic;
 50  
 import javax.tools.JavaFileManager;
 51  
 import javax.tools.JavaFileObject;
 52  
 import javax.tools.DiagnosticListener;
 53  
 
 54  
 /** This class provides a commandline interface to the GJC compiler.
 55  
  *
 56  
  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
 57  
  *  you write code that depends on this, you do so at your own risk.
 58  
  *  This code and its internal interfaces are subject to change or
 59  
  *  deletion without notice.</b>
 60  
  */
 61  
 public class Main {
 62  
 
 63  
     /** The name of the compiler, for use in diagnostics.
 64  
      */
 65  
     String ownName;
 66  
 
 67  
     /** The writer to use for diagnostic output.
 68  
      */
 69  
     PrintWriter out;
 70  
 
 71  
     /**
 72  
      * If true, any command line arg errors will cause an exception.
 73  
      */
 74  
     boolean fatalErrors;
 75  
 
 76  
     /** Result codes.
 77  
      */
 78  
     static final int
 79  
         EXIT_OK = 0,        // Compilation completed with no errors.
 80  
         EXIT_ERROR = 1,     // Completed but reported errors.
 81  
         EXIT_CMDERR = 2,    // Bad command-line arguments
 82  
         EXIT_SYSERR = 3,    // System error or resource exhaustion.
 83  
         EXIT_ABNORMAL = 4;  // Compiler terminated abnormally
 84  
 
 85  459
     private Option[] recognizedOptions = RecognizedOptions.getJavaCompilerOptions(new OptionHelper() {
 86  
 
 87  
         public void setOut(PrintWriter out) {
 88  0
             Main.this.out = out;
 89  0
         }
 90  
 
 91  
         public void error(String key, Object... args) {
 92  0
             Main.this.error(key, args);
 93  0
         }
 94  
 
 95  
         public void printVersion() {
 96  0
             Log.printLines(out, getLocalizedString(MsgSym.MESSAGE_VERSION, ownName,  JavafxCompiler.version()));
 97  0
         }
 98  
 
 99  
         public void printFullVersion() {
 100  0
             Log.printLines(out, getLocalizedString(MsgSym.MESSAGE_FULLVERSION, ownName,  JavafxCompiler.fullVersion()));
 101  0
         }
 102  
 
 103  
         public void printHelp() {
 104  0
             help();
 105  0
         }
 106  
 
 107  
         public void printXhelp() {
 108  0
             xhelp();
 109  0
         }
 110  
 
 111  
         public void addFile(File f) {
 112  365
             if (!filenames.contains(f))
 113  363
                 filenames.append(f);
 114  365
         }
 115  
 
 116  
         public void addClassName(String s) {
 117  0
             classnames.append(s);
 118  0
         }
 119  
 
 120  
     });
 121  
 
 122  
     /**
 123  
      * Construct a compiler instance.
 124  
      */
 125  
     public Main(String name) {
 126  0
         this(name, new PrintWriter(System.err, true));
 127  0
     }
 128  
 
 129  
     /**
 130  
      * Construct a compiler instance.
 131  
      */
 132  459
     public Main(String name, PrintWriter out) {
 133  459
         this.ownName = name;
 134  459
         this.out = out;
 135  459
     }
 136  
     /** A table of all options that's passed to the JavaCompiler constructor.  */
 137  459
     private Options options = null;
 138  
 
 139  
     /** The list of source files to process
 140  
      */
 141  459
     public ListBuffer<File> filenames = null; // XXX sb protected
 142  
 
 143  
     /** List of class files names passed on the command line
 144  
      */
 145  459
     public ListBuffer<String> classnames = null; // XXX sb protected
 146  
 
 147  
     /** Print a string that explains usage.
 148  
      */
 149  
     void help() {
 150  0
         Log.printLines(out, getLocalizedString(MsgSym.MESSAGE_MSG_USAGE_HEADER, ownName));
 151  0
         for (int i=0; i<recognizedOptions.length; i++) {
 152  0
             recognizedOptions[i].help(out);
 153  
         }
 154  0
         out.println();
 155  0
     }
 156  
 
 157  
     /** Print a string that explains usage for X options.
 158  
      */
 159  
     void xhelp() {
 160  0
         for (int i=0; i<recognizedOptions.length; i++) {
 161  0
             recognizedOptions[i].xhelp(out);
 162  
         }
 163  0
         out.println();
 164  0
         Log.printLines(out, getLocalizedString(MsgSym.MESSAGE_MSG_USAGE_NONSTANDARD_FOOTER));
 165  0
     }
 166  
 
 167  
     /** Report a usage error.
 168  
      */
 169  
     void error(String key, Object... args) {
 170  0
         if (fatalErrors) {
 171  0
             String msg = getLocalizedString(key, args);
 172  0
             throw new PropagatedException(new IllegalStateException(msg));
 173  
         }
 174  0
         warning(key, args);
 175  0
         Log.printLines(out, getLocalizedString(MsgSym.MESSAGE_MSG_USAGE, ownName));
 176  0
     }
 177  
 
 178  
     /** Report a warning.
 179  
      */
 180  
     void warning(String key, Object... args) {
 181  0
         Log.printLines(out, ownName + ": "
 182  
                        + getLocalizedString(key, args));
 183  0
     }
 184  
 
 185  
     public Option getOption(String flag) {
 186  0
         for (Option option : recognizedOptions) {
 187  0
             if (option.matches(flag))
 188  0
                 return option;
 189  
         }
 190  0
         return null;
 191  
     }
 192  
 
 193  
     public void setOptions(Options options) {
 194  75
         if (options == null)
 195  0
             throw new NullPointerException();
 196  75
         this.options = options;
 197  75
     }
 198  
 
 199  
     public void setFatalErrors(boolean fatalErrors) {
 200  0
         this.fatalErrors = fatalErrors;
 201  0
     }
 202  
 
 203  
     /** Process command line arguments: store all command line options
 204  
      *  in `options' table and return all source filenames.
 205  
      *  @param flags    The array of command line arguments.
 206  
      */
 207  
     public List<File> processArgs(String[] flags) { // XXX sb protected
 208  399
         int ac = 0;
 209  1989
         while (ac < flags.length) {
 210  1590
             String flag = flags[ac];
 211  1590
             ac++;
 212  
 
 213  
             int j;
 214  
             // quick hack to speed up file processing: 
 215  
             // if the option does not begin with '-', there is no need to check
 216  
             // most of the compiler options.
 217  1590
             int firstOptionToCheck = flag.charAt(0) == '-' ? 0 : recognizedOptions.length-1;
 218  24667
             for (j=firstOptionToCheck; j<recognizedOptions.length; j++)
 219  24667
                 if (recognizedOptions[j].matches(flag)) break;
 220  
 
 221  1590
             if (j == recognizedOptions.length) {
 222  0
                 error(MsgSym.MESSAGE_ERR_INVALID_FLAG, flag);
 223  0
                 return null;
 224  
             }
 225  
 
 226  1590
             Option option = recognizedOptions[j];
 227  1590
             if (option.hasArg()) {
 228  1109
                 if (ac == flags.length) {
 229  0
                     error(MsgSym.MESSAGE_ERR_REQ_ARG, flag);
 230  0
                     return null;
 231  
                 }
 232  1109
                 String operand = flags[ac];
 233  1109
                 ac++;
 234  1109
                 if (option.process(options, flag, operand))
 235  0
                     return null;
 236  1109
             } else {
 237  481
                 if (option.process(options, flag))
 238  0
                     return null;
 239  
             }
 240  1590
         }
 241  
         
 242  399
         if (!checkDirectory("-d"))
 243  0
             return null;
 244  399
         if (!checkDirectory("-s"))
 245  0
             return null;
 246  
 
 247  399
         String sourceString = options.get("-source");
 248  399
         Source source = (sourceString != null)
 249  
             ? Source.lookup(sourceString)
 250  
             : Source.DEFAULT;
 251  399
         String targetString = options.get("-target");
 252  399
         Target target = (targetString != null)
 253  
             ? Target.lookup(targetString)
 254  
             : Target.DEFAULT;
 255  
         // We don't check source/target consistency for CLDC, as J2ME
 256  
         // profiles are not aligned with J2SE targets; moreover, a
 257  
         // single CLDC target may have many profiles.  In addition,
 258  
         // this is needed for the continued functioning of the JSR14
 259  
         // prototype.
 260  399
         if (Character.isDigit(target.name.charAt(0))) {
 261  399
             if (target.compareTo(source.requiredTarget()) < 0) {
 262  0
                 if (targetString != null) {
 263  0
                     if (sourceString == null) {
 264  0
                         warning(MsgSym.MESSAGE_WARN_TARGET_DEFAULT_SOURCE_CONFLICT,
 265  
                                 targetString,
 266  
                                 source.requiredTarget().name);
 267  
                     } else {
 268  0
                         warning(MsgSym.MESSAGE_WARN_SOURCE_TARGET_CONFLICT,
 269  
                                 sourceString,
 270  
                                 source.requiredTarget().name);
 271  
                     }
 272  0
                     return null;
 273  
                 } else {
 274  0
                     options.put("-target", source.requiredTarget().name);
 275  
                 }
 276  
             } else {
 277  399
                 if (targetString == null && !source.allowGenerics()) {
 278  0
                     options.put("-target", Target.JDK1_4.name);
 279  
                 }
 280  
             }
 281  
         }
 282  399
         return filenames.toList();
 283  
     }
 284  
     // where
 285  
         private boolean checkDirectory(String optName) {
 286  798
             String value = options.get(optName);
 287  798
             if (value == null)
 288  447
                 return true;
 289  351
             File file = new File(value);
 290  351
             if (!file.exists()) {
 291  0
                 error(MsgSym.MESSAGE_ERR_DIR_NOT_FOUND, value);
 292  0
                 return false;
 293  
             }
 294  351
             if (!file.isDirectory()) {
 295  0
                 error(MsgSym.MESSAGE_ERR_FILE_NOT_DIRECTORY, value);
 296  0
                 return false;
 297  
             }
 298  351
             return true;
 299  
         }
 300  
 
 301  
     /** Programmatic interface for main function.
 302  
      * @param args    The command line parameters.
 303  
      */
 304  
     public int compile(String[] args) {
 305  351
         Context context = new Context();
 306  351
         int result = compile(args, context, List.<JavaFileObject>nil());
 307  351
         if (fileManager instanceof JavacFileManager) {
 308  
             // A fresh context was created above, so jfm must be a JavacFileManager
 309  351
             ((JavacFileManager)fileManager).close();
 310  
         }
 311  351
         return result;
 312  
     }
 313  
     
 314  
     public void registerServices(Context context, String[] args) {
 315  399
         Context backEndContext = new Context();
 316  399
         backEndContext.put(DiagnosticListener.class, new DiagnosticForwarder(context));
 317  
         // add -target flag to backEndContext, if specified
 318  399
         options = Options.instance(backEndContext);
 319  
         try {
 320  399
             String[] allArgs = CommandLine.parse(args);
 321  2719
             for (int i = 0; i < allArgs.length; i++) {
 322  2320
                 if (allArgs[i].endsWith("-target") && ++i < allArgs.length)
 323  379
                     options.put("-target", allArgs[i]);
 324  
             }
 325  0
         } catch (IOException e) {
 326  
             // ignore: will be caught and reported on second command line parse.
 327  399
         }
 328  399
         options = null;
 329  399
         filenames = null;
 330  
         
 331  399
         com.sun.tools.javafx.comp.JavafxFlow.preRegister(backEndContext);
 332  399
         com.sun.tools.javafx.code.JavafxLint.preRegister(backEndContext);
 333  399
         com.sun.tools.javafx.code.BlockExprSymtab.preRegister(backEndContext);
 334  399
         com.sun.tools.javafx.comp.BlockExprAttr.preRegister(backEndContext);
 335  399
         com.sun.tools.javafx.comp.BlockExprEnter.preRegister(backEndContext);
 336  399
         com.sun.tools.javafx.comp.BlockExprMemberEnter.preRegister(backEndContext);
 337  399
         com.sun.tools.javafx.comp.BlockExprResolve.preRegister(backEndContext);
 338  399
         com.sun.tools.javafx.comp.BlockExprLower.preRegister(backEndContext);
 339  399
         com.sun.tools.javafx.comp.BlockExprTransTypes.preRegister(backEndContext);
 340  399
         com.sun.tools.javafx.comp.BlockExprGen.preRegister(backEndContext);
 341  
         
 342  399
         JavaFileManager currentFileManager = context.get(JavaFileManager.class);
 343  399
         if (currentFileManager == null)
 344  351
             JavacFileManager.preRegister(backEndContext); 
 345  
         else
 346  48
             backEndContext.put(JavaFileManager.class, currentFileManager);
 347  
         
 348  
         // Sequencing requires that we get the name table from the fully initialized back-end
 349  
         // rather than send the completed one.
 350  399
         JavafxJavaCompiler javafxJavaCompiler = JavafxJavaCompiler.instance(backEndContext);
 351  
         
 352  399
         context.put(JavafxJavaCompiler.javafxJavaCompilerKey, javafxJavaCompiler);
 353  
         
 354  
         // Tranfer the name table -- must be done before any initialization
 355  399
         context.put(Name.Table.namesKey, backEndContext.get(Name.Table.namesKey));
 356  
 
 357  
         // Tranfer the options -- must be done before any initialization
 358  399
         context.put(Options.optionsKey, (Options)null);  // remove any old value
 359  399
         context.put(Options.optionsKey, backEndContext.get(Options.optionsKey));
 360  
 
 361  399
         ClassReader jreader = ClassReader.instance(backEndContext);
 362  399
         com.sun.tools.javafx.comp.JavafxClassReader.preRegister(context, jreader);
 363  
 
 364  399
         if (currentFileManager == null)
 365  351
             JavafxFileManager.preRegister(context); // can't create it until Log has been set up
 366  399
         com.sun.tools.javafx.code.JavafxLint.preRegister(context);
 367  399
     }
 368  
 
 369  
     /** Load a plug-in corresponding to platform option. If platform option had 
 370  
      *  not been defined, the method returns immediately. 
 371  
      * @param context The compiler context.
 372  
      * @param options The compiler options.
 373  
      */
 374  
     private void loadPlatformPlugin(Context context, Options options)
 375  
     {
 376  380
         String platform = options.get("-platform");
 377  380
         if (platform == null)
 378  380
             return;
 379  
 
 380  
         // collect names of jar files located in the compiler lib directory
 381  0
         String path = this.getClass().getCanonicalName();
 382  0
         path = path.substring(path.lastIndexOf('.') + 1);
 383  0
         path = this.getClass().getResource(path + ".class").toString();
 384  0
         path = path.substring(0, path.lastIndexOf(".jar!"));
 385  0
         path = path.substring("jar:file:".length(), path.lastIndexOf("/")); 
 386  0
         File   dir  = new File(path);
 387  0
         File[] jars = dir.listFiles(new FilenameFilter() {
 388  
             public boolean accept(File dir, String name) {
 389  0
                 return name.endsWith(".jar");
 390  
             }
 391  
         });
 392  
         // search for platform plugins in jar files collected above
 393  0
         PlatformPlugin plugin = null;
 394  0
         URL urls[] = new URL[1];
 395  0
         for (File jar : jars) {
 396  
             try {
 397  0
                 plugin  = null;
 398  0
                 urls[0] = jar.toURL();
 399  0
                 URLClassLoader loader = new URLClassLoader(urls);
 400  0
                 InputStream    stream = loader.getResourceAsStream(
 401  
                     "META-INF/services/" + PlatformPlugin.SERVICE);
 402  0
                 if (stream == null)
 403  0
                     continue;  // there is no platform plugin in this jar
 404  
                 // read service provider class name
 405  0
                 Reader reader = new InputStreamReader(stream);
 406  0
                 String pname  = Main.readServiceProvider(reader);
 407  
                 try { 
 408  0
                     reader.close(); 
 409  0
                 } catch (IOException ioe) {
 410  0
                 }
 411  0
                 if (pname == null) {
 412  0
                     Log.instance(context).warning(
 413  
                         MsgSym.MESSAGE_PLUGIN_CANNOT_LOAD_PLUGIN, urls[0].getPath());
 414  0
                     continue;
 415  
                 }
 416  
                 // load and instantiate plug-in class
 417  0
                 Class pclass = loader.loadClass(pname);
 418  0
                 plugin = (PlatformPlugin)pclass.newInstance();
 419  0
                 if (!plugin.isSupported(platform))
 420  0
                     continue;  // this plugin does not support required platform
 421  
                 try {
 422  
                     // attempt to load plug-in's messages
 423  0
                     Class mclass = loader.loadClass(PlatformPlugin.MESSAGE);
 424  0
                     ResourceBundle msgs = (ResourceBundle)mclass.newInstance();
 425  0
                     Messages.instance(context).add(msgs);
 426  0
                 } catch (java.lang.ClassNotFoundException cnfe) {
 427  0
                 } catch (java.lang.InstantiationException ie) {
 428  0
                 }
 429  0
                 plugin.initialize(options, Log.instance(context));
 430  
 
 431  0
                 context.put(PlatformPlugin.pluginKey, plugin);
 432  0
                 break;  // the plugin had been loaded; no need to continue
 433  
 
 434  0
             } catch (java.net.MalformedURLException murle) {
 435  
                 // cannot resolve URL: ignore this jar
 436  0
             } catch (java.lang.ClassNotFoundException cnfe) {
 437  
                 // cannot load service provider
 438  0
                 Log.instance(context).warning(
 439  
                     MsgSym.MESSAGE_PLUGIN_CANNOT_LOAD_PLUGIN, urls[0].getPath());
 440  0
             } catch (java.lang.InstantiationException ie) {
 441  
                 // cannot create an instance of plugin
 442  0
                 Log.instance(context).warning(
 443  
                     MsgSym.MESSAGE_PLUGIN_CANNOT_LOAD_PLUGIN, urls[0].getPath());
 444  0
             } catch (java.lang.IllegalAccessException iae) {
 445  
                 // cannot create an instance of plugin
 446  0
                 Log.instance(context).warning(
 447  
                     MsgSym.MESSAGE_PLUGIN_CANNOT_LOAD_PLUGIN, urls[0].getPath());
 448  0
             }
 449  
         }
 450  
         // handle no plugin found
 451  0
         if (plugin == null) {
 452  0
             Log.instance(context).error(
 453  
                 MsgSym.MESSAGE_PLUGIN_CANNOT_FIND_PLUGIN, platform);
 454  
         }
 455  0
     }
 456  
 
 457  
     /** Reads the first class name as defined by Jar &quot;Service provider&quot; 
 458  
      *  specification.
 459  
      * @param reader The reader of service provider configuration file.
 460  
      * @return Plugin&apos;s class name on successful read, null otherwise.
 461  
      */
 462  
     private static String readServiceProvider(Reader reader)
 463  
     {
 464  0
         StringBuffer name = new StringBuffer(128);
 465  0
         int st = 0;
 466  
         try {
 467  
             int ch;
 468  0
             while ((ch = reader.read()) >= 0) {
 469  0
                 switch (st) {
 470  
                 case 0:  // skip white spaces before class name
 471  0
                     switch (ch) {
 472  
                     case ' ':
 473  
                     case '\t':
 474  
                     case '\r':
 475  
                     case '\n':
 476  0
                         break;
 477  
 
 478  
                     case '#':
 479  0
                         st = 1;  // skip comment before the class name
 480  0
                         break;
 481  
 
 482  
                     default:
 483  0
                         name.append((char)ch);
 484  0
                         st = 2;  // accumulate characters of the class name
 485  0
                         break;
 486  
                     }
 487  
                     break;
 488  
 
 489  
                 case 1:  // skip comment before the class name
 490  0
                     switch (ch) {
 491  
                     case '\r':
 492  
                     case '\n':
 493  0
                         st = 0;  // skip white spaces before class name
 494  0
                         break;
 495  
 
 496  
                     default:
 497  0
                         break;
 498  
                     }
 499  
                     break;
 500  
 
 501  
                 case 2:  // accumulate characters of the class name
 502  0
                     switch (ch) {
 503  
                     case ' ':
 504  
                     case '\t':
 505  
                     case '\r':
 506  
                     case '\n':
 507  
                     case '#':
 508  0
                         return name.toString();
 509  
 
 510  
                     default:
 511  0
                         name.append((char)ch);
 512  0
                         break;
 513  
                     }
 514  
                     break;
 515  
 
 516  
                 default:
 517  0
                     return null;
 518  
                 }
 519  
             }
 520  0
         } catch (IOException ioe) {
 521  0
             return null;
 522  0
         }
 523  0
         return (st == 2)? name.toString(): null;
 524  
     }
 525  
 
 526  
     /** Programmatic interface for main function.
 527  
      * @param args    The command line parameters.
 528  
      */
 529  
     public int compile(String[] args,
 530  
                        Context context,
 531  
                        List<JavaFileObject> fileObjects)
 532  
     {
 533  380
         registerServices(context, args);
 534  380
         if (options == null)
 535  380
             options = Options.instance(context); // creates a new one
 536  
 
 537  380
         filenames = new ListBuffer<File>();
 538  380
         classnames = new ListBuffer<String>();
 539  380
         JavafxCompiler comp = null;
 540  
         /*
 541  
          * TODO: Logic below about what is an acceptable command line
 542  
          * should be updated to take annotation processing semantics
 543  
          * into account.
 544  
          */
 545  
         try {
 546  380
             if (args.length == 0 && fileObjects.isEmpty()) {
 547  0
                 help();
 548  0
                 return EXIT_CMDERR;
 549  
             }
 550  
 
 551  
             List<File> fnames;
 552  
             try {
 553  380
                 fnames = processArgs(CommandLine.parse(args));
 554  380
                 if (fnames == null) {
 555  
                     // null signals an error in options, abort
 556  0
                     return EXIT_CMDERR;
 557  380
                 } else if (fnames.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) {
 558  
                     // it is allowed to compile nothing if just asking for help or version info
 559  0
                     if (options.get("-help") != null
 560  
                         || options.get("-X") != null
 561  
                         || options.get("-version") != null
 562  
                         || options.get("-fullversion") != null)
 563  0
                         return EXIT_OK;
 564  0
                     error(MsgSym.MESSAGE_ERR_NO_SOURCE_FILES);
 565  0
                     return EXIT_CMDERR;
 566  
                 }
 567  0
             } catch (java.io.FileNotFoundException e) {
 568  0
                 Log.printLines(out, ownName + ": " +
 569  
                                getLocalizedString(MsgSym.MESSAGE_ERR_FILE_NOT_FOUND,
 570  
                                                   e.getMessage()));
 571  0
                 return EXIT_SYSERR;
 572  380
             }
 573  
 
 574  380
             boolean forceStdOut = options.get("stdout") != null;
 575  380
             if (forceStdOut) {
 576  0
                 out.flush();
 577  0
                 out = new PrintWriter(System.out, true);
 578  
             }
 579  
 
 580  380
             context.put(Log.outKey, out);
 581  
 
 582  380
             fileManager = context.get(JavaFileManager.class);
 583  
 
 584  380
             comp = JavafxCompiler.instance(context);
 585  380
             if (comp == null) return EXIT_SYSERR;
 586  
 
 587  380
             loadPlatformPlugin(context, options);
 588  
 
 589  380
             if (!fnames.isEmpty()) {
 590  
                 // add filenames to fileObjects
 591  351
                 comp = JavafxCompiler.instance(context);
 592  351
                 List<JavaFileObject> otherFiles = List.nil();
 593  351
                 JavacFileManager dfm = (JavacFileManager)fileManager;
 594  351
                 for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(fnames))
 595  363
                     otherFiles = otherFiles.prepend(fo);
 596  351
                 for (JavaFileObject fo : otherFiles)
 597  363
                     fileObjects = fileObjects.prepend(fo);
 598  
             }
 599  380
             comp.compile(fileObjects,
 600  
                          classnames.toList());
 601  
 
 602  377
             if (comp.errorCount() != 0 ||
 603  
                 options.get("-Werror") != null && comp.warningCount() != 0)
 604  51
                 return EXIT_ERROR;
 605  0
         } catch (IOException ex) {
 606  0
             ioMessage(ex);
 607  0
             return EXIT_SYSERR;
 608  0
         } catch (OutOfMemoryError ex) {
 609  0
             resourceMessage(ex);
 610  0
             return EXIT_SYSERR;
 611  0
         } catch (StackOverflowError ex) {
 612  0
             resourceMessage(ex);
 613  0
             return EXIT_SYSERR;
 614  0
         } catch (FatalError ex) {
 615  0
             feMessage(ex);
 616  0
             return EXIT_SYSERR;
 617  0
         } catch (ClientCodeException ex) {
 618  
             // as specified by javax.tools.JavaCompiler#getTask
 619  
             // and javax.tools.JavaCompiler.CompilationTask#call
 620  0
             throw new RuntimeException(ex.getCause());
 621  0
         } catch (PropagatedException ex) {
 622  0
             throw ex.getCause();
 623  3
         } catch (Throwable ex) {
 624  
             // Nasty.  If we've already reported an error, compensate
 625  
             // for buggy compiler error recovery by swallowing thrown
 626  
             // exceptions.
 627  3
             if (comp == null || comp.errorCount() == 0 ||
 628  
                 options == null || options.get("dev") != null)
 629  0
                 bugMessage(ex);
 630  3
             return EXIT_ABNORMAL;
 631  
         } finally {
 632  380
             if (comp != null) comp.close();
 633  380
             filenames = null;
 634  380
             options = null;
 635  326
         }
 636  326
         return EXIT_OK;
 637  
     }
 638  
 
 639  
     /** Print a message reporting an internal error.
 640  
      */
 641  
     void bugMessage(Throwable ex) {
 642  0
         Log.printLines(out, getJavafxLocalizedString(MsgSym.MESSAGE_JAVAFX_MSG_BUG,
 643  
                                                JavafxCompiler.version()));
 644  0
         ex.printStackTrace(out);
 645  0
     }
 646  
 
 647  
     /** Print a message reporting an fatal error.
 648  
      */
 649  
     void feMessage(Throwable ex) {
 650  0
         Log.printLines(out, ex.getMessage());
 651  0
     }
 652  
 
 653  
     /** Print a message reporting an input/output error.
 654  
      */
 655  
     void ioMessage(Throwable ex) {
 656  0
         Log.printLines(out, getLocalizedString(MsgSym.MESSAGE_MSG_IO));
 657  0
         ex.printStackTrace(out);
 658  0
     }
 659  
 
 660  
     /** Print a message reporting an out-of-resources error.
 661  
      */
 662  
     void resourceMessage(Throwable ex) {
 663  0
         Log.printLines(out, getLocalizedString(MsgSym.MESSAGE_MSG_RESOURCE));
 664  
 //      System.out.println("(name buffer len = " + Name.names.length + " " + Name.nc);//DEBUG
 665  0
         ex.printStackTrace(out);
 666  0
     }
 667  
 
 668  
     private JavaFileManager fileManager;
 669  
 
 670  
     /* ************************************************************************
 671  
      * Internationalization
 672  
      *************************************************************************/
 673  
 
 674  
     /** Find a localized string in the resource bundle.
 675  
      *  @param key     The key for the localized string.
 676  
      */
 677  
     public static String getLocalizedString(String key, Object... args) { // FIXME sb private
 678  
         try {
 679  0
             if (messages == null)
 680  0
                 messages = new Messages(javacBundleName);
 681  0
             return messages.getLocalizedString(MsgSym.MESSAGEPREFIX_JAVAC + key, args);
 682  
         }
 683  0
         catch (MissingResourceException e) {
 684  0
             throw new Error("Fatal Error: Resource for javac is missing", e);
 685  
         }
 686  
     }
 687  
 
 688  
     /** Find a localized string in the resource bundle.
 689  
      *  @param key     The key for the localized string.
 690  
      */
 691  
     public static String getJavafxLocalizedString(String key, Object... args) { // FIXME sb private
 692  
         try {
 693  0
             Messages fxmessages = new Messages(javafxBundleName);
 694  0
             return fxmessages.getLocalizedString(key, args);
 695  
         }
 696  0
         catch (MissingResourceException e) {
 697  0
             throw new Error("Fatal Error: Resource for javac is missing", e);
 698  
         }
 699  
     }
 700  
 
 701  
     public static void useRawMessages(boolean enable) {
 702  0
         if (enable) {
 703  0
             messages = new Messages(javacBundleName) {
 704  
                 @Override
 705  
                 public String getLocalizedString(String key, Object... args) {
 706  0
                     return key;
 707  
                 }
 708  
             };
 709  
         } else {
 710  0
             messages = new Messages(javacBundleName);
 711  
         }
 712  0
     }
 713  
 
 714  
     private static final String javacBundleName =
 715  
         "com.sun.tools.javac.resources.javac";
 716  
 
 717  
     private static final String javafxBundleName =
 718  
         "com.sun.tools.javafx.resources.javafxcompiler";
 719  
 
 720  
     private static Messages messages;
 721  
 
 722  
     private static class DiagnosticForwarder implements DiagnosticListener {
 723  
         Context otherContext;
 724  
 
 725  399
         public DiagnosticForwarder(Context context) {
 726  399
             otherContext = context;
 727  399
         }
 728  
 
 729  
         public void report(Diagnostic diag) {
 730  5
             Log log = Log.instance(otherContext);
 731  5
             log.report((JCDiagnostic)diag);
 732  5
         }
 733  
     }
 734  
 }