Author: pero
Date: Mon Jun  4 23:19:13 2007
New Revision: 544401

URL: http://svn.apache.org/viewvc?view=rev&rev=544401
Log:
Add JMXAdaptorLifecycleListener to start JMX Connector with fix naming and data 
port. 
This feature is needed to have stable remote access as your local firewall is 
activ.

Added:
    
tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/mbeans/JMXAdaptorLifecycleListener.java
   (with props)
Modified:
    tomcat/container/tc5.5.x/webapps/docs/changelog.xml
    tomcat/container/tc5.5.x/webapps/docs/monitoring.xml

Added: 
tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/mbeans/JMXAdaptorLifecycleListener.java
URL: 
http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/mbeans/JMXAdaptorLifecycleListener.java?view=auto&rev=544401
==============================================================================
--- 
tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/mbeans/JMXAdaptorLifecycleListener.java
 (added)
+++ 
tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/mbeans/JMXAdaptorLifecycleListener.java
 Mon Jun  4 23:19:13 2007
@@ -0,0 +1,355 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.mbeans;
+
+import java.util.HashMap;
+import java.util.Properties;
+import java.io.IOException;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.core.StandardServer;
+
+import java.net.InetAddress;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import javax.rmi.ssl.SslRMIServerSocketFactory;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+
+import java.lang.management.ManagementFactory;
+import javax.management.MBeanServer;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.rmi.RMIConnectorServer;
+
+/**
+ * Start JSR160 JMX Adapter with naming and jmx port! Add only as Server 
Listner
+ * to your tomcat <i>server.xml</i> <br/><pre>
+ * &lt;Server ...&gt;
+ * ...
+ *   &lt;Listener 
className="org.apache.catalina.mbeans.JMXAdaptorLifecycleListener"<br/>
+ *             namingPort="8083" port="8084" host="myhost" />  
+ * ...
+ * &lt;/Server&gt;
+ * </pre>
+ * 
+ * You can use normal jmx system properties from command line or jmx config 
file: 
+ * <ul>
+ * <li><code>-Dcom.sun.management.jmxremote.authenticate=true</code></li>
+ * <li><code>-Dcom.sun.management.jmxremote.ssl=false</code></li>
+ * 
<li><code>-Dcom.sun.management.jmxremote.access.file=$CATALINA_BASE/conf/access.file</code></li>
+ * 
<li><code>-Dcom.sun.management.jmxremote.password.file=$CATALINA_BASE/conf/password.file</code></li>
+ * 
<li><code>-Dcom.sun.management.config.file=$CATALINA_BASE/conf/jmx.properties</code></li>
+ * </ul>
+ * <br/>
+ * Then run jconsole with:
+ * <code>
+ * jconsole service:jmx:rmi://myhost:8084/jndi/rmi://myhost:8083/server
+ * </code>
+ * 
+ * <p>
+ * It would be be better if this was built into Tomcat as a configuration
+ * option, rather than having to do it as part of every Tomcat instance.
+ * </p>
+ * <p>Origanal code idea comes from George Lindholm read
+ * <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=39055";>Tomcat 
Bug 39055<a/>
+ * and other helpful links are:<br/>
+ * <ul>
+ * <li><a 
href="http://today.java.net/pub/a/today/2005/11/15/using-jmx-to-manage-web-applications.html";>Using
 Web Apps</a></li>
+ * <li><a 
href="http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html#SSL_enabled";>JVM
 1.5 JMX Guide</a></li>
+ * </p>
+ * @author Peter Rossbach
+ * @author Juergen Herrmann
+ */
+public class JMXAdaptorLifecycleListener implements LifecycleListener {
+
+    /**
+     * Logger
+     */
+    private static org.apache.commons.logging.Log log = 
org.apache.commons.logging.LogFactory
+            .getLog(JMXAdaptorLifecycleListener.class);
+
+    /**
+     * The descriptive information string for this implementation.
+     */
+    private static final String info = 
"org.apache.catalina.mbeans.JMXAdaptorLifecycleListener/1.0";
+
+    private boolean enabled = true;
+
+    private int namingPort = 0;
+
+    private int port = 0;
+
+    private String host = null;
+
+    private String jmxUrl = null;
+
+    private JMXConnectorServer connectorServer = null;
+
+    private Properties managementProperties = null;
+
+    /**
+     * create new jmx adaptor and read properties from file.
+     * Use jvm property <code>-Dcom.sun.management.config.file=xxx</code> as 
file.
+     *
+     */
+    public JMXAdaptorLifecycleListener() {
+        final String configProperty = "com.sun.management.config.file";
+        String configFileName = System.getProperty(configProperty);
+
+        if (configFileName != null) {
+            try {
+                FileInputStream configFile = new 
FileInputStream(configFileName);
+                try {
+                    managementProperties = new Properties();
+                    managementProperties.load(configFile);
+                } finally {
+                    configFile.close();
+                }
+            } catch (FileNotFoundException ex) {
+                log.error("Cannot open " + configFileName, ex);
+            } catch (IOException ex) {
+                log.error("Error while reading " + configFileName, ex);
+            }
+        }
+    }
+
+    /**
+     * @return Returns the host.
+     */
+    public String getHost() {
+        return host;
+    }
+
+    /**
+     * @paramhost The host to set.
+     */
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    /**
+     * @return Returns the port.
+     */
+    public int getPort() {
+        return port;
+    }
+
+    /**
+     * @param port The port to set.
+     */
+    public void setPort(int port) {
+        if (port < 1 || 65535 < port) {
+            log.warn("Illegal port value " + port);
+            port = 0;
+        }
+        this.port = port;
+    }
+
+    /**
+     * @return Returns the namingPort.
+     */
+    public int getNamingPort() {
+        return namingPort;
+    }
+
+    /**
+     * @param namingPort The namingPort to set.
+     */
+    public void setNamingPort(int namingPort) {
+        this.namingPort = namingPort;
+        if (namingPort < 1 || 65535 < namingPort) {
+            log.warn("Illegal namingPort value " + namingPort);
+            namingPort = 0;
+        }
+        this.namingPort = namingPort;
+    }
+
+    /**
+     * @return Returns the enabled.
+     */
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    /**
+     * @param enabled The enabled to set.
+     */
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    /**
+     * @return the jmxUrl
+     */
+    public String getJmxUrl() {
+        return jmxUrl;
+    }
+
+    /**
+     * Return descriptive information about this Listener implementation and 
the
+     * corresponding version number, in the format
+     * <code>&lt;description&gt;/&lt;version&gt;</code>.
+     */
+    public String getInfo() {
+
+        return (info);
+
+    }
+
+    /*
+     * Start/Stop JSR 160 Adaptor
+     * 
+     * @see 
org.apache.catalina.LifecycleListener#lifecycleEvent(org.apache.catalina.LifecycleEvent)
+     */
+    public void lifecycleEvent(LifecycleEvent event) {
+        Object source = event.getSource();
+        if (!(source instanceof StandardServer))
+            return;
+
+        if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
+            start();
+        }
+        if (Lifecycle.BEFORE_STOP_EVENT.equals(event.getType())) {
+            stop();
+        }
+    }
+
+    /**
+     * stop jmx connector at tomcat normale shutdown 
+     *
+     */
+    protected void stop() {
+        if (connectorServer != null) {
+            if (log.isInfoEnabled())
+                log.info("JMXConnectorServer stopping on " + jmxUrl);
+
+            try {
+                // Stop connector, else shutdown takes a lot longer
+                connectorServer.stop();
+                jmxUrl = null;
+            } catch (IOException ex) {
+                // We always get this (why?), so just trace it
+                log.error("Error while stopping remote JMX connector", ex);
+            }
+            connectorServer = null;
+        }
+    }
+
+    /**
+     * get jmx config parameter from jmx config file or system property.
+     * @param name
+     * @return config parameter value
+     */
+    protected String getConfigProperty(String name) {
+        String result = null;
+        if (managementProperties != null) {
+            result = managementProperties.getProperty(name);
+        }
+        if (result == null) {
+            result = System.getProperty(name);
+        }
+        return result;
+    }
+
+    /**
+     * Start JMX connector and local name registry
+     *
+     */
+    public void start() {
+
+        if (enabled) {
+            if (namingPort == 0 || port == 0)
+                return;
+ 
+            try {
+                if (host == null || "".equals(host)) {
+                    final InetAddress address = InetAddress.getLocalHost();
+                    host = address.getHostName();
+                }
+
+                // naming
+                LocateRegistry.createRegistry(namingPort);
+                // tomcat normal mbeanserver
+                MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+                // read ssl config
+                HashMap env = new HashMap();
+                final String sslProperty = "com.sun.management.jmxremote.ssl";
+                String value = getConfigProperty(sslProperty);
+                if (Boolean.valueOf(value).booleanValue()) {
+                    if (log.isInfoEnabled())
+                        log.info("Activated SSL communication");
+                    SslRMIClientSocketFactory csf = new 
SslRMIClientSocketFactory();
+                    SslRMIServerSocketFactory ssf = new 
SslRMIServerSocketFactory();
+                    
env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE,csf);
+                    
env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,ssf);
+                }
+
+                // read auth config
+                final String authenticateProperty = 
"com.sun.management.jmxremote.authenticate";
+                value = getConfigProperty(authenticateProperty);
+                if (log.isTraceEnabled())
+                    log.trace(authenticateProperty + " is " + value);
+
+                if (Boolean.valueOf(value).booleanValue()) {
+                    final String accessFileProperty = 
"com.sun.management.jmxremote.access.file";
+                    value = getConfigProperty(accessFileProperty);
+                    if (log.isTraceEnabled())
+                        log.trace(accessFileProperty + " is " + value);
+                    if (value != null) {
+                        env.put("jmx.remote.x.access.file", value);
+                    }
+
+                    final String passwordFileProperty = 
"com.sun.management.jmxremote.password.file";
+                    value = getConfigProperty(passwordFileProperty);
+                    if (log.isTraceEnabled())
+                        log.trace(passwordFileProperty + " is " + value);
+                    if (value != null) {
+                        env.put("jmx.remote.x.password.file", value);
+                    }
+                } else {
+                    log.warn("Unsafe JMX remote access!");
+                }
+
+                // create jmx adaptor
+                jmxUrl = "service:jmx:rmi://" + host + ":" + port
+                        + "/jndi/rmi://" + host + ":" + namingPort + "/server";
+                final JMXServiceURL url = new JMXServiceURL(jmxUrl);
+                connectorServer = JMXConnectorServerFactory
+                        .newJMXConnectorServer(url, env, mbs);
+
+                // start jmx adaptor
+                try {
+                    connectorServer.start();
+                    if (log.isInfoEnabled())
+                        log.info("JMXConnectorServer started on " + jmxUrl);
+                } catch (IOException ex) {
+                    log.warn("Cannot start JMXConnectorServer on " + jmxUrl, 
ex);
+                }
+            } catch (Exception ex) {
+                log.error("Error while setting up remote JMX connector", ex);
+            }
+        }
+    }
+
+}

