org.apache.tools.ant.UnknownElement

public class UnknownElement extends Task {

    /**
     * Holds the name of the task/type or nested child element of a
     * task/type that hasn't been defined at parser time or has
     * been redefined since original creation.
     */
    private String elementName;

    /**
     * The real object after it has been loaded.
     */
    private Object realThing;

    /**
     * List of child elements (UnknownElements).
     */
    private Vector children = new Vector();

    /**
     * Creates an UnknownElement for the given element name.
     *
     * @param elementName The name of the unknown element.
     *                    Must not be null.
     */
    public UnknownElement (String elementName) {
        this.elementName = elementName;
    }

    /**
     * Returns the name of the XML element which generated this unknown
     * element.
     *
     * @return the name of the XML element which generated this unknown
     *         element.
     */
    public String getTag() {
        return elementName;
    }

    /**
     * Creates the real object instance and child elements, then configures
     * the attributes and text of the real object. This unknown element
     * is then replaced with the real object in the containing target's list
     * of children.
     *
     * @exception BuildException if the configuration fails
     */
    public void maybeConfigure() throws BuildException {
        realThing = makeObject(this, wrapper);

        wrapper.setProxy(realThing);
        if (realThing instanceof Task) {
            ((Task) realThing).setRuntimeConfigurableWrapper(wrapper);
        }

        handleChildren(realThing, wrapper);

        wrapper.maybeConfigure(getProject());
    }

    /**
     * Handles output sent to System.out by this task or its real task.
     *
     * @param line The line of output to log. Should not be null.
     */
    protected void handleOutput(String line) {
        if (realThing instanceof Task) {
            ((Task) realThing).handleOutput(line);
        } else {
            super.handleOutput(line);
        }
    }

    /**
     * Handles output sent to System.out by this task or its real task.
     *
     * @param line The line of output to log. Should not be null.
     */
    protected void handleFlush(String line) {
        if (realThing instanceof Task) {
            ((Task) realThing).handleFlush(line);
        } else {
            super.handleFlush(line);
        }
    }

    /**
     * Handles error output sent to System.err by this task or its real task.
     *
     * @param line The error line to log. Should not be null.
     */
    protected void handleErrorOutput(String line) {
        if (realThing instanceof Task) {
            ((Task) realThing).handleErrorOutput(line);
        } else {
            super.handleErrorOutput(line);
        }
    }

    /**
     * Handles error output sent to System.err by this task or its real task.
     *
     * @param line The error line to log. Should not be null.
     */
    protected void handleErrorFlush(String line) {
        if (realThing instanceof Task) {
            ((Task) realThing).handleErrorOutput(line);
        } else {
            super.handleErrorOutput(line);
        }
    }

    /**
     * Executes the real object if it's a task. If it's not a task
     * (e.g. a data type) then this method does nothing.
     */
    public void execute() {
        if (realThing == null) {
            throw new BuildException("Could not create task of type: "
                                     + elementName, getLocation());
        }

        if (realThing instanceof Task) {
            ((Task) realThing).execute();
        }
    }

    /**
     * Adds a child element to this element.
     *
     * @param child The child element to add. Must not be null.
     */
    public void addChild(UnknownElement child) {
        children.addElement(child);
    }

    /**
     * Creates child elements, creates children of the children
     * (recursively), and sets attributes of the child elements.
     *
     * @param parent The configured object for the parent.
     *               Must not be null.
     *
     * @param parentWrapper The wrapper containing child wrappers
     *                      to be configured. Must not be null
     *                      if there are any children.
     *
     * @exception BuildException if the children cannot be configured.
     */
    protected void handleChildren(Object parent,
                                  RuntimeConfigurable parentWrapper)
        throws BuildException {

        if (parent instanceof TaskAdapter) {
            parent = ((TaskAdapter) parent).getProxy();
        }

        Class parentClass = parent.getClass();
        IntrospectionHelper ih = IntrospectionHelper.getHelper(parentClass);

        for (int i = 0;  i < children.size(); i++) {
            RuntimeConfigurable childWrapper = parentWrapper.getChild(i);
            UnknownElement child = (UnknownElement) children.elementAt(i);
            Object realChild = null;

            if (parent instanceof TaskContainer) {
                realChild = makeTask(child, childWrapper, false);
                ((TaskContainer) parent).addTask((Task) realChild);
            } else {
                realChild = ih.createElement(getProject(), parent, child.getTag());
            }

            childWrapper.setProxy(realChild);
            if (parent instanceof TaskContainer) {
                ((Task) realChild).setRuntimeConfigurableWrapper(childWrapper);
            }

            child.handleChildren(realChild, childWrapper);
        }
    }

    /**
     * Creates a named task or data type. If the real object is a task,
     * it is configured up to the init() stage.
     *
     * @param ue The unknown element to create the real object for.
     *           Must not be null.
     * @param w  Ignored in this implementation.
     *
     * @return the task or data type represented by the given unknown element.
     */
    protected Object makeObject(UnknownElement ue, RuntimeConfigurable w) {
        Object o = makeTask(ue, w, true);
        if (o == null) {
            o = getProject().createDataType(ue.getTag());
        }
        if (o == null) {
            throw getNotFoundException("task or type", ue.getTag());
        }
        return o;
    }

    /**
     * Creates a named task and configures it up to the init() stage.
     *
     * @param ue The UnknownElement to create the real task for.
     *           Must not be null.
     * @param w  Ignored.
     * @param onTopLevel Whether or not this is definitely trying to create
     *                   a task. If this is true and the
     *                   task name is not recognised, a BuildException
     *                   is thrown.
     *
     * @return the task specified by the given unknown element, or
     *         null if the task name is not recognised and
     *         onTopLevel is false.
     */
    protected Task makeTask(UnknownElement ue, RuntimeConfigurable w,
                            boolean onTopLevel) {
        Task task = getProject().createTask(ue.getTag());
        if (task == null && !onTopLevel) {
            throw getNotFoundException("task", ue.getTag());
        }

        if (task != null) {
            task.setLocation(getLocation());
            task.setOwningTarget(getOwningTarget());
            task.init();
        }
        return task;
    }

    /**
     * Returns a very verbose exception for when a task/data type cannot
     * be found.
     *
     * @param what The kind of thing being created. For example, when
     *             a task name could not be found, this would be
     *             "task". Should not be null.
     * @param elementName The name of the element which could not be found.
     *                    Should not be null.
     *
     * @return a detailed description of what might have caused the problem.
     */
    protected BuildException getNotFoundException(String what,
                                                  String elementName) {
        String lSep = System.getProperty("line.separator");
        String msg = "Could not create " + what + " of type: " + elementName
            + "." + lSep + lSep
            + "Ant could not find the task or a class this "
            + "task relies upon." + lSep + lSep
            + "This is common and has a number of causes; the usual " + lSep
            + "solutions are to read the manual pages then download and" + lSep
            + "install needed JAR files, or fix the build file: " + lSep
            + " - You have misspelt '" + elementName + "'." + lSep
            + "   Fix: check your spelling." + lSep
            + " - The task needs an external JAR file to execute" + lSep
            + "   and this is not found at the right place in the classpath." + lSep
            + "   Fix: check the documentation for dependencies." + lSep
            + "   Fix: declare the task." + lSep
            + " - The task is an Ant optional task and optional.jar is absent" + lSep
            + "   Fix: look for optional.jar in ANT_HOME/lib, download if needed" + lSep
            + " - The task was not built into optional.jar as dependent"  + lSep
            + "   libraries were not found at build time." + lSep
            + "   Fix: look in the JAR to verify, then rebuild with the needed" + lSep
            + "   libraries, or download a release version from apache.org" + lSep
            + " - The build file was written for a later version of Ant" + lSep
            + "   Fix: upgrade to at least the latest release version of Ant" + lSep
            + " - The task is not an Ant core or optional task " + lSep
            + "   and needs to be declared using <taskdef>." + lSep
            + lSep
            + "Remember that for JAR files to be visible to Ant tasks implemented" + lSep
            + "in ANT_HOME/lib, the files must be in the same directory or on the" + lSep
            + "classpath" + lSep
            + lSep
            + "Please neither file bug reports on this problem, nor email the" + lSep
            + "Ant mailing lists, until all of these causes have been explored," + lSep
            + "as this is not an Ant bug.";

        return new BuildException(msg, getLocation());
    }

    /**
     * Returns the name to use in logging messages.
     *
     * @return the name to use in logging messages.
     */
    public String getTaskName() {
        return realThing == null || !(realThing instanceof Task) ?
            super.getTaskName() : ((Task) realThing).getTaskName();
    }

