Logo Search packages:      
Sourcecode: ecj version File versions

Main.java

/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Tom Tromey - Contribution for bug 125961
 *     Tom Tromey - Contribution for bug 159641
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.batch;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.StringTokenizer;

import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
import org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRule;
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.compiler.util.GenericXMLWriter;
import org.eclipse.jdt.internal.compiler.util.Messages;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.Util;

public class Main implements ProblemSeverities, SuffixConstants {

      public static class Logger {
            private static final String CLASS = "class"; //$NON-NLS-1$
            private static final String CLASS_FILE = "classfile"; //$NON-NLS-1$
            private static final String CLASSPATH = "classpath"; //$NON-NLS-1$
            private static final String CLASSPATH_FILE = "FILE"; //$NON-NLS-1$
            private static final String CLASSPATH_FOLDER = "FOLDER"; //$NON-NLS-1$
            private static final String CLASSPATH_ID = "id"; //$NON-NLS-1$
            private static final String CLASSPATH_JAR = "JAR"; //$NON-NLS-1$
            private static final String CLASSPATHS = "classpaths"; //$NON-NLS-1$
            private static final String COMMAND_LINE_ARGUMENT = "argument"; //$NON-NLS-1$
            private static final String COMMAND_LINE_ARGUMENTS = "command_line"; //$NON-NLS-1$
            private static final String COMPILER = "compiler"; //$NON-NLS-1$
            private static final String COMPILER_COPYRIGHT = "copyright"; //$NON-NLS-1$
            private static final String COMPILER_NAME = "name"; //$NON-NLS-1$
            private static final String COMPILER_VERSION = "version"; //$NON-NLS-1$
            public static final int EMACS = 2;
            private static final String ERROR = "ERROR"; //$NON-NLS-1$
            private static final String ERROR_TAG = "error"; //$NON-NLS-1$
            private static final String EXCEPTION = "exception"; //$NON-NLS-1$
            private static final HashMap FIELD_TABLE = new HashMap();
            private static final String KEY = "key"; //$NON-NLS-1$
            private static final String MESSAGE = "message"; //$NON-NLS-1$
            private static final String NUMBER_OF_CLASSFILES = "number_of_classfiles"; //$NON-NLS-1$
            private static final String NUMBER_OF_ERRORS = "errors"; //$NON-NLS-1$
            private static final String NUMBER_OF_LINES = "number_of_lines"; //$NON-NLS-1$
            private static final String NUMBER_OF_PROBLEMS = "problems"; //$NON-NLS-1$
            private static final String NUMBER_OF_TASKS = "tasks"; //$NON-NLS-1$
            private static final String NUMBER_OF_WARNINGS = "warnings"; //$NON-NLS-1$
            private static final String OPTION = "option"; //$NON-NLS-1$
            private static final String OPTIONS = "options"; //$NON-NLS-1$
            private static final String PATH = "path"; //$NON-NLS-1$
            private static final String PROBLEM_ARGUMENT = "argument"; //$NON-NLS-1$
            private static final String PROBLEM_ARGUMENT_VALUE = "value"; //$NON-NLS-1$
            private static final String PROBLEM_ARGUMENTS = "arguments"; //$NON-NLS-1$
            private static final String PROBLEM_ID = "id"; //$NON-NLS-1$
            private static final String PROBLEM_LINE = "line"; //$NON-NLS-1$
            private static final String PROBLEM_MESSAGE = "message"; //$NON-NLS-1$
            private static final String PROBLEM_SEVERITY = "severity"; //$NON-NLS-1$
            private static final String PROBLEM_SOURCE_END = "charEnd"; //$NON-NLS-1$
            private static final String PROBLEM_SOURCE_START = "charStart"; //$NON-NLS-1$
            private static final String PROBLEM_SUMMARY = "problem_summary"; //$NON-NLS-1$
            private static final String PROBLEM_TAG = "problem"; //$NON-NLS-1$
            private static final String PROBLEMS = "problems"; //$NON-NLS-1$
            private static final String SOURCE = "source"; //$NON-NLS-1$
            private static final String SOURCE_CONTEXT = "source_context"; //$NON-NLS-1$
            private static final String SOURCE_END = "sourceEnd"; //$NON-NLS-1$
            private static final String SOURCE_START = "sourceStart"; //$NON-NLS-1$
            private static final String SOURCES = "sources"; //$NON-NLS-1$
            private static final String STATS = "stats"; //$NON-NLS-1$
            private static final String TASK = "task"; //$NON-NLS-1$
            private static final String TASKS = "tasks"; //$NON-NLS-1$
            private static final String TIME = "time"; //$NON-NLS-1$
            private static final String VALUE = "value"; //$NON-NLS-1$
            private static final String WARNING = "WARNING"; //$NON-NLS-1$

            public static final int XML = 1;
            
            private static final String XML_DTD_DECLARATION = "<!DOCTYPE compiler PUBLIC \"-//Eclipse.org//DTD Eclipse JDT 3.2.002 Compiler//EN\" \"http://www.eclipse.org/jdt/core/compiler_32_002.dtd\">"; //$NON-NLS-1$
            static {
                  try {
                        Class c = IProblem.class;
                        Field[] fields = c.getFields();
                        for (int i = 0, max = fields.length; i < max; i++) {
                              Field field = fields[i];
                              Logger.FIELD_TABLE.put(field.get(null), field.getName());
                        }
                  } catch (SecurityException e) {
                        e.printStackTrace();
                  } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                  } catch (IllegalAccessException e) {
                        e.printStackTrace();
                  }
            }
            private PrintWriter err;
            private PrintWriter log;
            private Main main;
            private PrintWriter out;
            private HashMap parameters;
            int tagBits;
            public Logger(Main main, PrintWriter out, PrintWriter err) {
                  this.out = out;
                  this.err = err;
                  this.parameters = new HashMap();
                  this.main = main;
            }

            public String buildFileName(
                  String outputPath,
                  String relativeFileName) {
                  char fileSeparatorChar = File.separatorChar;
                  String fileSeparator = File.separator;
                  
                  outputPath = outputPath.replace('/', fileSeparatorChar);
                  // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
                  StringBuffer outDir = new StringBuffer(outputPath);
                  if (!outputPath.endsWith(fileSeparator)) {
                        outDir.append(fileSeparator);
                  }
                  StringTokenizer tokenizer =
                        new StringTokenizer(relativeFileName, fileSeparator);
                  String token = tokenizer.nextToken();
                  while (tokenizer.hasMoreTokens()) {
                        outDir.append(token).append(fileSeparator);
                        token = tokenizer.nextToken();
                  }
                  // token contains the last one
                  return outDir.append(token).toString();
            }
            
            public void close() {
                  if (this.log != null) {
                        if ((this.tagBits & Logger.XML) != 0) {
                              this.endTag(Logger.COMPILER);
                              this.flush();
                        }
                        this.log.close();
                  }
            }

            /**
             * 
             */
            public void compiling() {
                  this.printlnOut(this.main.bind("progress.compiling")); //$NON-NLS-1$
            }
            
