Update of /cvsroot/mocklib/osgimgr/input/javasrc/biz/xsoftware/osgimgr
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5023/input/javasrc/biz/xsoftware/osgimgr
Added Files:
BundleRegistrar.java ConfigServiceImpl.java
GetComponentImpl.java MBeanInvokeHandler.java
OsgiStandardMBean.java ServerFactoryImpl.java Testing.java
TestingMBean.java
Log Message:
add osgimgr to mocklib project for now.
--- NEW FILE: ServerFactoryImpl.java ---
package biz.xsoftware.osgimgr;
import java.io.IOException;
import java.util.Map;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXConnectorServerMBean;
import javax.management.remote.JMXServiceURL;
import biz.xsoftware.api.osgimgr.ServerFactory;
public class ServerFactoryImpl implements ServerFactory {
public MBeanServer createServer() {
return MBeanServerFactory.createMBeanServer();
}
public JMXConnectorServerMBean createJMXConnector(JMXServiceURL address, Map<String, ?> environment, MBeanServer server) throws IOException {
return JMXConnectorServerFactory.newJMXConnectorServer(address, environment, server);
}
}
--- NEW FILE: ConfigServiceImpl.java ---
package biz.xsoftware.osgimgr;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import biz.xsoftware.api.osgimgr.ConfigService;
import biz.xsoftware.api.mgmt.Domain;
import biz.xsoftware.api.osgimgr.ServerFactory;
public class ConfigServiceImpl implements ConfigService {
private static final Logger log = Logger.getLogger(ConfigServiceImpl.class.getName());
private static ConfigServiceImpl lastRef;
private BundleRegistrar registrar;
private ServerFactory factory;
//lifecycle of both maps is from register to uninstall(not register to unregister)
private Map<Key, Value> keyToProxy = new HashMap<Key, Value>();
private Map<String, List<Key>> idToKeyList = new HashMap<String, List<Key>>();
public ConfigServiceImpl() {
this.factory = new ServerFactoryImpl();
registrar = new BundleRegistrar(factory);
lastRef = this;
}
public ConfigServiceImpl(ServerFactory factory) {
this.factory = factory;
registrar = new BundleRegistrar(factory);
lastRef = this;
}
public void start() throws Exception {
registrar.start("ConfigurationService");
}
public void stop() throws Exception {
registrar.stop();
registrar = null;
lastRef = null;
}
//should be called before starting a service so config can all be
//applied while service is not running(in case there are certain things
//that can't be set while running which many services have that problem
public void configureAndRegisterService(Object svc, String id) throws Exception {
if(log.isLoggable(Level.FINE))
log.fine("register service="+svc.getClass().getName()+" id="+id);
List<Class> beanInterfaces = getBeanInterfaces(svc);
List<Key> keys = idToKeyList.get(id);
if(keys == null) {
keys = new ArrayList<Key>();
idToKeyList.put(id, keys);
}
for(Class beanInterface : beanInterfaces) {
ObjectName name = getObjectName(id, beanInterface);
//check if proxy already exists. If exists place this real service
//in the proxy, so user changes immediately have affect
Key key = new Key(beanInterface.getName(), id);
Value v = keyToProxy.get(key);
if(v != null) {
//setting the real svc in the proxy should config the service and
//deal with race conditions with the user setting new config options
//and us applying the old configuration.
MBeanInvokeHandler handler = v.getInvokeHandler();
handler.setRealService(svc);
return;
}
//create proxy
Class[] interfaces = new Class[] { beanInterface };
MBeanInvokeHandler handler = new MBeanInvokeHandler();
handler.setRealService(svc);
Object proxy = Proxy.newProxyInstance(beanInterface.getClassLoader(), interfaces, handler);
registerBean(beanInterface, name, proxy);
v = new Value(handler, proxy, name);
keyToProxy.put(key, v);
keys.add(key);
}
}
private ObjectName getObjectName(String id, Class<?> beanInterface) throws MalformedObjectNameException {
Domain dom = beanInterface.getAnnotation(Domain.class);
String domainName = "Zeus.Level3.";
if(dom != null)
domainName = domainName+dom.value()+":name=";
else
domainName = domainName+"Services:name=";
//register proxy
ObjectName name = new ObjectName(domainName+beanInterface.getName()+",id="+id);
return name;
}
public void unregisterService(Object svc, String id) {
if(log.isLoggable(Level.FINE))
log.fine("unregister service="+svc.getClass().getName());
List<Class> beanInterfaces = getBeanInterfaces(svc);
for(Class beanInterface : beanInterfaces) {
//find proxy, remove real svc from proxy
Value v = keyToProxy.get(new Key(beanInterface.getName(), id));
if(v == null)
return;
if(log.isLoggable(Level.FINE))
log.fine("set proxy to null");
v.getInvokeHandler().setRealService(null);
}
}
public void uninstalled(String id) {
List<Key> keys = idToKeyList.remove(id);
if(keys == null)
return;
for(Key key : keys) {
Value v = keyToProxy.remove(key);
unregisterBean(v.getObjectName());
}
}
private List<Class> getBeanInterfaces(Object possibleBean) {
if(log.isLoggable(Level.FINE))
log.fine("introspecting service="+possibleBean.getClass().getName());
List<Class> beanInterfaces = new ArrayList<Class>();
Class[] classes = possibleBean.getClass().getInterfaces();
for(Class c : classes) {
if(log.isLoggable(Level.FINE))
log.fine("introspecting interface="+c.getName());
if(c.getName().endsWith("MBean")) {
beanInterfaces.add(c);
}
}
return beanInterfaces;
}
private static class Key {
private String id;
private String svcName;
public Key(String svcName, String id) {
this.id = id;
this.svcName = svcName;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Key)) {
return false;
}
Key right = (Key)obj;
if(!id.equals(right.id)) {
return false;
} else if(!svcName.equals(right.svcName)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = id.hashCode();
int hash2 = svcName.hashCode();
return 17*hash2+hash;
}
}
private static class Value {
private MBeanInvokeHandler invokeHandler;
private Object proxy;
private ObjectName name;
public Value(MBeanInvokeHandler invokeHandler, Object proxy, ObjectName name) {
this.invokeHandler = invokeHandler;
this.proxy = proxy;
this.name = name;
}
public MBeanInvokeHandler getInvokeHandler() {
return invokeHandler;
}
public Object getProxy() {
return proxy;
}
public ObjectName getObjectName() {
return name;
}
}
public static ConfigServiceImpl getLastRef() {
return lastRef;
}
public void registerBean(Class beanInterface, ObjectName name, Object realBean) throws NotCompliantMBeanException {
OsgiStandardMBean bean = new OsgiStandardMBean(realBean, beanInterface);
registrar.registerBean(name, bean);
}
public void unregisterBean(ObjectName name) {
registrar.unregisterBean(name);
}
}
--- NEW FILE: OsgiStandardMBean.java ---
package biz.xsoftware.osgimgr;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.NotCompliantMBeanException;
import javax.management.StandardMBean;
import biz.xsoftware.api.mgmt.Documentation;
public class OsgiStandardMBean extends StandardMBean {
private static final Logger log = Logger.getLogger(OsgiStandardMBean.class.getName());
private final Map<String, Class> nameToPrimitiveClass = new HashMap<String, Class>();
public OsgiStandardMBean(Object implementation, Class mbeanInterface) throws NotCompliantMBeanException {
super(implementation, mbeanInterface);
if(log.isLoggable(Level.FINE))
log.fine("mbean interface="+mbeanInterface.getClass());
nameToPrimitiveClass.put("boolean",Boolean.TYPE);
nameToPrimitiveClass.put("byte",Byte.TYPE);
nameToPrimitiveClass.put("char",Character.TYPE);
nameToPrimitiveClass.put("short",Short.TYPE);
nameToPrimitiveClass.put("int",Integer.TYPE);
nameToPrimitiveClass.put("long",Long.TYPE);
nameToPrimitiveClass.put("float",Float.TYPE);
nameToPrimitiveClass.put("double",Double.TYPE);
}
@Override
protected String getDescription(MBeanAttributeInfo info) {
Class c = getMBeanInterface();
String doc = getDoc(c, "get", info);
if(doc == null)
doc = getDoc(c, "is", info);
if(doc == null)
return "No @Documentation annotation on get/is method for property="+info.getName();
return doc;
}
private String getDoc(Class c, String methodPrefix, MBeanAttributeInfo info) {
Method m = null;
try {
m = c.getMethod("get"+info.getName(), (Class[])null);
} catch(NoSuchMethodException e) {}
try {
if(m == null)
m = c.getMethod("is"+info.getName(), (Class[])null);
} catch(NoSuchMethodException e) {}
if(m == null)
return "Neither method=get"+info.getName()+" not method=is"+info.getName()+" exist on mbean="+c.getName()+" so unable to retrieve documentation";
Documentation doc = (Documentation)m.getAnnotation(Documentation.class);
if(doc == null)
return "No documentation present on get/is method of property";
return doc.value();
}
// @Override
// protected String getDescription(MBeanConstructorInfo ctor, MBeanParameterInfo param, int sequence) {
// return "ctor, param, seq description";
// }
//
// @Override
// protected String getDescription(MBeanConstructorInfo info) {
// return "constructor description";
// }
//
// @Override
// protected String getDescription(MBeanFeatureInfo info) {
// return "feature description";
// }
@Override
protected String getDescription(MBeanInfo info) {
Class<?> c = getMBeanInterface();
Documentation doc = c.getAnnotation(Documentation.class);
if(log.isLoggable(Level.FINE))
log.finer("doc="+doc);
if(doc == null)
return "No description specified using @Documentation Annotation";
return doc.value();
}
// @Override
// protected String getDescription(MBeanOperationInfo op, MBeanParameterInfo param, int sequence) {
// // TODO Auto-generated method stub
// return "TODO: operation param description";
// }
@Override
protected String getDescription(MBeanOperationInfo info) {
Class c = getMBeanInterface();
try {
MBeanParameterInfo[] paramInfos = info.getSignature();
Class[] classes = new Class[paramInfos.length];
for(int i = 0; i < paramInfos.length; i++) {
classes[i] = nameToPrimitiveClass.get(paramInfos[i].getType());
if(classes[i] == null)
classes[i] = c.getClassLoader().loadClass(paramInfos[i].getType());
}
Method m = c.getMethod(info.getName(), classes);
Documentation doc = (Documentation)m.getAnnotation(Documentation.class);
if(doc == null)
return "No documentation for this operation";
return doc.value();
} catch(NoSuchMethodException e) {
return "Could not find operation="+info.getName()+" on class="+c.getName();
} catch (Exception e) {
log.log(Level.WARNING, "Could not find method", e);
return "Exception trying to get documentation on operation="+info.getName();
}
}
}
--- NEW FILE: Testing.java ---
package biz.xsoftware.osgimgr;
import java.util.logging.Logger;
public class Testing implements TestingMBean {
private static final Logger log = Logger.getLogger(Testing.class.getName());
public Testing() {
}
public String echo(int number) {
//slog.log(LogService.LOG_WARNING, "runLog number="+number);
log.info("jdk logger. runLog number="+number);
return "The number you entered was="+number;
}
}
--- NEW FILE: GetComponentImpl.java ---
package biz.xsoftware.osgimgr;
import biz.xsoftware.api.osgimgr.ConfigService;
import biz.xsoftware.api.osgimgr.GetComponent;
public class GetComponentImpl implements GetComponent {
public ConfigService getConfigService() {
return ConfigServiceImpl.getLastRef();
}
}
--- NEW FILE: MBeanInvokeHandler.java ---
package biz.xsoftware.osgimgr;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
public class MBeanInvokeHandler implements InvocationHandler {
private static final Logger log = Logger.getLogger(MBeanInvokeHandler.class.getName());
private Object realSvc;
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(log.isLoggable(Level.FINE))
log.fine("o="+realSvc);
//TODO: fix this so we return real values....
if(realSvc == null)
throw new UnsupportedOperationException("Can't get/set properties while service is stopped yet...i need to implement that");
String name = method.getName();
Class[] paramClasses = method.getParameterTypes();
ClassLoader cl = realSvc.getClass().getClassLoader();
//must copy Class to String and then load the Class again
//as the Class's may actually be different
//because they were loaded from a different class loaders.
for(int i = 0; i < paramClasses.length; i++) {
if(!paramClasses[i].isPrimitive()) {
String className = paramClasses[i].getName();
paramClasses[i] = cl.loadClass(className);
}
}
Method m = realSvc.getClass().getMethod(name, paramClasses);
Object retVal = m.invoke(realSvc, args);
return retVal;
}
public void setRealService(Object o) {
this.realSvc = o;
}
}
--- NEW FILE: TestingMBean.java ---
package biz.xsoftware.osgimgr;
public interface TestingMBean {
public String echo(int number);
}
--- NEW FILE: BundleRegistrar.java ---
package biz.xsoftware.osgimgr;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import javax.management.Attribute;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServerMBean;
import javax.management.remote.JMXServiceURL;
import biz.xsoftware.api.osgimgr.ConfigService;
import biz.xsoftware.api.osgimgr.ServerFactory;
import mx4j.tools.adaptor.http.HttpAdaptor;
import mx4j.tools.adaptor.http.XSLTProcessor;
public class BundleRegistrar {
private static final Logger log = Logger.getLogger(BundleRegistrar.class.getName());
private MBeanServer server;
private HttpAdaptor adapter;
private JMXConnectorServerMBean cntorServer;
private List<ObjectName> registrarsBeans;
private ServerFactory factory;
public BundleRegistrar(ServerFactory factory) {
this.factory = factory;
}
public void start(String id) throws Exception {
if(log.isLoggable(Level.FINE))
log.fine("Starting BundleRegistrar");
server = factory.createServer();
registrarsBeans = new ArrayList<ObjectName>();
ObjectName beanName = new ObjectName(ConfigService.SERVER_LEVEL1+"TestBean");
ObjectName httpBeanName = new ObjectName(ConfigService.SERVER_LEVEL1+"HttpAdaptor");
ObjectName processorName = new ObjectName(ConfigService.SERVER_LEVEL1+"XSLTProcessor");
ObjectName logBean = new ObjectName(LogManager.LOGGING_MXBEAN_NAME);
ObjectName memBean = new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME);
ObjectName thread = new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME);
ObjectName osBean = new ObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
ObjectName javaVMBean = new ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);
ObjectName clBean = new ObjectName(ManagementFactory.CLASS_LOADING_MXBEAN_NAME);
//here are the beans created
Testing bean = new Testing();
XSLTProcessor processor = new XSLTProcessor();
adapter = new HttpAdaptor();
List<GarbageCollectorMXBean> beans = ManagementFactory.getGarbageCollectorMXBeans();
for(int i = 0; i < beans.size(); i++) {
GarbageCollectorMXBean gcBean = beans.get(i);
String tmp = ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE+", name=GarbageCollector["+i+"]";
ObjectName gcBeanName = new ObjectName(tmp);
registerBean(gcBean, gcBeanName);
}
registerBean(ManagementFactory.getMemoryMXBean(), memBean);
registerBean(ManagementFactory.getThreadMXBean(), thread);
registerBean(ManagementFactory.getOperatingSystemMXBean(), osBean);
registerBean(ManagementFactory.getRuntimeMXBean(), javaVMBean);
registerBean(ManagementFactory.getClassLoadingMXBean(), clBean);
registerBean(LogManager.getLoggingMXBean(), logBean);
registerBean(bean, beanName);
registerBean(adapter, httpBeanName);
registerBean(processor, processorName);
server.setAttribute(httpBeanName, new Attribute("ProcessorName", processorName));
//set port to 9000 for now...
adapter.setHost("127.0.0.1");
adapter.setPort(9000);
adapter.start();
//The address of the connector server
// JMXServiceURL address = new JMXServiceURL("service:jmx:rmi://localhost");
JMXServiceURL address = new JMXServiceURL("rmi", "localhost", 1099);
//The environment map, null in this case
Map<String, ?> environment = null;
cntorServer = factory.createJMXConnector(address, environment, server);
//Start the JMXConnectorServer
cntorServer.start();
System.out.println("~"+cntorServer.getAddress()+"~");
}
public synchronized void stop() throws Exception {
cntorServer.stop();
cntorServer = null;
adapter.stop();
for(int i = registrarsBeans.size()-1; i >= 0; i--) {
unregisterBean(registrarsBeans.get(i));
}
server = null;
}
private void registerBean(Object bean, ObjectName name) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
server.registerMBean(bean, name);
registrarsBeans.add(name);
}
public void registerBean(ObjectName name, Object bean) {
if(name == null || bean == null)
throw new IllegalArgumentException("name and bean must be supplied");
try {
server.registerMBean(bean, name);
registrarsBeans.add(name);
} catch (Exception e) {
log.log(Level.WARNING, "Registering MBean failed", e);
}
}
public synchronized void unregisterBean(ObjectName name) {
if(name == null)
throw new IllegalArgumentException("name cannot be null");
try {
//if bean not registered, return and ignore.....
if(!registrarsBeans.contains(name))
return;
server.unregisterMBean(name);
registrarsBeans.remove(name);
} catch (InstanceNotFoundException e) {
//so what, who cares
} catch (Exception e) {
log.log(Level.WARNING, "Unregistration failure", e);
}
}
}
|