1 /* 2 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.script; 27 28 import java.util.*; 29 import java.io.*; 30 31 /** 32 * Simple implementation of ScriptContext. 33 * 34 * @author Mike Grogan 35 * @since 1.6 36 */ 37 public class SimpleScriptContext implements ScriptContext { 38 39 /** 40 * This is the writer to be used to output from scripts. 41 * By default, a <code>PrintWriter</code> based on <code>System.out</code> 42 * is used. Accessor methods getWriter, setWriter are used to manage 43 * this field. 44 * @see java.lang.System#out 45 * @see java.io.PrintWriter 46 */ 47 protected Writer writer; 48 49 /** 50 * This is the writer to be used to output errors from scripts. 51 * By default, a <code>PrintWriter</code> based on <code>System.err</code> is 52 * used. Accessor methods getErrorWriter, setErrorWriter are used to manage 53 * this field. 54 * @see java.lang.System#err 55 * @see java.io.PrintWriter 56 */ 57 protected Writer errorWriter; 58 59 /** 60 * This is the reader to be used for input from scripts. 61 * By default, a <code>InputStreamReader</code> based on <code>System.in</code> 62 * is used and default charset is used by this reader. Accessor methods 63 * getReader, setReader are used to manage this field. 64 * @see java.lang.System#in 65 * @see java.io.InputStreamReader 66 */ 67 protected Reader reader; 68 69 70 /** 71 * This is the engine scope bindings. 72 * By default, a <code>SimpleBindings</code> is used. Accessor 73 * methods setBindings, getBindings are used to manage this field. 74 * @see SimpleBindings 75 */ 76 protected Bindings engineScope; 77 78 /** 79 * This is the global scope bindings. 80 * By default, a null value (which means no global scope) is used. Accessor 81 * methods setBindings, getBindings are used to manage this field. 82 */ 83 protected Bindings globalScope; 84 85 /** 86 * Create a {@code SimpleScriptContext}. 87 */ 88 public SimpleScriptContext() { 89 engineScope = new SimpleBindings(); 90 globalScope = null; 91 reader = new InputStreamReader(System.in); 92 writer = new PrintWriter(System.out , true); 93 errorWriter = new PrintWriter(System.err, true); 94 } 95 96 /** 97 * Sets a <code>Bindings</code> of attributes for the given scope. If the value 98 * of scope is <code>ENGINE_SCOPE</code> the given <code>Bindings</code> replaces the 99 * <code>engineScope</code> field. If the value 100 * of scope is <code>GLOBAL_SCOPE</code> the given <code>Bindings</code> replaces the 101 * <code>globalScope</code> field. 102 * 103 * @param bindings The <code>Bindings</code> of attributes to set. 104 * @param scope The value of the scope in which the attributes are set. 105 * 106 * @throws IllegalArgumentException if scope is invalid. 107 * @throws NullPointerException if the value of scope is <code>ENGINE_SCOPE</code> and 108 * the specified <code>Bindings</code> is null. 109 */ 110 public void setBindings(Bindings bindings, int scope) { 111 112 switch (scope) { 113 114 case ENGINE_SCOPE: 115 if (bindings == null) { 116 throw new NullPointerException("Engine scope cannot be null."); 117 } 118 engineScope = bindings; 119 break; 120 case GLOBAL_SCOPE: 121 globalScope = bindings; 122 break; 123 default: 124 throw new IllegalArgumentException("Invalid scope value."); 125 } 126 } 127 128 129 /** 130 * Retrieves the value of the attribute with the given name in 131 * the scope occurring earliest in the search order. The order 132 * is determined by the numeric value of the scope parameter (lowest 133 * scope values first.) 134 * 135 * @param name The name of the attribute to retrieve. 136 * @return The value of the attribute in the lowest scope for 137 * which an attribute with the given name is defined. Returns 138 * null if no attribute with the name exists in any scope. 139 * @throws NullPointerException if the name is null. 140 * @throws IllegalArgumentException if the name is empty. 141 */ 142 public Object getAttribute(String name) { 143 checkName(name); 144 if (engineScope.containsKey(name)) { 145 return getAttribute(name, ENGINE_SCOPE); 146 } else if (globalScope != null && globalScope.containsKey(name)) { 147 return getAttribute(name, GLOBAL_SCOPE); 148 } 149 150 return null; 151 } 152 153 /** 154 * Gets the value of an attribute in a given scope. 155 * 156 * @param name The name of the attribute to retrieve. 157 * @param scope The scope in which to retrieve the attribute. 158 * @return The value of the attribute. Returns <code>null</code> is the name 159 * does not exist in the given scope. 160 * 161 * @throws IllegalArgumentException 162 * if the name is empty or if the value of scope is invalid. 163 * @throws NullPointerException if the name is null. 164 */ 165 public Object getAttribute(String name, int scope) { 166 checkName(name); 167 switch (scope) { 168 169 case ENGINE_SCOPE: 170 return engineScope.get(name); 171 172 case GLOBAL_SCOPE: 173 if (globalScope != null) { 174 return globalScope.get(name); 175 } 176 return null; 177 178 default: 179 throw new IllegalArgumentException("Illegal scope value."); 180 } 181 } 182 183 /** 184 * Remove an attribute in a given scope. 185 * 186 * @param name The name of the attribute to remove 187 * @param scope The scope in which to remove the attribute 188 * 189 * @return The removed value. 190 * @throws IllegalArgumentException 191 * if the name is empty or if the scope is invalid. 192 * @throws NullPointerException if the name is null. 193 */ 194 public Object removeAttribute(String name, int scope) { 195 checkName(name); 196 switch (scope) { 197 198 case ENGINE_SCOPE: 199 if (getBindings(ENGINE_SCOPE) != null) { 200 return getBindings(ENGINE_SCOPE).remove(name); 201 } 202 return null; 203 204 case GLOBAL_SCOPE: 205 if (getBindings(GLOBAL_SCOPE) != null) { 206 return getBindings(GLOBAL_SCOPE).remove(name); 207 } 208 return null; 209 210 default: 211 throw new IllegalArgumentException("Illegal scope value."); 212 } 213 } 214 215 /** 216 * Sets the value of an attribute in a given scope. 217 * 218 * @param name The name of the attribute to set 219 * @param value The value of the attribute 220 * @param scope The scope in which to set the attribute 221 * 222 * @throws IllegalArgumentException 223 * if the name is empty or if the scope is invalid. 224 * @throws NullPointerException if the name is null. 225 */ 226 public void setAttribute(String name, Object value, int scope) { 227 checkName(name); 228 switch (scope) { 229 230 case ENGINE_SCOPE: 231 engineScope.put(name, value); 232 return; 233 234 case GLOBAL_SCOPE: 235 if (globalScope != null) { 236 globalScope.put(name, value); 237 } 238 return; 239 240 default: 241 throw new IllegalArgumentException("Illegal scope value."); 242 } 243 } 244 245 /** {@inheritDoc} */ 246 public Writer getWriter() { 247 return writer; 248 } 249 250 /** {@inheritDoc} */ 251 public Reader getReader() { 252 return reader; 253 } 254 255 /** {@inheritDoc} */ 256 public void setReader(Reader reader) { 257 this.reader = reader; 258 } 259 260 /** {@inheritDoc} */ 261 public void setWriter(Writer writer) { 262 this.writer = writer; 263 } 264 265 /** {@inheritDoc} */ 266 public Writer getErrorWriter() { 267 return errorWriter; 268 } 269 270 /** {@inheritDoc} */ 271 public void setErrorWriter(Writer writer) { 272 this.errorWriter = writer; 273 } 274 275 /** 276 * Get the lowest scope in which an attribute is defined. 277 * @param name Name of the attribute 278 * . 279 * @return The lowest scope. Returns -1 if no attribute with the given 280 * name is defined in any scope. 281 * @throws NullPointerException if name is null. 282 * @throws IllegalArgumentException if name is empty. 283 */ 284 public int getAttributesScope(String name) { 285 checkName(name); 286 if (engineScope.containsKey(name)) { 287 return ENGINE_SCOPE; 288 } else if (globalScope != null && globalScope.containsKey(name)) { 289 return GLOBAL_SCOPE; 290 } else { 291 return -1; 292 } 293 } 294 295 /** 296 * Returns the value of the <code>engineScope</code> field if specified scope is 297 * <code>ENGINE_SCOPE</code>. Returns the value of the <code>globalScope</code> field if the specified scope is 298 * <code>GLOBAL_SCOPE</code>. 299 * 300 * @param scope The specified scope 301 * @return The value of either the <code>engineScope</code> or <code>globalScope</code> field. 302 * @throws IllegalArgumentException if the value of scope is invalid. 303 */ 304 public Bindings getBindings(int scope) { 305 if (scope == ENGINE_SCOPE) { 306 return engineScope; 307 } else if (scope == GLOBAL_SCOPE) { 308 return globalScope; 309 } else { 310 throw new IllegalArgumentException("Illegal scope value."); 311 } 312 } 313 314 /** {@inheritDoc} */ 315 public List<Integer> getScopes() { 316 return scopes; 317 } 318 319 private void checkName(String name) { 320 Objects.requireNonNull(name); 321 if (name.isEmpty()) { 322 throw new IllegalArgumentException("name cannot be empty"); 323 } 324 } 325 326 private static List<Integer> scopes; 327 static { 328 scopes = new ArrayList<Integer>(2); 329 scopes.add(ENGINE_SCOPE); 330 scopes.add(GLOBAL_SCOPE); 331 scopes = Collections.unmodifiableList(scopes); 332 } 333 }