1 /*
   2  * Copyright (c) 2006, 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 6376416 6406447
  27  * @summary Test use of generic types in MXBeans (mostly illegal).
  28  * @author Eamonn McManus
  29  * @modules java.management
  30  * @run main GenericTypeTest
  31  */
  32 
  33 import java.lang.reflect.InvocationHandler;
  34 import java.lang.reflect.Method;
  35 import java.lang.reflect.Proxy;
  36 import java.util.*;
  37 import javax.management.*;
  38 
  39 public class GenericTypeTest {
  40     public static class Gen<T> {
  41         public T getThing() {
  42             return null;
  43         }
  44     }
  45 
  46     // Illegal MXBeans:
  47 
  48     public static interface GenTMXBean {
  49         public <T> Gen<T> getFoo();
  50     }
  51 
  52     public static interface GenStringMXBean {
  53         public Gen<String> getFoo();
  54     }
  55 
  56     public static class GenMethod {
  57         public <T> Gen<T> getWhatever() {
  58             return null;
  59         }
  60     }
  61 
  62     public static interface GenMethodMXBean {
  63         public GenMethod getFoo();
  64     }
  65 
  66     public static interface TypeVarMXBean {
  67         public <T> List<T> getFoo();
  68     }
  69 
  70     private static final Class<?>[] illegalMXBeans = {
  71         GenTMXBean.class, GenStringMXBean.class, GenMethodMXBean.class,
  72         TypeVarMXBean.class,
  73     };
  74 
  75     // Legal MXBeans:
  76 
  77 // Not currently supported (see 6406447):
  78 //    public static class ConcreteNoOverride extends Gen<String> {}
  79 //
  80 //    public static interface ConcreteNoOverrideMXBean {
  81 //        public ConcreteNoOverride getFoo();
  82 //    }
  83 
  84     public static class ConcreteOverride extends Gen<String> {
  85         @Override
  86         public String getThing() {
  87             return super.getThing();
  88         }
  89     }
  90 
  91     public static interface ConcreteOverrideMXBean {
  92         public ConcreteOverride getFoo();
  93     }
  94 
  95     private static final Class<?>[] legalMXBeans = {
  96         /*ConcreteNoOverrideMXBean.class,*/ ConcreteOverrideMXBean.class,
  97     };
  98 
  99     private static class NullInvocationHandler implements InvocationHandler {
 100         public Object invoke(Object proxy, Method method, Object[] args)
 101         throws Throwable {
 102             return null;
 103         }
 104     }
 105     private static final InvocationHandler nullInvocationHandler =
 106             new NullInvocationHandler();
 107 
 108     private static <T> T makeNullMXBean(Class<T> intf) throws Exception {
 109         return intf.cast(Proxy.newProxyInstance(intf.getClassLoader(),
 110                 new Class<?>[] {intf},
 111                 nullInvocationHandler));
 112     }
 113 
 114     private static String failure;
 115 
 116     public static void main(String[] args) throws Exception {
 117         MBeanServer mbs = MBeanServerFactory.newMBeanServer();
 118         for (boolean legal : new boolean[] {false, true}) {
 119             Class<?>[] intfs = legal ? legalMXBeans : illegalMXBeans;
 120             for (Class<?> intf : intfs) {
 121                 String intfName = intf.getName();
 122                 System.out.println("Testing " + intfName);
 123                 Object mxbean = makeNullMXBean(intf);
 124                 ObjectName name = new ObjectName("test:type=" + intfName);
 125                 try {
 126                     mbs.registerMBean(mxbean, name);
 127                     if (!legal)
 128                         fail("Registering " + intfName + " should not succeed");
 129                 } catch (NotCompliantMBeanException e) {
 130                     if (legal)
 131                         failX("Registering " + intfName + " should succeed", e);
 132                 } catch (Exception e) {
 133                     if (legal)
 134                         failX("Registering " + intfName + " should succeed", e);
 135                     else {
 136                         failX("Registering " + intfName + " should produce " +
 137                                 "NotCompliantMBeanException", e);
 138                     }
 139                 }
 140             }
 141         }
 142         if (failure != null)
 143             throw new Exception("TEST FAILED: " + failure);
 144         System.out.println("Test passed");
 145     }
 146 
 147     private static void fail(String msg) {
 148         System.out.println("FAILED: " + msg);
 149         failure = msg;
 150     }
 151 
 152     private static void failX(String msg, Throwable x) {
 153         fail(msg + ": " + x);
 154         x.printStackTrace(System.out);
 155     }
 156 }