File README.md

Last commit: Sun May 31 21:52:03 2026 +0200	Jan Dankert	Adding maven info in README.
1 # Script Sandbox for Java 2 3 ## Overview 4 5 This is a script interpreter for Java. Custom code is parsed and interpreted in a sandbox. 6 7 The code syntax is similar to [Javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript). More precisely, it is a **subset of Javascript**. 8 9 ## Advantages 10 11 Tiny library with zero dependencies and a small no memory footprint. No need for a graal JS or Node JS engine. 12 13 ## Disadvantages 14 15 Probably slow. And by no means a complete javascript engine. 16 17 18 ## History 19 20 It was originally written in PHP for the [OpenRat CMS](http://www.openrat.de) and then migrated to Java. 21 22 23 ## Details 24 25 Scriptbox is an in-memory script interpreter for the Java Virtual Machine. The scripts are interpreted directly in the syntax tree and are **not** transpiled to native Bytecode. 26 27 A script is running in its sandbox, but it may access java objects if you provide appropriate classes (see below). 28 29 It consists of a lexer, a syntax parser and an interpreter. 30 31 The scripts may be used as a [domain specific language (DSL)](https://en.wikipedia.org/wiki/Domain-specific_language) in your application. 32 33 34 ## Get it 35 36 ### Maven 37 38 [JScriptbox is in Maven central](https://central.sonatype.com/artifact/de.jandankert.jscriptbox/jscriptbox). 39 40 In `pom.xml` 41 ```xml 42 <dependency> 43 <groupId>de.jandankert.jscriptbox</groupId> 44 <artifactId>jscriptbox</artifactId> 45 <version>1.0.0</version> 46 </dependency> 47 ``` 48 ### 49 50 51 ## Usage 52 53 Just use the `ScriptInterpreter` to run your code: 54 55 ```java 56 ScriptInterpreter interpreter = new ScriptInterpreter(); 57 interpreter.runCode( """ 58 write( "Hello, World" );" 59 """ ); 60 ``` 61 62 ### Get the output 63 64 For getting the standard output, simply call `getOutput()`: 65 66 ```java 67 ScriptInterpreter interpreter = new ScriptInterpreter(); 68 interpreter.runCode( "write( \"Hello, World\" );" ); 69 CharSequence output = interpreter.getOutput() ); // get the output "Hello, World" 70 ``` 71 72 ### Add classes to the script context 73 74 A very powerful approach is to make custom objects from your application available in the script context: 75 76 ```java 77 ScriptInterpreter interpreter = new ScriptInterpreter(); 78 interpreter.addToContext("bob",new Person("Bob")); 79 interpreter.runCode(""" 80 write( bob.greet() ); 81 """); 82 ``` 83 84 While in secure mode, your classes must implement the `Scriptable` interface, then your code may execute 85 86 myclass.method(); 87 88 ### Return values 89 90 ```java 91 ScriptInterpreter interpreter = new ScriptInterpreter(); 92 String returnValue = interpreter.runCode( code ); 93 ``` 94 95 ### Caching 96 You may cache the Script for multiple executions: 97 98 ```java 99 ScriptInterpreter interpreter = new ScriptInterpreter(); 100 interpreter.prepareCode(""" 101 return "Hello, World"; 102 """); 103 assertEquals("Hello, World", interpreter.run()); 104 assertEquals("Hello, World", interpreter.run()); 105 ``` 106 ## Syntax 107 108 The language syntax is a subset of javascript. 109 110 ## Features 111 112 ### comments 113 114 single line comments like 115 116 ```javascript 117 // this is a comment 118 ``` 119 120 and multiline comments like 121 122 ```javascript 123 124 /** 125 * this is a comment 126 */ 127 ``` 128 129 are supported 130 131 132 ### Text 133 134 ```javascript 135 write( "this is a 'string'" ); // writes to standard out 136 write( 'this is a "string"' ); // writes to standard out 137 ``` 138 139 140 ### Variables 141 142 variables and string concatenation: 143 144 ```javascript 145 age = 18; 146 write("my age is " + age ); 147 ``` 148 149 variables *may* be initialized with `let`,`var` or `const` but this is optional: 150 151 ```javascript 152 let age = 18; // "let" is optional and completely ignored 153 write("my age is " + age ); 154 ``` 155 156 every variable is _block scoped_. 157 158 159 ### Function scope 160 161 variables are valid for the current block. 162 163 ```javascript 164 age = 18; 165 166 function add() { 167 age = age + 1; 168 write( "next year, you are " + age ); // 19 169 } 170 add(); 171 172 write( "but this year you are " + age ); // 18 173 ``` 174 175 ### Function calls 176 177 Functions are auto-hoisted. 178 179 Example: 180 181 ```javascript 182 write( "powered by " + name() ); 183 184 function name() { 185 return "script sandbox"; 186 { 187 ``` 188 189 ### if / else 190 191 ```javascript 192 age = 17; 193 if ( age < 18 ) 194 write( "you are under 18" ); 195 else { 196 write( "you are already 18" ); 197 write( "you are allowed to enter" ); 198 } 199 ``` 200 201 ### Full arithmetic calculations 202 203 ```javascript 204 write( 1 + 2 * 3 ); // this resolves to 7 because of the operator priority 205 ``` 206 ### arrays and for loops 207 208 ```javascript 209 animals = Array.of('lion', 'ape', 'fish'); 210 211 for( animal of animals ) 212 write( animal + " is an animal." ); 213 ``` 214 215 ### Access object properties 216 217 ```javascript 218 write( "PI is " + Math.PI ); 219 ``` 220 ### throw an error 221 222 You may throw an error: 223 224 ```javascript 225 throw "this is an error"; 226 ``` 227 The message is thrown as a `ScriptUserDefinedException` and is able to be catched from the calling Java code. 228 229 Hint: try/catch blocks in scripts are **not** supported. 230 231 ## Template script 232 233 Remember JSP, Smarty, Twig or Freemarker? Check out this template parser with a JSP-like syntax: 234 235 ```html 236 <html> 237 <body> 238 <% age = 12; %> 239 Next year your age is <%= (age+1) %></br> 240 </body></html> 241 ``` 242 243 ### Usage 244 245 ```java 246 Template template = new Template(); 247 248 template.parseTemplate(""" 249 <html> 250 <body> 251 <% age = 12; %> 252 Next year your age is <%= (age+1) %></br> 253 </body> 254 </html> 255 """); 256 257 ScriptInterpreter interpreter = new ScriptInterpreter(); 258 interpreter.runCode(template.getScriptCode()); 259 ``` 260 261 262 ## Unsupported 263 264 - There is NO support for creating classes or objects. 265 - no asynchronous things like `async` or `await`. 266 - No try/catch 267 - No `window`, `document` or `navigator` objects 268 269 ## FAQ 270 271 _Does it generate Java sourcecode oder bytecode?_ 272 273 No. The Interpreter works in memory. There is no way to create Java code, even if it would be possible to implement. 274 275 _Is it slow?_ 276 277 Yes, maybe, because there is no cache and no compilation to bytecode. You may cache the syntax tree (see above). 278 279 _What about memory leaks_ 280 281 When the interpreter is cleaned up by the JVM garbage collector, all of the script is freed from the heap memory. 282 283 _Is it safe?_ 284 285 The code execution is sandboxed. No Java objects are directly available for the script. The default objects (Math, Number, Array) are safe. But please be careful if you are exposing your internal Java classes. 286 287 The Interpreter starts per default in secure mode, so only methods of objects, whose classes are marked as "Scriptable", can be called. 288 289 _Why did you do this?_ 290 291 Because it was possible ;) And I needed a sandboxed DSL (domain specific language) for my CMS.
Download README.md
History Sun, 31 May 2026 21:52:03 +0200 Jan Dankert Adding maven info in README. Thu, 21 May 2026 00:56:09 +0200 Jan Dankert Enhanced documentation Thu, 21 May 2026 00:44:13 +0200 Jan Dankert New: Special Exception for user-defined Errors. Sat, 28 Oct 2023 15:13:17 +0200 Jan Dankert All is complete, but the AST is broken at the moment.