    /**
     * Returns the task instance after it has been created and if it is a task.
     *
     * @return a task instance or null if the real object is not
     *         a task.
     */
    public Task getTask() {
        if (realThing instanceof Task) {
            return (Task) realThing;
        }
        return null;

FUNC_DECL IF CALL CALL BINARY_OP CALL ASSIGN CALL CALL


org.apache.xml.utils.ObjectPool

public class ObjectPool implements java.io.Serializable
{

  /** Type of objects in this pool.
   *  @serial          */
  private final Class objectType;

  /** Vector of given objects this points to.
   *  @serial          */
  private final Vector freeStack;

  /**
   * Constructor ObjectPool
   *
   * @param type Type of objects for this pool
   */
  public ObjectPool(Class type)
  {
    objectType = type;
    freeStack = new Vector();
  }

  /**
   * Constructor ObjectPool
   *
   * @param className Fully qualified name of the type of objects for this pool.
   */
  public ObjectPool(String className)
  {
    try
    {
      objectType = ObjectFactory.findProviderClass(
        className, ObjectFactory.findClassLoader(), true);
    }
    catch(ClassNotFoundException cnfe)
    {
      throw new WrappedRuntimeException(cnfe);
    }
    freeStack = new Vector();
  }

  /**
   * Constructor ObjectPool
   *
   *
   * @param type Type of objects for this pool
   * @param size Size of vector to allocate
   */
  public ObjectPool(Class type, int size)
  {
    objectType = type;
    freeStack = new Vector(size);
  }

  /**
   * Constructor ObjectPool
   *
   */
  public ObjectPool()
  {
    objectType = null;
    freeStack = new Vector();
  }

  /**
   * Get an instance of the given object in this pool if available
   *
   *
   * @return an instance of the given object if available or null
   */
  public synchronized Object getInstanceIfFree()
  {

    if (!freeStack.isEmpty())
    {

      Object result = freeStack.lastElement();

      freeStack.setSize(freeStack.size() - 1);

      return result;
    }

    return null;
  }

  /**
   * Get an instance of the given object in this pool
   *
   *
   * @return An instance of the given object
   */
  public synchronized Object getInstance()
  {

    if (freeStack.isEmpty())
    {

      try
      {
        return objectType.newInstance();
      }
      catch (InstantiationException ex){}
      catch (IllegalAccessException ex){}

    }
    else
    {

      Object result = freeStack.lastElement();

      freeStack.setSize(freeStack.size() - 1);

      return result;
    }
  }

  /**
   * Add an instance of the given object to the pool
   *
   *
   * @param obj Object to add.
   */
  public synchronized void freeInstance(Object obj)
  {

    freeStack.addElement(obj);

FUNC_DECL IF CALL RETURN VAR_DECL TRY CALL CATCH CATCH RETURN BINARY_OP CALL CALL LITERAL_ANCHOR CALL

FUNC_DECL TRY PARAM ASSIGN CATCH CALL THROW_RAISE ASSIGN CALL CALL LITERAL_ANCHOR CALL

FUNC_DECL PARAM PARAM ASSIGN ASSIGN CALL


public class FullAnalyzer extends AbstractAnalyzer {
    /**
     * Default constructor
     *
     * Causes the BCEL classes to load to ensure BCEL dependencies can
     * be satisfied
     */
    public FullAnalyzer() {
        try {
            new ClassParser("force");
        } catch (IOException e) {
        }
    }

    /**
     * Determine the dependencies of the configured root classes.
     *
     * @param files a vector to be populated with the files which contain
     *      the dependency classes
     * @param classes a vector to be populated with the names of the
     *      depencency classes.
     */
    protected void determineDependencies(Vector files, Vector classes) {
        Hashtable dependencies = new Hashtable();
        Hashtable containers = new Hashtable();
        Hashtable toAnalyze = new Hashtable();
        for (Enumeration e = getRootClasses(); e.hasMoreElements();) {
            String classname = (String) e.nextElement();
            toAnalyze.put(classname, classname);
        }

        int count = 0;
        int maxCount = isClosureRequired() ? MAX_LOOPS : 2;
        while (toAnalyze.size() != 0 && count++ < maxCount) {
            DependencyVisitor dependencyVisitor = new DependencyVisitor();
            for (Enumeration e = toAnalyze.keys(); e.hasMoreElements();) {
                String classname = (String) e.nextElement();
                dependencies.put(classname, classname);
                try {
                    File container = getClassContainer(classname);
                    if (container == null) {
                        continue;
                    }
                    containers.put(container, container);

                    ClassParser parser = null;
                    if (container.getName().endsWith(".class")) {
                        parser = new ClassParser(container.getPath());
                    } else {
                        parser = new ClassParser(container.getPath(),
                            classname.replace('.', '/') + ".class");
                    }

                    JavaClass javaClass = parser.parse();
                    DescendingVisitor traverser
                         = new DescendingVisitor(javaClass, dependencyVisitor);
                    traverser.visit();
                } catch (IOException ioe) {
                }
            }

            toAnalyze.clear();

            Enumeration depsEnum = dependencyVisitor.getDependencies();
            while (depsEnum.hasMoreElements()) {
                String className = (String) depsEnum.nextElement();
                if (!dependencies.containsKey(className)) {
                    toAnalyze.put(className, className);
                }
            }
        }

        files.removeAllElements();
        for (Enumeration e = containers.keys(); e.hasMoreElements();) {
            files.addElement((File) e.nextElement());
        }

        classes.removeAllElements();
        for (Enumeration e = dependencies.keys(); e.hasMoreElements();) {
            classes.addElement((String) e.nextElement());
        }
    }

    /**
     * Indicate if this analyzer can determine dependent files.
     *
     * @return true if the analyzer provides dependency file information.
     */
    protected boolean supportsFileDependencies() {
        return true;


public class JakartaOroMatcher implements RegexpMatcher {

    protected Perl5Matcher reg = new Perl5Matcher();
    protected Perl5Compiler comp = new Perl5Compiler();
    private Pattern pattern;

    /**
     * Set the regexp pattern from the String description.
     */
    public void setPattern(String pattern) throws BuildException {
        try {
            this.pattern = comp.compile(pattern);
        } catch (MalformedPatternException e) {
            throw new BuildException(e);
        }
    }

    /**
     * Get a String representation of the regexp pattern
     */
    public String getPattern() {
        return pattern.getPattern();
    }

    /**
     * Does the given argument match the pattern?
     */
    public boolean matches(String argument) {
        return reg.contains(argument, pattern);
    }

    /**
     * Returns a Vector of matched groups found in the argument.
     *
     *
Group 0 will be the full match, the rest are the
     * parenthesized subexpressions
.
     */
    public Vector getGroups(String argument) {
        if (!matches(argument)) {
            return null;
        }
        Vector v = new Vector();
        MatchResult mr = reg.getMatch();
        for (int i=0; i<mr.groups(); i++) {
            v.addElement(mr.group(i));
        }
        return v;

FUNC_DECL TRY PARAM CATCH THROW_RAISE ASSIGN CALL CALL


public class RuntimeTransformException extends RuntimeCamelException {

    private static final long serialVersionUID = -8417806626073055262L;

    public RuntimeTransformException(String message) {
        super(message);
    }

    public RuntimeTransformException(String message, Throwable cause) {
        super(message, cause);
    }

    public RuntimeTransformException(Throwable cause) {
        super(cause);


org.apache.tools.ant.Project

public class Project {

    /** Message priority of "error". */
    public static final int MSG_ERR = 0;
    /** Message priority of "warning". */
    public static final int MSG_WARN = 1;
    /** Message priority of "information". */
    public static final int MSG_INFO = 2;
    /** Message priority of "verbose". */
    public static final int MSG_VERBOSE = 3;
    /** Message priority of "debug". */
    public static final int MSG_DEBUG = 4;

    /**
     * Constant for the "visiting" state, used when
     * traversing a DFS of target dependencies.
     */
    private static final String VISITING = "VISITING";
    /**
     * Constant for the "visited" state, used when
     * traversing a DFS of target dependencies.
     */
    private static final String VISITED = "VISITED";

    /**
     * Version constant for Java 1.0
     *
     * @deprecated use org.apache.tools.ant.util.JavaEnvUtils instead
     */
    public static final String JAVA_1_0 = JavaEnvUtils.JAVA_1_0;
    /**
     * Version constant for Java 1.1
     *
     * @deprecated use org.apache.tools.ant.util.JavaEnvUtils instead
     */
    public static final String JAVA_1_1 = JavaEnvUtils.JAVA_1_1;
    /**
     * Version constant for Java 1.2
     *
     * @deprecated use org.apache.tools.ant.util.JavaEnvUtils instead
     */
    public static final String JAVA_1_2 = JavaEnvUtils.JAVA_1_2;
    /**
     * Version constant for Java 1.3
     *
     * @deprecated use org.apache.tools.ant.util.JavaEnvUtils instead
     */
    public static final String JAVA_1_3 = JavaEnvUtils.JAVA_1_3;
    /**
     * Version constant for Java 1.4
     *
     * @deprecated use org.apache.tools.ant.util.JavaEnvUtils instead
     */
    public static final String JAVA_1_4 = JavaEnvUtils.JAVA_1_4;

    /** Default filter start token. */
    public static final String TOKEN_START = FilterSet.DEFAULT_TOKEN_START;
    /** Default filter end token. */
    public static final String TOKEN_END = FilterSet.DEFAULT_TOKEN_END;

    /** Name of this project. */
    private String name;
    /** Description for this project (if any). */
    private String description;

    /** Project properties map (usually String to String). */
    private Hashtable properties = new Hashtable();
    /**
     * Map of "user" properties (as created in the Ant task, for example).
     * Note that these key/value pairs are also always put into the
     * project properties, so only the project properties need to be queried.
     * Mapping is String to String.
     */
    private Hashtable userProperties = new Hashtable();
    /**
     * Map of inherited "user" properties - that are those "user"
     * properties that have been created by tasks and not been set
     * from the command line or a GUI tool.
     * Mapping is String to String.
     */
    private Hashtable inheritedProperties = new Hashtable();
    /** Map of references within the project (paths etc) (String to Object). */
    private Hashtable references = new Hashtable();

    /** Name of the project's default target. */
    private String defaultTarget;
    /** Map from data type names to implementing classes (String to Class). */
    private Hashtable dataClassDefinitions = new Hashtable();
    /** Map from task names to implementing classes (String to Class). */
    private Hashtable taskClassDefinitions = new Hashtable();
    /**
     * Map from task names to vectors of created tasks
     * (String to Vector of Task). This is used to invalidate tasks if
     * the task definition changes.
     */
    private Hashtable createdTasks = new Hashtable();
    /** Map from target names to targets (String to Target). */
    private Hashtable targets = new Hashtable();
    /** Set of global filters. */
    private FilterSet globalFilterSet = new FilterSet();
    /**
     * Wrapper around globalFilterSet. This collection only ever
     * contains one FilterSet, but the wrapper is needed in order to
     * make it easier to use the FileUtils interface.
     */
    private FilterSetCollection globalFilters
        = new FilterSetCollection(globalFilterSet);

    /** Project base directory. */
    private File baseDir;

    /** List of listeners to notify of build events. */
    private Vector listeners = new Vector();

    /**
     * The Ant core classloader - may be null if using
     * parent classloader.
     */
    private ClassLoader coreLoader = null;

    /** Records the latest task to be executed on a thread (Thread to Task). */
    private Hashtable threadTasks = new Hashtable();

    /**
     * Called to handle any input requests.
     */
    private InputHandler inputHandler = null;

    /**
     * Sets the input handler
     */
    public void setInputHandler(InputHandler handler) {
        inputHandler = handler;
    }

    /**
     * Retrieves the current input handler.
     */
    public InputHandler getInputHandler() {
        return inputHandler;
    }

    /** Instance of a utility class to use for file operations. */
    private FileUtils fileUtils;

    /**
     * Flag which catches Listeners which try to use System.out or System.err
     */
    private boolean loggingMessage = false;

    /**
     * Creates a new Ant project.
     */
    public Project() {
        fileUtils = FileUtils.newFileUtils();
        inputHandler = new DefaultInputHandler();
    }

    /**
     * Initialises the project.
     *
     * This involves setting the default task definitions and loading the
     * system properties.
     *
     * @exception BuildException if the default task list cannot be loaded
     */
    public void init() throws BuildException {
        setJavaVersionProperty();

        String defs = "/org/apache/tools/ant/taskdefs/defaults.properties";

        try {
            Properties props = new Properties();
            InputStream in = this.getClass().getResourceAsStream(defs);
            if (in == null) {
                throw new BuildException("Can't load default task list");
            }
            props.load(in);
            in.close();

            Enumeration enum1 = props.propertyNames();
            while (enum1.hasMoreElements()) {
                String key = (String) enum1.nextElement();
                String value = props.getProperty(key);
                try {
                    Class taskClass = Class.forName(value);
                    addTaskDefinition(key, taskClass);
                } catch (NoClassDefFoundError ncdfe) {
                    log("Could not load a dependent class ("
                        + ncdfe.getMessage() + ") for task " + key, MSG_DEBUG);
                } catch (ClassNotFoundException cnfe) {
                    log("Could not load class (" + value
                        + ") for task " + key, MSG_DEBUG);
                }
            }
        } catch (IOException ioe) {
            throw new BuildException("Can't load default task list");
        }

        String dataDefs = "/org/apache/tools/ant/types/defaults.properties";

        try {
            Properties props = new Properties();
            InputStream in = this.getClass().getResourceAsStream(dataDefs);
            if (in == null) {
                throw new BuildException("Can't load default datatype list");
            }
            props.load(in);
            in.close();

            Enumeration enum1 = props.propertyNames();
            while (enum1.hasMoreElements()) {
                String key = (String) enum1.nextElement();
                String value = props.getProperty(key);
                try {
                    Class dataClass = Class.forName(value);
                    addDataTypeDefinition(key, dataClass);
                } catch (NoClassDefFoundError ncdfe) {
                } catch (ClassNotFoundException cnfe) {
                }
            }
        } catch (IOException ioe) {
            throw new BuildException("Can't load default datatype list");
        }

        setSystemProperties();
    }

    /**
     * Sets the core classloader for the project. If a null
     * classloader is specified, the parent classloader should be used.
     *
     * @param coreLoader The classloader to use for the project.
     *                   May be null.
     */
    public void setCoreLoader(ClassLoader coreLoader) {
        this.coreLoader = coreLoader;
    }

    /**
     * Returns the core classloader to use for this project.
     * This may be null, indicating that
     * the parent classloader should be used.
     *
     * @return the core classloader to use for this project.
     *
     */
    public ClassLoader getCoreLoader() {
        return coreLoader;
    }

    /**
     * Adds a build listener to the list. This listener will
     * be notified of build events for this project.
     *
     * @param listener The listener to add to the list.
     *                 Must not be null.
     */
    public void addBuildListener(BuildListener listener) {
        listeners.addElement(listener);
    }

    /**
     * Removes a build listener from the list. This listener
     * will no longer be notified of build events for this project.
     *
     * @param listener The listener to remove from the list.
     *                 Should not be null.
     */
    public void removeBuildListener(BuildListener listener) {
        listeners.removeElement(listener);
    }

    /**
     * Returns a list of build listeners for the project.
     *
     * @return a list of build listeners for the project
     */
    public Vector getBuildListeners() {
        return (Vector) listeners.clone();
    }

    /**
     * Writes a message to the log with the default log level
     * of MSG_INFO
     * @param message The text to log. Should not be null.
     */

    public void log(String message) {
        log(message, MSG_INFO);
    }

    /**
     * Writes a project level message to the log with the given log level.
     * @param message The text to log. Should not be null.
     * @param msgLevel The priority level to log at.
     */
    public void log(String message, int msgLevel) {
        fireMessageLogged(this, message, msgLevel);
    }

    /**
     * Writes a task level message to the log with the given log level.
     * @param task The task to use in the log. Must not be null.
     * @param message The text to log. Should not be null.
     * @param msgLevel The priority level to log at.
     */
    public void log(Task task, String message, int msgLevel) {
        fireMessageLogged(task, message, msgLevel);
    }

    /**
     * Writes a target level message to the log with the given log level.
     * @param target The target to use in the log.
     *               Must not be null.
     * @param message The text to log. Should not be null.
     * @param msgLevel The priority level to log at.
     */
    public void log(Target target, String message, int msgLevel) {
        fireMessageLogged(target, message, msgLevel);
    }

    /**
     * Returns the set of global filters.
     *
     * @return the set of global filters
     */
    public FilterSet getGlobalFilterSet() {
        return globalFilterSet;
    }

    /**
     * Sets a property. Any existing property of the same name
     * is overwritten, unless it is a user property.
     * @param name The name of property to set.
     *             Must not be null.
     * @param value The new value of the property.
     *              Must not be null.
     */
    public synchronized void setProperty(String name, String value) {
        if (null != userProperties.get(name)) {
            log("Override ignored for user property " + name, MSG_VERBOSE);
            return;
        }

        if (null != properties.get(name)) {
            log("Overriding previous definition of property " + name,
                MSG_VERBOSE);
        }

        log("Setting project property: " + name + " -> " +
             value, MSG_DEBUG);
        properties.put(name, value);
    }

    /**
     * Sets a property if no value currently exists. If the property
     * exists already, a message is logged and the method returns with
     * no other effect.
     *
     * @param name The name of property to set.
     *             Must not be null.
     * @param value The new value of the property.
     *              Must not be null.
     * @since 1.5
     */
    public synchronized void setNewProperty(String name, String value) {
        if (null != properties.get(name)) {
            log("Override ignored for property " + name, MSG_VERBOSE);
            return;
        }
        log("Setting project property: " + name + " -> " +
            value, MSG_DEBUG);
        properties.put(name, value);
    }

    /**
     * Sets a user property, which cannot be overwritten by
     * set/unset property calls. Any previous value is overwritten.
     * @param name The name of property to set.
     *             Must not be null.
     * @param value The new value of the property.
     *              Must not be null.
     * @see #setProperty(String,String)
     */
    public synchronized void setUserProperty(String name, String value) {
        log("Setting ro project property: " + name + " -> " +
            value, MSG_DEBUG);
        userProperties.put(name, value);
        properties.put(name, value);
    }

    /**
     * Sets a user property, which cannot be overwritten by set/unset
     * property calls. Any previous value is overwritten. Also marks
     * these properties as properties that have not come from the
     * command line.
     *
     * @param name The name of property to set.
     *             Must not be null.
     * @param value The new value of the property.
     *              Must not be null.
     * @see #setProperty(String,String)
     */
    public synchronized void setInheritedProperty(String name, String value) {
        inheritedProperties.put(name, value);
        setUserProperty(name, value);
    }

    /**
     * Sets a property unless it is already defined as a user property
     * (in which case the method returns silently).
     *
     * @param name The name of the property.
     *             Must not be null.
     * @param value The property value. Must not be null.
     */
    private void setPropertyInternal(String name, String value) {
        if (null != userProperties.get(name)) {
            return;
        }
        properties.put(name, value);
    }

    /**
     * Returns the value of a property, if it is set.
     *
     * @param name The name of the property.
     *             May be null, in which case
     *             the return value is also null.
     * @return the property value, or null for no match
     *         or if a null name is provided.
     */
    public String getProperty(String name) {
        if (name == null) {
          return null;
        }
        String property = (String) properties.get(name);
        return property;
    }

    /**
     * Replaces ${} style constructions in the given value with the
     * string value of the corresponding data types.
     *
     * @param value The string to be scanned for property references.
     *              May be null.
     *
     * @return the given string with embedded property names replaced
     *         by values, or null if the given string is
     *         null.
     *
     * @exception BuildException if the given value has an unclosed
     *                           property name, e.g. ${xxx
     */
    public String replaceProperties(String value)
        throws BuildException {
        return ProjectHelper.replaceProperties(this, value, properties);
    }

    /**
     * Returns the value of a user property, if it is set.
     *
     * @param name The name of the property.
     *             May be null, in which case
     *             the return value is also null.
     * @return the property value, or null for no match
     *         or if a null name is provided.
     */
     public String getUserProperty(String name) {
        if (name == null) {
            return null;
        }
        String property = (String) userProperties.get(name);
        return property;
    }

    /**
     * Returns a copy of the properties table.
     * @return a hashtable containing all properties
     *         (including user properties).
     */
    public Hashtable getProperties() {
        Hashtable propertiesCopy = new Hashtable();

        Enumeration e = properties.keys();
        while (e.hasMoreElements()) {
            Object name = e.nextElement();
            Object value = properties.get(name);
            propertiesCopy.put(name, value);
        }

        return propertiesCopy;
    }

    /**
     * Returns a copy of the user property hashtable
     * @return a hashtable containing just the user properties
     */
    public Hashtable getUserProperties() {
        Hashtable propertiesCopy = new Hashtable();

        Enumeration e = userProperties.keys();
        while (e.hasMoreElements()) {
            Object name = e.nextElement();
            Object value = properties.get(name);
            propertiesCopy.put(name, value);
        }

        return propertiesCopy;
    }

    /**
     * Copies all user properties that have been set on the command
     * line or a GUI tool from this instance to the Project instance
     * given as the argument.
     *
     *
To copy all "user" properties, you will also have to call
     * {@link #copyInheritedProperties copyInheritedProperties}.

     *
     * @param other the project to copy the properties to.  Must not be null.
     *
     * @since Ant 1.5
     */
    public void copyUserProperties(Project other) {
        Enumeration e = userProperties.keys();
        while (e.hasMoreElements()) {
            Object arg = e.nextElement();
            if (inheritedProperties.containsKey(arg)) {
                continue;
            }
            Object value = userProperties.get(arg);
            other.setUserProperty(arg.toString(), value.toString());
        }
    }

    /**
     * Copies all user properties that have not been set on the
     * command line or a GUI tool from this instance to the Project
     * instance given as the argument.
     *
     *
To copy all "user" properties, you will also have to call
     * {@link #copyUserProperties copyUserProperties}.

     *
     * @param other the project to copy the properties to.  Must not be null.
     *
     * @since Ant 1.5
     */
    public void copyInheritedProperties(Project other) {
        Enumeration e = inheritedProperties.keys();
        while (e.hasMoreElements()) {
            String arg = e.nextElement().toString();
            if (other.getUserProperty(arg) != null) {
                continue;
            }
            Object value = inheritedProperties.get(arg);
            other.setInheritedProperty(arg, value.toString());
        }
    }

    /**
     * Sets the default target of the project.
     *
     * @param defaultTarget The name of the default target for this project.
     *                      May be null, indicating that there is
     *                      no default target.
     *
     * @deprecated use setDefault
     * @see #setDefault(String)
     */
    public void setDefaultTarget(String defaultTarget) {
        this.defaultTarget = defaultTarget;
    }

    /**
     * Returns the name of the default target of the project.
     * @return name of the default target or
     *         null if no default has been set.
     */
    public String getDefaultTarget() {
        return defaultTarget;
    }

    /**
     * Sets the default target of the project.
     *
     * @param defaultTarget The name of the default target for this project.
     *                      May be null, indicating that there is
     *                      no default target.
     */
    public void setDefault(String defaultTarget) {
        this.defaultTarget = defaultTarget;
    }

    /**
     * Sets the name of the project, also setting the user
     * property ant.project.name.
     *
     * @param name The name of the project.
     *             Must not be null.
     */
    public void setName(String name) {
        setUserProperty("ant.project.name",  name);
        this.name = name;
    }

    /**
     * Returns the project name, if one has been set.
     *
     * @return the project name, or null if it hasn't been set.
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the project description.
     *
     * @param description The description of the project.
     *                    May be null.
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * Returns the project description, if one has been set.
     *
     * @return the project description, or null if it hasn't
     *         been set.
     */
    public String getDescription() {
        return description;
    }

    /**
     * Adds a filter to the set of global filters.
     *
     * @param token The token to filter.
     *              Must not be null.
     * @param value The replacement value.
     *              Must not be null.
     * @deprecated Use getGlobalFilterSet().addFilter(token,value)
     *
     * @see #getGlobalFilterSet()
     * @see FilterSet#addFilter(String,String)
     */
    public void addFilter(String token, String value) {
        if (token == null) {
            return;
        }

        globalFilterSet.addFilter(new FilterSet.Filter(token, value));
    }

    /**
     * Returns a hashtable of global filters, mapping tokens to values.
     *
     * @return a hashtable of global filters, mapping tokens to values
     *         (String to String).
     *
     * @deprecated Use getGlobalFilterSet().getFilterHash()
     *
     * @see #getGlobalFilterSet()
     * @see FilterSet#getFilterHash()
     */
    public Hashtable getFilters() {
        return globalFilterSet.getFilterHash();
    }

    /**
     * Sets the base directory for the project, checking that
     * the given filename exists and is a directory.
     *
     * @param baseD The project base directory.
     *              Must not be null.
     *
     * @exception BuildException if the directory if invalid
     */
    public void setBasedir(String baseD) throws BuildException {
        setBaseDir(new File(baseD));
    }

    /**
     * Sets the base directory for the project, checking that
     * the given file exists and is a directory.
     *
     * @param baseDir The project base directory.
     *                Must not be null.
     * @exception BuildException if the specified file doesn't exist or
     *                           isn't a directory
     */
    public void setBaseDir(File baseDir) throws BuildException {
        baseDir = fileUtils.normalize(baseDir.getAbsolutePath());
        if (!baseDir.exists()) {
            throw new BuildException("Basedir " + baseDir.getAbsolutePath()
                + " does not exist");
        }
        if (!baseDir.isDirectory()) {
            throw new BuildException("Basedir " + baseDir.getAbsolutePath()
                + " is not a directory");
        }
        this.baseDir = baseDir;
        setPropertyInternal("basedir", this.baseDir.getPath());
        String msg = "Project base dir set to: " + this.baseDir;
        log(msg, MSG_VERBOSE);
    }

    /**
     * Returns the base directory of the project as a file object.
     *
     * @return the project base directory, or null if the
     *         base directory has not been successfully set to a valid value.
     */
    public File getBaseDir() {
        if (baseDir == null) {
            try {
                setBasedir(".");
            } catch (BuildException ex) {
                ex.printStackTrace();
            }
        }
        return baseDir;
    }

    /**
     * Returns the version of Java this class is running under.
     * @return the version of Java as a String, e.g. "1.1"
     * @see org.apache.tools.ant.util.JavaEnvUtils#getJavaVersion
     * @deprecated use org.apache.tools.ant.util.JavaEnvUtils instead
     */
    public static String getJavaVersion() {
        return JavaEnvUtils.getJavaVersion();
    }

    /**
     * Sets the ant.java.version property and tests for
     * unsupported JVM versions. If the version is supported,
     * verbose log messages are generated to record the Java version
     * and operating system name.
     *
     * @exception BuildException if this Java version is not supported
     *
     * @see org.apache.tools.ant.util.JavaEnvUtils#getJavaVersion
     */
    public void setJavaVersionProperty() throws BuildException {
        String javaVersion = JavaEnvUtils.getJavaVersion();
        setPropertyInternal("ant.java.version", javaVersion);

        if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_0)) {
            throw new BuildException("Ant cannot work on Java 1.0");
        }

        log("Detected Java version: " + javaVersion + " in: "
            + System.getProperty("java.home"), MSG_VERBOSE);

        log("Detected OS: " + System.getProperty("os.name"), MSG_VERBOSE);
    }

    /**
     * Adds all system properties which aren't already defined as
     * user properties to the project properties.
     */
    public void setSystemProperties() {
        Properties systemP = System.getProperties();
        Enumeration e = systemP.keys();
        while (e.hasMoreElements()) {
            Object name = e.nextElement();
            String value = systemP.get(name).toString();
            this.setPropertyInternal(name.toString(), value);
        }
    }

    /**
     * Adds a new task definition to the project.
     * Attempting to override an existing definition with an
     * equivalent one (i.e. with the same classname) results in
     * a verbose log message. Attempting to override an existing definition
     * with a different one results in a warning log message and
     * invalidates any tasks which have already been created with the
     * old definition.
     *
     * @param taskName The name of the task to add.
     *                 Must not be null.
     * @param taskClass The full name of the class implementing the task.
     *                  Must not be null.
     *
     * @exception BuildException if the class is unsuitable for being an Ant
     *                           task. An error level message is logged before
     *                           this exception is thrown.
     *
     * @see #checkTaskClass(Class)
     */
    public void addTaskDefinition(String taskName, Class taskClass)
         throws BuildException {
        Class old = (Class) taskClassDefinitions.get(taskName);
        if (null != old) {
            if (old.equals(taskClass)) {
                log("Ignoring override for task " + taskName
                    + ", it is already defined by the same class.",
                    MSG_VERBOSE);
                return;
            } else {
                int logLevel = MSG_WARN;
                if (old.getName().equals(taskClass.getName())) {
                    ClassLoader oldLoader = old.getClassLoader();
                    ClassLoader newLoader = taskClass.getClassLoader();
                    if (oldLoader != null
                        && newLoader != null
                        && oldLoader instanceof AntClassLoader
                        && newLoader instanceof AntClassLoader
                        && ((AntClassLoader) oldLoader).getClasspath()
                        .equals(((AntClassLoader) newLoader).getClasspath())
                        ) {
                        logLevel = MSG_VERBOSE;
                    }
                }

                log("Trying to override old definition of task " + taskName,
                    logLevel);
                invalidateCreatedTasks(taskName);
            }
        }

        String msg = " +User task: " + taskName + "     " + taskClass.getName();
        log(msg, MSG_DEBUG);
        checkTaskClass(taskClass);
        taskClassDefinitions.put(taskName, taskClass);
    }

    /**
     * Checks whether or not a class is suitable for serving as Ant task.
     * Ant task implementation classes must be public, concrete, and have
     * a no-arg constructor.
     *
     * @param taskClass The class to be checked.
     *                  Must not be null.
     *
     * @exception BuildException if the class is unsuitable for being an Ant
     *                           task. An error level message is logged before
     *                           this exception is thrown.
     */
    public void checkTaskClass(final Class taskClass) throws BuildException {
        if (!Modifier.isPublic(taskClass.getModifiers())) {
            final String message = taskClass + " is not public";
            log(message, Project.MSG_ERR);
            throw new BuildException(message);
        }
        if (Modifier.isAbstract(taskClass.getModifiers())) {
            final String message = taskClass + " is abstract";
            log(message, Project.MSG_ERR);
            throw new BuildException(message);
        }
        try {
            taskClass.getConstructor(null);
        } catch (NoSuchMethodException e) {
            final String message = "No public no-arg constructor in "
                + taskClass;
            log(message, Project.MSG_ERR);
            throw new BuildException(message);
        }
        if (!Task.class.isAssignableFrom(taskClass)) {
            TaskAdapter.checkTaskClass(taskClass, this);
        }
    }

    /**
     * Returns the current task definition hashtable. The returned hashtable is
     * "live" and so should not be modified.
     *
     * @return a map of from task name to implementing class
     *         (String to Class).
     */
    public Hashtable getTaskDefinitions() {
        return taskClassDefinitions;
    }

    /**
     * Adds a new datatype definition.
     * Attempting to override an existing definition with an
     * equivalent one (i.e. with the same classname) results in
     * a verbose log message. Attempting to override an existing definition
     * with a different one results in a warning log message, but the
     * definition is changed.
     *
     * @param typeName The name of the datatype.
     *                 Must not be null.
     * @param typeClass The full name of the class implementing the datatype.
     *                  Must not be null.
     */
    public void addDataTypeDefinition(String typeName, Class typeClass) {
        synchronized(dataClassDefinitions) {
            Class old = (Class) dataClassDefinitions.get(typeName);
            if (null != old) {
                if (old.equals(typeClass)) {
                    log("Ignoring override for datatype " + typeName
                        + ", it is already defined by the same class.",
                        MSG_VERBOSE);
                    return;
                } else {
                    log("Trying to override old definition of datatype "
                        + typeName, MSG_WARN);
                }
            }
            dataClassDefinitions.put(typeName, typeClass);
        }
        String msg = " +User datatype: " + typeName + "     "
            + typeClass.getName();
        log(msg, MSG_DEBUG);
    }

    /**
     * Returns the current datatype definition hashtable. The returned
     * hashtable is "live" and so should not be modified.
     *
     * @return a map of from datatype name to implementing class
     *         (String to Class).
     */
    public Hashtable getDataTypeDefinitions() {
        return dataClassDefinitions;
    }

    /**
     * Adds a new target to the project.
     *
     * @param target The target to be added to the project.
     *               Must not be null.
     *
     * @exception BuildException if the target already exists in the project
     *
     * @see Project#addOrReplaceTarget
     */
    public void addTarget(Target target) throws BuildException {
        String name = target.getName();
        if (targets.get(name) != null) {
            throw new BuildException("Duplicate target: `" + name + "'");
        }
        addOrReplaceTarget(name, target);
    }

    /**
     * Adds a new target to the project.
     *
     * @param targetName The name to use for the target.
     *             Must not be null.
     * @param target The target to be added to the project.
     *               Must not be null.
     *
     * @exception BuildException if the target already exists in the project
     *
     * @see Project#addOrReplaceTarget
     */
     public void addTarget(String targetName, Target target)
         throws BuildException {
         if (targets.get(targetName) != null) {
             throw new BuildException("Duplicate target: `" + targetName + "'");
         }
         addOrReplaceTarget(targetName, target);
     }

    /**
     * Adds a target to the project, or replaces one with the same
     * name.
     *
     * @param target The target to be added or replaced in the project.
     *               Must not be null.
     */
    public void addOrReplaceTarget(Target target) {
        addOrReplaceTarget(target.getName(), target);
    }

    /**
     * Adds a target to the project, or replaces one with the same
     * name.
     *
     * @param targetName The name to use for the target.
     *                   Must not be null.
     * @param target The target to be added or replaced in the project.
     *               Must not be null.
     */
    public void addOrReplaceTarget(String targetName, Target target) {
        String msg = " +Target: " + targetName;
        log(msg, MSG_DEBUG);
        target.setProject(this);
        targets.put(targetName, target);
    }

    /**
     * Returns the hashtable of targets. The returned hashtable
     * is "live" and so should not be modified.
     * @return a map from name to target (String to Target).
     */
    public Hashtable getTargets() {
        return targets;
    }

    /**
     * Creates a new instance of a task.
     *
     * @param taskType The name of the task to create an instance of.
     *                 Must not be null.
     *
     * @return an instance of the specified task, or null if
     *         the task name is not recognised.
     *
     * @exception BuildException if the task name is recognised but task
     *                           creation fails.
     */
    public Task createTask(String taskType) throws BuildException {
        Class c = (Class) taskClassDefinitions.get(taskType);

        if (c == null) {
            return null;
        }

        try {
            Object o = c.newInstance();
            Task task = null;
            if (o instanceof Task) {
               task = (Task) o;
            } else {
                TaskAdapter taskA = new TaskAdapter();
                taskA.setProxy(o);
                task = taskA;
            }
            task.setProject(this);
            task.setTaskType(taskType);

            task.setTaskName(taskType);

            String msg = "   +Task: " + taskType;
            log (msg, MSG_DEBUG);
            addCreatedTask(taskType, task);
            return task;
        } catch (Throwable t) {
            String msg = "Could not create task of type: "
                 + taskType + " due to " + t;
            throw new BuildException(msg, t);
        }
    }

    /**
     * Keeps a record of all tasks that have been created so that they
     * can be invalidated if a new task definition overrides the current one.
     *
     * @param type The name of the type of task which has been created.
     *             Must not be null.
     *
     * @param task The freshly created task instance.
     *             Must not be null.
     */
    private void addCreatedTask(String type, Task task) {
        synchronized (createdTasks) {
            Vector v = (Vector) createdTasks.get(type);
            if (v == null) {
                v = new Vector();
                createdTasks.put(type, v);
            }
            v.addElement(task);
        }
    }

    /**
     * Mark tasks as invalid which no longer are of the correct type
     * for a given taskname.
     *
     * @param type The name of the type of task to invalidate.
     *             Must not be null.
     */
    private void invalidateCreatedTasks(String type) {
        synchronized (createdTasks) {
            Vector v = (Vector) createdTasks.get(type);
            if (v != null) {
                Enumeration enum1 = v.elements();
                while (enum1.hasMoreElements()) {
                    Task t = (Task) enum1.nextElement();
                    t.markInvalid();
                }
                v.removeAllElements();
                createdTasks.remove(type);
            }
        }
    }

    /**
     * Creates a new instance of a data type.
     *
     * @param typeName The name of the data type to create an instance of.
     *                 Must not be null.
     *
     * @return an instance of the specified data type, or null if
     *         the data type name is not recognised.
     *
     * @exception BuildException if the data type name is recognised but
     *                           instance creation fails.
     */
    public Object createDataType(String typeName) throws BuildException {
        Class c = (Class) dataClassDefinitions.get(typeName);

        if (c == null) {
            return null;
        }

        try {
            java.lang.reflect.Constructor ctor = null;
            boolean noArg = false;
            try {
                ctor = c.getConstructor(new Class[0]);
                noArg = true;
            } catch (NoSuchMethodException nse) {
                ctor = c.getConstructor(new Class[] {Project.class});
                noArg = false;
            }

            Object o = null;
            if (noArg) {
                 o = ctor.newInstance(new Object[0]);
            } else {
                 o = ctor.newInstance(new Object[] {this});
            }
            if (o instanceof ProjectComponent) {
                ((ProjectComponent) o).setProject(this);
            }
            String msg = "   +DataType: " + typeName;
            log (msg, MSG_DEBUG);
            return o;
        } catch (java.lang.reflect.InvocationTargetException ite) {
            Throwable t = ite.getTargetException();
            String msg = "Could not create datatype of type: "
                 + typeName + " due to " + t;
            throw new BuildException(msg, t);
        } catch (Throwable t) {
            String msg = "Could not create datatype of type: "
                 + typeName + " due to " + t;
            throw new BuildException(msg, t);
        }
    }

    /**
     * Execute the specified sequence of targets, and the targets
     * they depend on.
     *
     * @param targetNames A vector of target name strings to execute.
     *                    Must not be null.
     *
     * @exception BuildException if the build failed
     */
    public void executeTargets(Vector targetNames) throws BuildException {
        Throwable error = null;

        for (int i = 0; i < targetNames.size(); i++) {
            executeTarget((String) targetNames.elementAt(i));
        }
    }

    /**
     * Demultiplexes output so that each task receives the appropriate
     * messages. If the current thread is not currently executing a task,
     * the message is logged directly.
     *
     * @param line Message to handle. Should not be null.
     * @param isError Whether the text represents an error (true)
     *        or information (false).
     */
    public void demuxOutput(String line, boolean isError) {
        Task task = (Task) threadTasks.get(Thread.currentThread());
        if (task == null) {
            fireMessageLogged(this, line, isError ? MSG_ERR : MSG_INFO);
        } else {
            if (isError) {
                task.handleErrorOutput(line);
            } else {
                task.handleOutput(line);
            }
        }
    }

    /**
     * Demultiplexes flush operation so that each task receives the appropriate
     * messages. If the current thread is not currently executing a task,
     * the message is logged directly.
     *
     * @since Ant 1.5.2
     *
     * @param line Message to handle. Should not be null.
     * @param isError Whether the text represents an error (true)
     *        or information (false).
     * @param terminated true if this line should be terminated with an
     *        end-of-line marker
     */
    public void demuxFlush(String line, boolean isError) {
        Task task = (Task) threadTasks.get(Thread.currentThread());
        if (task == null) {
            fireMessageLogged(this, line, isError ? MSG_ERR : MSG_INFO);
        } else {
            if (isError) {
                task.handleErrorFlush(line);
            } else {
                task.handleFlush(line);
            }
        }
    }

    /**
     * Executes the specified target and any targets it depends on.
     *
     * @param targetName The name of the target to execute.
     *                   Must not be null.
     *
     * @exception BuildException if the build failed
     */
    public void executeTarget(String targetName) throws BuildException {

        if (targetName == null) {
            String msg = "No target specified";
            throw new BuildException(msg);
        }

        Vector sortedTargets = topoSort(targetName, targets);

        int curidx = 0;
        Target curtarget;

        do {
            curtarget = (Target) sortedTargets.elementAt(curidx++);
            curtarget.performTasks();
        } while (!curtarget.getName().equals(targetName));
    }

    /**
     * Returns the canonical form of a filename.
     *

     * If the specified file name is relative it is resolved
     * with respect to the given root directory.
     *
     * @param fileName The name of the file to resolve.
     *                 Must not be null.
     *
     * @param rootDir  The directory to resolve relative file names with
     *                 respect to. May be null, in which case
     *                 the current directory is used.
     *
     * @return the resolved File.
     *
     * @deprecated
     */
    public File resolveFile(String fileName, File rootDir) {
        return fileUtils.resolveFile(rootDir, fileName);
    }

    /**
     * Returns the canonical form of a filename.
     *

     * If the specified file name is relative it is resolved
     * with respect to the project's base directory.
     *
     * @param fileName The name of the file to resolve.
     *                 Must not be null.
     *
     * @return the resolved File.
     *
     */
    public File resolveFile(String fileName) {
        return fileUtils.resolveFile(baseDir, fileName);
    }

    /**
     * Translates a path into its native (platform specific) format.
     *

     * This method uses PathTokenizer to separate the input path
     * into its components. This handles DOS style paths in a relatively
     * sensible way. The file separators are then converted to their platform
     * specific versions.
     *
     * @param toProcess The path to be translated.
     *                  May be null.
     *
     * @return the native version of the specified path or
     *         an empty string if the path is null or empty.
     *
     * @see PathTokenizer
     */
    public static String translatePath(String toProcess) {
        if (toProcess == null || toProcess.length() == 0) {
            return "";
        }

        StringBuffer path = new StringBuffer(toProcess.length() + 50);
        PathTokenizer tokenizer = new PathTokenizer(toProcess);
        while (tokenizer.hasMoreTokens()) {
            String pathComponent = tokenizer.nextToken();
            pathComponent = pathComponent.replace('/', File.separatorChar);
            pathComponent = pathComponent.replace('\\', File.separatorChar);
            if (path.length() != 0) {
                path.append(File.pathSeparatorChar);
            }
            path.append(pathComponent);
        }

        return path.toString();
    }

    /**
     * Convenience method to copy a file from a source to a destination.
     * No filtering is performed.
     *
     * @param sourceFile Name of file to copy from.
     *                   Must not be null.
     * @param destFile Name of file to copy to.
     *                 Must not be null.
     *
     * @exception IOException if the copying fails
     *
     * @deprecated
     */
    public void copyFile(String sourceFile, String destFile)
          throws IOException {
        fileUtils.copyFile(sourceFile, destFile);
    }

    /**
     * Convenience method to copy a file from a source to a destination
     * specifying if token filtering should be used.
     *
     * @param sourceFile Name of file to copy from.
     *                   Must not be null.
     * @param destFile Name of file to copy to.
     *                 Must not be null.
     * @param filtering Whether or not token filtering should be used during
     *                  the copy.
     *
     * @exception IOException if the copying fails
     *
     * @deprecated
     */
    public void copyFile(String sourceFile, String destFile, boolean filtering)
        throws IOException {
        fileUtils.copyFile(sourceFile, destFile,
            filtering ? globalFilters : null);
    }

    /**
     * Convenience method to copy a file from a source to a
     * destination specifying if token filtering should be used and if
     * source files may overwrite newer destination files.
     *
     * @param sourceFile Name of file to copy from.
     *                   Must not be null.
     * @param destFile Name of file to copy to.
     *                 Must not be null.
     * @param filtering Whether or not token filtering should be used during
     *                  the copy.
     * @param overwrite Whether or not the destination file should be
     *                  overwritten if it already exists.
     *
     * @exception IOException if the copying fails
     *
     * @deprecated
     */
    public void copyFile(String sourceFile, String destFile, boolean filtering,
                         boolean overwrite) throws IOException {
        fileUtils.copyFile(sourceFile, destFile,
            filtering ? globalFilters : null, overwrite);
    }

    /**
     * Convenience method to copy a file from a source to a
     * destination specifying if token filtering should be used, if
     * source files may overwrite newer destination files, and if the
     * last modified time of the resulting file should be set to
     * that of the source file.
     *
     * @param sourceFile Name of file to copy from.
     *                   Must not be null.
     * @param destFile Name of file to copy to.
     *                 Must not be null.
     * @param filtering Whether or not token filtering should be used during
     *                  the copy.
     * @param overwrite Whether or not the destination file should be
     *                  overwritten if it already exists.
     * @param preserveLastModified Whether or not the last modified time of
     *                             the resulting file should be set to that
     *                             of the source file.
     *
     * @exception IOException if the copying fails
     *
     * @deprecated
     */
    public void copyFile(String sourceFile, String destFile, boolean filtering,
                         boolean overwrite, boolean preserveLastModified)
        throws IOException {
        fileUtils.copyFile(sourceFile, destFile,
            filtering ? globalFilters : null, overwrite, preserveLastModified);
    }

    /**
     * Convenience method to copy a file from a source to a destination.
     * No filtering is performed.
     *
     * @param sourceFile File to copy from.
     *                   Must not be null.
     * @param destFile File to copy to.
     *                 Must not be null.
     *
     * @exception IOException if the copying fails
     *
     * @deprecated
     */
    public void copyFile(File sourceFile, File destFile) throws IOException {
        fileUtils.copyFile(sourceFile, destFile);
    }

    /**
     * Convenience method to copy a file from a source to a destination
     * specifying if token filtering should be used.
     *
     * @param sourceFile File to copy from.
     *                   Must not be null.
     * @param destFile File to copy to.
     *                 Must not be null.
     * @param filtering Whether or not token filtering should be used during
     *                  the copy.
     *
     * @exception IOException if the copying fails
     *
     * @deprecated
     */
    public void copyFile(File sourceFile, File destFile, boolean filtering)
        throws IOException {
        fileUtils.copyFile(sourceFile, destFile,
            filtering ? globalFilters : null);
    }

    /**
     * Convenience method to copy a file from a source to a
     * destination specifying if token filtering should be used and if
     * source files may overwrite newer destination files.
     *
     * @param sourceFile File to copy from.
     *                   Must not be null.
     * @param destFile File to copy to.
     *                 Must not be null.
     * @param filtering Whether or not token filtering should be used during
     *                  the copy.
     * @param overwrite Whether or not the destination file should be
     *                  overwritten if it already exists.
     *
     * @exception IOException if the file cannot be copied.
     *
     * @deprecated
     */
    public void copyFile(File sourceFile, File destFile, boolean filtering,
                         boolean overwrite) throws IOException {
        fileUtils.copyFile(sourceFile, destFile,
            filtering ? globalFilters : null, overwrite);
    }

    /**
     * Convenience method to copy a file from a source to a
     * destination specifying if token filtering should be used, if
     * source files may overwrite newer destination files, and if the
     * last modified time of the resulting file should be set to
     * that of the source file.
     *
     * @param sourceFile File to copy from.
     *                   Must not be null.
     * @param destFile File to copy to.
     *                 Must not be null.
     * @param filtering Whether or not token filtering should be used during
     *                  the copy.
     * @param overwrite Whether or not the destination file should be
     *                  overwritten if it already exists.
     * @param preserveLastModified Whether or not the last modified time of
     *                             the resulting file should be set to that
     *                             of the source file.
     *
     * @exception IOException if the file cannot be copied.
     *
     * @deprecated
     */
    public void copyFile(File sourceFile, File destFile, boolean filtering,
                         boolean overwrite, boolean preserveLastModified)
        throws IOException {
        fileUtils.copyFile(sourceFile, destFile,
            filtering ? globalFilters : null, overwrite, preserveLastModified);
    }

    /**
     * Calls File.setLastModified(long time) on Java above 1.1, and logs
     * a warning on Java 1.1.
     *
     * @param file The file to set the last modified time on.
     *             Must not be null.
     *
     * @param time the required modification time.
     *
     * @deprecated
     *
     * @exception BuildException if the last modified time cannot be set
     *                           despite running on a platform with a version
     *                           above 1.1.
     */
    public void setFileLastModified(File file, long time)
         throws BuildException {
        if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) {
            log("Cannot change the modification time of " + file
                + " in JDK 1.1", Project.MSG_WARN);
            return;
        }
        fileUtils.setFileLastModified(file, time);
        log("Setting modification time for " + file, MSG_VERBOSE);
    }

    /**
     * Returns the boolean equivalent of a string, which is considered
     * true if either "on", "true",
     * or "yes" is found, ignoring case.
     *
     * @param s The string to convert to a boolean value.
     *          Must not be null.
     *
     * @return true if the given string is "on",
     *         "true" or "yes", or
     *         false otherwise.
     */
    public static boolean toBoolean(String s) {
        return (s.equalsIgnoreCase("on") ||
                s.equalsIgnoreCase("true") ||
                s.equalsIgnoreCase("yes"));
    }

    /**
     * Topologically sorts a set of targets.
     *
     * @param root The name of the root target. The sort is created in such
     *             a way that the sequence of Targets up to the root
     *             target is the minimum possible such sequence.
     *             Must not be null.
     * @param targets A map of names to targets (String to Target).
     *                Must not be null.
     * @return a vector of strings with the names of the targets in
     *         sorted order.
     * @exception BuildException if there is a cyclic dependency among the
     *                           targets, or if a named target does not exist.
     */
    public final Vector topoSort(String root, Hashtable targets)
        throws BuildException {
        Vector ret = new Vector();
        Hashtable state = new Hashtable();
        Stack visiting = new Stack();

        tsort(root, targets, state, visiting, ret);
        log("Build sequence for target `" + root + "' is " + ret, MSG_VERBOSE);
        for (Enumeration en = targets.keys(); en.hasMoreElements();) {
            String curTarget = (String) en.nextElement();
            String st = (String) state.get(curTarget);
            if (st == null) {
                tsort(curTarget, targets, state, visiting, ret);
            } else if (st == VISITING) {
                throw new RuntimeException("Unexpected node in visiting state: "
                    + curTarget);
            }
        }
        log("Complete build sequence is " + ret, MSG_VERBOSE);
        return ret;
    }

    /**
     * Performs a single step in a recursive depth-first-search traversal of
     * the target dependency tree.
     *

     * The current target is first set to the "visiting" state, and pushed
     * onto the "visiting" stack.
     *

     * An exception is then thrown if any child of the current node is in the
     * visiting state, as that implies a circular dependency. The exception
     * contains details of the cycle, using elements of the "visiting" stack.
     *

     * If any child has not already been "visited", this method is called
     * recursively on it.
     *

     * The current target is then added to the ordered list of targets. Note
     * that this is performed after the children have been visited in order
     * to get the correct order. The current target is set to the "visited"
     * state.
     *

     * By the time this method returns, the ordered list contains the sequence
     * of targets up to and including the current target.
     *
     * @param root The current target to inspect.
     *             Must not be null.
     * @param targets A mapping from names to targets (String to Target).
     *                Must not be null.
     * @param state   A mapping from target names to states
     *                (String to String).
     *                The states in question are "VISITING" and "VISITED".
     *                Must not be null.
     * @param visiting A stack of targets which are currently being visited.
     *                 Must not be null.
     * @param ret     The list to add target names to. This will end up
     *                containing the complete list of depenencies in
     *                dependency order.
     *                Must not be null.
     *
     * @exception BuildException if a non-existent target is specified or if
     *                           a circular dependency is detected.
     */
    private final void tsort(String root, Hashtable targets,
                             Hashtable state, Stack visiting,
                             Vector ret)
        throws BuildException {
        state.put(root, VISITING);
        visiting.push(root);

        Target target = (Target) targets.get(root);

        if (target == null) {
            StringBuffer sb = new StringBuffer("Target `");
            sb.append(root);
            sb.append("' does not exist in this project. ");
            visiting.pop();
            if (!visiting.empty()) {
                String parent = (String) visiting.peek();
                sb.append("It is used from target `");
                sb.append(parent);
                sb.append("'.");
            }

            throw new BuildException(new String(sb));
        }

        for (Enumeration en = target.getDependencies(); en.hasMoreElements();) {
            String cur = (String) en.nextElement();
            String m = (String) state.get(cur);
            if (m == null) {
                tsort(cur, targets, state, visiting, ret);
            } else if (m == VISITING) {
                throw makeCircularException(cur, visiting);
            }
        }

        String p = (String) visiting.pop();
        if (root != p) {
            throw new RuntimeException("Unexpected internal error: expected to "
                + "pop " + root + " but got " + p);
        }
        state.put(root, VISITED);
        ret.addElement(target);
    }

    /**
     * Builds an appropriate exception detailing a specified circular
     * dependency.
     *
     * @param end The dependency to stop at. Must not be null.
     * @param stk A stack of dependencies. Must not be null.
     *
     * @return a BuildException detailing the specified circular dependency.
     */
    private static BuildException makeCircularException(String end, Stack stk) {
        StringBuffer sb = new StringBuffer("Circular dependency: ");
        sb.append(end);
        String c;
        do {
            c = (String) stk.pop();
            sb.append(" <- ");
            sb.append(c);
        } while (!c.equals(end));
        return new BuildException(new String(sb));
    }

    /**
     * Adds a reference to the project.
     *
     * @param name The name of the reference. Must not be null.
     * @param value The value of the reference. Must not be null.
     */
    public void addReference(String name, Object value) {
        synchronized (references) {
            Object old = references.get(name);
            if (old == value) {
                return;
            }
            if (old != null && !(old instanceof UnknownElement)) {
                log("Overriding previous definition of reference to " + name,
                    MSG_WARN);
            }
            String valueAsString = "";
            try {
                valueAsString = value.toString();
            } catch (Throwable t) {
                log("Caught exception (" + t.getClass().getName() +")"
                    + " while expanding " + name + ": " + t.getMessage(),
                    MSG_WARN);
            }
            log("Adding reference: " + name + " -> " + valueAsString,
                MSG_DEBUG);
            references.put(name, value);
        }
    }

    /**
     * Returns a map of the references in the project (String to Object).
     * The returned hashtable is "live" and so must not be modified.
     *
     * @return a map of the references in the project (String to Object).
     */
    public Hashtable getReferences() {
        return references;
    }

    /**
     * Looks up a reference by its key (ID).
     *
     * @param key The key for the desired reference.
     *            Must not be null.
     *
     * @return the reference with the specified ID, or null if
     *         there is no such reference in the project.
     */
    public Object getReference(String key) {
        return references.get(key);
    }

    /**
     * Returns a description of the type of the given element, with
     * special handling for instances of tasks and data types.
     *

     * This is useful for logging purposes.
     *
     * @param element The element to describe.
     *                Must not be null.
     *
     * @return a description of the element type
     *
     * @since 1.95, Ant 1.5
     */
    public String getElementName(Object element) {
        Hashtable elements = taskClassDefinitions;
        Class elementClass = element.getClass();
        String typeName = "task";
        if (!elements.contains(elementClass)) {
            elements = dataClassDefinitions;
            typeName = "data type";
            if (!elements.contains(elementClass)) {
                elements = null;
            }
        }

        if (elements != null) {
            Enumeration e = elements.keys();
            while (e.hasMoreElements()) {
                String name = (String) e.nextElement();
                Class clazz = (Class) elements.get(name);
                if (elementClass.equals(clazz)) {
                    return "The <" + name + "> " + typeName;
                }
            }
        }

        return "Class " + elementClass.getName();
    }

    /**
     * Sends a "build started" event to the build listeners for this project.
     */
    public void fireBuildStarted() {
        BuildEvent event = new BuildEvent(this);
        Vector listeners = getBuildListeners();
        for (int i = 0; i < listeners.size(); i++) {
            BuildListener listener = (BuildListener) listeners.elementAt(i);
            listener.buildStarted(event);
        }
    }

    /**
     * Sends a "build finished" event to the build listeners for this project.
     * @param exception an exception indicating a reason for a build
     *                  failure. May be null, indicating
     *                  a successful build.
     */
    public void fireBuildFinished(Throwable exception) {
        BuildEvent event = new BuildEvent(this);
        event.setException(exception);
        Vector listeners = getBuildListeners();
        for (int i = 0; i < listeners.size(); i++) {
            BuildListener listener = (BuildListener) listeners.elementAt(i);
            listener.buildFinished(event);
        }
    }

    /**
     * Sends a "target started" event to the build listeners for this project.
     *
     * @param target The target which is starting to build.
     *               Must not be null.
     */
    protected void fireTargetStarted(Target target) {
        BuildEvent event = new BuildEvent(target);
        Vector listeners = getBuildListeners();
        for (int i = 0; i < listeners.size(); i++) {
            BuildListener listener = (BuildListener) listeners.elementAt(i);
            listener.targetStarted(event);
        }
    }

    /**
     * Sends a "target finished" event to the build listeners for this
     * project.
     *
     * @param target    The target which has finished building.
     *                  Must not be null.
     * @param exception an exception indicating a reason for a build
     *                  failure. May be null, indicating
     *                  a successful build.
     */
    protected void fireTargetFinished(Target target, Throwable exception) {
        BuildEvent event = new BuildEvent(target);
        event.setException(exception);
        Vector listeners = getBuildListeners();
        for (int i = 0; i < listeners.size(); i++) {
            BuildListener listener = (BuildListener) listeners.elementAt(i);
            listener.targetFinished(event);
        }
    }

    /**
     * Sends a "task started" event to the build listeners for this project.
     *
     * @param task The target which is starting to execute.
     *               Must not be null.
     */
    protected void fireTaskStarted(Task task) {
        registerThreadTask(Thread.currentThread(), task);
        BuildEvent event = new BuildEvent(task);
        Vector listeners = getBuildListeners();
        for (int i = 0; i < listeners.size(); i++) {
            BuildListener listener = (BuildListener) listeners.elementAt(i);
            listener.taskStarted(event);
        }
    }

    /**
     * Sends a "task finished" event to the build listeners for this
     * project.
     *
     * @param task      The task which has finished executing.
     *                  Must not be null.
     * @param exception an exception indicating a reason for a build
     *                  failure. May be null, indicating
     *                  a successful build.
     */
    protected void fireTaskFinished(Task task, Throwable exception) {
        registerThreadTask(Thread.currentThread(), null);
        System.out.flush();
        System.err.flush();
        BuildEvent event = new BuildEvent(task);
        event.setException(exception);
        Vector listeners = getBuildListeners();
        for (int i = 0; i < listeners.size(); i++) {
            BuildListener listener = (BuildListener) listeners.elementAt(i);
            listener.taskFinished(event);
        }
    }

    /**
     * Sends a "message logged" event to the build listeners for this project.
     *
     * @param event    The event to send. This should be built up with the
     *                 appropriate task/target/project by the caller, so that
     *                 this method can set the message and priority, then send
     *                 the event. Must not be null.
     * @param message  The message to send. Should not be null.
     * @param priority The priority of the message.
     */
    private void fireMessageLoggedEvent(BuildEvent event, String message,
                                        int priority) {
        event.setMessage(message, priority);
        Vector listeners = getBuildListeners();
        synchronized(this) {
            if (loggingMessage) {
                throw new BuildException("Listener attempted to access "
                    + (priority == MSG_ERR ? "System.err" : "System.out")
                    + " - infinite loop terminated");
            }
            loggingMessage = true;
            for (int i = 0; i < listeners.size(); i++) {
                BuildListener listener = (BuildListener) listeners.elementAt(i);
                listener.messageLogged(event);
            }
            loggingMessage = false;
        }
    }

    /**
     * Sends a "message logged" project level event to the build listeners for
     * this project.
     *
     * @param project  The project generating the event.
     *                 Should not be null.
     * @param message  The message to send. Should not be null.
     * @param priority The priority of the message.
     */
    protected void fireMessageLogged(Project project, String message,
                                     int priority) {
        BuildEvent event = new BuildEvent(project);
        fireMessageLoggedEvent(event, message, priority);
    }

    /**
     * Sends a "message logged" target level event to the build listeners for
     * this project.
     *
     * @param target   The target generating the event.
     *                 Must not be null.
     * @param message  The message to send. Should not be null.
     * @param priority The priority of the message.
     */
    protected void fireMessageLogged(Target target, String message,
                                     int priority) {
        BuildEvent event = new BuildEvent(target);
        fireMessageLoggedEvent(event, message, priority);
    }

    /**
     * Sends a "message logged" task level event to the build listeners for
     * this project.
     *
     * @param task     The task generating the event.
     *                 Must not be null.
     * @param message  The message to send. Should not be null.
     * @param priority The priority of the message.
     */
    protected void fireMessageLogged(Task task, String message, int priority) {
        BuildEvent event = new BuildEvent(task);
        fireMessageLoggedEvent(event, message, priority);
    }

    /**
     * Register a task as the current task for a thread.
     * If the task is null, the thread's entry is removed.
     *
     * @param thread the thread on which the task is registered.
     * @param task the task to be registered.
     * @since Ant 1.5
     */
    public synchronized void registerThreadTask(Thread thread, Task task) {
        if (task != null) {
            threadTasks.put(thread, task);
        } else {
            threadTasks.remove(thread);
        }
    }

    /**
     * Get the current task assopciated with a thread, if any
     *
     * @param thread the thread for which the task is required.
     * @return the task which is currently registered for the given thread or
     *         null if no task is registered.
     */
    public Task getThreadTask(Thread thread) {
        return (Task) threadTasks.get(thread);

    public void setInputHandler(InputHandler handler) {
        inputHandler = handler;

    public InputHandler getInputHandler() {
        return inputHandler;

    public void setCoreLoader(ClassLoader coreLoader) {
        this.coreLoader = coreLoader;

    public ClassLoader getCoreLoader() {
        return coreLoader;

    public void addBuildListener(BuildListener listener) {
        listeners.addElement(listener);

    public void removeBuildListener(BuildListener listener) {
        listeners.removeElement(listener);

    public Vector getBuildListeners() {
        return (Vector) listeners.clone();

    public void log(String message) {
        log(message, MSG_INFO);

    public void log(String message, int msgLevel) {
        fireMessageLogged(this, message, msgLevel);

    public void log(Task task, String message, int msgLevel) {
        fireMessageLogged(task, message, msgLevel);

    public FilterSet getGlobalFilterSet() {
        return globalFilterSet;

FUNC_DECL IF PARAM PARAM CALL BINARY_OP RETURN CALL LITERAL_ANCHOR

FUNC_DECL LOOP VAR_DECL PARAM CALL VAR_DECL IF VAR_DECL CALL CALL CALL CALL CALL CALL BREAK_CONTINUE CALL

    public void setDefaultTarget(String defaultTarget) {
        this.defaultTarget = defaultTarget;

    public String getDefaultTarget() {
        return defaultTarget;

    public void setDefault(String defaultTarget) {
        this.defaultTarget = defaultTarget;

    public void setName(String name) {
        setUserProperty("ant.project.name",  name);
        this.name = name;

    public String getName() {
        return name;

    public void setDescription(String description) {
        this.description = description;

    public String getDescription() {
        return description;

FUNC_DECL IF PARAM PARAM CALL BINARY_OP CALL RETURN LITERAL_ANCHOR

    public Hashtable getFilters() {
        return globalFilterSet.getFilterHash();

    public void setBasedir(String baseD) throws BuildException {
        setBaseDir(new File(baseD));

    public static String getJavaVersion() {
        return JavaEnvUtils.getJavaVersion();

    public Hashtable getTaskDefinitions() {
        return taskClassDefinitions;

    public Hashtable getDataTypeDefinitions() {
        return dataClassDefinitions;

    public void addOrReplaceTarget(Target target) {
        addOrReplaceTarget(target.getName(), target);

    public Hashtable getTargets() {
        return targets;

FUNC_DECL PARAM PARAM IF VAR_DECL CALL BINARY_OP LITERAL_ANCHOR CALL ASSIGN CALL CALL

    public File resolveFile(String fileName) {
        return fileUtils.resolveFile(baseDir, fileName);

FUNC_DECL PARAM PARAM PARAM PARAM PARAM CALL COND_EXPR LITERAL_ANCHOR

FUNC_DECL RETURN LOOP VAR_DECL VAR_DECL PARAM PARAM CALL CALL CALL CALL CALL CALL CALL ASSIGN LITERAL_ANCHOR LITERAL_ANCHOR CALL

    public Hashtable getReferences() {
        return references;

    public Object getReference(String key) {
        return references.get(key);

FUNC_DECL VAR_DECL PARAM PARAM PARAM CALL CALL

    public Task getThreadTask(Thread thread) {
        return (Task) threadTasks.get(thread);

    public Project() {
        fileUtils = FileUtils.newFileUtils();
        inputHandler = new DefaultInputHandler();


public class GeneralOptionPane extends AbstractOptionPane
{
	//{{{ checkFileStatus options
	// Check the buffer status when the view got the focus
	public static final int checkFileStatus_focus = 0;
	// Check the file status when the view got the status
	// or when saving or visiting the buffer
	public static final int checkFileStatus_all = 1;
	// Check the file status when visiting or saving <b>any</b> buffer
	public static final int checkFileStatus_operations = 2;
	// Check the file status when visiting or saving the buffer
	public static final int checkFileStatus_focusBuffer = 3;
	// Check the file status when saving the buffer
	public static final int checkFileStatus_none = 4;
	//}}}

	//{{{ Private members
	private JComboBox lineSeparator;
	private JComboBox checkModStatus;
	private JComboBox checkModStatusUpon;
	private JTextField recentFiles;
	private JTextField hypersearchResultsWarning;
	private JCheckBox saveCaret;
	private JCheckBox sortRecent;
	private JCheckBox persistentMarkers;
	private JCheckBox restore;
	private JCheckBox restoreRemote;
	private JCheckBox restoreCLI;
	//}}}

	//{{{ GeneralOptionPane constructor
	public GeneralOptionPane()
	{
		super("general");
	} //}}}

	//{{{ _init() method
	@Override
	protected void _init()
	{

		/* Line separator */
		String[] lineSeps = { jEdit.getProperty("lineSep.unix"),
			jEdit.getProperty("lineSep.windows"),
			jEdit.getProperty("lineSep.mac") };
		lineSeparator = new JComboBox(lineSeps);
		String lineSep = jEdit.getProperty("buffer."+ JEditBuffer.LINESEP,
			System.getProperty("line.separator"));
		if("\n".equals(lineSep))
			lineSeparator.setSelectedIndex(0);
		else if("\r\n".equals(lineSep))
			lineSeparator.setSelectedIndex(1);
		else if("\r".equals(lineSep))
			lineSeparator.setSelectedIndex(2);
		addComponent(jEdit.getProperty("options.general.lineSeparator"),
			lineSeparator);

		/* Check mod status */
		String[] modCheckOptions = {
			jEdit.getProperty("options.general.checkModStatus.nothing"),
			jEdit.getProperty("options.general.checkModStatus.prompt"),
			jEdit.getProperty("options.general.checkModStatus.reload"),
			jEdit.getProperty("options.general.checkModStatus.silentReload")
		};
		checkModStatus = new JComboBox(modCheckOptions);
		if(jEdit.getBooleanProperty("autoReload"))
		{
			if (jEdit.getBooleanProperty("autoReloadDialog"))
				// reload and notify
				checkModStatus.setSelectedIndex(2);
			else	// reload silently
				checkModStatus.setSelectedIndex(3);
		}
		else
		{
			if (jEdit.getBooleanProperty("autoReloadDialog"))
				// prompt
				checkModStatus.setSelectedIndex(1);
			else	// do nothing
				checkModStatus.setSelectedIndex(0);
		}
		addComponent(jEdit.getProperty("options.general.checkModStatus"),
			checkModStatus);

		/* Check mod status upon */
		String[] modCheckUponOptions = {
			jEdit.getProperty("options.general.checkModStatusUpon.focus"),
			jEdit.getProperty("options.general.checkModStatusUpon.all"),
			jEdit.getProperty("options.general.checkModStatusUpon.operations"),
			jEdit.getProperty("options.general.checkModStatusUpon.focusBuffer"),
			jEdit.getProperty("options.general.checkModStatusUpon.none")
		};
		checkModStatusUpon = new JComboBox(modCheckUponOptions);
		checkModStatusUpon.setSelectedIndex(jEdit.getIntegerProperty("checkFileStatus"));
		addComponent(jEdit.getProperty("options.general.checkModStatusUpon"),
			checkModStatusUpon);

		/* Recent file list size */
		recentFiles = new JTextField(jEdit.getProperty(
			"options.general.recentFiles"));
		recentFiles.setText(jEdit.getProperty("recentFiles"));
		addComponent(jEdit.getProperty("options.general.recentFiles"),
			recentFiles);

		/* Sort recent file list */
		sortRecent = new JCheckBox(jEdit.getProperty(
			"options.general.sortRecent"));
		sortRecent.setSelected(jEdit.getBooleanProperty("sortRecent"));
		addComponent(sortRecent);

		/* Save caret positions */
		saveCaret = new JCheckBox(jEdit.getProperty(
			"options.general.saveCaret"));
		saveCaret.setSelected(jEdit.getBooleanProperty("saveCaret"));
		addComponent(saveCaret);

		/* Persistent markers */
		persistentMarkers = new JCheckBox(jEdit.getProperty(
			"options.general.persistentMarkers"));
		persistentMarkers.setSelected(jEdit.getBooleanProperty(
			"persistentMarkers"));
		addComponent(persistentMarkers);

		/* Session management */
		restore = new JCheckBox(jEdit.getProperty(
			"options.general.restore"));

		restore.setSelected(jEdit.getBooleanProperty("restore"));
		restore.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent evt)
			{
				restoreCLI.setEnabled(restore.isSelected());
				restoreRemote.setEnabled(restore.isSelected());
			}
		});

		addComponent(restore);

		restoreRemote = new JCheckBox(jEdit.getProperty(
			"options.general.restore.remote"));
		restoreRemote.setSelected(jEdit.getBooleanProperty("restore.remote", false));
		restoreRemote.setEnabled(restore.isSelected());
		addComponent(restoreRemote);

		restoreCLI = new JCheckBox(jEdit.getProperty(
			"options.general.restore.cli"));
		restoreCLI.setSelected(jEdit.getBooleanProperty("restore.cli"));
		restoreCLI.setEnabled(restore.isSelected());
		addComponent(restoreCLI);

		hypersearchResultsWarning = new JTextField(jEdit.getProperty("hypersearch.maxWarningResults"));
		addComponent(jEdit.getProperty("options.general.hypersearch.maxWarningResults"),
			hypersearchResultsWarning);

	} //}}}

	//{{{ _save() method
	@Override
	protected void _save()
	{

		String lineSep = null;
		switch(lineSeparator.getSelectedIndex())
		{
		case 0:
			lineSep = "\n";
			break;
		case 1:
			lineSep = "\r\n";
			break;
		case 2:
			lineSep = "\r";
			break;
		}
		jEdit.setProperty("buffer."+ JEditBuffer.LINESEP,lineSep);
		switch(checkModStatus.getSelectedIndex())
		{
		case 0:
			jEdit.setBooleanProperty("autoReloadDialog",false);
			jEdit.setBooleanProperty("autoReload",false);
			break;
		case 1:
			jEdit.setBooleanProperty("autoReloadDialog",true);
			jEdit.setBooleanProperty("autoReload",false);
			break;
		case 2:
			jEdit.setBooleanProperty("autoReloadDialog",true);
			jEdit.setBooleanProperty("autoReload",true);
			break;
		case 3:
			jEdit.setBooleanProperty("autoReloadDialog",false);
			jEdit.setBooleanProperty("autoReload",true);
			break;
		}
		jEdit.setIntegerProperty("checkFileStatus",checkModStatusUpon.getSelectedIndex());
		jEdit.setProperty("recentFiles",recentFiles.getText());
		jEdit.setBooleanProperty("sortRecent",sortRecent.isSelected());
		jEdit.setBooleanProperty("saveCaret",saveCaret.isSelected());
		jEdit.setBooleanProperty("persistentMarkers",
			persistentMarkers.isSelected());
		jEdit.setBooleanProperty("restore",restore.isSelected());
		jEdit.setBooleanProperty("restore.cli",restoreCLI.isSelected());
		jEdit.setBooleanProperty("restore.remote", restoreRemote.isSelected());
		try
		{
			jEdit.setIntegerProperty("hypersearch.maxWarningResults", Integer.parseInt(hypersearchResultsWarning.getText()));
		}
		catch (NumberFormatException e)
		{
			Log.log(Log.WARNING, this, "hypersearchResultsWarning: " + hypersearchResultsWarning.getText() + " is not a valid value for this option");