/*
* Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com>
* Licensed under the Apache License, Version 2.0 (the "License")
* $Id: BeanLoaderJanino.java 3953 2008-05-08 01:04:08Z gbevin $
*/
package com.uwyn.rife.crud.beanloaders;
import com.uwyn.rife.crud.BeanClassType;
import com.uwyn.rife.crud.exceptions.BeanImplementationInstantiationException;
import com.uwyn.rife.crud.exceptions.BeanImplementationNotFoundException;
import com.uwyn.rife.resources.ResourceFinder;
import com.uwyn.rife.tools.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import org.codehaus.janino.CompileException;
import org.codehaus.janino.Parser;
import org.codehaus.janino.Scanner;
import org.codehaus.janino.SimpleCompiler;
public class BeanLoaderJanino
{
private ResourceFinder mResourceFinder = null;
private HashMap<String, Long> mScriptsModification = new HashMap<String, Long>();
private HashMap<String, Class> mScriptsCache = new HashMap<String, Class>();
private class JaninoClassCompiler
{
private Class mClass = null;
public JaninoClassCompiler(String className, Scanner scanner, ClassLoader optionalParentClassLoader)
throws CompileException, Parser.ParseException, Scanner.ScanException, IOException
{
SimpleCompiler compiler = new SimpleCompiler();
compiler.setParentClassLoader(optionalParentClassLoader);
compiler.cook(scanner);
try
{
mClass = compiler.getClassLoader().loadClass(className);
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
}
public Class evaluate()
{
return mClass;
}
}
public BeanLoaderJanino(ResourceFinder resourceFinder)
{
mResourceFinder = resourceFinder;
}
public synchronized Class getClassInstance(final String implementation)
throws ClassNotFoundException
{
try
{
URL resource = mResourceFinder.getResource(implementation);
long current_modification = -1;
if (resource != null)
{
current_modification = mResourceFinder.getModificationTime(implementation);
}
if (null == resource)
{
throw new BeanImplementationNotFoundException(implementation, null);
}
Long previous_modification = mScriptsModification.get(implementation);
Class bean_class = null;
if (mScriptsCache.containsKey(implementation) &&
(null == previous_modification ||
previous_modification == current_modification))
{
bean_class = mScriptsCache.get(implementation);
}
else
{
try
{
URL script_resource = mResourceFinder.getResource(implementation);
if (null == script_resource)
{
throw new BeanImplementationNotFoundException(implementation, null);
}
// get the classname
String classname = StringUtils.replace(implementation.substring(0, implementation.length()-BeanClassType.SCRIPT_EXT_JANINO.length()), "/", ".");
// create the input stream
URLConnection connection = script_resource.openConnection();
connection.setUseCaches(false);
InputStream script_stream = connection.getInputStream();
bean_class = new JaninoClassCompiler(classname, new Scanner(implementation, script_stream), getClass().getClassLoader()).evaluate();
}
catch (Throwable e)
{
throw new BeanImplementationInstantiationException(implementation, e);
}
if (null == previous_modification ||
previous_modification != current_modification)
{
mScriptsModification.put(implementation, current_modification);
mScriptsCache.put(implementation, bean_class);
}
}
return bean_class;
}
catch (Throwable e)
{
throw new BeanImplementationInstantiationException(implementation, e);
}
}
}