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