Skip to content

Instantly share code, notes, and snippets.

@seregasheypak
Last active April 15, 2016 18:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seregasheypak/2d7f5a16fa31018c8212754c8e94f9a4 to your computer and use it in GitHub Desktop.
Save seregasheypak/2d7f5a16fa31018c8212754c8e94f9a4 to your computer and use it in GitHub Desktop.
public class ScriptFactory{
private final Map<String, Script> cache = new HashMap<>()
private static final GroovyClassLoader CLASS_LOADER = new GroovyClassLoader()
private String template
/**
@param source is a dynamic expression to be evaluated: user.attr1 == 'x' || user.attr2 == 'y'
@return instance of script
*/
public Script create(String source) throws InstantiationException, IllegalAccessException, IOException{
if (!cache.containsKey(source)) {
cache.put(source,
CLASS_LOADER.parseClass(String.format(loadTemplate(), source))newInstance()
)
}
return cache.get(source)
}
/**
@return template used for dynamic expression execution
*/
protected String loadTemplate() throws IOException
{
return """
def evaluateExpression(Map context){
def user =context.user
%s
}
"""
}
}
@jwagenleitner
Copy link

If a single instance of this is used in a highly concurrent app I'd recommend a ConcurrentHashMap to make sure all threads can see the puts.

private static final ConcurrentHashMap<String, Script> cache = new ConcurrentHashMap<>()

...
...
public Script create(String source) throws InstantiationException, IllegalAccessException, IOException {
    Script script = cache.get(source) // assume you'll get a hit after cache is warmed up
    if (script == null) {
        script = CLASS_LOADER...
        cache.put(source, script)
    }
    return script
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment