package org.jboss.jms.client.container;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.jboss.aop.advice.Interceptor;
import org.jboss.aop.joinpoint.Invocation;
import org.jboss.aop.joinpoint.MethodInvocation;
import org.jboss.jms.client.Lifecycle;
import org.jboss.jms.container.Container;
public class ClosedInterceptor
implements Interceptor
{
private static final int NOT_CLOSED = 0;
private static final int IN_CLOSING = 1;
private static final int CLOSING = 2;
private static final int IN_CLOSE = 3;
private static final int CLOSED = -1;
private int state = NOT_CLOSED;
private int inuseCount = 0;
public String getName()
{
return "ClosedInterceptor";
}
public Object invoke(Invocation invocation) throws Throwable
{
String methodName = ((MethodInvocation) invocation).getMethod().getName();
boolean isClosing = methodName.equals("closing");
boolean isClose = methodName.equals("close");
if (isClosing)
{
if (checkClosingAlreadyDone())
return null;
}
else if (isClose)
{
if(checkCloseAlreadyDone())
return null;
}
else
inuse();
if (isClosing)
maintainRelatives(invocation);
try
{
return invocation.invokeNext();
}
finally
{
if (isClosing)
closing();
else if (isClose)
closed();
else
done();
}
}
protected synchronized boolean checkClosingAlreadyDone()
throws Throwable
{
if (state != NOT_CLOSED)
return true;
state = IN_CLOSING;
return false;
}
protected synchronized void closing()
throws Throwable
{
state = CLOSING;
}
protected synchronized boolean checkCloseAlreadyDone()
throws Throwable
{
if (state != CLOSING)
return true;
while (inuseCount > 0)
wait();
state = IN_CLOSE;
return false;
}
protected synchronized void closed()
throws Throwable
{
state = CLOSED;
}
protected synchronized void inuse()
throws Throwable
{
if (state != NOT_CLOSED)
throw new IllegalStateException("Already closed");
++inuseCount;
}
protected synchronized void done()
throws Throwable
{
if (--inuseCount == 0)
notifyAll();
}
protected void maintainRelatives(Invocation invocation)
{
Container container = Container.getContainer(invocation);
Set clone = null;
Set children = container.getChildren();
synchronized (children)
{
clone = new HashSet(children);
}
for (Iterator i = clone.iterator(); i.hasNext();)
{
Container childContainer = (Container) i.next();
Lifecycle child = (Lifecycle) childContainer.getProxy();
try
{
child.closing();
child.close();
}
catch (Throwable ignored)
{
}
}
Container parent = container.getParent();
if (parent != null)
parent.removeChild(container);
}
}