Subversion Repositories pub

Compare Revisions

No changes between revisions

Ignore whitespace Rev 52 → Rev 53

/pluggablejs/trunk/debian/changelog
1,5 → 1,11
pluggablejs (0.0build27-upstream.0) experimental; urgency=low
 
* Repackaging
 
-- Toni Corvera <outlyer@gmail.com> Fri, 27 Jun 2008 19:25:49 +0200
 
pluggablejs (0.0build14-upstream.0) experimental; urgency=low
 
* Initial Release.
* Initial package.
 
-- Toni Corvera <outlyer@gmail.com> Thu, 26 Jun 2008 03:08:21 +0200
/pluggablejs/trunk/samples/ui.js
0,0 → 1,8
 
var file = ui.promptForFile("Choose an appropriate executable");
 
err.println("Chosen file: "+file);
 
if (!file.canExecute()) {
err.println("Not a valid executable");
}
/pluggablejs/trunk/samples/sandbox.js
0,0 → 1,30
 
var api = {
createPE: function() {
var pe = net.outlyer.plugins.PluginEnvironment.create();
pe.exportGlobalObject("input", input);
pe.exportGlobalObject("out", out);
pe.exportGlobalObject("err", err);
return pe;
},
 
createSandbox: function(uri) {
return api.createPE().createSandbox(uri);
},
};
 
var sb = api.createSandbox(new java.io.File("sandboxed-sandbox.js").toURI());
 
sb.execute();
 
/*
do {
var line = ui.prompt("%> ");
if (null == line || line.isEmpty()) {
break;
}
}
while (true);
*/
 
// vim:set ts=4 et ai: //
/pluggablejs/trunk/samples/prefs.js
0,0 → 1,17
 
var prefs = java.utils.prefs;
 
var p = java.util.prefs.Preferences.userRoot();
 
var shell = new net.outlyer.plugins.Shell();
 
var k = java.util.prefs.Preferences.userNodeForPackage(shell.getClass());
 
err.println("user root: " + p);
err.println("pkg root: " + k);
 
k.put("SampleKey", "sampleValue");
k.sync();
err.println("Read: " + k.get("SampleKey", "none set"));
k.remove("SampleKey");
k.sync();
/pluggablejs/trunk/samples/sandboxed-sandbox.js
0,0 → 1,3
 
err.println("I'm a sandbox inside a sandbox");
 
/pluggablejs/trunk/src/net/outlyer/plugins/Sandbox.java
0,0 → 1,90
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.
*/
 
/**
* Public methods provided by the sandbox.
* Note that all methods in this interface imply a call to {@link #execute}.
*/
public interface Sandbox extends RuntimeHooks, SandboxProperties {
 
/**
* @see #createDelayedImplementation(Class, boolean)
* @deprecated (TEMPORARILY) Until the API stabilizes,
* {@link #createDelayedImplementation(Class, String)} is the only
* secure variant.
*/
<T> T createDelayedImplementation(final Class<T> interfaceClass) throws PluginExecutionException;
 
/**
* Creates an implementation of an interface from JS code
* @param interfaceClass Class of the interface to implement
* @param allowPartialImplementation If true, the implementation would be used
* even if incomplete (note that calling an unimplemented method will produce
* an exception)
* @return The implementation
* @throws net.outlyer.plugins.sandboxing.PluginExecutionException
* @deprecated (TEMPORARILY) Until the API stabilizes,
* {@link #createDelayedImplementation(Class, String)} is the only
* secure variant.
*/
<T> T createDelayedImplementation(final Class<T> interfaceClass,
boolean allowPartialImplementation)
throws PluginExecutionException;
 
/**
* @see #createDelayedImplementation(Class, boolean)
* @param fallbackObject If not null incomplete implementations are allowed and
* calls to undefined methods will be passed to this object
* @deprecated (TEMPORARILY) Until the API stabilizes,
* {@link #createDelayedImplementation(Class, String)} is the only
* secure variant.
*/
<T> T createDelayedImplementation(final Class<T> interfaceClass,
final T fallbackObject)
throws PluginExecutionException;
 
/**
* Creates an implementation of an interface from a JS object
* containing the interface's methods.
* @param interfaceClass Interface to implement
* @param objectName Name of the JS object implementing the interface
* @return The implementation
* @throws net.outlyer.plugins.PluginExecutionException
*/
<T> T createDelayedImplementation(final Class<T> interfaceClass, final String objectName) throws PluginExecutionException;
 
/**
* Run the script
*/
void execute() throws PluginExecutionException;
 
/**
* Obtains object containing the plugin object
* @see #getPluginName
* @return Plugin object associated to this sandbox
*/
BasePluginObject getPluginObject() throws PluginExecutionException;
}
/pluggablejs/trunk/src/net/outlyer/plugins/PluginExecutionException.java
0,0 → 1,47
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.
*/
 
