/** * Copyright (C) 2013-2016 The Rythm Engine project * for LICENSE and other details see: * https://github.com/rythmengine/rythmengine */ package org.rythmengine.sandbox; import org.rythmengine.RythmEngine; import org.rythmengine.logger.ILogger; import org.rythmengine.logger.Logger; import org.rythmengine.template.ITemplate; import java.io.File; import java.util.Map; import java.util.concurrent.*; /** * A secure executing service run template in a separate thread in case there are infinite loop, and also set * the SecurityManager in the executing thread */ public class SandboxExecutingService { private static ILogger logger = Logger.get(SandboxExecutingService.class); private ScheduledExecutorService scheduler = null; private long timeout = 1000; private RythmEngine engine; private String code = null; public SandboxExecutingService(int poolSize, SandboxThreadFactory fact, long timeout, RythmEngine re, String code) { scheduler = new ScheduledThreadPoolExecutor(poolSize, fact, new ThreadPoolExecutor.AbortPolicy()); this.timeout = timeout; engine = re; this.code = code; } private Future<Object> exec(final Map<String, Object> userCtx, final ITemplate tmpl, final String template, final File file, final Object... args) { return scheduler.submit(new Callable<Object>() { @Override public Object call() throws Exception { try { engine.prepare(userCtx); ITemplate t = tmpl; if (null != t) { } else if (null != template) { t = engine.getTemplate(template, args); } else if (null != file) { t = engine.getTemplate(file, args); } else { throw new NullPointerException(); } return t.__setSecureCode(code).render(); } catch (Exception e) { return e; } } }); } public String execute(Map<String, Object> context, File template, Object... args) { if (null == template) throw new NullPointerException(); Future<Object> f = null; try { f = exec(context, null, null, template, args); Object o = f.get(timeout, TimeUnit.MILLISECONDS); if (o instanceof RuntimeException) throw (RuntimeException) o; if (o instanceof Exception) throw new RuntimeException((Exception) o); return (null == o) ? "" : o.toString(); } catch (RuntimeException e) { if (null != f) { f.cancel(true); } throw e; } catch (Exception e) { f.cancel(true); throw new RuntimeException(e); } } public String execute(Map<String, Object> context, String template, Object... args) { if (null == template) throw new NullPointerException(); Future<Object> f = null; try { f = exec(context, null, template, null, args); Object o = f.get(timeout, TimeUnit.MILLISECONDS); if (o instanceof RuntimeException) throw (RuntimeException) o; if (o instanceof Exception) throw new RuntimeException((Exception) o); return (null == o) ? "" : o.toString(); } catch (RuntimeException e) { if (null != f) { f.cancel(true); } throw e; } catch (TimeoutException e) { f.cancel(true); throw new SecurityException(e); } catch (Exception e) { f.cancel(true); throw new RuntimeException(e); } } public Future<Object> executeAsync(final ITemplate t) { final Future<Object> f = exec(null, t, null, null, null); // make sure it get cancelled if timeout scheduler.schedule(new Runnable() { @Override public void run() { f.cancel(true); } }, timeout, TimeUnit.MILLISECONDS); return f; } public void shutdown() { scheduler.shutdownNow(); } @Override protected void finalize() throws Throwable { shutdown(); } }