001: /***** BEGIN LICENSE BLOCK *****
002: * Version: CPL 1.0/GPL 2.0/LGPL 2.1
003: *
004: * The contents of this file are subject to the Common Public
005: * License Version 1.0 (the "License"); you may not use this file
006: * except in compliance with the License. You may obtain a copy of
007: * the License at http://www.eclipse.org/legal/cpl-v10.html
008: *
009: * Software distributed under the License is distributed on an "AS
010: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
011: * implied. See the License for the specific language governing
012: * rights and limitations under the License.
013: *
014: * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
015: * Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
016: * Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
017: * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
018: * Copyright (C) 2005 Charles O Nutter <headius@headius.com>
019: *
020: * Alternatively, the contents of this file may be used under the terms of
021: * either of the GNU General Public License Version 2 or later (the "GPL"),
022: * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
023: * in which case the provisions of the GPL or the LGPL are applicable instead
024: * of those above. If you wish to allow use of your version of this file only
025: * under the terms of either the GPL or the LGPL, and not to allow others to
026: * use your version of this file under the terms of the CPL, indicate your
027: * decision by deleting the provisions above and replace them with the notice
028: * and other provisions required by the GPL or the LGPL. If you do not delete
029: * the provisions above, a recipient may use your version of this file under
030: * the terms of any one of the CPL, the GPL or the LGPL.
031: ***** END LICENSE BLOCK *****/package org.jruby.internal.runtime;
032:
033: import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
034: import java.util.HashMap;
035: import java.util.Iterator;
036: import java.util.Map;
037:
038: import org.jruby.Ruby;
039: import org.jruby.RubyProc;
040: import org.jruby.exceptions.RaiseException;
041: import org.jruby.runtime.IAccessor;
042: import org.jruby.runtime.builtin.IRubyObject;
043:
044: /**
045: *
046: * @author jpetersen
047: */
048: public class GlobalVariables {
049: private Ruby runtime;
050: private Map globalVariables = new ConcurrentHashMap();
051:
052: public GlobalVariables(Ruby runtime) {
053: this .runtime = runtime;
054: }
055:
056: public void define(String name, IAccessor accessor) {
057: assert name != null;
058: assert accessor != null;
059: assert name.startsWith("$");
060:
061: globalVariables.put(name, new GlobalVariable(accessor));
062: }
063:
064: public void defineReadonly(String name, IAccessor accessor) {
065: assert name != null;
066: assert accessor != null;
067: assert name.startsWith("$");
068:
069: globalVariables.put(name, new GlobalVariable(
070: new ReadonlyAccessor(name, accessor)));
071: }
072:
073: public boolean isDefined(String name) {
074: assert name != null;
075: assert name.startsWith("$");
076:
077: GlobalVariable variable = (GlobalVariable) globalVariables
078: .get(name);
079: return variable != null
080: && !(variable.getAccessor() instanceof UndefinedAccessor);
081: }
082:
083: /** Creates a new global variable which links to
084: * the oldName global variable.
085: *
086: * <b>WANRING</b> we are already using the 1.7.1 behaviour.
087: */
088: public void alias(String name, String oldName) {
089: assert name != null;
090: assert oldName != null;
091: assert name.startsWith("$");
092: assert oldName.startsWith("$");
093:
094: if (runtime.getSafeLevel() >= 4) {
095: throw runtime
096: .newSecurityError("Insecure: can't alias global variable");
097: }
098:
099: GlobalVariable oldVariable = createIfNotDefined(oldName);
100: GlobalVariable variable = (GlobalVariable) globalVariables
101: .get(name);
102:
103: if (variable != null && oldVariable != variable
104: && variable.isTracing()) {
105: throw new RaiseException(runtime, runtime
106: .getClass("RuntimeError"), "can't alias in tracer",
107: false);
108: }
109:
110: globalVariables.put(name, oldVariable);
111: }
112:
113: public IRubyObject get(String name) {
114: assert name != null;
115: assert name.startsWith("$");
116:
117: GlobalVariable variable = (GlobalVariable) globalVariables
118: .get(name);
119: if (variable != null) {
120: return variable.getAccessor().getValue();
121: }
122: runtime.getWarnings().warning(
123: "global variable `" + name + "' not initialized");
124: return runtime.getNil();
125: }
126:
127: public IRubyObject set(String name, IRubyObject value) {
128: assert name != null;
129: assert name.startsWith("$");
130:
131: if (runtime.getSafeLevel() >= 4) {
132: throw runtime
133: .newSecurityError("Insecure: can't change global variable value");
134: }
135:
136: GlobalVariable variable = createIfNotDefined(name);
137: IRubyObject result = variable.getAccessor().setValue(value);
138: variable.trace(value);
139: return result;
140: }
141:
142: public void setTraceVar(String name, RubyProc proc) {
143: assert name != null;
144: assert name.startsWith("$");
145:
146: GlobalVariable variable = createIfNotDefined(name);
147: variable.addTrace(proc);
148: }
149:
150: public boolean untraceVar(String name, IRubyObject command) {
151: assert name != null;
152: assert name.startsWith("$");
153:
154: if (isDefined(name)) {
155: GlobalVariable variable = (GlobalVariable) globalVariables
156: .get(name);
157: return variable.removeTrace(command);
158: }
159: return false;
160: }
161:
162: public void untraceVar(String name) {
163: assert name != null;
164: assert name.startsWith("$");
165:
166: if (isDefined(name)) {
167: GlobalVariable variable = (GlobalVariable) globalVariables
168: .get(name);
169: variable.removeTraces();
170: }
171: }
172:
173: public Iterator getNames() {
174: return globalVariables.keySet().iterator();
175: }
176:
177: private GlobalVariable createIfNotDefined(String name) {
178: GlobalVariable variable = (GlobalVariable) globalVariables
179: .get(name);
180: if (variable == null) {
181: variable = GlobalVariable.newUndefined(runtime, name);
182: globalVariables.put(name, variable);
183: }
184: return variable;
185: }
186: }
|