/**
* 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() {
}
 
}
/pluggablejs/trunk/src/net/outlyer/plugins/SandboxAccessorImpl.java
0,0 → 1,47
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.
*/
 
import java.util.concurrent.Callable;
 
/**
* {@see SandboxAccessor}
*/
public abstract class SandboxAccessorImpl implements SandboxAccessor {
public Callable<Sandbox> _getSandbox;
protected final Sandbox getSandbox() {
if (null == _getSandbox) {
throw new IllegalStateException(getClass()+" hasn't been correctly initialised");
}
try {
return _getSandbox.call();
}
catch (final Exception e) {
throw new IllegalStateException("getSandbox produced an exception, which is not expected!");
}
}
}
/pluggablejs/trunk/src/net/outlyer/plugins/PluginEnvironmentImpl.java
0,0 → 1,246
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.
*/
 
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;
 
/**
* Default implementation of a PluginEnvironment.
*/
final class PluginEnvironmentImpl extends 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.REVISION;
int linesToCheckForSupport = 5;
static final String EXPORTED_SANDBOX_VARIABLE = "$net.outlyer.runtime.sandbox";
{
exportedObjects = new HashMap();
pluginObject = null;
boilerPlate = new StringBuilder();
}
private void enableSandboxAccess(final String name, final SandboxAccessor sa) {
try {
Field f = sa.getClass().getField("_getSandbox");
}
catch (final NoSuchFieldException e) {
throw new IllegalArgumentException("object " + name + " must comply " +
"with the contract of SandboxAccessor");
}
 
final String callback = name + "._getSandbox";
 
boilerPlate.append(callback).append("=function() {")
.append(" return ")
.append(EXPORTED_SANDBOX_VARIABLE).append(";\n};");
 
}
/**
* {@inheritDoc}
*/
public void exportGlobalObject(final String name, final Object object) {
if (null == name) {
throw new IllegalArgumentException("Can't export an object with" +
"a null name");
}
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);
}
}
/**
* {@inheritDoc}
*/
public void setPluginObject(BasePluginObject pObject) {
pluginObject = pObject;
}
PluginProperties checkForSupport(final URI uri) throws PluginException {
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) {
throw new PluginExecutionException("Failed while reading plugin: " + e.getMessage(), e);
}
 
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) {
throw new PluginException("Incorrect value for apiVersion provided, must be integer");
}
if (null != acceptedTypes) {
if (!acceptedTypes.contains(pp.type)) {
throw new UnsupportedTypeException(pp.type);
}
}
if (pp.apiVersion > maxApi) {
throw new UnsupportedAPIException(pp.apiVersion);
}
return pp;
}
 
/**
* {@inheritDoc}
*/
public Sandbox createSandbox(final URI forUri) throws PluginException {
final ScriptEngine rhino = new ScriptEngineManager().getEngineByName("rhino");
final PluginProperties pp = checkForSupport(forUri);
 
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(forUri, bindings, pp, boilerPlate.toString());
}
catch (final CloneNotSupportedException e) {
assert false;
throw new IllegalStateException("Incorrect implementation");
}
}
 