Propchange: 
tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/mbeans/JMXAdaptorLifecycleListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/container/tc5.5.x/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/webapps/docs/changelog.xml?view=diff&rev=544401&r1=544400&r2=544401
==============================================================================
--- tomcat/container/tc5.5.x/webapps/docs/changelog.xml (original)
+++ tomcat/container/tc5.5.x/webapps/docs/changelog.xml Mon Jun  4 23:19:13 2007
@@ -95,6 +95,11 @@
       <fix>
          Allow for a forward/include to call getAttributeNames on the Request 
in a sandbox. (billbarker)
       </fix>
+      <add>
+        <bug>39055</bug>: Add JMXAdaptorLifecycleListener to start JMX 
Connector with fix naming and data port. 
+        This feature is needed to have stable remote access as your local 
firewall is activ. The adaptor read all
+        standard JMX system properties (-Dcom.sun.management.jmxremote). 
Feature provided by George Lindholm and Juergen Herrman (pero)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Webapps">

Modified: tomcat/container/tc5.5.x/webapps/docs/monitoring.xml
URL: 
http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/webapps/docs/monitoring.xml?view=diff&rev=544401&r1=544400&r2=544401
==============================================================================
--- tomcat/container/tc5.5.x/webapps/docs/monitoring.xml (original)
+++ tomcat/container/tc5.5.x/webapps/docs/monitoring.xml Mon Jun  4 23:19:13 
2007
@@ -63,9 +63,21 @@
     </ol>
     <b>Note:</b>The JSR 160 JMX-Adaptor opens a second data protocol port. 
