org.apache.tools.ant.taskdefs.Execute

public class Execute {

    private static final int ONE_SECOND = 1000;

    /** Invalid exit code.
     * set to {@link Integer#MAX_VALUE}
     */
    public static final int INVALID = Integer.MAX_VALUE;

    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();

    private String[] cmdl = null;
    private String[] env = null;
    private int exitValue = INVALID;
    private ExecuteStreamHandler streamHandler;
    private ExecuteWatchdog watchdog;
    private File workingDirectory = null;
    private Project project = null;
    private boolean newEnvironment = false;
    private boolean spawn = false;

    /** Controls whether the VM is used to launch commands, where possible. */
    private boolean useVMLauncher = true;

    private static String antWorkingDirectory = System.getProperty("user.dir");
    private static CommandLauncher vmLauncher = null;
    private static CommandLauncher shellLauncher = null;
    private static Vector procEnvironment = null;

    /** Used to destroy processes when the VM exits. */
    private static ProcessDestroyer processDestroyer = new ProcessDestroyer();

    /** Used for replacing env variables */
    private static boolean environmentCaseInSensitive = false;

    /*
     * Builds a command launcher for the OS and JVM we are running under.
     */
    static {
        try {
            if (!Os.isFamily("os/2")) {
                vmLauncher = new Java13CommandLauncher();
            }
        } catch (NoSuchMethodException exc) {
        }
        if (Os.isFamily("mac") && !Os.isFamily("unix")) {
            shellLauncher = new MacCommandLauncher(new CommandLauncher());
        } else if (Os.isFamily("os/2")) {
            shellLauncher = new OS2CommandLauncher(new CommandLauncher());
        } else if (Os.isFamily("windows")) {
            environmentCaseInSensitive = true;
            CommandLauncher baseLauncher = new CommandLauncher();

            if (!Os.isFamily("win9x")) {
                shellLauncher = new WinNTCommandLauncher(baseLauncher);
            } else {
                shellLauncher
                    = new ScriptCommandLauncher("bin/antRun.bat", baseLauncher);
            }
        } else if (Os.isFamily("netware")) {

            CommandLauncher baseLauncher = new CommandLauncher();

            shellLauncher
                = new PerlScriptCommandLauncher("bin/antRun.pl", baseLauncher);
        } else if (Os.isFamily("openvms")) {
            try {
                shellLauncher = new VmsCommandLauncher();
            } catch (NoSuchMethodException exc) {
            }
        } else {
            shellLauncher = new ScriptCommandLauncher("bin/antRun",
                new CommandLauncher());
        }
    }

    /**
     * Set whether or not you want the process to be spawned.
     * Default is not spawned.
     *
     * @param spawn if true you do not want Ant
     *              to wait for the end of the process.
     *
     * @since Ant 1.6
     */
    public void setSpawn(boolean spawn) {
        this.spawn = spawn;
    }