/**
* {@inheritDoc}
*/
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);
}
}
/pluggablejs/trunk/src/net/outlyer/plugins/Shell.java
0,0 → 1,66
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.
*/
 
import java.io.File;
import net.outlyer.plugins.utils.*;
 
/**
* Sample shell for tests, files passed as arguments will be loaded and
* executed.
*/
public final class Shell {
public static void main(String...args) {
if (args.length == 0) {
System.err.printf("Usage: java [...] %s [file1.js [file2.js [...]]]\n",
Shell.class.getName());
System.exit(1);
}
final PluginEnvironment pe = PluginEnvironment.create();
pe.exportGlobalObject("input", new Input());
pe.exportGlobalObject("out", new Output());
pe.exportGlobalObject("err", new Output(System.err));
pe.exportGlobalObject("hooks", new Hooks());
// Generally either UI or GUI should be used but not both
// since GUI falls-back to UI if appropriate
pe.exportGlobalObject("ui", new UI());
pe.exportGlobalObject("gui", new GUI());
final PluginObject po = new PluginObject();
pe.setPluginObject(po);
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);
}
}
}
}
/pluggablejs/trunk/src/net/outlyer/plugins/API.java
1,9 → 1,58
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.
*/
 
/**
* API versioning
*/
public final class API {
// Release will be REVISION.(IMPLEMENTATION-1) i.e.
// for REVISION=1 and IMPLEMENTATION=1, release would be 1.0
 
/**
* API Revision.
* Newer revisions might break backwards compatibility (see
* {@link #MIN_SUPPORTED_REVISION}).
*/
public static final int REVISION = 1;
 
/**
* Implementation of the API revision.
* Different implementations of an API are guaranteed to maintain
* the API unchanged.
* @see #REVISION
*/
public static final int IMPLEMENTATION = 1;
 
/**
* Minimum API revision 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 #REVISION
* @pre MIN_SUPPORTED_REVISION &lt;= REVISION
*/
public static final int MIN_SUPPORTED_REVISION = 1;
}
/pluggablejs/trunk/src/net/outlyer/plugins/SandboxProperties.java
0,0 → 1,53
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.
*/
import java.net.URI;
 
/**
* Provides access to some properties of a sandbox
* @see Sandbox
*/
public 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();
}
/pluggablejs/trunk/src/net/outlyer/plugins/PluginProperties.java
1,7 → 1,31
package net.outlyer.plugins;
 
import net.outlyer.plugins.sandboxing.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.
*/
 
import net.outlyer.plugins.SandboxAccessorImpl;
 
/**
*
*/
8,4 → 32,6
public class PluginProperties extends SandboxAccessorImpl {
public int apiVersion = 1;
public String type;
public String name;
public Object properties; // FIXME: To be defined
}
/pluggablejs/trunk/src/net/outlyer/plugins/sandboxing/SandboxImpl.java
File deleted
/pluggablejs/trunk/src/net/outlyer/plugins/sandboxing/SandboxAccessorImpl.java
File deleted
/pluggablejs/trunk/src/net/outlyer/plugins/sandboxing/PluginEnvironment.java
File deleted
/pluggablejs/trunk/src/net/outlyer/plugins/sandboxing/RuntimeHooks.java
File deleted
/pluggablejs/trunk/src/net/outlyer/plugins/sandboxing/SandboxProperties.java
File deleted
/pluggablejs/trunk/src/net/outlyer/plugins/sandboxing/PluginExecutionException.java
File deleted
/pluggablejs/trunk/src/net/outlyer/plugins/sandboxing/Sandbox.java
File deleted
/pluggablejs/trunk/src/net/outlyer/plugins/sandboxing/PluginReader.java
File deleted
/pluggablejs/trunk/src/net/outlyer/plugins/sandboxing/SandboxAccessor.java
File deleted
/pluggablejs/trunk/src/net/outlyer/plugins/PluginException.java
1,8 → 1,32
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.
*/
 
