Javascript.java
/*-
* #%L
* io.earcam.utilitarian.site.search.offline
* %%
* Copyright (C) 2017 earcam
* %%
* SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
*
* You <b>must</b> choose to accept, in full - any individual or combination of
* the following licenses:
* <ul>
* <li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
* <li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
* <li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
* <li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
* </ul>
* #L%
*/
package io.earcam.utilitarian.site.search.offline;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.ServiceLoader.load;
import static java.util.stream.StreamSupport.stream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Optional;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import io.earcam.unexceptional.Exceptional;
final class Javascript {
private static final String ECMA_SCRIPT = "ECMAScript";
private static final Charset CHARSET = UTF_8;
private Javascript()
{
throw new IllegalStateException("nope");
}
public static Invocable createJavascriptEngine(InputStream... scripts)
{
return createScriptEngine(ECMA_SCRIPT, scripts);
}
public static Invocable createScriptEngine(String language, InputStream... scripts)
{
ScriptEngine engine = specified().orElseGet(() -> spi(language));
for(InputStream script : scripts) {
try {
engine.eval(new InputStreamReader(script, CHARSET));
} catch(ScriptException e) {
throw new ScriptRuntimeException(e);
}
}
return (Invocable) engine;
}
private static Optional<ScriptEngine> specified()
{
String specified = System.getProperty(Resources.PROPERTY_USE_SCRIPT_ENGINE, "");
return ("".equals(specified)) ? Optional.empty() : Exceptional.apply(Javascript::loadSpecified, specified);
}
private static Optional<ScriptEngine> loadSpecified(String engineType) throws ReflectiveOperationException
{
Class<?> specific = Javascript.class.getClassLoader().loadClass(engineType);
ScriptEngineFactory factory = (ScriptEngineFactory) specific.newInstance();
return Optional.of(factory.getScriptEngine());
}
private static ScriptEngine spi(String language)
{
return stream(load(ScriptEngineFactory.class).spliterator(), false)
.filter(f -> f.getLanguageName().equals(language))
.findAny()
.orElseThrow(ScriptRuntimeException::engineNotFound)
.getScriptEngine();
}
public static Object invokeFunction(Invocable engine, String name, Object... args)
{
return Exceptional.apply(engine::invokeFunction, name, args);
}
}