Subversion Repositories pub

Compare Revisions

No changes between revisions

Ignore whitespace Rev 64 → Rev 62

/pluggablejs/trunk/TODO
File deleted
/pluggablejs/trunk/Makefile
5,7 → 5,7
 
buildnum=$(shell grep 'build.number' build.num | cut -d'=' -f2)
version=$(shell grep '<property name="version"' build.xml | sed -r 's/.*value="([^"]*)".*/\1/')
jarbasename=pluggablejs-$(version)build$(buildnum).jar
jarbasename=pluggablejs-$(version)-build$(buildnum).jar
 
bindir=$(DESTDIR)/$(prefix)/bin
 
/pluggablejs/trunk/build.num
1,3 → 1,3
#Build Number for ANT. Do not edit!
#Wed Jul 02 21:19:34 CEST 2008
build.number=34
#Mon Jun 30 20:53:31 CEST 2008
build.number=33
/pluggablejs/trunk/build.xml
10,7 → 10,7
<property name="depends" location="lib"/>
 
<property name="version" value="1.1.0"/>
<property name="jarbasename" value="pluggablejs-${version}build" /><!-- followed by build.number, can't resolve yet -->
<property name="jarbasename" value="pluggablejs-${version}-build" /><!-- followed by build.number, can't resolve yet -->
 
<target name="init">
<!-- Create timestamp, sets TODAY (full, human), DSTAMP (yyyymmdd) and
/pluggablejs/trunk/src/net/outlyer/plugins/Internal.java
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:keywords
-Rev Id Date
\ No newline at end of property
/pluggablejs/trunk/src/net/outlyer/plugins/Functor.java
File deleted
Property changes:
Deleted: svn:keywords
-Rev Id Date
\ No newline at end of property
/pluggablejs/trunk/src/net/outlyer/plugins/Shell.java
31,14 → 31,11
import javax.script.ScriptException;
import net.outlyer.plugins.utils.*;
 
import static net.outlyer.plugins.Internal.getInternalObjectFieldName;
 