/**
* Base exception
*/
public class PluginException extends Exception {
 
public PluginException(Throwable cause) {
/pluggablejs/trunk/src/net/outlyer/plugins/SandboxImpl.java
0,0 → 1,302
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.
*/
 
import net.outlyer.plugins.Sandbox;
import java.io.File;
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;
import net.outlyer.plugins.BasePluginObject;
import net.outlyer.plugins.PluginProperties;
 
/**
* 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 static final String END_KEY = "e";
 
static {
nextUniqueVarNum = (int) (1193 * (1+Math.random()));
}
{
hooks = new HashMap<String, Collection<Runnable>>();
hooks.put(END_KEY, new LinkedList<Runnable>());
}
protected SandboxImpl(final URI plugin, final Bindings bs, final PluginProperties pp) {
this(plugin, bs, pp, null);
}
protected SandboxImpl(final URI plugin, final Bindings bs,
final PluginProperties pp, final String boilerPlate) {
bindings = bs;
pluginUri = plugin;
this.boilerPlate = boilerPlate;
properties = pp;
}
public void addEndHook(Runnable r) {
hooks.get(END_KEY).add(r);
}
 
/**
* Namespace for variables used by the enviroment
*/
private static String namespace() {
return "$net.outlyer.runtime";
}
 
/**
* 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 new StringBuilder(namespace()).append(".")
.append(uniqueVarName()).toString();
}
private static ScriptEngine getEngine() {
return new ScriptEngineManager().getEngineByName("rhino");
}
private ScriptEngine execute(boolean appendText, String text, final Map<String,Object> extraBindings)
throws PluginExecutionException {
final ScriptEngine rhino = getEngine();
// First, export in the global namespace the reference to this
// sandbox. This variable isn't meant to be used directly, it's only
// set to refer to it from the boilerplate code (AFAIK there's no
// way to add a binding with a FQ name).
// TODO: Can a fully qualified name be bound directly?
final String globalSanboxVarName = uniqueVarName();
bindings.put(globalSanboxVarName, this);
if (null != extraBindings) {
for (final String key : extraBindings.keySet()) {
bindings.put(key, extraBindings.get(key));
}
}
// Will contain some biolerplate code used to provide access
// to the runtime wrapped-environment
final StringBuilder runtime = new StringBuilder();
// $net.outlyer.runtime.sandbox Contains a reference to this object
// Implementation note: PluginEnvironment.EXPORTED_SANDBOX_VARIABLE should have the same name
// TODO: ? $net.outlyer.runtime.pluginEnvironment
runtime.append("var $net = {\n")
.append(" outlyer : {\n")
.append(" runtime : {\n")
.append(" sandbox : ").append(globalSanboxVarName).append("\n")
.append(" }\n")
.append(" }\n")
.append("};\n");
 
try {
rhino.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
 
execution++;
if (null != boilerPlate) {
rhino.eval(boilerPlate);
}
// Create the $net.outlyer.runtime pseudo-namespace...
rhino.eval(runtime.toString());
 
rhino.eval(new PluginReader(pluginUri));
if (appendText) {
rhino.eval(text);
}
// 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);
}
return rhino;
}
public void execute() throws PluginExecutionException {
execute(false, null, null);
}
 
public <T> T createDelayedImplementation(Class<T> c, String objectName)
throws PluginExecutionException {
final String varImpl = uniqueVarName();
final StringBuilder code = new StringBuilder();
code.append(varImpl).append(" = new ")
.append(c.getCanonicalName()).append("(").append(objectName).append(");");
//System.err.println(code.toString());
final ScriptEngine rhino = execute(true, code.toString(), null);
assert (c.isInstance(rhino.get(varImpl)));
return (T) rhino.get(varImpl);
}
 
public <T> T createDelayedImplementation(Class<T> c) throws PluginExecutionException {
return createDelayedImplementation(c, false);
}
public <T> T createDelayedImplementation(Class<T> c, boolean allowPartial) throws PluginExecutionException {
return createDelayedImplementation(c, null, allowPartial);
}
 
public <T> T createDelayedImplementation(Class<T> interfaceClass, final T fallbackObject) throws PluginExecutionException {
if (null == fallbackObject) {
throw new IllegalArgumentException("Can't use a null fallback object");
}
return createDelayedImplementation(interfaceClass, fallbackObject, true);
}
private <T> T createDelayedImplementation(Class<T> c, T fallback, boolean allowPartial) throws PluginExecutionException {
final StringBuilder hack = new StringBuilder();
 
final String var = uniqueFQVarName();
// Apparently only global namespace objects can be retrieved with get()
// so to simplify retrieval a global variable is used
final String varImpl = uniqueVarName();
 
hack.append(var).append("={\n");
final StringBuilder script = new StringBuilder();
final String varFallback = uniqueVarName();
for (final Method m : c.getMethods()) {
if (m.getDeclaringClass() != c) {
continue;
}
final String implFuncName = c.getSimpleName()+"_"+m.getName();
if (allowPartial) {
// This makes undefined functions to be mapped to undefined
// variables (otherwise the interface instantation would fail)
// Apparently defining a var with the same name as a function
// produces no error, while checking for an undefined
// variable/method does fail.
// FIXME: Might be cleaner by handling "undefined"
script.append("var ").append(implFuncName).append(";\n");
if (null != fallback) {
script.append("if (!").append(implFuncName).append(")\n\t")
.append(implFuncName).append("=")
.append(varFallback).append(".").append(m.getName())
.append("\n");
}
// script.append("if (!").append(implFuncName).append(") ")
// .append(implFuncName).append("=null;\n");
}
hack.append("\t").append(m.getName()).append(" : ").append(implFuncName).append(",\n");
}
hack.append("};\nvar ")
.append(varImpl).append("=new ")
.append(c.getCanonicalName()).append("(").append(var).append(");");
script.append(hack.toString());
final HashMap<String, Object> bn = new HashMap();
bn.put(varFallback, fallback);
 
if (null != fallback) {
script.append("\n// " + bn.get(varFallback).getClass());
}
//System.err.println(script.toString());
 
final ScriptEngine rhino = execute(true, script.toString(), bn);
assert (c.isInstance(rhino.get(varImpl)));
return (T) rhino.get(varImpl);
}
 
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) {
return new File(loadedFrom().getPath()).getName(); // FIXME: <= Is this safe?
}
return properties.name;
}
 
/**
* {@inheritDoc}
*/
public URI loadedFrom() {
return pluginUri.normalize(); // FIXME: Return a copy
}
}
/pluggablejs/trunk/src/net/outlyer/plugins/BasePluginObject.java
1,6 → 1,28
package net.outlyer.plugins;
 
import net.outlyer.plugins.sandboxing.SandboxAccessor;
/*
* 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.
*/
 
/**
* Simplest object to be exported as "plugin"
7,7 → 29,6
* @see PluginObject
*/
public class BasePluginObject extends PluginProperties implements SandboxAccessor, Cloneable {
public String name;
public int version = 0;
 
@Override public Object clone() throws CloneNotSupportedException {
/pluggablejs/trunk/src/net/outlyer/plugins/utils/Hooks.java
1,7 → 1,31
package net.outlyer.plugins.utils;
 
import net.outlyer.plugins.sandboxing.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.
*/
 
import net.outlyer.plugins.SandboxAccessorImpl;
 
/**
*
*/
/pluggablejs/trunk/src/net/outlyer/plugins/utils/package-info.java
1,4 → 1,3
 
/**
* This package provides some common functionality that might often be
* wanted to be exported as global objects.
7,4 → 6,26
 
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.
*/
/pluggablejs/trunk/src/net/outlyer/plugins/utils/GUI.java
0,0 → 1,62
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.
*/
 
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();
}
}
/pluggablejs/trunk/src/net/outlyer/plugins/utils/UI.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.
*/
 
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);
}
}
/pluggablejs/trunk/src/net/outlyer/plugins/utils/Input.java
1,7 → 1,33
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.
*/
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
 
