1/*
2 * Copyright (c) 2004, 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 5035217 6766173
27 * @summary Test that MBean's RuntimeException is wrapped in
28 * RuntimeMBeanException and (for Standard MBeans) that checked exceptions
29 * are wrapped in MBeanException
30 * @author Eamonn McManus
31 *
32 * @run main MBeanExceptionTest
33 */
34
35import java.util.Collections;
36import java.util.Set;
37import javax.management.Attribute;
38import javax.management.AttributeList;
39import javax.management.DynamicMBean;
40import javax.management.MBeanException;
41import javax.management.MBeanInfo;
42import javax.management.MBeanServer;
43import javax.management.MBeanServerFactory;
44import javax.management.ObjectName;
45import javax.management.RuntimeMBeanException;
46import javax.management.StandardMBean;
47
48public class MBeanExceptionTest {
49    public static void main(String[] args) throws Exception {
50        System.out.println("Test that if an MBean throws RuntimeException " +
51                           "it is wrapped in RuntimeMBeanException,");
52        System.out.println("and if a Standard MBean throws Exception " +
53                           "it is wrapped in MBeanException");
54        MBeanServer mbs = MBeanServerFactory.newMBeanServer();
55        Object standard = new Except();
56        ObjectName standardName = new ObjectName(":name=Standard MBean");
57        Object standardMBean =
58            new StandardMBean(new Except(), ExceptMBean.class);
59        ObjectName standardMBeanName =
60            new ObjectName(":name=Instance of StandardMBean");
61        Object dynamic = new DynamicExcept();
62        ObjectName dynamicName = new ObjectName(":name=Dynamic MBean");
63        mbs.registerMBean(standard, standardName);
64        mbs.registerMBean(standardMBean, standardMBeanName);
65        mbs.registerMBean(dynamic, dynamicName);
66        int failures = 0;
67        failures += test(mbs, standardName, true);
68        failures += test(mbs, standardMBeanName, true);
69        failures += test(mbs, dynamicName, false);
70
71        final boolean[] booleans = {false, true};
72
73        for (boolean runtimeX : booleans) {
74            Class<? extends Exception> excC =
75                    runtimeX ? RuntimeMBeanException.class : MBeanException.class;
76            String excS =
77                    runtimeX ? "a RuntimeMBeanException" : "an MBeanException";
78            String mbsS = "a plain MBeanServer";
79            System.out.println(
80                    "Test that, with " + mbsS + ", " + excS + " is wrapped " +
81                    "in " + excS);
82            // E.g. "Test that, with a plain MBeanServer, an MBeanException
83            // is wrapped in an MBeanException".
84            try {
85                mbs.createMBean(
86                        Except.class.getName(), new ObjectName(":name=Oops"),
87                        new Object[] {runtimeX},
88                        new String[] {boolean.class.getName()});
89                System.out.println(
90                        "FAIL: createMBean succeeded but should not have");
91                failures++;
92            } catch (Exception e) {
93                if (!excC.isInstance(e)) {
94                    System.out.println(
95                            "FAIL: expected " + excC.getName() + " from " +
96                            "createMBean, got " + e);
97                    failures++;
98                } else {
99                    Throwable cause = e.getCause();
100                    if (!excC.isInstance(cause)) {
101                        System.out.println(
102                                "FAIL: expected " + excC.getName() +
103                                " as cause of " + excC.getName() +
104                                ", got " + e);
105                        failures++;
106                    } else
107                        System.out.println("...ok");
108                }
109            }
110        }
111
112        if (failures == 0)
113            System.out.println("Test passed");
114        else {
115            System.out.println("TEST FAILED: " + failures + " failure(s)");
116            System.exit(1);
117        }
118    }
119
120    private static int test(MBeanServer mbs, ObjectName name,
121                            boolean testChecked)
122            throws Exception {
123        System.out.println("--------" + name + "--------");
124
125        int failures = 0;
126        final String[] ops = {"getAttribute", "setAttribute", "invoke"};
127        final int GET = 0, SET = 1, INVOKE = 2;
128        final String[] targets = {"UncheckedException", "CheckedException"};
129        final int UNCHECKED = 0, CHECKED = 1;
130
131        for (int i = 0; i < ops.length; i++) {
132            for (int j = 0; j < targets.length; j++) {
133
134                if (j == CHECKED && !testChecked)
135                    continue;
136
137                String target = targets[j];
138                String what = ops[i] + "/" + target;
139                System.out.println(what);
140
141                try {
142                    switch (i) {
143                    case GET:
144                        mbs.getAttribute(name, target);
145                        break;
146                    case SET:
147                        mbs.setAttribute(name, new Attribute(target, "x"));
148                        break;
149                    case INVOKE:
150                        mbs.invoke(name, target, null, null);
151                        break;
152                    default:
153                        throw new AssertionError();
154                    }
155                    System.out.println("failure: " + what + " returned!");
156                    failures++;
157                } catch (RuntimeMBeanException e) {
158                    if (j == CHECKED) {
159                        System.out.println("failure: RuntimeMBeanException " +
160                                           "when checked expected: " + e);
161                        failures++;
162                    } else {
163                        Throwable cause = e.getCause();
164                        if (cause == theUncheckedException)
165                            System.out.println("ok: " + what);
166                        else {
167                            System.out.println("failure: " + what +
168                                               " wrapped " + cause);
169                            failures++;
170                        }
171                    }
172                } catch (MBeanException e) {
173                    if (j == UNCHECKED) {
174                        System.out.println("failure: checked exception " +
175                                           "when unchecked expected: " + e);
176                        failures++;
177                    } else {
178                        Throwable cause = e.getCause();
179                        if (cause == theCheckedException)
180                            System.out.println("ok: " + what);
181                        else {
182                            System.out.println("failure: " + what +
183                                               " wrapped " + cause);
184                            failures++;
185                        }
186                    }
187                } catch (Throwable t) {
188                    System.out.println("failure: " + what + " threw: " + t);
189                    while ((t = t.getCause()) != null)
190                        System.out.println("  ... " + t);
191                    failures++;
192                }
193            }
194        }
195
196        return failures;
197    }
198
199    public static interface ExceptMBean {
200        public String getUncheckedException();
201        public void setUncheckedException(String x);
202        public void UncheckedException();
203        public String getCheckedException() throws Exception;
204        public void setCheckedException(String x) throws Exception;
205        public void CheckedException() throws Exception;
206    }
207
208    public static class Except implements ExceptMBean {
209        public Except() {}
210
211        public Except(boolean runtimeX) throws MBeanException {
212            if (runtimeX)
213                throw new RuntimeMBeanException(new RuntimeException(), "Bang");
214            else
215                throw new MBeanException(new Exception(), "Bang");
216        }
217
218        public String getUncheckedException() {
219            throw theUncheckedException;
220        }
221        public void setUncheckedException(String x) {
222            throw theUncheckedException;
223        }
224        public void UncheckedException() {
225            throw theUncheckedException;
226        }
227        public String getCheckedException() throws Exception {
228            throw theCheckedException;
229        }
230        public void setCheckedException(String x) throws Exception {
231            throw theCheckedException;
232        }
233        public void CheckedException() throws Exception {
234            throw theCheckedException;
235        }
236    }
237
238    public static class DynamicExcept implements DynamicMBean {
239        public Object getAttribute(String attrName)
240                throws MBeanException {
241            if (attrName.equals("UncheckedException"))
242                throw theUncheckedException;
243            else
244                throw new AssertionError();
245        }
246        public void setAttribute(Attribute attr)
247                throws MBeanException {
248            String attrName = attr.getName();
249            if (attrName.equals("UncheckedException"))
250                throw theUncheckedException;
251            else
252                throw new AssertionError();
253        }
254        public Object invoke(String opName, Object[] params, String[] sig)
255                throws MBeanException {
256            assert params == null && sig == null;
257            if (opName.equals("UncheckedException"))
258                throw theUncheckedException;
259            else
260                throw new AssertionError();
261        }
262        public AttributeList getAttributes(String[] names) {
263            assert false;
264            return null;
265        }
266        public AttributeList setAttributes(AttributeList attrs) {
267            assert false;
268            return null;
269        }
270        public MBeanInfo getMBeanInfo() {
271            try {
272                return new StandardMBean(new Except(), ExceptMBean.class)
273                    .getMBeanInfo();
274            } catch (Exception e) {
275                assert false;
276                return null;
277            }
278        }
279    }
280
281    private static final Exception theCheckedException =
282        new Exception("The checked exception that should be seen");
283    private static final RuntimeException theUncheckedException =
284        new UnsupportedOperationException("The unchecked exception " +
285                                          "that should be seen");
286}
287