/**
* Sample shell for tests, or scripts.
* Files passed as arguments will be loaded and executed.
*/
public final class Shell {
 
public static void interactive(final PluginEnvironment pe) {
try {
final Sandbox sandbox = pe.createSandbox(null);
46,45 → 43,19
 
final Input in = new Input();
final Output out = new Output();
System.err.printf("pluggablejsShell v%d.%d.%d\n", API.VERSION, API.MIN_SUPPORTED_VERSION, API.REVISION);
System.err.printf("pluggablejsShell v%d.%d.%d\n",API.VERSION,API.MIN_SUPPORTED_VERSION,API.REVISION);
final boolean isWin = System.getProperty("os.name").toLowerCase().startsWith("windows");
// apparently windows doesn't get EOF until enter is pressed
System.err.printf(" use EOF (%s) or break (CTRL+C) to exit\n", (isWin) ? "CTRL+Z,Enter" : "CTRL+D");
System.err.printf(" use EOF (%s) or break (CTRL+C) to exit\n", (isWin)?"CTRL+Z,Enter":"CTRL+D");
 
// This object is used as a template to identify JavaScript arrays;
// since the sun.org.mozilla.javascript package is forbidden a more
// direct check can't be used
Object jsArray;
// This is the name of the internal function used to dump
// javascript arrays
final String arrayDumpFn = getInternalObjectFieldName("shell.arrayDump");
try {
// undocumented features: when
// $net_outlyer.runtime.internal.shell,autoEOL is true an extra println() is
// undocumented feature: when
// $net.outlyer.runtime.internal.shell is true an extra println() is
// issued after each eval
// and when
// $net_outlyer.runtime.internal.shell.inspect is true the result
// of each line is automatically printed
rhino.eval(getInternalObjectFieldName("shell")+" = { " +
" autoEOL: false, inspect: true, arrayDump: null };");
jsArray = rhino.eval("new Array()");
 
// Define the arrayDump internal function
rhino.eval(arrayDumpFn+
" = function(arr) {\n" +
" var s = new String();" +
" s += '[';\n" +
" for (var i=0;i<arr.length;++i) {\n" +
" s += arr[i]+',';\n" +
" }\n" +
" java.lang.System.out.println(s.substring(0,s.length-1)+']');\n" +
"};");
rhino.eval("$net.outlyer.runtime.internal.shell = { autoEOL: false, };");
}
catch (final ScriptException e) {
e.printStackTrace();
throw new IllegalStateException("Failed to initialise interactive shell");
}
while (true) {
out.print("pjsh% : ");
92,33 → 63,12
if (null == line) {
break;
}
if (line.isEmpty()) {
continue;
}
try {
final Object result = rhino.eval(line);
final boolean eol = (Boolean) rhino.eval(getInternalObjectFieldName("shell.autoEOL"));
rhino.eval(line);
final boolean eol = (Boolean) rhino.eval("$net.outlyer.runtime.internal.shell.autoEOL");
if (eol) {
out.println();
}
final boolean insp = (Boolean) rhino.eval(getInternalObjectFieldName("shell.inspect"));
if (insp) {
if (null==result) {
out.println("null");
}
else if (result.getClass() == jsArray.getClass()) { // JavaScript array
// Store...
Internal.setInternalValue(rhino, "result", result);
// Dump
rhino.eval(String.format("%s(%s);",
arrayDumpFn,
getInternalObjectFieldName("get")+"('result')"));
Internal.setInternalValue(rhino, "result", null);
}
else {
out.println(result.toString());
}
}
}
catch (final ScriptException e) {
System.err.println("//[E] Error: " + e.getMessage());
133,14 → 83,14
System.exit(5);
}
}
 
public static void main(String... args) {
public static void main(String...args) {
if (args.length == 0) {
System.err.printf("Usage: \n" +
" java [...] %s <file1.js [file2.js [...]]>\n" +
" or\n" +
" java [...] %1$s <-i|--interactive>\n",
Shell.class.getName());
" java [...] %s <file1.js [file2.js [...]]>\n"+
" or\n"+
" java [...] %1$s <-i|--interactive>\n",
Shell.class.getName());
System.exit(1);
}
 
158,14 → 108,14
pe.exportObject("lang", new LanguageExtensions());
final PluginObject po = new PluginObject();
pe.setPluginObject(po);
 
if (args.length == 1 && (args[0].equals("-i") || args[0].equals("--interactive"))) {
interactive(pe);
assert false;
}
 
// Non-interactive mode
 
for (final String path : args) {
try {
final Sandbox sandbox = pe.createSandbox(new File(path).toURI());
/pluggablejs/trunk/src/net/outlyer/plugins/API.java
33,7 → 33,7
* {@link http://www.gnu.org/software/libtool/manual.html#Versioning}, i.e.
* <pre>
* API version = "current"
* API revision = "revision"
* API revvision = "revision"
* API min_supported_revision = "current" - "age"
* </pre>
*
55,7 → 55,7
* existing ones neither remove any of them.
* @see #VERSION
*/
public static final int REVISION = 1;
public static final int REVISION = 0;
 
/**
* Number of previous Versions supported.
/pluggablejs/trunk/src/net/outlyer/plugins/utils/LanguageExtensions_V1.java
File deleted
Property changes:
Deleted: svn:keywords
-Rev Id Date
\ No newline at end of property
/pluggablejs/trunk/src/net/outlyer/plugins/utils/LanguageExtensions.java
26,10 → 26,11
 
// $Id$
 
import java.lang.reflect.Array;
import java.util.Arrays;
import net.outlyer.plugins.Functor;
import net.outlyer.plugins.SandboxAccessor;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import javax.script.ScriptException;
import net.outlyer.plugins.SandboxAccessorImpl;
 
/**
* Extra facilities found in other languages or more complete
36,162 → 37,39
* versions of available facilities.
* Recommended name: lang
*/
public class LanguageExtensions extends LanguageExtensions_V1
implements SandboxAccessor {
 
public static final int revision = 2;
 
// The array() family is mostly redundant since rhino translates
// automatically as required from JavaScript arrays to Java arrays
// but there are some edge-cases in which they might be desirable
public class LanguageExtensions extends SandboxAccessorImpl {
/**
* Create an array of the same class as the provided object.
* @param tplt Template for the array, must be non-null and non-Void
* @param size Size of the array to create (can be 0)
* @since {@link #revision} 2
* ScriptEngine's eval.
* The built-in eval() appears to be less-powerful, in general they're
* equivalent, but if the eval'ed string is obtainer from input
* <code>eval()</code> appears to ignore it, while
* <code>LanguageExtensions.eval()</code> does eval it.
* @param code Code to evaluate
* @return Eval's result
*/
public <T> T[] array(final T tplt, int size) {
if (null == tplt || Void.class == tplt.getClass()) {
return null;
public Object eval(final String code) {
try {
return getSandbox().getCurrentEngine().eval(code);
}
return (T[]) Array.newInstance(tplt.getClass(), size);
}
 
/**
* Create an array of the provided class.
* @param c Class of the array elements, must be non-null and different from Void.class
* @param size Size of the array (can be 0)
* @since {@link #revision} 2
*/
public <T> T[] array(final Class<T> c, int size) {
return (T[]) Array.newInstance(c, size);
}
 
/**
* Create an array and copy a set of elements to it.
* Note that a JavaScript array will produce a java.lang.Object array
* @param size Size of the array to create (if less than
* <code>initValues.length</code>, will use
* <code>initValues.length</code> instead) (i.e., use 0 to
* get the same size as initValues)
* @param initValues Initial values to put in the array
* @since {@link #revision} 2
*/
public <T> T[] array(final T[] initValues, int size) {
if (null == initValues) {
return null;
catch (final ScriptException e) {
// FIXME: Handle better
System.err.println("Exception: " + e.getMessage());
}
final T[] a = Arrays.copyOf(initValues, Math.max(size, initValues.length));
if (null == a) {
return null;
}
for (int i=0; i<initValues.length; ++i) {
a[i] = initValues[i];
}
return a;
return null;
}
 
/**
* Shorthand form, allows getting a Java array from a JavaScript array.
* @param initValues
* @since {@link #revision} 2
*/
public <T> T[] array(final T[] initValues) {
return array(initValues, initValues.length);
}
 
public void var_dump(final Object obj) {
System.out.println(var_dump_(obj));
}
 
private String var_dump_(final Object obj) {
final StringBuilder sb = new StringBuilder();
if (null == obj) {
sb.append("null");
}
else if (obj.getClass() == String.class) {
sb.append("String(").append(((String)obj).length())
.append(") \"").append(obj).append("\"");
}
else if (Number.class.isInstance(obj)) {
final Class c = obj.getClass();
String v;
if (c == Double.class) { // Most probable
v = String.format("double(%f)", (Double)obj);
public Object include(final String fileName) { // TODO: Support jar URIs
try {
return getSandbox().getCurrentEngine().eval(new FileReader(new File(fileName)));
}
else if (c == Float.class) {
v = String.format("float(%f)", (Float)obj);
catch (final FileNotFoundException e) {
// FIXME: Handle better
System.err.println("Failed to read "+fileName);
}
else if (c == Long.class) {
v = String.format("long(%d)", (Long)obj);
catch (final ScriptException e) {
// FIXME: Handle better
System.err.println("Exception: " + e.getMessage());
}
else if (c == Integer.class) {
v = String.format("int(%d)", (Integer)obj);
}
else if (c == Short.class) {
v = String.format("short(%d)", (Short)obj);
}
else if (c == Byte.class) {
v = String.format("byte(%d)", (Byte)obj);
}
else {
v = String.format("%s(%f)", c.getSimpleName(),
((Number)obj).doubleValue());
}
sb.append(v);
return null;
}
else if (obj.getClass().isArray()) {
sb.append("array(").append(java.lang.reflect.Array.getLength(obj))
.append(") {\n");
/*
for (final Object elem : java.util.Arrays.asList(obj)) {
sb.append(var_dump_(elem));
}
*/
int len = java.lang.reflect.Array.getLength(obj);
for (int i=0; i<len; ++i) {
sb.append(" [").append(i).append("]=>\n ")
.append(var_dump_(java.lang.reflect.Array.get(obj, i)))
.append("\n");
}
sb.append("}");
}
else {
sb.append(obj);
}
return sb.toString();
}
 
/**
* Apply a function to each element of an iterable collection.
* @see #for_each(Object[], Functor)
* @param c Collection to which to apply
* @param f Function to apply
* @since {@link #revision} 2
*/
public <T> void for_each(final Iterable<T> c, final Functor<Object, T> f) {
for (final T elem : c) {
f.apply(elem);
}
}
/**
* Apply a function to each element of an array
* A JavaScript function can be used transparently as a functor, e.g.:
* <br />
* <code>var arr = lang.array(new Array(1, 2, 3));<br />
* lang.for_each(arr, function(x) { err.println("Element: "+x); });</code>>
* Will produce:
* <pre>Element: 1<br />Element: 2<br />Element: 3</pre>
* @param a Array to which to apply
* @param f Function to apply
* @since {@link #revision} 2
*/
public <T> void for_each(final T[] a, final Functor<Object, T> f) {
if (null == a || null == f) {
return; // FIXME: Error handling
}
for_each(Arrays.asList(a), f);
}
}
/pluggablejs/trunk/src/net/outlyer/plugins/SandboxImpl.java
98,6 → 98,13
}
 
/**
* Namespace for variables used by the enviroment
*/
private static String namespace() {
return "$net.outlyer.runtime.internal";
}
 
/**
* Creates a unique variable name.
*/
private static String uniqueVarName() {
110,7 → 117,8
* @see #uniqueVarName
*/
private static String uniqueFQVarName() {
return Internal.getInternalObjectFieldName(uniqueVarName());
return new StringBuilder(namespace()).append(".")
.append(uniqueVarName()).toString();
}
 
/**
152,12 → 160,12
// $net.outlyer.runtime.sandbox Contains a reference to this object
// Implementation note: PluginEnvironment.EXPORTED_SANDBOX_VARIABLE
// should have the same name
final NamespaceContainer.$Net_Outlyer $nspc = new NamespaceContainer.$Net_Outlyer(pE, this);
assert this == $nspc.runtime.sandbox;
rhino.put(Internal.getReservedObjectName(), $nspc);
final NamespaceContainer.$Net $net = new NamespaceContainer.$Net(pE, this);
assert this == $net.outlyer.runtime.sandbox;
rhino.put("$net", $net);
// ....internal can be used to store random internal data, it's
// a dynamic object so that fields can be created as needed
rhino.eval(Internal.getInternalObjectName()+Internal.getInternalInitialisation());
rhino.eval("$net.outlyer.runtime.internal={};");
 
if (null != prependText) {
rhino.eval(prependText);
/pluggablejs/trunk/src/net/outlyer/plugins/PluginEnvironment.java
65,6 → 65,8
// so the lower the number the better to reduce unexpected side effects
private static int linesToCheckForSupport = 1;
 
static final String EXPORTED_SANDBOX_VARIABLE = "$net.outlyer.runtime.sandbox";
{
exportedObjects = new HashMap();
pluginObject = null;
73,9 → 75,7
// plugin is guaranteed to be a SandboxAccessor, regardless of which
// exact object it ends up mapping to, see enableSandboxAccess()
boilerPlate.append("plugin.sandboxGetter = new java.util.concurrent.Callable(function() {")
.append(" return ")
.append(Internal.getRuntimeObjectName())
.append(".sandbox; });\n");
.append(" return $net.outlyer.runtime.sandbox; });\n");
}
 
////////////////////////////////////////////////////////
220,7 → 220,6
// Non-public interface
////////////////////////////////////////////////////////
 
/**
* Makes a {@link SanboxAccessor}'s field <code>getSandbox</code>
* be evaluable as a <code>Callable&lt;Sandbox&gt;</code>, i.e.,
247,8 → 246,7
 
boilerPlate.append(name).append(".sandboxGetter=new java.util.concurrent.Callable(function() {")
.append(" return ")
.append(Internal.getRuntimeObjectName())
.append(".sandbox").append("; });\n");
.append(EXPORTED_SANDBOX_VARIABLE).append("; });\n");
}
PluginProperties checkForSupport(final URI uri) throws PluginException {
/pluggablejs/trunk/src/net/outlyer/plugins/NamespaceContainer.java
41,14 → 41,19
}
}
 
/**
* This object is published as $net_outlyer
*/
public static class $Net_Outlyer {
public static class Outlyer {
public final Runtime runtime;
$Net_Outlyer(final PluginEnvironment pe, final Sandbox sandbox) {
private Outlyer(final PluginEnvironment pe, final Sandbox sandbox) {
runtime = new Runtime(pe, sandbox);
}
}
public static class $Net {
public final Outlyer outlyer;
$Net(final PluginEnvironment pe, final Sandbox sandbox) {
outlyer = new Outlyer(pe, sandbox);
}
}
}
/pluggablejs/trunk/ChangeLog
1,12 → 1,3
1.1.1build34: not a release
* Renamed the $net object to $net_outlyer to be less intrusive
* Interactive shell prints the result of each line (optionally and on by default)
* Cleaner use of internal variables, there's no longer a need to
reserve any variable name / namespace beyond $net_outlyer
* lang.array() family of methods to create Java arrays
* lang.var_dump() to help in debugging
* lang.for_each()
 
1.1.0build33: 2008-07-01
* Sandbox can be created with no associated file (only boilerPlate code
will be issued)