/**
*
9,26 → 35,22
public class Input {
 
private final InputStream in;
 
public Input() {
this(System.in);
}
{
in = System.in;
public Input(final InputStream is) {
in = is;
}
public String readline() {
final StringBuilder sb = new StringBuilder();
 
int c;
final BufferedReader br = new BufferedReader(new InputStreamReader(in));
try {
do {
c = in.read();
sb.append((char) c);
} while (0 != c && '\n' != c);
return br.readLine();
}
catch (final IOException e) {
return null;
}
return sb.toString();
}
}
/pluggablejs/trunk/src/net/outlyer/plugins/utils/Output.java
1,5 → 1,29
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.
*/
 
import java.io.PrintStream;
 
/**
9,6 → 33,10
 
private final PrintStream ps;
public Output() {
this(System.out);
}
public Output(final PrintStream ps) {
this.ps = ps;
}
/pluggablejs/trunk/src/net/outlyer/plugins/PluginReader.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.
*/
 
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();
}
}
/pluggablejs/trunk/src/net/outlyer/plugins/SandboxAccessor.java
0,0 → 1,41
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.
*/
 
/**
* 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 exactly:
*
* public Callable<Sandbox> _getSandbox = null;
*
* The convenience default implementation, {@link SandboxAccessorImpl} can
* be used as a base class if that's possible, to hide such requirement.
*/
public interface SandboxAccessor {
}
/pluggablejs/trunk/src/net/outlyer/plugins/PluginLocator.java
1,5 → 1,29
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.
*/
 
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
14,11 → 38,10
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import net.outlyer.plugins.sandboxing.PluginEnvironment;
import net.outlyer.plugins.sandboxing.Sandbox;
 
