Author: markt
Date: Tue Sep 30 17:38:00 2008
New Revision: 700645

URL: http://svn.apache.org/viewvc?rev=700645&view=rev
Log:
Fix some issues discovered when using this with PuTTY.

Modified:
    tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java
    tomcat/trunk/webapps/docs/config/listeners.xml

Modified: 
tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java?rev=700645&r1=700644&r2=700645&view=diff
==============================================================================
--- 
tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java 
(original)
+++ 
tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java 
Tue Sep 30 17:38:00 2008
@@ -18,10 +18,14 @@
 package org.apache.catalina.mbeans;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.lang.management.ManagementFactory;
 import java.net.MalformedURLException;
+import java.net.Socket;
 import java.rmi.RemoteException;
 import java.rmi.registry.LocateRegistry;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
 import java.util.HashMap;
 
 import javax.management.MBeanServer;
@@ -44,7 +48,8 @@
  * simpler if you need to connect jconsole or similar to a remote Tomcat
  * instance that is running behind a firewall. Only this port is configured via
  * the listener. The remainder of the configuration is via the standard system
- * properties for configuring JMX.
+ * properties for configuring JMX. Because Tomcat uses a separate MBean server
+ * to the platform MBean server, both servers must be configured separately.
  */
 public class JmxRemoteLifecycleListener implements LifecycleListener {
     
@@ -57,8 +62,10 @@
     protected static final StringManager sm =
         StringManager.getManager(Constants.Package);
 
-    protected int rmiRegistryPort = -1;
-    protected int rmiServerPort = -1;
+    protected int rmiRegistryPortPlatform = -1;
+    protected int rmiServerPortPlatform = -1;
+    protected int rmiRegistryPortCatalina = -1;
+    protected int rmiServerPortCatalina = -1;
     protected boolean rmiSSL = true;
     protected String ciphers[] = null;
     protected String protocols[] = null;
@@ -66,39 +73,95 @@
     protected boolean authenticate = true;
     protected String passwordFile = null;
     protected String accessFile = null;
+    protected boolean useLocalPorts = false;
 
     /**
-     * Get the port on which the RMI server is exported. This is the port that
-     * is normally chosen by the RMI stack.
+     * Get the port on which the Platform RMI server is exported. This is the
+     * port that is normally chosen by the RMI stack.
      * @returns The port number
      */
-    public int getRmiServerPort() {
-        return rmiServerPort;
+    public int getRmiServerPortPlatform() {
+        return rmiServerPortPlatform;
     }
     
     /**
-     * Set the port on which the RMI server is exported. This is the port that
-     * is normally chosen by the RMI stack.
-     * @param theRmiServerPort The port number
+     * Set the port on which the Platform RMI server is exported. This is the
+     * port that is normally chosen by the RMI stack.
+     * @param theRmiServerPortPlatform The port number
      */
-    public void setRmiServerPort(int theRmiServerPort) {
-        rmiServerPort = theRmiServerPort;
+    public void setRmiServerPortPlatform(int theRmiServerPortPlatform) {
+        rmiServerPortPlatform = theRmiServerPortPlatform;
     }
     
     /**
-     * Get the port on which the RMI registry is exported.
+     * Get the port on which the Platform RMI registry is exported.
      * @returns The port number
      */
-    public int getRmiRegistryPort() {
-        return rmiRegistryPort;
+    public int getRmiRegistryPortPlatform() {
+        return rmiRegistryPortPlatform;
     }
     
     /**
-     * Set the port on which the RMI registryis exported.
-     * @param theRmiServerPort The port number
+     * Set the port on which the Platform RMI registry is exported.
+     * @param theRmiRegistryPortPlatform The port number
      */
-    public void setRmiRegistryPort(int theRmiRegistryPort) {
-        rmiRegistryPort = theRmiRegistryPort;
+    public void setRmiRegistryPortPlatform(int theRmiRegistryPortPlatform) {
+        rmiRegistryPortPlatform = theRmiRegistryPortPlatform;
+    }
+    
+    /**
+     * Get the port on which the Catalina RMI server is exported. This is the
+     * port that is normally chosen by the RMI stack.
+     * @returns The port number
+     */
+    public int getRmiServerPortCatalina() {
+        return rmiServerPortCatalina;
+    }
+    
+    /**
+     * Set the port on which the Catalina RMI server is exported. This is the
+     * port that is normally chosen by the RMI stack.
+     * @param theRmiServerPortCatalina The port number
+     */
+    public void setRmiServerPortCatalina(int theRmiServerPortCatalina) {
+        rmiServerPortCatalina = theRmiServerPortCatalina;
+    }
+    
+    /**
+     * Get the port on which the Catalina RMI registry is exported.
+     * @returns The port number
+     */
+    public int getRmiRegistryPortCatalina() {
+        return rmiRegistryPortCatalina;
+    }
+    
+    /**
+     * Set the port on which the Catalina RMI registry is exported.
+     * @param theRmiRegistryPortCatalina The port number
+     */
+    public void setRmiRegistryPortCatalina(int theRmiRegistryPortCatalina) {
+        rmiRegistryPortCatalina = theRmiRegistryPortCatalina;
+    }
+    
+    /**
+     * Get the flag that indicates that local ports should be used for all
+     * connections. If using SSH tunnels, or similar, this should be set to
+     * true to ensure the RMI client uses the tunnel.
+     * @returns <code>true</code> if local ports should be used
+     */
+    public boolean getUseLocalPorts() {
+        return useLocalPorts;
+    }
+    
+    /**
+     * Set the flag that indicates that local ports should be used for all
+     * connections. If using SSH tunnels, or similar, this should be set to
+     * true to ensure the RMI client uses the tunnel.
+     * @param useLocalPorts Set to <code>true</code> if local ports should be
+     *                      used
+     */
+    public void setUseLocalPorts(boolean useLocalPorts) {
+        this.useLocalPorts = useLocalPorts;
     }
     
     private void init() {
@@ -148,60 +211,113 @@
             // Prevent an attacker guessing the RMI object ID
             System.setProperty("java.rmi.server.randomIDs", "true");
 
-            try {
-                LocateRegistry.createRegistry(rmiRegistryPort);
-            } catch (RemoteException e) {
-                log.error(sm.getString(
-                        "jmxRemoteLifecycleListener.createRegistryFailed",
-                        Integer.toString(rmiRegistryPort)), e);
-                return;
-            }
-            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+            // Create the environment
             HashMap<String,Object> env = new HashMap<String,Object>();
-            
+
+            RMIClientSocketFactory csf = null;
+            RMIServerSocketFactory ssf = null;
+
+            // Configure SSL for RMI connection if required
             if (rmiSSL) {
-                // Use SSL for RMI connection
-                SslRMIClientSocketFactory csf =
-                    new SslRMIClientSocketFactory();
-                SslRMIServerSocketFactory ssf =
-                    new SslRMIServerSocketFactory(ciphers, protocols,
+                csf = new SslRMIClientSocketFactory();
+                ssf = new SslRMIServerSocketFactory(ciphers, protocols,
                             clientAuth);
+            }
+            
+            // Force the use of local ports if required
+            if (useLocalPorts) {
+                csf = new RmiClientLocalhostSocketFactory(csf);
+            }
+
+            // Populate the env properties used to create the server
+            if (csf != null) {
                 env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE,
                         csf);
+            }
+            if (ssf != null) {
                 env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
                         ssf);
             }
+
+            // Configure authentication
             if (authenticate) {
                 env.put("jmx.remote.x.password.file", passwordFile);
                 env.put("jmx.remote.x.access.file", accessFile);
             }
-            StringBuffer url = new StringBuffer();
-            url.append("service:jmx:rmi://localhost:");
-            url.append(rmiServerPort);
-            url.append("/jndi/rmi://localhost:");
-            url.append(rmiRegistryPort);
-            url.append("/jmxrmi");
-            JMXServiceURL serviceUrl;
-            try {
-                serviceUrl = new JMXServiceURL(url.toString());
-            } catch (MalformedURLException e) {
-                log.error(sm.getString(
-                        "jmxRemoteLifecycleListener.invalidURL",
-                        url.toString()), e);
-                return;
-            }
-            JMXConnectorServer cs;
-            try {
-                cs = JMXConnectorServerFactory.newJMXConnectorServer(
-                        serviceUrl, env, mbs);
-                cs.start();
-                log.info(sm.getString("jmxRemoteLifecycleListener.start",
-                        new Integer(rmiRegistryPort),
-                        new Integer(rmiServerPort)));
-            } catch (IOException e) {
-                log.error(sm.getString(""), e);
-            }
+
+
+            // Create the Platform server
+            createServer(rmiRegistryPortPlatform, rmiServerPortPlatform, env,
+                    ManagementFactory.getPlatformMBeanServer());
+            
+            // Create the catalina server
+            createServer(rmiRegistryPortCatalina, rmiServerPortCatalina, env,
+                    MBeanUtils.createServer());
+        }
+    }
+
+    private void createServer(int theRmiRegistryPort, int theRmiServerPort,
+            HashMap<String,Object> theEnv, MBeanServer theMBeanServer) {
+        
+        // Create the RMI registry
+        try {
+            LocateRegistry.createRegistry(theRmiRegistryPort);
+        } catch (RemoteException e) {
+            log.error(sm.getString(
+                    "jmxRemoteLifecycleListener.createRegistryFailed",
+                    Integer.toString(theRmiRegistryPort)), e);
+            return;
+        }
+
+        // Build the connection string with fixed ports
+        StringBuffer url = new StringBuffer();
+        url.append("service:jmx:rmi://localhost:");
+        url.append(theRmiServerPort);
+        url.append("/jndi/rmi://localhost:");
+        url.append(theRmiRegistryPort);
+        url.append("/jmxrmi");
+        JMXServiceURL serviceUrl;
+        try {
+            serviceUrl = new JMXServiceURL(url.toString());
+        } catch (MalformedURLException e) {
+            log.error(sm.getString(
+                    "jmxRemoteLifecycleListener.invalidURL",
+                    url.toString()), e);
+            return;
+        }
+        
+        // Start the JMX server with the connection string
+        JMXConnectorServer cs;
+        try {
+            cs = JMXConnectorServerFactory.newJMXConnectorServer(
+                    serviceUrl, theEnv, theMBeanServer);
+            cs.start();
+            log.info(sm.getString("jmxRemoteLifecycleListener.start",
+                    Integer.valueOf(theRmiRegistryPort),
+                    Integer.valueOf(theRmiServerPort)));
+        } catch (IOException e) {
+            log.error(sm.getString(""), e);
         }
     }
 
+    public static class RmiClientLocalhostSocketFactory
+    implements RMIClientSocketFactory, Serializable {
+        private static final String FORCED_HOST = "localhost";
+
+        private RMIClientSocketFactory factory = null;
+        
+        public RmiClientLocalhostSocketFactory(RMIClientSocketFactory 
theFactory) {
+            factory = theFactory;
+        }
+
+        public Socket createSocket(String host, int port) throws IOException {
+            if (factory == null) {
+                return new Socket(FORCED_HOST, port);
+            } else {
+                return factory.createSocket(FORCED_HOST, port);
+            }
+        }
+
+        
+    }
 }

Modified: tomcat/trunk/webapps/docs/config/listeners.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/listeners.xml?rev=700645&r1=700644&r2=700645&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/listeners.xml (original)
+++ tomcat/trunk/webapps/docs/config/listeners.xml Tue Sep 30 17:38:00 2008
@@ -174,14 +174,32 @@
 
     <attributes>
 
-      <attribute name="rmiRegsitryPort" required="true">
-        <p>The port to be used by the JMX/RMI registry. The replaces the use of
-        the <code>com.sun.management.jmxremote.port</code> system propoerty 
that
+      <attribute name="rmiRegsitryPortPlatform" required="true">
+        <p>The port to be used by the JMX/RMI registry for the Platform MBeans.
+        The replaces the use of the
+        <code>com.sun.management.jmxremote.port</code> system property that
         should not be set when using this valve.</p>
       </attribute>
 
-      <attribute name="rmiServerPort" required="true">
-        <p>The port to be used by the JMX/RMI server.</p>
+      <attribute name="rmiServerPortPlatform" required="true">
+        <p>The port to be used by the Platform JMX/RMI server.</p>
+      </attribute>
+
+      <attribute name="rmiRegsitryPortCatalina" required="true">
+        <p>The port to be used by the JMX/RMI registry for the Catalina MBeans.
+        The replaces the use of the
+        <code>com.sun.management.jmxremote.port</code> system property that
+        should not be set when using this valve.</p>
+      </attribute>
+
+      <attribute name="rmiServerPortCatalina" required="true">
+        <p>The port to be used by the Catalina JMX/RMI server.</p>
+      </attribute>
+
+      <attribute name="useLocalPorts" required="false">
+        <p>Should any clients using these ports be forced to use local ports to
+        connect to the the JMX/RMI server. This is useful when tunnelling
+        connections over SSH or similar. Defaults to <code>false</code>.</p>
       </attribute>
 
     </attributes>



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

Reply via email to