Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   ***** BEGIN LICENSE BLOCK *****
   * Version: CPL 1.0/GPL 2.0/LGPL 2.1
   *
   * The contents of this file are subject to the Common Public
   * License Version 1.0 (the "License"); you may not use this file
   * except in compliance with the License. You may obtain a copy of
   * the License at http://www.eclipse.org/legal/cpl-v10.html
   *
  * Software distributed under the License is distributed on an "AS
  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  * implied. See the License for the specific language governing
  * rights and limitations under the License.
  *
  * Copyright (C) 2001 Alan Moore <alan_moore@gmx.net>
  * Copyright (C) 2001-2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
  * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
  * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
  * Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
  * Copyright (C) 2004-2006 Charles O Nutter <headius@headius.com>
  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
  * Copyright (C) 2005 Kiel Hodges <jruby-devel@selfsosoft.com>
  * Copyright (C) 2005 Jason Voegele <jason@jvoegele.com>
  * Copyright (C) 2005 Tim Azzopardi <tim@tigerfive.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the CPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the CPL, the GPL or the LGPL.
  ***** END LICENSE BLOCK *****/
 package org.jruby;
 
 import java.io.File;
 
 import java.util.List;
 import java.util.Map;
Class used to launch the interpreter. This is the main class as defined in the jruby.mf manifest. It is very basic and does not support yet the same array of switches as the C interpreter. Usage: java -jar jruby.jar [switches] [rubyfile.rb] [arguments] -e 'command' one line of script. Several -e's allowed. Omit [programfile]

