package org.yajul.jmx;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yajul.util.Lifecycle;
/**
* A proxy that instantiates the implementation JMX MBean when needed.
* <br>User: Joshua Davis
* Date: Aug 29, 2007
* Time: 6:17:01 AM
*/
public class Proxy implements Lifecycle {
private static final Logger log = LoggerFactory.getLogger(Proxy.class);
private String implementationClassName;
private Class implementationClass;
private Lifecycle implementation;
private boolean started;
private boolean implementationStarted;
private Exception exception;
private JmxBridge bridge;
Proxy(String implementationClassName,JmxBridge bridge) {
this.implementationClassName = implementationClassName;
this.bridge = bridge;
started = false;
implementationStarted = false;
}
public String getImplementationClassName() {
return implementationClassName;
}
public void start() throws Exception {
synchronized (this) {
started = true;
startImplementation();
}
}
public void stop() {
synchronized (this) {
started = false;
stopImplementation();
}
}
/**
* Returns the implementation.
*
* @return the implementation
*/
public Lifecycle getImplementation() {
return implementation;
}
/**
* Returns true if the implementation has been started.
*
* @return true if the implementation has been started
*/
public boolean isImplementationStarted() {
synchronized (this) {
return implementationStarted;
}
}
/**
* Returns any exception thrown while starting the implementation.
*
* @return an exception, or null
*/
public Exception getException() {
synchronized (this) {
return exception;
}
}
/**
* Internal method - initialize the implementation using the current thread context class loader.
*
* @throws Exception if something goes wrong.
*/
void initialize() throws Exception {
synchronized (this) {
if (implementation != null)
return;
String className = getImplementationClassName();
try {
log.info("initialize() : Looking up implementation class " + className + " ...");
implementationClass = bridge.getImplementationClass(className);
// Call the start method (delayed) if the proxy is in the started state.
log.info("initialize() : " + className + " created.");
if (started) {
startImplementation();
}
} catch (Exception e) {
log.error("** Unable to initialize " + className + " due to " + e,e);
throw e;
}
}
}
private void startImplementation() throws Exception {
if (implementationClass != null && implementation == null) {
log.info("Instantiating " + implementationClass.getName() + " ...");
Object impl = bridge.getImplementation(implementationClass);
if (!(impl instanceof Lifecycle))
throw new ClassCastException("Class " + implementationClass.getName() + " doesn't implement " + Lifecycle.class.getName());
implementation = (Lifecycle) impl;
}
if (implementation == null) {
log.info("No implementation for " + getImplementationClassName() + " yet, deferring start.");
}
else {
try {
log.info("Starting instance ...");
implementation.start();
} catch (Exception e) {
log.error("Unable to start " + implementation.getClass().getName() + " due to " + e,e);
implementationStarted = false;
exception = e;
throw e;
}
// No need to catch the exception here.
implementationStarted = true;
}
}
private void stopImplementation() {
implementationStarted = false;
if (implementation != null) {
log.info("Stopping and releasing implementation " + implementation + " ...");
implementation.stop();
implementation = null;
}
}
}