/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 <= 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; |
/** |
* |
10,25 → 36,21 |
private final InputStream in; |
{ |
in = System.in; |
public Input() { |
this(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; |
} |
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()); |
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 (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"); |
scan(); |
return Collections.unmodifiableCollection(library.unique); |
} |
return Collections.unmodifiableCollection(library.byFilename.values()); |
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); |
} |