src/jdk/nashorn/api/scripting/ScriptObjectMirror.java

Wed, 16 Jan 2013 17:58:51 +0530

author
sundar
date
Wed, 16 Jan 2013 17:58:51 +0530
changeset 33
80447df16322
parent 7
5a1b0714df0e
child 38
c887baec012a
permissions
-rw-r--r--

8006412: Improve toString method of ScriptObjectMirror class
Reviewed-by: jlaskey, lagergren

jlaskey@3 1 /*
jlaskey@7 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
jlaskey@3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jlaskey@3 4 *
jlaskey@3 5 * This code is free software; you can redistribute it and/or modify it
jlaskey@3 6 * under the terms of the GNU General Public License version 2 only, as
jlaskey@3 7 * published by the Free Software Foundation. Oracle designates this
jlaskey@3 8 * particular file as subject to the "Classpath" exception as provided
jlaskey@3 9 * by Oracle in the LICENSE file that accompanied this code.
jlaskey@3 10 *
jlaskey@3 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jlaskey@3 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jlaskey@3 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jlaskey@3 14 * version 2 for more details (a copy is included in the LICENSE file that
jlaskey@3 15 * accompanied this code).
jlaskey@3 16 *
jlaskey@3 17 * You should have received a copy of the GNU General Public License version
jlaskey@3 18 * 2 along with this work; if not, write to the Free Software Foundation,
jlaskey@3 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jlaskey@3 20 *
jlaskey@3 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jlaskey@3 22 * or visit www.oracle.com if you need additional information or have any
jlaskey@3 23 * questions.
jlaskey@3 24 */
jlaskey@3 25
jlaskey@3 26 package jdk.nashorn.api.scripting;
jlaskey@3 27
jlaskey@3 28 import java.util.AbstractMap;
jlaskey@3 29 import java.util.ArrayList;
jlaskey@3 30 import java.util.Collection;
jlaskey@3 31 import java.util.Collections;
jlaskey@3 32 import java.util.HashSet;
jlaskey@3 33 import java.util.Iterator;
jlaskey@3 34 import java.util.List;
jlaskey@3 35 import java.util.Map;
jlaskey@3 36 import java.util.Set;
jlaskey@3 37 import java.util.concurrent.Callable;
jlaskey@3 38 import jdk.nashorn.internal.runtime.Context;
jlaskey@3 39 import jdk.nashorn.internal.runtime.ScriptFunction;
jlaskey@3 40 import jdk.nashorn.internal.runtime.ScriptObject;
sundar@33 41 import jdk.nashorn.internal.runtime.ScriptRuntime;
jlaskey@3 42 import netscape.javascript.JSObject;
jlaskey@3 43
jlaskey@3 44 /**
jlaskey@3 45 * Mirror object that wraps a given ScriptObject instance. User can
jlaskey@3 46 * access ScriptObject via the java.util.Map interface.
jlaskey@3 47 */
jlaskey@3 48 final class ScriptObjectMirror extends JSObject implements Map<Object, Object> {
jlaskey@3 49 private final ScriptObject sobj;
jlaskey@3 50 private final ScriptObject global;
jlaskey@3 51
jlaskey@3 52 ScriptObjectMirror(final ScriptObject sobj, final ScriptObject global) {
jlaskey@3 53 this.sobj = sobj;
jlaskey@3 54 this.global = global;
jlaskey@3 55 }
jlaskey@3 56
jlaskey@3 57 @Override
jlaskey@3 58 public boolean equals(final Object other) {
jlaskey@3 59 if (other instanceof ScriptObjectMirror) {
jlaskey@3 60 return sobj.equals(((ScriptObjectMirror)other).sobj);
jlaskey@3 61 }
jlaskey@3 62
jlaskey@3 63 return false;
jlaskey@3 64 }
jlaskey@3 65
jlaskey@3 66 @Override
jlaskey@3 67 public int hashCode() {
jlaskey@3 68 return sobj.hashCode();
jlaskey@3 69 }
jlaskey@3 70
sundar@33 71 @Override
sundar@33 72 public String toString() {
sundar@33 73 return inGlobal(new Callable<String>() {
sundar@33 74 @Override
sundar@33 75 public String call() {
sundar@33 76 return ScriptRuntime.safeToString(sobj);
sundar@33 77 }
sundar@33 78 });
sundar@33 79 }
sundar@33 80
jlaskey@3 81 private <V> V inGlobal(final Callable<V> callable) {
jlaskey@3 82 final ScriptObject oldGlobal = Context.getGlobal();
jlaskey@3 83 final boolean globalChanged = (oldGlobal != global);
jlaskey@3 84 if (globalChanged) {
jlaskey@3 85 NashornScriptEngine.setNashornGlobal(global);
jlaskey@3 86 }
jlaskey@3 87 try {
jlaskey@3 88 return callable.call();
jlaskey@3 89 } catch (final RuntimeException e) {
jlaskey@3 90 throw e;
jlaskey@3 91 } catch (final Exception e) {
jlaskey@3 92 throw new AssertionError("Cannot happen", e);
jlaskey@3 93 } finally {
jlaskey@3 94 if (globalChanged) {
jlaskey@3 95 NashornScriptEngine.setNashornGlobal(oldGlobal);
jlaskey@3 96 }
jlaskey@3 97 }
jlaskey@3 98 }
jlaskey@3 99
jlaskey@3 100 // JSObject methods
jlaskey@3 101 @Override
jlaskey@3 102 public Object call(final String methodName, final Object args[]) {
jlaskey@3 103 final Object val = sobj.get(methodName);
jlaskey@3 104 final ScriptObject oldGlobal = Context.getGlobal();
jlaskey@3 105 final boolean globalChanged = (oldGlobal != global);
jlaskey@3 106
jlaskey@3 107 if (val instanceof ScriptFunction) {
jlaskey@3 108 final Object[] modifiedArgs = unwrapArray(args, global);
jlaskey@3 109 if (modifiedArgs != null) {
jlaskey@3 110 for (int i = 0; i < modifiedArgs.length; i++) {
jlaskey@3 111 final Object arg = modifiedArgs[i];
jlaskey@3 112 if (arg instanceof ScriptObject) {
jlaskey@3 113 modifiedArgs[i] = wrap(arg, oldGlobal);
jlaskey@3 114 }
jlaskey@3 115 }
jlaskey@3 116 }
jlaskey@3 117
jlaskey@3 118 try {
jlaskey@3 119 if (globalChanged) {
jlaskey@3 120 NashornScriptEngine.setNashornGlobal(global);
jlaskey@3 121 }
jlaskey@3 122 return wrap(((ScriptFunction)val).invoke(sobj, modifiedArgs), global);
jlaskey@3 123 } catch (final RuntimeException | Error e) {
jlaskey@3 124 throw e;
jlaskey@3 125 } catch (final Throwable t) {
jlaskey@3 126 throw new RuntimeException(t);
jlaskey@3 127 } finally {
jlaskey@3 128 if (globalChanged) {
jlaskey@3 129 NashornScriptEngine.setNashornGlobal(oldGlobal);
jlaskey@3 130 }
jlaskey@3 131 }
jlaskey@3 132 }
jlaskey@3 133
jlaskey@3 134 throw new RuntimeException("No such method: " + methodName);
jlaskey@3 135 }
jlaskey@3 136
jlaskey@3 137 @Override
jlaskey@3 138 public Object eval(final String s) {
jlaskey@3 139 return inGlobal(new Callable<Object>() {
jlaskey@3 140 @Override
jlaskey@3 141 public Object call() {
jlaskey@3 142 return wrap(global.getContext().eval(global, s, null, null, false), global);
jlaskey@3 143 }
jlaskey@3 144 });
jlaskey@3 145 }
jlaskey@3 146
jlaskey@3 147 @Override
jlaskey@3 148 public Object getMember(final String name) {
jlaskey@3 149 return get(name);
jlaskey@3 150 }
jlaskey@3 151
jlaskey@3 152 @Override
jlaskey@3 153 public Object getSlot(final int index) {
jlaskey@3 154 return get(Integer.valueOf(index));
jlaskey@3 155 }
jlaskey@3 156
jlaskey@3 157 @Override
jlaskey@3 158 public void removeMember(final String name) {
jlaskey@3 159 remove(name);
jlaskey@3 160 }
jlaskey@3 161
jlaskey@3 162 @Override
jlaskey@3 163 public void setMember(final String name, final Object value) {
jlaskey@3 164 put(name, wrap(value, Context.getGlobal()));
jlaskey@3 165 }
jlaskey@3 166
jlaskey@3 167 @Override
jlaskey@3 168 public void setSlot(final int index, final Object value) {
jlaskey@3 169 put(Integer.valueOf(index), wrap(value, Context.getGlobal()));
jlaskey@3 170 }
jlaskey@3 171
jlaskey@3 172 @Override
jlaskey@3 173 public void clear() {
jlaskey@3 174 inGlobal(new Callable<Object>() {
jlaskey@3 175 @Override public Object call() {
jlaskey@3 176 sobj.clear();
jlaskey@3 177 return null;
jlaskey@3 178 }});
jlaskey@3 179 }
jlaskey@3 180
jlaskey@3 181 @Override
jlaskey@3 182 public boolean containsKey(final Object key) {
jlaskey@3 183 return inGlobal(new Callable<Boolean>() {
jlaskey@3 184 @Override public Boolean call() {
jlaskey@3 185 return sobj.containsKey(unwrap(key, global));
jlaskey@3 186 }});
jlaskey@3 187 }
jlaskey@3 188
jlaskey@3 189 @Override
jlaskey@3 190 public boolean containsValue(final Object value) {
jlaskey@3 191 return inGlobal(new Callable<Boolean>() {
jlaskey@3 192 @Override public Boolean call() {
jlaskey@3 193 return sobj.containsValue(unwrap(value, global));
jlaskey@3 194 }});
jlaskey@3 195 }
jlaskey@3 196
jlaskey@3 197 @Override
jlaskey@3 198 public Set<Map.Entry<Object, Object>> entrySet() {
jlaskey@3 199 return inGlobal(new Callable<Set<Map.Entry<Object, Object>>>() {
jlaskey@3 200 @Override public Set<Map.Entry<Object, Object>> call() {
jlaskey@3 201 final Iterator<String> iter = sobj.propertyIterator();
jlaskey@3 202 final Set<Map.Entry<Object, Object>> entries = new HashSet<>();
jlaskey@3 203
jlaskey@3 204 while (iter.hasNext()) {
jlaskey@3 205 final Object key = wrap(iter.next(), global);
jlaskey@3 206 final Object value = wrap(sobj.get(key), global);
jlaskey@3 207 entries.add(new AbstractMap.SimpleImmutableEntry<>(key, value));
jlaskey@3 208 }
jlaskey@3 209
jlaskey@3 210 return Collections.unmodifiableSet(entries);
jlaskey@3 211 }
jlaskey@3 212 });
jlaskey@3 213 }
jlaskey@3 214
jlaskey@3 215 @Override
jlaskey@3 216 public Object get(final Object key) {
jlaskey@3 217 return inGlobal(new Callable<Object>() { @Override public Object call() {
jlaskey@3 218 return wrap(sobj.get(key), global);
jlaskey@3 219 }});
jlaskey@3 220 }
jlaskey@3 221
jlaskey@3 222 @Override
jlaskey@3 223 public boolean isEmpty() {
jlaskey@3 224 return inGlobal(new Callable<Boolean>() { @Override public Boolean call() {
jlaskey@3 225 return sobj.isEmpty();
jlaskey@3 226 }});
jlaskey@3 227 }
jlaskey@3 228
jlaskey@3 229 @Override
jlaskey@3 230 public Set<Object> keySet() {
jlaskey@3 231 return inGlobal(new Callable<Set<Object>>() { @Override public Set<Object> call() {
jlaskey@3 232 final Iterator<String> iter = sobj.propertyIterator();
jlaskey@3 233 final Set<Object> keySet = new HashSet<>();
jlaskey@3 234
jlaskey@3 235 while (iter.hasNext()) {
jlaskey@3 236 keySet.add(wrap(iter.next(), global));
jlaskey@3 237 }
jlaskey@3 238
jlaskey@3 239 return Collections.unmodifiableSet(keySet);
jlaskey@3 240 }});
jlaskey@3 241 }
jlaskey@3 242
jlaskey@3 243 @Override
jlaskey@3 244 public Object put(final Object key, final Object value) {
jlaskey@3 245 return inGlobal(new Callable<Object>() {
jlaskey@3 246 @Override public Object call() {
jlaskey@3 247 return sobj.put(unwrap(key, global), unwrap(value, global));
jlaskey@3 248 }});
jlaskey@3 249 }
jlaskey@3 250
jlaskey@3 251 @Override
jlaskey@3 252 public void putAll(final Map<?, ?> map) {
jlaskey@3 253 final boolean strict = sobj.getContext()._strict;
jlaskey@3 254 inGlobal(new Callable<Object>() { @Override public Object call() {
jlaskey@3 255 for (final Map.Entry<?, ?> entry : map.entrySet()) {
jlaskey@3 256 sobj.set(unwrap(entry.getKey(), global), unwrap(entry.getValue(), global), strict);
jlaskey@3 257 }
jlaskey@3 258 return null;
jlaskey@3 259 }});
jlaskey@3 260 }
jlaskey@3 261
jlaskey@3 262 @Override
jlaskey@3 263 public Object remove(final Object key) {
jlaskey@3 264 return inGlobal(new Callable<Object>() {
jlaskey@3 265 @Override public Object call() {
jlaskey@3 266 return wrap(sobj.remove(unwrap(key, global)), global);
jlaskey@3 267 }
jlaskey@3 268 });
jlaskey@3 269 }
jlaskey@3 270
jlaskey@3 271 @Override
jlaskey@3 272 public int size() {
jlaskey@3 273 return inGlobal(new Callable<Integer>() {
jlaskey@3 274 @Override public Integer call() {
jlaskey@3 275 return sobj.size();
jlaskey@3 276 }
jlaskey@3 277 });
jlaskey@3 278 }
jlaskey@3 279
jlaskey@3 280 @Override
jlaskey@3 281 public Collection<Object> values() {
jlaskey@3 282 return inGlobal(new Callable<Collection<Object>>() { @Override public Collection<Object> call() {
jlaskey@3 283 final List<Object> values = new ArrayList<>(size());
jlaskey@3 284 final Iterator<Object> iter = sobj.valueIterator();
jlaskey@3 285
jlaskey@3 286 while (iter.hasNext()) {
jlaskey@3 287 values.add(wrap(iter.next(), global));
jlaskey@3 288 }
jlaskey@3 289
jlaskey@3 290 return Collections.unmodifiableList(values);
jlaskey@3 291 }});
jlaskey@3 292 }
jlaskey@3 293
jlaskey@3 294 static Object wrap(final Object obj, final ScriptObject homeGlobal) {
jlaskey@3 295 return (obj instanceof ScriptObject) ? new ScriptObjectMirror((ScriptObject)obj, homeGlobal) : obj;
jlaskey@3 296 }
jlaskey@3 297
jlaskey@3 298 static Object unwrap(final Object obj, final ScriptObject homeGlobal) {
jlaskey@3 299 if (obj instanceof ScriptObjectMirror) {
jlaskey@3 300 final ScriptObjectMirror mirror = (ScriptObjectMirror)obj;
jlaskey@3 301 return (mirror.global == homeGlobal)? mirror.sobj : obj;
jlaskey@3 302 }
jlaskey@3 303
jlaskey@3 304 return obj;
jlaskey@3 305 }
jlaskey@3 306
jlaskey@3 307 static Object[] wrapArray(final Object[] args, final ScriptObject homeGlobal) {
jlaskey@3 308 if (args == null || args.length == 0) {
jlaskey@3 309 return args;
jlaskey@3 310 }
jlaskey@3 311
jlaskey@3 312 final Object[] newArgs = new Object[args.length];
jlaskey@3 313 int index = 0;
jlaskey@3 314 for (final Object obj : args) {
jlaskey@3 315 newArgs[index] = wrap(obj, homeGlobal);
jlaskey@3 316 index++;
jlaskey@3 317 }
jlaskey@3 318 return newArgs;
jlaskey@3 319 }
jlaskey@3 320
jlaskey@3 321 static Object[] unwrapArray(final Object[] args, final ScriptObject homeGlobal) {
jlaskey@3 322 if (args == null || args.length == 0) {
jlaskey@3 323 return args;
jlaskey@3 324 }
jlaskey@3 325
jlaskey@3 326 final Object[] newArgs = new Object[args.length];
jlaskey@3 327 int index = 0;
jlaskey@3 328 for (final Object obj : args) {
jlaskey@3 329 newArgs[index] = unwrap(obj, homeGlobal);
jlaskey@3 330 index++;
jlaskey@3 331 }
jlaskey@3 332 return newArgs;
jlaskey@3 333 }
jlaskey@3 334 }

mercurial