#base.path=/usr/local\r
\r
compile.source=1.5\r
-\r
-# ----- Servlet API v2.4 -----\r
-servlet-api.home=${base.path}/servlet-api-2.4\r
-servlet-api.lib=${servlet-api.home}/lib\r
-servlet-api.jar=${servlet-api.lib}/servlet-api.jar\r
+compile.target=1.5\r
\r
# ----- Commons Logging, version 1.0.1 or later -----\r
commons-logging.home=${base.path}/commons-logging-1.0.4\r
commons-logging.jar=${commons-logging.lib}/commons-logging.jar\r
commons-logging.loc=${base-jakarta.loc}/commons/logging/binaries/commons-logging-1.0.4.tar.gz\r
\r
-# ----- Commons Modeler, version 1.1 or later -----\r
-commons-modeler.home=${base.path}/commons-modeler-1.1\r
-commons-modeler.lib=${commons-modeler.home}\r
-commons-modeler.jar=${commons-modeler.lib}/commons-modeler.jar\r
-commons-modeler.loc=${base-jakarta.loc}/commons/modeler/binaries/modeler-1.1.tar.gz\r
-\r
# ----- Eclipse JDT, version 3.1.2 or later -----\r
jdt.home=${base.path}/eclipse/plugins\r
jdt.lib=${jdt.home}\r
<property name="compile.source" value="1.5"/>\r
\r
<!-- JAR artifacts -->\r
+ <property name="bootstrap.jar" value="${tomcat.build}/bin/bootstrap.jar"/>\r
+\r
<property name="servlet-api.jar" value="${tomcat.build}/lib/servlet-api.jar"/>\r
<property name="jsp-api.jar" value="${tomcat.build}/lib/jsp-api.jar"/>\r
<property name="el-api.jar" value="${tomcat.build}/lib/el-api.jar"/>\r
<property name="catalina.jar" value="${tomcat.build}/lib/catalina.jar"/>\r
<property name="catalina-ant.jar" value="${tomcat.build}/lib/catalina-ant.jar"/>\r
<property name="catalina-ant-jmx.jar" value="${tomcat.build}/lib/catalina-ant-jmx.jar"/>\r
- <property name="naming-factory.jar" value="${tomcat.build}/lib/naming-factory.jar"/>\r
- <property name="naming-resources.jar" value="${tomcat.build}/lib/naming-resources.jar"/>\r
- <property name="servlets-cgi.jar" value="${tomcat.build}/lib/servlets-cgi.renametojar"/>\r
- <property name="servlets-default.jar" value="${tomcat.build}/lib/servlets-default.jar"/>\r
- <property name="servlets-invoker.jar" value="${tomcat.build}/lib/servlets-invoker.jar"/>\r
- <property name="servlets-ssi.jar" value="${tomcat.build}/lib/servlets-ssi.renametojar"/>\r
- <property name="servlets-webdav.jar" value="${tomcat.build}/lib/servlets-webdav.jar"/>\r
- <property name="tomcat-util.jar" value="${tomcat.build}/lib/tomcat-util.jar"/>\r
<property name="tomcat-coyote.jar" value="${tomcat.build}/lib/tomcat-coyote.jar"/>\r
- <property name="tomcat-apr.jar" value="${tomcat.build}/lib/tomcat-apr.jar"/>\r
- <property name="tomcat-ajp.jar" value="${tomcat.build}/lib/tomcat-ajp.jar"/>\r
- <property name="tomcat-http.jar" value="${tomcat.build}/lib/tomcat-http.jar"/>\r
\r
- <property name="jasper-compiler.jar" value="${tomcat.build}/lib/jasper-compiler.jar"/>\r
- <property name="jasper-runtime.jar" value="${tomcat.build}/lib/jasper-runtime.jar"/>\r
+ <property name="jasper.jar" value="${tomcat.build}/lib/jasper.jar"/>\r
<property name="jasper-el.jar" value="${tomcat.build}/lib/jasper-el.jar"/>\r
\r
<!-- Classpath -->\r
<pathelement location="${ant.jar}"/>\r
<pathelement location="${jdt.jar}"/>\r
<pathelement location="${commons-logging.jar}"/>\r
- <pathelement location="${commons-modeler.jar}"/>\r
</path>\r
\r
<!-- Just build Tomcat -->\r
<mkdir dir="${tomcat.build}/bin"/>\r
<mkdir dir="${tomcat.build}/conf"/>\r
<mkdir dir="${tomcat.build}/lib"/>\r
+ <mkdir dir="${tomcat.build}/webapps"/>\r
\r
</target>\r
\r
<exclude name="org/apache/naming/factory/SendMailFactory.java"/>\r
</javac>\r
<!-- Copy static resource files -->\r
- <copy todir="${tomcat.classes}">\r
+ <filter token="VERSION" value="${version}"/>\r
+ <copy todir="${tomcat.classes}" filtering="true">\r
<fileset dir="java">\r
<include name="**/*.properties"/>\r
<include name="**/*.dtd"/>\r
+ <include name="**/*.xsd"/>\r
</fileset>\r
</copy>\r
\r
<target name="package" > \r
\r
<!-- Servlet 2.5 Implementation JAR File -->\r
- <jar jarfile="${servlet-api.jar}" index="true">\r
+ <jar jarfile="${servlet-api.jar}">\r
<fileset dir="${tomcat.classes}">\r
<include name="javax/servlet/*" />\r
<include name="javax/servlet/http/*" />\r
</jar>\r
\r
<!-- JSP 2.1 Implementation JAR File -->\r
- <jar jarfile="${jsp-api.jar}" index="true">\r
+ <jar jarfile="${jsp-api.jar}">\r
<fileset dir="${tomcat.classes}">\r
<include name="javax/servlet/jsp/**" />\r
<!-- Javadoc and i18n exclusions -->\r
</jar>\r
\r
<!-- JSP 2.1 EL Implementation JAR File -->\r
- <jar jarfile="${el-api.jar}" index="true">\r
+ <jar jarfile="${el-api.jar}">\r
<fileset dir="${tomcat.classes}">\r
<include name="javax/el/**" />\r
<!-- Javadoc and i18n exclusions -->\r
</fileset>\r
</jar>\r
\r
+ <!-- Bootstrap JAR File -->\r
+ <jar jarfile="${bootstrap.jar}" \r
+ manifest="res/bootstrap.jar.manifest">\r
+ <fileset dir="${tomcat.classes}">\r
+ <include name="org/apache/catalina/startup/Bootstrap.class" />\r
+ <include name="org/apache/catalina/startup/catalina.properties" />\r
+ <include name="org/apache/catalina/startup/CatalinaProperties.class" />\r
+ <include name="org/apache/catalina/startup/ClassLoaderFactory.class" />\r
+ <include name="org/apache/catalina/startup/Tool.class" />\r
+ <include name="org/apache/catalina/loader/StandardClassLoader*.class" />\r
+ <include name="org/apache/catalina/loader/Extension.class" />\r
+ <include name="org/apache/catalina/loader/Reloader.class" />\r
+ <include name="org/apache/catalina/security/SecurityClassLoad.class" />\r
+ <include name="org/apache/naming/JndiPermission.class" />\r
+ <include name="org/apache/tomcat/util/compat/*" />\r
+ <!-- Javadoc and i18n exclusions -->\r
+ <exclude name="**/package.html" />\r
+ <exclude name="**/LocalStrings_*" />\r
+ </fileset>\r
+ </jar>\r
+\r
<!-- Catalina Main JAR File -->\r
- <jar jarfile="${catalina.jar}" index="true" manifest="res/bootstrap.jar.manifest">\r
+ <jar jarfile="${catalina.jar}">\r
<fileset dir="${tomcat.classes}">\r
<include name="org/apache/catalina/**" />\r
+ <include name="org/apache/naming/**" />\r
<!-- Javadoc and i18n exclusions -->\r
<exclude name="**/package.html" />\r
<exclude name="**/LocalStrings_*" />\r
<exclude name="org/apache/catalina/ant/**" />\r
<exclude name="org/apache/catalina/cluster/**" />\r
<exclude name="org/apache/catalina/launcher/**" />\r
- <exclude name="org/apache/catalina/servlets/**" />\r
<exclude name="org/apache/catalina/storeconfig/**" />\r
- <exclude name="org/apache/catalina/ssi/**" />\r
</fileset>\r
</jar>\r
\r
<!-- Catalina Ant Tasks JAR File -->\r
- <jar jarfile="${catalina-ant.jar}" index="true">\r
+ <jar jarfile="${catalina-ant.jar}">\r
<fileset dir="${tomcat.classes}">\r
<include name="org/apache/catalina/ant/*" />\r
<include name="org/apache/catalina/util/Base64.class" />\r
</jar>\r
\r
<!-- Catalina JMX Accessor Ant Tasks JAR File -->\r
- <jar jarfile="${catalina-ant-jmx.jar}" index="true">\r
+ <jar jarfile="${catalina-ant-jmx.jar}">\r
<fileset dir="${tomcat.classes}">\r
<include name="org/apache/catalina/ant/jmx/*" />\r
<!-- Javadoc and i18n exclusions -->\r
</fileset>\r
</jar>\r
\r
- <!-- Naming - Factory JAR File -->\r
- <jar jarfile="${naming-factory.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/naming/**" />\r
- <exclude name="org/apache/naming/resources/**" />\r
- <exclude name="org/apache/naming/JndiPermission.class" />\r
- <exclude name="org/apache/naming/NameParserImpl.class" />\r
- <exclude name="org/apache/naming/NamingContextBindingsEnumeration.class" />\r
- <exclude name="org/apache/naming/NamingContextEnumeration.class" />\r
- <exclude name="org/apache/naming/NamingEntry.class" />\r
- <exclude name="org/apache/naming/StringManager.class" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
- <!-- Naming - Resources JAR File -->\r
- <jar jarfile="${naming-resources.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/naming/JndiPermission.class" />\r
- <include name="org/apache/naming/NameParserImpl.class" />\r
- <include name="org/apache/naming/NamingContextBindingsEnumeration.class" />\r
- <include name="org/apache/naming/NamingContextEnumeration.class" />\r
- <include name="org/apache/naming/NamingEntry.class" />\r
- <include name="org/apache/naming/StringManager.class" />\r
- <include name="org/apache/naming/resources/**" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
- <!-- Servlets - CGI Servlet -->\r
- <jar jarfile="${servlets-cgi.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/catalina/servlets/CGI*" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
- <!-- Servlets - Default File-Serving Servlet -->\r
- <jar jarfile="${servlets-default.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/catalina/servlets/Default*" />\r
- <include name="org/apache/catalina/servlets/Constants.class" />\r
- <include name="org/apache/catalina/servlets/LocalStrings.properties" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
- <!-- Servlets - Invoker Servlet -->\r
- <jar jarfile="${servlets-invoker.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/catalina/servlets/Invoker*" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
- <!-- Servlets - SSI Servlet -->\r
- <jar jarfile="${servlets-ssi.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/catalina/ssi/**" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
- <!-- Servlets - Webdav Servlet -->\r
- <jar jarfile="${servlets-webdav.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/catalina/servlets/Webdav*" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
<!-- Protocol handlers - Coyote -->\r
- <jar jarfile="${tomcat-coyote.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/coyote/*" />\r
- <include name="org/apache/coyote/memory/*" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
- <!-- Protocol handlers - APR -->\r
- <jar jarfile="${tomcat-apr.jar}" index="true">\r
+ <jar jarfile="${tomcat-coyote.jar}">\r
<fileset dir="${tomcat.classes}">\r
+ <include name="org/apache/coyote/**" />\r
<include name="org/apache/tomcat/jni/**" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
- <!-- Protocol handlers - HTTP -->\r
- <jar jarfile="${tomcat-http.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/coyote/http11/**" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
- <!-- Protocol handlers - AJP -->\r
- <jar jarfile="${tomcat-ajp.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/coyote/ajp/**" />\r
<include name="org/apache/jk/**" />\r
- <exclude name="org/apache/jk/ant/**" />\r
+ <include name="org/apache/tomcat/util/**" />\r
<!-- Javadoc and i18n exclusions -->\r
<exclude name="**/package.html" />\r
<exclude name="**/LocalStrings_*" />\r
</fileset>\r
</jar>\r
\r
- <!-- Util JAR File -->\r
- <jar jarfile="${tomcat-util.jar}" index="true">\r
+ <!-- Jasper Implementation JAR File -->\r
+ <jar jarfile="${jasper.jar}">\r
<fileset dir="${tomcat.classes}">\r
- <include name="org/apache/tomcat/util/**" />\r
+ <include name="org/apache/jasper/**" />\r
<!-- Javadoc and i18n exclusions -->\r
<exclude name="**/package.html" />\r
<exclude name="**/LocalStrings_*" />\r
</fileset>\r
</jar>\r
\r
- <!-- Jasper Compiler JAR File -->\r
- <jar jarfile="${jasper-compiler.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/jasper/compiler/**" />\r
- <include name="org/apache/jasper/xmlparser/**" />\r
- <include name="org/apache/jasper/servlet/**" />\r
- <include name="org/apache/jasper/tagplugins/**" />\r
- <exclude name="org/apache/jasper/Constants.class" />\r
- <exclude name="org/apache/jasper/JasperException.class" />\r
- <include name="org/apache/jasper/*.class" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
- <!-- Jasper Runtime JAR File -->\r
- <jar jarfile="${jasper-runtime.jar}" index="true">\r
- <fileset dir="${tomcat.classes}">\r
- <include name="org/apache/jasper/Constants.class" />\r
- <include name="org/apache/jasper/JasperException.class" />\r
- <include name="org/apache/jasper/compiler/Localizer.class" />\r
- <include name="org/apache/jasper/el/**" />\r
- <include name="org/apache/jasper/resources/**" />\r
- <include name="org/apache/jasper/runtime/**" />\r
- <include name="org/apache/jasper/security/**" />\r
- <include name="org/apache/jasper/util/**" />\r
- <!-- Javadoc and i18n exclusions -->\r
- <exclude name="**/package.html" />\r
- <exclude name="**/LocalStrings_*" />\r
- </fileset>\r
- </jar>\r
-\r
<!-- Jasper EL Implementation JAR File -->\r
- <jar jarfile="${jasper-el.jar}" index="true">\r
+ <jar jarfile="${jasper-el.jar}">\r
<fileset dir="${tomcat.classes}">\r
<include name="org/apache/el/**" />\r
<!-- Javadoc and i18n exclusions -->\r
\r
<target name="deploy" depends="build-only">\r
\r
- <copy file="${commons-logging-api.jar}" todir="${tomcat.build}/lib" />\r
+ <copy file="${commons-logging-api.jar}" todir="${tomcat.build}/bin" />\r
\r
<!-- Copy static resource files -->\r
<copy todir="${tomcat.build}/conf">\r
</fileset>\r
</copy>\r
\r
+ <!-- Temp: Copy webapps -->\r
+ <copy todir="${tomcat.build}/webapps">\r
+ <fileset dir="webapps">\r
+ <include name="ROOT/**"/>\r
+ </fileset>\r
+ </copy>\r
+\r
</target>\r
\r
<target name="clean">\r
try {\r
MBeanInfo minfo = jmxServerConnection.getMBeanInfo(oname);\r
String code = minfo.getClassName();\r
- if ("org.apache.commons.modeler.BaseModelMBean".equals(code)) {\r
+ if ("org.apache.tomcat.util.modeler.BaseModelMBean".equals(code)) {\r
code = (String) jmxServerConnection.getAttribute(oname,\r
"modelerType");\r
}\r
import org.apache.catalina.util.StringManager;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.coyote.Adapter;\r
import org.apache.coyote.ProtocolHandler;\r
import org.apache.tomcat.util.IntrospectionUtils;\r
import org.apache.tomcat.util.http.mapper.Mapper;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
\r
-import org.apache.commons.modeler.Registry;\r
\r
import org.apache.tomcat.util.http.mapper.Mapper;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
import org.apache.tomcat.util.res.StringManager;\r
\r
import org.apache.catalina.util.StringManager;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.naming.resources.ProxyDirContext;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.catalina.util.StringManager;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.naming.ContextAccessController;\r
import org.apache.naming.ContextBindings;\r
import org.apache.naming.EjbRef;\r
import org.apache.naming.ResourceLinkRef;\r
import org.apache.naming.ResourceRef;\r
import org.apache.naming.TransactionRef;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.catalina.util.URLEncoder;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.naming.ContextBindings;\r
import org.apache.naming.resources.BaseDirContext;\r
import org.apache.naming.resources.DirContextURLStreamHandler;\r
import org.apache.naming.resources.ProxyDirContext;\r
import org.apache.naming.resources.WARDirContext;\r
import org.apache.tomcat.util.compat.JdkCompat;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
/**\r
* Standard implementation of the <b>Context</b> interface. Each\r
import org.apache.catalina.util.ServerInfo;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.commons.modeler.Registry;\r
-import org.apache.commons.modeler.modules.MbeansSource;\r
+import org.apache.tomcat.util.modeler.Registry;\r
+import org.apache.tomcat.util.modeler.modules.MbeansSource;\r
\r
/**\r
* Standard implementation of the <b>Engine</b> interface. Each\r
import org.apache.catalina.Valve;\r
import org.apache.catalina.startup.HostConfig;\r
import org.apache.catalina.valves.ValveBase;\r
-import org.apache.commons.modeler.Registry;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.catalina.valves.ValveBase;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.commons.modeler.Registry;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.catalina.util.ServerInfo;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.tomcat.util.buf.StringCache;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
\r
import org.apache.catalina.util.StringManager;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.commons.modeler.Registry;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.catalina.util.InstanceSupport;\r
import org.apache.tomcat.util.IntrospectionUtils;\r
import org.apache.tomcat.util.log.SystemLogHandler;\r
-import org.apache.commons.modeler.Registry;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
/**\r
* Standard implementation of the <b>Wrapper</b> interface that represents\r
import org.apache.catalina.core.StandardContext;\r
import org.apache.catalina.util.LifecycleSupport;\r
import org.apache.catalina.util.StringManager;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.naming.resources.DirContextURLStreamHandler;\r
import org.apache.naming.resources.DirContextURLStreamHandlerFactory;\r
import org.apache.naming.resources.Resource;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
\r
import javax.management.MBeanException;\r
import javax.management.RuntimeOperationsException;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
+\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
\r
\r
/**\r
\r
import org.apache.catalina.deploy.ContextEnvironment;\r
import org.apache.catalina.deploy.NamingResources;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
\r
\r
/**\r
\r
import org.apache.catalina.deploy.ContextResourceLink;\r
import org.apache.catalina.deploy.NamingResources;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
\r
\r
/**\r
\r
import org.apache.catalina.deploy.ContextResource;\r
import org.apache.catalina.deploy.NamingResources;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
\r
\r
/**\r
import org.apache.catalina.deploy.ContextResource;\r
import org.apache.catalina.deploy.ContextResourceLink;\r
import org.apache.catalina.deploy.NamingResources;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
-import org.apache.commons.modeler.ManagedBean;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.tomcat.util.compat.JdkCompat;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
/**\r
* <p>A <strong>ModelMBean</strong> implementation for the\r
import org.apache.catalina.Role;\r
import org.apache.catalina.User;\r
import org.apache.catalina.UserDatabase;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.catalina.Group;\r
import org.apache.catalina.Role;\r
import org.apache.catalina.User;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
-import org.apache.commons.modeler.ManagedBean;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.tomcat.util.compat.JdkCompat;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
/**\r
* <p>A <strong>ModelMBean</strong> implementation for the\r
import org.apache.catalina.valves.RemoteHostValve;\r
import org.apache.catalina.valves.RequestDumperValve;\r
import org.apache.catalina.valves.ValveBase;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
-import org.apache.commons.modeler.Registry;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.catalina.valves.ValveBase;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.commons.modeler.ManagedBean;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.tomcat.util.IntrospectionUtils;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.catalina.Role;\r
import org.apache.catalina.User;\r
import org.apache.catalina.UserDatabase;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
-import org.apache.commons.modeler.ManagedBean;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.tomcat.util.compat.JdkCompat;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
/**\r
* <p>A <strong>ModelMBean</strong> implementation for the\r
import org.apache.catalina.deploy.ContextResource;\r
import org.apache.catalina.deploy.ContextResourceLink;\r
import org.apache.catalina.deploy.NamingResources;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
-import org.apache.commons.modeler.ManagedBean;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.tomcat.util.compat.JdkCompat;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
/**\r
* <p>A <strong>ModelMBean</strong> implementation for the\r
import javax.management.MBeanServer;\r
import javax.management.RuntimeOperationsException;\r
\r
-import org.apache.commons.modeler.BaseModelMBean;\r
-import org.apache.commons.modeler.ManagedBean;\r
-import org.apache.commons.modeler.Registry;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.catalina.deploy.ContextResource;\r
import org.apache.catalina.deploy.ContextResourceLink;\r
import org.apache.catalina.deploy.NamingResources;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
-import org.apache.commons.modeler.ManagedBean;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.tomcat.util.compat.JdkCompat;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
/**\r
* <p>A <strong>ModelMBean</strong> implementation for the\r
import javax.management.MBeanServer;\r
import javax.management.RuntimeOperationsException;\r
\r
-import org.apache.commons.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
\r
\r
/**\r
\r
import org.apache.catalina.Valve;\r
import org.apache.catalina.core.StandardHost;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
-import org.apache.commons.modeler.ManagedBean;\r
-import org.apache.commons.modeler.Registry;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.catalina.Server;\r
import org.apache.catalina.ServerFactory;\r
import org.apache.catalina.core.StandardServer;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
\r
\r
/**\r
import javax.management.MBeanServer;\r
import javax.management.RuntimeOperationsException;\r
\r
-import org.apache.commons.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
\r
\r
/**\r
import org.apache.catalina.Group;\r
import org.apache.catalina.Role;\r
import org.apache.catalina.User;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
-import org.apache.commons.modeler.ManagedBean;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.tomcat.util.compat.JdkCompat;\r
+import org.apache.tomcat.util.modeler.BaseModelMBean;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
/**\r
* <p>A <strong>ModelMBean</strong> implementation for the\r
import org.apache.catalina.util.StringManager;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.commons.modeler.Registry;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
/**\r
* Simple implementation of <b>Realm</b> that reads an XML file to configure\r
import org.apache.catalina.util.StringManager;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.commons.modeler.Registry;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import org.apache.catalina.core.ContainerBase;\r
import org.apache.catalina.core.StandardHost;\r
import org.apache.catalina.util.StringManager;\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.tomcat.util.digester.Digester;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import javax.management.MBeanServer;\r
import javax.management.ObjectName;\r
\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.coyote.ActionCode;\r
import org.apache.coyote.ActionHook;\r
import org.apache.coyote.Adapter;\r
import org.apache.coyote.ProtocolHandler;\r
import org.apache.coyote.RequestGroupInfo;\r
import org.apache.coyote.RequestInfo;\r
+import org.apache.tomcat.util.modeler.Registry;\r
import org.apache.tomcat.util.net.AprEndpoint;\r
import org.apache.tomcat.util.net.AprEndpoint.Handler;\r
import org.apache.tomcat.util.res.StringManager;\r
import javax.management.MBeanServer;\r
import javax.management.ObjectName;\r
\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.coyote.ActionCode;\r
import org.apache.coyote.ActionHook;\r
import org.apache.coyote.Adapter;\r
import org.apache.coyote.ProtocolHandler;\r
import org.apache.coyote.RequestGroupInfo;\r
import org.apache.coyote.RequestInfo;\r
+import org.apache.tomcat.util.modeler.Registry;\r
import org.apache.tomcat.util.net.AprEndpoint;\r
import org.apache.tomcat.util.net.AprEndpoint.Handler;\r
import org.apache.tomcat.util.res.StringManager;\r
import javax.management.MBeanServer;\r
import javax.management.ObjectName;\r
\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.coyote.RequestInfo;\r
+import org.apache.tomcat.util.modeler.Registry;\r
import org.apache.tomcat.util.threads.ThreadPool;\r
import org.apache.tomcat.util.threads.ThreadWithAttributes;\r
\r
import javax.management.NotificationListener;\r
import javax.management.ObjectName;\r
\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.jk.core.JkHandler;\r
import org.apache.jk.core.Msg;\r
import org.apache.jk.core.MsgContext;\r
import org.apache.coyote.Request;\r
import org.apache.coyote.RequestGroupInfo;\r
import org.apache.coyote.RequestInfo;\r
+import org.apache.tomcat.util.modeler.Registry;\r
import org.apache.tomcat.util.threads.ThreadPool;\r
import org.apache.tomcat.util.threads.ThreadPoolRunnable;\r
\r
import javax.management.NotificationListener;\r
import javax.management.ObjectName;\r
\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.jk.core.JkHandler;\r
import org.apache.jk.core.Msg;\r
import org.apache.jk.core.MsgContext;\r
import org.apache.coyote.Request;\r
import org.apache.coyote.RequestGroupInfo;\r
import org.apache.coyote.RequestInfo;\r
+import org.apache.tomcat.util.modeler.Registry;\r
import org.apache.tomcat.util.threads.ThreadPool;\r
import org.apache.tomcat.util.threads.ThreadPoolRunnable;\r
\r
import java.io.IOException;\r
import javax.management.ObjectName;\r
\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.jk.core.JkHandler;\r
import org.apache.jk.core.Msg;\r
import org.apache.jk.core.MsgContext;\r
import org.apache.coyote.Request;\r
import org.apache.coyote.RequestGroupInfo;\r
import org.apache.coyote.RequestInfo;\r
+import org.apache.tomcat.util.modeler.Registry;\r
import org.apache.tomcat.util.threads.ThreadPool;\r
import org.apache.tomcat.util.threads.ThreadPoolRunnable;\r
\r
\r
import javax.management.ObjectName;\r
\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.jk.apr.AprImpl;\r
import org.apache.jk.core.JkHandler;\r
import org.apache.jk.core.Msg;\r
import org.apache.tomcat.util.buf.ByteChunk;\r
import org.apache.tomcat.util.buf.C2BConverter;\r
import org.apache.tomcat.util.buf.MessageBytes;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
\r
/**\r
import javax.management.ObjectName;\r
\r
import org.apache.jk.core.JkHandler;\r
-import org.apache.commons.modeler.Registry;\r
-import org.apache.commons.modeler.BaseModelMBean;\r
-import org.apache.commons.modeler.ManagedBean;\r
-import org.apache.commons.modeler.AttributeInfo;\r
-import org.apache.commons.modeler.OperationInfo;\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
import javax.management.NotificationListener;\r
import javax.management.ObjectName;\r
\r
-import org.apache.commons.modeler.Registry;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
/**\r
*\r
import javax.management.MBeanServer;\r
import javax.management.ObjectName;\r
\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.coyote.Adapter;\r
import org.apache.coyote.ProtocolHandler;\r
import org.apache.coyote.Request;\r
import org.apache.tomcat.util.buf.MessageBytes;\r
import org.apache.tomcat.util.http.HttpMessages;\r
import org.apache.tomcat.util.http.MimeHeaders;\r
+import org.apache.tomcat.util.modeler.Registry;\r
import org.apache.tomcat.util.net.SSLSupport;\r
\r
/** Plugs Jk into Coyote. Must be named "type=JkHandler,name=container"\r
import javax.management.MBeanServer;\r
import javax.management.ObjectName;\r
\r
-import org.apache.commons.modeler.Registry;\r
import org.apache.jk.core.JkHandler;\r
import org.apache.jk.core.WorkerEnv;\r
import org.apache.tomcat.util.IntrospectionUtils;\r
+import org.apache.tomcat.util.modeler.Registry;\r
\r
/** Main class used to startup and configure jk. It manages the conf/jk2.properties file\r
* and is the target of JMX proxy.\r
--- /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
+package org.apache.tomcat.util;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.io.StringReader;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.transform.OutputKeys;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerException;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.dom.DOMSource;\r
+import javax.xml.transform.stream.StreamResult;\r
+\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.NamedNodeMap;\r
+import org.w3c.dom.Node;\r
+import org.xml.sax.EntityResolver;\r
+import org.xml.sax.InputSource;\r
+import org.xml.sax.SAXException;\r
+\r
+\r
+/**\r
+ * Few simple utils to read DOM\r
+ *\r
+ * @author Costin Manolache\r
+ */\r
+public class DomUtil {\r
+ private static org.apache.commons.logging.Log log=\r
+ org.apache.commons.logging.LogFactory.getLog( DomUtil.class );\r
+\r
+ // -------------------- DOM utils --------------------\r
+\r
+ /** Get the trimed text content of a node or null if there is no text\r
+ */\r
+ public static String getContent(Node n ) {\r
+ if( n==null ) return null;\r
+ Node n1=DomUtil.getChild(n, Node.TEXT_NODE);\r
+\r
+ if( n1==null ) return null;\r
+\r
+ String s1=n1.getNodeValue();\r
+ return s1.trim();\r
+ }\r
+\r
+ /** Get the first element child.\r
+ * @param parent lookup direct childs\r
+ * @param name name of the element. If null return the first element.\r
+ */\r
+ public static Node getChild( Node parent, String name ) {\r
+ if( parent==null ) return null;\r
+ Node first=parent.getFirstChild();\r
+ if( first==null ) return null;\r
+\r
+ for (Node node = first; node != null;\r
+ node = node.getNextSibling()) {\r
+ //System.out.println("getNode: " + name + " " + node.getNodeName());\r
+ if( node.getNodeType()!=Node.ELEMENT_NODE)\r
+ continue;\r
+ if( name != null &&\r
+ name.equals( node.getNodeName() ) ) {\r
+ return node;\r
+ }\r
+ if( name == null ) {\r
+ return node;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public static String getAttribute(Node element, String attName ) {\r
+ NamedNodeMap attrs=element.getAttributes();\r
+ if( attrs==null ) return null;\r
+ Node attN=attrs.getNamedItem(attName);\r
+ if( attN==null ) return null;\r
+ return attN.getNodeValue();\r
+ }\r
+\r
+ public static void setAttribute(Node node, String attName, String val) {\r
+ NamedNodeMap attributes=node.getAttributes();\r
+ Node attNode=node.getOwnerDocument().createAttribute(attName);\r
+ attNode.setNodeValue( val );\r
+ attributes.setNamedItem(attNode);\r
+ }\r
+ \r
+ public static void removeAttribute( Node node, String attName ) {\r
+ NamedNodeMap attributes=node.getAttributes();\r
+ attributes.removeNamedItem(attName); \r
+ }\r
+ \r
+ \r
+ /** Set or replace the text value \r
+ */ \r
+ public static void setText(Node node, String val) {\r
+ Node chld=DomUtil.getChild(node, Node.TEXT_NODE);\r
+ if( chld == null ) {\r
+ Node textN=node.getOwnerDocument().createTextNode(val);\r
+ node.appendChild(textN);\r
+ return;\r
+ }\r
+ // change the value\r
+ chld.setNodeValue(val); \r
+ }\r
+\r
+ /** Find the first direct child with a given attribute.\r
+ * @param parent\r
+ * @param elemName name of the element, or null for any \r
+ * @param attName attribute we're looking for\r
+ * @param attVal attribute value or null if we just want any\r
+ */ \r
+ public static Node findChildWithAtt(Node parent, String elemName,\r
+ String attName, String attVal) {\r
+ \r
+ Node child=DomUtil.getChild(parent, Node.ELEMENT_NODE);\r
+ if( attVal== null ) {\r
+ while( child!= null &&\r
+ ( elemName==null || elemName.equals( child.getNodeName())) && \r
+ DomUtil.getAttribute(child, attName) != null ) {\r
+ child=getNext(child, elemName, Node.ELEMENT_NODE );\r
+ }\r
+ } else {\r
+ while( child!= null && \r
+ ( elemName==null || elemName.equals( child.getNodeName())) && \r
+ ! attVal.equals( DomUtil.getAttribute(child, attName)) ) {\r
+ child=getNext(child, elemName, Node.ELEMENT_NODE );\r
+ }\r
+ }\r
+ return child; \r
+ } \r
+ \r
+\r
+ /** Get the first child's content ( ie it's included TEXT node ).\r
+ */\r
+ public static String getChildContent( Node parent, String name ) {\r
+ Node first=parent.getFirstChild();\r
+ if( first==null ) return null;\r
+ for (Node node = first; node != null;\r
+ node = node.getNextSibling()) {\r
+ //System.out.println("getNode: " + name + " " + node.getNodeName());\r
+ if( name.equals( node.getNodeName() ) ) {\r
+ return getContent( node );\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /** Get the first direct child with a given type\r
+ */\r
+ public static Node getChild( Node parent, int type ) {\r
+ Node n=parent.getFirstChild();\r
+ while( n!=null && type != n.getNodeType() ) {\r
+ n=n.getNextSibling();\r
+ }\r
+ if( n==null ) return null;\r
+ return n;\r
+ }\r
+\r
+ /** Get the next sibling with the same name and type\r
+ */\r
+ public static Node getNext( Node current ) {\r
+ String name=current.getNodeName();\r
+ int type=current.getNodeType();\r
+ return getNext( current, name, type);\r
+ }\r
+\r
+ /** Return the next sibling with a given name and type\r
+ */ \r
+ public static Node getNext( Node current, String name, int type) {\r
+ Node first=current.getNextSibling();\r
+ if( first==null ) return null;\r
+\r
+ for (Node node = first; node != null;\r
+ node = node.getNextSibling()) {\r
+ \r
+ if( type >= 0 && node.getNodeType() != type ) continue;\r
+ //System.out.println("getNode: " + name + " " + node.getNodeName());\r
+ if( name==null )\r
+ return node;\r
+ if( name.equals( node.getNodeName() ) ) {\r
+ return node;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public static class NullResolver implements EntityResolver {\r
+ public InputSource resolveEntity (String publicId,\r
+ String systemId)\r
+ throws SAXException, IOException\r
+ {\r
+ if( log.isTraceEnabled())\r
+ log.trace("ResolveEntity: " + publicId + " " + systemId);\r
+ return new InputSource(new StringReader(""));\r
+ }\r
+ }\r
+\r
+ public static void setAttributes( Object o, Node parent)\r
+ {\r
+ NamedNodeMap attrs=parent.getAttributes();\r
+ if( attrs==null ) return;\r
+\r
+ for (int i=0; i<attrs.getLength(); i++ ) {\r
+ Node n=attrs.item(i);\r
+ String name=n.getNodeName();\r
+ String value=n.getNodeValue();\r
+\r
+ if( log.isTraceEnabled() )\r
+ log.trace("Attribute " + parent.getNodeName() + " " +\r
+ name + "=" + value);\r
+ try {\r
+ IntrospectionUtils.setProperty(o, name, value);\r
+ } catch( Exception ex ) {\r
+ ex.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+\r
+ /** Read XML as DOM.\r
+ */\r
+ public static Document readXml(InputStream is)\r
+ throws SAXException, IOException, ParserConfigurationException\r
+ {\r
+ DocumentBuilderFactory dbf =\r
+ DocumentBuilderFactory.newInstance();\r
+\r
+ dbf.setValidating(false);\r
+ dbf.setIgnoringComments(false);\r
+ dbf.setIgnoringElementContentWhitespace(true);\r
+ //dbf.setCoalescing(true);\r
+ //dbf.setExpandEntityReferences(true);\r
+\r
+ DocumentBuilder db = null;\r
+ db = dbf.newDocumentBuilder();\r
+ db.setEntityResolver( new NullResolver() );\r
+\r
+ // db.setErrorHandler( new MyErrorHandler());\r
+\r
+ Document doc = db.parse(is);\r
+ return doc;\r
+ }\r
+\r
+ public static void writeXml( Node n, OutputStream os )\r
+ throws TransformerException\r
+ {\r
+ TransformerFactory tf=TransformerFactory.newInstance();\r
+ //identity\r
+ Transformer t=tf.newTransformer();\r
+ t.setOutputProperty(OutputKeys.INDENT, "yes");\r
+ t.transform(new DOMSource( n ), new StreamResult( os ));\r
+ }\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.io.Serializable;\r
+import java.lang.reflect.Method;\r
+\r
+import javax.management.Descriptor;\r
+import javax.management.modelmbean.ModelMBeanAttributeInfo;\r
+\r
+\r
+/**\r
+ * <p>Internal configuration information for an <code>Attribute</code>\r
+ * descriptor.</p>\r
+ *\r
+ * @author Craig R. McClanahan\r
+ * @version $Revision: 155428 $ $Date: 2005-02-26 14:12:25 +0100 (sam., 26 févr. 2005) $\r
+ */\r
+\r
+public class AttributeInfo extends FeatureInfo implements Serializable {\r
+ static final long serialVersionUID = -2511626862303972143L;\r
+\r
+ // ----------------------------------------------------- Instance Variables\r
+\r
+\r
+ /**\r
+ * The <code>ModelMBeanAttributeInfo</code> object that corresponds\r
+ * to this <code>AttributeInfo</code> instance.\r
+ */\r
+ protected transient ModelMBeanAttributeInfo info = null;\r
+ protected String displayName = null;\r
+ protected String getMethod = null;\r
+ protected String setMethod = null;\r
+\r
+ protected transient Method getMethodObj = null;\r
+ protected transient Method setMethodObj = null;\r
+\r
+ protected boolean readable = true;\r
+ protected boolean writeable = true;\r
+\r
+ protected boolean is = false;\r
+ protected String type = null;\r
+\r
+ protected String persist;\r
+ protected String defaultStringValue;\r
+ // ------------------------------------------------------------- Properties\r
+\r
+\r
+ /**\r
+ * Override the <code>description</code> property setter.\r
+ *\r
+ * @param description The new description\r
+ */\r
+ public void setDescription(String description) {\r
+ super.setDescription(description);\r
+ this.info = null;\r
+ }\r
+\r
+ /**\r
+ * Override the <code>name</code> property setter.\r
+ *\r
+ * @param name The new name\r
+ */\r
+ public void setName(String name) {\r
+ super.setName(name);\r
+ this.info = null;\r
+ }\r
+\r
+ /**\r
+ * The display name of this attribute.\r
+ */\r
+ public String getDisplayName() {\r
+ return (this.displayName);\r
+ }\r
+\r
+ public void setDisplayName(String displayName) {\r
+ this.displayName = displayName;\r
+ }\r
+\r
+ /**\r
+ * The name of the property getter method, if non-standard.\r
+ */\r
+ public String getGetMethod() {\r
+ return (this.getMethod);\r
+ }\r
+\r
+ public void setGetMethod(String getMethod) {\r
+ this.getMethod = getMethod;\r
+ this.info = null;\r
+ }\r
+\r
+ public Method getGetMethodObj() {\r
+ return getMethodObj;\r
+ }\r
+\r
+ public void setGetMethodObj(Method getMethodObj) {\r
+ this.getMethodObj = getMethodObj;\r
+ }\r
+\r
+ public Method getSetMethodObj() {\r
+ return setMethodObj;\r
+ }\r
+\r
+ public void setSetMethodObj(Method setMethodObj) {\r
+ this.setMethodObj = setMethodObj;\r
+ }\r
+\r
+ /**\r
+ * Is this a boolean attribute with an "is" getter?\r
+ */\r
+ public boolean isIs() {\r
+ return (this.is);\r
+ }\r
+\r
+ public void setIs(boolean is) {\r
+ this.is = is;\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * Is this attribute readable by management applications?\r
+ */\r
+ public boolean isReadable() {\r
+ return (this.readable);\r
+ }\r
+\r
+ public void setReadable(boolean readable) {\r
+ this.readable = readable;\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * The name of the property setter method, if non-standard.\r
+ */\r
+ public String getSetMethod() {\r
+ return (this.setMethod);\r
+ }\r
+\r
+ public void setSetMethod(String setMethod) {\r
+ this.setMethod = setMethod;\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * The fully qualified Java class name of this attribute.\r
+ */\r
+ public String getType() {\r
+ return (this.type);\r
+ }\r
+\r
+ public void setType(String type) {\r
+ this.type = type;\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * Is this attribute writeable by management applications?\r
+ */\r
+ public boolean isWriteable() {\r
+ return (this.writeable);\r
+ }\r
+\r
+ public void setWriteable(boolean writeable) {\r
+ this.writeable = writeable;\r
+ this.info = null;\r
+ }\r
+\r
+ /** Persistence policy.\r
+ * All persistent attributes should have this attribute set.\r
+ * Valid values:\r
+ * ???\r
+ */\r
+ public String getPersist() {\r
+ return persist;\r
+ }\r
+\r
+ public void setPersist(String persist) {\r
+ this.persist = persist;\r
+ }\r
+\r
+ /** Default value. If set, it can provide info to the user and\r
+ * it can be used by persistence mechanism to generate a more compact\r
+ * representation ( a value may not be saved if it's default )\r
+ */\r
+ public String getDefault() {\r
+ return defaultStringValue;\r
+ }\r
+\r
+ public void setDefault(String defaultStringValue) {\r
+ this.defaultStringValue = defaultStringValue;\r
+ }\r
+\r
+\r
+ // --------------------------------------------------------- Public Methods\r
+\r
+\r
+ /**\r
+ * Create and return a <code>ModelMBeanAttributeInfo</code> object that\r
+ * corresponds to the attribute described by this instance.\r
+ */\r
+ public ModelMBeanAttributeInfo createAttributeInfo() {\r
+ // Return our cached information (if any)\r
+ if (info != null)\r
+ return (info);\r
+ if((getMethodObj != null) || (setMethodObj != null) ) {\r
+ try {\r
+ info=new ModelMBeanAttributeInfo(getName(), getDescription(),\r
+ getMethodObj, setMethodObj);\r
+ return info;\r
+ } catch( Exception ex) {\r
+ ex.printStackTrace();\r
+ }\r
+ }\r
+\r
+ // Create and return a new information object\r
+ info = new ModelMBeanAttributeInfo\r
+ (getName(), getType(), getDescription(),\r
+ isReadable(), isWriteable(), false);\r
+ Descriptor descriptor = info.getDescriptor();\r
+ if (getDisplayName() != null)\r
+ descriptor.setField("displayName", getDisplayName());\r
+ if (isReadable()) {\r
+ if (getGetMethod() != null)\r
+ descriptor.setField("getMethod", getGetMethod());\r
+ else\r
+ descriptor.setField("getMethod",\r
+ getMethodName(getName(), true, isIs()));\r
+ }\r
+ if (isWriteable()) {\r
+ if (getSetMethod() != null)\r
+ descriptor.setField("setMethod", getSetMethod());\r
+ else\r
+ descriptor.setField("setMethod",\r
+ getMethodName(getName(), false, false));\r
+ }\r
+ addFields(descriptor);\r
+ info.setDescriptor(descriptor);\r
+ return (info);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Return a string representation of this attribute descriptor.\r
+ */\r
+ public String toString() {\r
+\r
+ StringBuffer sb = new StringBuffer("AttributeInfo[");\r
+ sb.append("name=");\r
+ sb.append(name);\r
+ sb.append(", description=");\r
+ sb.append(description);\r
+ if (!readable) {\r
+ sb.append(", readable=");\r
+ sb.append(readable);\r
+ }\r
+ sb.append(", type=");\r
+ sb.append(type);\r
+ if (!writeable) {\r
+ sb.append(", writeable=");\r
+ sb.append(writeable);\r
+ }\r
+ sb.append("]");\r
+ return (sb.toString());\r
+\r
+ }\r
+\r
+\r
+ // -------------------------------------------------------- Private Methods\r
+\r
+\r
+ /**\r
+ * Create and return the name of a default property getter or setter\r
+ * method, according to the specified values.\r
+ *\r
+ * @param name Name of the property itself\r
+ * @param getter Do we want a get method (versus a set method)?\r
+ * @param is If returning a getter, do we want the "is" form?\r
+ */\r
+ private String getMethodName(String name, boolean getter, boolean is) {\r
+\r
+ StringBuffer sb = new StringBuffer();\r
+ if (getter) {\r
+ if (is)\r
+ sb.append("is");\r
+ else\r
+ sb.append("get");\r
+ } else\r
+ sb.append("set");\r
+ sb.append(Character.toUpperCase(name.charAt(0)));\r
+ sb.append(name.substring(1));\r
+ return (sb.toString());\r
+\r
+ }\r
+\r
+\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.util.HashSet;\r
+\r
+import javax.management.AttributeChangeNotification;\r
+import javax.management.Notification;\r
+import javax.management.NotificationFilter;\r
+\r
+\r
+/**\r
+ * <p>Implementation of <code>NotificationFilter</code> for attribute change\r
+ * notifications. This class is used by <code>BaseModelMBean</code> to\r
+ * construct attribute change notification event filters when a filter is not\r
+ * supplied by the application.</p>\r
+ *\r
+ * @author Craig R. McClanahan\r
+ * @version $Revision: 155428 $ $Date: 2005-02-26 14:12:25 +0100 (sam., 26 févr. 2005) $\r
+ */\r
+\r
+public class BaseAttributeFilter implements NotificationFilter {\r
+\r
+\r
+ // ----------------------------------------------------------- Constructors\r
+\r
+\r
+ /**\r
+ * Construct a new filter that accepts only the specified attribute\r
+ * name.\r
+ *\r
+ * @param name Name of the attribute to be accepted by this filter, or\r
+ * <code>null</code> to accept all attribute names\r
+ */\r
+ public BaseAttributeFilter(String name) {\r
+\r
+ super();\r
+ if (name != null)\r
+ addAttribute(name);\r
+\r
+ }\r
+\r
+\r
+ // ----------------------------------------------------- Instance Variables\r
+\r
+\r
+ /**\r
+ * The set of attribute names that are accepted by this filter. If this\r
+ * list is empty, all attribute names are accepted.\r
+ */\r
+ private HashSet names = new HashSet();\r
+\r
+\r
+ // --------------------------------------------------------- Public Methods\r
+\r
+\r
+ /**\r
+ * Add a new attribute name to the set of names accepted by this filter.\r
+ *\r
+ * @param name Name of the attribute to be accepted\r
+ */\r
+ public void addAttribute(String name) {\r
+\r
+ synchronized (names) {\r
+ names.add(name);\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Clear all accepted names from this filter, so that it will accept\r
+ * all attribute names.\r
+ */\r
+ public void clear() {\r
+\r
+ synchronized (names) {\r
+ names.clear();\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Return the set of names that are accepted by this filter. If this\r
+ * filter accepts all attribute names, a zero length array will be\r
+ * returned.\r
+ */\r
+ public String[] getNames() {\r
+\r
+ synchronized (names) {\r
+ return ((String[]) names.toArray(new String[names.size()]));\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * <p>Test whether notification enabled for this event.\r
+ * Return true if:</p>\r
+ * <ul>\r
+ * <li>This is an attribute change notification</li>\r
+ * <li>Either the set of accepted names is empty (implying that all\r
+ * attribute names are of interest) or the set of accepted names\r
+ * includes the name of the attribute in this notification</li>\r
+ * </ul>\r
+ */\r
+ public boolean isNotificationEnabled(Notification notification) {\r
+\r
+ if (notification == null)\r
+ return (false);\r
+ if (!(notification instanceof AttributeChangeNotification))\r
+ return (false);\r
+ AttributeChangeNotification acn =\r
+ (AttributeChangeNotification) notification;\r
+ if (!AttributeChangeNotification.ATTRIBUTE_CHANGE.equals(acn.getType()))\r
+ return (false);\r
+ synchronized (names) {\r
+ if (names.size() < 1)\r
+ return (true);\r
+ else\r
+ return (names.contains(acn.getAttributeName()));\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Remove an attribute name from the set of names accepted by this\r
+ * filter.\r
+ *\r
+ * @param name Name of the attribute to be removed\r
+ */\r
+ public void removeAttribute(String name) {\r
+\r
+ synchronized (names) {\r
+ names.remove(name);\r
+ }\r
+\r
+ }\r
+\r
+\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.util.HashMap;\r
+import java.util.Hashtable;\r
+import java.util.Iterator;\r
+\r
+import javax.management.Attribute;\r
+import javax.management.AttributeChangeNotification;\r
+import javax.management.AttributeList;\r
+import javax.management.AttributeNotFoundException;\r
+import javax.management.Descriptor;\r
+import javax.management.DynamicMBean;\r
+import javax.management.InstanceNotFoundException;\r
+import javax.management.InvalidAttributeValueException;\r
+import javax.management.ListenerNotFoundException;\r
+import javax.management.MBeanException;\r
+import javax.management.MBeanInfo;\r
+import javax.management.MBeanNotificationInfo;\r
+import javax.management.MBeanRegistration;\r
+import javax.management.MBeanServer;\r
+import javax.management.Notification;\r
+import javax.management.NotificationFilter;\r
+import javax.management.NotificationListener;\r
+import javax.management.ObjectName;\r
+import javax.management.ReflectionException;\r
+import javax.management.RuntimeErrorException;\r
+import javax.management.RuntimeOperationsException;\r
+import javax.management.ServiceNotFoundException;\r
+import javax.management.modelmbean.DescriptorSupport;\r
+import javax.management.modelmbean.InvalidTargetObjectTypeException;\r
+import javax.management.modelmbean.ModelMBean;\r
+import javax.management.modelmbean.ModelMBeanAttributeInfo;\r
+import javax.management.modelmbean.ModelMBeanInfo;\r
+import javax.management.modelmbean.ModelMBeanInfoSupport;\r
+import javax.management.modelmbean.ModelMBeanNotificationInfo;\r
+import javax.management.modelmbean.ModelMBeanOperationInfo;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.apache.tomcat.util.modeler.modules.ModelerSource;\r
+\r
+// TODO: enable ant-like substitutions ? ( or at least discuss it )\r
+\r
+/**\r
+ * <p>Basic implementation of the <code>ModelMBean</code> interface, which\r
+ * supports the minimal requirements of the interface contract.</p>\r
+ *\r
+ * <p>This can be used directly to wrap an existing java bean, or inside\r
+ * an mlet or anywhere an MBean would be used. The String parameter\r
+ * passed to the constructor will be used to construct an instance of the\r
+ * real object that we wrap.\r
+ *\r
+ * Limitations:\r
+ * <ul>\r
+ * <li>Only managed resources of type <code>objectReference</code> are\r
+ * supportd.</li>\r
+ * <li>Caching of attribute values and operation results is not supported.\r
+ * All calls to <code>invoke()</code> are immediately executed.</li>\r
+ * <li>Logging (under control of descriptors) is not supported.</li>\r
+ * <li>Persistence of MBean attributes and operations is not supported.</li>\r
+ * <li>All classes referenced as attribute types, operation parameters, or\r
+ * operation return values must be one of the following:\r
+ * <ul>\r
+ * <li>One of the Java primitive types (boolean, byte, char, double,\r
+ * float, integer, long, short). Corresponding value will be wrapped\r
+ * in the appropriate wrapper class automatically.</li>\r
+ * <li>Operations that return no value should declare a return type of\r
+ * <code>void</code>.</li>\r
+ * </ul>\r
+ * <li>Attribute caching is not supported</li>\r
+ * </ul>\r
+ *\r
+ * @author Craig R. McClanahan\r
+ * @author Costin Manolache\r
+ * @version $Revision: 383269 $ $Date: 2006-03-05 03:22:41 +0100 (dim., 05 mars 2006) $\r
+ */\r
+\r
+public class BaseModelMBean implements ModelMBean, MBeanRegistration {\r
+ private static Log log = LogFactory.getLog(BaseModelMBean.class);\r
+\r
+ // ----------------------------------------------------------- Constructors\r
+\r
+ /**\r
+ * Construct a <code>ModelMBean</code> with default\r
+ * <code>ModelMBeanInfo</code> information.\r
+ *\r
+ * @exception MBeanException if the initializer of an object\r
+ * throws an exception\r
+ * @exception RuntimeOperationsException if an IllegalArgumentException\r
+ * occurs\r
+ */\r
+ public BaseModelMBean() throws MBeanException, RuntimeOperationsException {\r
+\r
+ super();\r
+ if( log.isDebugEnabled()) log.debug("default constructor");\r
+ setModelMBeanInfo(createDefaultModelMBeanInfo());\r
+ }\r
+\r
+\r
+ /**\r
+ * Construct a <code>ModelMBean</code> associated with the specified\r
+ * <code>ModelMBeanInfo</code> information.\r
+ *\r
+ * @param info ModelMBeanInfo for this MBean\r
+ *\r
+ * @exception MBeanException if the initializer of an object\r
+ * throws an exception\r
+ * @exception RuntimeOperationsException if an IllegalArgumentException\r
+ * occurs\r
+ */\r
+ public BaseModelMBean(ModelMBeanInfo info)\r
+ throws MBeanException, RuntimeOperationsException {\r
+ // XXX should be deprecated - just call setInfo\r
+ super();\r
+ setModelMBeanInfo(info);\r
+ if( log.isDebugEnabled()) log.debug("ModelMBeanInfo constructor");\r
+ }\r
+\r
+ /** Construct a ModelMBean of a specified type.\r
+ * The type can be a class name or the key used in one of the descriptors.\r
+ *\r
+ * If no descriptor is available, we'll first try to locate one in\r
+ * the same package with the class, then use introspection.\r
+ *\r
+ * The mbean resource will be created.\r
+ *\r
+ * @param type Class name or the type key used in the descriptor.\r
+ * @throws MBeanException\r
+ * @throws RuntimeOperationsException\r
+ */\r
+ public BaseModelMBean( String type )\r
+ throws MBeanException, RuntimeOperationsException\r
+ {\r
+ try {\r
+ // This constructor is used from <mlet>, it should create\r
+ // the resource\r
+ setModeledType(type);\r
+ } catch( Throwable ex ) {\r
+ log.error( "Error creating mbean ", ex);\r
+ }\r
+ }\r
+\r
+ public BaseModelMBean( String type, ModelerSource source )\r
+ throws MBeanException, RuntimeOperationsException\r
+ {\r
+ try {\r
+ setModeledType(type);\r
+ } catch( Throwable ex ) {\r
+ log.error( "Error creating mbean ", ex);\r
+ }\r
+ this.source=source;\r
+ }\r
+\r
+ // ----------------------------------------------------- Instance Variables\r
+\r
+\r
+ /**\r
+ * Notification broadcaster for attribute changes.\r
+ */\r
+ protected BaseNotificationBroadcaster attributeBroadcaster = null;\r
+\r
+ /** Registry we are associated with\r
+ */\r
+ protected Registry registry=null;\r
+\r
+ /**\r
+ * Notification broadcaster for general notifications.\r
+ */\r
+ protected BaseNotificationBroadcaster generalBroadcaster = null;\r
+\r
+ protected ObjectName oname=null;\r
+\r
+ /**\r
+ * The <code>ModelMBeanInfo</code> object that controls our activity.\r
+ */\r
+ protected ModelMBeanInfo info = null;\r
+\r
+\r
+ /**\r
+ * The managed resource this MBean is associated with (if any).\r
+ */\r
+ protected Object resource = null;\r
+ protected String resourceType = null;\r
+\r
+ /** Source object used to read this mbean. Can be used to\r
+ * persist the mbean\r
+ */\r
+ protected ModelerSource source=null;\r
+\r
+ /** Attribute values. XXX That can be stored in the value Field\r
+ */\r
+ protected HashMap attributes=new HashMap();\r
+\r
+ // --------------------------------------------------- DynamicMBean Methods\r
+ static final Object[] NO_ARGS_PARAM=new Object[0];\r
+ static final Class[] NO_ARGS_PARAM_SIG=new Class[0];\r
+ // key: attribute val: getter method\r
+ private Hashtable getAttMap=new Hashtable();\r
+\r
+ // key: attribute val: setter method\r
+ private Hashtable setAttMap=new Hashtable();\r
+\r
+ // key: operation val: invoke method\r
+ private Hashtable invokeAttMap=new Hashtable();\r
+\r
+ /**\r
+ * Obtain and return the value of a specific attribute of this MBean.\r
+ *\r
+ * @param name Name of the requested attribute\r
+ *\r
+ * @exception AttributeNotFoundException if this attribute is not\r
+ * supported by this MBean\r
+ * @exception MBeanException if the initializer of an object\r
+ * throws an exception\r
+ * @exception ReflectionException if a Java reflection exception\r
+ * occurs when invoking the getter\r
+ */\r
+ public Object getAttribute(String name)\r
+ throws AttributeNotFoundException, MBeanException,\r
+ ReflectionException {\r
+ // Validate the input parameters\r
+ if (name == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Attribute name is null"),\r
+ "Attribute name is null");\r
+\r
+ if( (resource instanceof DynamicMBean) && \r
+ ! ( resource instanceof BaseModelMBean )) {\r
+ return ((DynamicMBean)resource).getAttribute(name);\r
+ }\r
+ \r
+ // Extract the method from cache\r
+ Method m=(Method)getAttMap.get( name );\r
+\r
+ if( m==null ) {\r
+ // Look up the actual operation to be used\r
+ ModelMBeanAttributeInfo attrInfo = info.getAttribute(name);\r
+ if (attrInfo == null)\r
+ throw new AttributeNotFoundException(" Cannot find attribute " + name);\r
+ Descriptor attrDesc = attrInfo.getDescriptor();\r
+ if (attrDesc == null)\r
+ throw new AttributeNotFoundException("Cannot find attribute " + name + " descriptor");\r
+ String getMethod = (String) attrDesc.getFieldValue("getMethod");\r
+\r
+ if (getMethod == null)\r
+ throw new AttributeNotFoundException("Cannot find attribute " + name + " get method name");\r
+\r
+ Object object = null;\r
+ NoSuchMethodException exception = null;\r
+ try {\r
+ object = this;\r
+ m = object.getClass().getMethod(getMethod, NO_ARGS_PARAM_SIG);\r
+ } catch (NoSuchMethodException e) {\r
+ exception = e;;\r
+ }\r
+ if( m== null && resource != null ) {\r
+ try {\r
+ object = resource;\r
+ m = object.getClass().getMethod(getMethod, NO_ARGS_PARAM_SIG);\r
+ exception=null;\r
+ } catch (NoSuchMethodException e) {\r
+ exception = e;\r
+ }\r
+ }\r
+ if( exception != null )\r
+ throw new ReflectionException(exception,\r
+ "Cannot find getter method " + getMethod);\r
+ getAttMap.put( name, m );\r
+ }\r
+\r
+ Object result = null;\r
+ try {\r
+ Class declaring=m.getDeclaringClass();\r
+ // workaround for catalina weird mbeans - the declaring class is BaseModelMBean.\r
+ // but this is the catalina class.\r
+ if( declaring.isAssignableFrom(this.getClass()) ) {\r
+ result = m.invoke(this, NO_ARGS_PARAM );\r
+ } else {\r
+ result = m.invoke(resource, NO_ARGS_PARAM );\r
+ }\r
+ } catch (InvocationTargetException e) {\r
+ Throwable t = e.getTargetException();\r
+ if (t == null)\r
+ t = e;\r
+ if (t instanceof RuntimeException)\r
+ throw new RuntimeOperationsException\r
+ ((RuntimeException) t, "Exception invoking method " + name);\r
+ else if (t instanceof Error)\r
+ throw new RuntimeErrorException\r
+ ((Error) t, "Error invoking method " + name);\r
+ else\r
+ throw new MBeanException\r
+ (e, "Exception invoking method " + name);\r
+ } catch (Exception e) {\r
+ throw new MBeanException\r
+ (e, "Exception invoking method " + name);\r
+ }\r
+\r
+ // Return the results of this method invocation\r
+ // FIXME - should we validate the return type?\r
+ return (result);\r
+ }\r
+\r
+\r
+ /**\r
+ * Obtain and return the values of several attributes of this MBean.\r
+ *\r
+ * @param names Names of the requested attributes\r
+ */\r
+ public AttributeList getAttributes(String names[]) {\r
+\r
+ // Validate the input parameters\r
+ if (names == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Attribute names list is null"),\r
+ "Attribute names list is null");\r
+\r
+ // Prepare our response, eating all exceptions\r
+ AttributeList response = new AttributeList();\r
+ for (int i = 0; i < names.length; i++) {\r
+ try {\r
+ response.add(new Attribute(names[i],getAttribute(names[i])));\r
+ } catch (Exception e) {\r
+ ; // Not having a particular attribute in the response\r
+ ; // is the indication of a getter problem\r
+ }\r
+ }\r
+ return (response);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Return the <code>MBeanInfo</code> object for this MBean.\r
+ */\r
+ public MBeanInfo getMBeanInfo() {\r
+ // XXX Why do we have to clone ?\r
+ if( info== null ) return null;\r
+ return ((MBeanInfo) info.clone());\r
+ }\r
+\r
+\r
+ /**\r
+ * Invoke a particular method on this MBean, and return any returned\r
+ * value.\r
+ *\r
+ * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation will\r
+ * attempt to invoke this method on the MBean itself, or (if not\r
+ * available) on the managed resource object associated with this\r
+ * MBean.</p>\r
+ *\r
+ * @param name Name of the operation to be invoked\r
+ * @param params Array containing the method parameters of this operation\r
+ * @param signature Array containing the class names representing\r
+ * the signature of this operation\r
+ *\r
+ * @exception MBeanException if the initializer of an object\r
+ * throws an exception\r
+ * @exception ReflectioNException if a Java reflection exception\r
+ * occurs when invoking a method\r
+ */\r
+ public Object invoke(String name, Object params[], String signature[])\r
+ throws MBeanException, ReflectionException \r
+ {\r
+ if( (resource instanceof DynamicMBean) && \r
+ ! ( resource instanceof BaseModelMBean )) {\r
+ return ((DynamicMBean)resource).invoke(name, params, signature);\r
+ }\r
+ \r
+ // Validate the input parameters\r
+ if (name == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Method name is null"),\r
+ "Method name is null");\r
+\r
+ if( log.isDebugEnabled()) log.debug("Invoke " + name);\r
+ MethodKey mkey = new MethodKey(name, signature);\r
+ Method method=(Method)invokeAttMap.get(mkey);\r
+ if( method==null ) {\r
+ if (params == null)\r
+ params = new Object[0];\r
+ if (signature == null)\r
+ signature = new String[0];\r
+ if (params.length != signature.length)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Inconsistent arguments and signature"),\r
+ "Inconsistent arguments and signature");\r
+\r
+ // Acquire the ModelMBeanOperationInfo information for\r
+ // the requested operation\r
+ ModelMBeanOperationInfo opInfo = info.getOperation(name);\r
+ if (opInfo == null)\r
+ throw new MBeanException\r
+ (new ServiceNotFoundException("Cannot find operation " + name),\r
+ "Cannot find operation " + name);\r
+\r
+ // Prepare the signature required by Java reflection APIs\r
+ // FIXME - should we use the signature from opInfo?\r
+ Class types[] = new Class[signature.length];\r
+ for (int i = 0; i < signature.length; i++) {\r
+ types[i]=getAttributeClass( signature[i] );\r
+ }\r
+\r
+ // Locate the method to be invoked, either in this MBean itself\r
+ // or in the corresponding managed resource\r
+ // FIXME - Accessible methods in superinterfaces?\r
+ Object object = null;\r
+ Exception exception = null;\r
+ try {\r
+ object = this;\r
+ method = object.getClass().getMethod(name, types);\r
+ } catch (NoSuchMethodException e) {\r
+ exception = e;;\r
+ }\r
+ try {\r
+ if ((method == null) && (resource != null)) {\r
+ object = resource;\r
+ method = object.getClass().getMethod(name, types);\r
+ }\r
+ } catch (NoSuchMethodException e) {\r
+ exception = e;\r
+ }\r
+ if (method == null) {\r
+ throw new ReflectionException(exception,\r
+ "Cannot find method " + name +\r
+ " with this signature");\r
+ }\r
+ invokeAttMap.put( mkey, method );\r
+ }\r
+\r
+ // Invoke the selected method on the appropriate object\r
+ Object result = null;\r
+ try {\r
+ if( method.getDeclaringClass().isAssignableFrom( this.getClass()) ) {\r
+ result = method.invoke(this, params );\r
+ } else {\r
+ result = method.invoke(resource, params);\r
+ }\r
+ } catch (InvocationTargetException e) {\r
+ Throwable t = e.getTargetException();\r
+ log.error("Exception invoking method " + name , t );\r
+ if (t == null)\r
+ t = e;\r
+ if (t instanceof RuntimeException)\r
+ throw new RuntimeOperationsException\r
+ ((RuntimeException) t, "Exception invoking method " + name);\r
+ else if (t instanceof Error)\r
+ throw new RuntimeErrorException\r
+ ((Error) t, "Error invoking method " + name);\r
+ else\r
+ throw new MBeanException\r
+ ((Exception)t, "Exception invoking method " + name);\r
+ } catch (Exception e) {\r
+ log.error("Exception invoking method " + name , e );\r
+ throw new MBeanException\r
+ (e, "Exception invoking method " + name);\r
+ }\r
+\r
+ // Return the results of this method invocation\r
+ // FIXME - should we validate the return type?\r
+ return (result);\r
+\r
+ }\r
+\r
+ private Class getAttributeClass(String signature)\r
+ throws ReflectionException\r
+ {\r
+ if (signature.equals(Boolean.TYPE.getName()))\r
+ return Boolean.TYPE;\r
+ else if (signature.equals(Byte.TYPE.getName()))\r
+ return Byte.TYPE;\r
+ else if (signature.equals(Character.TYPE.getName()))\r
+ return Character.TYPE;\r
+ else if (signature.equals(Double.TYPE.getName()))\r
+ return Double.TYPE;\r
+ else if (signature.equals(Float.TYPE.getName()))\r
+ return Float.TYPE;\r
+ else if (signature.equals(Integer.TYPE.getName()))\r
+ return Integer.TYPE;\r
+ else if (signature.equals(Long.TYPE.getName()))\r
+ return Long.TYPE;\r
+ else if (signature.equals(Short.TYPE.getName()))\r
+ return Short.TYPE;\r
+ else {\r
+ try {\r
+ ClassLoader cl=Thread.currentThread().getContextClassLoader();\r
+ if( cl!=null )\r
+ return cl.loadClass(signature); \r
+ } catch( ClassNotFoundException e ) {\r
+ }\r
+ try {\r
+ return Class.forName(signature);\r
+ } catch (ClassNotFoundException e) {\r
+ throw new ReflectionException\r
+ (e, "Cannot find Class for " + signature);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set the value of a specific attribute of this MBean.\r
+ *\r
+ * @param attribute The identification of the attribute to be set\r
+ * and the new value\r
+ *\r
+ * @exception AttributeNotFoundException if this attribute is not\r
+ * supported by this MBean\r
+ * @exception MBeanException if the initializer of an object\r
+ * throws an exception\r
+ * @exception ReflectionException if a Java reflection exception\r
+ * occurs when invoking the getter\r
+ */\r
+ public void setAttribute(Attribute attribute)\r
+ throws AttributeNotFoundException, MBeanException,\r
+ ReflectionException\r
+ {\r
+ if( log.isDebugEnabled() )\r
+ log.debug("Setting attribute " + this + " " + attribute );\r
+\r
+ if( (resource instanceof DynamicMBean) && \r
+ ! ( resource instanceof BaseModelMBean )) {\r
+ try {\r
+ ((DynamicMBean)resource).setAttribute(attribute);\r
+ } catch (InvalidAttributeValueException e) {\r
+ throw new MBeanException(e); \r
+ }\r
+ return;\r
+ }\r
+ \r
+ // Validate the input parameters\r
+ if (attribute == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Attribute is null"),\r
+ "Attribute is null");\r
+\r
+ String name = attribute.getName();\r
+ Object value = attribute.getValue();\r
+\r
+ if (name == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Attribute name is null"),\r
+ "Attribute name is null");\r
+\r
+ ModelMBeanAttributeInfo attrInfo=info.getAttribute(name);\r
+ if (attrInfo == null)\r
+ throw new AttributeNotFoundException("Cannot find attribute " + name);\r
+\r
+ Descriptor attrDesc=attrInfo.getDescriptor();\r
+ if (attrDesc == null)\r
+ throw new AttributeNotFoundException("Cannot find attribute " + name + " descriptor");\r
+\r
+ Object oldValue=null;\r
+ if( getAttMap.get(name) != null )\r
+ oldValue=getAttribute( name );\r
+\r
+\r
+ // Extract the method from cache\r
+ Method m=(Method)setAttMap.get( name );\r
+\r
+ if( m==null ) {\r
+ // Look up the actual operation to be used\r
+ String setMethod = (String) attrDesc.getFieldValue("setMethod");\r
+ if (setMethod == null)\r
+ throw new AttributeNotFoundException("Cannot find attribute " + name + " set method name");\r
+\r
+ String argType=attrInfo.getType();\r
+\r
+ Class signature[] = new Class[] { getAttributeClass( argType ) };\r
+\r
+ Object object = null;\r
+ NoSuchMethodException exception = null;\r
+ try {\r
+ object = this;\r
+ m = object.getClass().getMethod(setMethod, signature);\r
+ } catch (NoSuchMethodException e) {\r
+ exception = e;;\r
+ }\r
+ if( m== null && resource != null ) {\r
+ try {\r
+ object = resource;\r
+ m = object.getClass().getMethod(setMethod, signature);\r
+ exception=null;\r
+ } catch (NoSuchMethodException e) {\r
+ if( log.isDebugEnabled())\r
+ log.debug("Method not found in resource " +resource);\r
+ exception = e;\r
+ }\r
+ }\r
+ if( exception != null )\r
+ throw new ReflectionException(exception,\r
+ "Cannot find setter method " + setMethod +\r
+ " " + resource);\r
+ setAttMap.put( name, m );\r
+ }\r
+\r
+ Object result = null;\r
+ try {\r
+ if( m.getDeclaringClass().isAssignableFrom( this.getClass()) ) {\r
+ result = m.invoke(this, new Object[] { value });\r
+ } else {\r
+ result = m.invoke(resource, new Object[] { value });\r
+ }\r
+ } catch (InvocationTargetException e) {\r
+ Throwable t = e.getTargetException();\r
+ if (t == null)\r
+ t = e;\r
+ if (t instanceof RuntimeException)\r
+ throw new RuntimeOperationsException\r
+ ((RuntimeException) t, "Exception invoking method " + name);\r
+ else if (t instanceof Error)\r
+ throw new RuntimeErrorException\r
+ ((Error) t, "Error invoking method " + name);\r
+ else\r
+ throw new MBeanException\r
+ (e, "Exception invoking method " + name);\r
+ } catch (Exception e) {\r
+ log.error("Exception invoking method " + name , e );\r
+ throw new MBeanException\r
+ (e, "Exception invoking method " + name);\r
+ }\r
+ try {\r
+ sendAttributeChangeNotification(new Attribute( name, oldValue),\r
+ attribute);\r
+ } catch(Exception ex) {\r
+ log.error("Error sending notification " + name, ex);\r
+ }\r
+ attributes.put( name, value );\r
+ if( source != null ) {\r
+ // this mbean is asscoiated with a source - maybe we want to persist\r
+ source.updateField(oname, name, value);\r
+ }\r
+ }\r
+\r
+ public String toString() {\r
+ if( resource==null ) \r
+ return "BaseModelMbean[" + resourceType + "]";\r
+ return resource.toString();\r
+ }\r
+\r
+ /**\r
+ * Set the values of several attributes of this MBean.\r
+ *\r
+ * @param attributes THe names and values to be set\r
+ *\r
+ * @return The list of attributes that were set and their new values\r
+ */\r
+ public AttributeList setAttributes(AttributeList attributes) {\r
+\r
+ // Validate the input parameters\r
+ if (attributes == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Attributes list is null"),\r
+ "Attributes list is null");\r
+\r
+ // Prepare and return our response, eating all exceptions\r
+ AttributeList response = new AttributeList();\r
+ String names[] = new String[attributes.size()];\r
+ int n = 0;\r
+ Iterator items = attributes.iterator();\r
+ while (items.hasNext()) {\r
+ Attribute item = (Attribute) items.next();\r
+ names[n++] = item.getName();\r
+ try {\r
+ setAttribute(item);\r
+ } catch (Exception e) {\r
+ ; // Ignore all exceptions\r
+ }\r
+ }\r
+\r
+ return (getAttributes(names));\r
+\r
+ }\r
+\r
+\r
+ // ----------------------------------------------------- ModelMBean Methods\r
+\r
+\r
+ /**\r
+ * Get the instance handle of the object against which we execute\r
+ * all methods in this ModelMBean management interface.\r
+ *\r
+ * @exception InstanceNotFoundException if the managed resource object\r
+ * cannot be found\r
+ * @exception MBeanException if the initializer of the object throws\r
+ * an exception\r
+ * @exception RuntimeOperationsException if the managed resource or the\r
+ * resource type is <code>null</code> or invalid\r
+ */\r
+ public Object getManagedResource()\r
+ throws InstanceNotFoundException, InvalidTargetObjectTypeException,\r
+ MBeanException, RuntimeOperationsException {\r
+\r
+ if (resource == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Managed resource is null"),\r
+ "Managed resource is null");\r
+\r
+ return resource;\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Set the instance handle of the object against which we will execute\r
+ * all methods in this ModelMBean management interface.\r
+ *\r
+ * This method will detect and call "setModelMbean" method. A resource\r
+ * can implement this method to get a reference to the model mbean.\r
+ * The reference can be used to send notification and access the\r
+ * registry.\r
+ *\r
+ * @param resource The resource object to be managed\r
+ * @param type The type of reference for the managed resource\r
+ * ("ObjectReference", "Handle", "IOR", "EJBHandle", or\r
+ * "RMIReference")\r
+ *\r
+ * @exception InstanceNotFoundException if the managed resource object\r
+ * cannot be found\r
+ * @exception InvalidTargetObjectTypeException if this ModelMBean is\r
+ * asked to handle a reference type it cannot deal with\r
+ * @exception MBeanException if the initializer of the object throws\r
+ * an exception\r
+ * @exception RuntimeOperationsException if the managed resource or the\r
+ * resource type is <code>null</code> or invalid\r
+ */\r
+ public void setManagedResource(Object resource, String type)\r
+ throws InstanceNotFoundException, InvalidTargetObjectTypeException,\r
+ MBeanException, RuntimeOperationsException\r
+ {\r
+ if (resource == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Managed resource is null"),\r
+ "Managed resource is null");\r
+\r
+ if (!"objectreference".equalsIgnoreCase(type))\r
+ throw new InvalidTargetObjectTypeException(type);\r
+\r
+ this.resource = resource;\r
+ this.resourceType = resource.getClass().getName();\r
+ \r
+ // Make the resource aware of the model mbean.\r
+ try {\r
+ Method m=resource.getClass().getMethod("setModelMBean",\r
+ new Class[] {ModelMBean.class});\r
+ if( m!= null ) {\r
+ m.invoke(resource, new Object[] {this});\r
+ }\r
+ } catch( NoSuchMethodException t ) {\r
+ // ignore\r
+ } catch( Throwable t ) {\r
+ log.error( "Can't set model mbean ", t );\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * Initialize the <code>ModelMBeanInfo</code> associated with this\r
+ * <code>ModelMBean</code>. After the information and associated\r
+ * descriptors have been customized, the <code>ModelMBean</code> should\r
+ * be registered with the associated <code>MBeanServer</code>.\r
+ *\r
+ * Currently the model can be set after registration. This behavior is\r
+ * deprecated and won't be supported in future versions.\r
+ *\r
+ * @param info The ModelMBeanInfo object to be used by this ModelMBean\r
+ *\r
+ * @exception MBeanException If an exception occurs recording this\r
+ * ModelMBeanInfo information\r
+ * @exception RuntimeOperations if the specified parameter is\r
+ * <code>null</code> or invalid\r
+ */\r
+ public void setModelMBeanInfo(ModelMBeanInfo info)\r
+ throws MBeanException, RuntimeOperationsException {\r
+\r
+ if (info == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("ModelMBeanInfo is null"),\r
+ "ModelMBeanInfo is null");\r
+\r
+ if (!isModelMBeanInfoValid(info))\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("ModelMBeanInfo is invalid"),\r
+ "ModelMBeanInfo is invalid");\r
+\r
+ this.info = (ModelMBeanInfo) info.clone();\r
+\r
+ }\r
+\r
+\r
+ // ------------------------------ ModelMBeanNotificationBroadcaster Methods\r
+\r
+\r
+ /**\r
+ * Add an attribute change notification event listener to this MBean.\r
+ *\r
+ * @param listener Listener that will receive event notifications\r
+ * @param name Name of the attribute of interest, or <code>null</code>\r
+ * to indicate interest in all attributes\r
+ * @param handback Handback object to be sent along with event\r
+ * notifications\r
+ *\r
+ * @exception IllegalArgumentException if the listener parameter is null\r
+ */\r
+ public void addAttributeChangeNotificationListener\r
+ (NotificationListener listener, String name, Object handback)\r
+ throws IllegalArgumentException {\r
+\r
+ if (listener == null)\r
+ throw new IllegalArgumentException("Listener is null");\r
+ if (attributeBroadcaster == null)\r
+ attributeBroadcaster = new BaseNotificationBroadcaster();\r
+\r
+ if( log.isDebugEnabled() )\r
+ log.debug("addAttributeNotificationListener " + listener);\r
+\r
+ BaseAttributeFilter filter = new BaseAttributeFilter(name);\r
+ attributeBroadcaster.addNotificationListener\r
+ (listener, filter, handback);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Remove an attribute change notification event listener from\r
+ * this MBean.\r
+ *\r
+ * @param listener The listener to be removed\r
+ * @param name The attribute name for which no more events are required\r
+ *\r
+ *\r
+ * @exception ListenerNotFoundException if this listener is not\r
+ * registered in the MBean\r
+ */\r
+ public void removeAttributeChangeNotificationListener\r
+ (NotificationListener listener, String name)\r
+ throws ListenerNotFoundException {\r
+\r
+ if (listener == null)\r
+ throw new IllegalArgumentException("Listener is null");\r
+ if (attributeBroadcaster == null)\r
+ attributeBroadcaster = new BaseNotificationBroadcaster();\r
+\r
+ // FIXME - currently this removes *all* notifications for this listener\r
+ attributeBroadcaster.removeNotificationListener(listener);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Remove an attribute change notification event listener from\r
+ * this MBean.\r
+ *\r
+ * @param listener The listener to be removed\r
+ * @param attributeName The attribute name for which no more events are required\r
+ * @param handback Handback object to be sent along with event\r
+ * notifications\r
+ *\r
+ *\r
+ * @exception ListenerNotFoundException if this listener is not\r
+ * registered in the MBean\r
+ */\r
+ public void removeAttributeChangeNotificationListener\r
+ (NotificationListener listener, String attributeName, Object handback)\r
+ throws ListenerNotFoundException {\r
+\r
+ removeAttributeChangeNotificationListener(listener, attributeName);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Send an <code>AttributeChangeNotification</code> to all registered\r
+ * listeners.\r
+ *\r
+ * @param notification The <code>AttributeChangeNotification</code>\r
+ * that will be passed\r
+ *\r
+ * @exception MBeanException if an object initializer throws an\r
+ * exception\r
+ * @exception RuntimeOperationsException wraps IllegalArgumentException\r
+ * when the specified notification is <code>null</code> or invalid\r
+ */\r
+ public void sendAttributeChangeNotification\r
+ (AttributeChangeNotification notification)\r
+ throws MBeanException, RuntimeOperationsException {\r
+\r
+ if (notification == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Notification is null"),\r
+ "Notification is null");\r
+ if (attributeBroadcaster == null)\r
+ return; // This means there are no registered listeners\r
+ if( log.isDebugEnabled() )\r
+ log.debug( "AttributeChangeNotification " + notification );\r
+ attributeBroadcaster.sendNotification(notification);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Send an <code>AttributeChangeNotification</code> to all registered\r
+ * listeners.\r
+ *\r
+ * @param oldValue The original value of the <code>Attribute</code>\r
+ * @param newValue The new value of the <code>Attribute</code>\r
+ *\r
+ * @exception MBeanException if an object initializer throws an\r
+ * exception\r
+ * @exception RuntimeOperationsException wraps IllegalArgumentException\r
+ * when the specified notification is <code>null</code> or invalid\r
+ */\r
+ public void sendAttributeChangeNotification\r
+ (Attribute oldValue, Attribute newValue)\r
+ throws MBeanException, RuntimeOperationsException {\r
+\r
+ // Calculate the class name for the change notification\r
+ String type = null;\r
+ if (newValue.getValue() != null)\r
+ type = newValue.getValue().getClass().getName();\r
+ else if (oldValue.getValue() != null)\r
+ type = oldValue.getValue().getClass().getName();\r
+ else\r
+ return; // Old and new are both null == no change\r
+\r
+ AttributeChangeNotification notification =\r
+ new AttributeChangeNotification\r
+ (this, 1, System.currentTimeMillis(),\r
+ "Attribute value has changed",\r
+ oldValue.getName(), type,\r
+ oldValue.getValue(), newValue.getValue());\r
+ sendAttributeChangeNotification(notification);\r
+\r
+ }\r
+\r
+\r
+\r
+\r
+ /**\r
+ * Send a <code>Notification</code> to all registered listeners as a\r
+ * <code>jmx.modelmbean.general</code> notification.\r
+ *\r
+ * @param notification The <code>Notification</code> that will be passed\r
+ *\r
+ * @exception MBeanException if an object initializer throws an\r
+ * exception\r
+ * @exception RuntimeOperationsException wraps IllegalArgumentException\r
+ * when the specified notification is <code>null</code> or invalid\r
+ */\r
+ public void sendNotification(Notification notification)\r
+ throws MBeanException, RuntimeOperationsException {\r
+\r
+ if (notification == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Notification is null"),\r
+ "Notification is null");\r
+ if (generalBroadcaster == null)\r
+ return; // This means there are no registered listeners\r
+ generalBroadcaster.sendNotification(notification);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Send a <code>Notification</code> which contains the specified string\r
+ * as a <code>jmx.modelmbean.generic</code> notification.\r
+ *\r
+ * @param message The message string to be passed\r
+ *\r
+ * @exception MBeanException if an object initializer throws an\r
+ * exception\r
+ * @exception RuntimeOperationsException wraps IllegalArgumentException\r
+ * when the specified notification is <code>null</code> or invalid\r
+ */\r
+ public void sendNotification(String message)\r
+ throws MBeanException, RuntimeOperationsException {\r
+\r
+ if (message == null)\r
+ throw new RuntimeOperationsException\r
+ (new IllegalArgumentException("Message is null"),\r
+ "Message is null");\r
+ Notification notification = new Notification\r
+ ("jmx.modelmbean.generic", this, 1, message);\r
+ sendNotification(notification);\r
+\r
+ }\r
+\r
+\r
+\r
+\r
+ // ---------------------------------------- NotificationBroadcaster Methods\r
+\r
+\r
+ /**\r
+ * Add a notification event listener to this MBean.\r
+ *\r
+ * @param listener Listener that will receive event notifications\r
+ * @param filter Filter object used to filter event notifications\r
+ * actually delivered, or <code>null</code> for no filtering\r
+ * @param handback Handback object to be sent along with event\r
+ * notifications\r
+ *\r
+ * @exception IllegalArgumentException if the listener parameter is null\r
+ */\r
+ public void addNotificationListener(NotificationListener listener,\r
+ NotificationFilter filter,\r
+ Object handback)\r
+ throws IllegalArgumentException {\r
+\r
+ if (listener == null)\r
+ throw new IllegalArgumentException("Listener is null");\r
+\r
+ if( log.isDebugEnabled() ) log.debug("addNotificationListener " + listener);\r
+\r
+ if (generalBroadcaster == null)\r
+ generalBroadcaster = new BaseNotificationBroadcaster();\r
+ generalBroadcaster.addNotificationListener\r
+ (listener, filter, handback);\r
+\r
+ // We'll send the attribute change notifications to all listeners ( who care )\r
+ // The normal filtering can be used.\r
+ // The problem is that there is no other way to add attribute change listeners\r
+ // to a model mbean ( AFAIK ). I suppose the spec should be fixed.\r
+ if (attributeBroadcaster == null)\r
+ attributeBroadcaster = new BaseNotificationBroadcaster();\r
+\r
+ if( log.isDebugEnabled() )\r
+ log.debug("addAttributeNotificationListener " + listener);\r
+\r
+ attributeBroadcaster.addNotificationListener\r
+ (listener, filter, handback);\r
+ }\r
+\r
+\r
+ /**\r
+ * Return an <code>MBeanNotificationInfo</code> object describing the\r
+ * notifications sent by this MBean.\r
+ */\r
+ public MBeanNotificationInfo[] getNotificationInfo() {\r
+\r
+ // Acquire the set of application notifications\r
+ MBeanNotificationInfo current[] = info.getNotifications();\r
+ if (current == null)\r
+ current = new MBeanNotificationInfo[0];\r
+ MBeanNotificationInfo response[] =\r
+ new MBeanNotificationInfo[current.length + 2];\r
+ Descriptor descriptor = null;\r
+\r
+ // Fill in entry for general notifications\r
+ descriptor = new DescriptorSupport\r
+ (new String[] { "name=GENERIC",\r
+ "descriptorType=notification",\r
+ "log=T",\r
+ "severity=5",\r
+ "displayName=jmx.modelmbean.generic" });\r
+ response[0] = new ModelMBeanNotificationInfo\r
+ (new String[] { "jmx.modelmbean.generic" },\r
+ "GENERIC",\r
+ "Text message notification from the managed resource",\r
+ descriptor);\r
+\r
+ // Fill in entry for attribute change notifications\r
+ descriptor = new DescriptorSupport\r
+ (new String[] { "name=ATTRIBUTE_CHANGE",\r
+ "descriptorType=notification",\r
+ "log=T",\r
+ "severity=5",\r
+ "displayName=jmx.attribute.change" });\r
+ response[1] = new ModelMBeanNotificationInfo\r
+ (new String[] { "jmx.attribute.change" },\r
+ "ATTRIBUTE_CHANGE",\r
+ "Observed MBean attribute value has changed",\r
+ descriptor);\r
+\r
+ // Copy remaining notifications as reported by the application\r
+ System.arraycopy(current, 0, response, 2, current.length);\r
+ return (response);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Remove a notification event listener from this MBean.\r
+ *\r
+ * @param listener The listener to be removed (any and all registrations\r
+ * for this listener will be eliminated)\r
+ *\r
+ * @exception ListenerNotFoundException if this listener is not\r
+ * registered in the MBean\r
+ */\r
+ public void removeNotificationListener(NotificationListener listener)\r
+ throws ListenerNotFoundException {\r
+\r
+ if (listener == null)\r
+ throw new IllegalArgumentException("Listener is null");\r
+ if (generalBroadcaster == null)\r
+ generalBroadcaster = new BaseNotificationBroadcaster();\r
+ generalBroadcaster.removeNotificationListener(listener);\r
+\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Remove a notification event listener from this MBean.\r
+ *\r
+ * @param listener The listener to be removed (any and all registrations\r
+ * for this listener will be eliminated)\r
+ * @param handback Handback object to be sent along with event\r
+ * notifications\r
+ *\r
+ * @exception ListenerNotFoundException if this listener is not\r
+ * registered in the MBean\r
+ */\r
+ public void removeNotificationListener(NotificationListener listener,\r
+ Object handback)\r
+ throws ListenerNotFoundException {\r
+\r
+ removeNotificationListener(listener);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Remove a notification event listener from this MBean.\r
+ *\r
+ * @param listener The listener to be removed (any and all registrations\r
+ * for this listener will be eliminated)\r
+ * @param filter Filter object used to filter event notifications\r
+ * actually delivered, or <code>null</code> for no filtering\r
+ * @param handback Handback object to be sent along with event\r
+ * notifications\r
+ *\r
+ * @exception ListenerNotFoundException if this listener is not\r
+ * registered in the MBean\r
+ */\r
+ public void removeNotificationListener(NotificationListener listener,\r
+ NotificationFilter filter,\r
+ Object handback)\r
+ throws ListenerNotFoundException {\r
+\r
+ removeNotificationListener(listener);\r
+\r
+ }\r
+\r
+\r
+ // ------------------------------------------------ PersistentMBean Methods\r
+\r
+\r
+ /**\r
+ * Instantiates this MBean instance from data found in the persistent\r
+ * store. The data loaded could include attribute and operation values.\r
+ * This method should be called during construction or initialization\r
+ * of the instance, and before the MBean is registered with the\r
+ * <code>MBeanServer</code>.\r
+ *\r
+ * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation does\r
+ * not support persistence.</p>\r
+ *\r
+ * @exception InstanceNotFoundException if the managed resource object\r
+ * cannot be found\r
+ * @exception MBeanException if the initializer of the object throws\r
+ * an exception\r
+ * @exception RuntimeOperationsException if an exception is reported\r
+ * by the persistence mechanism\r
+ */\r
+ public void load() throws InstanceNotFoundException,\r
+ MBeanException, RuntimeOperationsException {\r
+ // XXX If a context was set, use it to load the data\r
+ throw new MBeanException\r
+ (new IllegalStateException("Persistence is not supported"),\r
+ "Persistence is not supported");\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Capture the current state of this MBean instance and write it out\r
+ * to the persistent store. The state stored could include attribute\r
+ * and operation values. If one of these methods of persistence is not\r
+ * supported, a "service not found" exception will be thrown.\r
+ *\r
+ * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation does\r
+ * not support persistence.</p>\r
+ *\r
+ * @exception InstanceNotFoundException if the managed resource object\r
+ * cannot be found\r
+ * @exception MBeanException if the initializer of the object throws\r
+ * an exception, or persistence is not supported\r
+ * @exception RuntimeOperationsException if an exception is reported\r
+ * by the persistence mechanism\r
+ */\r
+ public void store() throws InstanceNotFoundException,\r
+ MBeanException, RuntimeOperationsException {\r
+\r
+ // XXX if a context was set, use it to store the data\r
+ throw new MBeanException\r
+ (new IllegalStateException("Persistence is not supported"),\r
+ "Persistence is not supported");\r
+\r
+ }\r
+\r
+ // -------------------- BaseModelMBean methods --------------------\r
+\r
+ /** Set the type of the mbean. This is used as a key to locate\r
+ * the description in the Registry.\r
+ *\r
+ * @param type the type of classname of the modeled object\r
+ */\r
+ public void setModeledType( String type ) {\r
+ initModelInfo(type);\r
+ createResource();\r
+ }\r
+ /** Set the type of the mbean. This is used as a key to locate\r
+ * the description in the Registry.\r
+ *\r
+ * @param type the type of classname of the modeled object\r
+ */\r
+ protected void initModelInfo( String type ) {\r
+ try {\r
+ if( log.isDebugEnabled())\r
+ log.debug("setModeledType " + type);\r
+\r
+ log.debug( "Set model Info " + type);\r
+ if(type==null) {\r
+ return;\r
+ }\r
+ resourceType=type;\r
+ //Thread.currentThread().setContextClassLoader(BaseModelMBean.class.getClassLoader());\r
+ Class c=null;\r
+ try {\r
+ c=Class.forName( type);\r
+ } catch( Throwable t ) {\r
+ log.debug( "Error creating class " + t);\r
+ }\r
+\r
+ // The class c doesn't need to exist\r
+ ManagedBean descriptor=getRegistry().findManagedBean(c, type);\r
+ if( descriptor==null ) \r
+ return;\r
+ this.setModelMBeanInfo(descriptor.createMBeanInfo());\r
+ } catch( Throwable ex) {\r
+ log.error( "TCL: " + Thread.currentThread().getContextClassLoader(),\r
+ ex);\r
+ }\r
+ }\r
+\r
+ /** Set the type of the mbean. This is used as a key to locate\r
+ * the description in the Registry.\r
+ */\r
+ protected void createResource() {\r
+ try {\r
+ //Thread.currentThread().setContextClassLoader(BaseModelMBean.class.getClassLoader());\r
+ Class c=null;\r
+ try {\r
+ c=Class.forName( resourceType );\r
+ resource = c.newInstance();\r
+ } catch( Throwable t ) {\r
+ log.error( "Error creating class " + t);\r
+ }\r
+ } catch( Throwable ex) {\r
+ log.error( "TCL: " + Thread.currentThread().getContextClassLoader(),\r
+ ex);\r
+ }\r
+ }\r
+\r
+\r
+ public String getModelerType() {\r
+ return resourceType;\r
+ }\r
+\r
+ public String getClassName() {\r
+ return getModelerType();\r
+ }\r
+\r
+ public ObjectName getJmxName() {\r
+ return oname;\r
+ }\r
+\r
+ public String getObjectName() {\r
+ if (oname != null) {\r
+ return oname.toString();\r
+ } else {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ public void setRegistry(Registry registry) {\r
+ this.registry = registry;\r
+ }\r
+\r
+ public Registry getRegistry() {\r
+ // XXX Need a better solution - to avoid the static\r
+ if( registry == null )\r
+ registry=Registry.getRegistry();\r
+\r
+ return registry;\r
+ }\r
+\r
+ // ------------------------------------------------------ Protected Methods\r
+\r
+\r
+ /**\r
+ * Create and return a default <code>ModelMBeanInfo</code> object.\r
+ */\r
+ protected ModelMBeanInfo createDefaultModelMBeanInfo() {\r
+\r
+ return (new ModelMBeanInfoSupport(this.getClass().getName(),\r
+ "Default ModelMBean",\r
+ null, null, null, null));\r
+\r
+ }\r
+\r
+ /**\r
+ * Is the specified <code>ModelMBeanInfo</code> instance valid?\r
+ *\r
+ * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation\r
+ * does not check anything, but this method can be overridden\r
+ * as required.</p>\r
+ *\r
+ * @param info The <code>ModelMBeanInfo object to check\r
+ */\r
+ protected boolean isModelMBeanInfoValid(ModelMBeanInfo info) {\r
+ return (true);\r
+ }\r
+\r
+ // -------------------- Registration --------------------\r
+ // XXX We can add some method patterns here- like setName() and\r
+ // setDomain() for code that doesn't implement the Registration\r
+\r
+ public ObjectName preRegister(MBeanServer server,\r
+ ObjectName name)\r
+ throws Exception\r
+ {\r
+ if( log.isDebugEnabled())\r
+ log.debug("preRegister " + resource + " " + name );\r
+ oname=name;\r
+ if( resource instanceof MBeanRegistration ) {\r
+ oname = ((MBeanRegistration)resource).preRegister(server, name );\r
+ }\r
+ return oname;\r
+ }\r
+\r
+ public void postRegister(Boolean registrationDone) {\r
+ if( resource instanceof MBeanRegistration ) {\r
+ ((MBeanRegistration)resource).postRegister(registrationDone);\r
+ }\r
+ }\r
+\r
+ public void preDeregister() throws Exception {\r
+ if( resource instanceof MBeanRegistration ) {\r
+ ((MBeanRegistration)resource).preDeregister();\r
+ }\r
+ }\r
+\r
+ public void postDeregister() {\r
+ if( resource instanceof MBeanRegistration ) {\r
+ ((MBeanRegistration)resource).postDeregister();\r
+ }\r
+ }\r
+\r
+ static class MethodKey {\r
+ private String name;\r
+ private String[] signature;\r
+\r
+ MethodKey(String name, String[] signature) {\r
+ this.name = name;\r
+ if(signature == null) {\r
+ signature = new String[0];\r
+ }\r
+ this.signature = signature;\r
+ }\r
+\r
+ public boolean equals(Object other) {\r
+ if(!(other instanceof MethodKey)) {\r
+ return false;\r
+ }\r
+ MethodKey omk = (MethodKey)other;\r
+ if(!name.equals(omk.name)) {\r
+ return false;\r
+ }\r
+ if(signature.length != omk.signature.length) {\r
+ return false;\r
+ }\r
+ for(int i=0; i < signature.length; i++) {\r
+ if(!signature[i].equals(omk.signature[i])) {\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+ public int hashCode() {\r
+ return name.hashCode();\r
+ }\r
+ }\r
+}\r
--- /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
+package org.apache.tomcat.util.modeler;\r
+\r
+import javax.management.Notification;\r
+\r
+\r
+/**\r
+ * Base JMX Notification. Supports in int code and notes - for faster \r
+ * access and dispatching. \r
+ *\r
+ * @author Costin Manolache\r
+ */\r
+public final class BaseNotification extends Notification {\r
+\r
+ // ----------------------------------------------------------- Constructors\r
+ private int code;\r
+ private String type;\r
+ private Object source;\r
+ private long seq;\r
+ private long tstamp;\r
+\r
+ /**\r
+ * Private constructor.\r
+ */\r
+ private BaseNotification(String type,\r
+ Object source,\r
+ long seq,\r
+ long tstamp,\r
+ int code) {\r
+ super(type, source, seq, tstamp);\r
+ init( type, source, seq, tstamp, code );\r
+ this.code=code;\r
+ }\r
+\r
+ public void recycle() {\r
+\r
+ }\r
+\r
+ public void init( String type, Object source,\r
+ long seq, long tstamp, int code )\r
+ {\r
+ this.type=type;\r
+ this.source = source;\r
+ this.seq=seq;\r
+ this.tstamp=tstamp;\r
+ this.code = code;\r
+ }\r
+\r
+ // -------------------- Override base methods --------------------\r
+ // All base methods need to be overriden - in order to support recycling.\r
+\r
+\r
+ // -------------------- Information associated with the notification ----\r
+ // Like events ( which Notification extends ), notifications may store\r
+ // informations related with the event that trigered it. Source and type is\r
+ // one piece, but it is common to store more info.\r
+\r
+ /** Action id, useable in switches and table indexes\r
+ */\r
+ public int getCode() {\r
+ return code;\r
+ }\r
+\r
+ // XXX Make it customizable - or grow it\r
+ private Object notes[]=new Object[32];\r
+\r
+ public final Object getNote(int i ) {\r
+ return notes[i];\r
+ }\r
+\r
+ public final void setNote(int i, Object o ) {\r
+ notes[i]=o;\r
+ }\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+\r
+import javax.management.ListenerNotFoundException;\r
+import javax.management.MBeanNotificationInfo;\r
+import javax.management.Notification;\r
+import javax.management.NotificationBroadcaster;\r
+import javax.management.NotificationFilter;\r
+import javax.management.NotificationListener;\r
+\r
+\r
+/**\r
+ * <p>Implementation of <code>NotificationBroadcaster</code> for attribute\r
+ * change notifications. This class is used by <code>BaseModelMBean</code> to\r
+ * handle notifications of attribute change events to interested listeners.\r
+ *</p>\r
+ *\r
+ * @author Craig R. McClanahan\r
+ * @author Costin Manolache\r
+ */\r
+\r
+public class BaseNotificationBroadcaster implements NotificationBroadcaster {\r
+\r
+\r
+ // ----------------------------------------------------------- Constructors\r
+\r
+\r
+ // ----------------------------------------------------- Instance Variables\r
+\r
+\r
+ /**\r
+ * The set of registered <code>BaseNotificationBroadcasterEntry</code>\r
+ * entries.\r
+ */\r
+ protected ArrayList entries = new ArrayList();\r
+\r
+\r
+ // --------------------------------------------------------- Public Methods\r
+\r
+\r
+ /**\r
+ * Add a notification event listener to this MBean.\r
+ *\r
+ * @param listener Listener that will receive event notifications\r
+ * @param filter Filter object used to filter event notifications\r
+ * actually delivered, or <code>null</code> for no filtering\r
+ * @param handback Handback object to be sent along with event\r
+ * notifications\r
+ *\r
+ * @exception IllegalArgumentException if the listener parameter is null\r
+ */\r
+ public void addNotificationListener(NotificationListener listener,\r
+ NotificationFilter filter,\r
+ Object handback)\r
+ throws IllegalArgumentException {\r
+\r
+ synchronized (entries) {\r
+\r
+ // Optimization to coalesce attribute name filters\r
+ if (filter instanceof BaseAttributeFilter) {\r
+ BaseAttributeFilter newFilter = (BaseAttributeFilter) filter;\r
+ Iterator items = entries.iterator();\r
+ while (items.hasNext()) {\r
+ BaseNotificationBroadcasterEntry item =\r
+ (BaseNotificationBroadcasterEntry) items.next();\r
+ if ((item.listener == listener) &&\r
+ (item.filter != null) &&\r
+ (item.filter instanceof BaseAttributeFilter) &&\r
+ (item.handback == handback)) {\r
+ BaseAttributeFilter oldFilter =\r
+ (BaseAttributeFilter) item.filter;\r
+ String newNames[] = newFilter.getNames();\r
+ String oldNames[] = oldFilter.getNames();\r
+ if (newNames.length == 0) {\r
+ oldFilter.clear();\r
+ } else {\r
+ if (oldNames.length != 0) {\r
+ for (int i = 0; i < newNames.length; i++)\r
+ oldFilter.addAttribute(newNames[i]);\r
+ }\r
+ }\r
+ return;\r
+ }\r
+ }\r
+ }\r
+\r
+ // General purpose addition of a new entry\r
+ entries.add(new BaseNotificationBroadcasterEntry\r
+ (listener, filter, handback));\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Return an <code>MBeanNotificationInfo</code> object describing the\r
+ * notifications sent by this MBean.\r
+ */\r
+ public MBeanNotificationInfo[] getNotificationInfo() {\r
+\r
+ return (new MBeanNotificationInfo[0]);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Remove a notification event listener from this MBean.\r
+ *\r
+ * @param listener The listener to be removed (any and all registrations\r
+ * for this listener will be eliminated)\r
+ *\r
+ * @exception ListenerNotFoundException if this listener is not\r
+ * registered in the MBean\r
+ */\r
+ public void removeNotificationListener(NotificationListener listener)\r
+ throws ListenerNotFoundException {\r
+\r
+ synchronized (entries) {\r
+ Iterator items = entries.iterator();\r
+ while (items.hasNext()) {\r
+ BaseNotificationBroadcasterEntry item =\r
+ (BaseNotificationBroadcasterEntry) items.next();\r
+ if (item.listener == listener)\r
+ items.remove();\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Remove a notification event listener from this MBean.\r
+ *\r
+ * @param listener The listener to be removed (any and all registrations\r
+ * for this listener will be eliminated)\r
+ * @param handback Handback object to be sent along with event\r
+ * notifications\r
+ *\r
+ * @exception ListenerNotFoundException if this listener is not\r
+ * registered in the MBean\r
+ */\r
+ public void removeNotificationListener(NotificationListener listener,\r
+ Object handback)\r
+ throws ListenerNotFoundException {\r
+\r
+ removeNotificationListener(listener);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Remove a notification event listener from this MBean.\r
+ *\r
+ * @param listener The listener to be removed (any and all registrations\r
+ * for this listener will be eliminated)\r
+ * @param filter Filter object used to filter event notifications\r
+ * actually delivered, or <code>null</code> for no filtering\r
+ * @param handback Handback object to be sent along with event\r
+ * notifications\r
+ *\r
+ * @exception ListenerNotFoundException if this listener is not\r
+ * registered in the MBean\r
+ */\r
+ public void removeNotificationListener(NotificationListener listener,\r
+ NotificationFilter filter,\r
+ Object handback)\r
+ throws ListenerNotFoundException {\r
+\r
+ removeNotificationListener(listener);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Send the specified notification to all interested listeners.\r
+ *\r
+ * @param notification The notification to be sent\r
+ */\r
+ public void sendNotification(Notification notification) {\r
+\r
+ synchronized (entries) {\r
+ Iterator items = entries.iterator();\r
+ while (items.hasNext()) {\r
+ BaseNotificationBroadcasterEntry item =\r
+ (BaseNotificationBroadcasterEntry) items.next();\r
+ if ((item.filter != null) &&\r
+ (!item.filter.isNotificationEnabled(notification)))\r
+ continue;\r
+ item.listener.handleNotification(notification, item.handback);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+\r
+ // -------------------- Internal Extensions --------------------\r
+\r
+ // Fast access. First index is the hook type\r
+ // ( FixedNotificationFilter.getType() ).\r
+ NotificationListener hooks[][]=new NotificationListener[20][];\r
+ int hookCount[]=new int[20];\r
+\r
+ private synchronized void registerNotifications( FixedNotificationFilter filter ) {\r
+ String names[]=filter.getNames();\r
+ Registry reg=Registry.getRegistry();\r
+ for( int i=0; i<names.length; i++ ) {\r
+ int code=reg.getId(null, names[i]);\r
+ if( hooks.length < code ) {\r
+ // XXX reallocate\r
+ throw new RuntimeException( "Too many hooks " + code );\r
+ }\r
+ NotificationListener listeners[]=hooks[code];\r
+ if( listeners== null ) {\r
+\r
+ }\r
+\r
+\r
+ }\r
+ }\r
+\r
+}\r
+\r
+\r
+/**\r
+ * Utility class representing a particular registered listener entry.\r
+ */\r
+\r
+class BaseNotificationBroadcasterEntry {\r
+\r
+ public BaseNotificationBroadcasterEntry(NotificationListener listener,\r
+ NotificationFilter filter,\r
+ Object handback) {\r
+ this.listener = listener;\r
+ this.filter = filter;\r
+ this.handback = handback;\r
+ }\r
+\r
+ public NotificationFilter filter = null;\r
+\r
+ public Object handback = null;\r
+\r
+ public NotificationListener listener = null;\r
+\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.io.Serializable;\r
+\r
+import javax.management.Descriptor;\r
+import javax.management.MBeanParameterInfo;\r
+import javax.management.modelmbean.ModelMBeanConstructorInfo;\r
+\r
+\r
+/**\r
+ * <p>Internal configuration information for a <code>Constructor</code>\r
+ * descriptor.</p>\r
+ *\r
+ * @author Craig R. McClanahan\r
+ * @version $Revision: 155428 $ $Date: 2005-02-26 14:12:25 +0100 (sam., 26 févr. 2005) $\r
+ */\r
+\r
+public class ConstructorInfo extends FeatureInfo implements Serializable {\r
+ static final long serialVersionUID = -5735336213417238238L;\r
+\r
+ // ----------------------------------------------------- Instance Variables\r
+\r
+\r
+ /**\r
+ * The <code>ModelMBeanConstructorInfo</code> object that corresponds\r
+ * to this <code>ConstructorInfo</code> instance.\r
+ */\r
+ transient ModelMBeanConstructorInfo info = null;\r
+ protected String displayName = null;\r
+ protected ParameterInfo parameters[] = new ParameterInfo[0];\r
+\r
+\r
+ // ------------------------------------------------------------- Properties\r
+\r
+\r
+ /**\r
+ * Override the <code>description</code> property setter.\r
+ *\r
+ * @param description The new description\r
+ */\r
+ public void setDescription(String description) {\r
+ super.setDescription(description);\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * Override the <code>name</code> property setter.\r
+ *\r
+ * @param name The new name\r
+ */\r
+ public void setName(String name) {\r
+ super.setName(name);\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * The display name of this attribute.\r
+ */\r
+ public String getDisplayName() {\r
+ return (this.displayName);\r
+ }\r
+\r
+ public void setDisplayName(String displayName) {\r
+ this.displayName = displayName;\r
+ }\r
+\r
+\r
+ /**\r
+ * The set of parameters for this constructor.\r
+ */\r
+ public ParameterInfo[] getSignature() {\r
+ return (this.parameters);\r
+ }\r
+\r
+\r
+ // --------------------------------------------------------- Public Methods\r
+\r
+\r
+ /**\r
+ * Add a new parameter to the set of parameters for this constructor.\r
+ *\r
+ * @param parameter The new parameter descriptor\r
+ */\r
+ public void addParameter(ParameterInfo parameter) {\r
+\r
+ synchronized (parameters) {\r
+ ParameterInfo results[] = new ParameterInfo[parameters.length + 1];\r
+ System.arraycopy(parameters, 0, results, 0, parameters.length);\r
+ results[parameters.length] = parameter;\r
+ parameters = results;\r
+ this.info = null;\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Create and return a <code>ModelMBeanConstructorInfo</code> object that\r
+ * corresponds to the attribute described by this instance.\r
+ */\r
+ public ModelMBeanConstructorInfo createConstructorInfo() {\r
+\r
+ // Return our cached information (if any)\r
+ if (info != null)\r
+ return (info);\r
+\r
+ // Create and return a new information object\r
+ ParameterInfo params[] = getSignature();\r
+ MBeanParameterInfo parameters[] =\r
+ new MBeanParameterInfo[params.length];\r
+ for (int i = 0; i < params.length; i++)\r
+ parameters[i] = params[i].createParameterInfo();\r
+ info = new ModelMBeanConstructorInfo\r
+ (getName(), getDescription(), parameters);\r
+ Descriptor descriptor = info.getDescriptor();\r
+ descriptor.removeField("class");\r
+ if (getDisplayName() != null)\r
+ descriptor.setField("displayName", getDisplayName());\r
+ addFields(descriptor);\r
+ info.setDescriptor(descriptor);\r
+ return (info);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Return a string representation of this constructor descriptor.\r
+ */\r
+ public String toString() {\r
+\r
+ StringBuffer sb = new StringBuffer("ConstructorInfo[");\r
+ sb.append("name=");\r
+ sb.append(name);\r
+ sb.append(", description=");\r
+ sb.append(description);\r
+ sb.append(", parameters=");\r
+ sb.append(parameters.length);\r
+ sb.append("]");\r
+ return (sb.toString());\r
+\r
+ }\r
+\r
+\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.io.Serializable;\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import javax.management.Descriptor;\r
+\r
+\r
+/**\r
+ * <p>Convenience base class for <code>AttributeInfo</code>,\r
+ * <code>ConstructorInfo</code>, and <code>OperationInfo</code> classes\r
+ * that will be used to collect configuration information for the\r
+ * <code>ModelMBean</code> beans exposed for management.</p>\r
+ *\r
+ * @author Craig R. McClanahan\r
+ * @version $Revision: 155428 $ $Date: 2005-02-26 14:12:25 +0100 (sam., 26 févr. 2005) $\r
+ */\r
+\r
+public class FeatureInfo implements Serializable {\r
+ static final long serialVersionUID = -911529176124712296L;\r
+ protected String description = null;\r
+ protected List fields = new ArrayList();\r
+ protected String name = null;\r
+\r
+ // ------------------------------------------------------------- Properties\r
+\r
+\r
+ /**\r
+ * The human-readable description of this feature.\r
+ */\r
+ public String getDescription() {\r
+ return (this.description);\r
+ }\r
+\r
+ public void setDescription(String description) {\r
+ this.description = description;\r
+ }\r
+\r
+\r
+ /**\r
+ * The field information for this feature.\r
+ */\r
+ public List getFields() {\r
+ return (fields);\r
+ }\r
+\r
+\r
+ /**\r
+ * The name of this feature, which must be unique among features in the\r
+ * same collection.\r
+ */\r
+ public String getName() {\r
+ return (this.name);\r
+ }\r
+\r
+ public void setName(String name) {\r
+ this.name = name;\r
+ }\r
+\r
+\r
+ // --------------------------------------------------------- Public Methods\r
+\r
+\r
+ /**\r
+ * <p>Add a new field to the fields associated with the\r
+ * Descriptor that will be created from this metadata.</p>\r
+ *\r
+ * @param field The field to be added\r
+ */\r
+ public void addField(FieldInfo field) {\r
+ fields.add(field);\r
+ }\r
+\r
+\r
+ // ------------------------------------------------------ Protected Methods\r
+\r
+\r
+ /**\r
+ * <p>Add the name/value fields that have been stored into the\r
+ * specified <code>Descriptor</code> instance.</p>\r
+ *\r
+ * @param descriptor The <code>Descriptor</code> to add fields to\r
+ */\r
+ protected void addFields(Descriptor descriptor) {\r
+\r
+ Iterator items = getFields().iterator();\r
+ while (items.hasNext()) {\r
+ FieldInfo item = (FieldInfo) items.next();\r
+ descriptor.setField(item.getName(), item.getValue());\r
+ }\r
+\r
+ }\r
+\r
+\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.io.Serializable;\r
+\r
+\r
+/**\r
+ * <p>Simple JavaBean representing the contents of a <code><field></code>\r
+ * element in an MBeans descriptor file.\r
+ */\r
+\r
+public class FieldInfo implements Serializable {\r
+ static final long serialVersionUID = -8226401620640873691L;\r
+\r
+ /**\r
+ * <p>The field name for this field of a descriptor.</p>\r
+ */\r
+ protected String name = null;\r
+\r
+ public String getName() {\r
+ return (this.name);\r
+ }\r
+\r
+ public void setName(String name) {\r
+ this.name = name;\r
+ }\r
+\r
+\r
+ /**\r
+ * <p>The field value for this field of a descriptor.</p>\r
+ */\r
+ protected Object value = null;\r
+\r
+ public Object getValue() {\r
+ return (this.value);\r
+ }\r
+\r
+ public void setValue(Object value) {\r
+ this.value = value;\r
+ }\r
+\r
+\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.util.HashSet;\r
+\r
+import javax.management.Notification;\r
+import javax.management.NotificationFilter;\r
+\r
+\r
+/**\r
+ * Special NotificationFilter that allows modeler to optimize its notifications.\r
+ *\r
+ * This class is immutable - after you construct it it'll filter based on\r
+ * a fixed set of notification names.\r
+ *\r
+ * The JMX specification requires the filters to be called before the\r
+ * notifications are sent. We can call this filter well in advance, when\r
+ * the listener is added. Based on the result we can maintain separate\r
+ * channels for each notification - and reduce the overhead.\r
+ *\r
+ * @author Costin Manolache\r
+ */\r
+public class FixedNotificationFilter implements NotificationFilter {\r
+\r
+ /**\r
+ * The set of attribute names that are accepted by this filter. If this\r
+ * list is empty, all attribute names are accepted.\r
+ */\r
+ private HashSet names = new HashSet();\r
+ String namesA[]=null;\r
+\r
+ /**\r
+ * Construct a new filter that accepts only the specified notification\r
+ * names.\r
+ *\r
+ * @param names Names of the notification types\r
+ */\r
+ public FixedNotificationFilter(String names[]) {\r
+ super();\r
+ }\r
+\r
+ /**\r
+ * Return the set of names that are accepted by this filter. If this\r
+ * filter accepts all attribute names, a zero length array will be\r
+ * returned.\r
+ */\r
+ public String[] getNames() {\r
+ synchronized (names) {\r
+ return ((String[]) names.toArray(new String[names.size()]));\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * <p>Test whether notification enabled for this event.\r
+ * Return true if:</p>\r
+ * <ul>\r
+ * <li>Either the set of accepted names is empty (implying that all\r
+ * attribute names are of interest) or the set of accepted names\r
+ * includes the name of the attribute in this notification</li>\r
+ * </ul>\r
+ */\r
+ public boolean isNotificationEnabled(Notification notification) {\r
+\r
+ if (notification == null)\r
+ return (false);\r
+ synchronized (names) {\r
+ if (names.size() < 1)\r
+ return (true);\r
+ else\r
+ return (names.contains(notification.getType()));\r
+ }\r
+\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2001-2002,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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+\r
+import javax.management.AttributeChangeNotification;\r
+import javax.management.InstanceNotFoundException;\r
+import javax.management.MBeanException;\r
+import javax.management.MBeanServer;\r
+import javax.management.MBeanServerNotification;\r
+import javax.management.Notification;\r
+import javax.management.NotificationBroadcaster;\r
+import javax.management.NotificationListener;\r
+import javax.management.ObjectName;\r
+import javax.naming.Context;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+\r
+// EXPERIMENTAL. It may fit better in tomcat jndi impl.\r
+\r
+\r
+/**\r
+ *\r
+ * Link between JNDI and JMX. JNDI can be used for persistence ( it is\r
+ * an API for storing hierarchical data and a perfect fit for that ), as\r
+ * well as an alternate view of the MBean registry.\r
+ *\r
+ * If this component is enabled, all MBeans will be registered in JNDI, and\r
+ * all attributes that are set via JMX can be stored in a DirContext.\r
+ *\r
+ * This acts as a "recorder" for creation of mbeans and attribute changes\r
+ * done via JMX.\r
+ *\r
+ * XXX How can we control ( filter ) which mbeans will be registere ? Or\r
+ * attributes ?\r
+ * XXX How can we get the beans and attributes loaded before jndijmx ?\r
+ *\r
+ * The intended use:\r
+ * - do whatever you want to start the application\r
+ * - load JndiJmx as an mbean\r
+ * - make changes via JMX. All changes are recorded\r
+ * - you can use JndiJmx to save the changes in a Jndi context.\r
+ * - you can use JndiJmx to load changes from a JndiContext and replay them.\r
+ *\r
+ * The main benefit is that only changed attributes are saved, and the Jndi\r
+ * layer can preserve most of the original structure of the config file. The\r
+ * alternative is to override the config files with config info extracted\r
+ * from the live objects - but it's very hard to save only what was actually\r
+ * changed and preserve structure and comments.\r
+ *\r
+ * @author Costin Manolache\r
+ */\r
+public class JndiJmx extends BaseModelMBean implements NotificationListener {\r
+\r
+\r
+ private static Log log= LogFactory.getLog(JndiJmx.class);\r
+\r
+ protected Context componentContext;\r
+ protected Context descriptorContext;\r
+ protected Context configContext;\r
+\r
+ MBeanServer mserver;\r
+\r
+ /**\r
+ * Protected constructor to require use of the factory create method.\r
+ */\r
+ public JndiJmx() throws MBeanException {\r
+ super(JndiJmx.class.getName());\r
+ }\r
+\r
+\r
+ /** If a JNDI context is set, all components\r
+ * will be registered in the context.\r
+ *\r
+ * @param ctx\r
+ */\r
+ public void setComponentContext(Context ctx) {\r
+ this.componentContext= ctx;\r
+ }\r
+\r
+ /** JNDI context for component descriptors ( metadata ).\r
+ *\r
+ * @param ctx\r
+ */\r
+ public void setDescriptorContext(Context ctx) {\r
+ this.descriptorContext= ctx;\r
+ }\r
+\r
+ /** JNDI context where attributes will be stored for persistence\r
+ *\r
+ */\r
+ public void setConfigContext( Context ctx ) {\r
+ this.configContext= ctx;\r
+ }\r
+\r
+ // -------------------- Registration/unregistration --------------------\r
+ // temp - will only set in the jndi contexts\r
+ Hashtable attributes=new Hashtable();\r
+ Hashtable instances=new Hashtable();\r
+\r
+ public void handleNotification(Notification notification, Object handback)\r
+ {\r
+ // register/unregister mbeans in jndi\r
+ if( notification instanceof MBeanServerNotification ) {\r
+ MBeanServerNotification msnot=(MBeanServerNotification)notification;\r
+\r
+ ObjectName oname=msnot.getMBeanName();\r
+\r
+ if( "jmx.mbean.created".equalsIgnoreCase( notification.getType() )) {\r
+ try {\r
+ Object mbean=mserver.getObjectInstance(oname);\r
+\r
+ if( log.isDebugEnabled() )\r
+ log.debug( "MBean created " + oname + " " + mbean);\r
+\r
+ // XXX add filter support\r
+ if( mbean instanceof NotificationBroadcaster ) {\r
+ // register for attribute changes\r
+ NotificationBroadcaster nb=(NotificationBroadcaster)mbean;\r
+ nb.addNotificationListener(this, null, null);\r
+ if( log.isDebugEnabled() )\r
+ log.debug( "Add attribute change listener");\r
+ }\r
+\r
+ instances.put( oname.toString(), mbean );\r
+ } catch( InstanceNotFoundException ex ) {\r
+ log.error( "Instance not found for the created object", ex );\r
+ }\r
+ }\r
+ if( "jmx.mbean.deleted".equalsIgnoreCase( notification.getType() )) {\r
+ instances.remove(oname.toString());\r
+ }\r
+ }\r
+\r
+ // set attributes in jndi\r
+ // if( "jmx.attribute.changed".equals( notification.getType() )) {\r
+ if( notification instanceof AttributeChangeNotification) {\r
+\r
+ AttributeChangeNotification anotif=(AttributeChangeNotification)notification;\r
+ String name=anotif.getAttributeName();\r
+ Object value=anotif.getNewValue();\r
+ Object source=anotif.getSource();\r
+ String mname=null;\r
+\r
+ Hashtable mbeanAtt=(Hashtable)attributes.get( source );\r
+ if( mbeanAtt==null ) {\r
+ mbeanAtt=new Hashtable();\r
+ attributes.put( source, mbeanAtt);\r
+ if( log.isDebugEnabled())\r
+ log.debug("First attribute for " + source );\r
+ }\r
+ mbeanAtt.put( name, anotif );\r
+\r
+ log.debug( "Attribute change notification " + name + " " + value + " " + source );\r
+\r
+ }\r
+\r
+ }\r
+\r
+ public String dumpStatus() throws Exception\r
+ {\r
+ StringBuffer sb=new StringBuffer();\r
+ Enumeration en=instances.keys();\r
+ while (en.hasMoreElements()) {\r
+ String on = (String) en.nextElement();\r
+ Object mbean=instances.get(on);\r
+ Hashtable mbeanAtt=(Hashtable)attributes.get(mbean);\r
+\r
+ sb.append( "<mbean class=\"").append(on).append("\">");\r
+ sb.append( "\n");\r
+ Enumeration attEn=mbeanAtt.keys();\r
+ while (attEn.hasMoreElements()) {\r
+ String an = (String) attEn.nextElement();\r
+ AttributeChangeNotification anotif=\r
+ (AttributeChangeNotification)mbeanAtt.get(an);\r
+ sb.append(" <attribute name=\"").append(an).append("\" ");\r
+ sb.append("value=\"").append(anotif.getNewValue()).append("\">");\r
+ sb.append( "\n");\r
+ }\r
+\r
+\r
+ sb.append( "</mbean>");\r
+ sb.append( "\n");\r
+ }\r
+ return sb.toString();\r
+ }\r
+\r
+ public void replay() throws Exception\r
+ {\r
+\r
+\r
+ }\r
+\r
+\r
+ public void init() throws Exception\r
+ {\r
+\r
+ MBeanServer mserver=(MBeanServer)Registry.getRegistry().getMBeanServer();\r
+ ObjectName delegate=new ObjectName("JMImplementation:type=MBeanServerDelegate");\r
+\r
+ // XXX need to extract info about previously loaded beans\r
+\r
+ // we'll know of all registered beans\r
+ mserver.addNotificationListener(delegate, this, null, null );\r
+\r
+ }\r
+\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import javax.management.Descriptor;\r
+import javax.management.InstanceNotFoundException;\r
+import javax.management.MBeanException;\r
+import javax.management.RuntimeOperationsException;\r
+import javax.management.modelmbean.InvalidTargetObjectTypeException;\r
+import javax.management.modelmbean.ModelMBean;\r
+import javax.management.modelmbean.ModelMBeanAttributeInfo;\r
+import javax.management.modelmbean.ModelMBeanConstructorInfo;\r
+import javax.management.modelmbean.ModelMBeanInfo;\r
+import javax.management.modelmbean.ModelMBeanInfoSupport;\r
+import javax.management.modelmbean.ModelMBeanNotificationInfo;\r
+import javax.management.modelmbean.ModelMBeanOperationInfo;\r
+\r
+\r
+/**\r
+ * <p>Internal configuration information for a managed bean (MBean)\r
+ * descriptor.</p>\r
+ *\r
+ * @author Craig R. McClanahan\r
+ * @version $Revision: 383268 $ $Date: 2006-03-05 03:02:01 +0100 (dim., 05 mars 2006) $\r
+ */\r
+\r
+public class ManagedBean implements java.io.Serializable\r
+{\r
+ // ----------------------------------------------------- Instance Variables\r
+\r
+\r
+ /**\r
+ * The <code>ModelMBeanInfo</code> object that corresponds\r
+ * to this <code>ManagedBean</code> instance.\r
+ */\r
+ transient ModelMBeanInfo info = null;\r
+ protected AttributeInfo attributes[] = new AttributeInfo[0];\r
+ protected String className =\r
+ "org.apache.tomcat.util.modeler.BaseModelMBean";\r
+ protected ConstructorInfo constructors[] = new ConstructorInfo[0];\r
+ protected String description = null;\r
+ protected String domain = null;\r
+ protected String group = null;\r
+ protected String name = null;\r
+\r
+ protected List fields = new ArrayList();\r
+ protected NotificationInfo notifications[] = new NotificationInfo[0];\r
+ protected OperationInfo operations[] = new OperationInfo[0];\r
+ protected String type = null;\r
+\r
+ /** Constructor. Will add default attributes. \r
+ * \r
+ */ \r
+ public ManagedBean() {\r
+ AttributeInfo ai=new AttributeInfo();\r
+ ai.setName("modelerType");\r
+ ai.setDescription("Type of the modeled resource. Can be set only once");\r
+ ai.setType("java.lang.String");\r
+ ai.setWriteable(false);\r
+ addAttribute(ai);\r
+ }\r
+ \r
+ // ------------------------------------------------------------- Properties\r
+\r
+\r
+ /**\r
+ * The collection of attributes for this MBean.\r
+ */\r
+ public AttributeInfo[] getAttributes() {\r
+ return (this.attributes);\r
+ }\r
+\r
+\r
+ /**\r
+ * The fully qualified name of the Java class of the MBean\r
+ * described by this descriptor. If not specified, the standard JMX\r
+ * class (<code>javax.management.modelmbean.RequiredModeLMBean</code>)\r
+ * will be utilized.\r
+ */\r
+ public String getClassName() {\r
+ return (this.className);\r
+ }\r
+\r
+ public void setClassName(String className) {\r
+ this.className = className;\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * The collection of constructors for this MBean.\r
+ */\r
+ public ConstructorInfo[] getConstructors() {\r
+ return (this.constructors);\r
+ }\r
+\r
+\r
+ /**\r
+ * The human-readable description of this MBean.\r
+ */\r
+ public String getDescription() {\r
+ return (this.description);\r
+ }\r
+\r
+ public void setDescription(String description) {\r
+ this.description = description;\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * The (optional) <code>ObjectName</code> domain in which this MBean\r
+ * should be registered in the MBeanServer.\r
+ */\r
+ public String getDomain() {\r
+ return (this.domain);\r
+ }\r
+\r
+ public void setDomain(String domain) {\r
+ this.domain = domain;\r
+ }\r
+\r
+\r
+ /**\r
+ * <p>Return a <code>List</code> of the {@link FieldInfo} objects for\r
+ * the name/value pairs that should be\r
+ * added to the Descriptor created from this metadata.</p>\r
+ */\r
+ public List getFields() {\r
+ return (this.fields);\r
+ }\r
+\r
+\r
+ /**\r
+ * The (optional) group to which this MBean belongs.\r
+ */\r
+ public String getGroup() {\r
+ return (this.group);\r
+ }\r
+\r
+ public void setGroup(String group) {\r
+ this.group = group;\r
+ }\r
+\r
+\r
+ /**\r
+ * The name of this managed bean, which must be unique among all\r
+ * MBeans managed by a particular MBeans server.\r
+ */\r
+ public String getName() {\r
+ return (this.name);\r
+ }\r
+\r
+ public void setName(String name) {\r
+ this.name = name;\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * The collection of notifications for this MBean.\r
+ */\r
+ public NotificationInfo[] getNotifications() {\r
+ return (this.notifications);\r
+ }\r
+\r
+\r
+ /**\r
+ * The collection of operations for this MBean.\r
+ */\r
+ public OperationInfo[] getOperations() {\r
+ return (this.operations);\r
+ }\r
+\r
+\r
+ /**\r
+ * The fully qualified name of the Java class of the resource\r
+ * implementation class described by the managed bean described\r
+ * by this descriptor.\r
+ */\r
+ public String getType() {\r
+ return (this.type);\r
+ }\r
+\r
+ public void setType(String type) {\r
+ this.type = type;\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ // --------------------------------------------------------- Public Methods\r
+\r
+\r
+ /**\r
+ * Add a new attribute to the set of attributes for this MBean.\r
+ *\r
+ * @param attribute The new attribute descriptor\r
+ */\r
+ public void addAttribute(AttributeInfo attribute) {\r
+\r
+ synchronized (attributes) {\r
+ AttributeInfo results[] =\r
+ new AttributeInfo[attributes.length + 1];\r
+ System.arraycopy(attributes, 0, results, 0, attributes.length);\r
+ results[attributes.length] = attribute;\r
+ attributes = results;\r
+ this.info = null;\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Add a new constructor to the set of constructors for this MBean.\r
+ *\r
+ * @param constructor The new constructor descriptor\r
+ */\r
+ public void addConstructor(ConstructorInfo constructor) {\r
+\r
+ synchronized (constructors) {\r
+ ConstructorInfo results[] =\r
+ new ConstructorInfo[constructors.length + 1];\r
+ System.arraycopy(constructors, 0, results, 0, constructors.length);\r
+ results[constructors.length] = constructor;\r
+ constructors = results;\r
+ this.info = null;\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * <p>Add a new field to the fields associated with the\r
+ * Descriptor that will be created from this metadata.</p>\r
+ *\r
+ * @param field The field to be added\r
+ */\r
+ public void addField(FieldInfo field) {\r
+ fields.add(field);\r
+ }\r
+\r
+\r
+ /**\r
+ * Add a new notification to the set of notifications for this MBean.\r
+ *\r
+ * @param notification The new notification descriptor\r
+ */\r
+ public void addNotification(NotificationInfo notification) {\r
+\r
+ synchronized (notifications) {\r
+ NotificationInfo results[] =\r
+ new NotificationInfo[notifications.length + 1];\r
+ System.arraycopy(notifications, 0, results, 0,\r
+ notifications.length);\r
+ results[notifications.length] = notification;\r
+ notifications = results;\r
+ this.info = null;\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Add a new operation to the set of operations for this MBean.\r
+ *\r
+ * @param operation The new operation descriptor\r
+ */\r
+ public void addOperation(OperationInfo operation) {\r
+ synchronized (operations) {\r
+ OperationInfo results[] =\r
+ new OperationInfo[operations.length + 1];\r
+ System.arraycopy(operations, 0, results, 0, operations.length);\r
+ results[operations.length] = operation;\r
+ operations = results;\r
+ this.info = null;\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Create and return a <code>ModelMBean</code> that has been\r
+ * preconfigured with the <code>ModelMBeanInfo</code> information\r
+ * for this managed bean, but is not associated with any particular\r
+ * managed resource. The returned <code>ModelMBean</code> will\r
+ * <strong>NOT</strong> have been registered with our\r
+ * <code>MBeanServer</code>.\r
+ *\r
+ * @exception InstanceNotFoundException if the managed resource\r
+ * object cannot be found\r
+ * @exception InvalidTargetObjectTypeException if our MBean cannot\r
+ * handle object references (should never happen)\r
+ * @exception MBeanException if a problem occurs instantiating the\r
+ * <code>ModelMBean</code> instance\r
+ * @exception RuntimeOperationsException if a JMX runtime error occurs\r
+ */\r
+ public ModelMBean createMBean()\r
+ throws InstanceNotFoundException,\r
+ InvalidTargetObjectTypeException,\r
+ MBeanException, RuntimeOperationsException {\r
+\r
+ return (createMBean(null));\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Create and return a <code>ModelMBean</code> that has been\r
+ * preconfigured with the <code>ModelMBeanInfo</code> information\r
+ * for this managed bean, and is associated with the specified\r
+ * managed object instance. The returned <code>ModelMBean</code>\r
+ * will <strong>NOT</strong> have been registered with our\r
+ * <code>MBeanServer</code>.\r
+ *\r
+ * @param instance Instanced of the managed object, or <code>null</code>\r
+ * for no associated instance\r
+ *\r
+ * @exception InstanceNotFoundException if the managed resource\r
+ * object cannot be found\r
+ * @exception InvalidTargetObjectTypeException if our MBean cannot\r
+ * handle object references (should never happen)\r
+ * @exception MBeanException if a problem occurs instantiating the\r
+ * <code>ModelMBean</code> instance\r
+ * @exception RuntimeOperationsException if a JMX runtime error occurs\r
+ */\r
+ public ModelMBean createMBean(Object instance)\r
+ throws InstanceNotFoundException,\r
+ InvalidTargetObjectTypeException,\r
+ MBeanException, RuntimeOperationsException {\r
+\r
+ // Load the ModelMBean implementation class\r
+ Class clazz = null;\r
+ Exception ex = null;\r
+ try {\r
+ clazz = Class.forName(getClassName());\r
+ } catch (Exception e) {\r
+ }\r
+ \r
+ if( clazz==null ) { \r
+ try {\r
+ ClassLoader cl= Thread.currentThread().getContextClassLoader();\r
+ if ( cl != null)\r
+ clazz= cl.loadClass(getClassName());\r
+ } catch (Exception e) {\r
+ ex=e;\r
+ }\r
+ }\r
+\r
+ if( clazz==null) { \r
+ throw new MBeanException\r
+ (ex, "Cannot load ModelMBean class " + getClassName());\r
+ }\r
+\r
+ // Create a new ModelMBean instance\r
+ ModelMBean mbean = null;\r
+ try {\r
+ mbean = (ModelMBean) clazz.newInstance();\r
+ mbean.setModelMBeanInfo(createMBeanInfo());\r
+ } catch (MBeanException e) {\r
+ throw e;\r
+ } catch (RuntimeOperationsException e) {\r
+ throw e;\r
+ } catch (Exception e) {\r
+ throw new MBeanException\r
+ (e, "Cannot instantiate ModelMBean of class " +\r
+ getClassName());\r
+ }\r
+\r
+ // Set the managed resource (if any)\r
+ try {\r
+ if (instance != null)\r
+ mbean.setManagedResource(instance, "ObjectReference");\r
+ } catch (InstanceNotFoundException e) {\r
+ throw e;\r
+ } catch (InvalidTargetObjectTypeException e) {\r
+ throw e;\r
+ }\r
+ return (mbean);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Create and return a <code>ModelMBeanInfo</code> object that\r
+ * describes this entire managed bean.\r
+ */\r
+ public ModelMBeanInfo createMBeanInfo() {\r
+\r
+ // Return our cached information (if any)\r
+ if (info != null)\r
+ return (info);\r
+\r
+ // Create subordinate information descriptors as required\r
+ AttributeInfo attrs[] = getAttributes();\r
+ ModelMBeanAttributeInfo attributes[] =\r
+ new ModelMBeanAttributeInfo[attrs.length];\r
+ for (int i = 0; i < attrs.length; i++)\r
+ attributes[i] = attrs[i].createAttributeInfo();\r
+ \r
+ ConstructorInfo consts[] = getConstructors();\r
+ ModelMBeanConstructorInfo constructors[] =\r
+ new ModelMBeanConstructorInfo[consts.length];\r
+ for (int i = 0; i < consts.length; i++)\r
+ constructors[i] = consts[i].createConstructorInfo();\r
+ NotificationInfo notifs[] = getNotifications();\r
+ ModelMBeanNotificationInfo notifications[] =\r
+ new ModelMBeanNotificationInfo[notifs.length];\r
+ for (int i = 0; i < notifs.length; i++)\r
+ notifications[i] = notifs[i].createNotificationInfo();\r
+ OperationInfo opers[] = getOperations();\r
+ ModelMBeanOperationInfo operations[] =\r
+ new ModelMBeanOperationInfo[opers.length];\r
+ for (int i = 0; i < opers.length; i++)\r
+ operations[i] = opers[i].createOperationInfo();\r
+\r
+ /*\r
+ // Add operations for attribute getters and setters as needed\r
+ ArrayList list = new ArrayList();\r
+ for (int i = 0; i < operations.length; i++)\r
+ list.add(operations[i]);\r
+ for (int i = 0; i < attributes.length; i++) {\r
+ Descriptor descriptor = attributes[i].getDescriptor();\r
+ String getMethod = (String) descriptor.getFieldValue("getMethod");\r
+ if (getMethod != null) {\r
+ OperationInfo oper =\r
+ new OperationInfo(getMethod, true,\r
+ attributes[i].getType());\r
+ list.add(oper.createOperationInfo());\r
+ }\r
+ String setMethod = (String) descriptor.getFieldValue("setMethod");\r
+ if (setMethod != null) {\r
+ OperationInfo oper =\r
+ new OperationInfo(setMethod, false,\r
+ attributes[i].getType());\r
+ list.add(oper.createOperationInfo());\r
+ }\r
+ }\r
+ if (list.size() > operations.length)\r
+ operations =\r
+ (ModelMBeanOperationInfo[]) list.toArray(operations);\r
+ */\r
+ \r
+ // Construct and return a new ModelMBeanInfo object\r
+ info = new ModelMBeanInfoSupport\r
+ (getClassName(), getDescription(),\r
+ attributes, constructors, operations, notifications);\r
+ try {\r
+ Descriptor descriptor = info.getMBeanDescriptor();\r
+ Iterator fields = getFields().iterator();\r
+ while (fields.hasNext()) {\r
+ FieldInfo field = (FieldInfo) fields.next();\r
+ descriptor.setField(field.getName(), field.getValue());\r
+ }\r
+ info.setMBeanDescriptor(descriptor);\r
+ } catch (MBeanException e) {\r
+ ;\r
+ }\r
+\r
+ return (info);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Return a string representation of this managed bean.\r
+ */\r
+ public String toString() {\r
+\r
+ StringBuffer sb = new StringBuffer("ManagedBean[");\r
+ sb.append("name=");\r
+ sb.append(name);\r
+ sb.append(", className=");\r
+ sb.append(className);\r
+ sb.append(", description=");\r
+ sb.append(description);\r
+ if (group != null) {\r
+ sb.append(", group=");\r
+ sb.append(group);\r
+ }\r
+ sb.append(", type=");\r
+ sb.append(type);\r
+ sb.append("]");\r
+ return (sb.toString());\r
+\r
+ }\r
+\r
+\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.io.Serializable;\r
+\r
+import javax.management.Descriptor;\r
+import javax.management.modelmbean.ModelMBeanNotificationInfo;\r
+\r
+\r
+/**\r
+ * <p>Internal configuration information for a <code>Notification</code>\r
+ * descriptor.</p>\r
+ *\r
+ * @author Craig R. McClanahan\r
+ * @version $Revision: 155428 $ $Date: 2005-02-26 14:12:25 +0100 (sam., 26 févr. 2005) $\r
+ */\r
+\r
+public class NotificationInfo extends FeatureInfo implements Serializable {\r
+ static final long serialVersionUID = -6319885418912650856L;\r
+\r
+ // ----------------------------------------------------- Instance Variables\r
+\r
+\r
+ /**\r
+ * The <code>ModelMBeanNotificationInfo</code> object that corresponds\r
+ * to this <code>NotificationInfo</code> instance.\r
+ */\r
+ transient ModelMBeanNotificationInfo info = null;\r
+ protected String notifTypes[] = new String[0];\r
+\r
+ // ------------------------------------------------------------- Properties\r
+\r
+\r
+ /**\r
+ * Override the <code>description</code> property setter.\r
+ *\r
+ * @param description The new description\r
+ */\r
+ public void setDescription(String description) {\r
+ super.setDescription(description);\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * Override the <code>name</code> property setter.\r
+ *\r
+ * @param name The new name\r
+ */\r
+ public void setName(String name) {\r
+ super.setName(name);\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * The set of notification types for this MBean.\r
+ */\r
+ public String[] getNotifTypes() {\r
+ return (this.notifTypes);\r
+ }\r
+\r
+\r
+ // --------------------------------------------------------- Public Methods\r
+\r
+\r
+ /**\r
+ * Add a new notification type to the set managed by an MBean.\r
+ *\r
+ * @param notifType The new notification type\r
+ */\r
+ public void addNotifType(String notifType) {\r
+\r
+ synchronized (notifTypes) {\r
+ String results[] = new String[notifTypes.length + 1];\r
+ System.arraycopy(notifTypes, 0, results, 0, notifTypes.length);\r
+ results[notifTypes.length] = notifType;\r
+ notifTypes = results;\r
+ this.info = null;\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Create and return a <code>ModelMBeanNotificationInfo</code> object that\r
+ * corresponds to the attribute described by this instance.\r
+ */\r
+ public ModelMBeanNotificationInfo createNotificationInfo() {\r
+\r
+ // Return our cached information (if any)\r
+ if (info != null)\r
+ return (info);\r
+\r
+ // Create and return a new information object\r
+ info = new ModelMBeanNotificationInfo\r
+ (getNotifTypes(), getName(), getDescription());\r
+ Descriptor descriptor = info.getDescriptor();\r
+ addFields(descriptor);\r
+ info.setDescriptor(descriptor);\r
+ return (info);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Return a string representation of this notification descriptor.\r
+ */\r
+ public String toString() {\r
+\r
+ StringBuffer sb = new StringBuffer("NotificationInfo[");\r
+ sb.append("name=");\r
+ sb.append(name);\r
+ sb.append(", description=");\r
+ sb.append(description);\r
+ sb.append(", notifTypes=");\r
+ sb.append(notifTypes.length);\r
+ sb.append("]");\r
+ return (sb.toString());\r
+\r
+ }\r
+\r
+\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.io.Serializable;\r
+\r
+import javax.management.Descriptor;\r
+import javax.management.MBeanParameterInfo;\r
+import javax.management.modelmbean.ModelMBeanOperationInfo;\r
+\r
+\r
+/**\r
+ * <p>Internal configuration information for an <code>Operation</code>\r
+ * descriptor.</p>\r
+ *\r
+ * @author Craig R. McClanahan\r
+ * @version $Revision: 155428 $ $Date: 2005-02-26 14:12:25 +0100 (sam., 26 févr. 2005) $\r
+ */\r
+\r
+public class OperationInfo extends FeatureInfo implements Serializable {\r
+ static final long serialVersionUID = 4418342922072614875L;\r
+ // ----------------------------------------------------------- Constructors\r
+\r
+\r
+ /**\r
+ * Standard zero-arguments constructor.\r
+ */\r
+ public OperationInfo() {\r
+\r
+ super();\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Special constructor for setting up getter and setter operations.\r
+ *\r
+ * @param name Name of this operation\r
+ * @param getter Is this a getter (as opposed to a setter)?\r
+ * @param type Data type of the return value (if this is a getter)\r
+ * or the parameter (if this is a setter)\r
+ * \r
+ */\r
+ public OperationInfo(String name, boolean getter, String type) {\r
+\r
+ super();\r
+ setName(name);\r
+ if (getter) {\r
+ setDescription("Attribute getter method");\r
+ setImpact("INFO");\r
+ setReturnType(type);\r
+ setRole("getter");\r
+ } else {\r
+ setDescription("Attribute setter method");\r
+ setImpact("ACTION");\r
+ setReturnType("void");\r
+ setRole("setter");\r
+ addParameter(new ParameterInfo("value", type,\r
+ "New attribute value"));\r
+ }\r
+\r
+ }\r
+\r
+\r
+ // ----------------------------------------------------- Instance Variables\r
+\r
+\r
+ /**\r
+ * The <code>ModelMBeanOperationInfo</code> object that corresponds\r
+ * to this <code>OperationInfo</code> instance.\r
+ */\r
+ transient ModelMBeanOperationInfo info = null;\r
+ protected String impact = "UNKNOWN";\r
+ protected String role = "operation";\r
+ protected String returnType = "void"; // FIXME - Validate\r
+ protected ParameterInfo parameters[] = new ParameterInfo[0];\r
+\r
+\r
+ // ------------------------------------------------------------- Properties\r
+\r
+\r
+ /**\r
+ * Override the <code>description</code> property setter.\r
+ *\r
+ * @param description The new description\r
+ */\r
+ public void setDescription(String description) {\r
+ super.setDescription(description);\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * Override the <code>name</code> property setter.\r
+ *\r
+ * @param name The new name\r
+ */\r
+ public void setName(String name) {\r
+ super.setName(name);\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * The "impact" of this operation, which should be a (case-insensitive)\r
+ * string value "ACTION", "ACTION_INFO", "INFO", or "UNKNOWN".\r
+ */\r
+ public String getImpact() {\r
+ return (this.impact);\r
+ }\r
+\r
+ public void setImpact(String impact) {\r
+ if (impact == null)\r
+ this.impact = null;\r
+ else\r
+ this.impact = impact.toUpperCase();\r
+ }\r
+\r
+\r
+ /**\r
+ * The role of this operation ("getter", "setter", "operation", or\r
+ * "constructor").\r
+ */\r
+ public String getRole() {\r
+ return (this.role);\r
+ }\r
+\r
+ public void setRole(String role) {\r
+ this.role = role;\r
+ }\r
+\r
+\r
+ /**\r
+ * The fully qualified Java class name of the return type for this\r
+ * operation.\r
+ */\r
+ public String getReturnType() {\r
+ return (this.returnType);\r
+ }\r
+\r
+ public void setReturnType(String returnType) {\r
+ this.returnType = returnType;\r
+ }\r
+\r
+ /**\r
+ * The set of parameters for this operation.\r
+ */\r
+ public ParameterInfo[] getSignature() {\r
+ return (this.parameters);\r
+ }\r
+\r
+ // --------------------------------------------------------- Public Methods\r
+\r
+\r
+ /**\r
+ * Add a new parameter to the set of arguments for this operation.\r
+ *\r
+ * @param parameter The new parameter descriptor\r
+ */\r
+ public void addParameter(ParameterInfo parameter) {\r
+\r
+ synchronized (parameters) {\r
+ ParameterInfo results[] = new ParameterInfo[parameters.length + 1];\r
+ System.arraycopy(parameters, 0, results, 0, parameters.length);\r
+ results[parameters.length] = parameter;\r
+ parameters = results;\r
+ this.info = null;\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Create and return a <code>ModelMBeanOperationInfo</code> object that\r
+ * corresponds to the attribute described by this instance.\r
+ */\r
+ public ModelMBeanOperationInfo createOperationInfo() {\r
+\r
+ // Return our cached information (if any)\r
+ if (info != null)\r
+ return (info);\r
+\r
+ // Create and return a new information object\r
+ ParameterInfo params[] = getSignature();\r
+ MBeanParameterInfo parameters[] =\r
+ new MBeanParameterInfo[params.length];\r
+ for (int i = 0; i < params.length; i++)\r
+ parameters[i] = params[i].createParameterInfo();\r
+ int impact = ModelMBeanOperationInfo.UNKNOWN;\r
+ if ("ACTION".equals(getImpact()))\r
+ impact = ModelMBeanOperationInfo.ACTION;\r
+ else if ("ACTION_INFO".equals(getImpact()))\r
+ impact = ModelMBeanOperationInfo.ACTION_INFO;\r
+ else if ("INFO".equals(getImpact()))\r
+ impact = ModelMBeanOperationInfo.INFO;\r
+\r
+ info = new ModelMBeanOperationInfo\r
+ (getName(), getDescription(), parameters,\r
+ getReturnType(), impact);\r
+ Descriptor descriptor = info.getDescriptor();\r
+ descriptor.removeField("class");\r
+ descriptor.setField("role", getRole());\r
+ addFields(descriptor);\r
+ info.setDescriptor(descriptor);\r
+ return (info);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Return a string representation of this operation descriptor.\r
+ */\r
+ public String toString() {\r
+\r
+ StringBuffer sb = new StringBuffer("OperationInfo[");\r
+ sb.append("name=");\r
+ sb.append(name);\r
+ sb.append(", description=");\r
+ sb.append(description);\r
+ sb.append(", returnType=");\r
+ sb.append(returnType);\r
+ sb.append(", parameters=");\r
+ sb.append(parameters.length);\r
+ sb.append("]");\r
+ return (sb.toString());\r
+\r
+ }\r
+\r
+\r
+}\r
--- /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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.io.Serializable;\r
+\r
+import javax.management.MBeanParameterInfo;\r
+\r
+\r
+/**\r
+ * <p>Internal configuration information for a <code>Parameter</code>\r
+ * descriptor.</p>\r
+ *\r
+ * @author Craig R. McClanahan\r
+ * @version $Revision: 155428 $ $Date: 2005-02-26 14:12:25 +0100 (sam., 26 févr. 2005) $\r
+ */\r
+\r
+public class ParameterInfo extends FeatureInfo implements Serializable {\r
+ static final long serialVersionUID = 2222796006787664020L;\r
+ // ----------------------------------------------------------- Constructors\r
+\r
+\r
+ /**\r
+ * Standard zero-arguments constructor.\r
+ */\r
+ public ParameterInfo() {\r
+\r
+ super();\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Special constructor for setting up parameters programatically.\r
+ *\r
+ * @param name Name of this parameter\r
+ * @param type Java class of this parameter\r
+ * @param description Description of this parameter\r
+ */\r
+ public ParameterInfo(String name, String type, String description) {\r
+\r
+ super();\r
+ setName(name);\r
+ setType(type);\r
+ setDescription(description);\r
+\r
+ }\r
+\r
+\r
+ // ----------------------------------------------------- Instance Variables\r
+\r
+\r
+ /**\r
+ * The <code>MBeanParameterInfo</code> object that corresponds\r
+ * to this <code>ParameterInfo</code> instance.\r
+ */\r
+ transient MBeanParameterInfo info = null;\r
+ protected String type = null;\r
+\r
+ // ------------------------------------------------------------- Properties\r
+\r
+\r
+ /**\r
+ * Override the <code>description</code> property setter.\r
+ *\r
+ * @param description The new description\r
+ */\r
+ public void setDescription(String description) {\r
+ super.setDescription(description);\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * Override the <code>name</code> property setter.\r
+ *\r
+ * @param name The new name\r
+ */\r
+ public void setName(String name) {\r
+ super.setName(name);\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ /**\r
+ * The fully qualified Java class name of this parameter.\r
+ */\r
+ public String getType() {\r
+ return (this.type);\r
+ }\r
+\r
+ public void setType(String type) {\r
+ this.type = type;\r
+ this.info = null;\r
+ }\r
+\r
+\r
+ // --------------------------------------------------------- Public Methods\r
+\r
+\r
+ /**\r
+ * Create and return a <code>MBeanParameterInfo</code> object that\r
+ * corresponds to the parameter described by this instance.\r
+ */\r
+ public MBeanParameterInfo createParameterInfo() {\r
+\r
+ // Return our cached information (if any)\r
+ if (info != null)\r
+ return (info);\r
+\r
+ // Create and return a new information object\r
+ info = new MBeanParameterInfo\r
+ (getName(), getType(), getDescription());\r
+ return (info);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Return a string representation of this parameter descriptor.\r
+ */\r
+ public String toString() {\r
+\r
+ StringBuffer sb = new StringBuffer("ParameterInfo[");\r
+ sb.append("name=");\r
+ sb.append(name);\r
+ sb.append(", description=");\r
+ sb.append(description);\r
+ sb.append(", type=");\r
+ sb.append(type);\r
+ sb.append("]");\r
+ return (sb.toString());\r
+\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2001-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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.InputStream;\r
+import java.net.URL;\r
+import java.util.ArrayList;\r
+import java.util.Enumeration;\r
+import java.util.HashMap;\r
+import java.util.Hashtable;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import javax.management.DynamicMBean;\r
+import javax.management.MBeanAttributeInfo;\r
+import javax.management.MBeanInfo;\r
+import javax.management.MBeanOperationInfo;\r
+import javax.management.MBeanRegistration;\r
+import javax.management.MBeanServer;\r
+import javax.management.MBeanServerFactory;\r
+import javax.management.MalformedObjectNameException;\r
+import javax.management.ObjectName;\r
+import javax.management.modelmbean.ModelMBean;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.apache.tomcat.util.modeler.modules.ModelerSource;\r
+\r
+/*\r
+ Issues:\r
+ - exceptions - too many "throws Exception"\r
+ - double check the interfaces \r
+ - start removing the use of the experimental methods in tomcat, then remove\r
+ the methods ( before 1.1 final )\r
+ - is the security enough to prevent Registry beeing used to avoid the permission\r
+ checks in the mbean server ?\r
+*/ \r
+\r
+/**\r
+ * Registry for modeler MBeans. \r
+ *\r
+ * This is the main entry point into modeler. It provides methods to create\r
+ * and manipulate model mbeans and simplify their use.\r
+ *\r
+ * Starting with version 1.1, this is no longer a singleton and the static\r
+ * methods are strongly deprecated. In a container environment we can expect\r
+ * different applications to use different registries.\r
+ * \r
+ * This class is itself an mbean.\r
+ * \r
+ * IMPORTANT: public methods not marked with @since x.x are experimental or \r
+ * internal. Should not be used. \r
+ * \r
+ * @author Craig R. McClanahan\r
+ * @author Costin Manolache\r
+ */\r
+public class Registry implements RegistryMBean, MBeanRegistration {\r
+ /** Experimental support for manifest-based discovery.\r
+ */\r
+ public static String MODELER_MANIFEST="/META-INF/mbeans-descriptors.xml";\r
+\r
+ /**\r
+ * The Log instance to which we will write our log messages.\r
+ */\r
+ private static Log log = LogFactory.getLog(Registry.class);\r
+\r
+ // Support for the factory methods\r
+ \r
+ /** Will be used to isolate different apps and enhance security\r
+ */\r
+ private static HashMap perLoaderRegistries=null;\r
+\r
+ /**\r
+ * The registry instance created by our factory method the first time\r
+ * it is called.\r
+ */\r
+ private static Registry registry = null;\r
+\r
+ // Per registy fields\r
+ \r
+ /**\r
+ * The <code>MBeanServer</code> instance that we will use to register\r
+ * management beans.\r
+ */\r
+ private MBeanServer server = null;\r
+\r
+ /**\r
+ * The set of ManagedBean instances for the beans this registry\r
+ * knows about, keyed by name.\r
+ */\r
+ private HashMap descriptors = new HashMap();\r
+\r
+ /** List of managed byeans, keyed by class name\r
+ */\r
+ private HashMap descriptorsByClass = new HashMap();\r
+\r
+ // map to avoid duplicated searching or loading descriptors \r
+ private HashMap searchedPaths=new HashMap();\r
+ \r
+ private Object key;\r
+ private Object guard;\r
+\r
+ // Id - small ints to use array access. No reset on stop()\r
+ private Hashtable idDomains=new Hashtable();\r
+ private Hashtable ids=new Hashtable();\r
+\r
+ \r
+ // ----------------------------------------------------------- Constructors\r
+\r
+ /**\r
+ */\r
+ public Registry() {\r
+ super();\r
+ }\r
+\r
+ // -------------------- Static methods --------------------\r
+ // Factories\r
+ \r
+ /**\r
+ * Factory method to create (if necessary) and return our\r
+ * <code>Registry</code> instance.\r
+ *\r
+ * Use this method to obtain a Registry - all other static methods\r
+ * are deprecated and shouldn't be used.\r
+ *\r
+ * The current version uses a static - future versions could use\r
+ * the thread class loader.\r
+ * \r
+ * @param key Support for application isolation. If null, the context class\r
+ * loader will be used ( if setUseContextClassLoader is called ) or the \r
+ * default registry is returned. \r
+ * @param guard Prevent access to the registry by untrusted components\r
+ *\r
+ * @since 1.1\r
+ */\r
+ public synchronized static Registry getRegistry(Object key, Object guard) {\r
+ Registry localRegistry;\r
+ if( perLoaderRegistries!=null ) {\r
+ if( key==null ) \r
+ key=Thread.currentThread().getContextClassLoader();\r
+ if( key != null ) {\r
+ localRegistry=(Registry)perLoaderRegistries.get(key);\r
+ if( localRegistry == null ) {\r
+ localRegistry=new Registry();\r
+ localRegistry.key=key;\r
+ localRegistry.guard=guard;\r
+ perLoaderRegistries.put( key, localRegistry );\r
+ return localRegistry;\r
+ }\r
+ if( localRegistry.guard != null &&\r
+ localRegistry.guard != guard ) {\r
+ return null; // XXX Should I throw a permission ex ? \r
+ }\r
+ return localRegistry;\r
+ }\r
+ }\r
+\r
+ // static \r
+ if (registry == null) {\r
+ registry = new Registry();\r
+ }\r
+ if( registry.guard != null &&\r
+ registry.guard != guard ) {\r
+ return null;\r
+ }\r
+ return (registry);\r
+ }\r
+ \r
+ /** Allow containers to isolate apps. Can be called only once.\r
+ * It is highly recommended you call this method if using Registry in\r
+ * a container environment. The default is false for backward compatibility\r
+ * \r
+ * @param enable\r
+ * @since 1.1\r
+ */\r
+ public static void setUseContextClassLoader( boolean enable ) {\r
+ if( enable ) {\r
+ perLoaderRegistries=new HashMap();\r
+ }\r
+ }\r
+ \r
+ // -------------------- Generic methods --------------------\r
+\r
+ /** Set a guard object that will prevent access to this registry \r
+ * by unauthorized components\r
+ * \r
+ * @param guard\r
+ * \r
+ * @since 1.1\r
+ */ \r
+ public void setGuard( Object guard ) {\r
+ if( this.guard!=null ) {\r
+ return; // already set, only once\r
+ }\r
+ this.guard=guard;\r
+ }\r
+\r
+ /** Lifecycle method - clean up the registry metadata.\r
+ * \r
+ * @since 1.1\r
+ */ \r
+ public void stop() {\r
+ descriptorsByClass = new HashMap();\r
+ descriptors = new HashMap();\r
+ searchedPaths=new HashMap();\r
+ }\r
+ \r
+ /** \r
+ * Load an extended mlet file. The source can be an URL, File or\r
+ * InputStream. \r
+ * \r
+ * All mbeans will be instantiated, registered and the attributes will be \r
+ * set. The result is a list of ObjectNames.\r
+ *\r
+ * @param source InputStream or URL of the file\r
+ * @param cl ClassLoader to be used to load the mbeans, or null to use the\r
+ * default JMX mechanism ( i.e. all registered loaders )\r
+ * @return List of ObjectName for the loaded mbeans\r
+ * @throws Exception\r
+ * \r
+ * @since 1.1\r
+ */ \r
+ public List loadMBeans( Object source, ClassLoader cl )\r
+ throws Exception\r
+ {\r
+ return load("MbeansSource", source, null );\r
+ } \r
+\r
+\r
+ /** Load descriptors. The source can be a File or URL or InputStream for the \r
+ * descriptors file. In the case of File and URL, if the extension is ".ser"\r
+ * a serialized version will be loaded. \r
+ * \r
+ * Also ( experimental for now ) a ClassLoader - in which case META-INF/ will\r
+ * be used.\r
+ * \r
+ * This method should be used to explicitely load metadata - but this is not\r
+ * required in most cases. The registerComponent() method will find metadata\r
+ * in the same pacakge.\r
+ * \r
+ * @param source\r
+ */ \r
+ public void loadMetadata(Object source ) throws Exception {\r
+ if( source instanceof ClassLoader ) {\r
+ loadMetaInfDescriptors((ClassLoader)source);\r
+ return;\r
+ } else {\r
+ loadDescriptors( null, source, null );\r
+ }\r
+ \r
+ }\r
+\r
+ /** Register a bean by creating a modeler mbean and adding it to the \r
+ * MBeanServer.\r
+ * \r
+ * If metadata is not loaded, we'll look up and read a file named\r
+ * "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package\r
+ * or parent.\r
+ *\r
+ * If the bean is an instance of DynamicMBean. it's metadata will be converted\r
+ * to a model mbean and we'll wrap it - so modeler services will be supported\r
+ *\r
+ * If the metadata is still not found, introspection will be used to extract\r
+ * it automatically. \r
+ * \r
+ * If an mbean is already registered under this name, it'll be first\r
+ * unregistered.\r
+ * \r
+ * If the component implements MBeanRegistration, the methods will be called.\r
+ * If the method has a method "setRegistry" that takes a RegistryMBean as\r
+ * parameter, it'll be called with the current registry.\r
+ * \r
+ *\r
+ * @param bean Object to be registered\r
+ * @param oname Name used for registration\r
+ * @param type The type of the mbean, as declared in mbeans-descriptors. If\r
+ * null, the name of the class will be used. This can be used as a hint or\r
+ * by subclasses.\r
+ *\r
+ * @since 1.1\r
+ */ \r
+ public void registerComponent(Object bean, String oname, String type)\r
+ throws Exception\r
+ {\r
+ registerComponent(bean, new ObjectName(oname), type); \r
+ } \r
+\r
+ /** Unregister a component. We'll first check if it is registered,\r
+ * and mask all errors. This is mostly a helper.\r
+ * \r
+ * @param oname\r
+ * \r
+ * @since 1.1\r
+ */ \r
+ public void unregisterComponent( String oname ) {\r
+ try {\r
+ unregisterComponent(new ObjectName(oname));\r
+ } catch (MalformedObjectNameException e) {\r
+ log.info("Error creating object name " + e );\r
+ }\r
+ } \r
+ \r
+\r
+ /** Invoke a operation on a list of mbeans. Can be used to implement\r
+ * lifecycle operations.\r
+ *\r
+ * @param mbeans list of ObjectName on which we'll invoke the operations\r
+ * @param operation Name of the operation ( init, start, stop, etc)\r
+ * @param failFirst If false, exceptions will be ignored\r
+ * @throws Exception\r
+ * @since 1.1\r
+ */\r
+ public void invoke( List mbeans, String operation, boolean failFirst )\r
+ throws Exception\r
+ {\r
+ if( mbeans==null ) {\r
+ return;\r
+ }\r
+ Iterator itr=mbeans.iterator();\r
+ while(itr.hasNext()) {\r
+ Object current=itr.next();\r
+ ObjectName oN=null;\r
+ try {\r
+ if( current instanceof ObjectName) {\r
+ oN=(ObjectName)current;\r
+ }\r
+ if( current instanceof String ) {\r
+ oN=new ObjectName( (String)current );\r
+ }\r
+ if( oN==null ) {\r
+ continue;\r
+ }\r
+ if( getMethodInfo(oN, operation) == null) {\r
+ continue;\r
+ }\r
+ getMBeanServer().invoke(oN, operation,\r
+ new Object[] {}, new String[] {});\r
+\r
+ } catch( Exception t ) {\r
+ if( failFirst ) throw t;\r
+ log.info("Error initializing " + current + " " + t.toString());\r
+ }\r
+ }\r
+ }\r
+\r
+ // -------------------- ID registry --------------------\r
+\r
+ /** Return an int ID for faster access. Will be used for notifications\r
+ * and for other operations we want to optimize. \r
+ *\r
+ * @param domain Namespace \r
+ * @param name Type of the notification\r
+ * @return An unique id for the domain:name combination\r
+ * @since 1.1\r
+ */\r
+ public synchronized int getId( String domain, String name) {\r
+ if( domain==null) {\r
+ domain="";\r
+ }\r
+ Hashtable domainTable=(Hashtable)idDomains.get( domain );\r
+ if( domainTable == null ) {\r
+ domainTable=new Hashtable();\r
+ idDomains.put( domain, domainTable); \r
+ }\r
+ if( name==null ) {\r
+ name="";\r
+ }\r
+ Integer i=(Integer)domainTable.get(name);\r
+ \r
+ if( i!= null ) {\r
+ return i.intValue();\r
+ }\r
+\r
+ int id[]=(int [])ids.get( domain );\r
+ if( id == null ) {\r
+ id=new int[1];\r
+ ids.put( domain, id); \r
+ }\r
+ int code=id[0]++;\r
+ domainTable.put( name, new Integer( code ));\r
+ return code;\r
+ }\r
+ \r
+ // -------------------- Metadata --------------------\r
+ // methods from 1.0\r
+\r
+ /**\r
+ * Add a new bean metadata to the set of beans known to this registry.\r
+ * This is used by internal components.\r
+ *\r
+ * @param bean The managed bean to be added\r
+ * @since 1.0\r
+ */\r
+ public void addManagedBean(ManagedBean bean) {\r
+ // XXX Use group + name\r
+ descriptors.put(bean.getName(), bean);\r
+ if( bean.getType() != null ) {\r
+ descriptorsByClass.put( bean.getType(), bean );\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * Find and return the managed bean definition for the specified\r
+ * bean name, if any; otherwise return <code>null</code>.\r
+ *\r
+ * @param name Name of the managed bean to be returned. Since 1.1, both\r
+ * short names or the full name of the class can be used.\r
+ * @since 1.0\r
+ */\r
+ public ManagedBean findManagedBean(String name) {\r
+ // XXX Group ?? Use Group + Type\r
+ ManagedBean mb=((ManagedBean) descriptors.get(name));\r
+ if( mb==null )\r
+ mb=(ManagedBean)descriptorsByClass.get(name);\r
+ return mb;\r
+ }\r
+ \r
+ /**\r
+ * Return the set of bean names for all managed beans known to\r
+ * this registry.\r
+ *\r
+ * @since 1.0\r
+ */\r
+ public String[] findManagedBeans() {\r
+ return ((String[]) descriptors.keySet().toArray(new String[0]));\r
+ }\r
+\r
+\r
+ /**\r
+ * Return the set of bean names for all managed beans known to\r
+ * this registry that belong to the specified group.\r
+ *\r
+ * @param group Name of the group of interest, or <code>null</code>\r
+ * to select beans that do <em>not</em> belong to a group\r
+ * @since 1.0\r
+ */\r
+ public String[] findManagedBeans(String group) {\r
+\r
+ ArrayList results = new ArrayList();\r
+ Iterator items = descriptors.values().iterator();\r
+ while (items.hasNext()) {\r
+ ManagedBean item = (ManagedBean) items.next();\r
+ if ((group == null) && (item.getGroup() == null)) {\r
+ results.add(item.getName());\r
+ } else if (group.equals(item.getGroup())) {\r
+ results.add(item.getName());\r
+ }\r
+ }\r
+ String values[] = new String[results.size()];\r
+ return ((String[]) results.toArray(values));\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Remove an existing bean from the set of beans known to this registry.\r
+ *\r
+ * @param bean The managed bean to be removed\r
+ * @since 1.0\r
+ */\r
+ public void removeManagedBean(ManagedBean bean) {\r
+ // TODO: change this to use group/name\r
+ descriptors.remove(bean.getName());\r
+ descriptorsByClass.remove( bean.getType());\r
+ }\r
+\r
+ // -------------------- Deprecated 1.0 methods --------------------\r
+ \r
+ /**\r
+ * Factory method to create (if necessary) and return our\r
+ * <code>MBeanServer</code> instance.\r
+ *\r
+ * @since 1.0\r
+ * @deprecated Use the instance method\r
+ */\r
+ public static MBeanServer getServer() {\r
+ return Registry.getRegistry().getMBeanServer();\r
+ }\r
+\r
+ /**\r
+ * Set the <code>MBeanServer</code> to be utilized for our\r
+ * registered management beans.\r
+ *\r
+ * @param mbeanServer The new <code>MBeanServer</code> instance\r
+ * @since 1.0\r
+ * @deprecated Use the instance method\r
+ */\r
+ public static void setServer(MBeanServer mbeanServer) {\r
+ Registry.getRegistry().setMBeanServer(mbeanServer);\r
+ }\r
+\r
+ /**\r
+ * Load the registry from the XML input found in the specified input\r
+ * stream.\r
+ *\r
+ * @param stream InputStream containing the registry configuration\r
+ * information\r
+ *\r
+ * @exception Exception if any parsing or processing error occurs\r
+ * @deprecated use normal class method instead\r
+ * @since 1.0\r
+ */\r
+ public static void loadRegistry(InputStream stream) throws Exception {\r
+ Registry registry = getRegistry();\r
+ registry.loadMetadata(stream);\r
+ }\r
+\r
+ /** Get a "singelton" registry, or one per thread if setUseContextLoader \r
+ * was called \r
+ * \r
+ * @deprecated Not enough info - use the method that takes CL and domain\r
+ * @since 1.0 \r
+ */ \r
+ public synchronized static Registry getRegistry() {\r
+ return getRegistry(null, null);\r
+ } \r
+\r
+ // -------------------- Helpers --------------------\r
+\r
+ /** Get the type of an attribute of the object, from the metadata.\r
+ *\r
+ * @param oname\r
+ * @param attName\r
+ * @return null if metadata about the attribute is not found\r
+ * @since 1.1\r
+ */\r
+ public String getType( ObjectName oname, String attName )\r
+ {\r
+ String type=null;\r
+ MBeanInfo info=null;\r
+ try {\r
+ info=server.getMBeanInfo(oname);\r
+ } catch (Exception e) {\r
+ log.info( "Can't find metadata for object" + oname );\r
+ return null;\r
+ }\r
+\r
+ MBeanAttributeInfo attInfo[]=info.getAttributes();\r
+ for( int i=0; i<attInfo.length; i++ ) {\r
+ if( attName.equals(attInfo[i].getName())) {\r
+ type=attInfo[i].getType();\r
+ return type;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /** Find the operation info for a method\r
+ * \r
+ * @param oname\r
+ * @param opName\r
+ * @return the operation info for the specified operation\r
+ */ \r
+ public MBeanOperationInfo getMethodInfo( ObjectName oname, String opName )\r
+ {\r
+ String type=null;\r
+ MBeanInfo info=null;\r
+ try {\r
+ info=server.getMBeanInfo(oname);\r
+ } catch (Exception e) {\r
+ log.info( "Can't find metadata " + oname );\r
+ return null;\r
+ }\r
+ MBeanOperationInfo attInfo[]=info.getOperations();\r
+ for( int i=0; i<attInfo.length; i++ ) {\r
+ if( opName.equals(attInfo[i].getName())) {\r
+ return attInfo[i];\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /** Unregister a component. This is just a helper that\r
+ * avoids exceptions by checking if the mbean is already registered\r
+ *\r
+ * @param oname\r
+ */\r
+ public void unregisterComponent( ObjectName oname ) {\r
+ try {\r
+ if( getMBeanServer().isRegistered(oname)) {\r
+ getMBeanServer().unregisterMBean(oname);\r
+ }\r
+ } catch( Throwable t ) {\r
+ log.error( "Error unregistering mbean ", t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Factory method to create (if necessary) and return our\r
+ * <code>MBeanServer</code> instance.\r
+ *\r
+ */\r
+ public synchronized MBeanServer getMBeanServer() {\r
+ long t1=System.currentTimeMillis();\r
+\r
+ if (server == null) {\r
+ if( MBeanServerFactory.findMBeanServer(null).size() > 0 ) {\r
+ server=(MBeanServer)MBeanServerFactory.findMBeanServer(null).get(0);\r
+ if( log.isDebugEnabled() ) {\r
+ log.debug("Using existing MBeanServer " + (System.currentTimeMillis() - t1 ));\r
+ }\r
+ } else {\r
+ server=MBeanServerFactory.createMBeanServer();\r
+ if( log.isDebugEnabled() ) {\r
+ log.debug("Creating MBeanServer"+ (System.currentTimeMillis() - t1 ));\r
+ }\r
+ }\r
+ }\r
+ return (server);\r
+ }\r
+\r
+ /** Find or load metadata. \r
+ */ \r
+ public ManagedBean findManagedBean(Object bean, Class beanClass, String type)\r
+ throws Exception\r
+ {\r
+ if( bean!=null && beanClass==null ) {\r
+ beanClass=bean.getClass();\r
+ }\r
+ \r
+ if( type==null ) {\r
+ type=beanClass.getName();\r
+ }\r
+ \r
+ // first look for existing descriptor\r
+ ManagedBean managed = findManagedBean(type);\r
+\r
+ // Search for a descriptor in the same package\r
+ if( managed==null ) {\r
+ // check package and parent packages\r
+ if( log.isDebugEnabled() ) {\r
+ log.debug( "Looking for descriptor ");\r
+ }\r
+ findDescriptor( beanClass, type );\r
+\r
+ managed=findManagedBean(type);\r
+ }\r
+ \r
+ if( bean instanceof DynamicMBean ) {\r
+ if( log.isDebugEnabled() ) {\r
+ log.debug( "Dynamic mbean support ");\r
+ }\r
+ // Dynamic mbean\r
+ loadDescriptors("MbeansDescriptorsDynamicMBeanSource",\r
+ bean, type);\r
+\r
+ managed=findManagedBean(type);\r
+ }\r
+\r
+ // Still not found - use introspection\r
+ if( managed==null ) {\r
+ if( log.isDebugEnabled() ) {\r
+ log.debug( "Introspecting ");\r
+ }\r
+\r
+ // introspection\r
+ loadDescriptors("MbeansDescriptorsIntrospectionSource",\r
+ beanClass, type);\r
+\r
+ managed=findManagedBean(type);\r
+ if( managed==null ) {\r
+ log.warn( "No metadata found for " + type );\r
+ return null;\r
+ }\r
+ managed.setName( type );\r
+ addManagedBean(managed);\r
+ }\r
+ return managed;\r
+ }\r
+ \r
+\r
+ /** EXPERIMENTAL Convert a string to object, based on type. Used by several\r
+ * components. We could provide some pluggability. It is here to keep\r
+ * things consistent and avoid duplication in other tasks \r
+ * \r
+ * @param type Fully qualified class name of the resulting value\r
+ * @param value String value to be converted\r
+ * @return Converted value\r
+ */ \r
+ public Object convertValue(String type, String value)\r
+ {\r
+ Object objValue=value;\r
+ \r
+ if( type==null || "java.lang.String".equals( type )) {\r
+ // string is default\r
+ objValue=value;\r
+ } else if( "javax.management.ObjectName".equals( type ) ||\r
+ "ObjectName".equals( type )) {\r
+ try {\r
+ objValue=new ObjectName( value );\r
+ } catch (MalformedObjectNameException e) {\r
+ return null;\r
+ }\r
+ } else if( "java.lang.Integer".equals( type ) ||\r
+ "int".equals( type )) {\r
+ objValue=new Integer( value );\r
+ } else if( "java.lang.Boolean".equals( type ) ||\r
+ "boolean".equals( type )) {\r
+ objValue=new Boolean( value );\r
+ }\r
+ return objValue;\r
+ }\r
+ \r
+ /** Experimental.\r
+ *\r
+ * @param sourceType\r
+ * @param source\r
+ * @param param\r
+ * @return List of descriptors\r
+ * @throws Exception\r
+ * @deprecated bad interface, mixing of metadata and mbeans\r
+ */\r
+ public List load( String sourceType, Object source, String param)\r
+ throws Exception\r
+ {\r
+ if( log.isTraceEnabled()) {\r
+ log.trace("load " + source );\r
+ }\r
+ String location=null;\r
+ String type=null;\r
+ Object inputsource=null;\r
+\r
+ if( source instanceof DynamicMBean ) {\r
+ sourceType="MbeansDescriptorsDynamicMBeanSource";\r
+ inputsource=source;\r
+ } else if( source instanceof URL ) {\r
+ URL url=(URL)source;\r
+ location=url.toString();\r
+ type=param;\r
+ inputsource=url.openStream();\r
+ if( sourceType == null ) {\r
+ sourceType = sourceTypeFromExt(location);\r
+ }\r
+ } else if( source instanceof File ) {\r
+ location=((File)source).getAbsolutePath();\r
+ inputsource=new FileInputStream((File)source); \r
+ type=param;\r
+ if( sourceType == null ) {\r
+ sourceType = sourceTypeFromExt(location);\r
+ }\r
+ } else if( source instanceof InputStream ) {\r
+ type=param;\r
+ inputsource=source;\r
+ } else if( source instanceof Class ) {\r
+ location=((Class)source).getName();\r
+ type=param;\r
+ inputsource=source;\r
+ if( sourceType== null ) {\r
+ sourceType="MbeansDescriptorsIntrospectionSource";\r
+ }\r
+ }\r
+ \r
+ if( sourceType==null ) {\r
+ sourceType="MbeansDescriptorsDOMSource";\r
+ }\r
+ ModelerSource ds=getModelerSource(sourceType);\r
+ List mbeans=ds.loadDescriptors(this, location, type, inputsource);\r
+\r
+ return mbeans;\r
+ }\r
+\r
+ private String sourceTypeFromExt( String s ) {\r
+ if( s.endsWith( ".ser")) {\r
+ return "MbeansDescriptorsSerSource";\r
+ }\r
+ else if( s.endsWith(".xml")) {\r
+ return "MbeansDescriptorsDOMSource";\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /** Register a component \r
+ * XXX make it private \r
+ * \r
+ * @param bean\r
+ * @param oname\r
+ * @param type\r
+ * @throws Exception\r
+ */ \r
+ public void registerComponent(Object bean, ObjectName oname, String type)\r
+ throws Exception\r
+ {\r
+ if( log.isDebugEnabled() ) {\r
+ log.debug( "Managed= "+ oname);\r
+ }\r
+\r
+ if( bean ==null ) {\r
+ log.error("Null component " + oname );\r
+ return;\r
+ }\r
+\r
+ try {\r
+ if( type==null ) {\r
+ type=bean.getClass().getName();\r
+ }\r
+\r
+ ManagedBean managed = findManagedBean(bean.getClass(), type);\r
+\r
+ // The real mbean is created and registered\r
+ ModelMBean mbean = managed.createMBean(bean);\r
+\r
+ if( getMBeanServer().isRegistered( oname )) {\r
+ if( log.isDebugEnabled()) {\r
+ log.debug("Unregistering existing component " + oname );\r
+ }\r
+ getMBeanServer().unregisterMBean( oname );\r
+ }\r
+\r
+ getMBeanServer().registerMBean( mbean, oname);\r
+ } catch( Exception ex) {\r
+ log.error("Error registering " + oname, ex );\r
+ throw ex;\r
+ }\r
+ }\r
+\r
+ /** Lookup the component descriptor in the package and\r
+ * in the parent packages.\r
+ *\r
+ * @param packageName\r
+ */\r
+ public void loadDescriptors( String packageName, ClassLoader classLoader ) {\r
+ String res=packageName.replace( '.', '/');\r
+\r
+ if( log.isTraceEnabled() ) {\r
+ log.trace("Finding descriptor " + res );\r
+ }\r
+\r
+ if( searchedPaths.get( packageName ) != null ) {\r
+ return;\r
+ }\r
+ String descriptors=res + "/mbeans-descriptors.ser";\r
+\r
+ URL dURL=classLoader.getResource( descriptors );\r
+\r
+ if( dURL == null ) {\r
+ descriptors=res + "/mbeans-descriptors.xml";\r
+ dURL=classLoader.getResource( descriptors );\r
+ }\r
+ if( dURL == null ) {\r
+ return;\r
+ }\r
+\r
+ log.debug( "Found " + dURL);\r
+ searchedPaths.put( packageName, dURL );\r
+ try {\r
+ if( descriptors.endsWith(".xml" ))\r
+ loadDescriptors("MbeansDescriptorsDOMSource", dURL, null);\r
+ else\r
+ loadDescriptors("MbeansDescriptorsSerSource", dURL, null);\r
+ return;\r
+ } catch(Exception ex ) {\r
+ log.error("Error loading " + dURL);\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+ /** Experimental. Will become private, some code may still use it\r
+ *\r
+ * @param sourceType\r
+ * @param source\r
+ * @param param\r
+ * @throws Exception\r
+ * @deprecated\r
+ */\r
+ public void loadDescriptors( String sourceType, Object source, String param)\r
+ throws Exception\r
+ {\r
+ List mbeans=load( sourceType, source, param );\r
+ if( mbeans == null) return;\r
+\r
+ Iterator itr=mbeans.iterator();\r
+ while( itr.hasNext() ) {\r
+ Object mb=itr.next();\r
+ if( mb instanceof ManagedBean) {\r
+ addManagedBean((ManagedBean)mb);\r
+ }\r
+ }\r
+ }\r
+\r
+ /** Discover all META-INF/modeler.xml files in classpath and register\r
+ * the components\r
+ *\r
+ * @since EXPERIMENTAL\r
+ */\r
+ private void loadMetaInfDescriptors(ClassLoader cl) {\r
+ try {\r
+ Enumeration en=cl.getResources(MODELER_MANIFEST);\r
+ while( en.hasMoreElements() ) {\r
+ URL url=(URL)en.nextElement();\r
+ InputStream is=url.openStream();\r
+ if( log.isDebugEnabled()) log.debug("Loading " + url);\r
+ loadDescriptors("MBeansDescriptorDOMSource", is, null );\r
+ }\r
+ } catch( Exception ex ) {\r
+ ex.printStackTrace();\r
+ }\r
+ }\r
+\r
+ /** Lookup the component descriptor in the package and\r
+ * in the parent packages.\r
+ *\r
+ * @param beanClass\r
+ * @param type\r
+ */\r
+ private void findDescriptor( Class beanClass, String type ) {\r
+ if( type==null ) {\r
+ type=beanClass.getName();\r
+ }\r
+ ClassLoader classLoader=null;\r
+ if( beanClass!=null ) {\r
+ classLoader=beanClass.getClassLoader();\r
+ }\r
+ if( classLoader==null ) {\r
+ classLoader=Thread.currentThread().getContextClassLoader();\r
+ }\r
+ if( classLoader==null ) {\r
+ classLoader=this.getClass().getClassLoader();\r
+ }\r
+ \r
+ String className=type;\r
+ String pkg=className;\r
+ while( pkg.indexOf( ".") > 0 ) {\r
+ int lastComp=pkg.lastIndexOf( ".");\r
+ if( lastComp <= 0 ) return;\r
+ pkg=pkg.substring(0, lastComp);\r
+ if( searchedPaths.get( pkg ) != null ) {\r
+ return;\r
+ }\r
+ loadDescriptors(pkg, classLoader);\r
+ }\r
+ return;\r
+ }\r
+\r
+ private ModelerSource getModelerSource( String type )\r
+ throws Exception\r
+ {\r
+ if( type==null ) type="MbeansDescriptorsDOMSource";\r
+ if( type.indexOf( ".") < 0 ) {\r
+ type="org.apache.tomcat.util.modeler.modules." + type;\r
+ }\r
+\r
+ Class c=Class.forName( type );\r
+ ModelerSource ds=(ModelerSource)c.newInstance();\r
+ return ds;\r
+ }\r
+\r
+\r
+ // -------------------- Registration --------------------\r
+ \r
+ public ObjectName preRegister(MBeanServer server,\r
+ ObjectName name) throws Exception \r
+ {\r
+ this.server=server;\r
+ return name;\r
+ }\r
+\r
+ public void postRegister(Boolean registrationDone) {\r
+ }\r
+\r
+ public void preDeregister() throws Exception {\r
+ }\r
+\r
+ public void postDeregister() {\r
+ }\r
+\r
+ \r
+ \r
+ \r
+ // -------------------- DEPRECATED METHODS --------------------\r
+ // May still be used in tomcat \r
+ // Never part of an official release\r
+ \r
+ /** Called by a registry or by the container to unload a loader\r
+ * @param loader\r
+ */\r
+ public void unregisterRegistry(ClassLoader loader ) {\r
+ // XXX Cleanup ?\r
+ perLoaderRegistries.remove(loader);\r
+ }\r
+\r
+ public ManagedBean findManagedBean(Class beanClass, String type)\r
+ throws Exception\r
+ {\r
+ return findManagedBean(null, beanClass, type); \r
+ }\r
+ \r
+ /**\r
+ * Set the <code>MBeanServer</code> to be utilized for our\r
+ * registered management beans.\r
+ *\r
+ * @param server The new <code>MBeanServer</code> instance\r
+ */\r
+ public void setMBeanServer( MBeanServer server ) {\r
+ this.server=server;\r
+ }\r
+\r
+ public void resetMetadata() {\r
+ stop();\r
+ }\r
+ /**\r
+ * Load the registry from the XML input found in the specified input\r
+ * stream.\r
+ *\r
+ * @param source Source to be used to load. Can be an InputStream or URL.\r
+ *\r
+ * @exception Exception if any parsing or processing error occurs\r
+ */\r
+ public void loadDescriptors( Object source )\r
+ throws Exception\r
+ {\r
+ loadDescriptors("MbeansDescriptorsDOMSource", source, null );\r
+ }\r
+\r
+ /** @deprecated - may still be used in code using pre-1.1 builds\r
+ */\r
+ public void registerComponent(Object bean, String domain, String type,\r
+ String name)\r
+ throws Exception\r
+ {\r
+ StringBuffer sb=new StringBuffer();\r
+ sb.append( domain ).append(":");\r
+ sb.append( name );\r
+ String nameStr=sb.toString();\r
+ ObjectName oname=new ObjectName( nameStr );\r
+ registerComponent(bean, oname, type );\r
+ }\r
+\r
+ \r
+\r
+ // should be removed\r
+ public void unregisterComponent( String domain, String name ) {\r
+ try {\r
+ ObjectName oname=new ObjectName( domain + ":" + name );\r
+\r
+ // XXX remove from our tables.\r
+ getMBeanServer().unregisterMBean( oname );\r
+ } catch( Throwable t ) {\r
+ log.error( "Error unregistering mbean ", t );\r
+ }\r
+ }\r
+ \r
+ public List loadMBeans( Object source )\r
+ throws Exception\r
+ {\r
+ return loadMBeans( source, null );\r
+ }\r
+\r
+\r
+ /**\r
+ * Load the registry from a cached .ser file. This is typically 2-3 times\r
+ * faster than parsing the XML.\r
+ *\r
+ * @param source Source to be used to load. Can be an InputStream or URL.\r
+ *\r
+ * @exception Exception if any parsing or processing error occurs\r
+ * @deprecated Loaded automatically or using a File or Url ending in .ser\r
+ */\r
+ public void loadCachedDescriptors( Object source )\r
+ throws Exception\r
+ {\r
+ loadDescriptors("MbeansDescriptorsSerSource", source, null );\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2001-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
+\r
+package org.apache.tomcat.util.modeler;\r
+\r
+\r
+import java.util.List;\r
+\r
+/**\r
+ * Interface for modeler MBeans.\r
+ * \r
+ * This is the main entry point into modeler. It provides methods to create\r
+ * and manipulate model mbeans and simplify their use.\r
+ *\r
+ * Starting with version 1.1, this is no longer a singleton and the static\r
+ * methods are strongly deprecated. In a container environment we can expect\r
+ * different applications to use different registries.\r
+ * \r
+ * @author Craig R. McClanahan\r
+ * @author Costin Manolache\r
+ * \r
+ * @since 1.1\r
+ */\r
+public interface RegistryMBean {\r
+\r
+ /** \r
+ * Load an extended mlet file. The source can be an URL, File or\r
+ * InputStream. \r
+ * \r
+ * All mbeans will be instantiated, registered and the attributes will be \r
+ * set. The result is a list of ObjectNames.\r
+ *\r
+ * @param source InputStream or URL of the file\r
+ * @param cl ClassLoader to be used to load the mbeans, or null to use the\r
+ * default JMX mechanism ( i.e. all registered loaders )\r
+ * @return List of ObjectName for the loaded mbeans\r
+ * @throws Exception\r
+ * \r
+ * @since 1.1\r
+ */ \r
+ public List loadMBeans( Object source, ClassLoader cl ) throws Exception;\r
+\r
+ /** Invoke an operation on a set of mbeans. \r
+ * \r
+ * @param mbeans List of ObjectNames\r
+ * @param operation Operation to perform. Typically "init" "start" "stop" or "destroy"\r
+ * @param failFirst Behavior in case of exceptions - if false we'll ignore\r
+ * errors\r
+ * @throws Exception\r
+ */ \r
+ public void invoke( List mbeans, String operation, boolean failFirst )\r
+ throws Exception;\r
+\r
+ /** Register a bean by creating a modeler mbean and adding it to the \r
+ * MBeanServer.\r
+ * \r
+ * If metadata is not loaded, we'll look up and read a file named\r
+ * "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package\r
+ * or parent.\r
+ *\r
+ * If the bean is an instance of DynamicMBean. it's metadata will be converted\r
+ * to a model mbean and we'll wrap it - so modeler services will be supported\r
+ *\r
+ * If the metadata is still not found, introspection will be used to extract\r
+ * it automatically. \r
+ * \r
+ * If an mbean is already registered under this name, it'll be first\r
+ * unregistered.\r
+ * \r
+ * If the component implements MBeanRegistration, the methods will be called.\r
+ * If the method has a method "setRegistry" that takes a RegistryMBean as\r
+ * parameter, it'll be called with the current registry.\r
+ * \r
+ *\r
+ * @param bean Object to be registered\r
+ * @param oname Name used for registration\r
+ * @param type The type of the mbean, as declared in mbeans-descriptors. If\r
+ * null, the name of the class will be used. This can be used as a hint or\r
+ * by subclasses.\r
+ *\r
+ * @since 1.1\r
+ */ \r
+ public void registerComponent(Object bean, String oname, String type)\r
+ throws Exception;\r
+\r
+ /** Unregister a component. We'll first check if it is registered,\r
+ * and mask all errors. This is mostly a helper.\r
+ * \r
+ * @param oname\r
+ * \r
+ * @since 1.1\r
+ */ \r
+ public void unregisterComponent( String oname );\r
+\r
+\r
+ /** Return an int ID for faster access. Will be used for notifications\r
+ * and for other operations we want to optimize. \r
+ *\r
+ * @param domain Namespace \r
+ * @param name Type of the notification\r
+ * @return An unique id for the domain:name combination\r
+ * @since 1.1\r
+ */\r
+ public int getId( String domain, String name);\r
+\r
+\r
+ /** Reset all metadata cached by this registry. Should be called \r
+ * to support reloading. Existing mbeans will not be affected or modified.\r
+ * \r
+ * It will be called automatically if the Registry is unregistered.\r
+ * @since 1.1\r
+ */ \r
+ public void stop();\r
+\r
+ /** Load descriptors. The source can be a File, URL pointing to an\r
+ * mbeans-descriptors.xml.\r
+ * \r
+ * Also ( experimental for now ) a ClassLoader - in which case META-INF/ will\r
+ * be used.\r
+ * \r
+ * @param source\r
+ */ \r
+ public void loadMetadata(Object source ) throws Exception;\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>\r
+\r
+\r
+<!--\r
+ DTD for the Model MBeans Configuration File\r
+\r
+ To support validation of your configuration file, include the following\r
+ DOCTYPE element at the beginning (after the "xml" declaration):\r
+\r
+ <!DOCTYPE mbeans-descriptors PUBLIC\r
+ "-//Apache Software Foundation//DTD Model MBeans Configuration File"\r
+ "http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">\r
+\r
+ $Id: mbeans-descriptors.dtd 155428 2005-02-26 13:12:25Z dirkv $\r
+-->\r
+\r
+\r
+<!-- ========== Defined Types ============================================= -->\r
+\r
+\r
+<!-- A "Boolean" is the string representation of a boolean (true or false)\r
+ variable.\r
+-->\r
+<!ENTITY % Boolean "(true|false|yes|no)">\r
+\r
+\r
+<!-- A "ClassName" is the fully qualified name of a Java class that is\r
+ instantiated to provide the functionality of the enclosing element.\r
+-->\r
+<!ENTITY % ClassName "CDATA">\r
+\r
+\r
+<!-- A "MethodName" is the name of a constructor or method, which must\r
+ be legal according to the syntax requirements of the Java language.\r
+-->\r
+<!ENTITY % MethodName "CDATA">\r
+\r
+\r
+<!-- A "VariableName" is the name of a variable or parameter, which must\r
+ be legal according to the syntax requirements of the Java language.\r
+-->\r
+<!ENTITY % VariableName "CDATA">\r
+\r
+\r
+<!-- ========== Element Definitions ======================================= -->\r
+\r
+\r
+<!-- The "mbeans-descriptors" element is the root of the configuration file\r
+ hierarchy, and contains nested elements for all of the other\r
+ configuration settings. Remaining element definitions are listed\r
+ in alphabetical order.\r
+-->\r
+<!ELEMENT mbeans-descriptors (mbean*)>\r
+<!ATTLIST mbeans-descriptors id ID #IMPLIED>\r
+\r
+\r
+<!-- The "attribute" element describes a JavaBeans property of an MBean.\r
+ The following attributes are supported:\r
+\r
+ description Human-readable description of this attribute.\r
+\r
+ displayName Display name of this attribute.\r
+\r
+ getMethod Name of the property getter method, if it does\r
+ not follow standard JavaBeans naming patterns.\r
+\r
+ is Boolean value indicating whether or not this\r
+ attribute is a boolean with an "is" getter method.\r
+ By default, this is set to "false".\r
+\r
+ name Name of this JavaBeans property, conforming to\r
+ standard naming design patterns.\r
+\r
+ readable Boolean value indicating whether or not this\r
+ attribute is readable by management applications.\r
+ By default, this is set to "true".\r
+\r
+ setMethod Name of the property setter method, if it does\r
+ not follow standard JavaBeans naming patterns.\r
+\r
+ type Fully qualified Java class name of this attribute.\r
+\r
+ writeable Boolean value indicating whether or not this\r
+ attribute is writeable by management applications.\r
+ By default, this is set to "true".\r
+-->\r
+<!ELEMENT attribute (descriptor?)>\r
+<!ATTLIST attribute id ID #IMPLIED>\r
+<!ATTLIST attribute description CDATA #IMPLIED>\r
+<!ATTLIST attribute displayName CDATA #IMPLIED>\r
+<!ATTLIST attribute getMethod %MethodName; #IMPLIED>\r
+<!ATTLIST attribute is %Boolean; #IMPLIED>\r
+<!ATTLIST attribute name %VariableName; #IMPLIED>\r
+<!ATTLIST attribute readable %Boolean; #IMPLIED>\r
+<!ATTLIST attribute setMethod %MethodName; #IMPLIED>\r
+<!ATTLIST attribute type %ClassName; #IMPLIED>\r
+<!ATTLIST attribute writeable %Boolean; #IMPLIED>\r
+\r
+\r
+<!-- The "constructor" element describes a public constructor for the\r
+ underlying actual class. It may contain nested "parameter" elements\r
+ for the various arguments to this constructor. The following attributes\r
+ are supported:\r
+\r
+ displayName Display name of this constructor.\r
+\r
+ name Name of this constructor (by Java convention, this must\r
+ be the same as the base class name).\r
+-->\r
+<!ELEMENT constructor (descriptor?, parameter*)>\r
+<!ATTLIST constructor id ID #IMPLIED>\r
+<!ATTLIST constructor displayName CDATA #IMPLIED>\r
+<!ATTLIST constructor name %VariableName; #IMPLIED>\r
+\r
+\r
+<!-- The "descriptor" element groups a set of descriptor fields whose\r
+ values will be included in the Descriptor for the corresponding\r
+ metatdata info classes.\r
+-->\r
+<!ELEMENT descriptor (field*)>\r
+<!ATTLIST descriptor id ID #IMPLIED>\r
+\r
+\r
+<!-- The "field" element represents a single name/value pair that will\r
+ be included in the Descriptor corresponding to our enclosing\r
+ "descriptor" element. The following attributes are supported:\r
+\r
+ name Field name of the field to be included\r
+\r
+ value Field value of the field to be included\r
+ (will be stored as a String)\r
+-->\r
+<!ELEMENT field EMPTY>\r
+<!ATTLIST field id ID #IMPLIED>\r
+<!ATTLIST field name CDATA #REQUIRED>\r
+<!ATTLIST field value CDATA #REQUIRED>\r
+\r
+\r
+\r
+<!-- The "mbean" element describes a particular JMX ModelMBean implementation,\r
+ including the information necessary to construct the corresponding\r
+ ModelMBeanInfo structures. The following attributes are supported:\r
+\r
+ className Fully qualified Java class name of the ModelMBean\r
+ implementation class. If not specified, the standard\r
+ implementation provided by JMX will be utilized.\r
+\r
+ description Human-readable description of this managed bean.\r
+\r
+ domain The JMX MBeanServer domain in which the ModelMBean\r
+ created by this managed bean should be registered,\r
+ when creating its ObjectName.\r
+\r
+ group Optional name of a "grouping classification" that can\r
+ be used to select groups of similar MBean implementation\r
+ classes.\r
+\r
+ name Unique name of this MBean (normally corresponds to the\r
+ base class name of the corresponding server component).\r
+\r
+ type Fully qualified Java class name of the underlying\r
+ managed resource implementation class.\r
+-->\r
+<!ELEMENT mbean (descriptor?, attribute*, constructor*, notification*, operation*)>\r
+<!ATTLIST mbean id ID #IMPLIED>\r
+<!ATTLIST mbean className %ClassName; #IMPLIED>\r
+<!ATTLIST mbean description CDATA #IMPLIED>\r
+<!ATTLIST mbean domain CDATA #IMPLIED>\r
+<!ATTLIST mbean group CDATA #IMPLIED>\r
+<!ATTLIST mbean name %MethodName; #IMPLIED>\r
+<!ATTLIST mbean type %ClassName; #IMPLIED>\r
+\r
+\r
+<!-- The "notification" element describes the notification types that are\r
+ generated by a particular managed bean. The following attributes\r
+ are supported:\r
+\r
+ description Human-readable description of these notification events.\r
+\r
+ name Name of this set of notification event types.\r
+-->\r
+<!ELEMENT notification (descriptor?, notification-type*)>\r
+<!ATTLIST notification id ID #IMPLIED>\r
+<!ATTLIST notification description CDATA #IMPLIED>\r
+<!ATTLIST notification name %VariableName; #IMPLIED>\r
+\r
+\r
+<!-- The nested content of the "notification-type" element is the event string\r
+ of an event that can be emitted by this MBean.\r
+-->\r
+<!ELEMENT notification-type (#PCDATA)>\r
+<!ATTLIST notification-type id ID #IMPLIED>\r
+\r
+\r
+<!-- The "operation" element describes a the signature of a public method\r
+ that is accessible to management applications. The following attributes\r
+ are supported:\r
+\r
+ description Human-readable description of this operation.\r
+\r
+ impact Indication of the impact of this method:\r
+ ACTION (write like), ACTION-INFO (write+read like)\r
+ INFO (read like), or UNKNOWN.\r
+\r
+ name Name of this public method.\r
+\r
+ returnType Fully qualified Java class name of the return\r
+ type of this method.\r
+-->\r
+<!ELEMENT operation (descriptor?, parameter*)>\r
+<!ATTLIST operation id ID #IMPLIED>\r
+<!ATTLIST operation description CDATA #IMPLIED>\r
+<!ATTLIST operation impact CDATA #IMPLIED>\r
+<!ATTLIST operation name %VariableName; #IMPLIED>\r
+<!ATTLIST operation returnType %ClassName; #IMPLIED>\r
+\r
+\r
+<!-- The "parameter" element describes a single argument that will be passed\r
+ to a constructor or operation. The following attributes are supported:\r
+\r
+ description Human-readable description of this parameter.\r
+\r
+ name Java language name of this parameter.\r
+\r
+ type Fully qualified Java class name of this parameter.\r
+-->\r
+<!ELEMENT parameter EMPTY>\r
+<!ATTLIST parameter id ID #IMPLIED>\r
+<!ATTLIST parameter description CDATA #IMPLIED>\r
+<!ATTLIST parameter name %VariableName; #IMPLIED>\r
+<!ATTLIST parameter type %ClassName; #IMPLIED>\r
+\r
+\r
--- /dev/null
+/*\r
+ * Copyright 2001-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
+\r
+package org.apache.tomcat.util.modeler.modules;\r
+\r
+import java.io.InputStream;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.apache.tomcat.util.DomUtil;\r
+import org.apache.tomcat.util.modeler.AttributeInfo;\r
+import org.apache.tomcat.util.modeler.ConstructorInfo;\r
+import org.apache.tomcat.util.modeler.FieldInfo;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.NotificationInfo;\r
+import org.apache.tomcat.util.modeler.OperationInfo;\r
+import org.apache.tomcat.util.modeler.ParameterInfo;\r
+import org.apache.tomcat.util.modeler.Registry;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Node;\r
+\r
+\r
+public class MbeansDescriptorsDOMSource extends ModelerSource\r
+{\r
+ private static Log log = LogFactory.getLog(MbeansDescriptorsDOMSource.class);\r
+\r
+ Registry registry;\r
+ String location;\r
+ String type;\r
+ Object source;\r
+ List mbeans=new ArrayList();\r
+\r
+ public void setRegistry(Registry reg) {\r
+ this.registry=reg;\r
+ }\r
+\r
+ public void setLocation( String loc ) {\r
+ this.location=loc;\r
+ }\r
+\r
+ /** Used if a single component is loaded\r
+ *\r
+ * @param type\r
+ */\r
+ public void setType( String type ) {\r
+ this.type=type;\r
+ }\r
+\r
+ public void setSource( Object source ) {\r
+ this.source=source;\r
+ }\r
+\r
+ public List loadDescriptors( Registry registry, String location,\r
+ String type, Object source)\r
+ throws Exception\r
+ {\r
+ setRegistry(registry);\r
+ setLocation(location);\r
+ setType(type);\r
+ setSource(source);\r
+ execute();\r
+ return mbeans;\r
+ }\r
+\r
+ public void execute() throws Exception {\r
+ if( registry==null ) registry=Registry.getRegistry();\r
+\r
+ try {\r
+ InputStream stream=(InputStream)source;\r
+ long t1=System.currentTimeMillis();\r
+ Document doc=DomUtil.readXml(stream);\r
+ // Ignore for now the name of the root element\r
+ Node descriptorsN=doc.getDocumentElement();\r
+ //Node descriptorsN=DomUtil.getChild(doc, "mbeans-descriptors");\r
+ if( descriptorsN == null ) {\r
+ log.error("No descriptors found");\r
+ return;\r
+ }\r
+\r
+ Node firstMbeanN=null;\r
+ if( "mbean".equals( descriptorsN.getNodeName() ) ) {\r
+ firstMbeanN=descriptorsN;\r
+ } else {\r
+ firstMbeanN=DomUtil.getChild(descriptorsN, "mbean");\r
+ }\r
+\r
+ if( firstMbeanN==null ) {\r
+ log.error(" No mbean tags ");\r
+ return;\r
+ }\r
+\r
+ // Process each <mbean> element\r
+ for (Node mbeanN = firstMbeanN; mbeanN != null;\r
+ mbeanN= DomUtil.getNext(mbeanN))\r
+ {\r
+\r
+ // Create a new managed bean info\r
+ ManagedBean managed=new ManagedBean();\r
+ DomUtil.setAttributes(managed, mbeanN);\r
+ Node firstN;\r
+\r
+ // Process descriptor subnode\r
+ Node mbeanDescriptorN =\r
+ DomUtil.getChild(mbeanN, "descriptor");\r
+ if (mbeanDescriptorN != null) {\r
+ Node firstFieldN =\r
+ DomUtil.getChild(mbeanDescriptorN, "field");\r
+ for (Node fieldN = firstFieldN; fieldN != null;\r
+ fieldN = DomUtil.getNext(fieldN)) {\r
+ FieldInfo fi = new FieldInfo();\r
+ DomUtil.setAttributes(fi, fieldN);\r
+ managed.addField(fi);\r
+ }\r
+ }\r
+\r
+ // process attribute nodes\r
+ firstN=DomUtil.getChild( mbeanN, "attribute");\r
+ for (Node descN = firstN; descN != null;\r
+ descN = DomUtil.getNext( descN ))\r
+ {\r
+\r
+ // Create new attribute info\r
+ AttributeInfo ai=new AttributeInfo();\r
+ DomUtil.setAttributes(ai, descN);\r
+\r
+ // Process descriptor subnode\r
+ Node descriptorN =\r
+ DomUtil.getChild(descN, "descriptor");\r
+ if (descriptorN != null) {\r
+ Node firstFieldN =\r
+ DomUtil.getChild(descriptorN, "field");\r
+ for (Node fieldN = firstFieldN; fieldN != null;\r
+ fieldN = DomUtil.getNext(fieldN)) {\r
+ FieldInfo fi = new FieldInfo();\r
+ DomUtil.setAttributes(fi, fieldN);\r
+ ai.addField(fi);\r
+ }\r
+ }\r
+\r
+ // Add this info to our managed bean info\r
+ managed.addAttribute( ai );\r
+ if (log.isTraceEnabled()) {\r
+ log.trace("Create attribute " + ai);\r
+ }\r
+\r
+ }\r
+\r
+ // process constructor nodes\r
+ firstN=DomUtil.getChild( mbeanN, "constructor");\r
+ for (Node descN = firstN; descN != null;\r
+ descN = DomUtil.getNext( descN )) {\r
+\r
+ // Create new constructor info\r
+ ConstructorInfo ci=new ConstructorInfo();\r
+ DomUtil.setAttributes(ci, descN);\r
+\r
+ // Process descriptor subnode\r
+ Node firstDescriptorN =\r
+ DomUtil.getChild(descN, "descriptor");\r
+ if (firstDescriptorN != null) {\r
+ Node firstFieldN =\r
+ DomUtil.getChild(firstDescriptorN, "field");\r
+ for (Node fieldN = firstFieldN; fieldN != null;\r
+ fieldN = DomUtil.getNext(fieldN)) {\r
+ FieldInfo fi = new FieldInfo();\r
+ DomUtil.setAttributes(fi, fieldN);\r
+ ci.addField(fi);\r
+ }\r
+ }\r
+\r
+ // Process parameter subnodes\r
+ Node firstParamN=DomUtil.getChild( descN, "parameter");\r
+ for (Node paramN = firstParamN; paramN != null;\r
+ paramN = DomUtil.getNext(paramN))\r
+ {\r
+ ParameterInfo pi=new ParameterInfo();\r
+ DomUtil.setAttributes(pi, paramN);\r
+ ci.addParameter( pi );\r
+ }\r
+\r
+ // Add this info to our managed bean info\r
+ managed.addConstructor( ci );\r
+ if (log.isTraceEnabled()) {\r
+ log.trace("Create constructor " + ci);\r
+ }\r
+\r
+ }\r
+\r
+ // process notification nodes\r
+ firstN=DomUtil.getChild( mbeanN, "notification");\r
+ for (Node descN = firstN; descN != null;\r
+ descN = DomUtil.getNext( descN ))\r
+ {\r
+\r
+ // Create new notification info\r
+ NotificationInfo ni=new NotificationInfo();\r
+ DomUtil.setAttributes(ni, descN);\r
+\r
+ // Process descriptor subnode\r
+ Node firstDescriptorN =\r
+ DomUtil.getChild(descN, "descriptor");\r
+ if (firstDescriptorN != null) {\r
+ Node firstFieldN =\r
+ DomUtil.getChild(firstDescriptorN, "field");\r
+ for (Node fieldN = firstFieldN; fieldN != null;\r
+ fieldN = DomUtil.getNext(fieldN)) {\r
+ FieldInfo fi = new FieldInfo();\r
+ DomUtil.setAttributes(fi, fieldN);\r
+ ni.addField(fi);\r
+ }\r
+ }\r
+\r
+ // Process notification-type subnodes\r
+ Node firstParamN=DomUtil.getChild( descN, "notification-type");\r
+ for (Node paramN = firstParamN; paramN != null;\r
+ paramN = DomUtil.getNext(paramN))\r
+ {\r
+ ni.addNotifType( DomUtil.getContent(paramN) );\r
+ }\r
+\r
+ // Add this info to our managed bean info\r
+ managed.addNotification( ni );\r
+ if (log.isTraceEnabled()) {\r
+ log.trace("Created notification " + ni);\r
+ }\r
+\r
+ }\r
+\r
+ // process operation nodes\r
+ firstN=DomUtil.getChild( mbeanN, "operation");\r
+ for (Node descN = firstN; descN != null;\r
+ descN = DomUtil.getNext( descN ))\r
+\r
+ {\r
+\r
+ // Create new operation info\r
+ OperationInfo oi=new OperationInfo();\r
+ DomUtil.setAttributes(oi, descN);\r
+\r
+ // Process descriptor subnode\r
+ Node firstDescriptorN =\r
+ DomUtil.getChild(descN, "descriptor");\r
+ if (firstDescriptorN != null) {\r
+ Node firstFieldN =\r
+ DomUtil.getChild(firstDescriptorN, "field");\r
+ for (Node fieldN = firstFieldN; fieldN != null;\r
+ fieldN = DomUtil.getNext(fieldN)) {\r
+ FieldInfo fi = new FieldInfo();\r
+ DomUtil.setAttributes(fi, fieldN);\r
+ oi.addField(fi);\r
+ }\r
+ }\r
+\r
+ // Process parameter subnodes\r
+ Node firstParamN=DomUtil.getChild( descN, "parameter");\r
+ for (Node paramN = firstParamN; paramN != null;\r
+ paramN = DomUtil.getNext(paramN))\r
+ {\r
+ ParameterInfo pi=new ParameterInfo();\r
+ DomUtil.setAttributes(pi, paramN);\r
+ if( log.isTraceEnabled())\r
+ log.trace("Add param " + pi.getName());\r
+ oi.addParameter( pi );\r
+ }\r
+\r
+ // Add this info to our managed bean info\r
+ managed.addOperation( oi );\r
+ if( log.isTraceEnabled()) {\r
+ log.trace("Create operation " + oi);\r
+ }\r
+\r
+ }\r
+\r
+ // Add the completed managed bean info to the registry\r
+ //registry.addManagedBean(managed);\r
+ mbeans.add( managed );\r
+\r
+ }\r
+\r
+ long t2=System.currentTimeMillis();\r
+ log.debug( "Reading descriptors ( dom ) " + (t2-t1));\r
+ } catch( Exception ex ) {\r
+ log.error( "Error reading descriptors ", ex);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2001-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
+\r
+package org.apache.tomcat.util.modeler.modules;\r
+\r
+import java.io.InputStream;\r
+import java.net.URL;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.tomcat.util.digester.Digester;\r
+import org.apache.tomcat.util.modeler.Registry;\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+\r
+public class MbeansDescriptorsDigesterSource extends ModelerSource\r
+{\r
+ private static Log log =\r
+ LogFactory.getLog(MbeansDescriptorsDigesterSource.class);\r
+\r
+ Registry registry;\r
+ String location;\r
+ String type;\r
+ Object source;\r
+ List mbeans=new ArrayList();\r
+\r
+ public void setRegistry(Registry reg) {\r
+ this.registry=reg;\r
+ }\r
+\r
+ public void setLocation( String loc ) {\r
+ this.location=loc;\r
+ }\r
+\r
+ /** Used if a single component is loaded\r
+ *\r
+ * @param type\r
+ */\r
+ public void setType( String type ) {\r
+ this.type=type;\r
+ }\r
+\r
+ public void setSource( Object source ) {\r
+ this.source=source;\r
+ }\r
+\r
+ public List loadDescriptors( Registry registry, String location,\r
+ String type, Object source)\r
+ throws Exception\r
+ {\r
+ setRegistry(registry);\r
+ setLocation(location);\r
+ setType(type);\r
+ setSource(source);\r
+ execute();\r
+ return mbeans;\r
+ }\r
+\r
+ public void execute() throws Exception {\r
+ if( registry==null ) registry=Registry.getRegistry();\r
+\r
+ InputStream stream=(InputStream)source;\r
+\r
+ long t1=System.currentTimeMillis();\r
+\r
+ Digester digester = new Digester();\r
+ digester.setNamespaceAware(false);\r
+ digester.setValidating(false);\r
+ URL url = registry.getClass().getResource\r
+ ("/org/apache/commons/modeler/mbeans-descriptors.dtd");\r
+ digester.register\r
+ ("-//Apache Software Foundation//DTD Model MBeans Configuration File",\r
+ url.toString());\r
+\r
+ // Push our registry object onto the stack\r
+ digester.push(mbeans);\r
+\r
+ // Configure the parsing rules\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean",\r
+ "org.apache.tomcat.util.modeler.ManagedBean");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean",\r
+ "add",\r
+ "java.lang.Object");\r
+\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean/attribute",\r
+ "org.apache.tomcat.util.modeler.AttributeInfo");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean/attribute");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean/attribute",\r
+ "addAttribute",\r
+ "org.apache.tomcat.util.modeler.AttributeInfo");\r
+\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean/attribute/descriptor/field",\r
+ "org.apache.tomcat.util.modeler.FieldInfo");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean/attribute/descriptor/field");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean/attribute/descriptor/field",\r
+ "addField",\r
+ "org.apache.tomcat.util.modeler.FieldInfo");\r
+\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean/constructor",\r
+ "org.apache.tomcat.util.modeler.ConstructorInfo");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean/constructor");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean/constructor",\r
+ "addConstructor",\r
+ "org.apache.tomcat.util.modeler.ConstructorInfo");\r
+\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean/constructor/descriptor/field",\r
+ "org.apache.tomcat.util.modeler.FieldInfo");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean/constructor/descriptor/field");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean/constructor/descriptor/field",\r
+ "addField",\r
+ "org.apache.tomcat.util.modeler.FieldInfo");\r
+\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean/constructor/parameter",\r
+ "org.apache.tomcat.util.modeler.ParameterInfo");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean/constructor/parameter");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean/constructor/parameter",\r
+ "addParameter",\r
+ "org.apache.tomcat.util.modeler.ParameterInfo");\r
+\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean/descriptor/field",\r
+ "org.apache.tomcat.util.modeler.FieldInfo");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean/descriptor/field");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean/descriptor/field",\r
+ "addField",\r
+ "org.apache.tomcat.util.modeler.FieldInfo");\r
+\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean/notification",\r
+ "org.apache.tomcat.util.modeler.NotificationInfo");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean/notification");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean/notification",\r
+ "addNotification",\r
+ "org.apache.tomcat.util.modeler.NotificationInfo");\r
+\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean/notification/descriptor/field",\r
+ "org.apache.tomcat.util.modeler.FieldInfo");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean/notification/descriptor/field");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean/notification/descriptor/field",\r
+ "addField",\r
+ "org.apache.tomcat.util.modeler.FieldInfo");\r
+\r
+ digester.addCallMethod\r
+ ("mbeans-descriptors/mbean/notification/notification-type",\r
+ "addNotifType", 0);\r
+\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean/operation",\r
+ "org.apache.tomcat.util.modeler.OperationInfo");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean/operation");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean/operation",\r
+ "addOperation",\r
+ "org.apache.tomcat.util.modeler.OperationInfo");\r
+\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean/operation/descriptor/field",\r
+ "org.apache.tomcat.util.modeler.FieldInfo");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean/operation/descriptor/field");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean/operation/descriptor/field",\r
+ "addField",\r
+ "org.apache.tomcat.util.modeler.FieldInfo");\r
+\r
+ digester.addObjectCreate\r
+ ("mbeans-descriptors/mbean/operation/parameter",\r
+ "org.apache.tomcat.util.modeler.ParameterInfo");\r
+ digester.addSetProperties\r
+ ("mbeans-descriptors/mbean/operation/parameter");\r
+ digester.addSetNext\r
+ ("mbeans-descriptors/mbean/operation/parameter",\r
+ "addParameter",\r
+ "org.apache.tomcat.util.modeler.ParameterInfo");\r
+\r
+ // Process the input file to configure our registry\r
+ try {\r
+ digester.parse(stream);\r
+ } catch (Exception e) {\r
+ log.error("Error digesting Registry data", e);\r
+ throw e;\r
+ }\r
+ long t2=System.currentTimeMillis();\r
+// if( t2-t1 > 500 )\r
+ log.info("Loaded registry information (digester) " + ( t2 - t1 ) + " ms");\r
+ }\r
+}\r
--- /dev/null
+package org.apache.tomcat.util.modeler.modules;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.management.DynamicMBean;\r
+import javax.management.MBeanAttributeInfo;\r
+import javax.management.MBeanInfo;\r
+import javax.management.MBeanOperationInfo;\r
+import javax.management.MBeanParameterInfo;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.apache.tomcat.util.modeler.AttributeInfo;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.OperationInfo;\r
+import org.apache.tomcat.util.modeler.ParameterInfo;\r
+import org.apache.tomcat.util.modeler.Registry;\r
+\r
+\r
+/** Extract metadata from a dynamic mbean.\r
+ * Used to wrap a dynamic mbean in order to implement persistence.\r
+ * \r
+ * This is really an ugly asspect of the JMX spec - we need to convery \r
+ * from normal metainfo to model metainfo. The info is the same, but\r
+ * they use a different class. Just like the DOM spec - where all implementations\r
+ * get an order of unneeded complexity from the various types. \r
+ * \r
+ */ \r
+public class MbeansDescriptorsDynamicMBeanSource extends ModelerSource\r
+{\r
+ private static Log log = LogFactory.getLog(MbeansDescriptorsDynamicMBeanSource.class);\r
+\r
+ Registry registry;\r
+ String location;\r
+ String type;\r
+ Object source;\r
+ List mbeans=new ArrayList();\r
+\r
+ public void setRegistry(Registry reg) {\r
+ this.registry=reg;\r
+ }\r
+\r
+ public void setLocation( String loc ) {\r
+ this.location=loc;\r
+ }\r
+\r
+ /** Used if a single component is loaded\r
+ *\r
+ * @param type\r
+ */\r
+ public void setType( String type ) {\r
+ this.type=type;\r
+ }\r
+\r
+ public void setSource( Object source ) {\r
+ this.source=source;\r
+ }\r
+\r
+ public List loadDescriptors( Registry registry, String location,\r
+ String type, Object source)\r
+ throws Exception\r
+ {\r
+ setRegistry(registry);\r
+ setLocation(location);\r
+ setType(type);\r
+ setSource(source);\r
+ execute();\r
+ return mbeans;\r
+ }\r
+\r
+ public void execute() throws Exception {\r
+ if( registry==null ) registry=Registry.getRegistry();\r
+ try {\r
+ ManagedBean managed=createManagedBean(registry, null, source, type);\r
+ if( managed==null ) return;\r
+ managed.setName( type );\r
+ \r
+ mbeans.add(managed);\r
+\r
+ } catch( Exception ex ) {\r
+ log.error( "Error reading descriptors ", ex);\r
+ }\r
+ }\r
+\r
+\r
+\r
+ // ------------ Implementation for non-declared introspection classes\r
+\r
+\r
+ /**\r
+ * XXX Find if the 'className' is the name of the MBean or\r
+ * the real class ( I suppose first )\r
+ * XXX Read (optional) descriptions from a .properties, generated\r
+ * from source\r
+ * XXX Deal with constructors\r
+ *\r
+ */\r
+ public ManagedBean createManagedBean(Registry registry, String domain,\r
+ Object realObj, String type)\r
+ {\r
+ if( ! ( realObj instanceof DynamicMBean )) {\r
+ return null;\r
+ }\r
+ DynamicMBean dmb=(DynamicMBean)realObj;\r
+ \r
+ ManagedBean mbean= new ManagedBean();\r
+ \r
+ MBeanInfo mbi=dmb.getMBeanInfo();\r
+ \r
+ try {\r
+ MBeanAttributeInfo attInfo[]=mbi.getAttributes();\r
+ for( int i=0; i<attInfo.length; i++ ) {\r
+ MBeanAttributeInfo mai=attInfo[i];\r
+ String name=mai.getName();\r
+\r
+ AttributeInfo ai=new AttributeInfo();\r
+ ai.setName( name );\r
+\r
+ ai.setType( mai.getType());\r
+ ai.setReadable( mai.isReadable());\r
+ ai.setWriteable( mai.isWritable());\r
+ \r
+ mbean.addAttribute(ai);\r
+ }\r
+\r
+ MBeanOperationInfo opInfo[]=mbi.getOperations();\r
+ for( int i=0; i<opInfo.length; i++ ) {\r
+ MBeanOperationInfo moi=opInfo[i];\r
+ OperationInfo op=new OperationInfo();\r
+\r
+ op.setName(moi.getName());\r
+ op.setReturnType(moi.getReturnType());\r
+ \r
+ MBeanParameterInfo parms[]=moi.getSignature();\r
+ for(int j=0; j<parms.length; j++ ) {\r
+ ParameterInfo pi=new ParameterInfo();\r
+ pi.setType(parms[i].getType());\r
+ pi.setName(parms[i].getName());\r
+ op.addParameter(pi);\r
+ }\r
+ mbean.addOperation(op);\r
+ }\r
+\r
+ if( log.isDebugEnabled())\r
+ log.debug("Setting name: " + type );\r
+\r
+ mbean.setName( type );\r
+\r
+ return mbean;\r
+ } catch( Exception ex ) {\r
+ ex.printStackTrace();\r
+ return null;\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2001-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.tomcat.util.modeler.modules;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.apache.tomcat.util.modeler.AttributeInfo;\r
+import org.apache.tomcat.util.modeler.ConstructorInfo;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.OperationInfo;\r
+import org.apache.tomcat.util.modeler.ParameterInfo;\r
+import org.apache.tomcat.util.modeler.Registry;\r
+\r
+import javax.management.ObjectName;\r
+\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.Modifier;\r
+import java.lang.reflect.Constructor;\r
+import java.math.BigDecimal;\r
+import java.math.BigInteger;\r
+import java.util.ArrayList;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.List;\r
+\r
+public class MbeansDescriptorsIntrospectionSource extends ModelerSource\r
+{\r
+ private static Log log = LogFactory.getLog(MbeansDescriptorsIntrospectionSource.class);\r
+\r
+ Registry registry;\r
+ String location;\r
+ String type;\r
+ Object source;\r
+ List mbeans=new ArrayList();\r
+\r
+ public void setRegistry(Registry reg) {\r
+ this.registry=reg;\r
+ }\r
+\r
+ public void setLocation( String loc ) {\r
+ this.location=loc;\r
+ }\r
+\r
+ /** Used if a single component is loaded\r
+ *\r
+ * @param type\r
+ */\r
+ public void setType( String type ) {\r
+ this.type=type;\r
+ }\r
+\r
+ public void setSource( Object source ) {\r
+ this.source=source;\r
+ }\r
+\r
+ public List loadDescriptors( Registry registry, String location,\r
+ String type, Object source)\r
+ throws Exception\r
+ {\r
+ setRegistry(registry);\r
+ setLocation(location);\r
+ setType(type);\r
+ setSource(source);\r
+ execute();\r
+ return mbeans;\r
+ }\r
+\r
+ public void execute() throws Exception {\r
+ if( registry==null ) registry=Registry.getRegistry();\r
+ try {\r
+ ManagedBean managed=createManagedBean(registry, null, (Class)source, type);\r
+ if( managed==null ) return;\r
+ managed.setName( type );\r
+\r
+ mbeans.add(managed);\r
+\r
+ } catch( Exception ex ) {\r
+ log.error( "Error reading descriptors ", ex);\r
+ }\r
+ }\r
+\r
+\r
+\r
+ // ------------ Implementation for non-declared introspection classes\r
+\r
+ static Hashtable specialMethods=new Hashtable();\r
+ static {\r
+ specialMethods.put( "preDeregister", "");\r
+ specialMethods.put( "postDeregister", "");\r
+ }\r
+\r
+ private static String strArray[]=new String[0];\r
+ private static ObjectName objNameArray[]=new ObjectName[0];\r
+ // createMBean == registerClass + registerMBean\r
+\r
+ private static Class[] supportedTypes = new Class[] {\r
+ Boolean.class,\r
+ Boolean.TYPE,\r
+ Byte.class,\r
+ Byte.TYPE,\r
+ Character.class,\r
+ Character.TYPE,\r
+ Short.class,\r
+ Short.TYPE,\r
+ Integer.class,\r
+ Integer.TYPE,\r
+ Long.class,\r
+ Long.TYPE,\r
+ Float.class, \r
+ Float.TYPE,\r
+ Double.class,\r
+ Double.TYPE,\r
+ String.class,\r
+ strArray.getClass(),\r
+ BigDecimal.class,\r
+ BigInteger.class,\r
+ ObjectName.class,\r
+ objNameArray.getClass(),\r
+ java.io.File.class,\r
+ };\r
+ \r
+ /**\r
+ * Check if this class is one of the supported types.\r
+ * If the class is supported, returns true. Otherwise,\r
+ * returns false.\r
+ * @param ret The class to check\r
+ * @return boolean True if class is supported\r
+ */ \r
+ private boolean supportedType(Class ret) {\r
+ for (int i = 0; i < supportedTypes.length; i++) {\r
+ if (ret == supportedTypes[i]) {\r
+ return true;\r
+ }\r
+ }\r
+ if (isBeanCompatible(ret)) {\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Check if this class conforms to JavaBeans specifications.\r
+ * If the class is conformant, returns true.\r
+ *\r
+ * @param javaType The class to check\r
+ * @return boolean True if the class is compatible.\r
+ */\r
+ protected boolean isBeanCompatible(Class javaType) {\r
+ // Must be a non-primitive and non array\r
+ if (javaType.isArray() || javaType.isPrimitive()) {\r
+ return false;\r
+ }\r
+\r
+ // Anything in the java or javax package that\r
+ // does not have a defined mapping is excluded.\r
+ if (javaType.getName().startsWith("java.") || \r
+ javaType.getName().startsWith("javax.")) {\r
+ return false;\r
+ }\r
+\r
+ try {\r
+ javaType.getConstructor(new Class[]{});\r
+ } catch (java.lang.NoSuchMethodException e) {\r
+ return false;\r
+ }\r
+\r
+ // Make sure superclass is compatible\r
+ Class superClass = javaType.getSuperclass();\r
+ if (superClass != null && \r
+ superClass != java.lang.Object.class && \r
+ superClass != java.lang.Exception.class && \r
+ superClass != java.lang.Throwable.class) {\r
+ if (!isBeanCompatible(superClass)) {\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+ \r
+ /** \r
+ * Process the methods and extract 'attributes', methods, etc\r
+ *\r
+ * @param realClass The class to process\r
+ * @param methods The methods to process\r
+ * @param attMap The attribute map (complete)\r
+ * @param getAttMap The readable attributess map\r
+ * @param setAttMap The settable attributes map\r
+ * @param invokeAttMap The invokable attributes map\r
+ */\r
+ private void initMethods(Class realClass,\r
+ Method methods[],\r
+ Hashtable attMap, Hashtable getAttMap,\r
+ Hashtable setAttMap, Hashtable invokeAttMap)\r
+ {\r
+ for (int j = 0; j < methods.length; ++j) {\r
+ String name=methods[j].getName();\r
+\r
+ if( Modifier.isStatic(methods[j].getModifiers()))\r
+ continue;\r
+ if( ! Modifier.isPublic( methods[j].getModifiers() ) ) {\r
+ if( log.isDebugEnabled())\r
+ log.debug("Not public " + methods[j] );\r
+ continue;\r
+ }\r
+ if( methods[j].getDeclaringClass() == Object.class )\r
+ continue;\r
+ Class params[]=methods[j].getParameterTypes();\r
+\r
+ if( name.startsWith( "get" ) && params.length==0) {\r
+ Class ret=methods[j].getReturnType();\r
+ if( ! supportedType( ret ) ) {\r
+ if( log.isDebugEnabled() )\r
+ log.debug("Unsupported type " + methods[j]);\r
+ continue;\r
+ }\r
+ name=unCapitalize( name.substring(3));\r
+\r
+ getAttMap.put( name, methods[j] );\r
+ // just a marker, we don't use the value\r
+ attMap.put( name, methods[j] );\r
+ } else if( name.startsWith( "is" ) && params.length==0) {\r
+ Class ret=methods[j].getReturnType();\r
+ if( Boolean.TYPE != ret ) {\r
+ if( log.isDebugEnabled() )\r
+ log.debug("Unsupported type " + methods[j] + " " + ret );\r
+ continue;\r
+ }\r
+ name=unCapitalize( name.substring(2));\r
+\r
+ getAttMap.put( name, methods[j] );\r
+ // just a marker, we don't use the value\r
+ attMap.put( name, methods[j] );\r
+\r
+ } else if( name.startsWith( "set" ) && params.length==1) {\r
+ if( ! supportedType( params[0] ) ) {\r
+ if( log.isDebugEnabled() )\r
+ log.debug("Unsupported type " + methods[j] + " " + params[0]);\r
+ continue;\r
+ }\r
+ name=unCapitalize( name.substring(3));\r
+ setAttMap.put( name, methods[j] );\r
+ attMap.put( name, methods[j] );\r
+ } else {\r
+ if( params.length == 0 ) {\r
+ if( specialMethods.get( methods[j].getName() ) != null )\r
+ continue;\r
+ invokeAttMap.put( name, methods[j]);\r
+ } else {\r
+ boolean supported=true;\r
+ for( int i=0; i<params.length; i++ ) {\r
+ if( ! supportedType( params[i])) {\r
+ supported=false;\r
+ break;\r
+ }\r
+ }\r
+ if( supported )\r
+ invokeAttMap.put( name, methods[j]);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * XXX Find if the 'className' is the name of the MBean or\r
+ * the real class ( I suppose first )\r
+ * XXX Read (optional) descriptions from a .properties, generated\r
+ * from source\r
+ * XXX Deal with constructors\r
+ *\r
+ * @param registry The Bean registry (not used)\r
+ * @param domain The bean domain (not used)\r
+ * @param realClass The class to analyze\r
+ * @param type The bean type\r
+ * @return ManagedBean The create MBean\r
+ */\r
+ public ManagedBean createManagedBean(Registry registry, String domain,\r
+ Class realClass, String type)\r
+ {\r
+ ManagedBean mbean= new ManagedBean();\r
+\r
+ Method methods[]=null;\r
+\r
+ Hashtable attMap=new Hashtable();\r
+ // key: attribute val: getter method\r
+ Hashtable getAttMap=new Hashtable();\r
+ // key: attribute val: setter method\r
+ Hashtable setAttMap=new Hashtable();\r
+ // key: operation val: invoke method\r
+ Hashtable invokeAttMap=new Hashtable();\r
+\r
+ methods = realClass.getMethods();\r
+\r
+ initMethods(realClass, methods, attMap, getAttMap, setAttMap, invokeAttMap );\r
+\r
+ try {\r
+\r
+ Enumeration en=attMap.keys();\r
+ while( en.hasMoreElements() ) {\r
+ String name=(String)en.nextElement();\r
+ AttributeInfo ai=new AttributeInfo();\r
+ ai.setName( name );\r
+ Method gm=(Method)getAttMap.get(name);\r
+ if( gm!=null ) {\r
+ //ai.setGetMethodObj( gm );\r
+ ai.setGetMethod( gm.getName());\r
+ Class t=gm.getReturnType();\r
+ if( t!=null )\r
+ ai.setType( t.getName() );\r
+ }\r
+ Method sm=(Method)setAttMap.get(name);\r
+ if( sm!=null ) {\r
+ //ai.setSetMethodObj(sm);\r
+ Class t=sm.getParameterTypes()[0];\r
+ if( t!=null )\r
+ ai.setType( t.getName());\r
+ ai.setSetMethod( sm.getName());\r
+ }\r
+ ai.setDescription("Introspected attribute " + name);\r
+ if( log.isDebugEnabled()) log.debug("Introspected attribute " +\r
+ name + " " + gm + " " + sm);\r
+ if( gm==null )\r
+ ai.setReadable(false);\r
+ if( sm==null )\r
+ ai.setWriteable(false);\r
+ if( sm!=null || gm!=null )\r
+ mbean.addAttribute(ai);\r
+ }\r
+\r
+ en=invokeAttMap.keys();\r
+ while( en.hasMoreElements() ) {\r
+ String name=(String)en.nextElement();\r
+ Method m=(Method)invokeAttMap.get(name);\r
+ if( m!=null && name != null ) {\r
+ OperationInfo op=new OperationInfo();\r
+ op.setName(name);\r
+ op.setReturnType(m.getReturnType().getName());\r
+ op.setDescription("Introspected operation " + name);\r
+ Class parms[]=m.getParameterTypes();\r
+ for(int i=0; i<parms.length; i++ ) {\r
+ ParameterInfo pi=new ParameterInfo();\r
+ pi.setType(parms[i].getName());\r
+ pi.setName( "param" + i);\r
+ pi.setDescription("Introspected parameter param" + i);\r
+ op.addParameter(pi);\r
+ }\r
+ mbean.addOperation(op);\r
+ } else {\r
+ log.error("Null arg " + name + " " + m );\r
+ }\r
+ }\r
+\r
+ Constructor[] constructors = realClass.getConstructors();\r
+ for(int i=0;i<constructors.length;i++) {\r
+ ConstructorInfo info = new ConstructorInfo();\r
+ String className = realClass.getName();\r
+ int nIndex = -1;\r
+ if((nIndex = className.lastIndexOf('.'))!=-1) {\r
+ className = className.substring(nIndex+1);\r
+ }\r
+ info.setName(className);\r
+ info.setDescription(constructors[i].getName());\r
+ Class classes[] = constructors[i].getParameterTypes();\r
+ for(int j=0;j<classes.length;j++) {\r
+ ParameterInfo pi = new ParameterInfo();\r
+ pi.setType(classes[j].getName());\r
+ pi.setName("param" + j);\r
+ pi.setDescription("Introspected parameter param" + j);\r
+ info.addParameter(pi);\r
+ }\r
+ mbean.addConstructor(info);\r
+ }\r
+ \r
+ if( log.isDebugEnabled())\r
+ log.debug("Setting name: " + type );\r
+ mbean.setName( type );\r
+\r
+ return mbean;\r
+ } catch( Exception ex ) {\r
+ ex.printStackTrace();\r
+ return null;\r
+ }\r
+ }\r
+\r
+\r
+ // -------------------- Utils --------------------\r
+ /**\r
+ * Converts the first character of the given\r
+ * String into lower-case.\r
+ *\r
+ * @param name The string to convert\r
+ * @return String\r
+ */\r
+ private static String unCapitalize(String name) {\r
+ if (name == null || name.length() == 0) {\r
+ return name;\r
+ }\r
+ char chars[] = name.toCharArray();\r
+ chars[0] = Character.toLowerCase(chars[0]);\r
+ return new String(chars);\r
+ }\r
+\r
+}\r
+\r
+// End of class: MbeanDescriptorsIntrospectionSource\r
--- /dev/null
+package org.apache.tomcat.util.modeler.modules;\r
+\r
+import java.io.InputStream;\r
+import java.io.ObjectInputStream;\r
+import java.net.URL;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.apache.tomcat.util.modeler.ManagedBean;\r
+import org.apache.tomcat.util.modeler.Registry;\r
+\r
+\r
+public class MbeansDescriptorsSerSource extends ModelerSource\r
+{\r
+ private static Log log = LogFactory.getLog(MbeansDescriptorsSerSource.class);\r
+ Registry registry;\r
+ String location;\r
+ String type;\r
+ Object source;\r
+ List mbeans=new ArrayList();\r
+\r
+ public void setRegistry(Registry reg) {\r
+ this.registry=reg;\r
+ }\r
+\r
+ public void setLocation( String loc ) {\r
+ this.location=loc;\r
+ }\r
+\r
+ /** Used if a single component is loaded\r
+ *\r
+ * @param type\r
+ */\r
+ public void setType( String type ) {\r
+ this.type=type;\r
+ }\r
+\r
+ public void setSource( Object source ) {\r
+ this.source=source;\r
+ }\r
+\r
+ public List loadDescriptors( Registry registry, String location,\r
+ String type, Object source)\r
+ throws Exception\r
+ {\r
+ setRegistry(registry);\r
+ setLocation(location);\r
+ setType(type);\r
+ setSource(source);\r
+ execute();\r
+ return mbeans;\r
+ }\r
+\r
+ public void execute() throws Exception {\r
+ if( registry==null ) registry=Registry.getRegistry();\r
+ long t1=System.currentTimeMillis();\r
+ try {\r
+ InputStream stream=null;\r
+ if( source instanceof URL ) {\r
+ stream=((URL)source).openStream();\r
+ }\r
+ if( source instanceof InputStream ) {\r
+ stream=(InputStream)source;\r
+ }\r
+ if( stream==null ) {\r
+ throw new Exception( "Can't process "+ source);\r
+ }\r
+ ObjectInputStream ois=new ObjectInputStream(stream);\r
+ Thread.currentThread().setContextClassLoader(ManagedBean.class.getClassLoader());\r
+ Object obj=ois.readObject();\r
+ //log.info("Reading " + obj);\r
+ ManagedBean beans[]=(ManagedBean[])obj;\r
+ // after all are read without error\r
+ for( int i=0; i<beans.length; i++ ) {\r
+ mbeans.add(beans[i]);\r
+ }\r
+\r
+ } catch( Exception ex ) {\r
+ log.error( "Error reading descriptors " + source + " " + ex.toString(),\r
+ ex);\r
+ throw ex;\r
+ }\r
+ long t2=System.currentTimeMillis();\r
+ log.info( "Reading descriptors ( ser ) " + (t2-t1));\r
+ }\r
+}\r
--- /dev/null
+package org.apache.tomcat.util.modeler.modules;\r
+\r
+import java.io.FileNotFoundException;\r
+import java.io.FileOutputStream;\r
+import java.io.InputStream;\r
+import java.net.URL;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+\r
+import javax.management.Attribute;\r
+import javax.management.MBeanServer;\r
+import javax.management.ObjectName;\r
+import javax.management.loading.MLet;\r
+import javax.xml.transform.TransformerException;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.apache.tomcat.util.DomUtil;\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.Registry;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Node;\r
+\r
+\r
+/** This will create mbeans based on a config file.\r
+ * The format is an extended version of MLET.\r
+ *\r
+ * Classloading. We don't support any explicit classloader tag. \r
+ * A ClassLoader is just an mbean ( it can be the standard MLetMBean or\r
+ * a custom one ). \r
+ * \r
+ * XXX add a special attribute to reference the loader mbean,\r
+ * XXX figure out how to deal with private loaders\r
+ */\r
+public class MbeansSource extends ModelerSource implements MbeansSourceMBean\r
+{\r
+ private static Log log = LogFactory.getLog(MbeansSource.class);\r
+ Registry registry;\r
+ String type;\r
+\r
+ // true if we are during the original loading\r
+ boolean loading=true;\r
+ List mbeans=new ArrayList();\r
+ static boolean loaderLoaded=false;\r
+ private Document document;\r
+ private HashMap object2Node = new HashMap();\r
+\r
+ long lastUpdate;\r
+ long updateInterval=10000; // 10s\r
+\r
+ public void setRegistry(Registry reg) {\r
+ this.registry=reg;\r
+ } \r
+\r
+ public void setLocation( String loc ) {\r
+ this.location=loc;\r
+ }\r
+\r
+ /** Used if a single component is loaded\r
+ *\r
+ * @param type\r
+ */\r
+ public void setType( String type ) {\r
+ this.type=type;\r
+ }\r
+\r
+ public void setSource( Object source ) {\r
+ this.source=source;\r
+ }\r
+\r
+ public Object getSource() {\r
+ return source;\r
+ }\r
+\r
+ public String getLocation() {\r
+ return location;\r
+ }\r
+ \r
+ /** Return the list of mbeans created by this source.\r
+ * It can be used to implement runtime services.\r
+ */\r
+ public List getMBeans() {\r
+ return mbeans;\r
+ }\r
+\r
+ public List loadDescriptors( Registry registry, String location,\r
+ String type, Object source)\r
+ throws Exception\r
+ {\r
+ setRegistry(registry);\r
+ setLocation(location);\r
+ setType(type);\r
+ setSource(source);\r
+ execute();\r
+ return mbeans;\r
+ }\r
+ \r
+ public void start() throws Exception {\r
+ registry.invoke(mbeans, "start", false); \r
+ }\r
+\r
+ public void stop() throws Exception {\r
+ registry.invoke(mbeans, "stop", false); \r
+ }\r
+ \r
+ public void init() throws Exception {\r
+ if( mbeans==null) execute();\r
+ if( registry==null ) registry=Registry.getRegistry();\r
+ \r
+ registry.invoke(mbeans, "init", false);\r
+ }\r
+ \r
+ public void destroy() throws Exception {\r
+ registry.invoke(mbeans, "destroy", false); \r
+ }\r
+ \r
+ public void load() throws Exception {\r
+ execute(); // backward compat\r
+ }\r
+\r
+ public void execute() throws Exception {\r
+ if( registry==null ) registry=Registry.getRegistry();\r
+ try {\r
+ InputStream stream=getInputStream();\r
+ long t1=System.currentTimeMillis();\r
+ document = DomUtil.readXml(stream);\r
+\r
+ // We don't care what the root node is.\r
+ Node descriptorsN=document.getDocumentElement();\r
+\r
+ if( descriptorsN == null ) {\r
+ log.error("No descriptors found");\r
+ return;\r
+ }\r
+\r
+ Node firstMbeanN=DomUtil.getChild(descriptorsN, null);\r
+\r
+ if( firstMbeanN==null ) {\r
+ // maybe we have a single mlet\r
+ if( log.isDebugEnabled() )\r
+ log.debug("No child " + descriptorsN);\r
+ firstMbeanN=descriptorsN;\r
+ }\r
+\r
+ MBeanServer server=(MBeanServer)Registry.getServer();\r
+\r
+ // XXX Not very clean... Just a workaround\r
+ if( ! loaderLoaded ) {\r
+ // Register a loader that will be find ant classes.\r
+ ObjectName defaultLoader= new ObjectName("modeler",\r
+ "loader", "modeler");\r
+ MLet mlet=new MLet( new URL[0], this.getClass().getClassLoader());\r
+ server.registerMBean(mlet, defaultLoader);\r
+ loaderLoaded=true;\r
+ }\r
+ \r
+ // Process nodes\r
+ for (Node mbeanN = firstMbeanN; mbeanN != null;\r
+ mbeanN= DomUtil.getNext(mbeanN, null, Node.ELEMENT_NODE))\r
+ {\r
+ String nodeName=mbeanN.getNodeName();\r
+\r
+ // mbean is the "official" name\r
+ if( "mbean".equals(nodeName) || "MLET".equals(nodeName) )\r
+ {\r
+ String code=DomUtil.getAttribute( mbeanN, "code" );\r
+ String objectName=DomUtil.getAttribute( mbeanN, "objectName" );\r
+ if( objectName==null ) {\r
+ objectName=DomUtil.getAttribute( mbeanN, "name" );\r
+ }\r
+ \r
+ if( log.isDebugEnabled())\r
+ log.debug( "Processing mbean objectName=" + objectName +\r
+ " code=" + code);\r
+\r
+ // args can be grouped in constructor or direct childs\r
+ Node constructorN=DomUtil.getChild(mbeanN, "constructor");\r
+ if( constructorN == null ) constructorN=mbeanN;\r
+\r
+ processArg(constructorN);\r
+\r
+ try {\r
+ ObjectName oname=new ObjectName(objectName);\r
+ if( ! server.isRegistered( oname )) {\r
+ // We wrap everything in a model mbean.\r
+ // XXX need to support "StandardMBeanDescriptorsSource"\r
+ String modelMBean=BaseModelMBean.class.getName(); \r
+ server.createMBean(modelMBean, oname,\r
+ new Object[] { code, this},\r
+ new String[] { String.class.getName(),\r
+ ModelerSource.class.getName() } \r
+ );\r
+ mbeans.add(oname);\r
+ }\r
+ object2Node.put( oname, mbeanN );\r
+ // XXX Arguments, loader !!!\r
+ } catch( Exception ex ) {\r
+ log.error( "Error creating mbean " + objectName, ex);\r
+ }\r
+\r
+ Node firstAttN=DomUtil.getChild(mbeanN, "attribute");\r
+ for (Node descN = firstAttN; descN != null;\r
+ descN = DomUtil.getNext( descN ))\r
+ {\r
+ processAttribute(server, descN, objectName);\r
+ }\r
+ } else if("jmx-operation".equals(nodeName) ) {\r
+ String name=DomUtil.getAttribute(mbeanN, "objectName");\r
+ if( name==null )\r
+ name=DomUtil.getAttribute(mbeanN, "name");\r
+\r
+ String operation=DomUtil.getAttribute(mbeanN, "operation");\r
+\r
+ if( log.isDebugEnabled())\r
+ log.debug( "Processing invoke objectName=" + name +\r
+ " code=" + operation);\r
+ try {\r
+ ObjectName oname=new ObjectName(name);\r
+\r
+ processArg( mbeanN );\r
+ server.invoke( oname, operation, null, null);\r
+ } catch (Exception e) {\r
+ log.error( "Error in invoke " + name + " " + operation);\r
+ }\r
+ }\r
+\r
+ ManagedBean managed=new ManagedBean();\r
+ DomUtil.setAttributes(managed, mbeanN);\r
+ Node firstN;\r
+\r
+ // process attribute info\r
+ firstN=DomUtil.getChild( mbeanN, "attribute");\r
+ for (Node descN = firstN; descN != null;\r
+ descN = DomUtil.getNext( descN ))\r
+ {\r
+ AttributeInfo ci=new AttributeInfo();\r
+ DomUtil.setAttributes(ci, descN);\r
+ managed.addAttribute( ci );\r
+ }\r
+\r
+ }\r
+\r
+ long t2=System.currentTimeMillis();\r
+ log.info( "Reading mbeans " + (t2-t1));\r
+ loading=false;\r
+ } catch( Exception ex ) {\r
+ log.error( "Error reading mbeans ", ex);\r
+ }\r
+ }\r
+ \r
+ public void updateField( ObjectName oname, String name, \r
+ Object value )\r
+ {\r
+ if( loading ) return;\r
+ // nothing by default\r
+ //log.info( "XXX UpdateField " + oname + " " + name + " " + value);\r
+ Node n=(Node)object2Node.get( oname );\r
+ if( n == null ) {\r
+ log.info( "Node not found " + oname );\r
+ return;\r
+ }\r
+ Node attNode=DomUtil.findChildWithAtt(n, "attribute", "name", name);\r
+ if( attNode == null ) {\r
+ // found no existing attribute with this name\r
+ attNode=n.getOwnerDocument().createElement("attribute");\r
+ DomUtil.setAttribute(attNode, "name", name);\r
+ n.appendChild(attNode);\r
+ } \r
+ String oldValue=DomUtil.getAttribute(attNode, "value");\r
+ if( oldValue != null ) {\r
+ // we'll convert all values to text content\r
+ DomUtil.removeAttribute( attNode, "value");\r
+ }\r
+ DomUtil.setText(attNode, value.toString());\r
+\r
+ //store();\r
+ }\r
+ \r
+ /** Store the mbeans. \r
+ * XXX add a background thread to store it periodically \r
+ */ \r
+ public void save() {\r
+ // XXX customize no often than ( based on standard descriptor ), etc.\r
+ // It doesn't work very well if we call this on each set att - \r
+ // the triger will work for the first att, but all others will be delayed\r
+ long time=System.currentTimeMillis();\r
+ if( location!=null &&\r
+ time - lastUpdate > updateInterval ) {\r
+ lastUpdate=time;\r
+ try {\r
+ FileOutputStream fos=new FileOutputStream(location);\r
+ DomUtil.writeXml(document, fos);\r
+ } catch (TransformerException e) {\r
+ log.error( "Error writing");\r
+ } catch (FileNotFoundException e) {\r
+ log.error( "Error writing" ,e );\r
+ }\r
+ }\r
+ }\r
+\r
+ private void processAttribute(MBeanServer server,\r
+ Node descN, String objectName ) {\r
+ String attName=DomUtil.getAttribute(descN, "name");\r
+ String value=DomUtil.getAttribute(descN, "value");\r
+ String type=null; // DomUtil.getAttribute(descN, "type");\r
+ if( value==null ) {\r
+ // The value may be specified as CDATA\r
+ value=DomUtil.getContent(descN);\r
+ }\r
+ try {\r
+ if( log.isDebugEnabled())\r
+ log.debug("Set attribute " + objectName + " " + attName +\r
+ " " + value);\r
+ ObjectName oname=new ObjectName(objectName);\r
+ // find the type\r
+ if( type==null )\r
+ type=registry.getType( oname, attName );\r
+\r
+ if( type==null ) {\r
+ log.info("Can't find attribute " + objectName + " " + attName );\r
+\r
+ } else {\r
+ Object valueO=registry.convertValue( type, value);\r
+ server.setAttribute(oname, new Attribute(attName, valueO));\r
+ }\r
+ } catch( Exception ex) {\r
+ log.error("Error processing attribute " + objectName + " " +\r
+ attName + " " + value, ex);\r
+ }\r
+\r
+ }\r
+\r
+ private void processArg(Node mbeanN) {\r
+ Node firstArgN=DomUtil.getChild(mbeanN, "arg" );\r
+ // process all args\r
+ for (Node argN = firstArgN; argN != null;\r
+ argN = DomUtil.getNext( argN ))\r
+ {\r
+ String type=DomUtil.getAttribute(argN, "type");\r
+ String value=DomUtil.getAttribute(argN, "value");\r
+ if( value==null ) {\r
+ // The value may be specified as CDATA\r
+ value=DomUtil.getContent(argN);\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.apache.tomcat.util.modeler.modules;\r
+\r
+import java.util.List;\r
+\r
+\r
+/**\r
+ * This mbean will load an extended mlet file ( similar in syntax with jboss ).\r
+ * It'll keep track of all attribute changes and update the file when attributes\r
+ * change. \r
+ */\r
+public interface MbeansSourceMBean \r
+{\r
+ /** Set the source to be used to load the mbeans\r
+ * \r
+ * @param source File or URL\r
+ */ \r
+ public void setSource( Object source );\r
+ \r
+ public Object getSource();\r
+ \r
+ /** Return the list of loaded mbeans names\r
+ * \r
+ * @return List of ObjectName\r
+ */ \r
+ public List getMBeans();\r
+\r
+ /** Load the mbeans from the source. Called automatically on init() \r
+ * \r
+ * @throws Exception\r
+ */ \r
+ public void load() throws Exception;\r
+ \r
+ /** Call the init method on all mbeans. Will call load if not done already\r
+ * \r
+ * @throws Exception\r
+ */ \r
+ public void init() throws Exception;\r
+\r
+ /** Save the file.\r
+ */ \r
+ public void save();\r
+}\r
--- /dev/null
+package org.apache.tomcat.util.modeler.modules;\r
+\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.net.URL;\r
+import java.util.List;\r
+\r
+import javax.management.ObjectName;\r
+\r
+import org.apache.tomcat.util.modeler.Registry;\r
+\r
+/** Source for descriptor data. More sources can be added.\r
+ *\r
+ */\r
+public class ModelerSource {\r
+ protected Object source;\r
+ protected String location;\r
+\r
+ /** Load data, returns a list of items. \r
+ * \r
+ * @param registry\r
+ * @param location\r
+ * @param type\r
+ * @param source Introspected object or some other source\r
+ * @throws Exception\r
+ */ \r
+ public List loadDescriptors( Registry registry, String location,\r
+ String type, Object source)\r
+ throws Exception\r
+ {\r
+ // TODO\r
+ return null;\r
+ }\r
+ \r
+ /** Callback from the BaseMBean to notify that an attribute has changed.\r
+ * Can be used to implement persistence.\r
+ * \r
+ * @param oname\r
+ * @param name\r
+ * @param value\r
+ */ \r
+ public void updateField( ObjectName oname, String name, \r
+ Object value ) {\r
+ // nothing by default \r
+ }\r
+\r
+ public void store() {\r
+ // nothing\r
+ }\r
+\r
+ protected InputStream getInputStream() throws IOException {\r
+ if( source instanceof URL ) {\r
+ URL url=(URL)source;\r
+ location=url.toString();\r
+ return url.openStream();\r
+ } else if( source instanceof File ) {\r
+ location=((File)source).getAbsolutePath();\r
+ return new FileInputStream((File)source); \r
+ } else if( source instanceof String) {\r
+ location=(String)source;\r
+ return new FileInputStream((String)source); \r
+ } else if( source instanceof InputStream ) {\r
+ return (InputStream)source;\r
+ } \r
+ return null;\r
+ }\r
+\r
+}\r
--- /dev/null
+<html>\r
+<head>\r
+<title>org.apache.commons.modeler.modules</title>\r
+</head>\r
+<body>\r
+<p>Implementation classes - should not be used directly. The API is not stable\r
+but eventually the code will be refactored as a collection of mbeans that will be useable \r
+( more or less ) indepedently.</p>\r
+\r
+<p>The MbeanDescriptors* classes are used to extract metadata from different sources. They\r
+are result of few stages of refactoring - now they look very similar with ant tasks and are\r
+close to normal mbeans, with an execute() method. DOM, SER, Introspection and Dynamic mbean \r
+will load metadata from the corresponding sources.\r
+</p>\r
+\r
+<p>MbeansSource will load an extended MLET file, similar with jboss. It is not completely\r
+implemented - only modeler mbeans and dynamic mbeans are loaded. The important characteristic\r
+is that all declared mbeans will be registered in the mbean server as model mbeans. For\r
+regular java classes, the description will be used to construct the model mbean. DynamicMbeans\r
+metadata will be converted to model mbean and the model mbean wrapper will be loaded.</p>\r
+\r
+<p>The goal of MbeansSource is to implement a simple persistence mechanism. Since all components\r
+are model mbeans, we can detect all changes. The source will be loaded as DOM and modifications\r
+will be made to the tree. The save() method will save the DOM tree - preserving all comments\r
+and having only the changes that are needed.</p>\r
+\r
+<p>There are few remaining issues. First, we need to use the persistence metadata to avoid\r
+saving transient fields ( we save an attribute when we detect a change - but we don't know\r
+if this attribute should be saved ). The solution is to use the persistence fields in the\r
+spec - with some reasonable defaults or patterns for introspection or backward compat.\r
+</p>\r
+\r
+<p>Another problem is implementing adding and removing components. In catalina, a \r
+factory is used to create the components, and save will operate on all mbeans. \r
+For creation we need to also use a factory - using the "Type" as a parameter. This\r
+will also work very well with Ant1.6 where we can use the component factory to \r
+do a "natural" mapping ( i.e. mbeans can be treated as tasks, with attributes as\r
+task attributes ). The second part can be solve by either using a parameter on\r
+the factory method ( saveTo ? ), or by having a single mbeans source per domain.\r
+</p>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+<html>\r
+<head>\r
+<title>Package Documentation for COMMONS-MODELER</title>\r
+</head>\r
+<body bgcolor="white">\r
+<p>The <em>Modeler</em> component of the Jakarta Commons subproject\r
+offers convenient support for configuring and instantiating Model MBeans\r
+(management beans), as described in the JMX Specification. It is typically\r
+used within a server-based application that wants to expose management\r
+features via JMX. See the\r
+<a href="http://java.sun.com/products/JavaManagement/download.html">\r
+JMX Specification (Version 1.1)</a> for more information about Model MBeans\r
+and other JMX concepts.</p>\r
+\r
+<p>Model MBeans are very powerful - and the JMX specification includes a\r
+mechanism to use a standard JMX-provided base class to satisfy many of the\r
+requirements, without having to create custom Model MBean implementation\r
+classes yourself. However, one of the requirements in creating such a\r
+Model MBean is to create the corresponding metadata information (i.e. an\r
+implementation of the\r
+<code>javax.management.modelmbean.ModelMBeanInfo</code> interface and its\r
+corresponding subordinate interfaces). Creating this information can be\r
+tedious and error prone. The <em>Modeler</em> package makes the process\r
+much simpler, because the required information is constructed dynamically\r
+from an easy-to-understand XML description of the metadata. Once you have\r
+the metadata defined, and registered at runtime in the provided\r
+<a href="Registry.html">Registry</a>, <em>Modeler</em> also supports\r
+convenient factory methods to instantiate new Model MBean instances for you.\r
+</p>\r
+\r
+<p>The steps required to use Modeler in your server-based application are\r
+described in detail below. You can find some simple usage code in the unit\r
+tests that come with Modeler (in the <code>src/test</code> subdirectory of the\r
+source distribution), and much more complex usage code in Tomcat 4.1 (in the\r
+<code>org.apache.catalina.mbeans</code> package).</p>. More advanced uses can\r
+be found in Tomcat 5 and jakarta-tomcat-connectors.\r
+\r
+\r
+<h3>1. Acquire a JMX Implementation</h3>\r
+\r
+<p><em>Modeler</em> has been tested with different JMX implementations:\r
+<ul>\r
+<li>JMX Reference Implementation (version 1.0.1 or later) -\r
+ <a href="http://java.sun.com/products/JavaManagement/download.html">\r
+ http://java.sun.com/products/JavaManagement/download.html</a></li>\r
+<li>MX4J (version 1.1 or later) -\r
+ <a href="http://mx4j.sourceforge.net/">http://mx4j.sourceforge.net</a></li>\r
+<li>JBoss MX\r
+ <a href="http://www.jboss.org/">http://www.jboss.org</a></li>\r
+</ul>\r
+\r
+<p>After unpacking the release, you will need to ensure that the appropriate\r
+JAR file (<code>jmxri.jar</code> or <code>mx4j.jar</code>) is included on your\r
+compilation classpath, and in the classpath of your server application when it\r
+is executed.</p>\r
+\r
+\r
+<h3>2. Create a Modeler Configuration File</h3>\r
+\r
+<p><em>Modeler</em> requires that you construct a configuration file that\r
+describes the metadata ultimately need to construct the\r
+<code>javax.management.modelmbean.ModelMBeanInfo</code> structure that is\r
+required by JMX. Your XML file must conform to the\r
+<a href="../../../../../../mbeans-descriptors.dtd">mbeans-descriptors.dtd</a>\r
+DTD that defines the acceptable structure.</p>\r
+\r
+<p>Fundamentally, you will be constructing an <code><mbean></code>\r
+element for each type of Model MBean that a registry will know how to create.\r
+Nested within this element will be other elements describing the constructors,\r
+attributes, operations, and notifications associated with this MBean. See\r
+the comments in the DTD for detailed information about the valid attributes\r
+and their meanings.</p>\r
+\r
+<p>A simple example configuration file might include the following components\r
+(abstracted from the real definitions found in Tomcat 4.1's use of Modeler):\r
+</p>\r
+<pre>\r
+\r
+ <?xml version="1.0"?>\r
+ <!DOCTYPE mbeans-descriptors PUBLIC\r
+ "-//Apache Software Foundation//DTD Model MBeans Configuration File"\r
+ "http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">\r
+\r
+ <mbeans-descriptors>\r
+\r
+ <!-- ... other MBean definitions ... -->\r
+\r
+ <mbean name="Group"\r
+ className="org.apache.catalina.mbeans.GroupMBean"\r
+ description="Group from a user database"\r
+ domain="Users"\r
+ group="Group"\r
+ type="org.apache.catalina.Group">\r
+\r
+ <attribute name="description"\r
+ description="Description of this group"\r
+ type="java.lang.String"/>\r
+\r
+ <attribute name="groupname"\r
+ description="Group name of this group"\r
+ type="java.lang.String"/>\r
+\r
+ <attribute name="roles"\r
+ description="MBean Names of roles for this group"\r
+ type="java.lang.String[]"\r
+ writeable="false"/>\r
+\r
+ <attribute name="users"\r
+ description="MBean Names of user members of this group"\r
+ type="java.lang.String[]"\r
+ writeable="false"/>\r
+\r
+ <operation name="addRole"\r
+ description="Add a new authorized role for this group"\r
+ impact="ACTION"\r
+ returnType="void">\r
+ <parameter name="role"\r
+ description="Role to be added"\r
+ type="java.lang.String"/>\r
+ </operation>\r
+\r
+ <operation name="removeRole"\r
+ description="Remove an old authorized role for this group"\r
+ impact="ACTION"\r
+ returnType="void">\r
+ <parameter name="role"\r
+ description="Role to be removed"\r
+ type="java.lang.String"/>\r
+ </operation>\r
+\r
+ <operation name="removeRoles"\r
+ description="Remove all authorized roles for this group"\r
+ impact="ACTION"\r
+ returnType="void">\r
+ </operation>\r
+\r
+ </mbean>\r
+\r
+ <!-- ... other MBean definitions ... -->\r
+\r
+ </mbeans-descriptors>\r
+\r
+</pre>\r
+\r
+<p>This MBean represents an instance of <em>org.apache.catalina.Group</em>,\r
+which is an entity representing a group of users (with a shared set of security\r
+roles that all users in the group inherit) in a user database. This MBean\r
+advertises support for four attributes (description, groupname, roles, and\r
+users) that roughly correspond to JavaBean properties. By default, attributes\r
+are assumed to have read/write access. For this particular MBean, the roles\r
+and users attributes are read-only (<code>writeable="false"</code>). Finally,\r
+this MBean supports three operations (addRole, removeRole, and\r
+removeRoles) that roughly correspond to JavaBean methods on the underlying\r
+component.</p>\r
+\r
+<p>In general, <em>Modeler</em> provides a standard ModelMBean implementation\r
+that simply passes on JMX calls on attributes and operations directly through\r
+to the managed component that the ModelMBean is associated with. For special\r
+case requirements, you can define a subclass of\r
+<a href="BaseModelMBean.html">BaseModelMBean</a> that provides override\r
+methods for one or more of these attributes (i.e. the property getter and/or\r
+setter methods) and operations (i.e. direct method calls).\r
+\r
+<p>For this particular MBean, a custom BaseModelMBean implementation subclass\r
+is described (<code>org.apache.catalina.mbeans.GroupMBean</code>) is\r
+configured. It was necessary in this particular case because several of the\r
+underlying Catalina component's methods deal with internal objects or arrays of\r
+objects, rather than just the Strings and primitives that are supported by all\r
+JMX clients. Thus, the following method on the <code>Group</code> interface:\r
+</p>\r
+<pre>\r
+ public void addRole(Role role);\r
+</pre>\r
+<p>is represented, in the MBean, by an <code>addRole</code> method that takes\r
+a String argument representing the role name of the required role. The MBean's\r
+implementation class acts as an adapter, and looks up the required Role\r
+object (by name) before calling the <code>addRole</code> method on the\r
+underlying <code>Group</code> instance within the Server.</p>\r
+\r
+\r
+<h3>3. Create Modeler Registry at Startup Time</h3>\r
+\r
+<p>The metadata information, and the corresponding Model MBean factory, is\r
+represented at runtime in an instance of <a href="Registry.html">Registry</a>\r
+whose contents are initialized from the configuration file prepared as was\r
+described above. Typically, such a file will be included in the JAR file\r
+containing the MBean implementation classes themselves, and loaded as follows:\r
+</p>\r
+<pre>\r
+ URL url= this.getClass().getResource\r
+ ("/com/mycompany/mypackage/mbeans-descriptors.xml");\r
+ Registry registry = Registry.getRegistry();\r
+ registry.loadMetadata(url);\r
+</pre>\r
+\r
+<p>Besides using the configuration file, it is possible to configure the\r
+registry metadata by hand, using the <code>addManagedBean()</code> and\r
+<code>removeManagedBean()</code> methods. However, most users will find\r
+the standard support for loading a configuration file to be convenient\r
+and sufficient.</p>\r
+\r
+<p>Modeler will also look for a mbeans-descriptors.xml in the same package\r
+with the class beeing registered and in its parent. If no metadata is found,\r
+modeler will use a number of simple patterns, similar with the ones used by \r
+ant, to determine a reasonable metadata</p>\r
+\r
+<p>In a future version we should also support xdoclet-based generation of the\r
+descriptors</p>\r
+\r
+\r
+<h3>4. Instantiate Model MBeans As Needed</h3>\r
+\r
+<p>When your server application needs to instantiate a new MBean and register\r
+it with the corresponding <code>MBeanServer</code>, it can execute code like\r
+this:</p>\r
+\r
+<pre>\r
+ Group group = ... managed component instance ...;\r
+\r
+ MBeanServer mserver = registry.getMBeanServer();\r
+\r
+ String oname="myDomain:type=Group,name=myGroup";\r
+\r
+ registry.registerComponent( group, oname, "Group" );\r
+</pre>\r
+\r
+<p>After the Model MBean has been created and registered, it is accessible to\r
+JMX clients through the standard JMX client APIs.\r
+</p>\r
+\r
+</body>\r
+</html>\r
Manifest-Version: 1.0\r
Main-Class: org.apache.catalina.startup.Bootstrap\r
-Class-Path: commons-daemon.jar commons-logging-api.jar tomcat-juli.jar tomcat-util.jar\r
+Class-Path: commons-daemon.jar commons-logging-api.jar tomcat-juli.jar tomcat-coyote.jar\r
Specification-Title: Catalina\r
Specification-Version: 6.0
\ No newline at end of file