KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > RubyGlobal


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
15  * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
16  * Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
17  * Copyright (C) 2004 Charles O Nutter <headius@headius.com>
18  * Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
19  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
20  * Copyright (C) 2006 Tim Azzopardi <tim@tigerfive.com>
21  * Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
22  * Copyright (C) 2006 Michael Studman <codehaus@michaelstudman.com>
23  *
24  * Alternatively, the contents of this file may be used under the terms of
25  * either of the GNU General Public License Version 2 or later (the "GPL"),
26  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27  * in which case the provisions of the GPL or the LGPL are applicable instead
28  * of those above. If you wish to allow use of your version of this file only
29  * under the terms of either the GPL or the LGPL, and not to allow others to
30  * use your version of this file under the terms of the CPL, indicate your
31  * decision by deleting the provisions above and replace them with the notice
32  * and other provisions required by the GPL or the LGPL. If you do not delete
33  * the provisions above, a recipient may use your version of this file under
34  * the terms of any one of the CPL, the GPL or the LGPL.
35  ***** END LICENSE BLOCK *****/

36 package org.jruby;
37
38 import java.util.HashMap JavaDoc;
39 import java.util.Map JavaDoc;
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 /** This class initializes global variables and constants.
52  *
53  * @author jpetersen
54  */

55 public class RubyGlobal {
56     
57     /**
58      * Obligate string-keyed and string-valued hash, used for ENV and ENV_JAVA
59      *
60      */

61     private static class StringOnlyRubyHash extends RubyHash {
62         
63         public StringOnlyRubyHash(Ruby runtime, Map JavaDoc 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         // Version information:
93
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         // after defn of $stderr as the call may produce warnings
145
defineGlobalEnvConstants(runtime);
146         
147         // Fixme: Do we need the check or does Main.java not call this...they should consolidate
148
if (runtime.getGlobalVariables().get("$*").isNil()) {
149             runtime.getGlobalVariables().defineReadonly("$*", new ValueAccessor(runtime.newArray()));
150         }
151
152         // ARGF, $< object
153
new RubyArgsFile(runtime).initArgsFile();
154     }
155
156     private static void defineGlobalEnvConstants(Ruby runtime) {
157
158         Map JavaDoc environmentVariableMap = null;
159         OSEnvironment environment = new OSEnvironment();
160         try {
161             environmentVariableMap = environment.getEnvironmentVariableMap(runtime);
162         } catch (OSEnvironmentReaderExcepton e) {
163             // If the environment variables are not accessible shouldn't terminate
164
runtime.getWarnings().warn(e.getMessage());
165         }
166         
167         if (environmentVariableMap == null) {
168             // if the environment variables can't be obtained, define an empty ENV
169
environmentVariableMap = new HashMap JavaDoc();
170         }
171         runtime.defineGlobalConstant("ENV", new StringOnlyRubyHash(runtime,
172                 environmentVariableMap, runtime.getNil()));
173
174         // Define System.getProperties() in ENV_JAVA
175
Map JavaDoc systemProps = environment.getSystemPropertiesMap(runtime);
176         runtime.defineGlobalConstant("ENV_JAVA", new StringOnlyRubyHash(
177                 runtime, systemProps, runtime.getNil()));
178         
179     }
180
181
182
183     // Accessor methods.
184

185     private static class LineNumberGlobalVariable extends GlobalVariable {
186         public LineNumberGlobalVariable(Ruby runtime, String JavaDoc 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 JavaDoc 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     // FIXME: move out of this class!
210
public static class StringGlobalVariable extends GlobalVariable {
211         public StringGlobalVariable(Ruby runtime, String JavaDoc 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 JavaDoc 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 JavaDoc 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             // thread.setSafeLevel(level);
258
return value;
259         }
260     }
261
262     private static class BacktraceGlobalVariable extends GlobalVariable {
263         public BacktraceGlobalVariable(Ruby runtime, String JavaDoc 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             //$@ returns nil if $!.backtrace is not an array
271
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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc name) {
344             super(runtime, name, null);
345         }
346         
347         /**
348          * @see org.jruby.runtime.GlobalVariable#get()
349          */

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 JavaDoc name) {
357             super(runtime, name, null);
358         }
359         
360         /**
361          * @see org.jruby.runtime.GlobalVariable#get()
362          */

363         public IRubyObject get() {
364             return runtime.getLoadService().getLoadedFeatures();
365         }
366     }
367 }
368
Popular Tags