/**
*
* Simplifies seeking plugins and abstracts their location (whether they're
* in a directory or inside a jar file).
*/
public class PluginLocator {
 
26,6 → 49,7
private final Library library;
private static final FileFilter jsFileFilter;
private boolean scanned = false;
private final PluginEnvironment environment;
static {
jsFileFilter = new FileFilter() {
37,14 → 61,18
}
private static class Library {
// FIXME: Do something more elegant...
private final HashMap<String, List<Sandbox>> byType;
private final HashMap<String, Sandbox> byFilename;
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 BasePluginObject bpo, final Sandbox sbox) {
55,6 → 83,7
byType.put(bpo.type, new LinkedList<Sandbox>());
}
byType.get(bpo.type).add(sbox);
unique.add(sbox);
}
void drop() {
61,6 → 90,7
byType.clear();
byFilename.clear();
byName.clear();
unique.clear();
}
}
69,19 → 99,29
library = new Library();
}
public PluginLocator(final URI defaultPath) {
if (null == defaultPath) {
throw new IllegalArgumentException("Null path in list of paths");
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 (defaultPath.getScheme().equals("file")) {
final File path = new File(defaultPath.normalize()).getAbsoluteFile();
if (path.exists() && path.isDirectory() && path.canRead()) {
paths.add(path.toURI().normalize());
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 (defaultPath.getScheme().equals("jar")) {
final URI normalized = defaultPath.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");
200,20 → 240,24
return Collections.unmodifiableSet(set);
}
public void scan(final PluginEnvironment pe) {
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(pe, dir);
scan(dir);
}
else {
assert uri.getScheme().equals("jar");
scan(pe, uri);
scan(uri);
}
}
 
224,7 → 268,7
* Scan over a directory
* @param dir Directory to scan
*/
private void scan(final PluginEnvironment pe, final File dir) {
private void scan(final File dir) {
assert dir.isDirectory() && dir.canRead();
for (final File candidateFile : dir.listFiles(jsFileFilter)) {
231,7 → 275,7
final URI fileURI = candidateFile.toURI();
try {
final Sandbox sb = pe.createSandbox(fileURI);
final Sandbox sb = environment.createSandbox(fileURI);
final BasePluginObject bpo = sb.getPluginObject();
251,7 → 295,7
* @param jarUri Directory to scan
* @return LIst of plugins in directory <code>jarUri</code>
*/
private void scan(final PluginEnvironment pe, final URI jarUri) {
private void scan(final URI jarUri) {
assert jarUri.getScheme().equals("jar");
 
try {
273,11 → 317,11
// Accepted URI
 
try {
final Sandbox sb = pe.createSandbox(jarUri);
final URI pluginUri = new URI("jar:"+jarFile+"!"+url);
 
final Sandbox sb = environment.createSandbox(pluginUri);
final BasePluginObject bpo = sb.getPluginObject();
 
final String fileName = new File(jarUri.getPath()).getName();
final String fileName = new File(jarURIElements[1]).getName();
if (bpo.name == null) {
bpo.name = fileName;
}
310,10 → 354,13
}
public Collection<Sandbox> list() {
if (!scanned) {
throw new IllegalStateException("Can't list before scanning");
}
return Collections.unmodifiableCollection(library.byFilename.values());
scan();
return Collections.unmodifiableCollection(library.unique);
}
public int foundPlugins() {
scan();
return library.unique.size();
}
}
/pluggablejs/trunk/src/net/outlyer/plugins/PluginEnvironment.java
0,0 → 1,72
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.
*/
 
import java.net.URI;
 
/**
* Provides the environment for {@link net.outlyer.plugins.Sandbox}es.
*/
public abstract class PluginEnvironment {
/**
* Creates a sandbox associated to the script found in uri
* @param uri Plugin uri
* @return Sandbox associated to uri
* @throws net.outlyer.plugins.PluginException
*/
abstract public Sandbox createSandbox(final URI uri) throws PluginException;
 
/**
* 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
*/
abstract public void exportGlobalObject(final String name, final Object object);
 
/**
* 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
*/
abstract public void setAcceptedTypes(final String... pluginTypes);
 
/**
* 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.
*/
abstract public void setPluginObject(final BasePluginObject pluginObject);
 
public static PluginEnvironment create() {
return new PluginEnvironmentImpl();
}
}
/pluggablejs/trunk/src/net/outlyer/plugins/PluginObject.java
1,5 → 1,29
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.
*/
 
import java.util.LinkedList;
import java.util.List;
 
/pluggablejs/trunk/src/net/outlyer/plugins/RuntimeHooks.java
0,0 → 1,35
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.
*/
 
/**
* Provides hooks to the execution
*/
public interface RuntimeHooks {
/**
* Adds a callback to be executed after the script is finished
*/
void addEndHook(final Runnable r);
}
/pluggablejs/trunk/build.num
1,3 → 1,3
#Build Number for ANT. Do not edit!
#Thu Jun 26 02:53:26 CEST 2008
build.number=14
#Fri Jun 27 19:25:41 CEST 2008
build.number=27
/pluggablejs/trunk/build.xml
9,7 → 9,7
<property name="release" location="release"/>
<property name="depends" location="lib"/>
 
<property name="version" value="0.0"/>
<property name="version" value="1.0"/>
 
<target name="init">
<!-- Create timestamp, sets TODAY (full, human), DSTAMP (yyyymmdd) and
30,7 → 30,13
</target>
 
<target name="compile.downstream" depends="compile.real"
description="Compilation without build number increase" />
description="Compilation without build number increase">
<!-- Forge build number, buildnumber must be called to have
${build.number} defined -->
<copy file="build.num" tofile="build.number" />
<buildnumber file="build.number" />
<delete file="build.number" />
</target>
 
<target name="dist.real" description="Generate the distribution">
<mkdir dir="${dist}/"/>
/pluggablejs/trunk
Property changes:
Added: svn:mergeinfo
Merged /pluggablejs/branches/1.0build27:r52