1/*
2 * Copyright (c) 2005, 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 6337061
27 * @summary Test that  ModelMBeanInfoSupport.getDescriptors(null) also
28 *          returns the MBean's descriptor.
29 * @author Eamonn McManus, Daniel Fuchs
30 *
31 * @run clean GetAllDescriptorsTest
32 * @run build GetAllDescriptorsTest
33 * @run main/othervm/java.security.policy=policy  GetAllDescriptorsTest
34 */
35
36import java.lang.reflect.*;
37import java.util.*;
38import javax.management.*;
39import javax.management.modelmbean.*;
40
41public class GetAllDescriptorsTest {
42
43    public static class Resource {
44        public int getNumber() {
45            return number;
46        }
47
48        public void setNumber(int n) {
49            number = n;
50        }
51
52        public int addOne(int x) {
53            return x + 1;
54        }
55
56        public Object[] getArray() {
57            return (Object[]) array.clone();
58        }
59
60        // doesn't look like an attribute so not seen by caching logic
61        public void tweakArray(Object[] array) {
62            this.array = (Object[]) array.clone();
63        }
64
65        private int number = 1234;
66        private Object[] array = {"hello", "world"};
67    }
68
69    public static void main(String[] args) {
70        int errorCount = 0;
71        for (int i = 0; i < NTESTS; i++) {
72            try {
73                System.out.println("Test " + i + ":");
74                test(i);
75            } catch (Throwable e) {
76                errorCount++;
77                boolean first = true;
78                do {
79                    System.err.println(first ? "Exception:" : "Caused by:");
80                    first = false;
81                    e.printStackTrace();
82                    Throwable nexte;
83                    nexte = e.getCause();
84                    if (nexte == null) { // old JMX
85                        if (e instanceof MBeanException)
86                            nexte = ((MBeanException) e).getTargetException();
87                    }
88                    e = nexte;
89                } while (e != null);
90            }
91        }
92        if (errorCount == 0) {
93            System.out.println("All ModelMBean tests successfuly passed");
94            System.out.println("Bye! Bye!");
95            // JTReg doesn't like System.exit(0);
96            return;
97        } else {
98            System.err.println("ERROR: " + errorCount + " tests failed");
99            System.exit(errorCount);
100        }
101
102    }
103
104    private static void test(int testno) throws Exception {
105        // com.sun.jmx.trace.TraceImplementation.init(2);
106        Resource resource = new Resource();
107        Class resourceClass = Resource.class;
108        Class rmmbClass = RequiredModelMBean.class;
109        Method setManagedResource =
110            rmmbClass.getMethod("setManagedResource",
111                                new Class[] {Object.class,
112                                             String.class});
113        Method sendNotification =
114            rmmbClass.getMethod("sendNotification",
115                                new Class[] {Notification.class});
116        Method addAttributeChangeNL =
117            rmmbClass.getMethod("addAttributeChangeNotificationListener",
118                                new Class[] {NotificationListener.class,
119                                             String.class,
120                                             Object.class});
121        Method getArray = resourceClass.getMethod("getArray", new Class[0]);
122        Method getNumber = resourceClass.getMethod("getNumber", new Class[0]);
123        Method setNumber =
124            resourceClass.getMethod("setNumber", new Class[] {Integer.TYPE});
125        Method tweakArray =
126            resourceClass.getMethod("tweakArray",
127                                    new Class[] {Object[].class});
128        Method addOne =
129            resourceClass.getMethod("addOne", new Class[] {Integer.TYPE});
130        MBeanServer mbs = MBeanServerFactory.newMBeanServer();
131        ObjectName on = new ObjectName("a:b=c");
132        Descriptor attrDescr = new DescriptorSupport();
133        attrDescr.setField("name", "Array");
134        attrDescr.setField("descriptorType", "attribute");
135        attrDescr.setField("getMethod", "getArray");
136        ModelMBeanAttributeInfo attrInfo =
137            new ModelMBeanAttributeInfo("Array", "array attr", getArray,
138                                        null, attrDescr);
139        Descriptor attrDescr2 = new DescriptorSupport();
140        attrDescr2.setField("name", "Number");
141        attrDescr2.setField("descriptorType", "attribute");
142        attrDescr2.setField("getMethod", "getNumber");
143        attrDescr2.setField("setMethod", "setNumber");
144        ModelMBeanAttributeInfo attrInfo2 =
145            new ModelMBeanAttributeInfo("Number", "number attr", getNumber,
146                                        setNumber, attrDescr2);
147        Descriptor attrDescr3 = new DescriptorSupport();
148        attrDescr3.setField("name", "Local");
149        attrDescr3.setField("descriptorType", "attribute");
150        attrDescr3.setField("currencyTimeLimit", "" + Integer.MAX_VALUE);
151        ModelMBeanAttributeInfo attrInfo3 =
152            new ModelMBeanAttributeInfo("Local", "java.lang.String",
153                                        "local attr", true, true, false,
154                                        attrDescr3);
155        Descriptor attrDescr4 = new DescriptorSupport();
156        attrDescr4.setField("name", "Local2");
157        attrDescr4.setField("descriptorType", "attribute");
158        ModelMBeanAttributeInfo attrInfo4 =
159            new ModelMBeanAttributeInfo("Local2", "java.lang.String",
160                                        "local attr 2", true, true, false,
161                                        attrDescr4);
162        ModelMBeanAttributeInfo[] attrs =
163            new ModelMBeanAttributeInfo[] {attrInfo, attrInfo2, attrInfo3,
164                                           attrInfo4};
165        ModelMBeanOperationInfo operInfo =
166            new ModelMBeanOperationInfo("getArray descr", getArray);
167        ModelMBeanOperationInfo operInfo2 =
168            new ModelMBeanOperationInfo("getNumber descr", getNumber);
169        ModelMBeanOperationInfo operInfo3 =
170            new ModelMBeanOperationInfo("addOne descr", addOne);
171        ModelMBeanOperationInfo operInfo4 =
172            new ModelMBeanOperationInfo("setNumber descr", setNumber);
173        ModelMBeanOperationInfo operInfo5 =
174            new ModelMBeanOperationInfo("tweakArray descr", tweakArray);
175        ModelMBeanOperationInfo operInfoSetManagedResource =
176            new ModelMBeanOperationInfo("setManagedResource descr",
177                                        setManagedResource);
178        ModelMBeanOperationInfo operInfoSendNotification =
179            new ModelMBeanOperationInfo("sendNotification descr",
180                                        sendNotification);
181        ModelMBeanOperationInfo operInfoAddAttributeChangeNL =
182            new ModelMBeanOperationInfo("AddAttributeChangeNL descr",
183                                        addAttributeChangeNL);
184        ModelMBeanOperationInfo[] opers =
185            new ModelMBeanOperationInfo[] {operInfo, operInfo2, operInfo3,
186                                           operInfo4, operInfo5,
187                                           operInfoSetManagedResource,
188                                           operInfoSendNotification,
189                                           operInfoAddAttributeChangeNL};
190        ModelMBeanInfo info =
191            new ModelMBeanInfoSupport(Resource.class.getName(),
192                                      "Resourcish resource",
193                                      attrs, null, opers, null,
194                                      null);
195        mbs.createMBean(RequiredModelMBean.class.getName(),
196                        on,
197                        new Object[] {info},
198                        new String[] {ModelMBeanInfo.class.getName()});
199        mbs.invoke(on, "setManagedResource",
200                   new Object[] {resource, "objectReference"},
201                   new String[] {"java.lang.Object", "java.lang.String"});
202        switch (testno) {
203        case 0: {
204            /* Check  getDescriptors("") on original MBeanInfo */
205            final Descriptor[] desc = info.getDescriptors("");
206            checkDescriptors(info,desc,"info.getDescriptors(\"\")");
207            break;
208        }
209        case 1: {
210            /* Check  getDescriptors(null) on original MBeanInfo */
211            final Descriptor[] desc = info.getDescriptors(null);
212            checkDescriptors(info,desc,"info.getDescriptors(null)");
213            break;
214        }
215        case 2: {
216            /* Check  getDescriptors("") on retrieved MBeanInfo */
217            final MBeanInfo mbi = mbs.getMBeanInfo(on);
218            final ModelMBeanInfo model = (ModelMBeanInfo)mbi;
219            final Descriptor[] desc = model.getDescriptors("");
220            checkDescriptors(info,desc,"model.getDescriptors(\"\")");
221            break;
222        }
223        case 3: {
224            /* Check  getDescriptors(null) on retrieved MBeanInfo */
225            final MBeanInfo mbi = mbs.getMBeanInfo(on);
226            final ModelMBeanInfo model = (ModelMBeanInfo)mbi;
227            final Descriptor[] desc = model.getDescriptors(null);
228            checkDescriptors(info,desc,"model.getDescriptors(null)");
229            break;
230        }
231        default:
232            System.err.println("UNKNOWN TEST NUMBER " + testno);
233            break;
234        }
235    }
236
237    /* Removes descriptor from the list and returns it. Returns {@code null}
238       if descriptor is not found */
239    private static Descriptor remove(ArrayList<Descriptor> list,
240            Descriptor item) {
241        if (list.remove(item)) return item;
242        else return null;
243    }
244
245    /* Check that all descriptors have been returned */
246    private static void checkDescriptors(ModelMBeanInfo modelMBeanInfo,
247            Descriptor[] descriptors, String string) {
248        int errCount = 0;
249        final ArrayList<Descriptor> list =
250                new ArrayList<Descriptor>(descriptors.length);
251        list.addAll(Arrays.asList(descriptors));
252        System.out.println("Got " + list.size() + " descriptors for "+string);
253
254        // checks that MBean's descriptor is returned.
255        //
256        final Descriptor mbd = ((MBeanInfo)modelMBeanInfo).getDescriptor();
257        if (!mbd.equals(remove(list,mbd))) {
258            System.err.println("modelMBeanInfo.getDescriptor(): not found");
259            errCount++;
260        }
261
262        // checks that MBean's attributes descriptors are returned.
263        //
264        final MBeanAttributeInfo[] attrs = modelMBeanInfo.getAttributes();
265        for (MBeanAttributeInfo att : attrs) {
266            final Descriptor ad = att.getDescriptor();
267            final String name = att.getName();
268            if (!ad.equals(remove(list,ad))) {
269                System.err.println("attInfo.getDescriptor(): not found for "+
270                        name);
271                errCount++;
272            }
273        }
274
275        // checks that MBean's operations descriptors are returned.
276        //
277        final MBeanOperationInfo[] ops = modelMBeanInfo.getOperations();
278        for (MBeanOperationInfo op : ops) {
279            final Descriptor od = op.getDescriptor();
280            final String name = op.getName();
281            if (!od.equals(remove(list,od))) {
282                System.err.println("opInfo.getDescriptor(): not found for "+
283                        name);
284                errCount++;
285            }
286        }
287
288        // checks that MBean's notifications descriptors are returned.
289        //
290        final MBeanNotificationInfo[] ntfs = modelMBeanInfo.getNotifications();
291        for (MBeanNotificationInfo ntf : ntfs) {
292            final Descriptor nd = ntf.getDescriptor();
293            final String name = ntf.getName();
294            if (!nd.equals(remove(list,nd))) {
295                System.err.println("notifInfo.getDescriptor(): not found for "+
296                        name);
297                errCount++;
298            }
299        }
300        if (errCount > 0) {
301            throw new RuntimeException(string+": failed with "+errCount+
302                    " errors");
303        } else if (list.size() != 0) {
304            // Check that there are no additional descriptors
305            //
306            throw new RuntimeException(string+
307                    ": Unexpected remaining descriptors: "+list);
308        } else System.out.println(string+": PASSED");
309    }
310
311    private static final int NTESTS = 4;
312
313}
314