alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (Main.java)

This example Java source code file (Main.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

bufferedreader, command, default_language, fileinputstream, inputstream, inputstreamreader, ioexception, list, net, network, object, scriptengine, scriptexception, string, text, url, urlclassloader, util

The Main.java Java example source code

/*
 * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.script.shell;

import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import javax.script.*;

/**
 * This is the main class for Java script shell.
 */
public class Main {
    /**
     * main entry point to the command line tool
     * @param args command line argument array
     */
    public static void main(String[] args) {
        // parse command line options
        String[] scriptArgs = processOptions(args);

        // process each script command
        for (Command cmd : scripts) {
            cmd.run(scriptArgs);
        }

        System.exit(EXIT_SUCCESS);
    }

    // Each -e or -f or interactive mode is represented
    // by an instance of Command.
    private static interface Command {
        public void run(String[] arguments);
    }

    /**
     * Parses and processes command line options.
     * @param args command line argument array
     */
    private static String[] processOptions(String[] args) {
        // current scripting language selected
        String currentLanguage = DEFAULT_LANGUAGE;
        // current script file encoding selected
        String currentEncoding = null;

        // check for -classpath or -cp first
        checkClassPath(args);

        // have we seen -e or -f ?
        boolean seenScript = false;
        // have we seen -f - already?
        boolean seenStdin = false;
        for (int i=0; i < args.length; i++) {
            String arg = args[i];
            if (arg.equals("-classpath") ||
                    arg.equals("-cp")) {
                // handled already, just continue
                i++;
                continue;
            }

            // collect non-option arguments and pass these as script arguments
            if (!arg.startsWith("-")) {
                int numScriptArgs;
                int startScriptArg;
                if (seenScript) {
                    // if we have seen -e or -f already all non-option arguments
                    // are passed as script arguments
                    numScriptArgs = args.length - i;
                    startScriptArg = i;
                } else {
                    // if we have not seen -e or -f, first non-option argument
                    // is treated as script file name and rest of the non-option
                    // arguments are passed to script as script arguments
                    numScriptArgs = args.length - i - 1;
                    startScriptArg = i + 1;
                    ScriptEngine se = getScriptEngine(currentLanguage);
                    addFileSource(se, args[i], currentEncoding);
                }
                // collect script arguments and return to main
                String[] result = new String[numScriptArgs];
                System.arraycopy(args, startScriptArg, result, 0, numScriptArgs);
                return result;
            }

            if (arg.startsWith("-D")) {
                String value = arg.substring(2);
                int eq = value.indexOf('=');
                if (eq != -1) {
                    System.setProperty(value.substring(0, eq),
                            value.substring(eq + 1));
                } else {
                    if (!value.equals("")) {
                        System.setProperty(value, "");
                    } else {
                        // do not allow empty property name
                        usage(EXIT_CMD_NO_PROPNAME);
                    }
                }
                continue;
            } else if (arg.equals("-?") || arg.equals("-help")) {
                usage(EXIT_SUCCESS);
            } else if (arg.equals("-e")) {
                seenScript = true;
                if (++i == args.length)
                    usage(EXIT_CMD_NO_SCRIPT);

                ScriptEngine se = getScriptEngine(currentLanguage);
                addStringSource(se, args[i]);
                continue;
            } else if (arg.equals("-encoding")) {
                if (++i == args.length)
                    usage(EXIT_CMD_NO_ENCODING);
                currentEncoding = args[i];
                continue;
            } else if (arg.equals("-f")) {
                seenScript = true;
                if (++i == args.length)
                    usage(EXIT_CMD_NO_FILE);
                ScriptEngine se = getScriptEngine(currentLanguage);
                if (args[i].equals("-")) {
                    if (seenStdin) {
                        usage(EXIT_MULTIPLE_STDIN);
                    } else {
                        seenStdin = true;
                    }
                    addInteractiveMode(se);
                } else {
                    addFileSource(se, args[i], currentEncoding);
                }
                continue;
            } else if (arg.equals("-l")) {
                if (++i == args.length)
                    usage(EXIT_CMD_NO_LANG);
                currentLanguage = args[i];
                continue;
            } else if (arg.equals("-q")) {
                listScriptEngines();
            }
            // some unknown option...
            usage(EXIT_UNKNOWN_OPTION);
        }

        if (! seenScript) {
            ScriptEngine se = getScriptEngine(currentLanguage);
            addInteractiveMode(se);
        }
        return new String[0];
    }

    /**
     * Adds interactive mode Command
     * @param se ScriptEngine to use in interactive mode.
     */
    private static void addInteractiveMode(final ScriptEngine se) {
        scripts.add(new Command() {
            public void run(String[] args) {
                setScriptArguments(se, args);
                processSource(se, "-", null);
            }
        });
    }

    /**
     * Adds script source file Command
     * @param se ScriptEngine used to evaluate the script file
     * @param fileName script file name
     * @param encoding script file encoding
     */
    private static void addFileSource(final ScriptEngine se,
            final String fileName,
            final String encoding) {
        scripts.add(new Command() {
            public void run(String[] args) {
                setScriptArguments(se, args);
                processSource(se, fileName, encoding);
            }
        });
    }

    /**
     * Adds script string source Command
     * @param se ScriptEngine to be used to evaluate the script string
     * @param source Script source string
     */
    private static void addStringSource(final ScriptEngine se,
            final String source) {
        scripts.add(new Command() {
            public void run(String[] args) {
                setScriptArguments(se, args);
                String oldFile = setScriptFilename(se, "<string>");
                try {
                    evaluateString(se, source);
                } finally {
                    setScriptFilename(se, oldFile);
                }
            }
        });
    }

    /**
     * Prints list of script engines available and exits.
     */
    private static void listScriptEngines() {
        List<ScriptEngineFactory> factories = engineManager.getEngineFactories();
        for (ScriptEngineFactory factory: factories) {
            getError().println(getMessage("engine.info",
                    new Object[] { factory.getLanguageName(),
                            factory.getLanguageVersion(),
                            factory.getEngineName(),
                            factory.getEngineVersion()
            }));
        }
        System.exit(EXIT_SUCCESS);
    }

    /**
     * Processes a given source file or standard input.
     * @param se ScriptEngine to be used to evaluate
     * @param filename file name, can be null
     * @param encoding script file encoding, can be null
     */
    private static void processSource(ScriptEngine se, String filename,
            String encoding) {
        if (filename.equals("-")) {
            BufferedReader in = new BufferedReader
                    (new InputStreamReader(getIn()));
            boolean hitEOF = false;
            String prompt = getPrompt(se);
            se.put(ScriptEngine.FILENAME, "<STDIN>");
            while (!hitEOF) {
                getError().print(prompt);
                String source = "";
                try {
                    source = in.readLine();
                } catch (IOException ioe) {
                    getError().println(ioe.toString());
                }
                if (source == null) {
                    hitEOF = true;
                    break;
                }
                Object res = evaluateString(se, source, false);
                if (res != null) {
                    res = res.toString();
                    if (res == null) {
                        res = "null";
                    }
                    getError().println(res);
                }
            }
        } else {
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(filename);
            } catch (FileNotFoundException fnfe) {
                getError().println(getMessage("file.not.found",
                        new Object[] { filename }));
                        System.exit(EXIT_FILE_NOT_FOUND);
            }
            evaluateStream(se, fis, filename, encoding);
        }
    }

    /**
     * Evaluates given script source
     * @param se ScriptEngine to evaluate the string
     * @param script Script source string
     * @param exitOnError whether to exit the process on script error
     */
    private static Object evaluateString(ScriptEngine se,
            String script, boolean exitOnError) {
        try {
            return se.eval(script);
        } catch (ScriptException sexp) {
            getError().println(getMessage("string.script.error",
                    new Object[] { sexp.getMessage() }));
                    if (exitOnError)
                        System.exit(EXIT_SCRIPT_ERROR);
        } catch (Exception exp) {
            exp.printStackTrace(getError());
            if (exitOnError)
                System.exit(EXIT_SCRIPT_ERROR);
        }

        return null;
    }

    /**
     * Evaluate script string source and exit on script error
     * @param se ScriptEngine to evaluate the string
     * @param script Script source string
     */
    private static void evaluateString(ScriptEngine se, String script) {
        evaluateString(se, script, true);
    }

    /**
     * Evaluates script from given reader
     * @param se ScriptEngine to evaluate the string
     * @param reader Reader from which is script is read
     * @param name file name to report in error.
     */
    private static Object evaluateReader(ScriptEngine se,
            Reader reader, String name) {
        String oldFilename = setScriptFilename(se, name);
        try {
            return se.eval(reader);
        } catch (ScriptException sexp) {
            getError().println(getMessage("file.script.error",
                    new Object[] { name, sexp.getMessage() }));
                    System.exit(EXIT_SCRIPT_ERROR);
        } catch (Exception exp) {
            exp.printStackTrace(getError());
            System.exit(EXIT_SCRIPT_ERROR);
        } finally {
            setScriptFilename(se, oldFilename);
        }
        return null;
    }

    /**
     * Evaluates given input stream
     * @param se ScriptEngine to evaluate the string
     * @param is InputStream from which script is read
     * @param name file name to report in error
     */
    private static Object evaluateStream(ScriptEngine se,
            InputStream is, String name,
            String encoding) {
        BufferedReader reader = null;
        if (encoding != null) {
            try {
                reader = new BufferedReader(new InputStreamReader(is,
                        encoding));
            } catch (UnsupportedEncodingException uee) {
                getError().println(getMessage("encoding.unsupported",
                        new Object[] { encoding }));
                        System.exit(EXIT_NO_ENCODING_FOUND);
            }
        } else {
            reader = new BufferedReader(new InputStreamReader(is));
        }
        return evaluateReader(se, reader, name);
    }

    /**
     * Prints usage message and exits
     * @param exitCode process exit code
     */
    private static void usage(int exitCode) {
        getError().println(getMessage("main.usage",
                new Object[] { PROGRAM_NAME }));
                System.exit(exitCode);
    }

    /**
     * Gets prompt for interactive mode
     * @return prompt string to use
     */
    private static String getPrompt(ScriptEngine se) {
        List<String> names = se.getFactory().getNames();
        return names.get(0) + "> ";
    }

    /**
     * Get formatted, localized error message
     */
    private static String getMessage(String key, Object[] params) {
        return MessageFormat.format(msgRes.getString(key), params);
    }

    // input stream from where we will read
    private static InputStream getIn() {
        return System.in;
    }

    // stream to print error messages
    private static PrintStream getError() {
        return System.err;
    }

    // get current script engine
    private static ScriptEngine getScriptEngine(String lang) {
        ScriptEngine se = engines.get(lang);
        if (se == null) {
            se = engineManager.getEngineByName(lang);
            if (se == null) {
                getError().println(getMessage("engine.not.found",
                        new Object[] { lang }));
                        System.exit(EXIT_ENGINE_NOT_FOUND);
            }

            // initialize the engine
            initScriptEngine(se);
            // to avoid re-initialization of engine, store it in a map
            engines.put(lang, se);
        }
        return se;
    }

    // initialize a given script engine
    private static void initScriptEngine(ScriptEngine se) {
        // put engine global variable
        se.put("engine", se);

        // load init.<ext> file from resource
        List<String> exts = se.getFactory().getExtensions();
        InputStream sysIn = null;
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        for (String ext : exts) {
            sysIn = cl.getResourceAsStream("com/sun/tools/script/shell/init." +
                    ext);
            if (sysIn != null) break;
        }
        if (sysIn != null) {
            evaluateStream(se, sysIn, "<system-init>", null);
        }
    }

    /**
     * Checks for -classpath, -cp in command line args. Creates a ClassLoader
     * and sets it as Thread context loader for current thread.
     *
     * @param args command line argument array
     */
    private static void checkClassPath(String[] args) {
        String classPath = null;
        for (int i = 0; i < args.length; i++) {
            if (args[i].equals("-classpath") ||
                    args[i].equals("-cp")) {
                if (++i == args.length) {
                    // just -classpath or -cp with no value
                    usage(EXIT_CMD_NO_CLASSPATH);
                } else {
                    classPath = args[i];
                }
            }
        }

        if (classPath != null) {
            /* We create a class loader, configure it with specified
             * classpath values and set the same as context loader.
             * Note that ScriptEngineManager uses context loader to
             * load script engines. So, this ensures that user defined
             * script engines will be loaded. For classes referred
             * from scripts, Rhino engine uses thread context loader
             * but this is script engine dependent. We don't have
             * script engine independent solution anyway. Unless we
             * know the class loader used by a specific engine, we
             * can't configure correct loader.
             */
            ClassLoader parent = Main.class.getClassLoader();
            URL[] urls = pathToURLs(classPath);
            URLClassLoader loader = new URLClassLoader(urls, parent);
            Thread.currentThread().setContextClassLoader(loader);
        }

        // now initialize script engine manager. Note that this has to
        // be done after setting the context loader so that manager
        // will see script engines from user specified classpath
        engineManager = new ScriptEngineManager();
    }

    /**
     * Utility method for converting a search path string to an array
     * of directory and JAR file URLs.
     *
     * @param path the search path string
     * @return the resulting array of directory and JAR file URLs
     */
    private static URL[] pathToURLs(String path) {
        String[] components = path.split(File.pathSeparator);
        URL[] urls = new URL[components.length];
        int count = 0;
        while(count < components.length) {
            URL url = fileToURL(new File(components[count]));
            if (url != null) {
                urls[count++] = url;
            }
        }
        if (urls.length != count) {
            URL[] tmp = new URL[count];
            System.arraycopy(urls, 0, tmp, 0, count);
            urls = tmp;
        }
        return urls;
    }

    /**
     * Returns the directory or JAR file URL corresponding to the specified
     * local file name.
     *
     * @param file the File object
     * @return the resulting directory or JAR file URL, or null if unknown
     */
    private static URL fileToURL(File file) {
        String name;
        try {
            name = file.getCanonicalPath();
        } catch (IOException e) {
            name = file.getAbsolutePath();
        }
        name = name.replace(File.separatorChar, '/');
        if (!name.startsWith("/")) {
            name = "/" + name;
        }
        // If the file does not exist, then assume that it's a directory
        if (!file.isFile()) {
            name = name + "/";
        }
        try {
            return new URL("file", "", name);
        } catch (MalformedURLException e) {
            throw new IllegalArgumentException("file");
        }
    }

    private static void setScriptArguments(ScriptEngine se, String[] args) {
        se.put("arguments", args);
        se.put(ScriptEngine.ARGV, args);
    }

    private static String setScriptFilename(ScriptEngine se, String name) {
        String oldName = (String) se.get(ScriptEngine.FILENAME);
        se.put(ScriptEngine.FILENAME, name);
        return oldName;
    }

    // exit codes
    private static final int EXIT_SUCCESS            = 0;
    private static final int EXIT_CMD_NO_CLASSPATH   = 1;
    private static final int EXIT_CMD_NO_FILE        = 2;
    private static final int EXIT_CMD_NO_SCRIPT      = 3;
    private static final int EXIT_CMD_NO_LANG        = 4;
    private static final int EXIT_CMD_NO_ENCODING    = 5;
    private static final int EXIT_CMD_NO_PROPNAME    = 6;
    private static final int EXIT_UNKNOWN_OPTION     = 7;
    private static final int EXIT_ENGINE_NOT_FOUND   = 8;
    private static final int EXIT_NO_ENCODING_FOUND  = 9;
    private static final int EXIT_SCRIPT_ERROR       = 10;
    private static final int EXIT_FILE_NOT_FOUND     = 11;
    private static final int EXIT_MULTIPLE_STDIN     = 12;

    // default scripting language
    private static final String DEFAULT_LANGUAGE = "js";
    // list of scripts to process
    private static List<Command> scripts;
    // the script engine manager
    private static ScriptEngineManager engineManager;
    // map of engines we loaded
    private static Map<String, ScriptEngine> engines;
    // error messages resource
    private static ResourceBundle msgRes;
    private static String BUNDLE_NAME = "com.sun.tools.script.shell.messages";
    private static String PROGRAM_NAME = "jrunscript";

    static {
        scripts = new ArrayList<Command>();
        engines = new HashMap<String, ScriptEngine>();
        msgRes = ResourceBundle.getBundle(BUNDLE_NAME, Locale.getDefault());
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java Main.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.