/*
* Copyright (c) 2009 Armando Blancas. All rights reserved.
*
* The use and distribution terms for this software are covered by the
* Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
* which can be found in the file epl-v10.html at the root of this distribution.
*
* By using this software in any fashion, you are agreeing to be bound by
* the terms of this license.
*
* You must not remove this notice, or any other, from this software.
*/
package clojure.contrib.jsr223;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
/**
* Implementation of a {@code ScriptEngineFactory} for Clojure.
*
* @author Armando Blancas
* @version 1.2
*/
public class ClojureScriptEngineFactory
implements ScriptEngineFactory {
private ScriptEngine engine;
private List<String> extensions;
private List<String> names;
private List<String> mimeTypes;
/*
* Default Constructor.
*
* Initializes the cached immutable lists and creates the local
* engine used to return default settings.
*/
public ClojureScriptEngineFactory() {
List<String> list = new ArrayList<String>(1);
list.add("clj");
extensions = Collections.unmodifiableList(list);
list = new ArrayList<String>(1);
list.add("Clojure");
names = Collections.unmodifiableList(list);
list = new ArrayList<String>(2);
list.add("application/clojure");
list.add("text/clojure");
mimeTypes = Collections.unmodifiableList(list);
engine = new ClojureScriptEngine(this);
}
/**
* {@inheritDoc}
* <p>
* This method returns <i>Clojure Scripting Engine</i>.
*/
public String getEngineName() {
return (String) engine.get(ScriptEngine.ENGINE);
}
/**
* {@inheritDoc}
* <p>
* This method returns <i>1.2</i>.
*/
public String getEngineVersion() {
return (String) engine.get(ScriptEngine.ENGINE_VERSION);
}
/**
* {@inheritDoc}
* <p>
* This method returns a list with a single value <i>clj</i>.
*/
public List<String> getExtensions() {
return extensions;
}
/**
* {@inheritDoc}
* <p>
* This method returns <i>Clojure</i>.
*/
public String getLanguageName() {
return (String) engine.get(ScriptEngine.LANGUAGE);
}
/**
* {@inheritDoc}
* <p>
* This method returns <i>1.2</i>.
*/
public String getLanguageVersion() {
return (String) engine.get(ScriptEngine.LANGUAGE_VERSION);
}
/**
* {@inheritDoc}
* Uses the recommended sugared shortcut for calling Java methods
* in idiomatic Clojure:
* <p>
* {@code (.method object arg)}
*/
public String getMethodCallSyntax(String obj, String m, String... args) {
if (obj == null)
throw new NullPointerException("obj is null");
if (m == null)
throw new NullPointerException("m is null");
StringBuilder b = new StringBuilder("(.");
b.append(m).append(' ').append(obj);
for (int i = 0; i < args.length; i++)
b.append(' ').append(args[i]);
b.append(')');
return b.toString();
}
/**
* {@inheritDoc}
* <p>
* This method returns a list with two values:
* <pre>
* application/clojure
* text/clojure
* </pre>
*/
public List<String> getMimeTypes() {
return mimeTypes;
}
/**
* {@inheritDoc}
* <p>
* This method returns a list with a single value <i>Clojure</i>.
*/
public List<String> getNames() {
return names;
}
/**
* {@inheritDoc}
* Uses the {@code println} function with the argument inlined:
* <p>
* {@code (println "Now is the time")}
*/
public String getOutputStatement(String toDisplay) {
if (toDisplay == null)
throw new NullPointerException("toDisplay is null");
return "(println \"" + toDisplay + "\")";
}
/**
* {@inheritDoc}
* <p>
* The Clojure Scripting Engine supports these additional properties:
* <p>
* {@code clojure.source.path} Additional locations of Clojure source files,
* to be appended to the value of "java.class.path". This is an optional
* property and defaults to {@code null}.
* <p>
* {@code clojure.compile.path} The location for the generated .class files.
* Defaults to {@code "classes"}.
* <p>
* {@code clojure.compile.warn-on-reflection} Whether to get a warning when Clojure will
* use Java reflection. Defaults to {@code Boolean false}.
*/
public Object getParameter(String key) {
return (String) engine.get(key);
}
/**
* {@inheritDoc}
* It prints a Clojure program as a list of statements, each in its own line:
* <pre>
* (foo...)
* (bar...)
* </pre>
*/
public String getProgram(String... statements) {
StringBuilder b = new StringBuilder();
for (int i = 0; i < statements.length; i++)
b.append(statements[i]).append('\n');
return b.toString();
}
/**
* {@inheritDoc}
* <p>
* It always returns a new instance of the Clojure script engine. The Clojure runtime
* is the same for all engines, but keeping multiple engines can simplify usage if
* each one will set different bindings and redirection.
* <p>
*/
public ScriptEngine getScriptEngine() {
return new ClojureScriptEngine(this);
}
}