package org.jboss.iiop.rmi;
import java.lang.ref.SoftReference;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.HashMap;
import java.util.WeakHashMap;
class WorkCacheManager
{
private static final org.jboss.logging.Logger logger =
org.jboss.logging.Logger.getLogger(WorkCacheManager.class);
WorkCacheManager(Class cls)
{
logger.debug("Class: " + cls.getName());
try {
constructor = cls.getDeclaredConstructor(new Class[]{Class.class});
initializer = cls.getDeclaredMethod("doAnalyze", null);
} catch (NoSuchMethodException ex) {
throw new IllegalArgumentException("Bad Class: " + ex.toString());
}
workDone = new WeakHashMap();
workInProgress = new HashMap();
}
ContainerAnalysis getAnalysis(Class cls)
throws RMIIIOPViolationException
{
ContainerAnalysis ret;
synchronized (this) {
ret = lookupDone(cls);
if (ret != null)
return ret;
InProgress inProgress = (InProgress)workInProgress.get(cls);
if (inProgress != null) {
if (inProgress.thread == Thread.currentThread())
return inProgress.analysis;
}
ret = createWorkInProgress(cls);
}
doTheWork(cls, ret);
synchronized (this) {
workInProgress.remove(cls);
workDone.put(cls, new SoftReference(ret));
notifyAll();
}
return ret;
}
Constructor constructor;
Method initializer;
Map workDone;
Map workInProgress;
private ContainerAnalysis lookupDone(Class cls)
{
SoftReference ref = (SoftReference)workDone.get(cls);
if (ref == null)
return null;
ContainerAnalysis ret = (ContainerAnalysis)ref.get();
if (ret == null)
workDone.remove(cls); return ret;
}
private ContainerAnalysis createWorkInProgress(Class cls)
{
ContainerAnalysis analysis;
try {
analysis = (ContainerAnalysis)constructor.newInstance(new Object[]{cls});
} catch (InstantiationException ex) {
throw new RuntimeException(ex.toString());
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex.toString());
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex.toString());
}
workInProgress.put(cls, new InProgress(analysis, Thread.currentThread()));
return analysis;
}
private void doTheWork(Class cls, ContainerAnalysis ret)
throws RMIIIOPViolationException
{
try {
initializer.invoke(ret, new Object[]{});
} catch (Throwable t) {
synchronized (this) {
workInProgress.remove(cls);
}
if (t instanceof InvocationTargetException) t = ((InvocationTargetException)t).getTargetException();
if (t instanceof RMIIIOPViolationException)
throw (RMIIIOPViolationException)t;
if (t instanceof RuntimeException)
throw (RuntimeException)t;
if (t instanceof Error)
throw (Error)t;
throw new RuntimeException(t.toString());
}
}
private static class InProgress
{
ContainerAnalysis analysis;
Thread thread;
InProgress(ContainerAnalysis analysis, Thread thread)
{
this.analysis = analysis;
this.thread = thread;
}
}
}