package org.jboss.mx.interceptor;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import javax.management.Descriptor;
import javax.management.PersistentMBean;
import javax.management.MBeanException;
import javax.management.InstanceNotFoundException;
import javax.management.modelmbean.ModelMBeanInfo;
import org.jboss.mx.modelmbean.ModelMBeanConstants;
import org.jboss.mx.service.ServiceConstants;
import org.jboss.mx.server.Invocation;
import org.jboss.mx.server.MBeanInvoker;
public class PersistenceInterceptor
extends AbstractInterceptor
implements ModelMBeanConstants, ServiceConstants
{
private HashMap attrPersistencePolicies = new HashMap();
private HashMap timerTaskMap = new HashMap();
private String mbeanPersistencePolicy;
private PersistentMBean callback;
public PersistenceInterceptor()
{
super("Default Persistence Interceptor");
}
public Object invoke(Invocation invocation) throws Throwable
{
if( callback == null )
{
lazyInit(invocation);
}
Object returnValue = invocation.nextInterceptor().invoke(invocation);
String type = invocation.getType();
if (type != Invocation.OP_SETATTRIBUTE )
return returnValue;
String attrName = invocation.getName();
String policy = (String)attrPersistencePolicies.get(attrName);
if (policy == null)
policy = mbeanPersistencePolicy;
if (policy.equalsIgnoreCase(PP_ON_UPDATE) == true)
{
MBeanInvoker invoker = invocation.getInvoker();
Descriptor attrDesc = invocation.getDescriptor();
invoker.updateAttributeInfo(attrDesc);
callback.store();
}
else if(policy.equalsIgnoreCase(PP_NO_MORE_OFTEN_THAN) == true)
{
PersistenceTimerTask task = (PersistenceTimerTask) timerTaskMap.get(attrName);
if( task != null )
task.setHasUpdated(true);
}
return returnValue;
}
private synchronized void lazyInit(Invocation invocation) throws MBeanException
{
MBeanInvoker invoker = invocation.getInvoker();
callback = (PersistentMBean) invocation.getInvoker();
ModelMBeanInfo info = (ModelMBeanInfo) invoker.getMetaData();
Descriptor mbeanDesc = info.getMBeanDescriptor();
String policy = (String) mbeanDesc.getFieldValue(PERSIST_POLICY);
String persistPeriod = (String)mbeanDesc.getFieldValue(PERSIST_PERIOD);
mbeanPersistencePolicy = PP_NEVER;
if (policy != null)
{
mbeanPersistencePolicy = policy;
if (mbeanPersistencePolicy.equalsIgnoreCase(PP_ON_TIMER) ||
mbeanPersistencePolicy.equalsIgnoreCase(PP_NO_MORE_OFTEN_THAN))
{
boolean isNoMoreOftenThan = mbeanPersistencePolicy.equalsIgnoreCase(PP_NO_MORE_OFTEN_THAN);
schedulePersistenceNotifications(Long.parseLong(persistPeriod), MBEAN_DESCRIPTOR, isNoMoreOftenThan);
}
}
Descriptor[] attrDescs = info.getDescriptors(ATTRIBUTE_DESCRIPTOR);
for (int i = 0; i < attrDescs.length; ++i)
{
policy = (String) attrDescs[i].getFieldValue(PERSIST_POLICY);
persistPeriod = (String)attrDescs[i].getFieldValue(PERSIST_PERIOD);
if (policy != null)
{
String name = (String) attrDescs[i].getFieldValue(NAME);
attrPersistencePolicies.put(name, policy);
if(policy.equalsIgnoreCase(PP_ON_TIMER) ||
policy.equalsIgnoreCase(PP_NO_MORE_OFTEN_THAN))
{
boolean isNoMoreOftenThan = policy.equalsIgnoreCase(PP_NO_MORE_OFTEN_THAN);
schedulePersistenceNotifications(Long.parseLong(persistPeriod), name, isNoMoreOftenThan);
}
}
}
}
private void schedulePersistenceNotifications(long persistPeriod, String name,
boolean isNoMoreOftenThan)
{
PersistenceTimerTask task = new PersistenceTimerTask(name, isNoMoreOftenThan);
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(task, 0, persistPeriod);
timerTaskMap.put(name, task);
}
private class PersistenceTimerTask extends TimerTask
{
boolean noMoreOftenThan;
boolean hasUpdated;
String name;
PersistenceTimerTask(String name, boolean noMoreOftenThan)
{
this.name = name;
this.noMoreOftenThan = noMoreOftenThan;
}
synchronized void setHasUpdated(boolean flag)
{
hasUpdated = flag;
}
public void run()
{
try
{
boolean doStore = (noMoreOftenThan == true && hasUpdated == true)
|| noMoreOftenThan == false;
if( doStore == true )
{
callback.store();
setHasUpdated(false);
}
}
catch (MBeanException e)
{
}
catch (InstanceNotFoundException e)
{
}
}
}
}