- Reduce the number of JARs.
authorremm <remm@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 30 Mar 2006 00:55:22 +0000 (00:55 +0000)
committerremm <remm@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 30 Mar 2006 00:55:22 +0000 (00:55 +0000)
- Is it me, or are the JARs magically smaller ? There must be something related to JDK 1.5.
- bootstrap.jar is really needed.
- Import modeler. I think there are some serious possibilities to enhance XML processing,
  as everything (or almost everything, as I don't think the modeler does at the moment)
  goes through digester.
- I suppose the webapps could be added now.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk@389946 13f79535-47bb-0310-9956-ffa450edef68

76 files changed:
build.properties.default
build.xml
java/org/apache/catalina/ant/jmx/JMXAccessorQueryTask.java
java/org/apache/catalina/connector/Connector.java
java/org/apache/catalina/connector/MapperListener.java
java/org/apache/catalina/core/ContainerBase.java
java/org/apache/catalina/core/NamingContextListener.java
java/org/apache/catalina/core/StandardContext.java
java/org/apache/catalina/core/StandardEngine.java
java/org/apache/catalina/core/StandardHost.java
java/org/apache/catalina/core/StandardPipeline.java
java/org/apache/catalina/core/StandardServer.java
java/org/apache/catalina/core/StandardService.java
java/org/apache/catalina/core/StandardWrapper.java
java/org/apache/catalina/loader/WebappLoader.java
java/org/apache/catalina/mbeans/ClassNameMBean.java
java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java
java/org/apache/catalina/mbeans/ContextResourceMBean.java
java/org/apache/catalina/mbeans/DefaultContextMBean.java
java/org/apache/catalina/mbeans/GlobalResourcesLifecycleListener.java
java/org/apache/catalina/mbeans/GroupMBean.java
java/org/apache/catalina/mbeans/MBeanFactory.java
java/org/apache/catalina/mbeans/MBeanUtils.java
java/org/apache/catalina/mbeans/MemoryUserDatabaseMBean.java
java/org/apache/catalina/mbeans/NamingResourcesMBean.java
java/org/apache/catalina/mbeans/RoleMBean.java
java/org/apache/catalina/mbeans/StandardContextMBean.java
java/org/apache/catalina/mbeans/StandardEngineMBean.java
java/org/apache/catalina/mbeans/StandardHostMBean.java
java/org/apache/catalina/mbeans/StandardServerMBean.java
java/org/apache/catalina/mbeans/StandardServiceMBean.java
java/org/apache/catalina/mbeans/UserMBean.java
java/org/apache/catalina/realm/RealmBase.java
java/org/apache/catalina/session/ManagerBase.java
java/org/apache/catalina/startup/HostConfig.java
java/org/apache/coyote/ajp/AjpAprProtocol.java
java/org/apache/coyote/http11/Http11AprProtocol.java
java/org/apache/coyote/http11/Http11Protocol.java
java/org/apache/jk/common/ChannelNioSocket.java
java/org/apache/jk/common/ChannelSocket.java
java/org/apache/jk/common/ChannelUn.java
java/org/apache/jk/common/JniHandler.java
java/org/apache/jk/common/ModJkMX.java
java/org/apache/jk/core/JkHandler.java
java/org/apache/jk/server/JkCoyoteHandler.java
java/org/apache/jk/server/JkMain.java
java/org/apache/tomcat/util/DomUtil.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/AttributeInfo.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/BaseModelMBean.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/BaseNotification.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/ConstructorInfo.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/FeatureInfo.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/FieldInfo.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/FixedNotificationFilter.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/JndiJmx.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/ManagedBean.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/NotificationInfo.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/OperationInfo.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/ParameterInfo.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/Registry.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/RegistryMBean.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDOMSource.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDynamicMBeanSource.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsSerSource.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/modules/MbeansSource.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/modules/MbeansSourceMBean.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/modules/ModelerSource.java [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/modules/package.html [new file with mode: 0644]
java/org/apache/tomcat/util/modeler/package.html [new file with mode: 0644]
res/bootstrap.jar.manifest

index f049251..d66c22a 100644 (file)
@@ -18,11 +18,7 @@ base.path=/usr/share/java
 #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
@@ -31,12 +27,6 @@ commons-logging-api.jar=${commons-logging.lib}/commons-logging-api.jar
 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
index 093c482..d530c10 100644 (file)
--- a/build.xml
+++ b/build.xml
   <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
@@ -63,7 +53,6 @@
     <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
@@ -77,6 +66,7 @@
     <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
index 8aa749b..31bbbfa 100644 (file)
@@ -174,7 +174,7 @@ public class JMXAccessorQueryTask extends JMXAccessorTask {
             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
index 234771c..2e32c82 100644 (file)
@@ -36,11 +36,11 @@ import org.apache.catalina.util.LifecycleSupport;
 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
index 80ebe95..8e06b64 100644 (file)
@@ -28,9 +28,9 @@ import javax.management.ObjectName;
 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
index bf604d2..bf34aec 100644 (file)
@@ -54,8 +54,8 @@ import org.apache.catalina.util.LifecycleSupport;
 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
index 9962658..c5a9d35 100644 (file)
@@ -54,7 +54,6 @@ import org.apache.catalina.deploy.NamingResources;
 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
@@ -63,6 +62,7 @@ import org.apache.naming.ResourceEnvRef;
 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
index e2d8c1b..b4875b1 100644 (file)
@@ -90,7 +90,6 @@ import org.apache.catalina.util.RequestUtil;
 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
@@ -98,6 +97,7 @@ import org.apache.naming.resources.FileDirContext;
 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
index 976597e..98cace6 100644 (file)
@@ -35,8 +35,8 @@ import org.apache.catalina.realm.JAASRealm;
 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
index 2b1505f..5b9d8e3 100644 (file)
@@ -28,7 +28,7 @@ import org.apache.catalina.LifecycleException;
 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
index 819b21f..d0499f0 100644 (file)
@@ -34,7 +34,7 @@ import org.apache.catalina.util.StringManager;
 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
index fb6594d..908b379 100644 (file)
@@ -45,8 +45,8 @@ import org.apache.catalina.util.StringManager;
 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
index 4ffce27..707c823 100644 (file)
@@ -36,7 +36,7 @@ import org.apache.catalina.util.LifecycleSupport;
 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
index 4bbea6a..96b8734 100644 (file)
@@ -57,7 +57,7 @@ import org.apache.catalina.util.Enumerator;
 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
index 81d4cee..7d9bf3b 100644 (file)
@@ -57,10 +57,10 @@ import org.apache.catalina.Loader;
 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
index dc93fe1..9e132d6 100644 (file)
@@ -19,7 +19,8 @@ package org.apache.catalina.mbeans;
 \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
index f498102..6b59ddf 100644 (file)
@@ -27,7 +27,7 @@ import javax.management.modelmbean.InvalidTargetObjectTypeException;
 \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
index a1a3b59..322fc80 100644 (file)
@@ -27,7 +27,7 @@ import javax.management.modelmbean.InvalidTargetObjectTypeException;
 \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
index e86bd6d..ed15b9c 100644 (file)
@@ -27,7 +27,7 @@ import javax.management.modelmbean.InvalidTargetObjectTypeException;
 \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
index 7460a2b..767c526 100644 (file)
@@ -28,10 +28,10 @@ import org.apache.catalina.deploy.ContextEnvironment;
 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
index ab40612..0747665 100644 (file)
@@ -31,9 +31,9 @@ import org.apache.catalina.LifecycleListener;
 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
index 63f9298..15b28ef 100644 (file)
@@ -29,10 +29,10 @@ import javax.management.RuntimeOperationsException;
 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
index 2664d85..5c6592b 100644 (file)
@@ -52,8 +52,8 @@ import org.apache.catalina.valves.RemoteAddrValve;
 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
index a7d6a95..3f142f0 100644 (file)
@@ -48,9 +48,9 @@ import org.apache.catalina.deploy.NamingResources;
 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
index 38cdcbb..ce2ab05 100644 (file)
@@ -28,10 +28,10 @@ import org.apache.catalina.Group;
 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
index e8cb7bf..2020509 100644 (file)
@@ -27,10 +27,10 @@ import org.apache.catalina.deploy.ContextEnvironment;
 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
index a0aa357..541c57a 100644 (file)
@@ -21,9 +21,9 @@ import javax.management.MBeanException;
 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
index 9000af6..a4c4147 100644 (file)
@@ -28,10 +28,10 @@ import org.apache.catalina.deploy.ContextEnvironment;
 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
index 23e677c..6e4e6a8 100644 (file)
@@ -21,7 +21,7 @@ import javax.management.MBeanException;
 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
index 8a73359..4555710 100644 (file)
@@ -23,9 +23,9 @@ import javax.management.RuntimeOperationsException;
 \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
index 2a22ce1..94b8547 100644 (file)
@@ -24,7 +24,7 @@ import javax.management.RuntimeOperationsException;
 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
index 83f5069..503996d 100644 (file)
@@ -21,7 +21,7 @@ import javax.management.MBeanException;
 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
index 07a97a5..ee315f7 100644 (file)
@@ -29,10 +29,10 @@ import javax.management.RuntimeOperationsException;
 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
index 25d3740..4a0e3b7 100644 (file)
@@ -52,7 +52,7 @@ import org.apache.catalina.util.MD5Encoder;
 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
index 7213a0f..a033ce6 100644 (file)
@@ -48,7 +48,7 @@ import org.apache.catalina.core.StandardHost;
 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
index ab20c5e..fae2224 100644 (file)
@@ -41,8 +41,8 @@ import org.apache.catalina.LifecycleListener;
 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
index 3fb2c39..9e3ebfc 100644 (file)
@@ -25,13 +25,13 @@ import javax.management.MBeanRegistration;
 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
index c6b4e29..8c71250 100644 (file)
@@ -25,13 +25,13 @@ import javax.management.MBeanRegistration;
 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
index 96323c2..95cd8d8 100644 (file)
@@ -20,8 +20,8 @@ import javax.management.MBeanRegistration;
 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
index b51b350..9302d5a 100644 (file)
@@ -45,7 +45,6 @@ import javax.management.NotificationFilter;
 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
@@ -54,6 +53,7 @@ import org.apache.jk.core.WorkerEnv;
 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
index 5b71530..c49833d 100644 (file)
@@ -36,7 +36,6 @@ import javax.management.NotificationFilter;
 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
@@ -45,6 +44,7 @@ import org.apache.jk.core.WorkerEnv;
 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
index 281fa81..1253db9 100644 (file)
@@ -22,7 +22,6 @@ import java.io.FileOutputStream;
 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
@@ -31,6 +30,7 @@ import org.apache.jk.core.WorkerEnv;
 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
index 27824a6..46e176a 100644 (file)
@@ -20,7 +20,6 @@ import java.io.IOException;
 \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
@@ -29,6 +28,7 @@ import org.apache.jk.core.JkChannel;
 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
index 4220784..7fa732e 100644 (file)
@@ -33,11 +33,11 @@ import javax.management.Attribute;
 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
index 939e2ec..db08931 100644 (file)
@@ -25,7 +25,7 @@ import javax.management.Notification;
 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
index 045d964..91a1cda 100644 (file)
@@ -22,7 +22,6 @@ import java.util.Iterator;
 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
@@ -41,6 +40,7 @@ import org.apache.tomcat.util.buf.C2BConverter;
 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
index 1ac6385..bd44782 100644 (file)
@@ -31,10 +31,10 @@ import javax.management.MBeanRegistration;
 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
diff --git a/java/org/apache/tomcat/util/DomUtil.java b/java/org/apache/tomcat/util/DomUtil.java
new file mode 100644 (file)
index 0000000..3cac8a7
--- /dev/null
@@ -0,0 +1,269 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/AttributeInfo.java b/java/org/apache/tomcat/util/modeler/AttributeInfo.java
new file mode 100644 (file)
index 0000000..f806a1d
--- /dev/null
@@ -0,0 +1,317 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java b/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java
new file mode 100644 (file)
index 0000000..0701f6c
--- /dev/null
@@ -0,0 +1,159 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/BaseModelMBean.java b/java/org/apache/tomcat/util/modeler/BaseModelMBean.java
new file mode 100644 (file)
index 0000000..f633beb
--- /dev/null
@@ -0,0 +1,1416 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/BaseNotification.java b/java/org/apache/tomcat/util/modeler/BaseNotification.java
new file mode 100644 (file)
index 0000000..d6a5e27
--- /dev/null
@@ -0,0 +1,88 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java b/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java
new file mode 100644 (file)
index 0000000..197b9e6
--- /dev/null
@@ -0,0 +1,264 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/ConstructorInfo.java b/java/org/apache/tomcat/util/modeler/ConstructorInfo.java
new file mode 100644 (file)
index 0000000..13d0104
--- /dev/null
@@ -0,0 +1,164 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/FeatureInfo.java b/java/org/apache/tomcat/util/modeler/FeatureInfo.java
new file mode 100644 (file)
index 0000000..c23d96c
--- /dev/null
@@ -0,0 +1,115 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/FieldInfo.java b/java/org/apache/tomcat/util/modeler/FieldInfo.java
new file mode 100644 (file)
index 0000000..ddc6a3c
--- /dev/null
@@ -0,0 +1,60 @@
+/*\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>&lt;field&gt;</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
diff --git a/java/org/apache/tomcat/util/modeler/FixedNotificationFilter.java b/java/org/apache/tomcat/util/modeler/FixedNotificationFilter.java
new file mode 100644 (file)
index 0000000..6fb1836
--- /dev/null
@@ -0,0 +1,94 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/JndiJmx.java b/java/org/apache/tomcat/util/modeler/JndiJmx.java
new file mode 100644 (file)
index 0000000..988b5e1
--- /dev/null
@@ -0,0 +1,227 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/ManagedBean.java b/java/org/apache/tomcat/util/modeler/ManagedBean.java
new file mode 100644 (file)
index 0000000..a2c39a7
--- /dev/null
@@ -0,0 +1,508 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/NotificationInfo.java b/java/org/apache/tomcat/util/modeler/NotificationInfo.java
new file mode 100644 (file)
index 0000000..98e6556
--- /dev/null
@@ -0,0 +1,141 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/OperationInfo.java b/java/org/apache/tomcat/util/modeler/OperationInfo.java
new file mode 100644 (file)
index 0000000..6be9ea4
--- /dev/null
@@ -0,0 +1,246 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/ParameterInfo.java b/java/org/apache/tomcat/util/modeler/ParameterInfo.java
new file mode 100644 (file)
index 0000000..13717bd
--- /dev/null
@@ -0,0 +1,151 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/Registry.java b/java/org/apache/tomcat/util/modeler/Registry.java
new file mode 100644 (file)
index 0000000..1aac7dc
--- /dev/null
@@ -0,0 +1,1083 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/RegistryMBean.java b/java/org/apache/tomcat/util/modeler/RegistryMBean.java
new file mode 100644 (file)
index 0000000..b774301
--- /dev/null
@@ -0,0 +1,138 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd b/java/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd
new file mode 100644 (file)
index 0000000..231203e
--- /dev/null
@@ -0,0 +1,233 @@
+<?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
diff --git a/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDOMSource.java b/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDOMSource.java
new file mode 100644 (file)
index 0000000..3b7314c
--- /dev/null
@@ -0,0 +1,302 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java b/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java
new file mode 100644 (file)
index 0000000..901926a
--- /dev/null
@@ -0,0 +1,228 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDynamicMBeanSource.java b/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDynamicMBeanSource.java
new file mode 100644 (file)
index 0000000..5aa2ff7
--- /dev/null
@@ -0,0 +1,157 @@
+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
diff --git a/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java b/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java
new file mode 100644 (file)
index 0000000..8c4dc34
--- /dev/null
@@ -0,0 +1,418 @@
+/*\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
diff --git a/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsSerSource.java b/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsSerSource.java
new file mode 100644 (file)
index 0000000..6533f5a
--- /dev/null
@@ -0,0 +1,88 @@
+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
diff --git a/java/org/apache/tomcat/util/modeler/modules/MbeansSource.java b/java/org/apache/tomcat/util/modeler/modules/MbeansSource.java
new file mode 100644 (file)
index 0000000..44f2164
--- /dev/null
@@ -0,0 +1,350 @@
+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
diff --git a/java/org/apache/tomcat/util/modeler/modules/MbeansSourceMBean.java b/java/org/apache/tomcat/util/modeler/modules/MbeansSourceMBean.java
new file mode 100644 (file)
index 0000000..c577d84
--- /dev/null
@@ -0,0 +1,42 @@
+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
diff --git a/java/org/apache/tomcat/util/modeler/modules/ModelerSource.java b/java/org/apache/tomcat/util/modeler/modules/ModelerSource.java
new file mode 100644 (file)
index 0000000..35f21c8
--- /dev/null
@@ -0,0 +1,70 @@
+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
diff --git a/java/org/apache/tomcat/util/modeler/modules/package.html b/java/org/apache/tomcat/util/modeler/modules/package.html
new file mode 100644 (file)
index 0000000..7f1574d
--- /dev/null
@@ -0,0 +1,43 @@
+<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
diff --git a/java/org/apache/tomcat/util/modeler/package.html b/java/org/apache/tomcat/util/modeler/package.html
new file mode 100644 (file)
index 0000000..4d5aa68
--- /dev/null
@@ -0,0 +1,232 @@
+<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>&lt;mbean&gt;</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
+  &lt;?xml version="1.0"?&gt;\r
+  &lt;!DOCTYPE mbeans-descriptors PUBLIC\r
+   "-//Apache Software Foundation//DTD Model MBeans Configuration File"\r
+   "http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd"&gt;\r
+\r
+  &lt;mbeans-descriptors&gt;\r
+\r
+    &lt;!-- ... other MBean definitions ... --&gt;\r
+\r
+    &lt;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"&gt;\r
+\r
+      &lt;attribute   name="description"\r
+            description="Description of this group"\r
+                   type="java.lang.String"/&gt;\r
+\r
+      &lt;attribute   name="groupname"\r
+            description="Group name of this group"\r
+                   type="java.lang.String"/&gt;\r
+\r
+      &lt;attribute   name="roles"\r
+            description="MBean Names of roles for this group"\r
+                   type="java.lang.String[]"\r
+              writeable="false"/&gt;\r
+\r
+      &lt;attribute   name="users"\r
+            description="MBean Names of user members of this group"\r
+                   type="java.lang.String[]"\r
+              writeable="false"/&gt;\r
+\r
+      &lt;operation   name="addRole"\r
+            description="Add a new authorized role for this group"\r
+                 impact="ACTION"\r
+             returnType="void"&gt;\r
+        &lt;parameter name="role"\r
+            description="Role to be added"\r
+                   type="java.lang.String"/&gt;\r
+      &lt;/operation&gt;\r
+\r
+      &lt;operation   name="removeRole"\r
+            description="Remove an old authorized role for this group"\r
+                 impact="ACTION"\r
+             returnType="void"&gt;\r
+        &lt;parameter name="role"\r
+            description="Role to be removed"\r
+                   type="java.lang.String"/&gt;\r
+      &lt;/operation&gt;\r
+\r
+      &lt;operation   name="removeRoles"\r
+            description="Remove all authorized roles for this group"\r
+                 impact="ACTION"\r
+             returnType="void"&gt;\r
+      &lt;/operation&gt;\r
+\r
+    &lt;/mbean&gt;\r
+\r
+    &lt;!-- ... other MBean definitions ... --&gt;\r
+\r
+  &lt;/mbeans-descriptors&gt;\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
index 045e7a7..4ccb702 100644 (file)
@@ -1,5 +1,5 @@
 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