    /**
     * Find the list of environment variables for this process.
     *
     * @return a vector containing the environment variables.
     * The vector elements are strings formatted like variable = value.
     */
    public static synchronized Vector getProcEnvironment() {
        if (procEnvironment != null) {
            return procEnvironment;
        }
        procEnvironment = new Vector();
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            Execute exe = new Execute(new PumpStreamHandler(out));
            exe.setCommandline(getProcEnvCommand());
            exe.setNewenvironment(true);
            int retval = exe.execute();
            if (retval != 0) {
            }
            BufferedReader in =
                new BufferedReader(new StringReader(toString(out)));

            if (Os.isFamily("openvms")) {
                procEnvironment = addVMSLogicals(procEnvironment, in);
                return procEnvironment;
            }
            String var = null;
            String line, lineSep = StringUtils.LINE_SEP;
            while ((line = in.readLine()) != null) {
                if (line.indexOf('=') == -1) {
                    if (var == null) {
                        var = lineSep + line;
                    } else {
                        var += lineSep + line;
                    }
                } else {
                    if (var != null) {
                        procEnvironment.addElement(var);
                    }
                    var = line;
                }
            }
            if (var != null) {
                procEnvironment.addElement(var);
            }
        } catch (java.io.IOException exc) {
            exc.printStackTrace();
        }
        return procEnvironment;
    }

    /**
     * This is the operation to get our environment.
     * It is a notorious troublespot pre-Java1.5, and should be approached
     * with extreme caution.
     * @return
     */
    private static String[] getProcEnvCommand() {
        if (Os.isFamily("os/2")) {
            return new String[] {"cmd", "/c", "set" };
        } else if (Os.isFamily("windows")) {
            if (Os.isFamily("win9x")) {
                return new String[] {"command.com", "/c", "set" };
            } else {
                return new String[] {"cmd", "/c", "set" };
            }
        } else if (Os.isFamily("z/os") || Os.isFamily("unix")) {

            String[] cmd = new String[1];
            if (new File("/bin/env").canRead()) {
                cmd[0] = "/bin/env";
            } else if (new File("/usr/bin/env").canRead()) {
                cmd[0] = "/usr/bin/env";
            } else {
                cmd[0] = "env";
            }
            return cmd;
        } else if (Os.isFamily("netware") || Os.isFamily("os/400")) {
            return new String[] {"env"};
        } else if (Os.isFamily("openvms")) {
            return new String[] {"show", "logical"};
        } else {
            return null;
        }
    }

    /**
     * ByteArrayOutputStream#toString doesn't seem to work reliably on
     * OS/390, at least not the way we use it in the execution
     * context.
     *
     * @param bos the output stream that one wants to read.
     * @return the output stream as a string, read with
     * special encodings in the case of z/os and os/400.
     *
     * @since Ant 1.5
     */
    public static String toString(ByteArrayOutputStream bos) {
        if (Os.isFamily("z/os")) {
            try {
                return bos.toString("Cp1047");
            } catch (java.io.UnsupportedEncodingException e) {
            }
        } else if (Os.isFamily("os/400")) {
            try {
                return bos.toString("Cp500");
            } catch (java.io.UnsupportedEncodingException e) {
            }
        }
        return bos.toString();
    }

    /**
     * Creates a new execute object using PumpStreamHandler for
     * stream handling.
     */
    public Execute() {
        this(new PumpStreamHandler(), null);
    }

    /**
     * Creates a new execute object.
     *
     * @param streamHandler the stream handler used to handle the input and
     *        output streams of the subprocess.
     */
    public Execute(ExecuteStreamHandler streamHandler) {
        this(streamHandler, null);
    }

    /**
     * Creates a new execute object.
     *
     * @param streamHandler the stream handler used to handle the input and
     *        output streams of the subprocess.
     * @param watchdog a watchdog for the subprocess or null to
     *        to disable a timeout for the subprocess.
     */
    public Execute(ExecuteStreamHandler streamHandler,
                   ExecuteWatchdog watchdog) {
        setStreamHandler(streamHandler);
        this.watchdog = watchdog;
        if (Os.isFamily("openvms")) {
            useVMLauncher = false;
        }
    }

    /**
     * Set the stream handler to use.
     * @param streamHandler ExecuteStreamHandler.
     * @since Ant 1.6
     */
    public void setStreamHandler(ExecuteStreamHandler streamHandler) {
        this.streamHandler = streamHandler;
    }

    /**
     * Returns the commandline used to create a subprocess.
     *
     * @return the commandline used to create a subprocess.
     */
    public String[] getCommandline() {
        return cmdl;
    }

    /**
     * Sets the commandline of the subprocess to launch.
     *
     * @param commandline the commandline of the subprocess to launch.
     */
    public void setCommandline(String[] commandline) {
        cmdl = commandline;
    }

    /**
     * Set whether to propagate the default environment or not.
     *
     * @param newenv whether to propagate the process environment.
     */
    public void setNewenvironment(boolean newenv) {
        newEnvironment = newenv;
    }

    /**
     * Returns the environment used to create a subprocess.
     *
     * @return the environment used to create a subprocess.
     */
    public String[] getEnvironment() {
        return (env == null || newEnvironment)
            ? env : patchEnvironment();
    }

    /**
     * Sets the environment variables for the subprocess to launch.
     *
     * @param env array of Strings, each element of which has
     * an environment variable settings in format key=value.
     */
    public void setEnvironment(String[] env) {
        this.env = env;
    }

    /**
     * Sets the working directory of the process to execute.
     *
     *
This is emulated using the antRun scripts unless the OS is
     * Windows NT in which case a cmd.exe is spawned,
     * or MRJ and setting user.dir works, or JDK 1.3 and there is
     * official support in java.lang.Runtime.
     *
     * @param wd the working directory of the process.
     */
    public void setWorkingDirectory(File wd) {
        workingDirectory =
            (wd == null || wd.getAbsolutePath().equals(antWorkingDirectory))
            ? null : wd;
    }

    /**
     * Return the working directory.
     * @return the directory as a File.
     * @since Ant 1.7
     */
    public File getWorkingDirectory() {
        return workingDirectory == null ? new File(antWorkingDirectory)
                                        : workingDirectory;
    }

    /**
     * Set the name of the antRun script using the project's value.
     *
     * @param project the current project.
     *
     * @throws BuildException not clear when it is going to throw an exception, but
     * it is the method's signature.
     */
    public void setAntRun(Project project) throws BuildException {
        this.project = project;
    }

    /**
     * Launch this execution through the VM, where possible, rather than through
     * the OS's shell. In some cases and operating systems using the shell will
     * allow the shell to perform additional processing such as associating an
     * executable with a script, etc.
     *
     * @param useVMLauncher true if exec should launch through the VM,
     *                   false if the shell should be used to launch the
     *                   command.
     */
    public void setVMLauncher(boolean useVMLauncher) {
        this.useVMLauncher = useVMLauncher;
    }

    /**
     * Creates a process that runs a command.
     *
     * @param project the Project, only used for logging purposes, may be null.
     * @param command the command to run.
     * @param env the environment for the command.
     * @param dir the working directory for the command.
     * @param useVM use the built-in exec command for JDK 1.3 if available.
     * @return the process started.
     * @throws IOException forwarded from the particular launcher used.
     *
     * @since Ant 1.5
     */
    public static Process launch(Project project, String[] command,
                                 String[] env, File dir, boolean useVM)
        throws IOException {
        if (dir != null && !dir.exists()) {
            throw new BuildException(dir + " doesn't exist.");
        }
        CommandLauncher launcher
            = ((useVM && vmLauncher != null) ? vmLauncher : shellLauncher);
        return launcher.exec(project, command, env, dir);
    }

    /**
     * Runs a process defined by the command line and returns its exit status.
     *
     * @return the exit status of the subprocess or INVALID.
     * @exception java.io.IOException The exception is thrown, if launching
     *            of the subprocess failed.
     */
    public int execute() throws IOException {
        if (workingDirectory != null && !workingDirectory.exists()) {
            throw new BuildException(workingDirectory + " doesn't exist.");
        }
        final Process process = launch(project, getCommandline(),
                                       getEnvironment(), workingDirectory,
                                       useVMLauncher);
        try {
            streamHandler.setProcessInputStream(process.getOutputStream());
            streamHandler.setProcessOutputStream(process.getInputStream());
            streamHandler.setProcessErrorStream(process.getErrorStream());
        } catch (IOException e) {
            process.destroy();
            throw e;
        }
        streamHandler.start();

        try {
            processDestroyer.add(process);

            if (watchdog != null) {
                watchdog.start(process);
            }
            waitFor(process);

            if (watchdog != null) {
                watchdog.stop();
            }
            streamHandler.stop();
            closeStreams(process);

            if (watchdog != null) {
                watchdog.checkException();
            }
            return getExitValue();
        } catch (ThreadDeath t) {
            process.destroy();
            throw t;
        } finally {
            processDestroyer.remove(process);
        }
    }

    /**
     * Starts a process defined by the command line.
     * Ant will not wait for this process, nor log its output.
     *
     * @throws java.io.IOException The exception is thrown, if launching
     *            of the subprocess failed.
     * @since Ant 1.6
     */
    public void spawn() throws IOException {
        if (workingDirectory != null && !workingDirectory.exists()) {
            throw new BuildException(workingDirectory + " doesn't exist.");
        }
        final Process process = launch(project, getCommandline(),
                                       getEnvironment(), workingDirectory,
                                       useVMLauncher);
        if (Os.isFamily("windows")) {
            try {
                Thread.sleep(ONE_SECOND);
            } catch (InterruptedException e) {
                project.log("interruption in the sleep after having spawned a"
                            + " process", Project.MSG_VERBOSE);
            }
        }
        OutputStream dummyOut = new OutputStream() {
            public void write(int b) throws IOException {
            }
        };

        ExecuteStreamHandler handler = new PumpStreamHandler(dummyOut);
        handler.setProcessErrorStream(process.getErrorStream());
        handler.setProcessOutputStream(process.getInputStream());
        handler.start();
        process.getOutputStream().close();

        project.log("spawned process " + process.toString(),
                    Project.MSG_VERBOSE);
    }

    /**
     * Wait for a given process.
     *
     * @param process the process one wants to wait for.
     */
    protected void waitFor(Process process) {
        try {
            process.waitFor();
            setExitValue(process.exitValue());
        } catch (InterruptedException e) {
            process.destroy();
        }
    }

    /**
     * Set the exit value.
     *
     * @param value exit value of the process.
     */
    protected void setExitValue(int value) {
        exitValue = value;
    }

    /**
     * Query the exit value of the process.
     * @return the exit value or Execute.INVALID if no exit value has
     * been received.
     */
    public int getExitValue() {
        return exitValue;
    }

    /**
     * Checks whether exitValue signals a failure on the current
     * system (OS specific).
     *
     *
Note that this method relies on the conventions of
     * the OS, it will return false results if the application you are
     * running doesn't follow these conventions.  One notable
     * exception is the Java VM provided by HP for OpenVMS - it will
     * return 0 if successful (like on any other platform), but this
     * signals a failure on OpenVMS.  So if you execute a new Java VM
     * on OpenVMS, you cannot trust this method.

     *
     * @param exitValue the exit value (return code) to be checked.
     * @return true if exitValue signals a failure.
     */
    public static boolean isFailure(int exitValue) {
        return Os.isFamily("openvms")
            ? (exitValue % 2 == 0) : (exitValue != 0);
    }

    /**
     * Did this execute return in a failure.
     * @see #isFailure(int)
     * @return true if and only if the exit code is interpreted as a failure
     * @since Ant1.7
     */
    public boolean isFailure() {
        return isFailure(getExitValue());
    }

    /**
     * Test for an untimely death of the process.
     * @return true if a watchdog had to kill the process.
     * @since Ant 1.5
     */
    public boolean killedProcess() {
        return watchdog != null && watchdog.killedProcess();
    }

    /**
     * Patch the current environment with the new values from the user.
     * @return the patched environment.
     */
    private String[] patchEnvironment() {
        if (Os.isFamily("openvms")) {
            return env;
        }
        Vector osEnv = (Vector) getProcEnvironment().clone();
        for (int i = 0; i < env.length; i++) {
            String keyValue = env[i];
            String key = keyValue.substring(0, keyValue.indexOf('=') + 1);
            if (environmentCaseInSensitive) {
                key = key.toLowerCase();
            }
            int size = osEnv.size();
            for (int j = 0; j < size; j++) {
                String osEnvItem = (String) osEnv.elementAt(j);
                String convertedItem = environmentCaseInSensitive
                    ? osEnvItem.toLowerCase() : osEnvItem;
                if (convertedItem.startsWith(key)) {
                    osEnv.removeElementAt(j);
                    if (environmentCaseInSensitive) {
                        keyValue = osEnvItem.substring(0, key.length())
                            + keyValue.substring(key.length());
                    }
                    break;
                }
            }
            osEnv.addElement(keyValue);
        }
        return (String[]) (osEnv.toArray(new String[osEnv.size()]));
    }

    /**
     * A utility method that runs an external command.  Writes the output and
     * error streams of the command to the project log.
     *
     * @param task      The task that the command is part of.  Used for logging
     * @param cmdline   The command to execute.
     *
     * @throws BuildException if the command does not exit successfully.
     */
    public static void runCommand(Task task, String[] cmdline)
        throws BuildException {
        try {
            task.log(Commandline.describeCommand(cmdline),
                     Project.MSG_VERBOSE);
            Execute exe = new Execute(
                new LogStreamHandler(task, Project.MSG_INFO, Project.MSG_ERR));
            exe.setAntRun(task.getProject());
            exe.setCommandline(cmdline);
            int retval = exe.execute();
            if (isFailure(retval)) {
                throw new BuildException(cmdline[0]
                    + " failed with return code " + retval, task.getLocation());
            }
        } catch (java.io.IOException exc) {
            throw new BuildException("Could not launch " + cmdline[0] + ": "
                + exc, task.getLocation());
        }
    }

    /**
     * Close the streams belonging to the given Process.
     * @param process   the Process.
     */
    public static void closeStreams(Process process) {
        FileUtils.close(process.getInputStream());
        FileUtils.close(process.getOutputStream());
        FileUtils.close(process.getErrorStream());
    }

    /**
     * This method is VMS specific and used by getProcEnvironment().
     *
     * Parses VMS logicals from in and adds them to
     * environment.  in is expected to be the
     * output of "SHOW LOGICAL".  The method takes care of parsing the output
     * correctly as well as making sure that a logical defined in multiple
     * tables only gets added from the highest order table.  Logicals with
     * multiple equivalence names are mapped to a variable with multiple
     * values separated by a comma (,).
     */
    private static Vector addVMSLogicals(Vector environment, BufferedReader in)
        throws IOException {
        HashMap logicals = new HashMap();
        String logName = null, logValue = null, newLogName;
        String line = null;
        while ((line = in.readLine()) != null) {
            if (line.startsWith("\t=")) {
                if (logName != null) {
                    logValue += "," + line.substring(4, line.length() - 1);
                }
            } else if (line.startsWith("  \"")) {
                if (logName != null) {
                    logicals.put(logName, logValue);
                }
                int eqIndex = line.indexOf('=');
                newLogName = line.substring(3, eqIndex - 2);
                if (logicals.containsKey(newLogName)) {
                    logName = null;
                } else {
                    logName = newLogName;
                    logValue = line.substring(eqIndex + 3, line.length() - 1);
                }
            }
        }
        if (logName != null) {
            logicals.put(logName, logValue);
        }
        for (Iterator i = logicals.keySet().iterator(); i.hasNext();) {
            String logical = (String) i.next();
            environment.add(logical + "=" + logicals.get(logical));
        }
        return environment;
    }

    /**
     * A command launcher for a particular JVM/OS platform.  This class is
     * a general purpose command launcher which can only launch commands in
     * the current working directory.
     */
    private static class CommandLauncher {
        /**
         * Launches the given command in a new process.
         *
         * @param project       The project that the command is part of.
         * @param cmd           The command to execute.
         * @param env           The environment for the new process.  If null,
         *                      the environment of the current process is used.
         * @return the created Process.
         * @throws IOException if attempting to run a command in a
         * specific directory.
         */
        public Process exec(Project project, String[] cmd, String[] env)
             throws IOException {
            if (project != null) {
                project.log("Execute:CommandLauncher: "
                    + Commandline.describeCommand(cmd), Project.MSG_DEBUG);
            }
            return Runtime.getRuntime().exec(cmd, env);
        }

        /**
         * Launches the given command in a new process, in the given working
         * directory.
         *
         * @param project       The project that the command is part of.
         * @param cmd           The command to execute.
         * @param env           The environment for the new process.  If null,
         *                      the environment of the current process is used.
         * @param workingDir    The directory to start the command in.  If null,
         *                      the current directory is used.
         * @return the created Process.
         * @throws IOException  if trying to change directory.
         */
        public Process exec(Project project, String[] cmd, String[] env,
                            File workingDir) throws IOException {
            if (workingDir == null) {
                return exec(project, cmd, env);
            }
            throw new IOException("Cannot execute a process in different "
                + "directory under this JVM");
        }
    }

    /**
     * A command launcher for JDK/JRE 1.3 (and higher).  Uses the built-in
     * Runtime.exec() command.
     */
    private static class Java13CommandLauncher extends CommandLauncher {
        private Method myExecWithCWD;

        public Java13CommandLauncher() throws NoSuchMethodException {
            myExecWithCWD = Runtime.class.getMethod("exec",
                new Class[] {String[].class, String[].class, File.class});
        }

        /**
         * Launches the given command in a new process, in the given working
         * directory.
         * @param project the Ant project.
         * @param cmd the command line to execute as an array of strings.
         * @param env the environment to set as an array of strings.
         * @param workingDir the working directory where the command
         * should run.
         * @return the created Process.
         * @throws IOException probably forwarded from Runtime#exec.
         */
        public Process exec(Project project, String[] cmd, String[] env,
                            File workingDir) throws IOException {
            try {
                if (project != null) {
                    project.log("Execute:Java13CommandLauncher: "
                        + Commandline.describeCommand(cmd), Project.MSG_DEBUG);
                }
                return (Process) myExecWithCWD.invoke(Runtime.getRuntime(),
                   /* the arguments: */ new Object[] {cmd, env, workingDir});
            } catch (InvocationTargetException exc) {
                Throwable realexc = exc.getTargetException();
                if (realexc instanceof ThreadDeath) {
                    throw (ThreadDeath) realexc;
                } else if (realexc instanceof IOException) {
                    throw (IOException) realexc;
                } else {
                    throw new BuildException("Unable to execute command",
                                             realexc);
                }
            } catch (Exception exc) {
                throw new BuildException("Unable to execute command", exc);
            }
        }
    }

    /**
     * A command launcher that proxies another command launcher.
     *
     * Sub-classes override exec(args, env, workdir).
     */
    private static class CommandLauncherProxy extends CommandLauncher {
        private CommandLauncher myLauncher;

        CommandLauncherProxy(CommandLauncher launcher) {
            myLauncher = launcher;
        }

        /**
         * Launches the given command in a new process.  Delegates this
         * method to the proxied launcher.
         * @param project the Ant project.
         * @param cmd the command line to execute as an array of strings.
         * @param env the environment to set as an array of strings.
         * @return the created Process.
         * @throws IOException forwarded from the exec method of the
         * command launcher.
         */
        public Process exec(Project project, String[] cmd, String[] env)
            throws IOException {
            return myLauncher.exec(project, cmd, env);
        }
    }

    /**
     * A command launcher for OS/2 that uses 'cmd.exe' when launching
     * commands in directories other than the current working
     * directory.
     *
     *
Unlike Windows NT and friends, OS/2's cd doesn't support the
     * /d switch to change drives and directories in one go.

     */
    private static class OS2CommandLauncher extends CommandLauncherProxy {
        OS2CommandLauncher(CommandLauncher launcher) {
            super(launcher);
        }

        /**
         * Launches the given command in a new process, in the given working
         * directory.
         * @param project the Ant project.
         * @param cmd the command line to execute as an array of strings.
         * @param env the environment to set as an array of strings.
         * @param workingDir working directory where the command should run.
         * @return the created Process.
         * @throws IOException forwarded from the exec method of the
         * command launcher.
         */
        public Process exec(Project project, String[] cmd, String[] env,
                            File workingDir) throws IOException {
            File commandDir = workingDir;
            if (workingDir == null) {
                if (project != null) {
                    commandDir = project.getBaseDir();
                } else {
                    return exec(project, cmd, env);
                }
            }
            final int preCmdLength = 7;
            final String cmdDir = commandDir.getAbsolutePath();
            String[] newcmd = new String[cmd.length + preCmdLength];
            newcmd[0] = "cmd";
            newcmd[1] = "/c";
            newcmd[2] = cmdDir.substring(0, 2);
            newcmd[3] = "&&";
            newcmd[4] = "cd";
            newcmd[5] = cmdDir.substring(2);
            newcmd[6] = "&&";
            System.arraycopy(cmd, 0, newcmd, preCmdLength, cmd.length);

            return exec(project, newcmd, env);
        }
    }

    /**
     * A command launcher for Windows XP/2000/NT that uses 'cmd.exe' when
     * launching commands in directories other than the current working
     * directory.
     */
    private static class WinNTCommandLauncher extends CommandLauncherProxy {
        WinNTCommandLauncher(CommandLauncher launcher) {
            super(launcher);
        }

        /**
         * Launches the given command in a new process, in the given working
         * directory.
         * @param project the Ant project.
         * @param cmd the command line to execute as an array of strings.
         * @param env the environment to set as an array of strings.
         * @param workingDir working directory where the command should run.
         * @return the created Process.
         * @throws IOException forwarded from the exec method of the
         * command launcher.
         */
        public Process exec(Project project, String[] cmd, String[] env,
                            File workingDir) throws IOException {
            File commandDir = workingDir;
            if (workingDir == null) {
                if (project != null) {
                    commandDir = project.getBaseDir();
                } else {
                    return exec(project, cmd, env);
                }
            }
            final int preCmdLength = 6;
            String[] newcmd = new String[cmd.length + preCmdLength];
            newcmd[0] = "cmd";
            newcmd[1] = "/c";
            newcmd[2] = "cd";
            newcmd[3] = "/d";
            newcmd[4] = commandDir.getAbsolutePath();
            newcmd[5] = "&&";
            System.arraycopy(cmd, 0, newcmd, preCmdLength, cmd.length);

            return exec(project, newcmd, env);
        }
    }

    /**
     * A command launcher for Mac that uses a dodgy mechanism to change
     * working directory before launching commands.
     */
    private static class MacCommandLauncher extends CommandLauncherProxy {
        MacCommandLauncher(CommandLauncher launcher) {
            super(launcher);
        }

        /**
         * Launches the given command in a new process, in the given working
         * directory.
         * @param project the Ant project.
         * @param cmd the command line to execute as an array of strings.
         * @param env the environment to set as an array of strings.
         * @param workingDir working directory where the command should run.
         * @return the created Process.
         * @throws IOException forwarded from the exec method of the
         * command launcher.
         */
        public Process exec(Project project, String[] cmd, String[] env,
                            File workingDir) throws IOException {
            if (workingDir == null) {
                return exec(project, cmd, env);
            }
            System.getProperties().put("user.dir", workingDir.getAbsolutePath());
            try {
                return exec(project, cmd, env);
            } finally {
                System.getProperties().put("user.dir", antWorkingDirectory);
            }
        }
    }

    /**
     * A command launcher that uses an auxiliary script to launch commands
     * in directories other than the current working directory.
     */
    private static class ScriptCommandLauncher extends CommandLauncherProxy {
        ScriptCommandLauncher(String script, CommandLauncher launcher) {
            super(launcher);
            myScript = script;
        }

        /**
         * Launches the given command in a new process, in the given working
         * directory.
         * @param project the Ant project.
         * @param cmd the command line to execute as an array of strings.
         * @param env the environment to set as an array of strings.
         * @param workingDir working directory where the command should run.
         * @return the created Process.
         * @throws IOException forwarded from the exec method of the
         * command launcher.
         */
        public Process exec(Project project, String[] cmd, String[] env,
                            File workingDir) throws IOException {
            if (project == null) {
                if (workingDir == null) {
                    return exec(project, cmd, env);
                }
                throw new IOException("Cannot locate antRun script: "
                    + "No project provided");
            }
            String antHome = project.getProperty(MagicNames.ANT_HOME);
            if (antHome == null) {
                throw new IOException("Cannot locate antRun script: "
                    + "Property '" + MagicNames.ANT_HOME + "' not found");
            }
            String antRun =
                FILE_UTILS.resolveFile(project.getBaseDir(),
                        antHome + File.separator + myScript).toString();

            File commandDir = workingDir;
            if (workingDir == null) {
                commandDir = project.getBaseDir();
            }
            String[] newcmd = new String[cmd.length + 2];
            newcmd[0] = antRun;
            newcmd[1] = commandDir.getAbsolutePath();
            System.arraycopy(cmd, 0, newcmd, 2, cmd.length);

            return exec(project, newcmd, env);
        }

        private String myScript;
    }

    /**
     * A command launcher that uses an auxiliary perl script to launch commands
     * in directories other than the current working directory.
     */
    private static class PerlScriptCommandLauncher
        extends CommandLauncherProxy {
        private String myScript;

        PerlScriptCommandLauncher(String script, CommandLauncher launcher) {
            super(launcher);
            myScript = script;
        }

        /**
         * Launches the given command in a new process, in the given working
         * directory.
         * @param project the Ant project.
         * @param cmd the command line to execute as an array of strings.
         * @param env the environment to set as an array of strings.
         * @param workingDir working directory where the command should run.
         * @return the created Process.
         * @throws IOException forwarded from the exec method of the
         * command launcher.
         */
        public Process exec(Project project, String[] cmd, String[] env,
                            File workingDir) throws IOException {
            if (project == null) {
                if (workingDir == null) {
                    return exec(project, cmd, env);
                }
                throw new IOException("Cannot locate antRun script: "
                    + "No project provided");
            }
            String antHome = project.getProperty(MagicNames.ANT_HOME);
            if (antHome == null) {
                throw new IOException("Cannot locate antRun script: "
                    + "Property '" + MagicNames.ANT_HOME + "' not found");
            }
            String antRun =
                FILE_UTILS.resolveFile(project.getBaseDir(),
                        antHome + File.separator + myScript).toString();

            File commandDir = workingDir;
            if (workingDir == null) {
                commandDir = project.getBaseDir();
            }
            String[] newcmd = new String[cmd.length + 3];
            newcmd[0] = "perl";
            newcmd[1] = antRun;
            newcmd[2] = commandDir.getAbsolutePath();
            System.arraycopy(cmd, 0, newcmd, 3, cmd.length);

            return exec(project, newcmd, env);
        }
    }

    /**
     * A command launcher for VMS that writes the command to a temporary DCL
     * script before launching commands.  This is due to limitations of both
     * the DCL interpreter and the Java VM implementation.
     */
    private static class VmsCommandLauncher extends Java13CommandLauncher {

        public VmsCommandLauncher() throws NoSuchMethodException {
            super();
        }

        /**
         * Launches the given command in a new process.
         * @param project the Ant project.
         * @param cmd the command line to execute as an array of strings.
         * @param env the environment to set as an array of strings.
         * @return the created Process.
         * @throws IOException forwarded from the exec method of the
         * command launcher.
         */
        public Process exec(Project project, String[] cmd, String[] env)
            throws IOException {
            File cmdFile = createCommandFile(cmd, env);
            Process p
                = super.exec(project, new String[] {cmdFile.getPath()}, env);
            deleteAfter(cmdFile, p);
            return p;
        }

        /**
         * Launches the given command in a new process, in the given working
         * directory.  Note that under Java 1.3.1, 1.4.0 and 1.4.1 on VMS this
         * method only works if workingDir is null or the logical
         * JAVA$FORK_SUPPORT_CHDIR needs to be set to TRUE.
         * @param project the Ant project.
         * @param cmd the command line to execute as an array of strings.
         * @param env the environment to set as an array of strings.
         * @param workingDir working directory where the command should run.
         * @return the created Process.
         * @throws IOException forwarded from the exec method of the
         * command launcher.
         */
        public Process exec(Project project, String[] cmd, String[] env,
                            File workingDir) throws IOException {
            File cmdFile = createCommandFile(cmd, env);
            Process p = super.exec(project, new String[] {cmdFile.getPath()},
                                   env, workingDir);
            deleteAfter(cmdFile, p);
            return p;
        }

        /*
         * Writes the command into a temporary DCL script and returns the
         * corresponding File object.  The script will be deleted on exit.
         * @param cmd the command line to execute as an array of strings.
         * @param env the environment to set as an array of strings.
         * @return the command File.
         * @throws IOException if errors are encountered creating the file.
         */
        private File createCommandFile(String[] cmd, String[] env)
            throws IOException {
            File script = FILE_UTILS.createTempFile("ANT", ".COM", null, true, true);
            PrintWriter out = null;
            try {
                out = new PrintWriter(new FileWriter(script));

                if (env != null) {
                    int eqIndex;
                    for (int i = 0; i < env.length; i++) {
                        eqIndex = env[i].indexOf('=');
                        if (eqIndex != -1) {
                            out.print("$ DEFINE/NOLOG ");
                            out.print(env[i].substring(0, eqIndex));
                            out.print(" \"");
                            out.print(env[i].substring(eqIndex + 1));
                            out.println('\"');
                        }
                    }
                }
                out.print("$ " + cmd[0]);
                for (int i = 1; i < cmd.length; i++) {
                    out.println(" -");
                    out.print(cmd[i]);
                }
            } finally {
                if (out != null) {
                    out.close();
                }
            }
            return script;
        }

        private void deleteAfter(final File f, final Process p) {
            new Thread() {
                public void run() {
                    try {
                        p.waitFor();
                    } catch (InterruptedException e) {
                    }
                    FileUtils.delete(f);
                }
            }
            .start();

FUNC_DECL RETURN IF PARAM CALL IF CALL CALL TRY LITERAL_ANCHOR TRY LITERAL_ANCHOR CATCH RETURN CATCH RETURN CALL CALL LITERAL_ANCHOR LITERAL_ANCHOR

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

FUNC_DECL TRY PARAM CATCH CALL CALL CALL CALL

FUNC_DECL PARAM CALL CALL CALL CALL CALL CALL

FUNC_DECL IF PARAM PARAM CALL ASSIGN CALL LITERAL_ANCHOR ASSIGN LITERAL_ANCHOR


public class SerializerSwitcher
{

  /**
   * Switch to HTML serializer if element is HTML
   *
   *
   * @param transformer Non-null transformer instance
   * @param ns Namespace URI of the element
   * @param localName Local part of name of element
   *
   * @throws TransformerException
   */
  public static void switchSerializerIfHTML(
          TransformerImpl transformer, String ns, String localName)
            throws TransformerException
  {

    if (null == transformer)
      return;

    if (((null == ns) || (ns.length() == 0))
            && localName.equalsIgnoreCase("html"))
    {
      if (null != transformer.getOutputPropertyNoDefault(OutputKeys.METHOD))
        return;

      Properties prevProperties = transformer.getOutputFormat().getProperties();

      OutputProperties htmlOutputProperties = new OutputProperties(Method.HTML);

      htmlOutputProperties.copyFrom(prevProperties, true);
      Properties htmlProperties = htmlOutputProperties.getProperties();

      try
      {
        Serializer oldSerializer = null;

        if (null != oldSerializer)
        {
          Serializer serializer =
            SerializerFactory.getSerializer(htmlProperties);

          Writer writer = oldSerializer.getWriter();

          if (null != writer)
            serializer.setWriter(writer);
          else
          {
            OutputStream os = oldSerializer.getOutputStream();

            if (null != os)
              serializer.setOutputStream(os);
          }

          ContentHandler ch = serializer.asContentHandler();

          transformer.setContentHandler(ch);
        }
      }
      catch (java.io.IOException e)
      {
        throw new TransformerException(e);
      }
    }
  }

  /**
   * Get the value of a property, without using the default properties.  This
   * can be used to test if a property has been explicitly set by the stylesheet
   * or user.
   *
   * @param name The property name, which is a fully-qualified URI.
   *
   * @return The value of the property, or null if not found.
   *
   * @throws IllegalArgumentException If the property is not supported,
   * and is not namespaced.
   */
  private static String getOutputPropertyNoDefault(String qnameString, Properties props)
    throws IllegalArgumentException
  {
    String value = (String)props.get(qnameString);

    return value;
  }

  /**
   * Switch to HTML serializer if element is HTML
   *
   *
   * @param ns Namespace URI of the element
   * @param localName Local part of name of element
   *
   * @throws TransformerException
   * @return new contentHandler.
   */
  public static Serializer switchSerializerIfHTML(
          String ns, String localName, Properties props, Serializer oldSerializer)
            throws TransformerException
  {
    Serializer newSerializer = oldSerializer;

    if (((null == ns) || (ns.length() == 0))
            && localName.equalsIgnoreCase("html"))
    {
      if (null != getOutputPropertyNoDefault(OutputKeys.METHOD, props))
        return newSerializer;

      Properties prevProperties = props;

      OutputProperties htmlOutputProperties = new OutputProperties(Method.HTML);

      htmlOutputProperties.copyFrom(prevProperties, true);
      Properties htmlProperties = htmlOutputProperties.getProperties();

      {
        if (null != oldSerializer)
        {
          Serializer serializer =
            SerializerFactory.getSerializer(htmlProperties);

          Writer writer = oldSerializer.getWriter();

          if (null != writer)
            serializer.setWriter(writer);
          else
          {
            OutputStream os = serializer.getOutputStream();

            if (null != os)
              serializer.setOutputStream(os);
          }
          newSerializer = serializer;
        }
      }
    }
    return newSerializer;

FUNC_DECL RETURN VAR_DECL PARAM PARAM CALL


public class NoCacheStorage implements CacheStorage {

    public Object get(Object key) {
        return null;
    }

    public void put(Object key, Object value) {
    }

    public void remove(Object key) {
    }

    public void clear() {


org.apache.poi.hssf.dev.HSSF

public class HSSF
{
    private String         filename     = null;

    private InputStream    stream       = null;
    private Record[]       records      = null;
    protected HSSFWorkbook hssfworkbook = null;

    /**
     * Constructor HSSF - creates an HSSFStream from an InputStream.  The HSSFStream
     * reads in the records allowing modification.
     *
     *
     * @param filename
     *
     * @exception IOException
     *
     */

    public HSSF(String filename)
        throws IOException
    {
        this.filename = filename;
        POIFSFileSystem fs =
            new POIFSFileSystem(new FileInputStream(filename));

        hssfworkbook = new HSSFWorkbook(fs);

    }

    /**
     * Constructor HSSF - given a filename this outputs a sample sheet with just
     * a set of rows/cells.
     *
     *
     * @param filename
     * @param write
     *
     * @exception IOException
     *
     */

    public HSSF(String filename, boolean write)
        throws IOException
    {
        short            rownum = 0;
        FileOutputStream out    = new FileOutputStream(filename);
        HSSFWorkbook     wb     = new HSSFWorkbook();
        HSSFSheet        s      = wb.createSheet();
        HSSFRow          r      = null;
        HSSFCell         c      = null;
        HSSFCellStyle    cs     = wb.createCellStyle();
        HSSFCellStyle    cs2    = wb.createCellStyle();
        HSSFCellStyle    cs3    = wb.createCellStyle();
        HSSFFont         f      = wb.createFont();
        HSSFFont         f2     = wb.createFont();

        f.setFontHeightInPoints(( short ) 12);
        f.setColor(( short ) 0xA);
        f.setBoldweight(f.BOLDWEIGHT_BOLD);
        f2.setFontHeightInPoints(( short ) 10);
        f2.setColor(( short ) 0xf);
        f2.setBoldweight(f2.BOLDWEIGHT_BOLD);
        cs.setFont(f);
        cs.setDataFormat(HSSFDataFormat.getBuiltinFormat("($#,##0_);[Red]($#,##0)"));
        cs2.setBorderBottom(cs2.BORDER_THIN);
        cs2.setFillForegroundColor(( short ) 0xA);
        cs2.setFont(f2);
        wb.setSheetName(0, "HSSF Test");
        for (rownum = ( short ) 0; rownum < 300; rownum++)
        {
            r = s.createRow(rownum);
            if ((rownum % 2) == 0)
            {
                r.setHeight(( short ) 0x249);
            }

            for (short cellnum = ( short ) 0; cellnum < 50; cellnum += 2)
            {
                c = r.createCell(cellnum, HSSFCell.CELL_TYPE_NUMERIC);
                c.setCellValue(rownum * 10000 + cellnum
                               + ((( double ) rownum / 1000)
                                  + (( double ) cellnum / 10000)));
                if ((rownum % 2) == 0)
                {
                    c.setCellStyle(cs);
                }
                c = r.createCell(( short ) (cellnum + 1),
                                 HSSFCell.CELL_TYPE_STRING);
                c.setCellValue("TEST");
                s.setColumnWidth(( short ) (cellnum + 1),
                                 ( short ) ((50 * 8) / (( double ) 1 / 20)));
                if ((rownum % 2) == 0)
                {
                    c.setCellStyle(cs2);
                }
			}
        }

        rownum++;
        rownum++;
        r = s.createRow(rownum);
        cs3.setBorderBottom(cs3.BORDER_THICK);
        for (short cellnum = ( short ) 0; cellnum < 50; cellnum++)
        {
            c = r.createCell(cellnum, HSSFCell.CELL_TYPE_BLANK);

            c.setCellStyle(cs3);
        }
        s.addMergedRegion(new Region(( short ) 0, ( short ) 0, ( short ) 3,
                                     ( short ) 3));
        s.addMergedRegion(new Region(( short ) 100, ( short ) 100,
                                     ( short ) 110, ( short ) 110));

        s = wb.createSheet();
        wb.setSheetName(1, "DeletedSheet");
        wb.removeSheetAt(1);

        wb.write(out);
        out.close();
    }

    /**
     * Constructor HSSF - takes in file - attempts to read it then reconstruct it
     *
     *
     * @param infile
     * @param outfile
     * @param write
     *
     * @exception IOException
     *
     */

    public HSSF(String infile, String outfile, boolean write)
        throws IOException
    {
        this.filename = filename;
        POIFSFileSystem fs =
            new POIFSFileSystem(new FileInputStream(filename));

        hssfworkbook = new HSSFWorkbook(fs);

    }

    /**
     * Method main
     *
     * Given 1 argument takes that as the filename, inputs it and dumps the
     * cell values/types out to sys.out
     *
     * given 2 arguments where the second argument is the word "write" and the
     * first is the filename - writes out a sample (test) spreadsheet (see
     * public HSSF(String filename, boolean write)).
     *
     * given 2 arguments where the first is an input filename and the second
     * an output filename (not write), attempts to fully read in the
     * spreadsheet and fully write it out.
     *
     * given 3 arguments where the first is an input filename and the second an
     * output filename (not write) and the third is "modify1", attempts to read in the
     * spreadsheet, deletes rows 0-24, 74-99.  Changes cell at row 39, col 3 to
     * "MODIFIED CELL" then writes it out.  Hence this is "modify test 1".  If you
     * take the output from the write test, you'll have a valid scenario.
     *
     * @param args
     *
     */

    public static void main(String [] args)
    {
        if (args.length < 2)
        {

/*            try
            {
                HSSF hssf = new HSSF(args[ 0 ]);

                System.out.println("Data dump:\n");
                HSSFWorkbook wb = hssf.hssfworkbook;

                for (int k = 0; k < wb.getNumberOfSheets(); k++)
                {
                    System.out.println("Sheet " + k);
                    HSSFSheet sheet = wb.getSheetAt(k);
                    int       rows  = sheet.getPhysicalNumberOfRows();

                    for (int r = 0; r < rows; r++)
                    {
                        HSSFRow row   = sheet.getPhysicalRowAt(r);
                        int     cells = row.getPhysicalNumberOfCells();

                        System.out.println("ROW " + row.getRowNum());
                        for (int c = 0; c < cells; c++)
                        {
                            HSSFCell cell  = row.getPhysicalCellAt(c);
                            String   value = null;

                            switch (cell.getCellType())
                            {

                                case HSSFCell.CELL_TYPE_FORMULA :
                                    value = "FORMULA ";
                                    break;

                                case HSSFCell.CELL_TYPE_NUMERIC :
                                    value = "NUMERIC value="
                                            + cell.getNumericCellValue();
                                    break;

                                case HSSFCell.CELL_TYPE_STRING :
                                    value = "STRING value="
                                            + cell.getStringCellValue();
                                    break;

                                default :
                            }
                            System.out.println("CELL col="
                                               + cell.getCellNum()
                                               + " VALUE=" + value);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }*/
        }
        else if (args.length == 2)
        {
            if (args[ 1 ].toLowerCase().equals("write"))
            {
                System.out.println("Write mode");
                try
                {
                    long time = System.currentTimeMillis();
                    HSSF hssf = new HSSF(args[ 0 ], true);

                    System.out
                        .println("" + (System.currentTimeMillis() - time)
                                 + " ms generation time");
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
            else
            {
                System.out.println("readwrite test");
                try
                {
                    HSSF             hssf   = new HSSF(args[ 0 ]);

                    HSSFWorkbook     wb     = hssf.hssfworkbook;
                    FileOutputStream stream = new FileOutputStream(args[ 1 ]);

                    wb.write(stream);
                    stream.close();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
        else if ((args.length == 3)
                 && args[ 2 ].toLowerCase().equals("modify1"))
        {
            try{
                HSSF             hssf   = new HSSF(args[ 0 ]);

                HSSFWorkbook     wb     = hssf.hssfworkbook;
                FileOutputStream stream = new FileOutputStream(args[ 1 ]);
                HSSFSheet        sheet  = wb.getSheetAt(0);

                for (int k = 0; k < 25; k++)
                {
                    HSSFRow row = sheet.getRow(k);

                    sheet.removeRow(row);
                }
                for (int k = 74; k < 100; k++)
                {
                    HSSFRow row = sheet.getRow(k);

                    sheet.removeRow(row);
                }
                HSSFRow  row  = sheet.getRow(39);
                HSSFCell cell = row.getCell(( short ) 3);

                cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                cell.setCellValue("MODIFIED CELL!!!!!");

                wb.write(stream);
                stream.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();

FUNC_DECL VAR_DECL PARAM ASSIGN ASSIGN CALL CALL CALL

FUNC_DECL VAR_DECL PARAM PARAM PARAM ASSIGN ASSIGN CALL CALL CALL


public class License {
    private String name;

    private String url;

    public License(String name, String url) {
        this.name = name;
        this.url = url;
    }

    public String getName() {
        return name;
    }

    public String getUrl() {
        return url;

    public String getName() {
        return name;

    public String getUrl() {
        return url;


public final class UnitOfWorkProcessor extends DelegateAsyncProcessor {

    public UnitOfWorkProcessor(AsyncProcessor processor) {
        super(processor);
    }

    @Override
    public String toString() {
        return "UnitOfWrok(" + processor + ")";
    }

    public boolean process(final Exchange exchange, final AsyncCallback callback) {
        if (exchange.getUnitOfWork() == null) {
            final DefaultUnitOfWork uow = new DefaultUnitOfWork();
            exchange.setUnitOfWork(uow);
            try {
                uow.start();
            } catch (Exception e) {
                throw wrapRuntimeCamelException(e);
            }
            return processor.process(exchange, new AsyncCallback() {
                public void done(boolean sync) {
                    callback.done(sync);
                    exchange.getUnitOfWork().done(exchange);
                    try {
                        uow.stop();
                    } catch (Exception e) {
                        throw wrapRuntimeCamelException(e);
                    }
                    exchange.setUnitOfWork(null);
                }
            });
        } else {
            return processor.process(exchange, callback);

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


  public boolean isSevereLevel() {
    boolean isSevere = false;

    if (LogLevel.ERROR.equals(getLevel()) ||
        LogLevel.FATAL.equals(getLevel())) {
      isSevere = true;
    }

    return isSevere;

  public void setThrownStackTrace(ThrowableInformation throwableInfo) {
    String[] stackTraceArray = throwableInfo.getThrowableStrRep();

    StringBuffer stackTrace = new StringBuffer();
    String nextLine;

    for (int i = 0; i < stackTraceArray.length; i++) {
      nextLine = stackTraceArray[i] + "\n";
      stackTrace.append(nextLine);
    }

    _thrownStackTrace = stackTrace.toString();


org.apache.xml.dtm.DTMIterator

public interface DTMIterator
{

  /**
   * Accept the node.
   */
  public static final short FILTER_ACCEPT = 1;

  /**
   * Reject the node. Same behavior as FILTER_SKIP. (In the DOM these
   * differ when applied to a TreeWalker but have the same result when
   * applied to a NodeIterator).
   */
  public static final short FILTER_REJECT = 2;

  /**
   * Skip this single node.
   */
  public static final short FILTER_SKIP = 3;

  /**
   * Get an instance of a DTM that "owns" a node handle.  Since a node
   * iterator may be passed without a DTMManager, this allows the
   * caller to easily get the DTM using just the iterator.
   *
   * @param nodeHandle the nodeHandle.
   *
   * @return a non-null DTM reference.
   */
  public DTM getDTM(int nodeHandle);

  /**
   * Get an instance of the DTMManager.  Since a node
   * iterator may be passed without a DTMManager, this allows the
   * caller to easily get the DTMManager using just the iterator.
   *
   * @return a non-null DTMManager reference.
   */
  public DTMManager getDTMManager();

  /**
   * The root node of the DTMIterator, as specified when it
   * was created.  Note the root node is not the root node of the
   * document tree, but the context node from where the iteration
   * begins and ends.
   *
   * @return nodeHandle int Handle of the context node.
   */
  public int getRoot();

  /**
   * Reset the root node of the DTMIterator, overriding
   * the value specified when it was created.  Note the root node is
   * not the root node of the document tree, but the context node from
   * where the iteration begins.
   *
   * @param nodeHandle int Handle of the context node.
   * @param environment The environment object.
   * The environment in which this iterator operates, which should provide:
   *

   *
a node (the context node... same value as "root" defined below)

   *
a pair of non-zero positive integers (the context position and the context size)

   *
a set of variable bindings

   *
a function library

   *
the set of namespace declarations in scope for the expression.

   *

   *
   *
At this time the exact implementation of this environment is application
   * dependent.  Probably a proper interface will be created fairly soon.

   *
   */
  public void setRoot(int nodeHandle, Object environment);

  /**
   * Reset the iterator to the start. After resetting, the next node returned
   * will be the root node -- or, if that's filtered out, the first node
   * within the root's subtree which is _not_ skipped by the filters.
   */
  public void reset();

  /**
   * This attribute determines which node types are presented via the
   * iterator. The available set of constants is defined above.
   * Nodes not accepted by
   * whatToShow will be skipped, but their children may still
   * be considered.
   *
   * @return one of the SHOW_XXX constants, or several ORed together.
   */
  public int getWhatToShow();

  /**
   *
The value of this flag determines whether the children of entity
   * reference nodes are visible to the iterator. If false, they  and
   * their descendants will be rejected. Note that this rejection takes
   * precedence over whatToShow and the filter.

   *
   *
 To produce a view of the document that has entity references
   * expanded and does not expose the entity reference node itself, use
   * the whatToShow flags to hide the entity reference node
   * and set expandEntityReferences to true when creating the
   * iterator. To produce a view of the document that has entity reference
   * nodes but no entity expansion, use the whatToShow flags
   * to show the entity reference node and set
   * expandEntityReferences to false.

   *
   *
NOTE: In Xalan's use of DTM we will generally have fully expanded
   * entity references when the document tree was built, and thus this
   * flag will have no effect.

   *
   * @return true if entity references will be expanded.  */
  public boolean getExpandEntityReferences();

  /**
   * Returns the next node in the set and advances the position of the
   * iterator in the set. After a DTMIterator has setRoot called,
   * the first call to nextNode() returns that root or (if it
   * is rejected by the filters) the first node within its subtree which is
   * not filtered out.
   * @return The next node handle in the set being iterated over, or
   *  DTM.NULL if there are no more members in that set.
   */
  public int nextNode();

  /**
   * Returns the previous node in the set and moves the position of the
   * DTMIterator backwards in the set.
   * @return The previous node handle in the set being iterated over,
   *   or DTM.NULL if there are no more members in that set.
   */
  public int previousNode();

  /**
   * Detaches the DTMIterator from the set which it iterated
   * over, releasing any computational resources and placing the iterator
   * in the INVALID state. After detach has been invoked,
   * calls to nextNode or previousNode will
   * raise a runtime exception.
   */
  public void detach();

  /**
   * Specify if it's OK for detach to release the iterator for reuse.
   *
   * @param allowRelease true if it is OK for detach to release this iterator
   * for pooling.
   */
  public void allowDetachToRelease(boolean allowRelease);

  /**
   * Get the current node in the iterator. Note that this differs from
   * the DOM's NodeIterator, where the current position lies between two
   * nodes (as part of the maintain-relative-position semantic).
   *
   * @return The current node handle, or -1.
   */
  public int getCurrentNode();

  /**
   * Tells if this NodeSetDTM is "fresh", in other words, if
   * the first nextNode() that is called will return the
   * first node in the set.
   *
   * @return true if the iteration of this list has not yet begun.
   */
  public boolean isFresh();

  /**
   * If setShouldCacheNodes(true) is called, then nodes will
   * be cached, enabling random access, and giving the ability to do
   * sorts and the like.  They are not cached by default.
   *
   * %REVIEW% Shouldn't the other random-access methods throw an exception
   * if they're called on a DTMIterator with this flag set false?
   *
   * @param b true if the nodes should be cached.
   */
  public void setShouldCacheNodes(boolean b);

  /**
   * Tells if this iterator can have nodes added to it or set via
   * the setItem(int node, int index) method.
   *
   * @return True if the nodelist can be mutated.
   */
  public boolean isMutable();

  /** Get the current position within the cached list, which is one
   * less than the next nextNode() call will retrieve.  i.e. if you
   * call getCurrentPos() and the return is 0, the next fetch will
   * take place at index 1.
   *
   * @return The position of the iteration.
   */
  public int getCurrentPos();

  /**
   * If an index is requested, NodeSetDTM will call this method
   * to run the iterator to the index.  By default this sets
   * m_next to the index.  If the index argument is -1, this
   * signals that the iterator should be run to the end and
   * completely fill the cache.
   *
   * @param index The index to run to, or -1 if the iterator should be run
   *              to the end.
   */
  public void runTo(int index);

  /**
   * Set the current position in the node set.
   *
   * @param i Must be a valid index.
   */
  public void setCurrentPos(int i);

  /**
   * Returns the node handle of an item in the collection. If
   * index is greater than or equal to the number of nodes in
   * the list, this returns null.
   *
   * @param index of the item.
   * @return The node handle at the indexth position in the
   *   DTMIterator, or -1 if that is not a valid
   *   index.
   */
  public int item(int index);

  /**
   * Sets the node at the specified index of this vector to be the
   * specified node. The previous component at that position is discarded.
   *
   *
The index must be a value greater than or equal to 0 and less
   * than the current size of the vector.
   * The iterator must be in cached mode.

   *
   *
Meant to be used for sorted iterators.

   *
   * @param node Node to set
   * @param index Index of where to set the node
   */
  public void setItem(int node, int index);

  /**
   * The number of nodes in the list. The range of valid child node indices
   * is 0 to length-1 inclusive. Note that this requires running
   * the iterator to completion, and presumably filling the cache.
   *
   * @return The number of nodes in the list.
   */
  public int getLength();

  /**
   * Get a cloned Iterator that is reset to the start of the iteration.
   *
   * @return A clone of this iteration that has been reset.
   *
   * @throws CloneNotSupportedException
   */
  public DTMIterator cloneWithReset() throws CloneNotSupportedException;

  /**
   * Get a clone of this iterator, but don't reset the iteration in the
   * process, so that it may be used from the current position.
   *
   * @return A clone of this object.
   *
   * @throws CloneNotSupportedException
   */
  public Object clone() throws CloneNotSupportedException;

  /**
   * Returns true if all the nodes in the iteration well be returned in document
   * order.
   *
   * @return true if all the nodes in the iteration well be returned in document
   * order.
   */
  public boolean isDocOrdered();

  /**
   * Returns the axis being iterated, if it is known.
   *
   * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
   * types.
   */
  public int getAxis();


public class TestDriver
{

  /** Field sampleField          */
  public static int sampleField = 32;

  /** Field inTest          */
  private boolean inTest = false;

  /**
   * Method main
   *
   *
   * @param args
   */
  public static void main(String[] args)
  {

    try
    {
      System.out.println("Proxying java.awt.Frame...");

      Class myC = Class.forName("java.awt.Frame");

      myC.toSource(System.out, 0);
      System.out.println(
        "\nProxying org.apache.xml.utils.synthetic.TestDriver...");

      myC =
        Class.forName("com.ibm.org.apache.xml.utils.synthetic.TestDriver");

      myC.toSource(System.out, 0);
    }
    catch (ClassNotFoundException e)
    {
      System.out.println("Couldn't proxy: ");
      e.printStackTrace();
    }

    try
    {
      System.out.println("\nBuild a new beast...");

      Class myC = Class.declareClass(
        "com.ibm.org.apache.xml.utils.synthetic.BuildMe");
      Class inner = myC.declareInnerClass("island");

      inner.addExtends(Class.forName("java.lang.String"));

      Method m = inner.declareMethod("getValue");

      m.setReturnType(Class.forName("java.lang.String"));
      m.getBody().append("return toString();");
      myC.toSource(System.out, 0);
    }
    catch (ClassNotFoundException e)
    {
      e.printStackTrace();
    }
    catch (SynthesisException e)
    {
      e.printStackTrace();
    }
    catch (IllegalStateException e)
    {
      System.out.println("Unwritten function: " + e);
      e.printStackTrace();
    }
  }

  /**
   * Method dumpClass
   *
   *
   * @param C
   */
  public static void dumpClass(Class C)
  {

    System.out.println("toString(): " + C);
    System.out.println("\tisPrimitive(): " + C.isPrimitive());
    System.out.println("\tisInterface(): " + C.isInterface());
    System.out.println("\tisInstance(\"foo\"): " + C.isInstance("foo"));
    System.out.println("\tisArray(): " + C.isArray());
    System.out.println("\tgetRealClass(): " + C.getRealClass());
  }

  /**
   * Method quickcheck
   *
   */
  public void quickcheck()
  {

    Inner a = new Inner();

    a.setTest(!a.getTest());
  }

  /**
   * <meta name="usage" content="internal"/>
   * Class Inner <needs-comment/>
   */
  private class Inner
  {

    /**
     * Method getTest
     *
     *
     * @return
     */
    public boolean getTest()
    {
      return inTest;
    }

    /**
     * Method setTest
     *
     *
     * @param test
     */
    public void setTest(boolean test)
    {
      inTest = test;


org.apache.xpath.Expression

public abstract class Expression implements java.io.Serializable, ExpressionNode, XPathVisitable
{

  /**
   * The location where this expression was built from.  Need for diagnostic
   *  messages. May be null.
   *  @serial
   */
  private ExpressionNode m_parent;

  /**
   * Tell if this expression or it's subexpressions can traverse outside
   * the current subtree.
   *
   * @return true if traversal outside the context node's subtree can occur.
   */
  public boolean canTraverseOutsideSubtree()
  {
    return false;
  }

  /**
   * Execute an expression in the XPath runtime context, and return the
   * result of the expression.
   *
   *
   * @param xctxt The XPath runtime context.
   * @param currentNode The currentNode.
   *
   * @return The result of the expression in the form of a XObject.
   *
   * @throws javax.xml.transform.TransformerException if a runtime exception
   *         occurs.
   */
  public XObject execute(XPathContext xctxt, int currentNode)
          throws javax.xml.transform.TransformerException
  {

    return execute(xctxt);
  }

  /**
   * Execute an expression in the XPath runtime context, and return the
   * result of the expression.
   *
   *
   * @param xctxt The XPath runtime context.
   * @param currentNode The currentNode.
   * @param dtm The DTM of the current node.
   * @param expType The expanded type ID of the current node.
   *
   * @return The result of the expression in the form of a XObject.
   *
   * @throws javax.xml.transform.TransformerException if a runtime exception
   *         occurs.
   */
  public XObject execute(
          XPathContext xctxt, int currentNode, DTM dtm, int expType)
            throws javax.xml.transform.TransformerException
  {

    return execute(xctxt);
  }

  /**
   * Execute an expression in the XPath runtime context, and return the
   * result of the expression.
   *
   *
   * @param xctxt The XPath runtime context.
   *
   * @return The result of the expression in the form of a XObject.
   *
   * @throws javax.xml.transform.TransformerException if a runtime exception
   *         occurs.
   */
  public abstract XObject execute(XPathContext xctxt)
    throws javax.xml.transform.TransformerException;

  /**
   * Execute an expression in the XPath runtime context, and return the
   * result of the expression, but tell that a "safe" object doesn't have
   * to be returned.  The default implementation just calls execute(xctxt).
   *
   *
   * @param xctxt The XPath runtime context.
   * @param destructiveOK true if a "safe" object doesn't need to be returned.
   *
   * @return The result of the expression in the form of a XObject.
   *
   * @throws javax.xml.transform.TransformerException if a runtime exception
   *         occurs.
   */
  public XObject execute(XPathContext xctxt, boolean destructiveOK)
    throws javax.xml.transform.TransformerException
  {
  	return execute(xctxt);
  }

  /**
   * Evaluate expression to a number.
   *
   *
   * @param xctxt The XPath runtime context.
   * @return The expression evaluated as a double.
   *
   * @throws javax.xml.transform.TransformerException
   */
  public double num(XPathContext xctxt)
          throws javax.xml.transform.TransformerException
  {
    return execute(xctxt).num();
  }

  /**
   * Evaluate expression to a boolean.
   *
   *
   * @param xctxt The XPath runtime context.
   * @return false
   *
   * @throws javax.xml.transform.TransformerException
   */
  public boolean bool(XPathContext xctxt)
          throws javax.xml.transform.TransformerException
  {
    return execute(xctxt).bool();
  }

  /**
   * Cast result object to a string.
   *
   *
   * @param xctxt The XPath runtime context.
   * @return The string this wraps or the empty string if null
   *
   * @throws javax.xml.transform.TransformerException
   */
  public XMLString xstr(XPathContext xctxt)
          throws javax.xml.transform.TransformerException
  {
    return execute(xctxt).xstr();
  }

  /**
   * Tell if the expression is a nodeset expression.  In other words, tell
   * if you can execute {@link asNode() asNode} without an exception.
   * @return true if the expression can be represented as a nodeset.
   */
  public boolean isNodesetExpr()
  {
    return false;
  }

  /**
   * Return the first node out of the nodeset, if this expression is
   * a nodeset expression.
   * @param xctxt The XPath runtime context.
   * @return the first node out of the nodeset, or DTM.NULL.
   *
   * @throws javax.xml.transform.TransformerException
   */
  public int asNode(XPathContext xctxt)
          throws javax.xml.transform.TransformerException
  {
  	DTMIterator iter = execute(xctxt).iter();
    return iter.nextNode();
  }

  /**
   * Given an select expression and a context, evaluate the XPath
   * and return the resulting iterator.
   *
   * @param xctxt The execution context.
   * @param contextNode The node that "." expresses.
   *
   *
   * @return A valid DTMIterator.
   * @throws TransformerException thrown if the active ProblemListener decides
   * the error condition is severe enough to halt processing.
   *
   * @throws javax.xml.transform.TransformerException
   * @xsl.usage experimental
   */
  public DTMIterator asIterator(XPathContext xctxt, int contextNode)
          throws javax.xml.transform.TransformerException
  {

    try
    {
      xctxt.pushCurrentNodeAndExpression(contextNode, contextNode);

      return execute(xctxt).iter();
    }
    finally
    {
      xctxt.popCurrentNodeAndExpression();
    }
  }

  /**
   * Given an select expression and a context, evaluate the XPath
   * and return the resulting iterator, but do not clone.
   *
   * @param xctxt The execution context.
   * @param contextNode The node that "." expresses.
   *
   *
   * @return A valid DTMIterator.
   * @throws TransformerException thrown if the active ProblemListener decides
   * the error condition is severe enough to halt processing.
   *
   * @throws javax.xml.transform.TransformerException
   * @xsl.usage experimental
   */
  public DTMIterator asIteratorRaw(XPathContext xctxt, int contextNode)
          throws javax.xml.transform.TransformerException
  {

    try
    {
      xctxt.pushCurrentNodeAndExpression(contextNode, contextNode);

      XNodeSet nodeset = (XNodeSet)execute(xctxt);
      return nodeset.iterRaw();
    }
    finally
    {
      xctxt.popCurrentNodeAndExpression();
    }
  }

  /**
   * Execute an expression in the XPath runtime context, and return the
   * result of the expression.
   *
   *
   * @param xctxt The XPath runtime context.
   * NEEDSDOC @param handler
   *
   * @return The result of the expression in the form of a XObject.
   *
   * @throws javax.xml.transform.TransformerException if a runtime exception
   *         occurs.
   * @throws org.xml.sax.SAXException
   */
  public void executeCharsToContentHandler(
          XPathContext xctxt, ContentHandler handler)
            throws javax.xml.transform.TransformerException,
                   org.xml.sax.SAXException
  {

    XObject obj = execute(xctxt);

    obj.dispatchCharactersEvents(handler);
    obj.detach();
  }

  /**
   * Tell if this expression returns a stable number that will not change during
   * iterations within the expression.  This is used to determine if a proximity
   * position predicate can indicate that no more searching has to occur.
   *
   *
   * @return true if the expression represents a stable number.
   */
  public boolean isStableNumber()
  {
    return false;
  }

  /**
   * This function is used to fixup variables from QNames to stack frame
   * indexes at stylesheet build time.
   * @param vars List of QNames that correspond to variables.  This list
   * should be searched backwards for the first qualified name that
   * corresponds to the variable reference qname.  The position of the
   * QName in the vector from the start of the vector will be its position
   * in the stack frame (but variables above the globalsTop value will need
   * to be offset to the current stack frame).
   * NEEDSDOC @param globalsSize
   */
  public abstract void fixupVariables(java.util.Vector vars, int globalsSize);

  /**
   * Compare this object with another object and see
   * if they are equal, include the sub heararchy.
   *
   * @param expr Another expression object.
   * @return true if this objects class and the expr
   * object's class are the same, and the data contained
   * within both objects are considered equal.
   */
  public abstract boolean deepEquals(Expression expr);

  /**
   * This is a utility method to tell if the passed in
   * class is the same class as this.  It is to be used by
   * the deepEquals method.  I'm bottlenecking it here
   * because I'm not totally confident that comparing the
   * class objects is the best way to do this.
   * @return true of the passed in class is the exact same
   * class as this class.
   */
  protected final boolean isSameClass(Expression expr)
  {
  	if(null == expr)
  	  return false;

  	return (getClass() == expr.getClass());
  }

  /**
   * Warn the user of an problem.
   *
   * @param xctxt The XPath runtime context.
   * @param msg An error msgkey that corresponds to one of the conststants found
   *            in {@link org.apache.xpath.res.XPATHErrorResources}, which is
   *            a key for a format string.
   * @param args An array of arguments represented in the format string, which
   *             may be null.
   *
   * @throws TransformerException if the current ErrorListoner determines to
   *                              throw an exception.
   *
   * @throws javax.xml.transform.TransformerException
   */
  public void warn(XPathContext xctxt, String msg, Object[] args)
          throws javax.xml.transform.TransformerException
  {

    java.lang.String fmsg = XSLMessages.createXPATHWarning(msg, args);

    if (null != xctxt)
    {
      ErrorListener eh = xctxt.getErrorListener();

      eh.warning(new TransformerException(fmsg, xctxt.getSAXLocator()));
    }
  }

  /**
   * Tell the user of an assertion error, and probably throw an
   * exception.
   *
   * @param b  If false, a runtime exception will be thrown.
   * @param msg The assertion message, which should be informative.
   *
   * @throws RuntimeException if the b argument is false.
   *
   * @throws javax.xml.transform.TransformerException
   */
  public void assertion(boolean b, java.lang.String msg)
  {

    if (!b)
    {
      java.lang.String fMsg = XSLMessages.createXPATHMessage(
        XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION,
        new Object[]{ msg });

      throw new RuntimeException(fMsg);
    }
  }

  /**
   * Tell the user of an error, and probably throw an
   * exception.
   *
   * @param xctxt The XPath runtime context.
   * @param msg An error msgkey that corresponds to one of the constants found
   *            in {@link org.apache.xpath.res.XPATHErrorResources}, which is
   *            a key for a format string.
   * @param args An array of arguments represented in the format string, which
   *             may be null.
   *
   * @throws TransformerException if the current ErrorListoner determines to
   *                              throw an exception.
   *
   * @throws javax.xml.transform.TransformerException
   */
  public void error(XPathContext xctxt, String msg, Object[] args)
          throws javax.xml.transform.TransformerException
  {

    java.lang.String fmsg = XSLMessages.createXPATHMessage(msg, args);

    if (null != xctxt)
    {
      ErrorListener eh = xctxt.getErrorListener();
      TransformerException te = new TransformerException(fmsg, this);

      eh.fatalError(te);
    }
  }

  /**
   * Get the first non-Expression parent of this node.
   * @return null or first ancestor that is not an Expression.
   */
  public ExpressionNode getExpressionOwner()
  {
  	ExpressionNode parent = exprGetParent();
  	while((null != parent) && (parent instanceof Expression))
  		parent = parent.exprGetParent();
  	return parent;
  }

  /** This pair of methods are used to inform the node of its
    parent. */
  public void exprSetParent(ExpressionNode n)
  {
  	assertion(n != this, "Can not parent an expression to itself!");
  	m_parent = n;
  }

  public ExpressionNode exprGetParent()
  {
  	return m_parent;
  }

  /** This method tells the node to add its argument to the node's
    list of children.  */
  public void exprAddChild(ExpressionNode n, int i)
  {
  	assertion(false, "exprAddChild method not implemented!");
  }

  /** This method returns a child node.  The children are numbered
     from zero, left to right. */
  public ExpressionNode exprGetChild(int i)
  {
  	return null;
  }

  /** Return the number of children the node has. */
  public int exprGetNumChildren()
  {
  	return 0;
  }

  /**
   * Return the public identifier for the current document event.
   *
   *
The return value is the public identifier of the document
   * entity or of the external parsed entity in which the markup that
   * triggered the event appears.

   *
   * @return A string containing the public identifier, or
   *         null if none is available.
   * @see #getSystemId
   */
  public String getPublicId()
  {
  	if(null == m_parent)
  	  return null;
  	return m_parent.getPublicId();
  }

  /**
   * Return the system identifier for the current document event.
   *
   *
The return value is the system identifier of the document
   * entity or of the external parsed entity in which the markup that
   * triggered the event appears.

   *
   *
If the system identifier is a URL, the parser must resolve it
   * fully before passing it to the application.

   *
   * @return A string containing the system identifier, or null
   *         if none is available.
   * @see #getPublicId
   */
  public String getSystemId()
  {
  	if(null == m_parent)
  	  return null;
  	return m_parent.getSystemId();
  }

  /**
   * Return the line number where the current document event ends.
   *
   *
Warning: The return value from the method
   * is intended only as an approximation for the sake of error
   * reporting; it is not intended to provide sufficient information
   * to edit the character content of the original XML document.

   *
   *
The return value is an approximation of the line number
   * in the document entity or external parsed entity where the
   * markup that triggered the event appears.

   *
   * @return The line number, or -1 if none is available.
   * @see #getColumnNumber
   */
  public int getLineNumber()
  {
  	if(null == m_parent)
  	  return 0;
  	return m_parent.getLineNumber();
  }

  /**
   * Return the character position where the current document event ends.
   *
   *
Warning: The return value from the method
   * is intended only as an approximation for the sake of error
   * reporting; it is not intended to provide sufficient information
   * to edit the character content of the original XML document.

   *
   *
The return value is an approximation of the column number
   * in the document entity or external parsed entity where the
   * markup that triggered the event appears.

   *
   * @return The column number, or -1 if none is available.
   * @see #getLineNumber
   */
  public int getColumnNumber()
  {
  	if(null == m_parent)
  	  return 0;
  	return m_parent.getColumnNumber();

FUNC_DECL RETURN PARAM PARAM PARAM PARAM CALL

FUNC_DECL RETURN VAR_DECL PARAM CALL CALL CALL

FUNC_DECL TRY PARAM PARAM RETURN CALL CALL CALL CALL

FUNC_DECL TRY PARAM PARAM RETURN VAR_DECL CALL CALL CALL CALL

FUNC_DECL VAR_DECL PARAM PARAM CALL CALL CALL


public class RowRecordsAggregate
    extends Record
{
    int     firstrow = -1;
    int     lastrow  = -1;
    Map records  = null;
    int     size     = 0;

    /** Creates a new instance of ValueRecordsAggregate */

    public RowRecordsAggregate()
    {
        records = new TreeMap();
    }

    public void insertRow(RowRecord row)
    {
        size += row.getRecordSize();

        records.put(row, row);
        if ((row.getRowNumber() < firstrow) || (firstrow == -1))
        {
            firstrow = row.getRowNumber();
        }
        if ((row.getRowNumber() > lastrow) || (lastrow == -1))
        {
            lastrow = row.getRowNumber();
        }
    }

    public void removeRow(RowRecord row)
    {
        size -= row.getRecordSize();

        records.remove(row);
    }

    public RowRecord getRow(int rownum)
    {

        RowRecord row = new RowRecord();

        row.setRowNumber(( short ) rownum);
        return ( RowRecord ) records.get(row);
    }

    public int getPhysicalNumberOfRows()
    {
        return records.size();
    }

    public int getFirstRowNum()
    {
        return firstrow;
    }

    public int getLastRowNum()
    {
        return lastrow;
    }

	/*
	 * No need to go through all the records as we're just collecting RowRecords

    public int construct(int offset, List records)
    {
        int k = 0;

        for (k = offset; k < records.size(); k++)
        {
            Record rec = ( Record ) records.get(k);

            if (!rec.isInValueSection() && !(rec instanceof UnknownRecord))
            {
                break;
            }
            if (rec.getSid() == RowRecord.sid)
            {
                insertRow(( RowRecord ) rec);
            }
        }
        return k;
    }
	*/

    /**
     * called by the class that is responsible for writing this sucker.
     * Subclasses should implement this so that their data is passed back in a
     * byte array.
     *
     * @param offset    offset to begin writing at
     * @param data      byte array containing instance data
     * @return number of bytes written
     */

    public int serialize(int offset, byte [] data)
    {
        Iterator itr = records.values().iterator();
        int      pos = offset;

        while (itr.hasNext())
        {
            pos += (( Record ) itr.next()).serialize(pos, data);
        }
        return pos - offset;
    }

    /**
     * called by the constructor, should set class level fields.  Should throw
     * runtime exception for bad/icomplete data.
     *
     * @param data raw data
     * @param size size of data
     * @param offset of the record's data (provided a big array of the file)
     */

    protected void fillFields(byte [] data, short size, int offset)
    {
    }

    /**
     * called by constructor, should throw runtime exception in the event of a
     * record passed with a differing ID.
     *
     * @param id alleged id for this record
     */

    protected void validateSid(short id)
    {
    }

    /**
     * return the non static version of the id for this record.
     */

    public short getSid()
    {
        return -1000;
    }

    public int getRecordSize()
    {
        return size;
    }

    public Iterator getIterator()
    {
        return records.values().iterator();
    }

    /**
     * Performs a deep clone of the record
     */
    public Object clone()
    {
        RowRecordsAggregate rec = new RowRecordsAggregate();
        for ( Iterator rowIter = getIterator(); rowIter.hasNext(); )
        {
            RowRecord row = (RowRecord) ( (RowRecord) rowIter.next() ).clone();
            rec.insertRow( row );
        }
        return rec;
    }

    public int findStartOfRowOutlineGroup(int row)
    {
        RowRecord rowRecord = this.getRow( row );
        int level = rowRecord.getOutlineLevel();
        int currentRow = row;
        while (this.getRow( currentRow ) != null)
        {
            rowRecord = this.getRow( currentRow );
            if (rowRecord.getOutlineLevel() < level)
                return currentRow + 1;
            currentRow--;
        }

        return currentRow + 1;
    }

    public int findEndOfRowOutlineGroup( int row )
    {
        int level = getRow( row ).getOutlineLevel();
        int currentRow;
        for (currentRow = row; currentRow < this.getLastRowNum(); currentRow++)
        {
            if (getRow(currentRow) == null || getRow(currentRow).getOutlineLevel() < level)
            {
                break;
            }
        }

        return currentRow-1;
    }

    public int writeHidden( RowRecord rowRecord, int row, boolean hidden )
    {
        int level = rowRecord.getOutlineLevel();
        while (rowRecord != null && this.getRow(row).getOutlineLevel() >= level)
        {
            rowRecord.setZeroHeight( hidden );
            row++;
            rowRecord = this.getRow( row );
        }
        return row - 1;
    }

    public void collapseRow( int rowNumber )
    {

        int startRow = findStartOfRowOutlineGroup( rowNumber );
        RowRecord rowRecord = (RowRecord) getRow( startRow );

        int lastRow = writeHidden( rowRecord, startRow, true );

        if (getRow(lastRow + 1) != null)
        {
            getRow(lastRow + 1).setColapsed( true );
        }
        else
        {
            RowRecord row = createRow( lastRow + 1);
            row.setColapsed( true );
            insertRow( row );
        }
    }

    /**
     * Create a row record.
     *
     * @param row number
     * @return RowRecord created for the passed in row number
     * @see org.apache.poi.hssf.record.RowRecord
     */
    public static RowRecord createRow(int row)
    {
        RowRecord rowrec = new RowRecord();

        rowrec.setRowNumber(row);
        rowrec.setHeight(( short ) 0xff);
        rowrec.setOptimize(( short ) 0x0);
        rowrec.setXFIndex(( short ) 0xf);
        return rowrec;
    }

    public boolean isRowGroupCollapsed( int row )
    {
        int collapseRow = findEndOfRowOutlineGroup( row ) + 1;

        if (getRow(collapseRow) == null)
            return false;
        else
            return getRow( collapseRow ).getColapsed();
    }

    public void expandRow( int rowNumber )
    {
        int idx = rowNumber;
        if (idx == -1)
            return;

        if (!isRowGroupCollapsed(idx))
            return;

        int startIdx = findStartOfRowOutlineGroup( idx );
        RowRecord row = getRow( startIdx );

        int endIdx = findEndOfRowOutlineGroup( idx );

        if ( !isRowGroupHiddenByParent( idx ) )
        {
            for ( int i = startIdx; i <= endIdx; i++ )
            {
                if ( row.getOutlineLevel() == getRow( i ).getOutlineLevel() )
                    getRow( i ).setZeroHeight( false );
                else if (!isRowGroupCollapsed(i))
                    getRow( i ).setZeroHeight( false );
            }
        }

        getRow( endIdx + 1 ).setColapsed( false );
    }

    public boolean isRowGroupHiddenByParent( int row )
    {
        int endLevel;
        boolean endHidden;
        int endOfOutlineGroupIdx = findEndOfRowOutlineGroup( row );
        if (getRow( endOfOutlineGroupIdx + 1 ) == null)
        {
            endLevel = 0;
            endHidden = false;
        }
        else
        {
            endLevel = getRow( endOfOutlineGroupIdx + 1).getOutlineLevel();
            endHidden = getRow( endOfOutlineGroupIdx + 1).getZeroHeight();
        }

        int startLevel;
        boolean startHidden;
        int startOfOutlineGroupIdx = findStartOfRowOutlineGroup( row );
        if (startOfOutlineGroupIdx - 1 < 0 || getRow(startOfOutlineGroupIdx - 1) == null)
        {
            startLevel = 0;
            startHidden = false;
        }
        else
        {
            startLevel = getRow( startOfOutlineGroupIdx - 1).getOutlineLevel();
            startHidden = getRow( startOfOutlineGroupIdx - 1 ).getZeroHeight();
        }

        if (endLevel > startLevel)
        {
            return endHidden;
        }
        else
        {
            return startHidden;

FUNC_DECL RETURN LOOP VAR_DECL VAR_DECL PARAM PARAM BINARY_OP CALL CALL ASSIGN CALL CALL

    public short getSid()
    {
        return -1000;

FUNC_DECL RETURN LOOP VAR_DECL CALL VAR_DECL CALL CALL CALL CALL


public class MailComponent extends DefaultComponent<MailExchange> {
    private MailConfiguration configuration;

    public MailComponent() {
        this.configuration = new MailConfiguration();
    }

    public MailComponent(MailConfiguration configuration) {
        this.configuration = configuration;
    }

    public MailComponent(CamelContext context) {
        super(context);
        this.configuration = new MailConfiguration();
    }

    /**
     * Static builder method
     */
    public static MailComponent mailComponent() {
        return new MailComponent();
    }

    /**
     * Static builder method
     */
    public static MailComponent mailComponent(MailConfiguration configuration) {
        return new MailComponent(configuration);
    }

    @Override
    protected Endpoint<MailExchange> createEndpoint(String uri, String remaining, Map parameters) throws Exception {

        MailConfiguration config = getConfiguration().copy();
        config.configure(new URI(uri));

        MailEndpoint endpoint = new MailEndpoint(uri, this, config);

        setProperties(endpoint.getConfiguration(), parameters);
        return endpoint;
    }

    public MailConfiguration getConfiguration() {
        return configuration;
    }

    /**
     * Sets the Mail configuration
     *
     * @param configuration the configuration to use by default for endpoints
     */
    public void setConfiguration(MailConfiguration configuration) {
        this.configuration = configuration;
    }

    /**
     * A strategy method allowing the URI destination to be translated into the actual Mail destination name
     * (say by looking up in JNDI or something)
     */
    protected String convertPathToActualDestination(String path) {
        return path;

FUNC_DECL RETURN VAR_DECL VAR_DECL PARAM PARAM PARAM CALL CALL CALL CALL CALL CALL CALL