Author(s):
jpetersen
 
 public class Main {
     private static final Logger LOG = LoggerFactory.getLogger("Main");
     
     public Main(RubyInstanceConfig config) {
         this(configfalse);
     }
 
     public Main(final InputStream infinal PrintStream outfinal PrintStream err) {
         this(new RubyInstanceConfig(){{
             setInput(in);
             setOutput(out);
             setError(err);
         }});
     }
 
     public Main() {
         this(new RubyInstanceConfig());
     }
 
     private Main(RubyInstanceConfig configboolean hardExit) {
         this. = config;
         config.setHardExit(hardExit);
     }
 
     private Main(boolean hardExit) {
        // used only from main(String[]), so we process dotfile here
        processDotfile();
        this. = new RubyInstanceConfig();
        .setHardExit(hardExit);
    }
    
    private static List<StringgetDotfileDirectories() {
        ArrayList<StringsearchList = new ArrayList<String>();
        for (String homeProp : new String[] {"user.dir""user.home"}) {
            String home = SafePropertyAccessor.getProperty(homeProp);
            if (home != nullsearchList.add(home);
        }
        
        // JVM sometimes picks odd location for user.home based on a registry entry
        // (see http://bugs.sun.com/view_bug.do?bug_id=4787931).  Add extra check in 
        // case that entry is wrong. Add before user.home in search list.
        if (.) {
            String homeDrive = System.getenv("HOMEDRIVE");
            String homePath = System.getenv("HOMEPATH");
            if (homeDrive != null && homePath != null) {
                searchList.add(1, (homeDrive + homePath).replace('\\''/'));
            }
        }
        
        return searchList;
    }
    
    public static void processDotfile() {
        for (String home : getDotfileDirectories()) {
            File dotfile = new File(home + "/.jrubyrc");
            if (dotfile.exists()) loadJRubyProperties(dotfile);
        }
    }
    private static void loadJRubyProperties(File dotfile) {
        FileInputStream fis = null;
        
        try {
            // update system properties with long form jruby properties from .jrubyrc
            Properties sysProps = System.getProperties();
            Properties newProps = new Properties();
            // load properties and re-set as jruby.*
            fis = new FileInputStream(dotfile);
            newProps.load(fis);
            for (Map.Entry entry : newProps.entrySet()) {
                sysProps.put("jruby." + entry.getKey(), entry.getValue());
            }
        } catch (IOException ioe) {
            .debug("exception loading " + dotfileioe);
        } catch (SecurityException se) {
            .debug("exception loading " + dotfilese);
        } finally {
            if (fis != nulltry {fis.close();} catch (Exception e) {}        
        }
    }
    public static class Status {
        private boolean isExit = false;
        private int status = 0;

        
Creates a status object with the specified value and with explicit exit flag. An exit flag means that Kernel.exit() has been explicitly invoked during the run.

Parameters:
status The status value.
        Status(int status) {
            this. = true;
            this. = status;
        }

        
Creates a status object with 0 value and no explicit exit flag.
        Status() {}
        public boolean isExit() { return ; }
        public int getStatus() { return ; }
    }

    
This is the command-line entry point for JRuby, and should ONLY be used by Java when starting up JRuby from a command-line. Use other mechanisms when embedding JRuby into another application.

Parameters:
args command-line args, provided by the JVM.
    public static void main(String[] args) {
        doGCJCheck();
        
        Main main = new Main(true);
        
        try {
            Status status = main.run(args);
            if (status.isExit()) {
                System.exit(status.getStatus());
            }
        } catch (RaiseException rj) {
            System.exit(handleRaiseException(rj));
        } catch (Throwable t) {
            // print out as a nice Ruby backtrace
            ..println(ThreadContext.createRawBacktraceStringFromThrowable(t));
            while ((t = t.getCause()) != null) {
                ..println("Caused by:");
                ..println(ThreadContext.createRawBacktraceStringFromThrowable(t));
            }
            System.exit(1);
        }
    }
    public Status run(String[] args) {
        try {
            .processArguments(args);
            return run();
        } catch (MainExitException mee) {
            return handleMainExit(mee);
        } catch (OutOfMemoryError oome) {
            return handleOutOfMemory(oome);
        } catch (StackOverflowError soe) {
            return handleStackOverflow(soe);
        } catch (UnsupportedClassVersionError ucve) {
            return handleUnsupportedClassVersion(ucve);
        } catch (ThreadKill kill) {
            return new Status();
        }
    }
    @Deprecated
    public Status run() {
        return internalRun();
    }
    private Status internalRun() {
        doShowVersion();
        doShowCopyright();
        if (!.getShouldRunInterpreter() ) {
            doPrintUsage(false);
            doPrintProperties();
            return new Status();
        }
        InputStream in   = .getScriptSource();
        String filename  = .displayedFileName();
        
        doProcessArguments(in);
        
        Ruby runtime     = Ruby.newInstance();
        try {
            doSetContextClassLoader(runtime);
            if (in == null) {
                // no script to run, return success
                return new Status();
            } else if (.isXFlag() && !.hasShebangLine()) {
                // no shebang was found and x option is set
                throw new MainExitException(1, "jruby: no Ruby script found in input (LoadError)");
            } else if (.getShouldCheckSyntax()) {
                // check syntax only and exit
                return doCheckSyntax(runtimeinfilename);
            } else {
                // proceed to run the script
                return doRunFromMain(runtimeinfilename);
            }
        } finally {
            runtime.tearDown();
        }
    }
        .getError().println("Error: Some library (perhaps JRuby) was built with a later JVM version.");
        .getError().println("Please use libraries built with the version you intend to use or an earlier one.");
        if (.isVerbose()) {
            .getError().println("Exception trace follows:");
            ucve.printStackTrace();
        } else {
            .getError().println("Specify -w for full UnsupportedClassVersionError stack trace");
        }
        return new Status(1);
    }

    
Print a nicer stack size error since Rubyists aren't used to seeing this.
        String memoryMax = getRuntimeFlagValue("-Xss");
        if (memoryMax != null) {
            .getError().println("Error: Your application used more stack memory than the safety cap of " + memoryMax + ".");
        } else {
            .getError().println("Error: Your application used more stack memory than the default safety cap.");
        }
        .getError().println("Specify -J-Xss####k to increase it (#### = cap size in KB).");
        if (.isVerbose()) {
            .getError().println("Exception trace follows:");
            soe.printStackTrace(.getError());
        } else {
            .getError().println("Specify -w for full StackOverflowError stack trace");
        }
        return new Status(1);
    }

    
Print a nicer memory error since Rubyists aren't used to seeing this.
    private Status handleOutOfMemory(OutOfMemoryError oome) {
        System.gc(); // try to clean up a bit of space, hopefully, so we can report this error
        String oomeMessage = oome.getMessage();
        if (oomeMessage.contains("PermGen")) { // report permgen memory error
            .getError().println("Error: Your application exhausted PermGen area of the heap.");
            .getError().println("Specify -J-XX:MaxPermSize=###M to increase it (### = PermGen size in MB).");
        } else { // report heap memory error
            String memoryMax = getRuntimeFlagValue("-Xmx");
            if (memoryMax != null) {
                .getError().println("Error: Your application used more memory than the safety cap of " + memoryMax + ".");
            } else {
                .getError().println("Error: Your application used more memory than the default safety cap.");
            }
            .getError().println("Specify -J-Xmx####m to increase it (#### = cap size in MB).");
        }
        
        if (.isVerbose()) {
            .getError().println("Exception trace follows:");
            oome.printStackTrace(.getError());
        } else {
            .getError().println("Specify -w for full OutOfMemoryError stack trace");
        }
        return new Status(1);
    }
    private String getRuntimeFlagValue(String prefix) {
        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
        for (String param : runtime.getInputArguments()) {
            if (param.startsWith(prefix)) {
                return param.substring(prefix.length()).toUpperCase();
            }
        }
        return null;
    }
    private Status handleMainExit(MainExitException mee) {
        if (!mee.isAborted()) {
            .getOutput().println(mee.getMessage());
            if (mee.isUsageError()) {
                doPrintUsage(true);
            }
        }
        return new Status(mee.getStatus());
    }
    private Status doRunFromMain(Ruby runtimeInputStream inString filename) {
        long now = -1;
        try {
            if (.isBenchmarking()) {
                now = System.currentTimeMillis();
            }
            if (.isSamplingEnabled()) {
                SimpleSampler.startSampleThread();
            }
            doCheckSecurityManager();
            try {
                runtime.runFromMain(infilename);
            } finally {
                if (.isBenchmarking()) {
                    .getOutput().println("Runtime: " + (System.currentTimeMillis() - now) + " ms");
                }
                if (.isSamplingEnabled()) {
                    org.jruby.util.SimpleSampler.report();
                }
            }
        } catch (RaiseException rj) {
            return new Status(handleRaiseException(rj));
        }
        return new Status();
    }
    private Status doCheckSyntax(Ruby runtimeInputStream inString filenamethrows RaiseException {
        // check primary script
        boolean status = checkStreamSyntax(runtimeinfilename);
        
        // check other scripts specified on argv
        for (String arg : .getArgv()) {
            status = status && checkFileSyntax(runtimearg);
        }
        
        return new Status(status ? 0 : -1);
    }
    
    private boolean checkFileSyntax(Ruby runtimeString filename) {
        File file = new File(filename);
        if (file.exists()) {
            try {
                return checkStreamSyntax(runtimenew FileInputStream(file), filename);
            } catch (FileNotFoundException fnfe) {
                .getError().println("File not found: " + filename);
                return false;
            }
        } else {
            return false;
        }
    }
    
    private boolean checkStreamSyntax(Ruby runtimeInputStream inString filename) {
        PrintStream error = .getError();
        try {
            runtime.parseFromMain(infilename);
            error.println("Syntax OK for " + filename);
            return true;
        } catch (RaiseException re) {
            if (re.getException().getMetaClass().getBaseName().equals("SyntaxError")) {
                error.println("SyntaxError in " + re.getException().message(runtime.getCurrentContext()));
            } else {
                throw re;
            }
            return false;
        }
    }
    private void doSetContextClassLoader(Ruby runtime) {
        // set thread context JRuby classloader here, for the main thread
        try {
            Thread.currentThread().setContextClassLoader(runtime.getJRubyClassLoader());
        } catch (SecurityException se) {
            // can't set TC classloader
            if (runtime.getInstanceConfig().isVerbose()) {
                .getError().println("WARNING: Security restrictions disallowed setting context classloader for main thread.");
            }
        }
    }
    private void doProcessArguments(InputStream in) {
    }
    private void doPrintProperties() {
        if (.getShouldPrintProperties()) {
            .getOutput().print(OutputStrings.getPropertyHelp());
        }
    }
    private void doPrintUsage(boolean force) {
        if (.getShouldPrintUsage() || force) {
            .getOutput().print(OutputStrings.getBasicUsageHelp());
        }
    }
    private void doShowCopyright() {
        if (.isShowCopyright()) {
            .getOutput().println(OutputStrings.getCopyrightString());
        }
    }
    private void doShowVersion() {
        if (.isShowVersion()) {
            .getOutput().println(OutputStrings.getVersionString(.getCompatVersion()));
        }
    }
    private static void doGCJCheck() {
        // Ensure we're not running on GCJ, since it's not supported and leads to weird errors
        if (.) {
            ..println("Fatal: GCJ (GNU Compiler for Java) is not supported by JRuby.");
            System.exit(1);
        }
    }
    private void doCheckSecurityManager() {
        if (Main.class.getClassLoader() == null && System.getSecurityManager() != null) {
            ..println("Warning: security manager and JRuby running from boot classpath.\n" +
                    "Run from jruby.jar or set env VERIFY_JRUBY=true to enable security.");
        }
    }
    private static int handleRaiseException(RaiseException rj) {
        RubyException raisedException = rj.getException();
        Ruby runtime = raisedException.getRuntime();
        if (runtime.getSystemExit().isInstance(raisedException)) {
            IRubyObject status = raisedException.callMethod(runtime.getCurrentContext(), "status");
            if (status != null && !status.isNil()) {
                return RubyNumeric.fix2int(status);
            } else {
                return 0;
            }
        } else {
            ..print(runtime.getInstanceConfig().getTraceType().printBacktrace(raisedExceptionruntime.getPosix().isatty(.)));
            return 1;
        }
    }
    private final RubyInstanceConfig config;
New to GrepCode? Check out our FAQ X