That is a problem
     when you have installed a local firewall.  However, there is at least one 
possible
-    workaround: using a custom JMXConnectorServer.  The code for this is 
available
-    at <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=39055"; 
title="Bugzila 39055">Bugzilla 39055</a>.
+    workaround: using a custom JMXConnectorServer.</p>
+    <p>Start a JMX Adaptor with fix data port is supported with Tomcst 5.5.24 
release:
+    <source>
+&lt;Server ...&gt;
+...
+&lt;Listener className="org.apache.catalina.mbeans.JMXAdaptorLifecycleListener"
+          namingPort="8083" port="8084" host="myhost" />  
+...
+&lt;/Server&gt;
+   </source>
+    You can use all JMX system properties 
(<i>com.sun.management.jmxremote.xxx</i>) to configure the adaptor :-) <br/>At 
your remote jconsole
+    call the jmx adaptor with following command <br/><i>jconsole 
service:jmx:rmi://myhost:8084/jndi/rmi://myhost:8083/server</i>
     </p>
+ 
+ 
     <p>Activate JMX MX4J Http Adaptor with Java 1.4:
     <ol>
       <li>Install the tomcat compat package</li>
@@ -99,7 +111,7 @@
 
   <section name="Manage Tomcat with JMX remote Ant Tasks">
    <p>For simple tomcat ant task usage with ant 1.6.x we have integrate import 
and antlib support.</p>   
-   <p><b>antlib</b>Copy your catalina-ant.jar from $CATALINA_HOME/server/lib 
to $ANT_HOME/lib.</p>
+   <p><b>antlib support:</b><br/> Copy your catalina-ant.jar from 
$CATALINA_HOME/server/lib to $ANT_HOME/lib.</p>
    <p>Following example show the JMX Accessor usage:</p>
    <table border="1">
    <tr><td><p><pre>



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to