You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/18 17:03:59 UTC

[50/64] [abbrv] incubator-brooklyn git commit: BROOKLYN-162 - apply org.apache package prefix to jmx util/agent projects

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxrmi-agent/src/main/java/org/apache/brooklyn/util/jmx/jmxrmi/JmxRmiAgent.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxrmi-agent/src/main/java/org/apache/brooklyn/util/jmx/jmxrmi/JmxRmiAgent.java b/utils/jmx/jmxrmi-agent/src/main/java/org/apache/brooklyn/util/jmx/jmxrmi/JmxRmiAgent.java
new file mode 100644
index 0000000..6aa35d3
--- /dev/null
+++ b/utils/jmx/jmxrmi-agent/src/main/java/org/apache/brooklyn/util/jmx/jmxrmi/JmxRmiAgent.java
@@ -0,0 +1,190 @@
+/*
+ * 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.brooklyn.util.jmx.jmxrmi;
+
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.rmi.registry.LocateRegistry;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.management.MBeanServer;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+import org.apache.brooklyn.util.jmx.jmxrmi.JmxRmiAgent;
+
+/**
+ * This exposes JMX support for going through firewalls by starting an RMI registry server
+ * on a well-known port.
+ * <p>
+ * This implementation DOES NOT support port-forwarding however. The same hostname used internally
+ * (specified in {@link #RMI_HOSTNAME_PROPERTY} or autodetected by java) must also be addressable
+ * by the JMX client. This is due to how the property is used internally by java during the 
+ * RMI registry re-direction.
+ * <p>
+ * If you require that the client connects to a different hostname/IP than the one where the
+ * service is bound, consider using the Brooklyn JmxmpAgent, as this will not work!
+ * <p>
+ * This listens on {@value #RMI_REGISTRY_PORT_PROPERTY} unless overridden by system property 
+ * {@link #RMI_REGISTRY_PORT_PROPERTY} ({@value #RMI_REGISTRY_PORT_PROPERTY}).
+ *
+ * @see brooklyn.util.jmx.jmxmp.JmxmpAgent
+ * @see https://blogs.oracle.com/jmxetc/entry/connecting_through_firewall_using_jmx
+ * @see https://blogs.oracle.com/jmxetc/entry/more_on_premain_and_jmx
+ */
+public class JmxRmiAgent {
+
+    /** Port for RMI registry to listen on. Default to {@link #RMI_REGISTRY_DEFAULT_PORT}. */
+    public static final String RMI_REGISTRY_PORT_PROPERTY = "brooklyn.jmx-agent.rmi-port";
+    public static final String RMI_REGISTRY_DEFAULT_PORT = "9001";
+
+    /** Port for JMX server (sometimes called JMX_RMI server) to listen on. Default to {@link #JMX_SERVER_DEFAULT_PORT}. */
+    public static final String JMX_SERVER_PORT_PROPERTY = "brooklyn.jmx-agent.jmx-port";
+    public static final String JMX_SERVER_DEFAULT_PORT = "11099";
+
+    /** Hostname to advertise, and if {@value #JMX_SERVER_ADDRESS_WILDCARD_PROPERTY} is false also the hostname/interface to bind to. 
+     *  Should never be 0.0.0.0 as it is publicly advertised. */
+    public static final String RMI_HOSTNAME_PROPERTY = "java.rmi.server.hostname";
+
+    /** Whether JMX should bind to all interfaces. */
+    public static final String JMX_SERVER_ADDRESS_WILDCARD_PROPERTY = "jmx.remote.server.address.wildcard";
+
+    /**
+     * The entry point, uses the JDK dynamic agent loading feature.
+     */
+    public static void premain(String agentArgs) {
+        doMain(agentArgs);
+    }
+    
+    public static void agentmain(String agentArgs) {
+        doMain(agentArgs);
+    }
+    
+    public static void doMain(final String agentArgs) {
+        // taken from JmxmpAgent in sister project
+        
+        // do the work in a daemon thread so that if the main class terminates abnormally,
+        // such that shutdown hooks aren't called, we don't keep the application running
+        // (e.g. if the app is compiled with java7 then run with java6, with a java6 agent here;
+        // that causes the agent to launch, the main to fail, but the process to keep going)
+        Thread t = new Thread() {
+            public void run() {
+                doMainForeground(agentArgs);
+            }
+        };
+        t.setDaemon(true);
+        t.start();
+    }
+
+    public static void doMainForeground(String agentArgs) {
+        final JMXConnectorServer connector = new JmxRmiAgent().startServer(System.getProperties());
+        if (connector != null) {
+            Runtime.getRuntime().addShutdownHook(new Thread("jmxrmi-agent-shutdownHookThread") {
+                @Override public void run() {
+                    try {
+                        connector.stop();
+                    } catch (Exception e) {
+                        System.err.println("Error closing jmxrmi connector in shutdown hook (continuing): "+e);
+                    }
+                }});
+        }
+    }
+
+    public JMXConnectorServer startServer(Properties properties) {
+        try {
+            // Ensure cryptographically strong random number generator used
+            // to choose the object number - see java.rmi.server.ObjID
+            System.setProperty("java.rmi.server.randomIDs", "true");
+
+            // Start an RMI registry on port specified
+            final int rmiPort = Integer.parseInt(System.getProperty(RMI_REGISTRY_PORT_PROPERTY, RMI_REGISTRY_DEFAULT_PORT));
+            final int jmxPort = Integer.parseInt(System.getProperty(JMX_SERVER_PORT_PROPERTY, JMX_SERVER_DEFAULT_PORT));
+            final String hostname = getLocalhostHostname(properties);
+            
+            System.out.println("Setting up JmxRmiAgent for: "+hostname+" "+rmiPort+" / "+jmxPort);
+            
+            LocateRegistry.createRegistry(rmiPort);
+
+            // Retrieve the PlatformMBeanServer.
+            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+            // Environment map.
+            Map<String, Object> env = new LinkedHashMap<String, Object>();
+            propagate(properties, env, JMX_SERVER_ADDRESS_WILDCARD_PROPERTY, "true");
+
+            // TODO Security
+
+            // Create an RMI connector server.
+            JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://" + hostname + ":" + jmxPort + "/jndi/rmi://" + hostname + ":" + rmiPort + "/jmxrmi");
+
+            // Now create the server from the JMXServiceURL
+            JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+
+            // Start the RMI connector server.
+            connector.start();
+            System.out.println("JmxRmiAgent JMXConnectorServer active at: " + url);
+
+            return connector;
+        } catch (RuntimeException e) {
+            System.err.println("Unable to start JMXConnectorServer: " + e);
+            throw e;
+        } catch (Exception e) {
+            System.err.println("Unable to start JMXConnectorServer: " + e);
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Copies the value of key from the source to the target, if set. Otherwise
+     * sets the {@code defaultValueIfNotNull} if that is not null.
+     * 
+     * @return whether anything is set
+     */
+    private static boolean propagate(Properties source, Map<String, Object> target, String key, Object defaultValueIfNotNull) {
+        Object v = source.getProperty(key);
+        if (v == null) v = defaultValueIfNotNull;
+        if (v == null) return false;
+        target.put(key, v);
+        return true;
+    }
+
+    private String getLocalhostHostname(Properties properties) throws UnknownHostException {
+        String hostname = properties == null ? null : properties.getProperty(RMI_HOSTNAME_PROPERTY);
+        if ("0.0.0.0".equals(hostname)) {
+            System.err.println("WARN: invalid hostname 0.0.0.0 specified for JmxRmiAgent; " +
+                    "it typically must be an address or hostname which is bindable on the machine where " +
+                    "this service is running AND accessible by a client machine (access will likely be impossible)");
+        }
+        if (hostname == null || hostname.isEmpty()) {
+            hostname = InetAddress.getLocalHost().getHostName();
+        }
+        return hostname;
+    }
+
+    /**
+     * Convenience main method.
+     */
+    public static void main(String[] args) throws Exception {
+        premain("");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxrmi-agent/src/test/java/brooklyn/util/jmx/jmxrmi/JmxRmiClient.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxrmi-agent/src/test/java/brooklyn/util/jmx/jmxrmi/JmxRmiClient.java b/utils/jmx/jmxrmi-agent/src/test/java/brooklyn/util/jmx/jmxrmi/JmxRmiClient.java
deleted file mode 100644
index 577d352..0000000
--- a/utils/jmx/jmxrmi-agent/src/test/java/brooklyn/util/jmx/jmxrmi/JmxRmiClient.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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 brooklyn.util.jmx.jmxrmi;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.Map;
-
-import javax.management.MBeanServerConnection;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXConnectorFactory;
-import javax.management.remote.JMXServiceURL;
-
-@SuppressWarnings({"rawtypes","unchecked"})
-public class JmxRmiClient {
-
-    public void connect(String urlString, Map env) throws MalformedURLException, IOException {
-        JMXServiceURL url = new JMXServiceURL(urlString);
-        System.out.println("JmxmpClient connecting to "+url);
-        JMXConnector jmxc = JMXConnectorFactory.connect(url, env); 
-        
-        MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); 
-        String domains[] = mbsc.getDomains(); 
-        for (int i = 0; i < domains.length; i++) { 
-            System.out.println("Domain[" + i + "] = " + domains[i]); 
-        } 
-
-        jmxc.close();
-    } 
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxrmi-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxrmi/JmxRmiClient.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxrmi-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxrmi/JmxRmiClient.java b/utils/jmx/jmxrmi-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxrmi/JmxRmiClient.java
new file mode 100644
index 0000000..29b5de7
--- /dev/null
+++ b/utils/jmx/jmxrmi-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxrmi/JmxRmiClient.java
@@ -0,0 +1,47 @@
+/*
+ * 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.brooklyn.util.jmx.jmxrmi;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Map;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+@SuppressWarnings({"rawtypes","unchecked"})
+public class JmxRmiClient {
+
+    public void connect(String urlString, Map env) throws MalformedURLException, IOException {
+        JMXServiceURL url = new JMXServiceURL(urlString);
+        System.out.println("JmxmpClient connecting to "+url);
+        JMXConnector jmxc = JMXConnectorFactory.connect(url, env); 
+        
+        MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); 
+        String domains[] = mbsc.getDomains(); 
+        for (int i = 0; i < domains.length; i++) { 
+            System.out.println("Domain[" + i + "] = " + domains[i]); 
+        } 
+
+        jmxc.close();
+    } 
+
+}