+++ /dev/null
-/*\r
- * Copyright 1999-2004 The Apache Software Foundation\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-package org.apache.jk.common;\r
-\r
-import java.io.IOException;\r
-import java.io.BufferedReader;\r
-import java.io.InputStreamReader;\r
-import java.net.URLConnection;\r
-import java.net.URL;\r
-import java.util.List;\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import javax.management.MBeanServer;\r
-import javax.management.AttributeNotFoundException;\r
-import javax.management.MBeanException;\r
-import javax.management.ReflectionException;\r
-import javax.management.Attribute;\r
-import javax.management.ObjectName;\r
-\r
-import org.apache.jk.core.JkHandler;\r
-import org.apache.tomcat.util.modeler.AttributeInfo;\r
-import org.apache.tomcat.util.modeler.BaseModelMBean;\r
-import org.apache.tomcat.util.modeler.ManagedBean;\r
-import org.apache.tomcat.util.modeler.OperationInfo;\r
-import org.apache.tomcat.util.modeler.Registry;\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-\r
-/**\r
- * A small mbean that will act as a proxy for mod_jk2.\r
- *\r
- * For efficiency, it'll get bulk results and cache them - you\r
- * can force an update by calling the refreshAttributes and refreshMetadata\r
- * operations on this mbean.\r
- *\r
- * TODO: implement the user/pass auth ( right now you must use IP based security )\r
- * TODO: eventually support https\r
- * TODO: support for metadata ( mbean-descriptors ) for description and type conversions\r
- * TODO: filter out trivial components ( mutexes, etc )\r
- *\r
- * @author Costin Manolache\r
- */\r
-public class ModJkMX extends JkHandler\r
-{\r
- private static Log log = LogFactory.getLog(ModJkMX.class);\r
-\r
- MBeanServer mserver;\r
- String webServerHost="localhost";\r
- int webServerPort=80;\r
- String statusPath="/jkstatus";\r
- String user;\r
- String pass;\r
- Registry reg;\r
-\r
- HashMap mbeans=new HashMap();\r
- long lastRefresh=0;\r
- long updateInterval=5000; // 5 sec - it's min time between updates\r
-\r
- public ModJkMX()\r
- {\r
- }\r
-\r
- /* -------------------- Public methods -------------------- */\r
-\r
- public String getWebServerHost() {\r
- return webServerHost;\r
- }\r
-\r
- public void setWebServerHost(String webServerHost) {\r
- this.webServerHost = webServerHost;\r
- }\r
-\r
- public int getWebServerPort() {\r
- return webServerPort;\r
- }\r
-\r
- public void setWebServerPort(int webServerPort) {\r
- this.webServerPort = webServerPort;\r
- }\r
-\r
- public long getUpdateInterval() {\r
- return updateInterval;\r
- }\r
-\r
- public void setUpdateInterval(long updateInterval) {\r
- this.updateInterval = updateInterval;\r
- }\r
-\r
- public String getUser() {\r
- return user;\r
- }\r
-\r
- public void setUser(String user) {\r
- this.user = user;\r
- }\r
-\r
- public String getPass() {\r
- return pass;\r
- }\r
-\r
- public void setPass(String pass) {\r
- this.pass = pass;\r
- }\r
-\r
- public String getStatusPath() {\r
- return statusPath;\r
- }\r
-\r
- public void setStatusPath(String statusPath) {\r
- this.statusPath = statusPath;\r
- }\r
- /* ==================== Start/stop ==================== */\r
-\r
- public void destroy() {\r
- try {\r
- // We should keep track of loaded beans and call stop.\r
- // Modeler should do it...\r
- Iterator mbeansIt=mbeans.values().iterator();\r
- MBeanServer mbserver = Registry.getRegistry(null, null).getMBeanServer();\r
- while( mbeansIt.hasNext()) {\r
- MBeanProxy proxy=(MBeanProxy)mbeansIt.next();\r
- Object ooname = proxy.getObjectName();\r
- if( ooname != null ) {\r
- ObjectName oname = null;\r
- if(ooname instanceof ObjectName) {\r
- oname = (ObjectName)ooname;\r
- } else if(ooname instanceof String) {\r
- oname = new ObjectName((String)ooname);\r
- }\r
- if( oname != null ) {\r
- mbserver.unregisterMBean(oname);\r
- }\r
- }\r
- }\r
- } catch( Throwable t ) {\r
- log.error( "Destroy error", t );\r
- }\r
- }\r
-\r
- public void init() throws IOException {\r
- try {\r
- //if( log.isDebugEnabled() )\r
- log.info("init " + webServerHost + " " + webServerPort);\r
- reg=Registry.getRegistry(null, null);\r
- refreshMetadata();\r
- refreshAttributes();\r
- } catch( Throwable t ) {\r
- log.error( "Init error", t );\r
- }\r
- }\r
-\r
- public void start() throws IOException {\r
- if( reg==null)\r
- init();\r
- }\r
-\r
- /** Refresh the proxies, if updateInterval passed\r
- *\r
- */\r
- public void refresh() {\r
- long time=System.currentTimeMillis();\r
- if( time - lastRefresh < updateInterval ) {\r
- return;\r
- }\r
- lastRefresh=time;\r
- refreshMetadata();\r
- refreshAttributes();\r
- }\r
-\r
- public void refreshAttributes() {\r
- try {\r
- int cnt=0;\r
- // connect to apache, get a list of mbeans\r
- BufferedReader is=getStream( "dmp=*");\r
- if( is==null ) return;\r
-\r
- String name=null;\r
- String att=null;\r
- String val=null;\r
- while(true) {\r
- String line=is.readLine();\r
- if( line==null ) break;\r
- line=line.trim();\r
- if( "".equals(line) || line.startsWith("#") ) continue;\r
-\r
- // for each mbean, create a proxy\r
- if(log.isDebugEnabled())\r
- log.debug("Read " + line);\r
-\r
- if(line.startsWith( "[")) {\r
- name=line.substring(1);\r
- if( name.endsWith("]")) {\r
- name=name.substring(0, name.length()-1);\r
- }\r
- }\r
- // Name/value pair\r
- int idx=line.indexOf('=');\r
- if( idx < 0 ) continue;\r
- att=line.substring(0, idx );\r
- val=line.substring(idx+1);\r
-\r
- if( log.isDebugEnabled())\r
- log.debug("name: " + name + " att=" + att +\r
- " val=" + val);\r
-\r
- MBeanProxy proxy=(MBeanProxy)mbeans.get(name);\r
- if( proxy==null ) {\r
- log.info( "Unknown object " + name);\r
- } else {\r
- proxy.update(att, val);\r
- cnt++;\r
- }\r
- }\r
- log.info( "Refreshing attributes " + cnt);\r
- } catch( Exception ex ) {\r
- log.info("Error ", ex);\r
- }\r
- }\r
-\r
- /** connect to apache, get a list of mbeans\r
- */\r
- BufferedReader getStream(String qry) throws Exception {\r
- try {\r
- String path=statusPath + "?" + qry;\r
- URL url=new URL( "http", webServerHost, webServerPort, path);\r
- URLConnection urlc=url.openConnection();\r
- BufferedReader is=new BufferedReader(new InputStreamReader(urlc.getInputStream()));\r
- return is;\r
- } catch (IOException e) {\r
- log.info( "Can't connect to jkstatus " + webServerHost + ":" + webServerPort\r
- + " " + e.toString());\r
- return null;\r
- }\r
- }\r
-\r
- public void refreshMetadata() {\r
- try {\r
- int cnt=0;\r
- int newCnt=0;\r
- BufferedReader is=getStream("lst=*");\r
- if( is==null ) return;\r
- String name=null;\r
- String type=null;\r
- ArrayList getters=new ArrayList();\r
- ArrayList setters=new ArrayList();\r
- ArrayList methods=new ArrayList();\r
- while(true) {\r
- String line=is.readLine();\r
- if( log.isDebugEnabled())\r
- log.debug("Read " + line);\r
-\r
- // end of section\r
- if( line == null || line.startsWith("[") ) {\r
- if( name != null ) {\r
- cnt++;\r
- if( mbeans.get( name ) ==null ) {\r
- // New component\r
- newCnt++;\r
- MBeanProxy mproxy=new MBeanProxy(this);\r
- mproxy.init( name, getters, setters, methods);\r
- mbeans.put( name, mproxy );\r
- }\r
- if( log.isDebugEnabled())\r
- log.debug("mbean name: " + name + " type=" + type);\r
-\r
- getters.clear();\r
- setters.clear();\r
- methods.clear();\r
- }\r
- }\r
- // end of data\r
- if( line==null ) break;\r
-\r
- line=line.trim();\r
- if( "".equals( line ) || line.startsWith("#")) continue;\r
-\r
- // for each mbean, create a proxy\r
-\r
- if(line.startsWith( "[") && line.endsWith("]")) {\r
- name=line.substring(1, line.length()-1);\r
- }\r
- if(line.startsWith( "T=")) {\r
- type=line.substring(2);\r
- }\r
- if( line.startsWith("G=")) {\r
- getters.add(line.substring(2));\r
- }\r
- if( line.startsWith("S=")) {\r
- setters.add(line.substring(2));\r
- }\r
- if( line.startsWith("M=")) {\r
- methods.add(line.substring(2));\r
- }\r
- }\r
- log.info( "Refreshing metadata " + cnt + " " + newCnt);\r
- } catch( Exception ex ) {\r
- log.info("Error ", ex);\r
- }\r
- }\r
-\r
- /** Use the same metadata, except that we replace the attribute\r
- * get/set methods.\r
- */\r
- static class MBeanProxy extends BaseModelMBean {\r
- private static Log log = LogFactory.getLog(MBeanProxy.class);\r
-\r
- String jkName;\r
- List getAttNames;\r
- List setAttNames;\r
- HashMap atts=new HashMap();\r
- ModJkMX jkmx;\r
-\r
- public MBeanProxy(ModJkMX jkmx) throws Exception {\r
- this.jkmx=jkmx;\r
- }\r
-\r
- void init( String name, List getters, List setters, List methods )\r
- throws Exception\r
- {\r
- if(log.isDebugEnabled())\r
- log.debug("Register " + name );\r
- int col=name.indexOf( ':' );\r
- this.jkName=name;\r
- String type=name.substring(0, col );\r
- String id=name.substring(col+1);\r
- id=id.replace('*','%');\r
- id=id.replace(':', '%');\r
- if( id.length() == 0 ) {\r
- id="default";\r
- }\r
- ManagedBean mbean= new ManagedBean();\r
-\r
- AttributeInfo ai=new AttributeInfo();\r
- ai.setName( "jkName" );\r
- ai.setType( "java.lang.String");\r
- ai.setWriteable(false);\r
- mbean.addAttribute(ai);\r
-\r
- for( int i=0; i<getters.size(); i++ ) {\r
- String att=(String)getters.get(i);\r
- // Register metadata\r
- ai=new AttributeInfo();\r
- ai.setName( att );\r
- ai.setType( "java.lang.String");\r
- if( ! setters.contains(att))\r
- ai.setWriteable(false);\r
- mbean.addAttribute(ai);\r
- }\r
- for( int i=0; i<setters.size(); i++ ) {\r
- String att=(String)setters.get(i);\r
- if( getters.contains(att))\r
- continue;\r
- // Register metadata\r
- ai=new AttributeInfo();\r
- ai.setName( att );\r
- ai.setType( "java.lang.String");\r
- ai.setReadable(false);\r
- mbean.addAttribute(ai);\r
- }\r
- for( int i=0; i<methods.size(); i++ ) {\r
- String att=(String)methods.get(i);\r
- // Register metadata\r
- OperationInfo oi=new OperationInfo();\r
- oi.setName( att );\r
- oi.setReturnType("void");\r
- mbean.addOperation(oi);\r
- }\r
-\r
- this.setModelMBeanInfo(mbean.createMBeanInfo());\r
-\r
- MBeanServer mserver=Registry.getRegistry(null, null).getMBeanServer();\r
- oname=new ObjectName("apache:type=" + type + ",id=" + id);\r
- mserver.registerMBean(this, oname);\r
- }\r
-\r
- private void update( String name, String val ) {\r
- log.debug( "Updating " + jkName + " " + name + " " + val);\r
- atts.put( name, val);\r
- }\r
-\r
- public Object getAttribute(String name)\r
- throws AttributeNotFoundException, MBeanException,\r
- ReflectionException {\r
- if( "jkName".equals( name )) {\r
- return jkName;\r
- }\r
- jkmx.refresh();\r
- return atts.get(name);\r
- }\r
-\r
- public void setAttribute(Attribute attribute)\r
- throws AttributeNotFoundException, MBeanException,\r
- ReflectionException\r
- {\r
- try {\r
- // we support only string values\r
- String val=(String)attribute.getValue();\r
- String name=attribute.getName();\r
- BufferedReader is=jkmx.getStream("set=" + jkName + "|" +\r
- name + "|" + val);\r
- if( is==null ) return;\r
- String res=is.readLine();\r
- if( log.isDebugEnabled())\r
- log.debug( "Setting " + jkName + " " + name + " result " + res);\r
-\r
- jkmx.refreshMetadata();\r
- jkmx.refreshAttributes();\r
- } catch( Exception ex ) {\r
- throw new MBeanException(ex);\r
- }\r
- }\r
-\r
- public Object invoke(String name, Object params[], String signature[])\r
- throws MBeanException, ReflectionException {\r
- try {\r
- // we support only string values\r
- BufferedReader is=jkmx.getStream("inv=" + jkName + "|" +\r
- name );\r
- if( is==null ) return null;\r
- String res=is.readLine();\r
- if( log.isDebugEnabled())\r
- log.debug( "Invoking " + jkName + " " + name + " result " + res);\r
-\r
- jkmx.refreshMetadata();\r
- jkmx.refreshAttributes();\r
- } catch( Exception ex ) {\r
- throw new MBeanException(ex);\r
- }\r
- return null;\r
- }\r
-\r
- }\r
-\r
-\r
-}\r
-\r