1 36 package org.jruby; 37 38 import java.util.HashMap ; 39 import java.util.Map ; 40 41 import org.jruby.environment.OSEnvironmentReaderExcepton; 42 import org.jruby.environment.OSEnvironment; 43 import org.jruby.internal.runtime.ValueAccessor; 44 import org.jruby.runtime.Constants; 45 import org.jruby.runtime.GlobalVariable; 46 import org.jruby.runtime.ReadonlyGlobalVariable; 47 import org.jruby.runtime.ThreadContext; 48 import org.jruby.runtime.builtin.IRubyObject; 49 import org.jruby.util.KCode; 50 51 55 public class RubyGlobal { 56 57 61 private static class StringOnlyRubyHash extends RubyHash { 62 63 public StringOnlyRubyHash(Ruby runtime, Map valueMap, IRubyObject defaultValue) { 64 super(runtime, valueMap, defaultValue); 65 } 66 67 public IRubyObject aref(IRubyObject key) { 68 if (!key.respondsTo("to_str")) { 69 throw getRuntime().newTypeError("can't convert " + key.getMetaClass() + " into String"); 70 } 71 72 return super.aref(key.callMethod(getRuntime().getCurrentContext(), "to_str")); 73 } 74 75 public IRubyObject aset(IRubyObject key, IRubyObject value) { 76 if (!key.respondsTo("to_str")) { 77 throw getRuntime().newTypeError("can't convert " + key.getMetaClass() + " into String"); 78 } 79 if (!value.respondsTo("to_str") && !value.isNil()) { 80 throw getRuntime().newTypeError("can't convert " + value.getMetaClass() + " into String"); 81 } 82 83 ThreadContext context = getRuntime().getCurrentContext(); 84 85 return super.aset(key.callMethod(context, "to_str"), 86 value.isNil() ? getRuntime().getNil() : value.callMethod(context, "to_str")); 87 } 88 } 89 90 public static void createGlobals(Ruby runtime) { 91 92 IRubyObject version = runtime.newString(Constants.RUBY_VERSION).freeze(); 94 IRubyObject release = runtime.newString(Constants.COMPILE_DATE).freeze(); 95 IRubyObject platform = runtime.newString(Constants.PLATFORM).freeze(); 96 97 runtime.defineGlobalConstant("RUBY_VERSION", version); 98 runtime.defineGlobalConstant("RUBY_RELEASE_DATE", release); 99 runtime.defineGlobalConstant("RUBY_PLATFORM", platform); 100 101 runtime.defineGlobalConstant("VERSION", version); 102 runtime.defineGlobalConstant("RELEASE_DATE", release); 103 runtime.defineGlobalConstant("PLATFORM", platform); 104 105 GlobalVariable kcodeGV = new KCodeGlobalVariable(runtime, "$KCODE", runtime.newString("NONE")); 106 runtime.defineVariable(kcodeGV); 107 runtime.defineVariable(new GlobalVariable.Copy(runtime, "$-K", kcodeGV)); 108 runtime.defineVariable(new StringGlobalVariable(runtime, "$/", runtime.newString("\n").freeze())); 109 runtime.defineVariable(new StringGlobalVariable(runtime, "$\\", runtime.getNil())); 110 runtime.defineVariable(new StringGlobalVariable(runtime, "$,", runtime.getNil())); 111 112 runtime.defineVariable(new LineNumberGlobalVariable(runtime, "$.", RubyFixnum.one(runtime))); 113 runtime.defineVariable(new LastlineGlobalVariable(runtime, "$_")); 114 115 runtime.defineVariable(new ErrorInfoGlobalVariable(runtime, "$!", runtime.getNil())); 116 117 runtime.defineVariable(new SafeGlobalVariable(runtime, "$SAFE")); 118 119 runtime.defineVariable(new BacktraceGlobalVariable(runtime, "$@")); 120 121 IRubyObject stdin = RubyIO.fdOpen(runtime, RubyIO.STDIN); 122 IRubyObject stdout = RubyIO.fdOpen(runtime, RubyIO.STDOUT); 123 IRubyObject stderr = RubyIO.fdOpen(runtime, RubyIO.STDERR); 124 125 runtime.defineVariable(new InputGlobalVariable(runtime, "$stdin", stdin)); 126 127 runtime.defineVariable(new OutputGlobalVariable(runtime, "$stdout", stdout)); 128 runtime.defineVariable(new OutputGlobalVariable(runtime, "$stderr", stderr)); 129 runtime.defineVariable(new OutputGlobalVariable(runtime, "$>", stdout)); 130 runtime.defineVariable(new OutputGlobalVariable(runtime, "$defout", stdout)); 131 runtime.defineVariable(new OutputGlobalVariable(runtime, "$deferr", stderr)); 132 133 runtime.defineGlobalConstant("STDIN", stdin); 134 runtime.defineGlobalConstant("STDOUT", stdout); 135 runtime.defineGlobalConstant("STDERR", stderr); 136 137 runtime.defineVariable(new LoadedFeatures(runtime, "$\"")); 138 runtime.defineVariable(new LoadedFeatures(runtime, "$LOADED_FEATURES")); 139 140 runtime.defineVariable(new LoadPath(runtime, "$:")); 141 runtime.defineVariable(new LoadPath(runtime, "$-I")); 142 runtime.defineVariable(new LoadPath(runtime, "$LOAD_PATH")); 143 144 defineGlobalEnvConstants(runtime); 146 147 if (runtime.getGlobalVariables().get("$*").isNil()) { 149 runtime.getGlobalVariables().defineReadonly("$*", new ValueAccessor(runtime.newArray())); 150 } 151 152 new RubyArgsFile(runtime).initArgsFile(); 154 } 155 156 private static void defineGlobalEnvConstants(Ruby runtime) { 157 158 Map environmentVariableMap = null; 159 OSEnvironment environment = new OSEnvironment(); 160 try { 161 environmentVariableMap = environment.getEnvironmentVariableMap(runtime); 162 } catch (OSEnvironmentReaderExcepton e) { 163 runtime.getWarnings().warn(e.getMessage()); 165 } 166 167 if (environmentVariableMap == null) { 168 environmentVariableMap = new HashMap (); 170 } 171 runtime.defineGlobalConstant("ENV", new StringOnlyRubyHash(runtime, 172 environmentVariableMap, runtime.getNil())); 173 174 Map systemProps = environment.getSystemPropertiesMap(runtime); 176 runtime.defineGlobalConstant("ENV_JAVA", new StringOnlyRubyHash( 177 runtime, systemProps, runtime.getNil())); 178 179 } 180 181 182 183 185 private static class LineNumberGlobalVariable extends GlobalVariable { 186 public LineNumberGlobalVariable(Ruby runtime, String name, RubyFixnum value) { 187 super(runtime, name, value); 188 } 189 190 public IRubyObject set(IRubyObject value) { 191 ((RubyArgsFile) runtime.getGlobalVariables().get("$<")).setCurrentLineNumber(RubyNumeric.fix2int(value)); 192 return super.set(value); 193 } 194 } 195 196 private static class ErrorInfoGlobalVariable extends GlobalVariable { 197 public ErrorInfoGlobalVariable(Ruby runtime, String name, IRubyObject value) { 198 super(runtime, name, value); 199 } 200 201 public IRubyObject set(IRubyObject value) { 202 if (!value.isNil() && ! value.isKindOf(runtime.getClass("Exception"))) { 203 throw runtime.newTypeError("assigning non-exception to $!"); 204 } 205 return super.set(value); 206 } 207 } 208 209 public static class StringGlobalVariable extends GlobalVariable { 211 public StringGlobalVariable(Ruby runtime, String name, IRubyObject value) { 212 super(runtime, name, value); 213 } 214 215 public IRubyObject set(IRubyObject value) { 216 if (!value.isNil() && ! (value instanceof RubyString)) { 217 throw runtime.newTypeError("value of " + name() + " must be a String"); 218 } 219 return super.set(value); 220 } 221 } 222 223 public static class KCodeGlobalVariable extends GlobalVariable { 224 public KCodeGlobalVariable(Ruby runtime, String name, IRubyObject value) { 225 super(runtime, name, value); 226 } 227 228 public IRubyObject get() { 229 return runtime.getKCode().kcode(runtime); 230 } 231 232 public IRubyObject set(IRubyObject value) { 233 if (!value.isNil() && ! (value instanceof RubyString)) { 234 throw runtime.newTypeError("value of " + name() + " must be a String"); 235 } 236 runtime.setKCode(KCode.create(runtime, value.toString())); 237 return value; 238 } 239 } 240 241 private static class SafeGlobalVariable extends GlobalVariable { 242 public SafeGlobalVariable(Ruby runtime, String name) { 243 super(runtime, name, null); 244 } 245 246 public IRubyObject get() { 247 return runtime.newFixnum(runtime.getSafeLevel()); 248 } 249 250 public IRubyObject set(IRubyObject value) { 251 int level = RubyNumeric.fix2int(value); 252 if (level < runtime.getSafeLevel()) { 253 throw runtime.newSecurityError("tried to downgrade safe level from " + 254 runtime.getSafeLevel() + " to " + level); 255 } 256 runtime.setSafeLevel(level); 257 return value; 259 } 260 } 261 262 private static class BacktraceGlobalVariable extends GlobalVariable { 263 public BacktraceGlobalVariable(Ruby runtime, String name) { 264 super(runtime, name, null); 265 } 266 267 public IRubyObject get() { 268 IRubyObject errorInfo = runtime.getGlobalVariables().get("$!"); 269 IRubyObject backtrace = errorInfo.isNil() ? runtime.getNil() : errorInfo.callMethod(errorInfo.getRuntime().getCurrentContext(), "backtrace"); 270 if (!(backtrace instanceof RubyArray)) { 272 backtrace = runtime.getNil(); 273 } 274 return backtrace; 275 } 276 277 public IRubyObject set(IRubyObject value) { 278 if (runtime.getGlobalVariables().get("$!").isNil()) { 279 throw runtime.newArgumentError("$! not set."); 280 } 281 runtime.getGlobalVariables().get("$!").callMethod(value.getRuntime().getCurrentContext(), "set_backtrace", value); 282 return value; 283 } 284 } 285 286 private static class LastlineGlobalVariable extends GlobalVariable { 287 public LastlineGlobalVariable(Ruby runtime, String name) { 288 super(runtime, name, null); 289 } 290 291 public IRubyObject get() { 292 return runtime.getCurrentContext().getLastline(); 293 } 294 295 public IRubyObject set(IRubyObject value) { 296 runtime.getCurrentContext().setLastline(value); 297 return value; 298 } 299 } 300 301 private static class InputGlobalVariable extends GlobalVariable { 302 public InputGlobalVariable(Ruby runtime, String name, IRubyObject value) { 303 super(runtime, name, value); 304 } 305 306 public IRubyObject set(IRubyObject value) { 307 if (value == get()) { 308 return value; 309 } 310 if (value instanceof RubyIO) { 311 ((RubyIO) value).checkReadable(); 312 } 313 return super.set(value); 314 } 315 } 316 317 private static class OutputGlobalVariable extends GlobalVariable { 318 public OutputGlobalVariable(Ruby runtime, String name, IRubyObject value) { 319 super(runtime, name, value); 320 } 321 322 public IRubyObject set(IRubyObject value) { 323 if (value == get()) { 324 return value; 325 } 326 if (value instanceof RubyIO) { 327 ((RubyIO) value).checkWriteable(); 328 } 329 if (! value.respondsTo("write")) { 330 throw runtime.newTypeError(name() + " must have write method, " + 331 value.getType().getName() + " given"); 332 } 333 334 if ("$stdout".equals(name())) { 335 runtime.defineVariable(new OutputGlobalVariable(runtime, "$>", value)); 336 } 337 338 return super.set(value); 339 } 340 } 341 342 private static class LoadPath extends ReadonlyGlobalVariable { 343 public LoadPath(Ruby runtime, String name) { 344 super(runtime, name, null); 345 } 346 347 350 public IRubyObject get() { 351 return runtime.getLoadService().getLoadPath(); 352 } 353 } 354 355 private static class LoadedFeatures extends ReadonlyGlobalVariable { 356 public LoadedFeatures(Ruby runtime, String name) { 357 super(runtime, name, null); 358 } 359 360 363 public IRubyObject get() { 364 return runtime.getLoadService().getLoadedFeatures(); 365 } 366 } 367 } 368 | Popular Tags |