Subversion Repositories pub

Compare Revisions

No changes between revisions

Ignore whitespace Rev 62 → Rev 64

/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/PluginEnvironment.java
0,0 → 1,354
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.io.IOException;
import java.io.LineNumberReader;
import java.lang.reflect.Field;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
 
/**
* Provides the environment for {@link net.outlyer.plugins.Sandbox}es.
*/
public class PluginEnvironment {
static class UnsupportedAPIException extends PluginException {
public UnsupportedAPIException(int providedApi) {
super("Plugin has unsupported API ("+providedApi+")");
}
}
static class UnsupportedTypeException extends PluginException {
public UnsupportedTypeException(String pluginType) {
super("Plugin has unsupported type ("+pluginType+")");
}
}
private final Map<String, Object> exportedObjects;
private BasePluginObject pluginObject;
private StringBuilder boilerPlate;
private List<String> acceptedTypes = null;
private int maxApi=API.VERSION;
// Since these lines are evaluated they'll be executed twice
// so the lower the number the better to reduce unexpected side effects
private static int linesToCheckForSupport = 1;
 
{
exportedObjects = new HashMap();
pluginObject = null;
boilerPlate = new StringBuilder();
 
// 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");
}
 
////////////////////////////////////////////////////////
// Public interface
////////////////////////////////////////////////////////
 
/**
* Creates a sandbox associated to the script found in uri
* @param uri Plugin uri
* @return Sandbox associated to uri
* @throws net.outlyer.plugins.PluginException
*/
public Sandbox createSandbox(final URI forUri) throws PluginException {
final ScriptEngine rhino = new ScriptEngineManager().getEngineByName("rhino");
PluginProperties pp;
if (null != forUri) {
pp = checkForSupport(forUri);
}
else {
pp = new PluginProperties();
pp.apiVersion = API.VERSION;
pp.name = "none";
pp.type = "";
}
 
if (null == pluginObject) {
pluginObject = new PluginObject();
}
 
try {
final PluginObject po = (PluginObject) pluginObject.clone();
 
final Bindings bindings = rhino.createBindings();
 
for (final String objectName : exportedObjects.keySet()) {
bindings.put(objectName, exportedObjects.get(objectName));
}
bindings.put("plugin", po);
//enableSandboxAccess("plugin", po);
 
return new SandboxImpl(this, forUri, bindings, pp, boilerPlate.toString());
}
catch (final CloneNotSupportedException e) {
assert false;
throw new IllegalStateException("Incorrect implementation");
}
}
 
/**
* Makes an object accessible from the plugin.
* Note the object will be shared amongst any sandboxes created after
* the exporting it.
* @param name Name with which to access the object
* @param object Object to export
* @throws IllegalArgumentException If name is <code>null</code>
* @throws IllegalArgumentException If name is "<code>plugin</code>" (use
* {@link #setPluginObject()} instead).
*/
public void exportObject(final String name, final Object object) {
if (null == name) {
throw new IllegalArgumentException("Can't export an object with" +
"a null name");
}
// Since the plugin object rules' are special (it will be cloned)
// being nice could (?) lead to confusion
if (name.equals("plugin")) {
throw new IllegalArgumentException("Can't export an object named " +
"plugin, use setPluginObject() instead");
}
exportedObjects.put(name, object);
if (object instanceof SandboxAccessor) {
enableSandboxAccess(name, (SandboxAccessor)object);
}
}
 
/**
* Makes a package's contents available in the global namespace.
* (<em>Imports</em> it into JavaScript).
* @param pkg Package to export
* @see #exportPackage(String)
*/
public void exportPackage(final Package pkg) {
if (null == pkg) {
throw new IllegalArgumentException("Can't export a null package");
}
 
boilerPlate.append("importPackage("+pkg.getName()+")");
}
 
/**
* Makes a package's contents available in the global namespace.
* Like {@see #exportPackage(Package)} but exporting by name.
* @param packageName
* @see #exportPackage(Package)
*/
public void exportPackage(final String packageName) {
if (null == packageName) {
throw new IllegalArgumentException("Can't export a null-named package");
}
final Package pkg = Package.getPackage(packageName);
if (null == pkg) {
throw new IllegalArgumentException("Failed to find package "+packageName);
}
exportPackage(pkg);
}
 
/**
* Defines the object to be exported as <code>plugin</code>.
* The <code>plugin</code> object is the only one exported by default.
* If none is set, a default one will be provided.
* <br />
* <b>Note</b> that, unlike for other objects, plugin objects aren't
* shared amongst sandboxes, a clone of the one provided will be used.
* @param pluginObject Object to export, set to null to use a default one.
*/
public void setPluginObject(BasePluginObject pObject) {
pluginObject = pObject;
}
 
/**
* Restricts the set of supported plugins to the ones with the given plugin
* type (by default no restriction is applied).
* @see PluginProperties#type
* @param pluginTypes Set of types to allow; use null to allow all types
*/
public void setAcceptedTypes(final String ... pluginTypes) {
if (null != pluginTypes) {
for (final String type : pluginTypes) {
if (null == type) {
throw new IllegalArgumentException("The set of plugin types" +
" must be either null, or a set of non-null values");
}
}
}
acceptedTypes = Arrays.asList(pluginTypes);
}
 
////////////////////////////////////////////////////////
// Non-public interface
////////////////////////////////////////////////////////
 
/**
* Makes a {@link SanboxAccessor}'s field <code>getSandbox</code>
* be evaluable as a <code>Callable&lt;Sandbox&gt;</code>, i.e.,
* from Java it will be possible to use:<br />
* <pre>
* Sandbox sb = ( (Callable&lt;Sandbox&gt;) object.getSandbox ).call()
* </pre>
* to retrieve the sandbox, while from JavaScript it will be enough
* with:
* <pre>
* var sb = object.getSandbox()
* </pre>
* @param name Exported object's name
* @param sa Exported object
*/
private void enableSandboxAccess(final String name, final SandboxAccessor sa) {
try {
Field f = sa.getClass().getField("sandboxGetter");
}
catch (final NoSuchFieldException e) {
throw new IllegalArgumentException("object " + name + " must comply " +
"with the contract of SandboxAccessor");
}
 
boilerPlate.append(name).append(".sandboxGetter=new java.util.concurrent.Callable(function() {")
.append(" return ")
.append(Internal.getRuntimeObjectName())
.append(".sandbox").append("; });\n");
}
PluginProperties checkForSupport(final URI uri) throws PluginException {
assert null != uri;
 
final PluginProperties pp = fetchPluginProperties(uri);
if (null == pp) {
throw new PluginExecutionException("Failed while inspecting plugin "+uri);
}
 
if (null != acceptedTypes) {
if (!acceptedTypes.contains(pp.type)) {
throw new UnsupportedTypeException(pp.type);
}
}
if (pp.apiVersion > maxApi) {
throw new UnsupportedAPIException(pp.apiVersion);
}
return pp;
}
 
// TODO: ? Possibly cache this, so that the first line is only eval'ed
// once more than the # of executions
static PluginProperties fetchPluginProperties(final URI uri) {
assert null != uri;
 
final ScriptEngine rhino = new ScriptEngineManager().getEngineByName("rhino");
 
try {
// Define a Plugin object with a field named type
rhino.eval("var plugin={ type: null, apiVersion: null };");
}
catch (ScriptException e) {
assert false;
throw new IllegalStateException("Unknown error encountered");
}
// First of all check the script for support
Object type = null, name = null;
Object apiVersion = null;
// Try to eval each line, since it executes in a sandbox this is
// *relatively* safe
String line;
try {
final LineNumberReader script = new LineNumberReader(new PluginReader(uri));
try {
while ((null == type || null == apiVersion || null == name) &&
(null != (line = script.readLine())) &&
script.getLineNumber() <= linesToCheckForSupport) {
try {
rhino.eval(line);
// Note that undefined doesn't convert to null!
if (null == type) {
rhino.eval("$_1_$ = (undefined===plugin.type)?null:plugin.type;");
type = rhino.get("$_1_$");
}
if (null == apiVersion) {
rhino.eval("$_1_$ = (undefined===plugin.apiVersion)?null:plugin.apiVersion;");
apiVersion = rhino.get("$_1_$");
}
if (null == name) {
rhino.eval("$_1_$ = (undefined===plugin.name)?null:plugin.name;");
name = rhino.get("$_1_$");
}
}
catch (final ScriptException e) {
// Exceptions are to be expected since none of the guaranteed
// plugin tools are provided in this context they'll try to
// access unexisting objects
}
}
}
finally {
script.close();
}
}
catch (final IOException e) {
// XXX: Evil silent failure
return null;
}
 
if (null == type) {
type = "";
}
if (null == apiVersion) {
apiVersion = 0;
}
// name can be null
final PluginProperties pp = new PluginProperties();
try {
pp.apiVersion = Double.valueOf(apiVersion.toString()).intValue();
pp.type = type.toString();
pp.name = (null != name) ? name.toString(): null;
}
catch (final NumberFormatException e) {
// XXX: Evil silent failure
return null;
}
return pp;
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/NamespaceContainer.java
0,0 → 1,54
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
/**
* Provides the hierarchy exported to JavaScript as $net.outlyer.runtime.
*/
class NamespaceContainer {
public static class Runtime {
public final Sandbox sandbox;
public final PluginEnvironment pluginEnvironment;
public Object internal = null;
private Runtime(final PluginEnvironment pe, final Sandbox sandbox_) {
sandbox = sandbox_;
pluginEnvironment = pe;
}
}
 
/**
* This object is published as $net_outlyer
*/
public static class $Net_Outlyer {
public final Runtime runtime;
$Net_Outlyer(final PluginEnvironment pe, final Sandbox sandbox) {
runtime = new Runtime(pe, sandbox);
}
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/Shell.java
0,0 → 1,181
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.io.File;
import javax.script.ScriptEngine;
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);
final ScriptEngine rhino = ((SandboxImpl) sandbox).executeAndGetEngine();
 
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);
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");
 
// 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
// 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" +
"};");
}
catch (final ScriptException e) {
e.printStackTrace();
throw new IllegalStateException("Failed to initialise interactive shell");
}
while (true) {
out.print("pjsh% : ");
final String line = in.readline();
if (null == line) {
break;
}
if (line.isEmpty()) {
continue;
}
try {
final Object result = rhino.eval(line);
final boolean eol = (Boolean) rhino.eval(getInternalObjectFieldName("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());
}
}
// EOF
System.exit(0);
}
catch (final PluginException e) {
System.err.printf("Exception while running on-the-fly " +
"interpreted script", e.getLocalizedMessage());
System.exit(5);
}
}
 
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());
System.exit(1);
}
 
