3 # Licensed to the Apache Software Foundation (ASF) under one
4 # or more contributor license agreements. See the NOTICE file
5 # distributed with this work for additional information
6 # regarding copyright ownership. The ASF licenses this file
7 # to you under the Apache License, Version 2.0 (the
8 # "License"); you may not use this file except in compliance
9 # with the License. You may obtain a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
19 # File passed to org.jruby.Main by bin/hbase. Pollutes jirb with hbase imports
20 # and hbase commands and then loads jirb. Outputs a banner that tells user
21 # where to find help, shell version, and loads up a custom hirb.
23 # In noninteractive mode, runs commands from stdin until completion or an error.
24 # On success will exit with status 0, on any problem will exit non-zero. Callers
25 # should only rely on "not equal to 0", because the current error exit code of 1
26 # will likely be updated to diffentiate e.g. invalid commands, incorrect args,
29 # TODO: Interrupt a table creation or a connection to a bad master. Currently
30 # has to time out. Below we've set down the retries for rpc and hbase but
31 # still can be annoying (And there seem to be times when we'll retry for
33 # TODO: Add support for listing and manipulating catalog tables, etc.
34 # TODO: Encoding; need to know how to go from ruby String to UTF-8 bytes
36 # Run the java magic include and import basic HBase types that will help ease
40 # Some goodies for hirb. Should these be left up to the user's discretion?
41 require 'irb/completion'
44 # Add the directory names in hbase.jruby.sources commandline option
45 # to the ruby load path so I can load up my HBase ruby modules
46 sources = java.lang.System.getProperty('hbase.ruby.sources')
47 $LOAD_PATH.unshift Pathname.new(sources)
50 # FIXME: Switch args processing to getopt
52 # See if there are args for this shell. If any, read and then strip from ARGV
53 # so they don't go through to irb. Output shell 'usage' if user types '--help'
54 cmdline_help = <<HERE # HERE document output as shell usage
55 Usage: shell [OPTIONS] [SCRIPTFILE [ARGUMENTS]]
57 -d | --debug Set DEBUG log levels.
58 -h | --help This help.
59 -n | --noninteractive Do not run within an IRB session
60 and exit with non-zero status on
65 log_level = org.apache.log4j.Level::ERROR
69 if arg == '-h' || arg == '--help'
72 elsif arg == '-d' || arg == '--debug'
73 log_level = org.apache.log4j.Level::DEBUG
77 puts 'Setting DEBUG log level...'
78 elsif arg == '-n' || arg == '--noninteractive'
81 elsif arg == '-r' || arg == '--return-values'
82 warn '[INFO] the -r | --return-values option is ignored. we always behave '\
83 'as though it was given.'
86 # Presume it a script. Save it off for running later below
87 # after we've set up some environment.
90 # Presume that any other args are meant for the script.
95 # Delete all processed args
96 found.each { |arg| ARGV.delete(arg) }
97 # Make sure debug flag gets back to IRB
98 ARGV.unshift('-d') if @shell_debug
100 # Set logging level to avoid verboseness
101 org.apache.log4j.Logger.getLogger('org.apache.zookeeper').setLevel(log_level)
102 org.apache.log4j.Logger.getLogger('org.apache.hadoop.hbase').setLevel(log_level)
104 # Require HBase now after setting log levels
105 require 'hbase_constants'
111 require 'shell/formatter'
113 # Setup the HBase module. Create a configuration.
114 @hbase = Hbase::Hbase.new
117 @shell = Shell::Shell.new(@hbase, interactive)
118 @shell.debug = @shell_debug
120 # Add commands to this namespace
121 # TODO avoid polluting main namespace by using a binding
122 @shell.export_commands(self)
125 def help(command = nil)
129 # Backwards compatibility method
131 @shell.help_group('tools')
138 conf.back_trace_limit = 0
139 log_level = org.apache.log4j.Level::ERROR
142 conf.back_trace_limit = 100
143 log_level = org.apache.log4j.Level::DEBUG
145 org.apache.log4j.Logger.getLogger('org.apache.zookeeper').setLevel(log_level)
146 org.apache.log4j.Logger.getLogger('org.apache.hadoop.hbase').setLevel(log_level)
151 puts "Debug mode is #{@shell_debug ? 'ON' : 'OFF'}\n\n"
155 # Include hbase constants
156 include HBaseConstants
158 # If script2run, try running it. If we're in interactive mode, will go on to run the shell unless
159 # script calls 'exit' or 'exit 0' or 'exit errcode'.
160 load(script2run) if script2run
163 # Output a banner message that tells users where to go for help
170 def self.start(ap_path = nil)
171 $0 = File.basename(ap_path, '.rb') if ap_path
174 @CONF[:IRB_NAME] = 'hbase'
175 @CONF[:AP_NAME] = 'hbase'
176 @CONF[:BACK_TRACE_LIMIT] = 0 unless $fullBackTrace
178 hirb = if @CONF[:SCRIPT]
179 HIRB.new(nil, @CONF[:SCRIPT])
184 @CONF[:IRB_RC].call(hirb.context) if @CONF[:IRB_RC]
185 @CONF[:MAIN_CONTEXT] = hirb.context
196 # Noninteractive mode: if there is input on stdin, do a simple REPL.
197 # XXX Note that this purposefully uses STDIN and not Kernel.gets
198 # in order to maintain compatibility with previous behavior where
199 # a user could pass in script2run and then still pipe commands on
201 require 'irb/ruby-lex'
202 require 'irb/workspace'
203 workspace = IRB::WorkSpace.new(binding)
204 scanner = RubyLex.new
206 # RubyLex claims to take an IO but really wants an InputMethod
212 IO.include IOExtensions
214 scanner.set_input(STDIN)
215 scanner.each_top_level_statement do |statement, linenum|
216 puts(workspace.evaluate(nil, statement, 'stdin', linenum))
218 # XXX We're catching Exception on purpose, because we want to include
219 # unwrapped java exceptions, syntax errors, eval failures, etc.
220 rescue Exception => exception
221 message = exception.to_s
222 # exception unwrapping in shell means we'll have to handle Java exceptions
223 # as a special case in order to format them properly.
224 if exception.is_a? java.lang.Exception
225 $stderr.puts 'java exception'
226 message = exception.get_message
228 # Include the 'ERROR' string to try to make transition easier for scripts that
229 # may have already been relying on grepping output.
230 puts "ERROR #{exception.class}: #{message}"
232 # re-raising the will include a backtrace and exit.