/* * Copyright 2008 biaoping.yin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" bboss persistent, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.frameworkset.common.poolman.management; import java.beans.PropertyEditor; import java.beans.PropertyEditorManager; import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.Set; import javax.management.Attribute; import javax.management.MBeanAttributeInfo; import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.RuntimeMBeanException; import javax.management.RuntimeOperationsException; import com.frameworkset.common.poolman.PoolManConstants; import com.frameworkset.common.poolman.util.SQLManager; public class JMXPoolDeployer extends BaseTableManager implements PoolManDeployer, Runnable,Serializable { private static MBeanServer server; /** * added paramater server which is getted from application server such * as tomcat,weblogic,websphere etc. */ public JMXPoolDeployer(MBeanServer server) { super(); if(server != null) { this.server = server; } // add VM shutdown event handler try { // use reflection and catch the Exception to allow PoolMan to work with 1.2 VM's Class r = Runtime.getRuntime().getClass(); java.lang.reflect.Method m = r.getDeclaredMethod("addShutdownHook", new Class[]{Thread.class}); m.invoke(Runtime.getRuntime(), new Object[]{new Thread(this)}); } catch (Exception e) { } } /** This Runnable is not started until a VM shutdown event is fired. */ public void run() { try { super.updateTableInfo(); // Stop Pools ObjectName queryName = new ObjectName("*:*"); Set allservices = server.queryNames(queryName, null); for (Iterator iter = allservices.iterator(); iter.hasNext();) { ObjectName objn = (ObjectName) iter.next(); try { server.invoke(objn, "stop", null, null); } catch (Exception re1) { } } // Externalize State // TO DO... } catch (Exception e) { System.out.println("Unable to properly shutdown: " + e); } } /** Load DataSource info from XML and create a Service for each entry set. */ public void deployConfiguration(PoolManConfiguration config) throws Exception { try { // server if(server == null) JMXPoolDeployer.server = MBeanServerFactory.createMBeanServer(); // classloader SQLManager manager = SQLManager.getInstance(); ObjectName loaderName = new ObjectName("DefaultDomain:service=JMXPatchedClassLoader"); /** * className - The class name of the MBean to be instantiated. * name - The object name of the MBean. May be null. * params - An array containing the parameters of the constructor to be invoked. * signature - An array containing the signature of the constructor to be invoked. */ server.createMBean("com.frameworkset.common.poolman.management.JMXClassLoader", loaderName, new Object[]{ manager.getClass().getClassLoader() }, new String[]{ "java.lang.ClassLoader" }); ArrayList datasources = config.getDataSources(); if (datasources != null) { for (Iterator iter = datasources.iterator(); iter.hasNext();) { // Get each set of datasource entries Properties dbprops = (Properties) iter.next(); // Create a DataSourceServiceMBean using those entries ObjectInstance datasource = addDataSourceService(dbprops, loaderName); // Start the new DataSource MBean try { server.invoke(datasource.getObjectName(), "start", new Object[0], new String[0]); } catch (RuntimeMBeanException re) { Exception e = re.getTargetException(); throw e; } } } // start reflective Generic object pools ArrayList genericPools = config.getGenericPools(); if (genericPools != null) { for (Iterator iter = genericPools.iterator(); iter.hasNext();) { // Get each set of datasource entries Properties props = (Properties) iter.next(); // Create a GenericPoolServiceMBean using those entries ObjectInstance pooledObject = addPooledObjectService(props, loaderName); // Start the new Service try { server.invoke(pooledObject.getObjectName(), "start", new Object[0], new String[0]); } catch (RuntimeMBeanException re) { Exception e = re.getTargetException(); System.err.println(e.getMessage()); e.printStackTrace(); } } } // start admin agent Properties adminProps = config.getAdminProperties(); if (adminProps != null) { try { Class agentType = Class.forName(adminProps.getProperty("class", "com.sun.jdmk.comm.HtmlAdaptorServer")); Object agentInstance = agentType.newInstance(); String compositeName = new String(adminProps.getProperty("name", "Adaptor:name=html") + ",port=" + adminProps.getProperty("port", "8082")); ObjectName agentName = new ObjectName(compositeName); server.registerMBean(agentInstance, agentName); java.lang.reflect.Method startMethod = agentType.getMethod("start", null); startMethod.invoke(agentInstance, null); } catch (Exception e) { System.err.println("ERROR: Could not create the Admin Agent: " + e); e.printStackTrace(); } } } catch (RuntimeOperationsException e) { throw e.getTargetException(); } catch (MBeanException e) { throw e.getTargetException(); } catch (RuntimeMBeanException e) { throw e.getTargetException(); } catch (javax.management.RuntimeErrorException e) { throw e.getTargetError(); } catch (Exception e) { throw e; } } private ObjectInstance addDataSourceService(Properties props, ObjectName loaderName) throws Exception { String dbname = null; try { dbname = (String) props.get("dbname"); } catch (NullPointerException npe) { throw new Exception("No name found for database!"); } // instance will have JNDI name of getName() and // ObjectName of getObjectName() ObjectName objectName = new ObjectName("DefaultDomain:service=PoolManDataSource-" + dbname); // class is same for all DataSource services String className = PoolManConstants.DATASOURCE_SVC_CLASSNAME; // create the instance, this binds it to the MBeanServer // with no attributes yet set ObjectInstance instance = null; try { instance = server.createMBean(className, objectName, loaderName); } catch (Exception ine) { ine.printStackTrace(); //System.exit(0); } // here's the new MBean's info MBeanInfo mbeanInfo = server.getMBeanInfo(instance.getObjectName()); // set attributes based on properties MBeanAttributeInfo[] attributes = mbeanInfo.getAttributes(); for (int n = 0; n < attributes.length; n++) { // get MBean attribute name String attrName = attributes[n].getName(); if (props.containsKey(attrName.toLowerCase())) { // get value in props String propsVal = props.getProperty(attrName.toLowerCase()); // manage data type using java.bean package // so far we only need boolean, int, and String String datatype = attributes[n].getType(); Class type; if (datatype.equals("int")) type = Integer.TYPE; else if (datatype.equals("boolean")) type = Boolean.TYPE; else type = Class.forName(datatype); // create attribute value of correct type PropertyEditor editor = PropertyEditorManager.findEditor(type); editor.setAsText(propsVal); Object value = editor.getValue(); Attribute attrValue = new Attribute(attrName, value); // set attribute value on mbean server.setAttribute(objectName, attrValue); } } return instance; } private ObjectInstance addPooledObjectService(Properties props, ObjectName loaderName) throws Exception { String poolName = null; try { poolName = (String) props.get("name"); } catch (NullPointerException npe) { throw new Exception("No name found for ObjectPool!"); } ObjectName objectName = new ObjectName("DefaultDomain:service=PoolManObjectPool-" + poolName); // class is same for all DataSource services String className = PoolManConstants.GENERIC_SVC_CLASSNAME; // create the instance, this binds it to the MBeanServer // with no attributes yet set (all set to default) ObjectInstance instance = server.createMBean(className, objectName, loaderName); // here's the new MBean's info MBeanInfo mbeanInfo = server.getMBeanInfo(instance.getObjectName()); // set attributes based on properties MBeanAttributeInfo[] attributes = mbeanInfo.getAttributes(); for (int n = 0; n < attributes.length; n++) { // get MBean attribute name String attrName = attributes[n].getName(); if (props.containsKey(attrName.toLowerCase())) { // get value in props String propsVal = props.getProperty(attrName.toLowerCase()); // manage data type using java.bean package // so far we only need boolean, int, and String String datatype = attributes[n].getType(); Class type; if (datatype.equals("int")) type = Integer.TYPE; else if (datatype.equals("boolean")) type = Boolean.TYPE; else if (datatype.equals("float")) type = Float.TYPE; else if (datatype.equals("long")) type = Long.TYPE; else if (datatype.equals("double")) type = Double.TYPE; else type = Class.forName(datatype); // create attribute value of correct type PropertyEditor editor = PropertyEditorManager.findEditor(type); editor.setAsText(propsVal); Object value = editor.getValue(); Attribute attrValue = new Attribute(attrName, value); // set attribute value on mbean server.setAttribute(objectName, attrValue); } } return instance; } public void removeDataSourceService(String dbname) throws Exception { } public void deployConfiguration(PoolManConfiguration config, Map<String, String> values) throws Exception { // TODO Auto-generated method stub } public void deployConfiguration(PoolManConfiguration config, String dbname) throws Exception { // TODO Auto-generated method stub } }