final PluginEnvironment pe = new PluginEnvironment();
pe.exportObject("input", new Input());
pe.exportObject("out", new Output());
pe.exportObject("err", new Output(System.err));
pe.exportObject("hooks", new Hooks());
// Generally either UI or GUI should be used but not both
// since GUI falls-back to UI if appropriate (so the ui object
// will use the "best" implementation)
pe.exportObject("ui", new GUI());
pe.exportObject("gui", new GUI());
pe.exportObject("cui", new UI()); // cui stands for Console UI
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());
sandbox.execute();
}
catch (final PluginException e) {
System.err.printf("Exception while running plugin %s: %s\n",
path, e.getLocalizedMessage());
System.exit(2);
}
}
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/API.java
0,0 → 1,77
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
/**
* API versioning.
*
* Versioning is inspired by libtool's rules
* {@link http://www.gnu.org/software/libtool/manual.html#Versioning}, i.e.
* <pre>
* API version = "current"
* API revision = "revision"
* API min_supported_revision = "current" - "age"
* </pre>
*
* Release numbers are meaningful and composed like:
* <code>Version.MinSupported.Revision.build#</code>,
* so, e.g. release 2.3.0 won't valid since MinSupported can't be
* greater than version.
*/
public final class API {
/**
* API Version.
* Newer versions might break backwards compatibility.
*/
public static final int VERSION = 1;
 
/**
* Revision of the API Version.
* A newer revision might add features but not change the meaning of
* existing ones neither remove any of them.
* @see #VERSION
*/
public static final int REVISION = 1;
 
/**
* Number of previous Versions supported.
* For future use.
* {@see #VERSION}
* {@see #MIN_SUPPORTED_VERSION}
*/
public static final int AGE = 0;
/**
* Minimum API version supported by this implementation.
* For future use.
* In principle a new API should provide support for previous revisions,
* in case it doesn't, this constant will hold the lower supported API.
* @see #VERSION
* @pre MIN_SUPPORTED_VERSION &lt;= VERSION
*/
public static final int MIN_SUPPORTED_VERSION = VERSION - AGE;
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/Internal.java
0,0 → 1,96
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.util.Map;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
 
/**
* This class provides centralised access to features used internally.
*/
class Internal {
 
/**
* The reserved object is the only concrete variable name reserved
* in the global namespace.
* @return $net_outlyer
*/
static String getReservedObjectName() {
return "$net_outlyer";
}
/**
* Gets the name of the runtime object
* @return
*/
static String getRuntimeObjectName() {
return getReservedObjectName()+".runtime";
}
 
/**
* Gets the name of the internal object.
* Fields of this object provide access to internal features.
*/
static String getInternalObjectName() {
return getRuntimeObjectName()+".internal";
}
 
static String getInternalObjectFieldName(final String fieldName) {
return getInternalObjectName()+"."+fieldName;
}
private static String mapName = "$_";
static String getInternalInitialisation() {
return String.format("= {\n" +
" %2$s: new java.util.HashMap(),\n" +
" set: function(n,v) {\n"+
" %1$s.put(n,v);\n" +
" return v;\n" +
" },\n" +
" get: function(n) {\n" +
" return %1$s.get(n);\n" +
" }\n"+
"};",
getInternalObjectFieldName(mapName),
mapName);
}
 
static void setInternalValue(final ScriptEngine engine,
final String name,
final Object value) throws ScriptException {
final Map map = (Map) engine.eval(getInternalObjectFieldName(mapName));
map.put(name, value);
}
 
static Object getInternalValue(final ScriptEngine e,
final String name) throws ScriptException {
final Map map = (Map) e.eval(getInternalObjectFieldName(mapName));
return map.get(name);
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/SandboxImpl.java
0,0 → 1,361
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
// Related reference:
// http://java.sun.com/developer/technicalArticles/J2SE/Desktop/scripting/
 
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
 
/**
* Implementation of the Sandbox interface
*/
class SandboxImpl implements Sandbox {
private final Bindings bindings;
private final URI pluginUri;
private static int nextUniqueVarNum;
private Map<String, Collection<Runnable>> hooks;
private final String boilerPlate;
private int execution = 0;
private final PluginProperties properties;
private transient ScriptEngine currentEngine = null;
private static final String END_KEY = "e";
private static final boolean debug;
private final PluginEnvironment pE;
private static class ExecResult {
final ScriptEngine rhino;
final Object evalResult;
ExecResult(final ScriptEngine rhino_, final Object evalResult_) {
rhino = rhino_;
evalResult = evalResult_;
}
}
 
static {
nextUniqueVarNum = (int) (1193 * (1+Math.random()));
debug = System.getProperty("debug", "0").equals("1");
}
{
hooks = new HashMap<String, Collection<Runnable>>();
hooks.put(END_KEY, new LinkedList<Runnable>());
}
protected SandboxImpl(final PluginEnvironment pe, final URI plugin,
final Bindings bs, final PluginProperties pp) {
this(pe, plugin, bs, pp, null);
}
protected SandboxImpl(final PluginEnvironment pe, final URI plugin,
final Bindings bs,
final PluginProperties pp, final String boilerPlate) {
bindings = bs;
pluginUri = plugin; // if null => sandbox without file
this.boilerPlate = boilerPlate;
properties = pp;
pE = pe;
}
public void addEndHook(Runnable r) {
hooks.get(END_KEY).add(r);
}
 
/**
* Creates a unique variable name.
*/
private static String uniqueVarName() {
return new StringBuilder("$_").append(nextUniqueVarNum+=1193).append("_$").toString();
}
 
/**
* Creates a unique variable name including namespace
* @see #namespace
* @see #uniqueVarName
*/
private static String uniqueFQVarName() {
return Internal.getInternalObjectFieldName(uniqueVarName());
}
 
/**
* Gets an engine.
* If the system property "debug" is set to "1" the returned engine
* will dump extra information to the console
* @return New engine
*/
private static ScriptEngine getEngine() {
final ScriptEngine se = new ScriptEngineManager().getEngineByName("rhino");
if (debug) {
return new EngineSink(se);
}
return se;
}
 
private ExecResult execute(final String prependText,
final String appendText,
final Map<String,Object> extraBindings)
throws PluginExecutionException {
final ScriptEngine rhino = getEngine();
currentEngine = rhino;
if (null != extraBindings) {
bindings.putAll(extraBindings);
}
 
Object result = null;
try {
rhino.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
 
execution++;
if (null != boilerPlate) {
rhino.eval(boilerPlate);
}
 
// $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);
// ....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());
 
if (null != prependText) {
rhino.eval(prependText);
}
if (null != pluginUri) {
result = rhino.eval(new PluginReader(pluginUri));
}
else {
result = null;
}
if (null != appendText) {
rhino.eval(appendText);
}
// Execute any end hooks
for (final Runnable hook : hooks.get(END_KEY)) {
hook.run();
}
}
catch (final IOException e) {
throw new PluginExecutionException("I/O Error: " + e.getMessage(), e);
}
catch (final ScriptException e) {
throw new PluginExecutionException("Script exception: " + e.getMessage(), e);
}
finally {
currentEngine = null;
}
return new ExecResult(rhino, result);
}
public void execute() throws PluginExecutionException {
execute(null, null, null);
}
ScriptEngine executeAndGetEngine() throws PluginExecutionException {
return execute(null, null, null).rhino;
}
 
public <T> T createDelayedImplementation(final Class<T> c,
final String objectName)
throws PluginExecutionException {
if (null == c) {
throw new IllegalArgumentException("Can't instantiate null");
}
if (!c.isInterface()) {
throw new IllegalArgumentException("Can only create delayed " +
"implementations for interfaces");
}
if (null == objectName) {
throw new IllegalArgumentException("Implementor's name can't be null");
}
final StringBuilder preCode = new StringBuilder();
 
if (debug) {
preCode.append("// Forward declaration for delayed implementation:\n");
}
preCode.append("var ").append(objectName).append(" = {\n");
for (final Method method : c.getMethods()) {
if (method.getDeclaringClass() == Object.class) { // Implement everything, including hierarchies
continue;
}
preCode.append(method.getName()).append(": null,\n");
}
preCode.append("};\n");
 
final ScriptEngine rhino = execute(preCode.toString(), null, null).rhino;
try {
final StringBuilder retriever = new StringBuilder();
retriever.append("new ")
.append(c.getCanonicalName()).append("(").append(objectName).append(");");
if (debug) {
retriever.append("// <== Actual delayed implementation creation");
}
 
// Could be safely instantiated before actually being assigned IF
// plugins were required to define their methods with
// objectName.methodName = function() {} ...
// but would file with
// objectName = { methodName: function() {}, ... }
// Creating the instance as postCode does the job for both
 
try {
currentEngine = rhino;
// eval() returns the value of the last evaluated line/command
assert (c.isInstance(rhino.eval(retriever.toString())));
return (T) rhino.eval(retriever.toString());
}
finally {
currentEngine = null;
}
}
catch (final ScriptException e) {
throw new PluginExecutionException("Failed to create the delayed " +
"implementation instance: " + e.getMessage(), e);
}
}
 
/**
* {@inheritDoc}
*/
public <T> T createDelayedImplementation(final Class<T> c,
final Map<Method, String> map)
throws PluginExecutionException {
if (null == c) {
throw new IllegalArgumentException("Can't instantiate null");
}
if (!c.isInterface()) {
throw new IllegalArgumentException("Can only create delayed " +
"implementations for interfaces");
}
if (null == map || map.isEmpty()) {
throw new IllegalArgumentException("No mappings; creating a delayed " +
"implementation with no mappings " +
"is equivalent to creating" +
"the object from Java");
}
 
final StringBuffer preCode = new StringBuffer();
final String var = uniqueFQVarName();
preCode.append(var).append(" = {\n");
for (final Method method : map.keySet()) {
preCode.append(method.getName()).append(": ")
.append(map.get(method))
.append("\n,\n");
}
preCode.append("};\n");
final ScriptEngine rhino = execute(preCode.toString(), null, null).rhino;
try {
final StringBuilder retriever = new StringBuilder();
retriever.append("new ")
.append(c.getCanonicalName()).append("(").append(var).append(");");
if (debug) {
retriever.append("// <== Actual delayed implementation creation");
}
 
// Could be safely instantiated before actually being assigned IF
// plugins were required to define their methods with
// objectName.methodName = function() {} ...
// but would file with
// objectName = { methodName: function() {}, ... }
// Creating the instance as postCode does the job for both
 
try {
currentEngine = rhino;
// eval() returns the value of the last evaluated line/command
assert (c.isInstance(rhino.eval(retriever.toString())));
return (T) rhino.eval(retriever.toString());
}
finally {
currentEngine = null;
}
}
catch (final ScriptException e) {
throw new PluginExecutionException("Failed to create the delayed " +
"implementation instance: " + e.getMessage(), e);
}
}
 
public BasePluginObject getPluginObject() throws PluginExecutionException {
execute();
assert bindings.get("plugin") instanceof BasePluginObject;
return (BasePluginObject) bindings.get("plugin");
}
public int getExecution() {
return execution;
}
 
/**
* {@inheritDoc}
*/
public String getPluginName() {
if (null == properties.name) {
final String[] elements = loadedFrom().toString().split("/");
return elements[elements.length-1];
}
return properties.name;
}
 
/**
* {@inheritDoc}
*/
public URI loadedFrom() {
return pluginUri.normalize(); // FIXME: Return a copy
}
 
public ScriptEngine getCurrentEngine() {
return currentEngine;
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/utils/LanguageExtensions.java
0,0 → 1,197
package net.outlyer.plugins.utils;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.lang.reflect.Array;
import java.util.Arrays;
import net.outlyer.plugins.Functor;
import net.outlyer.plugins.SandboxAccessor;
 
/**
* Extra facilities found in other languages or more complete
* 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
/**
* 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
*/
public <T> T[] array(final T tplt, int size) {
if (null == tplt || Void.class == tplt.getClass()) {
return null;
}
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;
}
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;
}
 
/**
* 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);
}
else if (c == Float.class) {
v = String.format("float(%f)", (Float)obj);
}
else if (c == Long.class) {
v = String.format("long(%d)", (Long)obj);
}
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);
}
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);
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/utils/LanguageExtensions_V1.java
0,0 → 1,79
package net.outlyer.plugins.utils;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import javax.script.ScriptException;
import net.outlyer.plugins.SandboxAccessorImpl;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
/**
* Initial version of LanguageExtensions.
* @see LanguageExtensions
*/
class LanguageExtensions_V1 extends SandboxAccessorImpl {
/**
* 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 Object eval(final String code) {
try {
return getSandbox().getCurrentEngine().eval(code);
}
catch (final ScriptException e) {
// FIXME: Handle better
System.err.println("Exception: " + e.getMessage());
}
return null;
}
 
/**
* Load an external file
* @deprecated Not yet stabilised
*/
public Object include(final String fileName) { // TODO: Support jar URIs
try {
return getSandbox().getCurrentEngine().eval(new FileReader(new File(fileName)));
}
catch (final FileNotFoundException e) {
// FIXME: Handle better
System.err.println("Failed to read " + fileName);
}
catch (final ScriptException e) {
// FIXME: Handle better
System.err.println("Exception: " + e.getMessage());
}
return null;
}
 
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/utils/package-info.java
0,0 → 1,33
/**
* This package provides some common functionality that might often be
* wanted to be exported as global objects.
* {@see net.outlyer.plugins.PluginEnvironment#exportObject}.
*/
 
// $Id$
 
package net.outlyer.plugins.utils;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/utils/Output.java
0,0 → 1,73
package net.outlyer.plugins.utils;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.io.PrintStream;
 
/**
* Provides a simplified wrapper for output.
*/
public class Output {
 
private final PrintStream ps;
public Output() {
this(System.out);
}
public Output(final PrintStream ps) {
this.ps = ps;
}
 
// Note rhino already provides print() and println() in the global
// namespace
public void println() {
ps.println();
}
public void println(final String s) {
ps.println(s);
}
 
/**
* Note that varargs can't be used transparently from JS
* @param sfmt
* @param args
*/
public void printf(final String sfmt, final Object [] args) {
ps.printf(sfmt, args);
}
public void printf(final String s) {
print(s);
}
 
public void print(final String s) {
ps.print(s);
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/utils/Hooks.java
0,0 → 1,39
package net.outlyer.plugins.utils;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import net.outlyer.plugins.SandboxAccessorImpl;
 
/**
* Provides hooks to points in time during execution.
*/
public class Hooks extends SandboxAccessorImpl {
// Due to Rhino's magic passing a JS function() is enough
public void atexit(Runnable callback) {
getSandbox().addEndHook(callback);
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/utils/GUI.java
0,0 → 1,64
package net.outlyer.plugins.utils;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.awt.GraphicsEnvironment;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
 
/**
* User Interface-related methods with <b>optional</b> GUI support.
* In a headless environment will fall back to {@link net.outlyer.plugins.utils.UI}
* methods.
*/
public class GUI extends UI {
 
/**
* {@inheritDoc}
*/
@Override public String prompt(final String question) {
if (GraphicsEnvironment.isHeadless()) {
return super.prompt(question);
}
return JOptionPane.showInputDialog(question);
}
 
/**
* {@inheritDoc}
*/
@Override public File promptForFile(final String title) {
if (GraphicsEnvironment.isHeadless()) {
return super.promptForFile(title);
}
final JFileChooser fc = new JFileChooser();
fc.setMultiSelectionEnabled(false);
fc.setDialogTitle(title);
fc.showOpenDialog(null);
return fc.getSelectedFile();
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/utils/UI.java
0,0 → 1,66
package net.outlyer.plugins.utils;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.io.File;
 
/**
* User Interface-related methods.
*/
public class UI {
/**
* Prompt the user for a string
* @param question Question to ask
* @return String written by the user
*/
public String prompt(final String question) {
System.err.printf("%s: ", question);
return new Input().readline();
}
 
/**
* Prompts the user for an existent file path.
* If the provided path is empty the result will be null, otherwise
* the prompt will be repeated until a valid file is provided.
* @param message Message to display
* @return User-provided file or null if none
*/
public File promptForFile(final String message) {
do {
final Input in = new Input();
System.err.printf("%s: ", message);
final String path = in.readline();
if (path.isEmpty()) {
return null;
}
final File file = new File(path);
if (file.isFile()) {
return file;
}
} while (true);
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/utils/Input.java
0,0 → 1,58
package net.outlyer.plugins.utils;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
 
/**
* Provides a simplified wrapper for input.
*/
public class Input {
 
private final InputStream in;
 
public Input() {
this(System.in);
}
public Input(final InputStream is) {
in = is;
}
public String readline() {
final BufferedReader br = new BufferedReader(new InputStreamReader(in));
try {
return br.readLine();
}
catch (final IOException e) {
return null;
}
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/Functor.java
0,0 → 1,50
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
/**
* Basically a wrapper inspired by {@link java.util.concurrent.Callable}
* and {@link java.lang.Runnable}.
* Allows exported methods to explicitly declare a parameter as a
* function to be applied to an object.
* <br />
* Defines a single method, {@link #apply}.
* <br />
* Due to Rhino's code adaptations, passing a JavaScript function
* where a {@link Functor} is expected works transparently, e.g.:
* <code>lang.for_each(arr, function() { ... });</code>
* @see net.outlyer.plugins.utils.LanguageExtensions
* @see net.outlyer.plugins.utils.LanguageExtensions#for_each(Object[], Functor)
*
* @since {@link API#REVISION} 1
*/
public interface Functor<ResultType, ParamType> {
/**
* Apply the function to object p and return a ResultType object.
*/
ResultType apply(final ParamType p);
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/SandboxProperties.java
0,0 → 1,56
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.net.URI;
 
/**
* Provides access to properties of a sandbox
* @see Sandbox
*/
interface SandboxProperties {
/**
* Obtains the number of this execution (each time the script is executed
* this value is increases by one)
* @return Execution number
*/
public int getExecution();
 
/**
* Obtains the URI/file name from which this sandbox was created.
* @return Script file name
*/
public URI loadedFrom();
 
/**
* Obtains the name of the script of this sandbox
* @return Plugin name
* @see #loadedFrom
*/
public String getPluginName();
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/PluginProperties.java
0,0 → 1,61
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
/**
* Common properties of the plugin object. All of them
* take sane defaults.
*/
class PluginProperties extends SandboxAccessorImpl {
/**
* pluggablejs Api Version against which this plugin was written.
* Default: 1
* @see API#VERSION
*/
public int apiVersion = 1;
 
/**
* Type of this plugin, application-specific.
* Default: "" (no type)
* @see PluginLocator#getAll()
* @see PluginLocator#getFirst()
*/
public String type;
 
/**
* Name of this plugin.
* Default: same as filename (including extension but not path)
* @see PluginLocator#getAll()
* @see PluginLocator#getFirst()
*/
public String name;
 
/**
* @deprecated The use of this field is yet to be defined
*/
public Object properties; // FIXME: To be defined
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/SandboxAccessor.java
0,0 → 1,59
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
/**
* Optional interface for exported objects (see
* {@link net.outlyer.plugins.sandboxing.PluginEnvironment#exportGlobalObject}),
* it enables exported objects to retrieve the sandbox object in which they're
* being executed.
*
* Implementors must contain a field like
* <pre>
* public Object sandboxGetter = null;
* </pre>
*
* sandboxGetter MUST be public, it can be of class Object or
* Callable&lt;Sandbox&gt;, but shouldn't be used directly, instead, if required,
* use SandboxAccessorImpl#getSandbox(SandboxAccessor) to retrieve it's
* value, or inherit from SandboxAccessorImpl to be able to use
* SandboxAccessorImpl#getSandbox().
* <br />
* Implementation notes: It will be dynamically initialised, no user
* initialisation is required.
*
* The convenience default implementation, {@link SandboxAccessorImpl} can
* be used as a base class if that's possible, to hide such requirement.
*/
public interface SandboxAccessor {
/**
* Obtains the associated sanbdox.
* Implementors can use {@link SandboxAccessor#getSandbox(SandboxAccessor)}.
* @return The sandbox
*/
public Sandbox getSandbox();
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/package-info.java
0,0 → 1,32
/**
* This package contains the classes used to load JavaScript-based plugins.
* See {@link http://p.outlyer.net./pluggablejs/}
*/
 
// $Id$
 
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/PluginObject.java
0,0 → 1,69
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.util.HashSet;
import java.util.Set;
 
/**
* Default plugin object, adds a "features" field intended to describe
* the plugin features, and execution() which provides the number of times
* the script has been executed.
*/
public class PluginObject extends BasePluginObject {
/**
* Plugins can describe which features they provide by adding
* elements to this field. Possible values are application-specific.
* Default: empty
* @see #properties
*/
public Set<String> features;
 
{
features = new HashSet<String>();
}
 
/**
* Obtains the number of the current execution
* @return Current execution number
* @see Sandbox#getExecution()
*/
public int execution() {
return getSandbox().getExecution();
}
 
/**
* {@inheritDoc}
*/
@Override public Object clone() throws CloneNotSupportedException {
final PluginObject po = (PluginObject) super.clone();
po.features = new HashSet<String>(this.features);
return po;
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/RuntimeHooks.java
0,0 → 1,37
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
/**
* Provides hooks to some points in the execution process.
*/
interface RuntimeHooks {
/**
* Adds a callback to be executed after the script is finished
*/
void addEndHook(final Runnable r);
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/EngineSink.java
0,0 → 1,118
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.io.PrintStream;
import java.io.Reader;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
 
/**
* Intercepts ScriptEngine's methods and dumps their information to console.
* @see SandboxImpl#getEngine
*/
class EngineSink implements ScriptEngine {
private final ScriptEngine e;
private final PrintStream s;
{
s = System.err;
}
public EngineSink(final ScriptEngine actualEngine) {
e = actualEngine;
}
 
public Object eval(String script, ScriptContext context) throws ScriptException {
return e.eval(script, context);
}
 
public Object eval(Reader reader, ScriptContext context) throws ScriptException {
return e.eval(reader, context);
}
 
public Object eval(String script) throws ScriptException {
s.printf("//[D] eval(String):\n%s//[EOS]\n", script);
return e.eval(script);
}
 
public Object eval(Reader reader) throws ScriptException {
return e.eval(reader);
}
 
public Object eval(String script, Bindings n) throws ScriptException {
return e.eval(script, n);
}
 
public Object eval(Reader reader, Bindings n) throws ScriptException {
return e.eval(reader, n);
}
 
public void put(String key, Object value) {
s.printf("//[D] put('%s', %s)\n", key, value);
e.put(key, value);
}
 
public Object get(String key) {
return e.get(key);
}
 
public Bindings getBindings(int scope) {
return e.getBindings(scope);
}
 
public void setBindings(Bindings bindings, int scope) {
s.printf("//[D] setBindings() scope=%s:\n",
(scope==ScriptContext.ENGINE_SCOPE) ? "ENGINE_SCOPE" : "GLOBAL_SCOPE");
for (final String key : bindings.keySet()) {
s.printf(" %s=%s\n", key, bindings.get(key));
}
s.println("//[EOL]");
e.setBindings(bindings, scope);
}
 
public Bindings createBindings() {
return e.createBindings();
}
 
public ScriptContext getContext() {
return e.getContext();
}
 
public void setContext(ScriptContext context) {
e.setContext(context);
}
 
public ScriptEngineFactory getFactory() {
throw new UnsupportedOperationException("Not supported yet.");
}
 
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/Sandbox.java
0,0 → 1,112
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.lang.reflect.Method;
import java.util.Map;
import javax.script.ScriptEngine;
 
/**
* Public methods provided by the sandbox.
*/
// Note that all methods defined directly in this interface imply a call to {@link #execute}.
public interface Sandbox extends RuntimeHooks, SandboxProperties {
/**
* Creates an implementation of an interface from a JS object
* containing the interface's methods.
* <br />
* <b>Note</b>: Implies a call to {@link #execute()}.
* @param interfaceClass Interface to implement
* @param objectName Name of the JS object implementing the interface
* @return The implementation
* @throws net.outlyer.plugins.PluginExecutionException
* @see #createDelayedImplementation(Class,Map)
* @see #execute()
*/
<T> T createDelayedImplementation(final Class<T> interfaceClass, final String objectName) throws PluginExecutionException;
 
/**
* Creates an implementation of an interface from inline JS code.
* This variant allows more flexibility (e.g. the implementation might
* be split among objects, map to global functions or fallback to other
* object if unimplemented).
* Note the mapped code should be evaluable as a JS function AND
* it shouldn't end in a semicolon, e.g.:
* <br />
* Valid:
* <pre>
* function() { return SomeValue; }
* </pre>
* <pre>
* // myFunc() is a function defined somewhere in the code
* myFunc
* </pre>
* <br />
* Not valid:
* <pre>
* function() { return SomeValue; };
* </pre>
* <pre>
* SomeValue
* </pre>
* <br />
* Where possible {@link #createDelayedImplementation(Class,String)} is
* a much cleaner option.
* <br />
* <b>Note</b>: Implies a call to {@link #execute()}.
* @param interfaceClass
* @param methodToCodeMap
* @return
* @throws net.outlyer.plugins.PluginExecutionException
* @see #createDelayedImplementation(Class,String)
*/
<T> T createDelayedImplementation(final Class<T> interfaceClass,
final Map<Method, String> methodToCodeMap)
throws PluginExecutionException;
/**
* Run the script
*/
void execute() throws PluginExecutionException;
 
/**
* Obtains object containing the plugin object
* <br />
* <b>Note</b>: Implies a call to {@link #execute()}.
* @see #getPluginName
* @return Plugin object associated to this sandbox
*/
BasePluginObject getPluginObject() throws PluginExecutionException;
 
/**
* Obtains a reference to the engine currently in use, if any.
* If called during an execution it will return the current engine, from calling
* outside will return null.
* @return Current ScriptEngine
*/
ScriptEngine getCurrentEngine();
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/SandboxAccessorImpl.java
0,0 → 1,70
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.lang.reflect.Field;
import java.util.concurrent.Callable;
 
/**
* Default implementation of a {@see SandboxAccessor}.
*/
public abstract class SandboxAccessorImpl implements SandboxAccessor {
public Object sandboxGetter;
 
public static Sandbox getSandbox(final SandboxAccessor sa) {
try {
// Retrieve the field...
final Field gS = sa.getClass().getField("sandboxGetter");
// Evaluate as a callable
return ((Callable<Sandbox>)gS.get(sa)).call();
}
catch (final NoSuchFieldException e) {
throw new IllegalStateException(sa.getClass()+" hasn't been correctly initialised", e);
}
catch (final Exception e) {
throw new IllegalStateException("getSandbox produced an exception ("+
e.getClass().getSimpleName()+"),"+
"for object "+sa+" which is not expected!: " +
e.getMessage(), e);
}
}
 
public final Sandbox getSandbox() {
if (null == sandboxGetter) {
throw new IllegalStateException(getClass()+" hasn't been correctly initialised");
}
try {
return ((Callable<Sandbox>)sandboxGetter).call();
}
catch (final Exception e) {
throw new IllegalStateException("sandboxGetter produced an " +
"exception, which is not expected!");
}
 
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/PluginLocator.java
0,0 → 1,378
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
 
/**
* Simplifies seeking plugins and abstracts their location (whether they're
* in a directory or inside a jar file).
*/
public class PluginLocator {
 
private final List<URI> paths;
private final Library library;
private static final FileFilter jsFileFilter;
private boolean scanned = false;
private final PluginEnvironment environment;
static {
jsFileFilter = new FileFilter() {
public boolean accept(final File pathname) {
return pathname.isFile() && pathname.canRead() &&
pathname.getName().endsWith(".js");
}
};
}
private static class Library {
// FIXME: Do something more elegant...
private final HashMap<String, List<Sandbox>> byType;
private final HashMap<String, Sandbox> byFilename; // FIXME: Not really unique
private final HashMap<String, Sandbox> byName;
private final HashSet<Sandbox> unique;
{
byType = new HashMap<String, List<Sandbox>>();
byFilename = new HashMap<String, Sandbox>();
byName = new HashMap<String, Sandbox>();
unique = new HashSet<Sandbox>();
}
void add(final String fileName, final PluginProperties pp, final Sandbox sbox) {
byName.put(pp.name, sbox);
byFilename.put(fileName, sbox);
if (byType.get(pp.type) == null) {
byType.put(pp.type, new LinkedList<Sandbox>());
}
byType.get(pp.type).add(sbox);
unique.add(sbox);
}
void drop() {
byType.clear();
byFilename.clear();
byName.clear();
unique.clear();
}
}
{
paths = new LinkedList<URI>();
library = new Library();
}
public PluginLocator(final PluginEnvironment pe, final URI...searchPaths) {
if (null == searchPaths) {
throw new IllegalArgumentException("Can't initialise PluginLocator with no search path");
}
for (final URI path : searchPaths) {
addSearchPath(path);
}
environment = pe;
}
public void addSearchPath(final URI path) {
if (null == path) {
throw new IllegalArgumentException("Can't have a null path in the search paths");
}
 
if (path.getScheme().equals("file")) {
final File file = new File(path.normalize()).getAbsoluteFile();
if (file.exists() && file.isDirectory() && file.canRead()) {
paths.add(file.toURI().normalize());
}
}
else if (path.getScheme().equals("jar")) {
final URI normalized = path.normalize();
if (!normalized.getSchemeSpecificPart().endsWith("/")) {
throw new IllegalArgumentException("Jar file entries must" +
" represent directories");
}
// TODO: Check for existence (Class.getResource())
paths.add(normalized);
}
else {
throw new IllegalArgumentException("Only directories or jar directories are accepted");
}
}
public Sandbox getFirst(final String type, final String name, final String fileName) {
if (null == type && null == name && null == fileName) {
throw new IllegalArgumentException("At least one of type, name or fileName must be non-null");
}
if (!scanned) {
throw new IllegalStateException("Can't retrieve before scanning");
}
final Set<Sandbox> sf = new HashSet<Sandbox>(),
sn = new HashSet<Sandbox>(),
st = new HashSet<Sandbox>();
// All keys are optional but if one of them is not null and yields no
// results then getFirst yields no result
if (null != fileName) {
final Sandbox s = library.byFilename.get(fileName);
if (null == s) {
return null;
}
sf.add(s);
}
if (null != name) {
final Sandbox s = library.byName.get(name);
if (null == s) {
return null;
}
sn.add(s);
}
if (null != type) {
final Collection<Sandbox> byType = library.byType.get(type);
if (byType.isEmpty()) {
return null;
}
st.addAll(byType);
}
Set<Sandbox> inters;
 
if (null != fileName) {
inters = sf;
 
if (null != name) {
assert ! sn.isEmpty();
inters.retainAll(sn);
}
if (!inters.isEmpty() && null != type) {
assert ! st.isEmpty();
inters.retainAll(st);
}
}
else if (null != name) {
assert null == fileName && sf.isEmpty();
inters = sn;
if (null != type) {
assert ! st.isEmpty();
sn.retainAll(st);
}
}
else {
assert null != type && ! st.isEmpty();
assert null == name && sn.isEmpty();
assert null == fileName && sf.isEmpty();
 
inters = st;
}
if (inters.isEmpty()) {
return null;
}
 
return inters.iterator().next();
}
public Collection<Sandbox> getAll(final String type, final String name, final String fileName) {
if (null == type && null == name && null == fileName) {
throw new IllegalArgumentException("At least one of type, name or fileName must be non-null");
}
if (!scanned) {
throw new IllegalStateException("Can't retrieve before scanning");
}
final Set<Sandbox> set = new HashSet<Sandbox>();
if (null != fileName) {
final Sandbox s = library.byFilename.get(fileName);
if (null != s) {
set.add(s);
}
}
if (null != name) {
final Sandbox s = library.byName.get(name);
if (null != s) {
set.add(s);
}
}
if (null != type) {
final Collection<Sandbox> sbox = library.byType.get(type);
if (null != sbox) {
set.addAll(sbox);
}
}
return Collections.unmodifiableSet(set);
}
public void scan() {
if (scanned) {
return;
}
if (paths.size() == 0) { // Nothing to scan
scanned = true;
return;
}
 
for (final URI uri : paths) {
if (uri.getScheme().equals("file")) {
final File dir = new File(uri);
checkDirConsistency(dir);
scan(dir);
}
else {
assert uri.getScheme().equals("jar");
scan(uri);
}
}
 
scanned = true;
}
 
/**
* Scan over a directory
* @param dir Directory to scan
*/
private void scan(final File dir) {
assert dir.isDirectory() && dir.canRead();
for (final File candidateFile : dir.listFiles(jsFileFilter)) {
final URI fileURI = candidateFile.toURI();
 
try {
final Sandbox sb = environment.createSandbox(fileURI);
final PluginProperties pp = PluginEnvironment.fetchPluginProperties(fileURI);
if (null == pp) {
continue;
}
if (null == pp.name) {
pp.name = candidateFile.getName();
}
library.add(candidateFile.getName(), pp, sb);
}
catch (final PluginException e) {
continue;
}
}
}
 
/**
* Scan over a directory inside a jar file
* @param jarUri Directory to scan
* @return LIst of plugins in directory <code>jarUri</code>
*/
private void scan(final URI jarUri) {
assert jarUri.getScheme().equals("jar");
 
try {
final JarURLConnection conn = (JarURLConnection) jarUri.toURL().openConnection();
assert null != conn.getEntryName();
final Enumeration<JarEntry> entries = conn.getJarFile().entries();
final String[] jarURIElements =jarUri.getSchemeSpecificPart().split("!");
assert jarURIElements.length == 2;
final String jarFile = jarURIElements[0]; // = file:....jar
final String root = jarURIElements[1]; // = /path
while (entries.hasMoreElements()) {
final JarEntry je = entries.nextElement();
 
final String url = "/"+je.getName();
if (url.startsWith(root) && !je.isDirectory()) {
// Accepted URI
 
try {
final URI pluginUri = new URI("jar:"+jarFile+"!"+url);
 
final Sandbox sb = environment.createSandbox(pluginUri);
final PluginProperties pp = PluginEnvironment.fetchPluginProperties(jarUri);
// JarEntry's getName() returns the full path
final String fileName = new File(je.getName()).getName();
if (pp.name == null) {
pp.name = fileName;
}
library.add(fileName, pp, sb);
}
catch (final PluginException e) {
continue;
}
catch (final URISyntaxException e) {
assert false;
throw new IllegalStateException("Unexpected malformed " +
"jar URI, implementation error (?)");
}
}
}
}
catch (IOException e) {
throw new IllegalStateException("Error reading jar file");
}
}
 
/**
* Throws an unchecked exception if something that, on construction, was
* a valid directory, is not anymore.
* @param dir Directory to check
* @throws java.lang.IllegalStateException If the <em>directory</em> is
* no longer a directory or can't be accessed or has ceased to exist.
*/
private static void checkDirConsistency(final File dir)
throws IllegalStateException {
if (!dir.exists() || !dir.isDirectory() || !dir.canRead()) {
throw new IllegalStateException("Permissions of " + dir +
" modified while running");
}
}
public Collection<Sandbox> list() {
scan();
return Collections.unmodifiableCollection(library.unique);
}
public int foundPlugins() {
scan();
return library.unique.size();
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/PluginExecutionException.java
0,0 → 1,49
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
/**
* PluginException produced when an execution failed.
*/
public class PluginExecutionException extends PluginException {
 
public PluginExecutionException(Throwable cause) {
super(cause);
}
 
public PluginExecutionException(String message, Throwable cause) {
super(message, cause);
}
 
public PluginExecutionException(String message) {
super(message);
}
 
public PluginExecutionException() {
}
 
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/PluginException.java
0,0 → 1,49
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
/**
* Base exception
*/
public class PluginException extends Exception {
 
public PluginException(Throwable cause) {
super(cause);
}
 
public PluginException(String message, Throwable cause) {
super(message, cause);
}
 
public PluginException(String message) {
super(message);
}
 
public PluginException() {
}
 
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/BasePluginObject.java
0,0 → 1,39
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
/**
* Simplest object to be exported as "plugin"
* @see PluginObject
*/
public class BasePluginObject extends PluginProperties implements SandboxAccessor, Cloneable {
public int version = 0;
 
@Override public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property
/pluggablejs/branches/1.1.1build34/src/net/outlyer/plugins/PluginReader.java
0,0 → 1,79
package net.outlyer.plugins;
 
/*
* Copyright (c) 2008, Toni Corvera. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
// $Id$
 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
 
/**
* java.io.Reader for plugins, tries to abstract the plugin location (file or jar)
*/
class PluginReader extends Reader {
 
private final Reader readerImpl;
 
PluginReader(final URI uri) throws IOException {
super();
assert null != uri;
 
try {
if (uri.getScheme().equals("file")) {
readerImpl = new FileReader(new File(uri));
}
else {
final String path = uri.getSchemeSpecificPart().split("!")[1];
final InputStream is = getClass().getResourceAsStream(path);
if (null == is) {
throw new IOException("Failed to get resource for " + uri);
}
readerImpl = new InputStreamReader(is);
}
// TODO: Add exception for other schemes
}
catch (final FileNotFoundException e) {
throw new IOException("Can\'t read input " + uri);
}
}
 
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return readerImpl.read(cbuf, off, len);
}
 
@Override
public void close() throws IOException {
readerImpl.close();
}
}
Property changes:
Added: svn:keywords
+Rev Id Date
\ No newline at end of property