View Javadoc

1   package delight.rhinosandox.internal;
2   
3   import com.google.common.base.Objects;
4   import delight.rhinosandox.RhinoSandbox;
5   import delight.rhinosandox.internal.SafeClassShutter;
6   import delight.rhinosandox.internal.SafeContext;
7   import delight.rhinosandox.internal.SafeWrapFactory;
8   import java.util.HashMap;
9   import java.util.Map;
10  import java.util.Set;
11  import org.eclipse.xtext.xbase.lib.Exceptions;
12  import org.eclipse.xtext.xbase.lib.InputOutput;
13  import org.mozilla.javascript.Context;
14  import org.mozilla.javascript.ContextFactory;
15  import org.mozilla.javascript.Scriptable;
16  import org.mozilla.javascript.ScriptableObject;
17  
18  @SuppressWarnings("all")
19  public class RhinoSandboxImpl implements RhinoSandbox {
20    private SafeContext contextFactory;
21    
22    private ScriptableObject globalScope;
23    
24    private ScriptableObject safeScope;
25    
26    private int instructionLimit;
27    
28    private long maxDuration;
29    
30    private boolean useSafeStandardObjects;
31    
32    private boolean sealScope;
33    
34    private final Map<String, Object> inScope;
35    
36    private SafeClassShutter classShutter;
37    
38    /**
39     * see https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scopes_and_Contexts
40     */
41    public void assertContextFactory() {
42      boolean _notEquals = (!Objects.equal(this.contextFactory, null));
43      if (_notEquals) {
44        return;
45      }
46      SafeContext _safeContext = new SafeContext();
47      this.contextFactory = _safeContext;
48      boolean _hasExplicitGlobal = ContextFactory.hasExplicitGlobal();
49      boolean _not = (!_hasExplicitGlobal);
50      if (_not) {
51        ContextFactory.initGlobal(this.contextFactory);
52      }
53      this.contextFactory.maxInstructions = this.instructionLimit;
54      this.contextFactory.maxRuntimeInMs = this.maxDuration;
55      try {
56        final Context context = this.contextFactory.enterContext();
57        ScriptableObject _initStandardObjects = context.initStandardObjects(null, false);
58        this.globalScope = _initStandardObjects;
59        Set<Map.Entry<String, Object>> _entrySet = this.inScope.entrySet();
60        for (final Map.Entry<String, Object> entry : _entrySet) {
61          String _key = entry.getKey();
62          Object _value = entry.getValue();
63          Scriptable _object = Context.toObject(_value, this.globalScope);
64          this.globalScope.put(_key, this.globalScope, _object);
65        }
66      } finally {
67        Context.exit();
68      }
69    }
70    
71    public void assertSafeScope(final Context context) {
72      boolean _notEquals = (!Objects.equal(this.safeScope, null));
73      if (_notEquals) {
74        return;
75      }
76      if (this.useSafeStandardObjects) {
77        ScriptableObject _initSafeStandardObjects = context.initSafeStandardObjects(this.globalScope, true);
78        this.safeScope = _initSafeStandardObjects;
79        return;
80      }
81      context.setClassShutter(this.classShutter);
82      SafeWrapFactory _safeWrapFactory = new SafeWrapFactory();
83      context.setWrapFactory(_safeWrapFactory);
84      this.safeScope = this.globalScope;
85    }
86    
87    @Override
88    public Object evalWithGlobalScope(final String sourceName, final String js) {
89      this.assertContextFactory();
90      try {
91        final Context context = this.contextFactory.enterContext();
92        return context.evaluateString(this.globalScope, js, sourceName, 1, null);
93      } finally {
94        Context.exit();
95      }
96    }
97    
98    @Override
99    public Object eval(final String sourceName, final String js, final Map<String, Object> variables) {
100     this.assertContextFactory();
101     try {
102       final Context context = this.contextFactory.enterContext();
103       this.assertSafeScope(context);
104       InputOutput.<String>println("doing it");
105       final Scriptable instanceScope = context.newObject(this.safeScope);
106       instanceScope.setPrototype(this.safeScope);
107       instanceScope.setParentScope(null);
108       Set<Map.Entry<String, Object>> _entrySet = variables.entrySet();
109       for (final Map.Entry<String, Object> entry : _entrySet) {
110         {
111           Object _value = entry.getValue();
112           Class<?> _class = _value.getClass();
113           this.allow(_class);
114           String _key = entry.getKey();
115           Object _value_1 = entry.getValue();
116           Scriptable _object = Context.toObject(_value_1, instanceScope);
117           instanceScope.put(_key, instanceScope, _object);
118         }
119       }
120       return context.evaluateString(instanceScope, js, sourceName, 1, null);
121     } finally {
122       Context.exit();
123     }
124   }
125   
126   @Override
127   public Object eval(final String sourceName, final String js) {
128     HashMap<String, Object> _hashMap = new HashMap<String, Object>();
129     return this.eval(sourceName, js, _hashMap);
130   }
131   
132   @Override
133   public RhinoSandbox setInstructionLimit(final int limit) {
134     RhinoSandboxImpl _xblockexpression = null;
135     {
136       this.instructionLimit = limit;
137       boolean _notEquals = (!Objects.equal(this.contextFactory, null));
138       if (_notEquals) {
139         this.contextFactory.maxInstructions = this.instructionLimit;
140       }
141       _xblockexpression = this;
142     }
143     return _xblockexpression;
144   }
145   
146   /**
147    * Sets the maximum allowed duration for scripts.
148    */
149   @Override
150   public RhinoSandbox setMaxDuration(final int limitInMs) {
151     RhinoSandboxImpl _xblockexpression = null;
152     {
153       this.maxDuration = limitInMs;
154       boolean _notEquals = (!Objects.equal(this.contextFactory, null));
155       if (_notEquals) {
156         this.contextFactory.maxRuntimeInMs = this.maxDuration;
157       }
158       _xblockexpression = this;
159     }
160     return _xblockexpression;
161   }
162   
163   @Override
164   public RhinoSandbox setUseSafeStandardObjects(final boolean useSafeStandardObjects) {
165     RhinoSandboxImpl _xblockexpression = null;
166     {
167       this.useSafeStandardObjects = useSafeStandardObjects;
168       _xblockexpression = this;
169     }
170     return _xblockexpression;
171   }
172   
173   @Override
174   public RhinoSandbox allow(final Class<?> clazz) {
175     RhinoSandboxImpl _xblockexpression = null;
176     {
177       String _name = clazz.getName();
178       this.classShutter.allowedClasses.add(_name);
179       _xblockexpression = this;
180     }
181     return _xblockexpression;
182   }
183   
184   @Override
185   public RhinoSandbox inject(final Class<ScriptableObject> clazz) {
186     try {
187       RhinoSandboxImpl _xblockexpression = null;
188       {
189         ScriptableObject.<ScriptableObject>defineClass(this.globalScope, clazz);
190         this.allow(clazz);
191         _xblockexpression = this;
192       }
193       return _xblockexpression;
194     } catch (Throwable _e) {
195       throw Exceptions.sneakyThrow(_e);
196     }
197   }
198   
199   @Override
200   public RhinoSandbox inject(final String variableName, final Object object) {
201     RhinoSandboxImpl _xblockexpression = null;
202     {
203       this.injectInt(variableName, object);
204       Class<?> _class = object.getClass();
205       this.allow(_class);
206       _xblockexpression = this;
207     }
208     return _xblockexpression;
209   }
210   
211   private void injectInt(final String variableName, final Object object) {
212     boolean _containsKey = this.inScope.containsKey(variableName);
213     if (_containsKey) {
214       throw new IllegalArgumentException(
215         (("A variable with the name [" + variableName) + "] has already been defined."));
216     }
217     boolean _equals = Objects.equal(this.contextFactory, null);
218     if (_equals) {
219       this.inScope.put(variableName, object);
220     } else {
221       try {
222         this.contextFactory.enterContext();
223         Scriptable _object = Context.toObject(object, this.globalScope);
224         this.globalScope.put(variableName, this.globalScope, _object);
225       } finally {
226         Context.exit();
227       }
228     }
229   }
230   
231   public RhinoSandboxImpl() {
232     HashMap<String, Object> _hashMap = new HashMap<String, Object>();
233     this.inScope = _hashMap;
234     this.useSafeStandardObjects = false;
235     this.sealScope = true;
236     SafeClassShutter _safeClassShutter = new SafeClassShutter();
237     this.classShutter = _safeClassShutter;
238   }
239   
240   @Override
241   public RhinoSandbox setUseSealedScope(final boolean value) {
242     this.sealScope = value;
243     return this;
244   }
245 }