            /**
             * Used to stop logging problems.
             * Only use in xml mode.
             */
            private void endLoggingProblems() {
                  this.endTag(Logger.PROBLEMS);
            }
            public void endLoggingSource() {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.endTag(Logger.SOURCE);
                  }
            }
            
            public void endLoggingSources() {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.endTag(Logger.SOURCES);
                  }
            }
            
            public void endLoggingTasks() {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.endTag(Logger.TASKS);
                  }
            }
            private void endTag(String name) {
                  ((GenericXMLWriter) this.log).endTag(name, true, true);
            }
            private void extractContext(CategorizedProblem problem, char[] unitSource) {
                  //sanity .....
                  int startPosition = problem.getSourceStart();
                  int endPosition = problem.getSourceEnd();
                  if ((startPosition > endPosition)
                              || ((startPosition < 0) && (endPosition < 0))) {
                        this.parameters.put(Logger.VALUE, Messages.problem_noSourceInformation); 
                        this.parameters.put(Logger.SOURCE_START, "-1"); //$NON-NLS-1$
                        this.parameters.put(Logger.SOURCE_END, "-1"); //$NON-NLS-1$
                        return;
                  }

                  char c;
                  //the next code tries to underline the token.....
                  //it assumes (for a good display) that token source does not
                  //contain any \r \n. This is false on statements ! 
                  //(the code still works but the display is not optimal !)

                  // expand to line limits
                  int length = unitSource.length, begin, end;
                  for (begin = startPosition >= length ? length - 1 : startPosition; begin > 0; begin--) {
                        if ((c = unitSource[begin - 1]) == '\n' || c == '\r') break;
                  }
                  for (end = endPosition >= length ? length - 1 : endPosition ; end+1 < length; end++) {
                        if ((c = unitSource[end + 1]) == '\r' || c == '\n') break;
                  }

                  // trim left and right spaces/tabs
                  while ((c = unitSource[begin]) == ' ' || c == '\t') begin++;
                  while ((c = unitSource[end]) == ' ' || c == '\t') end--;
                  
                  // copy source
                  StringBuffer buffer = new StringBuffer();
                  buffer.append(unitSource, begin, end - begin + 1);
                  
                  this.parameters.put(Logger.VALUE, String.valueOf(buffer));
                  this.parameters.put(Logger.SOURCE_START, Integer.toString(startPosition - begin));
                  this.parameters.put(Logger.SOURCE_END, Integer.toString(endPosition - begin));
            }
            public void flush() {
                  this.out.flush();
                  this.err.flush();
                  if (this.log != null) {
                        this.log.flush();
                  }
            }
            
            private String getFieldName(int id) {
                  return (String) Logger.FIELD_TABLE.get(new Integer(id));
            }

            public void logAverage(long[] times, long lineCount) {
                  Arrays.sort(times);
                  final int length = times.length;
                  long sum = 0;
                  for (int i = 1, max = length - 1; i < max; i++) {
                        sum += times[i];
                  }
                  long time = sum / (length - 2);
                  this.printlnOut(this.main.bind(
                        "compile.averageTime", //$NON-NLS-1$
                        new String[] {
                              String.valueOf(lineCount),
                              String.valueOf(time),
                              String.valueOf(((int) (lineCount * 10000.0 / time)) / 10.0) }));
            }

            public void logClassFile(boolean generatePackagesStructure, String outputPath, String relativeFileName) {
                  if ((this.tagBits & Logger.XML) != 0) {
                        String fileName = null;
                        if (generatePackagesStructure) {
                              fileName = buildFileName(outputPath, relativeFileName);
                        } else {
                              char fileSeparatorChar = File.separatorChar;
                              String fileSeparator = File.separator;
                              // First we ensure that the outputPath exists
                              outputPath = outputPath.replace('/', fileSeparatorChar);
                              // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
                              int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
                              if (indexOfPackageSeparator == -1) {
                                    if (outputPath.endsWith(fileSeparator)) {
                                          fileName = outputPath + relativeFileName;
                                    } else {
                                          fileName = outputPath + fileSeparator + relativeFileName;
                                    }
                              } else {
                                    int length = relativeFileName.length();
                                    if (outputPath.endsWith(fileSeparator)) {
                                          fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
                                    } else {
                                          fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
                                    }
                              }
                        }
                        File f = new File(fileName);
                        try {
                              this.parameters.put(Logger.PATH, f.getCanonicalPath());
                              this.printTag(Logger.CLASS_FILE, this.parameters, true, true);
                        } catch (IOException e) {
                              this.logNoClassFileCreated(outputPath, relativeFileName, e);
                        }
                  }     
            }
            public void logClasspath(FileSystem.Classpath[] classpaths) {
                  if (classpaths == null) return;
                  if ((this.tagBits & Logger.XML) != 0) {
                        final int length = classpaths.length;
                        if (length != 0) {
                              // generate xml output
                              this.printTag(Logger.CLASSPATHS, null, true, false);
                              for (int i = 0; i < length; i++) {
                                    String classpath = classpaths[i].getPath();
                                    this.parameters.put(Logger.PATH, classpath);
                                    File f = new File(classpath);
                                    String id = null;
                                    if (f.isFile()) {
                                          if (Util.isArchiveFileName(classpath)) {
                                                id = Logger.CLASSPATH_JAR;
                                          } else {
                                                id = Logger.CLASSPATH_FILE;
                                          }
                                    } else if (f.isDirectory()) {
                                          id = Logger.CLASSPATH_FOLDER;
                                    }
                                    if (id != null) {
                                          this.parameters.put(Logger.CLASSPATH_ID, id);
                                          this.printTag(Logger.CLASSPATH, this.parameters, true, true);
                                    }
                              }
                              this.endTag(Logger.CLASSPATHS);
                        }
                  }
                  
            }
            public void logCommandLineArguments(String[] commandLineArguments) {
                  if (commandLineArguments == null) return;
                  if ((this.tagBits & Logger.XML) != 0) {
                        final int length = commandLineArguments.length;
                        if (length != 0) {
                              // generate xml output
                              this.printTag(Logger.COMMAND_LINE_ARGUMENTS, null, true, false);
                              for (int i = 0; i < length; i++) {
                                    this.parameters.put(Logger.VALUE, commandLineArguments[i]);
                                    this.printTag(Logger.COMMAND_LINE_ARGUMENT, this.parameters, true, true);
                              }
                              this.endTag(Logger.COMMAND_LINE_ARGUMENTS);
                        }
                  }
            }

            /**
             * @param e the given exception to log
             */
            public void logException(Exception e) {
                  StringWriter writer = new StringWriter();
                  PrintWriter printWriter = new PrintWriter(writer);
                  e.printStackTrace(printWriter);
                  printWriter.flush();
                  printWriter.close();
                  final String stackTrace = writer.getBuffer().toString();
                  if ((this.tagBits & Logger.XML) != 0) {
                        LineNumberReader reader = new LineNumberReader(new StringReader(stackTrace));
                        String line;
                        int i = 0;
                        StringBuffer buffer = new StringBuffer();
                        String message = e.getMessage();
                        if (message != null) {
                              buffer.append(message).append(Util.LINE_SEPARATOR);
                        }
                        try {
                              while ((line = reader.readLine()) != null && i < 4) {
                                    buffer.append(line).append(Util.LINE_SEPARATOR);
                                    i++;
                              }
                              reader.close();
                        } catch (IOException e1) {
                              // ignore
                        }
                        message = buffer.toString();
                        this.parameters.put(Logger.MESSAGE, message);
                        this.parameters.put(Logger.CLASS, e.getClass());
                        this.printTag(Logger.EXCEPTION, this.parameters, true, true);
                  }
                  String message = e.getMessage();
                  if (message == null) {
                        this.printlnErr(stackTrace);
                  } else {
                        this.printlnErr(message);
                  }
            }
            
            /**
             * @param wrongClasspath
             *            the given wrong classpath entry
             */
            public void logIncorrectClasspath(String wrongClasspath) {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.parameters.put(Logger.MESSAGE, this.main.bind("configure.incorrectClasspath", wrongClasspath)); //$NON-NLS-1$
                        this.printTag(Logger.ERROR_TAG, this.parameters, true, true);
                  }
                  this.printlnErr(this.main.bind(
                        "configure.incorrectClasspath", wrongClasspath)); //$NON-NLS-1$
            }

            /**
             * @param wrongPath
             *            the given wrong path entry
             */
            public void logIncorrectEndorsedDirsEntry(String wrongPath) {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.parameters.put(Logger.MESSAGE, this.main.bind("configure.incorrectEndorsedDirsEntry", wrongPath)); //$NON-NLS-1$
                        this.printTag(Logger.ERROR_TAG, this.parameters, true, true);
                  }
                  this.printlnErr(this.main.bind(
                        "configure.incorrectEndorsedDirsEntry", wrongPath)); //$NON-NLS-1$
            }

            /**
             * @param wrongPath
             *            the given wrong path entry
             */
            public void logIncorrectExtDirsEntry(String wrongPath) {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.parameters.put(Logger.MESSAGE, this.main.bind("configure.incorrectExtDirsEntry", wrongPath)); //$NON-NLS-1$
                        this.printTag(Logger.ERROR_TAG, this.parameters, true, true);
                  }
                  this.printlnErr(this.main.bind(
                        "configure.incorrectExtDirsEntry", wrongPath)); //$NON-NLS-1$
            }
            
            /**
             * 
             */
            public void logNoClassFileCreated(String outputDir, String relativeFileName, IOException e) {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.parameters.put(Logger.MESSAGE, this.main.bind("output.noClassFileCreated", //$NON-NLS-1$
                              new String[] {
                                    outputDir,
                                    relativeFileName,
                                    e.getMessage()
                              }));
                        this.printTag(Logger.ERROR_TAG, this.parameters, true, true);
                  }
                  this.printlnErr(this.main.bind("output.noClassFileCreated", //$NON-NLS-1$
                        new String[] {
                              outputDir,
                              relativeFileName,
                              e.getMessage()
                        }));
            }

            public void logNoClasspath() {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.parameters.put(Logger.MESSAGE, this.main.bind("configure.noClasspath")); //$NON-NLS-1$
                        this.printTag(Logger.ERROR_TAG, this.parameters, true, true);
                  }
                  this.printlnErr(this.main.bind("configure.noClasspath")); //$NON-NLS-1$
            }

            /**
             * @param exportedClassFilesCounter
             */
            public void logNumberOfClassFilesGenerated(int exportedClassFilesCounter) {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.parameters.put(Logger.VALUE, new Integer(exportedClassFilesCounter));
                        this.printTag(Logger.NUMBER_OF_CLASSFILES, this.parameters, true, true);
                  }
                  if (exportedClassFilesCounter == 1) {
                        this.printlnOut(this.main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
                  } else {
                        this.printlnOut(this.main.bind("compile.severalClassFilesGenerated", //$NON-NLS-1$
                              String.valueOf(exportedClassFilesCounter)));
                  }
            }

            /**
             * @param options the given compiler options
             */
            public void logOptions(Map options) {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.printTag(Logger.OPTIONS, null, true, false);
                        final Set keySet = options.keySet();
                        Object[] keys = keySet.toArray();
                        Arrays.sort(keys);
                        for (int i = 0, max = keys.length; i < max; i++) {
                              Object key = keys[i];
                              this.parameters.put(Logger.KEY, key);
                              this.parameters.put(Logger.VALUE, options.get(key));
                              this.printTag(Logger.OPTION, this.parameters, true, true);
                        }
                        this.endTag(Logger.OPTIONS);
                  }
            }

            private void logProblem(CategorizedProblem problem, int localErrorCount,
                  int globalErrorCount, char[] unitSource) {
                  if ((this.tagBits & Logger.EMACS) != 0) {
                        String result = (new String(problem.getOriginatingFileName())
                                    + ":" //$NON-NLS-1$
                                    + problem.getSourceLineNumber()
                                    + ": " //$NON-NLS-1$
                                    + (problem.isError() ? this.main.bind("output.emacs.error") : this.main.bind("output.emacs.warning")) //$NON-NLS-1$ //$NON-NLS-2$
                                    + ": " //$NON-NLS-1$
                                    + problem.getMessage());
                        this.printlnErr(result);
                        final String errorReportSource = ((DefaultProblem) problem).errorReportSource(unitSource, this.tagBits);
                        if (errorReportSource.length() != 0) this.printlnErr(errorReportSource);
                  } else {
                        if (localErrorCount == 0) {
                              this.printlnErr("----------"); //$NON-NLS-1$
                        }
                        this.printErr(problem.isError() ?
                                    this.main.bind(
                                                "requestor.error", //$NON-NLS-1$
                                                Integer.toString(globalErrorCount),
                                                new String(problem.getOriginatingFileName()))
                                                : this.main.bind(
                                                            "requestor.warning", //$NON-NLS-1$
                                                            Integer.toString(globalErrorCount),
                                                            new String(problem.getOriginatingFileName())));
                        try {
                              final String errorReportSource = ((DefaultProblem) problem).errorReportSource(unitSource);
                              this.printlnErr(errorReportSource);
                              this.printlnErr(problem.getMessage());
                        } catch (Exception e) {
                              this.printlnErr(this.main.bind(
                                    "requestor.notRetrieveErrorMessage", problem.toString())); //$NON-NLS-1$
                        }
                        this.printlnErr("----------"); //$NON-NLS-1$
                  }
            }

            public int logProblems(CategorizedProblem[] problems, char[] unitSource, Main currentMain) {
                  final int count = problems.length;
                  int localErrorCount = 0;
                  int localProblemCount = 0;
                  if (count != 0) {
                        if ((this.tagBits & Logger.XML) != 0) {
                              int errors = 0;
                              int warnings = 0;
                              int tasks = 0;
                              for (int i = 0; i < count; i++) {
                                    CategorizedProblem problem = problems[i];
                                    if (problem != null) {
                                          currentMain.globalProblemsCount++;
                                          this.logProblem(problem, localProblemCount, currentMain.globalProblemsCount, unitSource);
                                          localProblemCount++;
                                          if (problem.isError()) {
                                                localErrorCount++;                                          
                                                errors++;
                                                currentMain.globalErrorsCount++;
                                          } else if (problem.getID() == IProblem.Task) {
                                                currentMain.globalTasksCount++;
                                                tasks++;
                                          } else {
                                                currentMain.globalWarningsCount++;
                                                warnings++;
                                          }
                                    }
                              }
                              if ((errors + warnings) != 0) {
                                    this.startLoggingProblems(errors, warnings);
                                    for (int i = 0; i < count; i++) {
                                          CategorizedProblem problem = problems[i];
                                          if (problem!= null) {
                                                if (problem.getID() != IProblem.Task) {
                                                      this.logXmlProblem(problem, unitSource);
                                                }
                                          }
                                    }
                                    this.endLoggingProblems();
                              }
                              if (tasks != 0) {
                                    this.startLoggingTasks(tasks);
                                    for (int i = 0; i < count; i++) {
                                          CategorizedProblem problem = problems[i];
                                          if (problem!= null) {
                                                if (problem.getID() == IProblem.Task) {
                                                      this.logXmlTask(problem, unitSource);
                                                }
                                          }
                                    }
                                    this.endLoggingTasks();
                              }
                        } else {
                              for (int i = 0; i < count; i++) {
                                    if (problems[i] != null) {
                                          currentMain.globalProblemsCount++;
                                          this.logProblem(problems[i], localProblemCount, currentMain.globalProblemsCount, unitSource);
                                          localProblemCount++;
                                          if (problems[i].isError()) {
                                                localErrorCount++;
                                                currentMain.globalErrorsCount++;
                                          } else {
                                                currentMain.globalWarningsCount++;
                                          }
                                    }
                              }
                        }
                  }
                  return localErrorCount;
            }

            /**
             * @param globalProblemsCount
             * @param globalErrorsCount
             * @param globalWarningsCount
             */
            public void logProblemsSummary(int globalProblemsCount,
                  int globalErrorsCount, int globalWarningsCount, int globalTasksCount) {
                  if ((this.tagBits & Logger.XML) != 0) {
                        // generate xml
                        this.parameters.put(Logger.NUMBER_OF_PROBLEMS, new Integer(globalProblemsCount));
                        this.parameters.put(Logger.NUMBER_OF_ERRORS, new Integer(globalErrorsCount));
                        this.parameters.put(Logger.NUMBER_OF_WARNINGS, new Integer(globalWarningsCount));
                        this.parameters.put(Logger.NUMBER_OF_TASKS, new Integer(globalTasksCount));
                        this.printTag(Logger.PROBLEM_SUMMARY, this.parameters, true, true);
                  }
                  if (globalProblemsCount == 1) {
                        String message = null;
                        if (globalErrorsCount == 1) {
                              message = this.main.bind("compile.oneError"); //$NON-NLS-1$
                        } else {
                              message = this.main.bind("compile.oneWarning"); //$NON-NLS-1$
                        }
                        this.printErr(this.main.bind("compile.oneProblem", message)); //$NON-NLS-1$
                  } else {
                        String errorMessage = null;
                        String warningMessage = null;
                        if (globalErrorsCount > 0) {
                              if (globalErrorsCount == 1) {
                                    errorMessage = this.main.bind("compile.oneError"); //$NON-NLS-1$
                              } else {
                                    errorMessage = this.main.bind("compile.severalErrors", String.valueOf(globalErrorsCount)); //$NON-NLS-1$
                              }
                        }
                        int warningsNumber = globalWarningsCount + globalTasksCount;
                        if (warningsNumber > 0) {
                              if (warningsNumber == 1) {
                                    warningMessage = this.main.bind("compile.oneWarning"); //$NON-NLS-1$
                              } else {
                                    warningMessage = this.main.bind("compile.severalWarnings", String.valueOf(warningsNumber)); //$NON-NLS-1$
                              }
                        }
                        if (errorMessage == null || warningMessage == null) {
                              if (errorMessage == null) {
                                    this.printErr(this.main.bind(
                                          "compile.severalProblemsErrorsOrWarnings", //$NON-NLS-1$
                                          String.valueOf(globalProblemsCount),
                                          warningMessage));
                              } else {
                                    this.printErr(this.main.bind(
                                          "compile.severalProblemsErrorsOrWarnings", //$NON-NLS-1$
                                          String.valueOf(globalProblemsCount),
                                          errorMessage));
                              }
                        } else {
                              this.printErr(this.main.bind(
                                    "compile.severalProblemsErrorsAndWarnings", //$NON-NLS-1$
                                    new String[] {
                                          String.valueOf(globalProblemsCount),
                                          errorMessage,
                                          warningMessage
                                    }));
                        }
                  }
                  if ((this.tagBits & Logger.EMACS) != 0) {
                        this.printlnErr();
                  }
            }
            
            /**
             * 
             */
            public void logProgress() {
                  this.printOut('.');
            }

            /**
             * @param i
             *            the current repetition number
             * @param repetitions
             *            the given number of repetitions
             */
            public void logRepetition(int i, int repetitions) {
                  this.printlnOut(this.main.bind("compile.repetition", //$NON-NLS-1$
                        String.valueOf(i + 1), String.valueOf(repetitions)));
            }
            
            /**
             * @param time
             * @param lineCount
             */
            public void logTiming(long time, long lineCount) {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.parameters.put(Logger.VALUE, new Long(time));
                        this.printTag(Logger.TIME, this.parameters, true, true);
                        this.parameters.put(Logger.VALUE, new Long(lineCount));
                        this.printTag(Logger.NUMBER_OF_LINES, this.parameters, true, true);
                  }
                  if (lineCount != 0) {
                        this.printlnOut(this.main.bind(
                              "compile.instantTime", //$NON-NLS-1$
                              new String[] {
                                    String.valueOf(lineCount),
                                    String.valueOf(time),
                                    String.valueOf(((int) (lineCount * 10000.0 / time)) / 10.0) }));
                  } else {
                        this.printlnOut(this.main.bind("compile.totalTime", String.valueOf(time))); //$NON-NLS-1$
                  }
            }

            /**
             * Print the usage of the compiler
             * @param usage
             */
            public void logUsage(String usage) {
                  this.printlnOut(usage);
            }

            /**
             * Print the version of the compiler in the log and/or the out field
             */
            public void logVersion(final boolean printToOut) {
                  if (this.log != null && (this.tagBits & Logger.XML) == 0) {
                        final String version = this.main.bind("misc.version", //$NON-NLS-1$
                              new String[] {
                                    this.main.bind("compiler.name"), //$NON-NLS-1$
                                    this.main.bind("compiler.version"), //$NON-NLS-1$
                                    this.main.bind("compiler.copyright") //$NON-NLS-1$
                              }
                        );
                        this.log.println("# " + version); //$NON-NLS-1$
                        if (printToOut) {
                              this.out.println(version);
                              this.out.flush();
                        }
                  } else if (printToOut) {
                        final String version = this.main.bind("misc.version", //$NON-NLS-1$
                              new String[] {
                                    this.main.bind("compiler.name"), //$NON-NLS-1$
                                    this.main.bind("compiler.version"), //$NON-NLS-1$
                                    this.main.bind("compiler.copyright") //$NON-NLS-1$
                              }
                        );
                        this.out.println(version);
                        this.out.flush();
                  }
            }
            /**
             * Print the usage of wrong JDK
             */
            public void logWrongJDK() {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.parameters.put(Logger.MESSAGE, this.main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
                        this.printTag(Logger.ERROR, this.parameters, true, true);                     
                  }
                  this.printlnErr(this.main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
            }

            /**
             * @param problem
             *            the given problem to log
             * @param unitSource
             *            the given unit source
             */
            private void logXmlProblem(CategorizedProblem problem, char[] unitSource) {
                  final int sourceStart = problem.getSourceStart();
                  final int sourceEnd = problem.getSourceEnd();
                  this.parameters.put(Logger.PROBLEM_ID, getFieldName(problem.getID()));
                  this.parameters.put(Logger.PROBLEM_SEVERITY, problem.isError() ? Logger.ERROR : Logger.WARNING);
                  this.parameters.put(Logger.PROBLEM_LINE, new Integer(problem.getSourceLineNumber()));
                  this.parameters.put(Logger.PROBLEM_SOURCE_START, new Integer(sourceStart));
                  this.parameters.put(Logger.PROBLEM_SOURCE_END, new Integer(sourceEnd));
                  this.printTag(Logger.PROBLEM_TAG, this.parameters, true, false);
                  this.parameters.put(Logger.VALUE, problem.getMessage());
                  this.printTag(Logger.PROBLEM_MESSAGE, this.parameters, true, true);
                  extractContext(problem, unitSource);
                  this.printTag(Logger.SOURCE_CONTEXT, this.parameters, true, true);
                  String[] arguments = problem.getArguments();
                  final int length = arguments.length;
                  if (length != 0) {
                        this.printTag(Logger.PROBLEM_ARGUMENTS, null, true, false);
                        for (int i = 0; i < length; i++) {
                              this.parameters.put(Logger.PROBLEM_ARGUMENT_VALUE, arguments[i]);
                              this.printTag(Logger.PROBLEM_ARGUMENT, this.parameters, true, true);
                        }
                        this.endTag(Logger.PROBLEM_ARGUMENTS);
                  }
                  this.endTag(Logger.PROBLEM_TAG);
            }

            /**
             * @param problem
             *            the given problem to log
             * @param unitSource
             *            the given unit source
             */
            private void logXmlTask(CategorizedProblem problem, char[] unitSource) {
                  this.parameters.put(Logger.PROBLEM_LINE, new Integer(problem.getSourceLineNumber()));
                  this.parameters.put(Logger.PROBLEM_SOURCE_START, new Integer(problem.getSourceStart()));
                  this.parameters.put(Logger.PROBLEM_SOURCE_END, new Integer(problem.getSourceEnd()));
                  this.printTag(Logger.TASK, this.parameters, true, false);
                  this.parameters.put(Logger.VALUE, problem.getMessage());
                  this.printTag(Logger.PROBLEM_MESSAGE, this.parameters, true, true);
                  extractContext(problem, unitSource);
                  this.printTag(Logger.SOURCE_CONTEXT, this.parameters, true, true);
                  this.endTag(Logger.TASK);
            }

            private void printErr(String s) {
                  this.err.print(s);
                  if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
                        this.log.print(s);
                  }
            }

            private void printlnErr() {
                  this.err.println();
                  if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
                        this.log.println();
                  }
            }
            private void printlnErr(String s) {
                  this.err.println(s);
                  if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
                        this.log.println(s);
                  }
            }
            private void printlnOut(String s) {
                  this.out.println(s);
                  if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
                        this.log.println(s);
                  }
            }

            /**
             * 
             */
            public void printNewLine() {
                  this.out.println();
            }

            private void printOut(char c) {
                  this.out.print(c);
            }

            public void printStats() {
                  final boolean isTimed = this.main.timing;
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.printTag(Logger.STATS, null, true, false);
                  }
                  if (isTimed) {
                        long time = System.currentTimeMillis() - this.main.startTime;
                        this.logTiming(time, this.main.lineCount);
                        if (this.main.times != null) {
                              this.main.times[this.main.timesCounter++] = time;
                        }
                  }
                  if (this.main.globalProblemsCount > 0) {
                        this.logProblemsSummary(this.main.globalProblemsCount, this.main.globalErrorsCount, this.main.globalWarningsCount, main.globalTasksCount);
                  }
                  if (this.main.exportedClassFilesCounter != 0
                              && (this.main.showProgress || isTimed || this.main.verbose)) {
                        this.logNumberOfClassFilesGenerated(this.main.exportedClassFilesCounter);
                  }
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.endTag(Logger.STATS);
                  }
            }

            private void printTag(String name, HashMap params, boolean insertNewLine, boolean closeTag) {
                  ((GenericXMLWriter) this.log).printTag(name, parameters, true, insertNewLine, closeTag);
                  this.parameters.clear();
            }

            public void setEmacs() {
                  this.tagBits |= Logger.EMACS;
            }

            public void setLog(String logFileName) throws InvalidInputException {
                  final Date date = new Date();
                  final DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, Locale.getDefault());
                  try {
                        int index = logFileName.lastIndexOf('.');
                        if (index != -1) {
                              if (logFileName.substring(index).toLowerCase().equals(".xml")) { //$NON-NLS-1$
                                    this.log = new GenericXMLWriter(new FileOutputStream(logFileName, false), Util.LINE_SEPARATOR, true);
                                    this.tagBits |= Logger.XML;
                                    // insert time stamp as comment
                                    try {
                                          this.log.println("<!-- " + new String(dateFormat.format(date).getBytes(), "UTF-8") + " -->");//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
                                    } catch (UnsupportedEncodingException e) {
                                          e.printStackTrace();
                                    }
                                    this.log.println(Logger.XML_DTD_DECLARATION);
                                    this.parameters.put(Logger.COMPILER_NAME, this.main.bind("compiler.name")); //$NON-NLS-1$
                                    this.parameters.put(Logger.COMPILER_VERSION, this.main.bind("compiler.version")); //$NON-NLS-1$
                                    this.parameters.put(Logger.COMPILER_COPYRIGHT, this.main.bind("compiler.copyright")); //$NON-NLS-1$
                                    this.printTag(Logger.COMPILER, this.parameters, true, false);
                              } else {
                                    this.log = new PrintWriter(new FileOutputStream(logFileName, false));
                                    this.log.println("# " + dateFormat.format(date));//$NON-NLS-1$
                              }
                        } else {
                              this.log = new PrintWriter(new FileOutputStream(logFileName, false));
                              this.log.println("# " + dateFormat.format(date));//$NON-NLS-1$
                        }
                  } catch (FileNotFoundException e) {
                        throw new InvalidInputException(this.main.bind("configure.cannotOpenLog")); //$NON-NLS-1$
                  }
            }

            /**
             * Used to start logging problems.
             * Only use in xml mode.
             */
            private void startLoggingProblems(int errors, int warnings) {
                  this.parameters.put(Logger.NUMBER_OF_PROBLEMS, new Integer(errors + warnings));
                  this.parameters.put(Logger.NUMBER_OF_ERRORS, new Integer(errors));
                  this.parameters.put(Logger.NUMBER_OF_WARNINGS, new Integer(warnings));
                  this.printTag(Logger.PROBLEMS, this.parameters, true, false);
            }
            public void startLoggingSource(CompilationResult compilationResult) {
                  if ((this.tagBits & Logger.XML) != 0) {
                        ICompilationUnit compilationUnit = compilationResult.compilationUnit;
                        char[] fileName = compilationUnit.getFileName();
                        File f = new File(new String(fileName));
                        if (fileName != null) {
                              if (compilationUnit != null) {
                                    this.parameters.put(Logger.PATH, f.getAbsolutePath());
                              }
                        }
                        this.printTag(Logger.SOURCE, this.parameters, true, false);
                  }
            }
            public void startLoggingSources() {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.printTag(Logger.SOURCES, null, true, false);
                  }
            }
            public void startLoggingTasks(int tasks) {
                  if ((this.tagBits & Logger.XML) != 0) {
                        this.parameters.put(Logger.NUMBER_OF_TASKS, new Integer(tasks));
                        this.printTag(Logger.TASKS, this.parameters, true, false);
                  }
            }
      }
      public final static String bundleName =
            "org.eclipse.jdt.internal.compiler.batch.messages";   //$NON-NLS-1$

      // two uses: recognize 'none' in options; code the singleton none
            // for the '-d none' option (wherever it may be found)
      public static final int DEFAULT_SIZE_CLASSPATH = 4;
      public static final String NONE = "none"; //$NON-NLS-1$

      /*
       * Internal IDE API
       */
      public static boolean compile(String commandLine) {
      
            return compile(commandLine, new PrintWriter(System.out), new PrintWriter(System.err));
      }
            /*
       * Internal IDE API for test harness purpose
       */
      public static boolean compile(String commandLine, PrintWriter outWriter, PrintWriter errWriter) {
      
            return new Main(outWriter, errWriter, false).compile(tokenize(commandLine));
      }
      public static File[][] getLibrariesFiles(File[] files) {
            FilenameFilter filter = new FilenameFilter() {
                  public boolean accept(File dir, String name) {
                        String lowerCaseName = name.toLowerCase();
                        if (lowerCaseName.endsWith(SuffixConstants.SUFFIX_STRING_jar) || lowerCaseName.endsWith(SuffixConstants.SUFFIX_STRING_zip)) {
                              return true;
                        }
                        return false;
                  }
            };
            final int filesLength = files.length;
            File[][] result = new File[filesLength][];
            for (int i = 0; i < filesLength; i++) {
                  File currentFile = files[i];
                  if (currentFile.exists() && currentFile.isDirectory()) {
                        result[i] = currentFile.listFiles(filter);
                  }
            }
            return result;
      }
      public static void main(String[] argv) {
            new Main(new PrintWriter(System.out), new PrintWriter(System.err), true).compile(argv);
      } 
      public static String[] tokenize(String commandLine) {
      
            int count = 0;
            String[] arguments = new String[10];
            StringTokenizer tokenizer = new StringTokenizer(commandLine, " \"", true); //$NON-NLS-1$
            String token = ""; //$NON-NLS-1$
            boolean insideQuotes = false;
            boolean startNewToken = true;
      
            // take care to quotes on the command line
            // 'xxx "aaa bbb";ccc yyy' --->  {"xxx", "aaa bbb;ccc", "yyy" }
            // 'xxx "aaa bbb;ccc" yyy' --->  {"xxx", "aaa bbb;ccc", "yyy" }
            // 'xxx "aaa bbb";"ccc" yyy' --->  {"xxx", "aaa bbb;ccc", "yyy" }
            // 'xxx/"aaa bbb";"ccc" yyy' --->  {"xxx/aaa bbb;ccc", "yyy" }
            while (tokenizer.hasMoreTokens()) {
                  token = tokenizer.nextToken();
      
                  if (token.equals(" ")) { //$NON-NLS-1$
                        if (insideQuotes) {
                              arguments[count - 1] += token;
                              startNewToken = false;
                        } else {
                              startNewToken = true;
                        }
                  } else if (token.equals("\"")) { //$NON-NLS-1$
                        if (!insideQuotes && startNewToken) {
                              if (count == arguments.length)
                                    System.arraycopy(arguments, 0, (arguments = new String[count * 2]), 0, count);
                              arguments[count++] = ""; //$NON-NLS-1$
                        }
                        insideQuotes = !insideQuotes;
                        startNewToken = false;
                  } else {
                        if (insideQuotes) {
                              arguments[count - 1] += token;
                        } else {
                              if (token.length() > 0 && !startNewToken) {
                                    arguments[count - 1] += token;
                              } else {
                                    if (count == arguments.length)
                                          System.arraycopy(arguments, 0, (arguments = new String[count * 2]), 0, count);
                                    String trimmedToken = token.trim();
                                    if (trimmedToken.length() != 0) {
                                          arguments[count++] = trimmedToken;
                                    }
                              }
                        }
                        startNewToken = false;
                  }
            }
            System.arraycopy(arguments, 0, arguments = new String[count], 0, count);
            return arguments;
      }
      Compiler batchCompiler;
      /* Bundle containing messages */
      public ResourceBundle bundle;
            protected FileSystem.Classpath[] checkedClasspaths;
      public Locale compilerLocale;
      public CompilerOptions compilerOptions; // read-only
      public String destinationPath;
      // added in stream 3.2.x to support bug 159641
      public String[] destinationPaths;
      public boolean generatePackagesStructure;

      private boolean didSpecifySource;
      private boolean didSpecifyTarget;

      public String[] encodings;

      public int exportedClassFilesCounter; 
      public String[] filenames;

      // overrides of destinationPath on a directory argument basis
      public int globalErrorsCount;
      public int globalProblemsCount;
      public int globalTasksCount;
      public int globalWarningsCount;
      private File javaHomeCache;
      private boolean javaHomeChecked = false;
      public long lineCount;
      public String log;
      public Logger logger;
      public int maxProblems;
      public boolean noWarn = false;
      public Map options;
      PrintWriter out;
      public boolean proceed = true;
      public boolean proceedOnError = false;
      public boolean produceRefInfo = false;
      public int repetitions;

      public boolean showProgress = false;
            public long startTime;

