jdk/test/javax/management/remote/mandatory/connection/ConnectionTest.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2003 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  * @test
       
    26  * @bug 4865397
       
    27  * @summary Tests remote JMX connections
       
    28  * @author Eamonn McManus
       
    29  * @run clean ConnectionTest
       
    30  * @run build ConnectionTest
       
    31  * @run main ConnectionTest
       
    32  */
       
    33 
       
    34 import java.io.IOException;
       
    35 import java.net.MalformedURLException;
       
    36 import java.util.Collections;
       
    37 import java.util.HashMap;
       
    38 import java.util.HashSet;
       
    39 import java.util.Iterator;
       
    40 import java.util.LinkedList;
       
    41 import java.util.List;
       
    42 import java.util.Map;
       
    43 import java.util.Set;
       
    44 import java.util.StringTokenizer;
       
    45 
       
    46 import java.security.Principal;
       
    47 import javax.security.auth.Subject;
       
    48 
       
    49 import javax.management.MBeanServer;
       
    50 import javax.management.MBeanServerConnection;
       
    51 import javax.management.MBeanServerFactory;
       
    52 import javax.management.Notification;
       
    53 import javax.management.NotificationListener;
       
    54 import javax.management.ObjectName;
       
    55 
       
    56 import javax.management.remote.JMXAuthenticator;
       
    57 import javax.management.remote.JMXConnectionNotification;
       
    58 import javax.management.remote.JMXConnector;
       
    59 import javax.management.remote.JMXConnectorFactory;
       
    60 import javax.management.remote.JMXConnectorServer;
       
    61 import javax.management.remote.JMXConnectorServerFactory;
       
    62 import javax.management.remote.JMXPrincipal;
       
    63 import javax.management.remote.JMXServiceURL;
       
    64 
       
    65 public class ConnectionTest {
       
    66 
       
    67     public static void main(String[] args) {
       
    68 //      System.setProperty("java.util.logging.config.file",
       
    69 //                         "../../../../logging.properties");
       
    70 //      // we are in <workspace>/build/test/JTwork/scratch
       
    71 //      java.util.logging.LogManager.getLogManager().readConfiguration();
       
    72         boolean ok = true;
       
    73         String[] protocols = {"rmi", "iiop", "jmxmp"};
       
    74         if (args.length > 0)
       
    75             protocols = args;
       
    76         for (int i = 0; i < protocols.length; i++) {
       
    77             final String proto = protocols[i];
       
    78             System.out.println("Testing for protocol " + proto);
       
    79             try {
       
    80                 ok &= test(proto);
       
    81             } catch (Exception e) {
       
    82                 System.err.println("Unexpected exception: " + e);
       
    83                 e.printStackTrace();
       
    84                 ok = false;
       
    85             }
       
    86         }
       
    87 
       
    88         if (ok)
       
    89             System.out.println("Test passed");
       
    90         else {
       
    91             System.out.println("TEST FAILED");
       
    92             System.exit(1);
       
    93         }
       
    94     }
       
    95 
       
    96     private static boolean test(String proto) throws Exception {
       
    97         ObjectName serverName = ObjectName.getInstance("d:type=server");
       
    98         MBeanServer mbs = MBeanServerFactory.newMBeanServer();
       
    99         JMXAuthenticator authenticator = new BogusAuthenticator();
       
   100         Map env = Collections.singletonMap("jmx.remote.authenticator",
       
   101                                            authenticator);
       
   102         JMXServiceURL url = new JMXServiceURL("service:jmx:" + proto + "://");
       
   103         JMXConnectorServer server;
       
   104         try {
       
   105             server =
       
   106                 JMXConnectorServerFactory.newJMXConnectorServer(url, env,
       
   107                                                                 null);
       
   108         } catch (MalformedURLException e) {
       
   109             System.out.println("Protocol " + proto +
       
   110                                " not supported, ignoring");
       
   111             return true;
       
   112         }
       
   113         System.out.println("Created connector server");
       
   114         mbs.registerMBean(server, serverName);
       
   115         System.out.println("Registered connector server in MBean server");
       
   116         mbs.addNotificationListener(serverName, logListener, null, null);
       
   117         mbs.invoke(serverName, "start", null, null);
       
   118         System.out.println("Started connector server");
       
   119         JMXServiceURL address =
       
   120             (JMXServiceURL) mbs.getAttribute(serverName, "Address");
       
   121         System.out.println("Retrieved address: " + address);
       
   122 
       
   123         if (address.getHost().length() == 0) {
       
   124             System.out.println("Generated address has empty hostname");
       
   125             return false;
       
   126         }
       
   127 
       
   128         JMXConnector client = JMXConnectorFactory.connect(address);
       
   129         System.out.println("Client connected");
       
   130 
       
   131         String clientConnId = client.getConnectionId();
       
   132         System.out.println("Got connection ID on client: " + clientConnId);
       
   133         boolean ok = checkConnectionId(proto, clientConnId);
       
   134         if (!ok)
       
   135             return false;
       
   136         System.out.println("Connection ID is OK");
       
   137 
       
   138         // 4901826: connection ids need some time to be updated using jmxmp
       
   139         // we don't get the notif immediately either
       
   140         // this was originally timeout 1ms, which was not enough
       
   141         Notification notif = waitForNotification(1000);
       
   142         System.out.println("Server got notification: " + notif);
       
   143 
       
   144         ok = mustBeConnectionNotification(notif, clientConnId,
       
   145                                          JMXConnectionNotification.OPENED);
       
   146         if (!ok)
       
   147             return false;
       
   148 
       
   149         client.close();
       
   150         System.out.println("Closed client");
       
   151 
       
   152         notif = waitForNotification(1000);
       
   153         System.out.println("Got notification: " + notif);
       
   154 
       
   155         ok = mustBeConnectionNotification(notif, clientConnId,
       
   156                                           JMXConnectionNotification.CLOSED);
       
   157         if (!ok)
       
   158             return false;
       
   159 
       
   160         client = JMXConnectorFactory.connect(address);
       
   161         System.out.println("Second client connected");
       
   162 
       
   163         String clientConnId2 = client.getConnectionId();
       
   164         if (clientConnId.equals(clientConnId2)) {
       
   165             System.out.println("Same connection ID for two connections: " +
       
   166                                clientConnId2);
       
   167             return false;
       
   168         }
       
   169         System.out.println("Second client connection ID is different");
       
   170 
       
   171         notif = waitForNotification(1);
       
   172         ok = mustBeConnectionNotification(notif, clientConnId2,
       
   173                                           JMXConnectionNotification.OPENED);
       
   174         if (!ok)
       
   175             return false;
       
   176 
       
   177         MBeanServerConnection mbsc = client.getMBeanServerConnection();
       
   178         Map attrs = (Map) mbsc.getAttribute(serverName, "Attributes");
       
   179         System.out.println("Server attributes received by client: " + attrs);
       
   180 
       
   181         server.stop();
       
   182         System.out.println("Server stopped");
       
   183 
       
   184         notif = waitForNotification(1000);
       
   185         System.out.println("Server got connection-closed notification: " +
       
   186                            notif);
       
   187 
       
   188         ok = mustBeConnectionNotification(notif, clientConnId2,
       
   189                                           JMXConnectionNotification.CLOSED);
       
   190         if (!ok)
       
   191             return false;
       
   192 
       
   193         try {
       
   194             mbsc.getDefaultDomain();
       
   195             System.out.println("Connection still working but should not be");
       
   196             return false;
       
   197         } catch (IOException e) {
       
   198             System.out.println("Connection correctly got exception: " + e);
       
   199         }
       
   200 
       
   201         try {
       
   202             client = JMXConnectorFactory.connect(address);
       
   203             System.out.println("Connector server still working but should " +
       
   204                                "not be");
       
   205             return false;
       
   206         } catch (IOException e) {
       
   207             System.out.println("New connection correctly got exception: " + e);
       
   208         }
       
   209 
       
   210         return true;
       
   211     }
       
   212 
       
   213     private static boolean
       
   214         mustBeConnectionNotification(Notification notif,
       
   215                                      String requiredConnId,
       
   216                                      String requiredType) {
       
   217 
       
   218         if (!(notif instanceof JMXConnectionNotification)) {
       
   219             System.out.println("Should have been a " +
       
   220                                "JMXConnectionNotification: " +
       
   221                                notif.getClass());
       
   222             return false;
       
   223         }
       
   224 
       
   225         JMXConnectionNotification cnotif = (JMXConnectionNotification) notif;
       
   226         if (!cnotif.getType().equals(requiredType)) {
       
   227             System.out.println("Wrong type notif: is \"" + cnotif.getType() +
       
   228                                "\", should be \"" + requiredType + "\"");
       
   229             return false;
       
   230         }
       
   231 
       
   232         if (!cnotif.getConnectionId().equals(requiredConnId)) {
       
   233             System.out.println("Wrong connection id: is \"" +
       
   234                                cnotif.getConnectionId() + "\", should be \"" +
       
   235                                requiredConnId);
       
   236             return false;
       
   237         }
       
   238 
       
   239         return true;
       
   240     }
       
   241 
       
   242     private static boolean checkConnectionId(String proto, String clientConnId)
       
   243             throws Exception {
       
   244         StringTokenizer tok = new StringTokenizer(clientConnId, " ", true);
       
   245         String s;
       
   246         s = tok.nextToken();
       
   247         if (!s.startsWith(proto + ":")) {
       
   248             System.out.println("Expected \"" + proto + ":\", found \"" + s +
       
   249                                "\"");
       
   250             return false;
       
   251         }
       
   252         s = tok.nextToken();
       
   253         if (!s.equals(" ")) {
       
   254             System.out.println("Expected \" \", found \"" + s + "\"");
       
   255             return false;
       
   256         }
       
   257         s = tok.nextToken();
       
   258         StringTokenizer tok2 = new StringTokenizer(s, ";", true);
       
   259         Set principalNames = new HashSet();
       
   260         String s2;
       
   261         s2 = tok2.nextToken();
       
   262         if (s2.equals(";")) {
       
   263             System.out.println("In identity \"" + s +
       
   264                                "\", expected name, found \";\"");
       
   265             return false;
       
   266         }
       
   267         principalNames.add(s2);
       
   268         s2 = tok2.nextToken();
       
   269         if (!s2.equals(";"))
       
   270             throw new Exception("Can't happen");
       
   271         s2 = tok2.nextToken();
       
   272         if (s2.equals(";")) {
       
   273             System.out.println("In identity \"" + s +
       
   274                                "\", expected name, found \";\"");
       
   275             return false;
       
   276         }
       
   277         principalNames.add(s2);
       
   278         if (tok2.hasMoreTokens()) {
       
   279             System.out.println("In identity \"" + s + "\", too many tokens");
       
   280             return false;
       
   281         }
       
   282         if (principalNames.size() != bogusPrincipals.size()) {
       
   283             System.out.println("Wrong number of principal names: " +
       
   284                                principalNames.size() + " != " +
       
   285                                bogusPrincipals.size());
       
   286             return false;
       
   287         }
       
   288         for (Iterator it = bogusPrincipals.iterator(); it.hasNext(); ) {
       
   289             Principal p = (Principal) it.next();
       
   290             if (!principalNames.contains(p.getName())) {
       
   291                 System.out.println("Principal names don't contain \"" +
       
   292                                    p.getName() + "\"");
       
   293                 return false;
       
   294             }
       
   295         }
       
   296         s = tok.nextToken();
       
   297         if (!s.equals(" ")) {
       
   298             System.out.println("Expected \" \", found \"" + s + "\"");
       
   299             return false;
       
   300         }
       
   301         return true;
       
   302     }
       
   303 
       
   304     private static Notification waitForNotification(long timeout)
       
   305             throws InterruptedException {
       
   306         synchronized (log) {
       
   307             if (log.isEmpty()) {
       
   308                 long remainingTime = timeout;
       
   309                 final long startTime = System.currentTimeMillis();
       
   310 
       
   311                 while (log.isEmpty() && remainingTime >0) {
       
   312                     log.wait(remainingTime);
       
   313                     remainingTime = timeout - (System.currentTimeMillis() - startTime);
       
   314                 }
       
   315 
       
   316                 if (log.isEmpty()) {
       
   317                     throw new InterruptedException("Timed out waiting for " +
       
   318                                                    "notification!");
       
   319                 }
       
   320             }
       
   321             return (Notification) log.remove(0);
       
   322         }
       
   323     }
       
   324 
       
   325     private static class LogListener implements NotificationListener {
       
   326         LogListener(List log) {
       
   327             this.log = log;
       
   328         }
       
   329 
       
   330         public void handleNotification(Notification n, Object h) {
       
   331             synchronized (log) {
       
   332                 log.add(n);
       
   333                 log.notifyAll();
       
   334             }
       
   335         }
       
   336 
       
   337         private final List log;
       
   338     }
       
   339 
       
   340     private static List log = new LinkedList();
       
   341     private static NotificationListener logListener = new LogListener(log);
       
   342 
       
   343     private static class BogusAuthenticator implements JMXAuthenticator {
       
   344         public Subject authenticate(Object credentials) {
       
   345             Subject subject =
       
   346                 new Subject(true, bogusPrincipals,
       
   347                             Collections.EMPTY_SET, Collections.EMPTY_SET);
       
   348             System.out.println("Authenticator returns: " + subject);
       
   349             return subject;
       
   350         }
       
   351     }
       
   352 
       
   353     private static final Set bogusPrincipals = new HashSet();
       
   354     static {
       
   355         bogusPrincipals.add(new JMXPrincipal("foo"));
       
   356         bogusPrincipals.add(new JMXPrincipal("bar"));
       
   357     }
       
   358 }