package se.l4.vibe.backend;
import java.lang.management.ManagementFactory;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import se.l4.vibe.event.Events;
import se.l4.vibe.internal.jmx.ProbeBean;
import se.l4.vibe.internal.jmx.ServiceMBeanBridge;
import se.l4.vibe.internal.jmx.SamplerBean;
import se.l4.vibe.internal.service.Service;
import se.l4.vibe.internal.service.ServiceImpl;
import se.l4.vibe.probes.Probe;
import se.l4.vibe.probes.Sampler;
import se.l4.vibe.timer.Timer;
/**
* JMX backend that will export everything via JMX.
*
* @author Andreas Holstenson
*
*/
public class JmxBackend
implements VibeBackend
{
private final MBeanServer server;
private final String root;
public JmxBackend()
{
this("vibe");
}
public JmxBackend(String root)
{
this(root, ManagementFactory.getPlatformMBeanServer());
}
public JmxBackend(MBeanServer server)
{
this("vibe", server);
}
public JmxBackend(String root, MBeanServer server)
{
// Cut of last . if any
this.root = root.charAt(root.length() - 1) == '.'
? root.substring(0, root.length() - 1)
: root;
this.server = server;
}
/**
* Translate a path into a JMX location.
*
* @param path
* @return
*/
private String toJmxLocation(String path)
{
StringBuilder builder = new StringBuilder(path.length());
int lastSeparator = path.lastIndexOf('/');
if(! "".equals(root))
{
// Append the root domain
builder
.append(root)
.append(".");
}
if(lastSeparator == -1)
{
// No separator, append name directly
builder.append(":name=");
}
for(int i=0, n=path.length(); i<n; i++)
{
char c = path.charAt(i);
if(i < lastSeparator)
{
if(c == '.')
{
builder.append(' ');
}
else if(c == '/')
{
builder.append('.');
}
else
{
builder.append(c);
}
}
else if(i == lastSeparator)
{
builder.append(":name=");
}
else
{
if(c == '.')
{
builder.append(' ');
}
else
{
builder.append(c);
}
}
}
return builder.toString();
}
private void export(String path, Service service)
{
String jmxLocation = toJmxLocation(path);
try
{
server.registerMBean(new ServiceMBeanBridge(jmxLocation, service), new ObjectName(jmxLocation));
}
catch(InstanceAlreadyExistsException e)
{
throw new RuntimeException("Something has already been registered at " + path + " (JMX location: " + jmxLocation + ")");
}
catch(MBeanRegistrationException e)
{
throw new RuntimeException(e.getMessage(), e);
}
catch(NotCompliantMBeanException e)
{
throw new RuntimeException(e.getMessage(), e);
}
catch(MalformedObjectNameException e)
{
throw new RuntimeException(e.getMessage(), e);
}
}
public void export(String path, Object object)
{
export(path, new ServiceImpl(object));
}
@Override
public void export(String path, Sampler<?> series)
{
export(path, new SamplerBean(series));
}
@Override
public void export(String path, Probe<?> probe)
{
export(path, new ProbeBean(probe));
}
@Override
public void export(String path, Events<?> events)
{
// TODO Auto-generated method stub
}
@Override
public void export(String path, Timer timer)
{
// TODO Auto-generated method stub
}
@Override
public void close()
{
}
}