public boolean systemExitWhenFinished = true;

public long[] times;

public int timesCounter;

public boolean timing = false;

public boolean verbose = false;

public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished) {
      this(outWriter, errWriter, systemExitWhenFinished, null);
}

public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map customDefaultOptions) {
      this.initialize(outWriter, errWriter, systemExitWhenFinished, customDefaultOptions);
      this.relocalize();
}

protected void addNewEntry(ArrayList paths, String currentClasspathName, 
            ArrayList currentRuleSpecs, String customEncoding, boolean isSourceOnly) throws InvalidInputException {
      
      int rulesSpecsSize = currentRuleSpecs.size();
      AccessRuleSet accessRuleSet = null; 
      if (rulesSpecsSize != 0) {
            AccessRule[] accessRules = new AccessRule[currentRuleSpecs.size()];
      boolean rulesOK = true;
      Iterator i = currentRuleSpecs.iterator();
      int j = 0;
      while (i.hasNext()) {
            String ruleSpec = (String) i.next();
            char key = ruleSpec.charAt(0);
            String pattern = ruleSpec.substring(1);
            if (pattern.length() > 0) {
                  switch (key) {
                  case '+':
                        accessRules[j++] = new AccessRule(pattern
                                    .toCharArray(), 0);
                        break;
                  case '~':
                        accessRules[j++] = new AccessRule(pattern
                                    .toCharArray(),
                                    IProblem.DiscouragedReference);
                        break;
                  case '-':
                        accessRules[j++] = new AccessRule(pattern
                                    .toCharArray(),
                                    IProblem.ForbiddenReference);
                        break;
                  case '?':
                        accessRules[j++] = new AccessRule(pattern
                                    .toCharArray(),
                                    IProblem.ForbiddenReference, true/*keep looking for accessible type*/);
                        break;
                  default:
                        rulesOK = false;
                  }
            } else {
                  rulesOK = false;
            }
      }
      if (rulesOK) {
            String templates[] = new String[AccessRuleSet.MESSAGE_TEMPLATES_LENGTH];
            templates[0] = this.bind(
                  "template.restrictedAccess.type", //$NON-NLS-1$
                  new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$ 
            templates[1] = this.bind(
                  "template.restrictedAccess.constructor", //$NON-NLS-1$
                  new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$ 
            templates[2] = this.bind(
                  "template.restrictedAccess.method", //$NON-NLS-1$
                  new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$ 
            templates[3] = this.bind(
                  "template.restrictedAccess.field", //$NON-NLS-1$
                  new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$ 
            accessRuleSet = new AccessRuleSet(accessRules, templates);
      } else {
            // we go on anyway
            this.logger.logIncorrectClasspath(currentClasspathName);
            return;
      }
      }
      FileSystem.Classpath currentClasspath = FileSystem.getClasspath(
                  currentClasspathName,
                  customEncoding,
                  isSourceOnly,
                  accessRuleSet);
      if (currentClasspath != null) {
            paths.add(currentClasspath);
      } else {
            // we go on anyway
            this.logger.logIncorrectClasspath(currentClasspathName);
      }
}
/*
 * Lookup the message with the given ID in this catalog 
 */
public String bind(String id) {
      return bind(id, (String[]) null);
}
/*
 * Lookup the message with the given ID in this catalog and bind its
 * substitution locations with the given string.
 */
public String bind(String id, String binding) {
      return bind(id, new String[] { binding });
}

/*
 * Lookup the message with the given ID in this catalog and bind its
 * substitution locations with the given strings.
 */
public String bind(String id, String binding1, String binding2) {
      return bind(id, new String[] { binding1, binding2 });
}

/*
 * Lookup the message with the given ID in this catalog and bind its
 * substitution locations with the given string values.
 */
public String bind(String id, String[] arguments) {
      if (id == null)
            return "No message available"; //$NON-NLS-1$
      String message = null;
      try {
            message = this.bundle.getString(id);
      } catch (MissingResourceException e) {
            // If we got an exception looking for the message, fail gracefully by just returning
            // the id we were looking for.  In most cases this is semi-informative so is not too bad.
            return "Missing message: " + id + " in: " + Main.bundleName; //$NON-NLS-2$ //$NON-NLS-1$
      }
      return MessageFormat.format(message, arguments);
}

/*
 *  Low-level API performing the actual compilation
 */
public boolean compile(String[] argv) {

      // decode command line arguments
      try {
            configure(argv);
            if (this.proceed) {
//                      if (this.verbose) {
//                            System.out.println(new CompilerOptions(this.options));
//                      }
                  if (this.showProgress) this.logger.compiling();
                  for (int i = 0; i < this.repetitions; i++) {
                        this.globalProblemsCount = 0;
                        this.globalErrorsCount = 0;
                        this.globalWarningsCount = 0;
                        this.globalTasksCount = 0;
                        this.lineCount = 0;
                        this.exportedClassFilesCounter = 0;

                        if (this.repetitions > 1) {
                              this.logger.flush();
                              this.logger.logRepetition(i, this.repetitions);
                        } 
                        // request compilation
                        performCompilation();
                  }
                  if (this.times != null) {
                        this.logger.logAverage(this.times, this.lineCount);
                  }
                  if (this.showProgress) this.logger.printNewLine();
            }
            if (this.systemExitWhenFinished) {
                  this.logger.flush();
                  this.logger.close();
                  System.exit(this.globalErrorsCount > 0 ? -1 : 0);
            }
      } catch (InvalidInputException e) {
            this.logger.logException(e);
            if (this.systemExitWhenFinished) {
                  this.logger.flush();
                  this.logger.close();
                  System.exit(-1);
            }
            return false;
      } catch (RuntimeException e) { // internal compiler failure
            this.logger.logException(e);
            if (this.systemExitWhenFinished) {
                  this.logger.flush();
                  this.logger.close();
                  System.exit(-1);
            }
            return false;
      } finally {
            this.logger.flush();
            this.logger.close();
      }
      if (this.globalErrorsCount == 0)
            return true;
      return false;
}

/*
Handle a single warning token.
*/
protected void handleWarningToken(String token, boolean isEnabling, boolean useEnableJavadoc) throws InvalidInputException {
      if (token.equals("constructorName")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportMethodWithConstructorName,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("pkgDefaultMethod") || token.equals("packageDefaultMethod")/*backward compatible*/ ) { //$NON-NLS-1$ //$NON-NLS-2$
            this.options.put(
                  CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("maskedCatchBlock") || token.equals("maskedCatchBlocks")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
            this.options.put(
                  CompilerOptions.OPTION_ReportHiddenCatchBlock,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("deprecation")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportDeprecation, 
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            this.options.put(
                  CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, 
                  CompilerOptions.DISABLED);
            this.options.put(
                  CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, 
                  CompilerOptions.DISABLED);                                  
      } else if (token.equals("allDeprecation")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportDeprecation, 
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            this.options.put(
                  CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, 
                  isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
            this.options.put(
                  CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, 
                  isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
      } else if (token.equals("unusedLocal") || token.equals("unusedLocals")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
            this.options.put(
                  CompilerOptions.OPTION_ReportUnusedLocal, 
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("unusedArgument") || token.equals("unusedArguments")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
            this.options.put(
                  CompilerOptions.OPTION_ReportUnusedParameter,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("unusedImport") || token.equals("unusedImports")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
            this.options.put(
                  CompilerOptions.OPTION_ReportUnusedImport,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("unusedPrivate")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportUnusedPrivateMember,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("unusedLabel")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportUnusedLabel,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("localHiding")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportLocalVariableHiding,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("fieldHiding")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportFieldHiding,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("specialParamHiding")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportSpecialParameterHidingField,
                  isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
      } else if (token.equals("conditionAssign")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportPossibleAccidentalBooleanAssignment,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            } else if (token.equals("syntheticAccess") //$NON-NLS-1$
                        || token.equals("synthetic-access")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("nls")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("staticReceiver")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportNonStaticAccessToStatic,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("indirectStatic")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportIndirectStaticAccess,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("noEffectAssign")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportNoEffectAssignment,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("intfNonInherited") || token.equals("interfaceNonInherited")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
            this.options.put(
                  CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("charConcat") || token.equals("noImplicitStringConversion")/*backward compatible*/) {//$NON-NLS-1$ //$NON-NLS-2$
            this.options.put(
                  CompilerOptions.OPTION_ReportNoImplicitStringConversion,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("semicolon")) {//$NON-NLS-1$ 
            this.options.put(
                  CompilerOptions.OPTION_ReportEmptyStatement,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("serial")) {//$NON-NLS-1$ 
            this.options.put(
                  CompilerOptions.OPTION_ReportMissingSerialVersion,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("emptyBlock")) {//$NON-NLS-1$ 
            this.options.put(
                  CompilerOptions.OPTION_ReportUndocumentedEmptyBlock,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("uselessTypeCheck")) {//$NON-NLS-1$ 
            this.options.put(
                  CompilerOptions.OPTION_ReportUnnecessaryTypeCheck,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("unchecked") || token.equals("unsafe")) {//$NON-NLS-1$ //$NON-NLS-2$ 
            this.options.put(
                  CompilerOptions.OPTION_ReportUncheckedTypeOperation,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("raw")) {//$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportRawTypeReference,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);                                 
      } else if (token.equals("finalBound")) {//$NON-NLS-1$ 
            this.options.put(
                  CompilerOptions.OPTION_ReportFinalParameterBound,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("suppress")) {//$NON-NLS-1$ 
            this.options.put(
                  CompilerOptions.OPTION_SuppressWarnings,
                  isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
      } else if (token.equals("warningToken")) {//$NON-NLS-1$ 
            this.options.put(
                  CompilerOptions.OPTION_ReportUnhandledWarningToken,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("unnecessaryElse")) {//$NON-NLS-1$ 
            this.options.put(
                  CompilerOptions.OPTION_ReportUnnecessaryElse,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("javadoc")) {//$NON-NLS-1$ 
            if (!useEnableJavadoc) {
                  this.options.put(
                        CompilerOptions.OPTION_DocCommentSupport,
                        isEnabling ? CompilerOptions.ENABLED: CompilerOptions.DISABLED);
            }
            // if disabling then it's not necessary to set other javadoc options
            if (isEnabling) {
                  this.options.put(
                        CompilerOptions.OPTION_ReportInvalidJavadoc,
                        CompilerOptions.WARNING);
                  this.options.put(
                        CompilerOptions.OPTION_ReportInvalidJavadocTags,
                        CompilerOptions.ENABLED);
                  this.options.put(
                        CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef,
                        CompilerOptions.DISABLED);
                  this.options.put(
                        CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef,
                        CompilerOptions.DISABLED);
                  this.options.put(
                        CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
                        CompilerOptions.PRIVATE);
                  this.options.put(
                        CompilerOptions.OPTION_ReportMissingJavadocTags,
                        CompilerOptions.WARNING);
                  this.options.put(
                        CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
                        CompilerOptions.PRIVATE);
            }
      } else if (token.equals("allJavadoc")) { //$NON-NLS-1$
            if (!useEnableJavadoc) {
                  this.options.put(
                        CompilerOptions.OPTION_DocCommentSupport,
                        isEnabling ? CompilerOptions.ENABLED: CompilerOptions.DISABLED);
            }
            // if disabling then it's not necessary to set other javadoc options
            if (isEnabling) {
                  this.options.put(
                  CompilerOptions.OPTION_ReportInvalidJavadoc,
                  CompilerOptions.WARNING);
                  this.options.put(
                        CompilerOptions.OPTION_ReportInvalidJavadocTags,
                        CompilerOptions.ENABLED);
                  this.options.put(
                        CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
                        CompilerOptions.PRIVATE);
                  this.options.put(
                        CompilerOptions.OPTION_ReportMissingJavadocTags,
                        CompilerOptions.WARNING);
                  this.options.put(
                        CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
                        CompilerOptions.PRIVATE);
                  this.options.put(
                        CompilerOptions.OPTION_ReportMissingJavadocComments,
                        CompilerOptions.WARNING);
            }
      } else if (token.startsWith("tasks")) { //$NON-NLS-1$
            String taskTags = ""; //$NON-NLS-1$
            int start = token.indexOf('(');
            int end = token.indexOf(')');
            if (start >= 0 && end >= 0 && start < end){
                  taskTags = token.substring(start+1, end).trim();
                  taskTags = taskTags.replace('|',',');
            }
            if (taskTags.length() == 0){
                  throw new InvalidInputException(this.bind("configure.invalidTaskTag", token)); //$NON-NLS-1$
            }
            this.options.put(
                  CompilerOptions.OPTION_TaskTags,
                  isEnabling ? taskTags : "");  //$NON-NLS-1$
      } else if (token.equals("assertIdentifier")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportAssertIdentifier,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("enumIdentifier")) { //$NON-NLS-1$
            this.options.put(
                        CompilerOptions.OPTION_ReportEnumIdentifier,
                        isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("finally")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportFinallyBlockNotCompletingNormally,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("unusedThrown")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportUnusedDeclaredThrownException,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("unqualifiedField") //$NON-NLS-1$
                  || token.equals("unqualified-field-access")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportUnqualifiedFieldAccess,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("typeHiding")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportTypeParameterHiding,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("varargsCast")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportVarargsArgumentNeedCast,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);                                 
      } else if (token.equals("null")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportNullReference,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);                                 
      } else if (token.equals("boxing")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportAutoboxing,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);                                 
      } else if (token.equals("over-ann")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportMissingOverrideAnnotation,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);                                 
      } else if (token.equals("dep-ann")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportMissingDeprecatedAnnotation,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);                                 
      } else if (token.equals("intfAnnotation")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportAnnotationSuperInterface,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);                                 
      } else if (token.equals("enumSwitch") //$NON-NLS-1$
                  || token.equals("incomplete-switch")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportIncompleteEnumSwitch,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);                                 
      } else if (token.equals("hiding")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportHiddenCatchBlock,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            this.options.put(
                  CompilerOptions.OPTION_ReportLocalVariableHiding,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            this.options.put(
                  CompilerOptions.OPTION_ReportFieldHiding,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            this.options.put(
                  CompilerOptions.OPTION_ReportTypeParameterHiding,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("static-access")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportNonStaticAccessToStatic,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            this.options.put(
                  CompilerOptions.OPTION_ReportIndirectStaticAccess,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("unused")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportUnusedLocal, 
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            this.options.put(
                  CompilerOptions.OPTION_ReportUnusedParameter,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            this.options.put(
                  CompilerOptions.OPTION_ReportUnusedImport,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            this.options.put(
                  CompilerOptions.OPTION_ReportUnusedPrivateMember,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            this.options.put(
                  CompilerOptions.OPTION_ReportUnusedDeclaredThrownException,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
            this.options.put(
                        CompilerOptions.OPTION_ReportUnusedLabel,
                        isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("paramAssign")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportParameterAssignment,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("discouraged")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportDiscouragedReference,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("forbidden")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportForbiddenReference,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else if (token.equals("fallthrough")) { //$NON-NLS-1$
            this.options.put(
                  CompilerOptions.OPTION_ReportFallthroughCase,
                  isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
      } else {
            throw new InvalidInputException(this.bind("configure.invalidWarning", token)); //$NON-NLS-1$
      }
}

/*
Handle extdirs processing
*/
protected ArrayList handleExtdirs(ArrayList extdirsClasspaths) {
      final File javaHome = getJavaHome();

      /*
       * Feed extDirClasspath according to:
       * - -extdirs first if present;
       * - else java.ext.dirs if defined;
       * - else default extensions directory for the platform.
       */
      if (extdirsClasspaths == null) {
            extdirsClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
            String extdirsStr = System.getProperty("java.ext.dirs"); //$NON-NLS-1$
            if (extdirsStr == null) {
                  extdirsClasspaths.add(javaHome.getAbsolutePath() + "/lib/ext"); //$NON-NLS-1$
            } else {
                  StringTokenizer tokenizer = new StringTokenizer(extdirsStr, File.pathSeparator);
                  while (tokenizer.hasMoreTokens()) 
                        extdirsClasspaths.add(tokenizer.nextToken());
            }
      }
      
      /*
       * Feed extdirsClasspath with the entries found into the directories listed by
       * extdirsNames.
       */
      if (extdirsClasspaths.size() != 0) {
            File[] directoriesToCheck = new File[extdirsClasspaths.size()];
            for (int i = 0; i < directoriesToCheck.length; i++) 
                  directoriesToCheck[i] = new File((String) extdirsClasspaths.get(i));
            extdirsClasspaths.clear();
            File[][] extdirsJars = getLibrariesFiles(directoriesToCheck);
            if (extdirsJars != null) {
                  for (int i = 0, max = extdirsJars.length; i < max; i++) {
                        File[] current = extdirsJars[i];
                        if (current != null) {
                              for (int j = 0, max2 = current.length; j < max2; j++) {
                                    FileSystem.Classpath classpath = 
                                          FileSystem.getClasspath(
                                                      current[j].getAbsolutePath(),
                                                      null, null); 
                                    if (classpath != null) {
                                          extdirsClasspaths.add(classpath);
                                    }
                              }
                        } else if (directoriesToCheck[i].isFile()) {
                              this.logger.logIncorrectExtDirsEntry(directoriesToCheck[i].getAbsolutePath());
                        }
                  }
            }
      }
      
      return extdirsClasspaths;
}

protected ArrayList handleEndorseddirs(ArrayList endorsedDirClasspaths) {
      final File javaHome = getJavaHome();
      /*
       * Feed endorsedDirClasspath according to:
       * - -endorseddirs first if present;
       * - else java.endorsed.dirs if defined;
       * - else default extensions directory for the platform. (/lib/endorsed)
       */
      if (endorsedDirClasspaths == null) {
            endorsedDirClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
            String endorsedDirsStr = System.getProperty("java.endorsed.dirs"); //$NON-NLS-1$
            if (endorsedDirsStr == null) {
                  if (javaHome != null) {
                        endorsedDirClasspaths.add(javaHome.getAbsolutePath() + "/lib/endorsed"); //$NON-NLS-1$
                  }
            } else {
                  StringTokenizer tokenizer = new StringTokenizer(endorsedDirsStr, File.pathSeparator);
                  while (tokenizer.hasMoreTokens()) {
                        endorsedDirClasspaths.add(tokenizer.nextToken());
                  }
            }
      }
      
      /*
       * Feed extdirsClasspath with the entries found into the directories listed by
       * extdirsNames.
       */
      if (endorsedDirClasspaths.size() != 0) {
            File[] directoriesToCheck = new File[endorsedDirClasspaths.size()];
            for (int i = 0; i < directoriesToCheck.length; i++) 
                  directoriesToCheck[i] = new File((String) endorsedDirClasspaths.get(i));
            endorsedDirClasspaths.clear();
            File[][] endorsedDirsJars = getLibrariesFiles(directoriesToCheck);
            if (endorsedDirsJars != null) {
                  for (int i = 0, max = endorsedDirsJars.length; i < max; i++) {
                        File[] current = endorsedDirsJars[i];
                        if (current != null) {
                              for (int j = 0, max2 = current.length; j < max2; j++) {
                                    FileSystem.Classpath classpath = 
                                          FileSystem.getClasspath(
                                                      current[j].getAbsolutePath(),
                                                      null, null); 
                                    if (classpath != null) {
                                          endorsedDirClasspaths.add(classpath);
                                    }
                              }
                        } else if (directoriesToCheck[i].isFile()) {
                              this.logger.logIncorrectEndorsedDirsEntry(directoriesToCheck[i].getAbsolutePath());
                        }
                  }
            }
      }
      return endorsedDirClasspaths;
}

/*
Decode the command line arguments 
 */
public void configure(String[] argv) throws InvalidInputException {
      
      if ((argv == null) || (argv.length == 0)) {
            printUsage();
            return;
      }
      final int INSIDE_CLASSPATH_start = 1;
      final int INSIDE_DESTINATION_PATH = 3;
      final int INSIDE_TARGET = 4;
      final int INSIDE_LOG = 5;
      final int INSIDE_REPETITION = 6;
      final int INSIDE_SOURCE = 7;
      final int INSIDE_DEFAULT_ENCODING = 8;
      final int INSIDE_BOOTCLASSPATH_start = 9;
      final int INSIDE_MAX_PROBLEMS = 11;
      final int INSIDE_EXT_DIRS = 12;
      final int INSIDE_SOURCE_PATH_start = 13;
      final int INSIDE_ENDORSED_DIRS = 15;

      final int DEFAULT = 0;
      ArrayList bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
      String sourcepathClasspathArg = null;
      ArrayList sourcepathClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
      ArrayList classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
      ArrayList extdirsClasspaths = null;
      ArrayList endorsedDirClasspaths = null;
      
      int index = -1, filesCount = 0, argCount = argv.length;
      int mode = DEFAULT;
      this.repetitions = 0;
      boolean printUsageRequired = false;
      boolean printVersionRequired = false;
      
      boolean didSpecifyDefaultEncoding = false;
      boolean didSpecifyDeprecation = false;
      boolean didSpecifyWarnings = false;
      boolean useEnableJavadoc = false;
      boolean didSpecifyCompliance = false;     

      String customEncoding = null;
      String currentSourceDirectory = null;
      String currentArg = ""; //$NON-NLS-1$

      // expand the command line if necessary
      boolean needExpansion = false;
      loop: for (int i = 0; i < argCount; i++) {
                  if (argv[i].startsWith("@")) { //$NON-NLS-1$
                        needExpansion = true;
                        break loop;
                  }
      }

      String[] newCommandLineArgs = null;
      if (needExpansion) {
            newCommandLineArgs = new String[argCount];
            index = 0;
            for (int i = 0; i < argCount; i++) {
                  String[] newArgs = null;
                  String arg = argv[i].trim();
                  if (arg.startsWith("@")) { //$NON-NLS-1$
                        try {
                              LineNumberReader reader = new LineNumberReader(new StringReader(new String(Util.getFileCharContent(new File(arg.substring(1)), null))));
                              StringBuffer buffer = new StringBuffer();
                              String line;
                              while((line = reader.readLine()) != null) {
                                    line = line.trim();
                                    if (!line.startsWith("#")) { //$NON-NLS-1$
                                          buffer.append(line).append(" "); //$NON-NLS-1$
                                    }
                              }
                              newArgs = tokenize(buffer.toString());
                        } catch(IOException e) {
                              throw new InvalidInputException(
                                    this.bind("configure.invalidexpansionargumentname", arg)); //$NON-NLS-1$
                        }
                  }
                  if (newArgs != null) {
                        int newCommandLineArgsLength = newCommandLineArgs.length;
                        int newArgsLength = newArgs.length;
                        System.arraycopy(newCommandLineArgs, 0, (newCommandLineArgs = new String[newCommandLineArgsLength + newArgsLength - 1]), 0, index);
                        System.arraycopy(newArgs, 0, newCommandLineArgs, index, newArgsLength);
                        index += newArgsLength;
                  } else {
                        newCommandLineArgs[index++] = arg;
                  }
            }
            index = -1;
      } else {
            newCommandLineArgs = argv;
            for (int i = 0; i < argCount; i++) {
                  newCommandLineArgs[i] = newCommandLineArgs[i].trim();
            }
      }
      argCount = newCommandLineArgs.length;
      while (++index < argCount) {

            if (customEncoding != null) {
                  throw new InvalidInputException(
                        this.bind("configure.unexpectedCustomEncoding", currentArg, customEncoding)); //$NON-NLS-1$
            }

            currentArg = newCommandLineArgs[index];

            switch(mode) {
                  case DEFAULT :
                        customEncoding = null;
                        if (currentArg.endsWith("]")) { //$NON-NLS-1$
                              // look for encoding specification
                              int encodingStart = currentArg.indexOf('[') + 1;
                              int encodingEnd = currentArg.length() - 1;
                              if (encodingStart >= 1) {
                                    if (encodingStart < encodingEnd) {
                                          customEncoding = currentArg.substring(encodingStart, encodingEnd);
                                          try { // ensure encoding is supported
                                                new InputStreamReader(new ByteArrayInputStream(new byte[0]), customEncoding);
                                          } catch (UnsupportedEncodingException e) {
                                                throw new InvalidInputException(
                                                      this.bind("configure.unsupportedEncoding", customEncoding)); //$NON-NLS-1$
                                          }
                                    }
                                    currentArg = currentArg.substring(0, encodingStart - 1);
                              }
                        }
      
                        if (currentArg.endsWith(SuffixConstants.SUFFIX_STRING_java)) {
                              if (this.filenames == null) {
                                    this.filenames = new String[argCount - index];
                                    this.encodings = new String[argCount - index];
                              } else if (filesCount == this.filenames.length) {
                                    int length = this.filenames.length;
                                    System.arraycopy(
                                          this.filenames,
                                          0,
                                          (this.filenames = new String[length + argCount - index]),
                                          0,
                                          length);
                                    System.arraycopy(
                                          this.encodings,
                                          0,
                                          (this.encodings = new String[length + argCount - index]),
                                          0,
                                          length);
                              }
                              this.filenames[filesCount] = currentArg;
                              this.encodings[filesCount++] = customEncoding;
                              // destination path cannot be specified upon an individual file
                              customEncoding = null;
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-log")) { //$NON-NLS-1$
                              if (this.log != null)
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateLog", currentArg)); //$NON-NLS-1$
                              mode = INSIDE_LOG;
                              continue;
                        }
                        if (currentArg.equals("-repeat")) { //$NON-NLS-1$
                              if (this.repetitions > 0)
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateRepeat", currentArg)); //$NON-NLS-1$
                              mode = INSIDE_REPETITION;
                              continue;
                        }
                        if (currentArg.equals("-maxProblems")) { //$NON-NLS-1$
                              if (this.maxProblems > 0)
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateMaxProblems", currentArg)); //$NON-NLS-1$
                              mode = INSIDE_MAX_PROBLEMS;
                              continue;
                        }
                        if (currentArg.equals("-source")) { //$NON-NLS-1$
                              mode = INSIDE_SOURCE;
                              continue;
                        }
                        if (currentArg.equals("-encoding")) { //$NON-NLS-1$
                              mode = INSIDE_DEFAULT_ENCODING;
                              continue;
                        }
                        if (currentArg.equals("-1.3")) { //$NON-NLS-1$
                              if (didSpecifyCompliance) {
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateCompliance", currentArg));//$NON-NLS-1$
                              }
                              didSpecifyCompliance = true;
                              this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-1.4")) { //$NON-NLS-1$
                              if (didSpecifyCompliance) {
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
                              }
                              didSpecifyCompliance = true;
                              this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-1.5") || currentArg.equals("-5") || currentArg.equals("-5.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                              if (didSpecifyCompliance) {
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
                              }
                              didSpecifyCompliance = true;
                              this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-1.6") || currentArg.equals("-6") || currentArg.equals("-6.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                              if (didSpecifyCompliance) {
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
                              }
                              didSpecifyCompliance = true;
                              this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-d")) { //$NON-NLS-1$
                              if (this.destinationPath != null) {
                                    StringBuffer errorMessage = new StringBuffer();
                                    errorMessage.append(currentArg);
                                    if ((index + 1) < argCount) {
                                          errorMessage.append(' ');
                                          errorMessage.append(newCommandLineArgs[index + 1]);
                                    }
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateOutputPath", errorMessage.toString())); //$NON-NLS-1$
                              }
                              mode = INSIDE_DESTINATION_PATH;
                              continue;
                        }
                        if (currentArg.equals("-classpath") //$NON-NLS-1$
                              || currentArg.equals("-cp")) { //$NON-NLS-1$
                              mode = INSIDE_CLASSPATH_start;
                              continue;
                        }
                        if (currentArg.equals("-bootclasspath")) {//$NON-NLS-1$
                              if (bootclasspaths.size() > 0) {
                                    StringBuffer errorMessage = new StringBuffer();
                                    errorMessage.append(currentArg);
                                    if ((index + 1) < argCount) {
                                          errorMessage.append(' ');
                                          errorMessage.append(newCommandLineArgs[index + 1]);
                                    }
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateBootClasspath", errorMessage.toString())); //$NON-NLS-1$
                              }
                              mode = INSIDE_BOOTCLASSPATH_start;
                              continue;
                        }
                        if (currentArg.equals("-sourcepath")) {//$NON-NLS-1$
                              if (sourcepathClasspaths.size() > 0) {
                                    StringBuffer errorMessage = new StringBuffer();
                                    errorMessage.append(currentArg);
                                    if ((index + 1) < argCount) {
                                          errorMessage.append(' ');
                                          errorMessage.append(newCommandLineArgs[index + 1]);
                                    }
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateSourcepath", errorMessage.toString())); //$NON-NLS-1$
                              }
                              mode = INSIDE_SOURCE_PATH_start;
                              continue;
                        }
                        if (currentArg.equals("-extdirs")) {//$NON-NLS-1$
                              if (extdirsClasspaths != null) {
                                    StringBuffer errorMessage = new StringBuffer();
                                    errorMessage.append(currentArg);
                                    if ((index + 1) < argCount) {
                                          errorMessage.append(' ');
                                          errorMessage.append(newCommandLineArgs[index + 1]);
                                    }
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateExtDirs", errorMessage.toString())); //$NON-NLS-1$
                              }
                              mode = INSIDE_EXT_DIRS;
                              continue;
                        }
                        if (currentArg.equals("-endorseddirs")) { //$NON-NLS-1$
                              if (endorsedDirClasspaths != null) {
                                    StringBuffer errorMessage = new StringBuffer();
                                    errorMessage.append(currentArg);
                                    if ((index + 1) < argCount) {
                                          errorMessage.append(' ');
                                          errorMessage.append(newCommandLineArgs[index + 1]);
                                    }
                                    throw new InvalidInputException(
                                          this.bind("configure.duplicateEndorsedDirs", errorMessage.toString())); //$NON-NLS-1$
                              }
                              mode = INSIDE_ENDORSED_DIRS;
                              continue;
                        }
                        if (currentArg.equals("-progress")) { //$NON-NLS-1$
                              mode = DEFAULT;
                              this.showProgress = true;
                              continue;
                        }
                        if (currentArg.equals("-proceedOnError")) { //$NON-NLS-1$
                              mode = DEFAULT;
                              this.proceedOnError = true;
                              continue;
                        }
                        if (currentArg.equals("-time")) { //$NON-NLS-1$
                              mode = DEFAULT;
                              this.timing = true;
                              continue;
                        }
                        if (currentArg.equals("-version") //$NON-NLS-1$
                                    || currentArg.equals("-v")) { //$NON-NLS-1$
                              this.logger.logVersion(true);
                              this.proceed = false;
                              return;
                        }
                        if (currentArg.equals("-showversion")) { //$NON-NLS-1$
                              printVersionRequired = true;
                              mode = DEFAULT;
                              continue;
                        }                 
                        if ("-deprecation".equals(currentArg)) { //$NON-NLS-1$
                              didSpecifyDeprecation = true;
                              this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-help") || currentArg.equals("-?")) { //$NON-NLS-1$ //$NON-NLS-2$
                              printUsageRequired = true;
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-noExit")) { //$NON-NLS-1$
                              this.systemExitWhenFinished = false;
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-verbose")) { //$NON-NLS-1$
                              this.verbose = true;
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-referenceInfo")) { //$NON-NLS-1$
                              this.produceRefInfo = true;
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-inlineJSR")) { //$NON-NLS-1$
                            mode = DEFAULT;
                              this.options.put(
                                          CompilerOptions.OPTION_InlineJsr,
                                          CompilerOptions.ENABLED);
                            continue;
                        }
                        if (currentArg.startsWith("-g")) { //$NON-NLS-1$
                              mode = DEFAULT;
                              String debugOption = currentArg;
                              int length = currentArg.length();
                              if (length == 2) {
                                    this.options.put(
                                          CompilerOptions.OPTION_LocalVariableAttribute,
                                          CompilerOptions.GENERATE);
                                    this.options.put(
                                          CompilerOptions.OPTION_LineNumberAttribute,
                                          CompilerOptions.GENERATE);
                                    this.options.put(
                                          CompilerOptions.OPTION_SourceFileAttribute,
                                          CompilerOptions.GENERATE);
                                    continue;
                              }
                              if (length > 3) {
                                    this.options.put(
                                          CompilerOptions.OPTION_LocalVariableAttribute,
                                          CompilerOptions.DO_NOT_GENERATE);
                                    this.options.put(
                                          CompilerOptions.OPTION_LineNumberAttribute,
                                          CompilerOptions.DO_NOT_GENERATE);
                                    this.options.put(
                                          CompilerOptions.OPTION_SourceFileAttribute,
                                          CompilerOptions.DO_NOT_GENERATE);
                                    if (length == 7 && debugOption.equals("-g:" + NONE)) //$NON-NLS-1$
                                          continue;
                                    StringTokenizer tokenizer =
                                          new StringTokenizer(debugOption.substring(3, debugOption.length()), ","); //$NON-NLS-1$
                                    while (tokenizer.hasMoreTokens()) {
                                          String token = tokenizer.nextToken();
                                          if (token.equals("vars")) { //$NON-NLS-1$
                                                this.options.put(
                                                      CompilerOptions.OPTION_LocalVariableAttribute,
                                                      CompilerOptions.GENERATE);
                                          } else if (token.equals("lines")) { //$NON-NLS-1$
                                                this.options.put(
                                                      CompilerOptions.OPTION_LineNumberAttribute,
                                                      CompilerOptions.GENERATE);
                                          } else if (token.equals("source")) { //$NON-NLS-1$
                                                this.options.put(
                                                      CompilerOptions.OPTION_SourceFileAttribute,
                                                      CompilerOptions.GENERATE);
                                          } else {
                                                throw new InvalidInputException(
                                                      this.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
                                          }
                                    }
                                    continue;
                              }
                              throw new InvalidInputException(
                                    this.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
                        }
                        if (currentArg.startsWith("-nowarn")) { //$NON-NLS-1$
                              disableWarnings();
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.startsWith("-warn")) { //$NON-NLS-1$
                              mode = DEFAULT;
                              String warningOption = currentArg;
                              int length = currentArg.length();
                              if (length == 10 && warningOption.equals("-warn:" + NONE)) { //$NON-NLS-1$
                                    disableWarnings();
                                    continue;
                              }
                              if (length <= 6) {
                                    throw new InvalidInputException(
                                          this.bind("configure.invalidWarningConfiguration", warningOption)); //$NON-NLS-1$
                              }
                              int warnTokenStart;
                              boolean isEnabling;
                              switch (warningOption.charAt(6)) {
                                    case '+' : 
                                          warnTokenStart = 7;
                                          isEnabling = true;
                                          break;
                                    case '-' :
                                          warnTokenStart = 7;
                                          isEnabling = false; // mentionned warnings are disabled
                                          break;
                                    default:
                                          warnTokenStart = 6;
                                          // clear default warning level
                                          // but allow multiple warning option on the command line
                                          if (!didSpecifyWarnings) disableWarnings();
                                          isEnabling = true;
                              }
                        
                              StringTokenizer tokenizer =
                                    new StringTokenizer(warningOption.substring(warnTokenStart, warningOption.length()), ","); //$NON-NLS-1$
                              int tokenCounter = 0;
      
                              if (didSpecifyDeprecation) {  // deprecation could have also been set through -deprecation option
                                    this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
                              }
                              
                              while (tokenizer.hasMoreTokens()) {
                                    String token = tokenizer.nextToken();
                                    tokenCounter++;
                                    handleWarningToken(token, isEnabling, useEnableJavadoc);
                              }
                              if (tokenCounter == 0)
                                    throw new InvalidInputException(
                                          this.bind("configure.invalidWarningOption", currentArg)); //$NON-NLS-1$
                              didSpecifyWarnings = true;
                              continue;
                        }
                        if (currentArg.equals("-target")) { //$NON-NLS-1$
                              mode = INSIDE_TARGET;
                              continue;
                        }
                        if (currentArg.equals("-preserveAllLocals")) { //$NON-NLS-1$
                              this.options.put(
                                    CompilerOptions.OPTION_PreserveUnusedLocal,
                                    CompilerOptions.PRESERVE);
                            mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-enableJavadoc")) {//$NON-NLS-1$
                            mode = DEFAULT;
                              this.options.put(
                                    CompilerOptions.OPTION_DocCommentSupport,
                                    CompilerOptions.ENABLED);
                              useEnableJavadoc = true;
                              continue;
                        }
                        if (currentArg.equals("-Xemacs")) { //$NON-NLS-1$
                              mode = DEFAULT;
                              this.logger.setEmacs();
                              continue;
                        }
                        // tolerated javac options - quietly filtered out
                        if (currentArg.startsWith("-X")) { //$NON-NLS-1$
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.startsWith("-J")) { //$NON-NLS-1$
                              mode = DEFAULT;
                              continue;
                        }
                        if (currentArg.equals("-O")) { //$NON-NLS-1$
                              mode = DEFAULT;
                              continue;
                        }
                        break;
                  case INSIDE_TARGET :
                        if (this.didSpecifyTarget) {
                              throw new InvalidInputException(
                                    this.bind("configure.duplicateTarget", currentArg));//$NON-NLS-1$
                        }                       
                        this.didSpecifyTarget = true;
                        if (currentArg.equals("1.1")) { //$NON-NLS-1$
                              this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
                        } else if (currentArg.equals("1.2")) { //$NON-NLS-1$
                              this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
                        } else if (currentArg.equals("1.3")) { //$NON-NLS-1$
                              this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3);
                        } else if (currentArg.equals("1.4")) { //$NON-NLS-1$
                              this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
                        } else if (currentArg.equals("1.5") || currentArg.equals("5") || currentArg.equals("5.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
                              this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
                        } else if (currentArg.equals("1.6") || currentArg.equals("6") || currentArg.equals("6.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
                              this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
                        } else if (currentArg.equals("jsr14")) { //$NON-NLS-1$
                              this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_JSR14);
                        } else {
                              throw new InvalidInputException(this.bind("configure.targetJDK", currentArg)); //$NON-NLS-1$
                        }
                        mode = DEFAULT;
                        continue;
                  case INSIDE_LOG :
                        this.log = currentArg;
                        mode = DEFAULT;
                        continue;
                  case INSIDE_REPETITION :
                        try {
                              this.repetitions = Integer.parseInt(currentArg);
                              if (this.repetitions <= 0) {
                                    throw new InvalidInputException(this.bind("configure.repetition", currentArg)); //$NON-NLS-1$
                              }
                        } catch (NumberFormatException e) {
                              throw new InvalidInputException(this.bind("configure.repetition", currentArg)); //$NON-NLS-1$
                        }
                        mode = DEFAULT;
                        continue;
                  case INSIDE_MAX_PROBLEMS :
                        try {
                              this.maxProblems = Integer.parseInt(currentArg);
                              if (this.maxProblems <= 0) {
                                    throw new InvalidInputException(this.bind("configure.maxProblems", currentArg)); //$NON-NLS-1$
                              }
                              this.options.put(CompilerOptions.OPTION_MaxProblemPerUnit, currentArg);
                        } catch (NumberFormatException e) {
                              throw new InvalidInputException(this.bind("configure.maxProblems", currentArg)); //$NON-NLS-1$
                        }
                        mode = DEFAULT;
                        continue;
                  case INSIDE_SOURCE :
                        if (this.didSpecifySource) {
                              throw new InvalidInputException(
                                    this.bind("configure.duplicateSource", currentArg));//$NON-NLS-1$
                        }                       
                        this.didSpecifySource = true;
                        if (currentArg.equals("1.3")) { //$NON-NLS-1$
                              this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
                        } else if (currentArg.equals("1.4")) { //$NON-NLS-1$
                              this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
                        } else if (currentArg.equals("1.5") || currentArg.equals("5") || currentArg.equals("5.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
                              this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
                        } else if (currentArg.equals("1.6") || currentArg.equals("6") || currentArg.equals("6.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
                              this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6);
                        } else {
                              throw new InvalidInputException(this.bind("configure.source", currentArg)); //$NON-NLS-1$
                        }
                        mode = DEFAULT;
                        continue;
                  case INSIDE_DEFAULT_ENCODING :
                        if (didSpecifyDefaultEncoding) {
                              throw new InvalidInputException(
                                    this.bind("configure.duplicateDefaultEncoding", currentArg)); //$NON-NLS-1$
                        }
                        try { // ensure encoding is supported
                              new InputStreamReader(new ByteArrayInputStream(new byte[0]), currentArg);
                        } catch (UnsupportedEncodingException e) {
                              throw new InvalidInputException(
                                    this.bind("configure.unsupportedEncoding", currentArg)); //$NON-NLS-1$
                        }
                        this.options.put(CompilerOptions.OPTION_Encoding, currentArg);
                        didSpecifyDefaultEncoding = true;
                        mode = DEFAULT;
                        continue;
                  case INSIDE_DESTINATION_PATH :
                        if (!currentArg.equals(NONE)) {
                              this.setDestinationPath(currentArg);
                        }
                        mode = DEFAULT;
                        continue;
                  case INSIDE_CLASSPATH_start: 
                        classpaths.add(currentArg);
                        mode = DEFAULT;
                        continue;
                  case INSIDE_BOOTCLASSPATH_start: 
                        bootclasspaths.add(currentArg);
                        mode = DEFAULT;
                        continue;
                  case INSIDE_SOURCE_PATH_start:
                        sourcepathClasspaths.add(currentArg);
                        mode = DEFAULT;
                        continue;
                  case INSIDE_EXT_DIRS:
                        StringTokenizer tokenizer = new StringTokenizer(currentArg, File.pathSeparator, false);
                        extdirsClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
                        while (tokenizer.hasMoreTokens())
                              extdirsClasspaths.add(tokenizer.nextToken());
                        mode = DEFAULT;
                        continue;
                  case INSIDE_ENDORSED_DIRS:
                        tokenizer = new StringTokenizer(currentArg,     File.pathSeparator, false);
                        endorsedDirClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
                        while (tokenizer.hasMoreTokens())
                              endorsedDirClasspaths.add(tokenizer.nextToken());
                        mode = DEFAULT;
                        continue;
                        // continue; fall through on purpose
            }
            currentSourceDirectory = File.separatorChar == '/' ? currentArg : currentArg.replace('/', File.separatorChar);

            File dir = new File(currentSourceDirectory);
            if (!dir.isDirectory()) {
                  throw new InvalidInputException(
                        this.bind("configure.directoryNotExist", currentSourceDirectory)); //$NON-NLS-1$
            }
            String[] result = FileFinder.find(dir, SuffixConstants.SUFFIX_STRING_JAVA);
            if (this.filenames != null) {
                  // some source files were specified explicitly
                  int length = result.length;
                  System.arraycopy(
                        this.filenames,
                        0,
                        (this.filenames = new String[length + filesCount]),
                        0,
                        filesCount);
                  System.arraycopy(
                        this.encodings,
                        0,
                        (this.encodings = new String[length + filesCount]),
                        0,
                        filesCount);
                  System.arraycopy(result, 0, this.filenames, filesCount, length);
                  for (int i = 0; i < length; i++) {
                        this.encodings[filesCount + i] = customEncoding;
                  }
                  filesCount += length;
                  customEncoding = null;
                  currentSourceDirectory = null;
            } else {
                  this.filenames = result;
                  filesCount = this.filenames.length;
                  this.encodings = new String[filesCount];
                  for (int i = 0; i < filesCount; i++) {
                        this.encodings[i] = customEncoding;
                  }
                  customEncoding = null;
                  currentSourceDirectory = null;
            }
            mode = DEFAULT;
            continue;
      }
      
      if (printUsageRequired || filesCount == 0) {
            printUsage(); // default
            this.proceed = false;
            return;
      }

      if (this.log != null) {
            this.logger.setLog(this.log);
      } else {
            this.showProgress = false;
      }
      this.logger.logVersion(printVersionRequired);

      validateOptions(didSpecifyCompliance);
      
      this.logger.logCommandLineArguments(newCommandLineArgs);
      this.logger.logOptions(this.options);
      if (this.repetitions == 0) {
            this.repetitions = 1;
      }
      if (this.repetitions >= 3 && this.timing) {
            this.times = new long[this.repetitions];
            this.timesCounter = 0;
      }
      
      if (filesCount != 0)
            System.arraycopy(
                  this.filenames,
                  0,
                  (this.filenames = new String[filesCount]),
                  0,
                  filesCount);

      setPaths(bootclasspaths,
                  sourcepathClasspathArg,
                  sourcepathClasspaths,
                  classpaths,
                  extdirsClasspaths,
                  endorsedDirClasspaths,
                  customEncoding);
}

protected void disableWarnings() {
      Object[] entries = this.options.entrySet().toArray();
      for (int i = 0, max = entries.length; i < max; i++) {
            Map.Entry entry = (Map.Entry) entries[i];
            if (!(entry.getKey() instanceof String))
                  continue;
            if (!(entry.getValue() instanceof String))
                  continue;
            if (((String) entry.getValue()).equals(CompilerOptions.WARNING)) {
                  this.options.put(entry.getKey(), CompilerOptions.IGNORE);
            }
      }
      this.options.put(CompilerOptions.OPTION_TaskTags, ""); //$NON-NLS-1$
}

public String extractDestinationPathFromSourceFile(CompilationResult result) {
      ICompilationUnit compilationUnit = result.compilationUnit;
      if (compilationUnit != null) {
            char[] fileName = compilationUnit.getFileName();
            int lastIndex = CharOperation.lastIndexOf(java.io.File.separatorChar, fileName);
            if (lastIndex != -1) {
                  final String outputPathName = new String(fileName, 0, lastIndex);
                  final File output = new File(outputPathName);
                  if (output.exists() && output.isDirectory()) {
                        return outputPathName;
                  }
            }
      }
      return System.getProperty("user.dir"); //$NON-NLS-1$
}

/*
 * Answer the component to which will be handed back compilation results from the compiler
 */
public ICompilerRequestor getBatchRequestor() {
      return new ICompilerRequestor() {
            int lineDelta = 0;
            public void acceptResult(CompilationResult compilationResult) {
                  if (compilationResult.lineSeparatorPositions != null) {
                        int unitLineCount = compilationResult.lineSeparatorPositions.length;
                        Main.this.lineCount += unitLineCount;
                        this.lineDelta += unitLineCount;
                        if (Main.this.showProgress && this.lineDelta > 2000) {
                              // in -log mode, dump a dot every 2000 lines compiled
                              Main.this.logger.logProgress();
                              this.lineDelta = 0;
                        }
                  }
                  Main.this.logger.startLoggingSource(compilationResult);
                  if (compilationResult.hasProblems() || compilationResult.hasTasks()) {
                        int localErrorCount = Main.this.logger.logProblems(compilationResult.getAllProblems(), compilationResult.compilationUnit.getContents(), Main.this);
                        // exit?
                        if (Main.this.systemExitWhenFinished && !Main.this.proceedOnError && (localErrorCount > 0)) {
                              // ensure dumping problems for enqueued units as well, since may contain primary errors (123476)
                              CompilationUnitDeclaration[] queuedUnits = Main.this.batchCompiler.unitsToProcess;
                              for (int i = 0, length = Main.this.batchCompiler.totalUnits; i < length; i++) {
                                    CompilationUnitDeclaration queuedUnit = queuedUnits[i];
                                    if (queuedUnit == null) continue;
                                    CompilationResult result = queuedUnit.compilationResult;
                                    if (result.hasProblems() && !result.hasBeenAccepted) {
                                          Main.this.logger.logProblems(result.getAllProblems(), result.compilationUnit.getContents(), Main.this);
                                    }
                              }
                              Main.this.logger.endLoggingSource();
                              Main.this.logger.endLoggingSources();
                              Main.this.logger.printStats();
                              Main.this.logger.flush();
                              Main.this.logger.close();
                              System.exit(-1);
                        }
                  }
                  outputClassFiles(compilationResult);
                  Main.this.logger.endLoggingSource();
            }
      };
}

/*
 *  Build the set of compilation source units
 */
public CompilationUnit[] getCompilationUnits()
      throws InvalidInputException {
      int fileCount = this.filenames.length;
      CompilationUnit[] units = new CompilationUnit[fileCount];
      HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);

      String defaultEncoding = (String) this.options.get(CompilerOptions.OPTION_Encoding);
      if ("".equals(defaultEncoding)) //$NON-NLS-1$
            defaultEncoding = null;

      for (int i = 0; i < fileCount; i++) {
            char[] charName = this.filenames[i].toCharArray();
            if (knownFileNames.get(charName) != null)
                  throw new InvalidInputException(this.bind("unit.more", this.filenames[i])); //$NON-NLS-1$
            knownFileNames.put(charName, charName);
            File file = new File(this.filenames[i]);
            if (!file.exists())
                  throw new InvalidInputException(this.bind("unit.missing", this.filenames[i])); //$NON-NLS-1$
            String encoding = this.encodings[i];
            if (encoding == null)
                  encoding = defaultEncoding;
            units[i] = new CompilationUnit(null, this.filenames[i], encoding);
      }
      return units;
}

/*
 *  Low-level API performing the actual compilation
 */
public IErrorHandlingPolicy getHandlingPolicy() {

      // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match) 
      return new IErrorHandlingPolicy() {
            public boolean proceedOnErrors() {
                  return Main.this.proceedOnError; // stop if there are some errors 
            }
            public boolean stopOnFirstError() {
                  return false;
            }
      };
}

public File getJavaHome() {
      if (!javaHomeChecked) {
            javaHomeChecked = true;
            String javaHome = System.getProperty("java.home");//$NON-NLS-1$
            if (javaHome != null) {
                  this.javaHomeCache = new File(javaHome);
                  if (!this.javaHomeCache.exists())
                        this.javaHomeCache = null;
            }
      }
      return this.javaHomeCache;
}

public FileSystem getLibraryAccess() {
      return new FileSystem(this.checkedClasspaths, this.filenames);
}

/*
 *  Low-level API performing the actual compilation
 */
public IProblemFactory getProblemFactory() {
      return new DefaultProblemFactory(this.compilerLocale);
}

protected void initialize(PrintWriter outWriter,
            PrintWriter errWriter,
            boolean systemExit) {
      this.initialize(outWriter, errWriter, systemExit, null);
}
protected void initialize(PrintWriter outWriter,
            PrintWriter errWriter,
            boolean systemExit,
            Map customDefaultOptions) {
      this.logger = new Logger(this, outWriter, errWriter);
      this.out = outWriter;
      this.systemExitWhenFinished = systemExit;
      this.options = new CompilerOptions().getMap();
      if (customDefaultOptions != null) {
            this.didSpecifySource = customDefaultOptions.get(CompilerOptions.OPTION_Source) != null;
            this.didSpecifyTarget = customDefaultOptions.get(CompilerOptions.OPTION_TargetPlatform) != null;
            for (Iterator iter = customDefaultOptions.keySet().iterator(); iter.hasNext();) {
                  Object key = iter.next();
                  this.options.put(key, customDefaultOptions.get(key));
            }
      } else {
            this.didSpecifySource = false;
            this.didSpecifyTarget = false;
      }
}
public void outputClassFiles(CompilationResult unitResult) {
      if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) {
            ClassFile[] classFiles = unitResult.getClassFiles();
            if (!this.generatePackagesStructure) {
                  this.destinationPath = extractDestinationPathFromSourceFile(unitResult);
            }
            if (this.destinationPath != null) {
                  for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) {
                        // retrieve the key and the corresponding classfile
                        ClassFile classFile = classFiles[i];
                        char[] filename = classFile.fileName();
                        int length = filename.length;
                        char[] relativeName = new char[length + 6];
                        System.arraycopy(filename, 0, relativeName, 0, length);
                        System.arraycopy(SuffixConstants.SUFFIX_class, 0, relativeName, length, 6);
                        CharOperation.replace(relativeName, '/', File.separatorChar);
                        String relativeStringName = new String(relativeName);
                        try {
                              if (this.compilerOptions.verbose)
                                    this.out.println(
                                          Messages.bind(
                                                Messages.compilation_write,
                                                new String[] {
                                                      String.valueOf(this.exportedClassFilesCounter+1),
                                                      relativeStringName
                                                }));
                              ClassFile.writeToDisk(
                                    this.generatePackagesStructure,
                                    this.destinationPath,
                                    relativeStringName,
                                    classFile);
                              LookupEnvironment env = this.batchCompiler.lookupEnvironment;
                              if (classFile.isShared) env.classFilePool.release(classFile);
                              this.logger.logClassFile(
                                    this.generatePackagesStructure,
                                    this.destinationPath,
                                    relativeStringName);
                              this.exportedClassFilesCounter++;
                        } catch (IOException e) {
                              this.logger.logNoClassFileCreated(this.destinationPath, relativeStringName, e);
                        }
                  }
            }
      }
}

/*
 *  Low-level API performing the actual compilation
 */
public void performCompilation() throws InvalidInputException {

      this.startTime = System.currentTimeMillis();

      INameEnvironment environment = getLibraryAccess();
      this.compilerOptions = new CompilerOptions(this.options);
      this.compilerOptions.performStatementsRecovery = false;
      this.batchCompiler =
            new Compiler(
                  environment,
                  getHandlingPolicy(),
                  this.compilerOptions,
                  getBatchRequestor(),
                  getProblemFactory(),
                  this.out);

      // set the non-externally configurable options.
      this.compilerOptions.verbose = this.verbose;
      this.compilerOptions.produceReferenceInfo = this.produceRefInfo;
      try {
            this.logger.startLoggingSources();
            this.batchCompiler.compile(getCompilationUnits());
      } finally {
            this.logger.endLoggingSources();
      }

      this.logger.printStats();
      
      // cleanup
      environment.cleanup();
}

public void printUsage() {
      this.logger.logUsage(this.bind("misc.usage", //$NON-NLS-1$
            new String[] {
                  System.getProperty("path.separator"), //$NON-NLS-1$
                  this.bind("compiler.name"), //$NON-NLS-1$
                  this.bind("compiler.version"), //$NON-NLS-1$
                  this.bind("compiler.copyright") //$NON-NLS-1$
            }
      ));
}
public void processPathEntries(final int defaultSize, final ArrayList paths, 
                  final String currentPath, String customEncoding, boolean isSourceOnly,
                  boolean rejectDestinationPathOnJars) 
            throws InvalidInputException {
      String currentClasspathName = null;
      ArrayList currentRuleSpecs = new ArrayList(defaultSize);
      StringTokenizer tokenizer = new StringTokenizer(currentPath,
                  File.pathSeparator + "[]", true); //$NON-NLS-1$
      // state machine
      final int start = 0; 
      final int readyToClose = 1;
      // 'path' 'path1[rule];path2'
      final int readyToCloseEndingWithRules = 2;
      // 'path[rule]' 'path1;path2[rule]'
      final int readyToCloseOrOtherEntry = 3;
      // 'path[rule];' 'path;' 'path1;path2;'
      final int rulesNeedAnotherRule = 4;
      // 'path[rule1;'
      final int rulesStart = 5;
      // 'path[' 'path1;path2['
      final int rulesReadyToClose = 6;
      // 'path[rule' 'path[rule1;rule2'
      final int error = 99;
      int state = start;
      String token = null;
      while (tokenizer.hasMoreTokens() && state != error) {
            token = tokenizer.nextToken();
            if (token.equals(File.pathSeparator)) {
                  switch (state) {
                  case start:
                        break;
                  case readyToClose:
                  case readyToCloseEndingWithRules:
                  case readyToCloseOrOtherEntry:
                        state = readyToCloseOrOtherEntry;
                        addNewEntry(paths, currentClasspathName, currentRuleSpecs, 
                                    customEncoding, isSourceOnly);
                        currentRuleSpecs.clear();
                        break;
                  case rulesReadyToClose:
                        state = rulesNeedAnotherRule;
                        break;
                  default:
                        state = error;
                  }
            } else if (token.equals("[")) { //$NON-NLS-1$
                  switch (state) {
                  case readyToClose:
                        state = rulesStart;
                        break;
                  default:
                        state = error;
                  }
            } else if (token.equals("]")) { //$NON-NLS-1$
                  switch (state) {
                  case rulesReadyToClose:
                        state = readyToCloseEndingWithRules;
                        break;
                  default:
                        state = error;
                  }
            } else {
                  // regular word
                  switch (state) {
                  case start:
                  case readyToCloseOrOtherEntry:
                        state = readyToClose;
                        currentClasspathName = token;
                        break;
                  case rulesStart:
                  case rulesNeedAnotherRule:
                        state = rulesReadyToClose;
                        currentRuleSpecs.add(token);
                        break;
                  default:
                        state = error;
                  }
            }
      }
      switch(state) {
            case readyToClose:
            case readyToCloseEndingWithRules:
            case readyToCloseOrOtherEntry :
                  addNewEntry(paths, currentClasspathName, currentRuleSpecs, 
                        customEncoding, isSourceOnly);
                  break;
            default :
                  // we go on anyway
                  this.logger.logIncorrectClasspath(currentPath);
      }
}

/**
 * Creates a NLS catalog for the given locale.
 */
public void relocalize() {
      relocalize(Locale.getDefault());
}

public void relocalize(Locale locale) {
      this.compilerLocale = locale;
      try {
            this.bundle = ResourceBundle.getBundle(Main.bundleName, locale);
      } catch(MissingResourceException e) {
            System.out.println("Missing resource : " + Main.bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
            throw e;
      }
}
public void setLocale(Locale locale) {
      relocalize(locale);
}
/*
 * External API
 */
protected void setDestinationPath(String destPath) {
      this.destinationPath = destPath;
      this.generatePackagesStructure = true;
}
/*
 * External API
 */
protected void setPaths(ArrayList bootclasspaths,
            String sourcepathClasspathArg,
            ArrayList sourcepathClasspaths,
            ArrayList classpaths,
            ArrayList extdirsClasspaths,
            ArrayList endorsedDirClasspaths,
            String customEncoding) throws InvalidInputException {
      // process bootclasspath, classpath and sourcepaths
      final File javaHome = getJavaHome();
      final int bootclasspathsSize = bootclasspaths.size();
      if (bootclasspathsSize != 0) {
            String[] paths = new String[bootclasspathsSize];
            bootclasspaths.toArray(paths);
            bootclasspaths.clear();
            for (int i = 0; i < bootclasspathsSize; i++) {
                  processPathEntries(DEFAULT_SIZE_CLASSPATH, bootclasspaths, paths[i], customEncoding, false, false);
            }
      } else {
            /* no bootclasspath specified
             * we can try to retrieve the default librairies of the VM used to run
             * the batch compiler
             */
             String javaversion = System.getProperty("java.version");//$NON-NLS-1$
             if (javaversion != null && javaversion.equalsIgnoreCase("1.1.8")) { //$NON-NLS-1$
                  this.logger.logWrongJDK();
                  this.proceed = false;
                  return;
             }

            /*
             * Handle >= JDK 1.2.2 settings: retrieve rt.jar
             */
             if (javaHome != null) {
                  File[] directoriesToCheck = null;
                  if (System.getProperty("os.name").startsWith("Mac")) {//$NON-NLS-1$//$NON-NLS-2$
                        directoriesToCheck = new File[] {
                              new File(javaHome, "../Classes"), //$NON-NLS-1$
                        };
                  } else {
                        directoriesToCheck = new File[] { 
                              new File(javaHome, "lib") //$NON-NLS-1$
                        };
                  }
                  File[][] systemLibrariesJars = getLibrariesFiles(directoriesToCheck);
                  if (systemLibrariesJars != null) {
                        for (int i = 0, max = systemLibrariesJars.length; i < max; i++) {
                              File[] current = systemLibrariesJars[i];
                              if (current != null) {
                                    for (int j = 0, max2 = current.length; j < max2; j++) {
                                          FileSystem.Classpath classpath = 
                                                FileSystem.getClasspath(current[j].getAbsolutePath(),
                                                      null, false, null); 
                                          if (classpath != null) {
                                                bootclasspaths.add(classpath);
                                          }
                                    }
                              }
                        }
                  }
            }
      }
      final int classpathsSize = classpaths.size();
      if (classpaths.size() != 0) {
            String[] paths = new String[classpathsSize];
            classpaths.toArray(paths);
            classpaths.clear();
            for (int i = 0; i < classpathsSize; i++) {
                  processPathEntries(DEFAULT_SIZE_CLASSPATH, classpaths, paths[i], 
                              customEncoding, false, false);
            }                 
      } else {
            // no user classpath specified.
            String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$
            if ((classProp == null) || (classProp.length() == 0)) {
                  this.logger.logNoClasspath();
                  classpaths.add(FileSystem.getClasspath(System.getProperty("user.dir"), customEncoding, null));//$NON-NLS-1$
            } else {
                  StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator);
                  String token;
                  while (tokenizer.hasMoreTokens()) {
                        token = tokenizer.nextToken();
                        FileSystem.Classpath currentClasspath = FileSystem
                                    .getClasspath(token, customEncoding, null);
                        if (currentClasspath != null) {
                              classpaths.add(currentClasspath);
                        } else {
                              this.logger.logIncorrectClasspath(token);
                              // should not happen - we go on anyway
                        }
                  }
            }
      }
      final int sourcepathClasspathsSize = sourcepathClasspaths.size();
      if (sourcepathClasspathsSize != 0) {
            String[] paths = new String[sourcepathClasspathsSize];
            sourcepathClasspaths.toArray(paths);
            sourcepathClasspaths.clear();
            for (int i = 0; i < sourcepathClasspathsSize; i++) {
                  processPathEntries(DEFAULT_SIZE_CLASSPATH, sourcepathClasspaths, paths[i], customEncoding, true, false);
            }                 
      }

      /*
       * Feed endorsedDirClasspath according to:
       * - -extdirs first if present;
       * - else java.ext.dirs if defined;
       * - else default extensions directory for the platform.
       */
      extdirsClasspaths = handleExtdirs(extdirsClasspaths);

      endorsedDirClasspaths = handleEndorseddirs(endorsedDirClasspaths);
      
      /* 
       * Concatenate classpath entries
       * We put the bootclasspath at the beginning of the classpath
       * entries, followed by the extension libraries, followed by
       * the sourcepath followed by the classpath.  All classpath
       * entries are searched for both sources and binaries except
       * the sourcepath entries which are searched for sources only.
       */
      bootclasspaths.addAll(endorsedDirClasspaths);
      bootclasspaths.addAll(extdirsClasspaths);
      bootclasspaths.addAll(sourcepathClasspaths);
      bootclasspaths.addAll(classpaths);
      classpaths = bootclasspaths;
      this.checkedClasspaths = new FileSystem.Classpath[classpaths.size()];
      classpaths.toArray(this.checkedClasspaths);
      this.logger.logClasspath(this.checkedClasspaths);
}
protected void validateOptions(boolean didSpecifyCompliance) throws InvalidInputException {
      if (didSpecifyCompliance) {
            Object version = this.options.get(CompilerOptions.OPTION_Compliance);
            if (CompilerOptions.VERSION_1_3.equals(version)) {
                  if (!this.didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
                  if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
            } else if (CompilerOptions.VERSION_1_4.equals(version)) {
                  if (!this.didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
                  if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
            } else if (CompilerOptions.VERSION_1_5.equals(version)) {
                  if (!this.didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
                  if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
            } else if (CompilerOptions.VERSION_1_6.equals(version)) {
                  if (!this.didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6);
                  if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
            }
      }
      if (this.didSpecifySource) {
            Object version = this.options.get(CompilerOptions.OPTION_Source);
            // default is source 1.3 target 1.2 and compliance 1.4
            if (CompilerOptions.VERSION_1_4.equals(version)) {
                  if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
                  if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
            } else if (CompilerOptions.VERSION_1_5.equals(version)) {
                  if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
                  if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
            } else if (CompilerOptions.VERSION_1_6.equals(version)) {
                  if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
                  if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
            }
      }

      final Object sourceVersion = this.options.get(CompilerOptions.OPTION_Source);
      final Object compliance = this.options.get(CompilerOptions.OPTION_Compliance);
      if (sourceVersion.equals(CompilerOptions.VERSION_1_6)
                  && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_6) {
            // compliance must be 1.6 if source is 1.6
            throw new InvalidInputException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
      } else if (sourceVersion.equals(CompilerOptions.VERSION_1_5)
                  && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_5) {
            // compliance must be 1.5 if source is 1.5
            throw new InvalidInputException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
      } else if (sourceVersion.equals(CompilerOptions.VERSION_1_4)
                  && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_4) {
            // compliance must be 1.4 if source is 1.4
            throw new InvalidInputException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
      }

      // check and set compliance/source/target compatibilities
      if (this.didSpecifyTarget) {
            final Object targetVersion = this.options.get(CompilerOptions.OPTION_TargetPlatform); 
            // tolerate jsr14 target
            if (CompilerOptions.VERSION_JSR14.equals(targetVersion)) {
                  // expecting source >= 1.5
                  if (CompilerOptions.versionToJdkLevel(sourceVersion) < ClassFileConstants.JDK1_5) {
                        throw new InvalidInputException(this.bind("configure.incompatibleTargetForGenericSource", (String) targetVersion, (String) sourceVersion)); //$NON-NLS-1$
                  }
            } else {
                  // target must be 1.6 if source is 1.6
                  if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_6
                              && CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_6){ 
                        throw new InvalidInputException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
                  }
                  // target must be 1.5 if source is 1.5
                  if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_5
                              && CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_5){ 
                        throw new InvalidInputException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
                  }
                   // target must be 1.4 if source is 1.4
                  if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_4
                              && CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_4){ 
                        throw new InvalidInputException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
                  }
                  // target cannot be greater than compliance level
                  if (CompilerOptions.versionToJdkLevel(compliance) < CompilerOptions.versionToJdkLevel(targetVersion)){ 
                        throw new InvalidInputException(this.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), (String) targetVersion)); //$NON-NLS-1$
                  }
            }
      }
}
}

Generated by  Doxygen 1.6.0   Back to index