Path: blob/master/test/jdk/javax/management/MBeanServer/PostExceptionTest.java
41149 views
/*1* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 673092626* @summary Check behaviour of MBeanServer when postRegister and postDeregister27* throw exceptions.28* @author Daniel Fuchs29*30* @run main PostExceptionTest31*/3233import javax.management.*;34import java.io.Serializable;35import java.net.URL;36import java.util.EnumSet;37import javax.management.loading.MLet;3839public class PostExceptionTest {4041/**42* A test case where we instantiate an ExceptionalWombatMBean (or a43* subclass of it) which will throw the exception {@code t} from within44* the methods indicated by {@code where}45*/46public static class Case {47public final Throwable t;48public final EnumSet<WHERE> where;49public Case(Throwable t,EnumSet<WHERE> where) {50this.t=t; this.where=where;51}52}5354// Various methods to create an instance of Case in a single line55// --------------------------------------------------------------5657public static Case caze(Throwable t, WHERE w) {58return new Case(t,EnumSet.of(w));59}60public static Case caze(Throwable t, EnumSet<WHERE> where) {61return new Case(t,where);62}63public static Case caze(Throwable t, WHERE w, WHERE... rest) {64return new Case(t,EnumSet.of(w,rest));65}6667/**68* Here is the list of our test cases:69*/70public static Case[] cases ={71caze(new RuntimeException(),WHERE.PREREGISTER),72caze(new RuntimeException(),WHERE.POSTREGISTER),73caze(new RuntimeException(),WHERE.POSTREGISTER, WHERE.PREDEREGISTER),74caze(new RuntimeException(),WHERE.POSTREGISTER, WHERE.POSTDEREGISTER),75caze(new Exception(),WHERE.PREREGISTER),76caze(new Exception(),WHERE.POSTREGISTER),77caze(new Exception(),WHERE.POSTREGISTER, WHERE.PREDEREGISTER),78caze(new Exception(),WHERE.POSTREGISTER, WHERE.POSTDEREGISTER),79caze(new Error(),WHERE.PREREGISTER),80caze(new Error(),WHERE.POSTREGISTER),81caze(new Error(),WHERE.POSTREGISTER, WHERE.PREDEREGISTER),82caze(new Error(),WHERE.POSTREGISTER, WHERE.POSTDEREGISTER),83caze(new RuntimeException(),EnumSet.allOf(WHERE.class)),84caze(new Exception(),EnumSet.allOf(WHERE.class)),85caze(new Error(),EnumSet.allOf(WHERE.class)),86};8788public static void main(String[] args) throws Exception {89System.out.println("Test behaviour of MBeanServer when postRegister " +90"or postDeregister throw exceptions");91MBeanServer mbs = MBeanServerFactory.newMBeanServer();92int failures = 0;93final ObjectName n = new ObjectName("test:type=Wombat");9495// We're going to test each cases, using each of the 4 createMBean96// forms + registerMBean in turn to create the MBean.97// Wich method is used to create the MBean is indicated by "how"98//99for (Case caze:cases) {100for (CREATE how : CREATE.values()) {101failures+=test(mbs,n,how,caze.t,caze.where);102}103}104if (failures == 0)105System.out.println("Test passed");106else {107System.out.println("TEST FAILED: " + failures + " failure(s)");108System.exit(1);109}110}111112// Execute a test case composed of:113// mbs: The MBeanServer where the MBean will be registered,114// name: The name of that MBean115// how: How will the MBean be created/registered (which MBeanServer116// method)117// t: The exception/error that the MBean will throw118// where: In which pre/post register/deregister method the exception/error119// will be thrown120//121private static int test(MBeanServer mbs, ObjectName name, CREATE how,122Throwable t, EnumSet<WHERE> where)123throws Exception {124System.out.println("-------<"+how+"> / <"+t+"> / "+ where + "-------");125126int failures = 0;127ObjectInstance oi = null;128Exception reg = null; // exception thrown by create/register129Exception unreg = null; // exception thrown by unregister130try {131// Create the MBean132oi = how.create(t, where, mbs, name);133} catch (Exception xx) {134reg=xx;135}136final ObjectName n = (oi==null)?name:oi.getObjectName();137final boolean isRegistered = mbs.isRegistered(n);138try {139// If the MBean is registered, unregister it140if (isRegistered) mbs.unregisterMBean(n);141} catch (Exception xxx) {142unreg=xxx;143}144final boolean isUnregistered = !mbs.isRegistered(n);145if (!isUnregistered) {146// if the MBean is still registered (preDeregister threw an147// exception) signify to the MBean that it now should stop148// throwing anaything and unregister it.149JMX.newMBeanProxy(mbs, n, ExceptionalWombatMBean.class).end();150mbs.unregisterMBean(n);151}152153// Now analyze the result. If we didn't ask the MBean to throw any154// exception then reg should be null.155if (where.isEmpty() && reg!=null) {156System.out.println("Unexpected registration exception: "+157reg);158throw new RuntimeException("Unexpected registration exception: "+159reg,reg);160}161162// If we didn't ask the MBean to throw any exception then unreg should163// also be null.164if (where.isEmpty() && unreg!=null) {165System.out.println("Unexpected unregistration exception: "+166unreg);167throw new RuntimeException("Unexpected unregistration exception: "+168unreg,unreg);169}170171// If we asked the MBean to throw an exception in either of preRegister172// or postRegister, then reg should not be null.173if ((where.contains(WHERE.PREREGISTER)174|| where.contains(WHERE.POSTREGISTER))&& reg==null) {175System.out.println("Expected registration exception not " +176"thrown by "+where);177throw new RuntimeException("Expected registration exception not " +178"thrown by "+where);179}180181// If we asked the MBean not to throw any exception in preRegister182// then the MBean should have been registered, unregisterMBean should183// have been called.184// If we asked the MBean to throw an exception in either of preDeregister185// or postDeregister, then unreg should not be null.186if ((where.contains(WHERE.PREDEREGISTER)187|| where.contains(WHERE.POSTDEREGISTER))&& unreg==null188&& !where.contains(WHERE.PREREGISTER)) {189System.out.println("Expected unregistration exception not " +190"thrown by "+where);191throw new RuntimeException("Expected unregistration exception not " +192"thrown by "+where);193}194195// If we asked the MBean to throw an exception in preRegister196// then the MBean should not have been registered.197if (where.contains(WHERE.PREREGISTER)) {198if (isRegistered) {199System.out.println("MBean is still registered [" +200where+201"]: "+name+" / "+reg);202throw new RuntimeException("MBean is still registered [" +203where+204"]: "+name+" / "+reg,reg);205}206}207208// If we asked the MBean not to throw an exception in preRegister,209// but to throw an exception in postRegister, then the MBean should210// have been registered.211if (where.contains(WHERE.POSTREGISTER) &&212!where.contains(WHERE.PREREGISTER)) {213if (!isRegistered) {214System.out.println("MBean is already unregistered [" +215where+216"]: "+name+" / "+reg);217throw new RuntimeException("MBean is already unregistered [" +218where+219"]: "+name+" / "+reg,reg);220}221}222223// If we asked the MBean to throw an exception in preRegister,224// check that the exception we caught was as expected.225//226if (where.contains(WHERE.PREREGISTER)) {227WHERE.PREREGISTER.check(reg, t);228} else if (where.contains(WHERE.POSTREGISTER)) {229// If we asked the MBean to throw an exception in postRegister,230// check that the exception we caught was as expected.231// We don't do this check if we asked the MBean to also throw an232// exception in pre register, because postRegister will not have233// been called.234WHERE.POSTREGISTER.check(reg, t);235}236237if (!isRegistered) return failures;238239// The MBean was registered, so unregisterMBean was called. Check240// unregisterMBean exceptions...241//242243// If we asked the MBean to throw an exception in preDeregister244// then the MBean should not have been deregistered.245if (where.contains(WHERE.PREDEREGISTER)) {246if (isUnregistered) {247System.out.println("MBean is already unregistered [" +248where+249"]: "+name+" / "+unreg);250throw new RuntimeException("MBean is already unregistered [" +251where+252"]: "+name+" / "+unreg,unreg);253}254}255256// If we asked the MBean not to throw an exception in preDeregister,257// but to throw an exception in postDeregister, then the MBean should258// have been deregistered.259if (where.contains(WHERE.POSTDEREGISTER) &&260!where.contains(WHERE.PREDEREGISTER)) {261if (!isUnregistered) {262System.out.println("MBean is not unregistered [" +263where+264"]: "+name+" / "+unreg);265throw new RuntimeException("MBean is not unregistered [" +266where+267"]: "+name+" / "+unreg,unreg);268}269}270271// If we asked the MBean to throw an exception in preDeregister,272// check that the exception we caught was as expected.273//274if (where.contains(WHERE.PREDEREGISTER)) {275WHERE.PREDEREGISTER.check(unreg, t);276} else if (where.contains(WHERE.POSTDEREGISTER)) {277// If we asked the MBean to throw an exception in postDeregister,278// check that the exception we caught was as expected.279// We don't do this check if we asked the MBean to also throw an280// exception in pre register, because postRegister will not have281// been called.282WHERE.POSTDEREGISTER.check(unreg, t);283}284return failures;285}286287/**288* This enum lists the 4 methods in MBeanRegistration.289*/290public static enum WHERE {291292PREREGISTER, POSTREGISTER, PREDEREGISTER, POSTDEREGISTER;293294// Checks that an exception thrown by the MBeanServer correspond to295// what is expected when an MBean throws an exception in this296// MBeanRegistration method ("this" is one of the 4 enum values above)297//298public void check(Exception thrown, Throwable t)299throws Exception {300if (t instanceof RuntimeException) {301if (!(thrown instanceof RuntimeMBeanException)) {302System.out.println("Expected RuntimeMBeanException, got "+303thrown);304throw new Exception("Expected RuntimeMBeanException, got "+305thrown);306}307} else if (t instanceof Error) {308if (!(thrown instanceof RuntimeErrorException)) {309System.out.println("Expected RuntimeErrorException, got "+310thrown);311throw new Exception("Expected RuntimeErrorException, got "+312thrown);313}314} else if (t instanceof Exception) {315if (EnumSet.of(POSTDEREGISTER,POSTREGISTER).contains(this)) {316if (!(thrown instanceof RuntimeMBeanException)) {317System.out.println("Expected RuntimeMBeanException, got "+318thrown);319throw new Exception("Expected RuntimeMBeanException, got "+320thrown);321}322if (! (thrown.getCause() instanceof RuntimeException)) {323System.out.println("Bad cause: " +324"expected RuntimeException, " +325"got <"+thrown.getCause()+">");326throw new Exception("Bad cause: " +327"expected RuntimeException, " +328"got <"+thrown.getCause()+">");329}330}331if (EnumSet.of(PREDEREGISTER,PREREGISTER).contains(this)) {332if (!(thrown instanceof MBeanRegistrationException)) {333System.out.println("Expected " +334"MBeanRegistrationException, got "+335thrown);336throw new Exception("Expected " +337"MBeanRegistrationException, got "+338thrown);339}340if (! (thrown.getCause() instanceof Exception)) {341System.out.println("Bad cause: " +342"expected Exception, " +343"got <"+thrown.getCause()+">");344throw new Exception("Bad cause: " +345"expected Exception, " +346"got <"+thrown.getCause()+">");347}348}349}350351}352}353354/**355* This enum lists the 5 methods to create and register an356* ExceptionalWombat MBean357*/358public static enum CREATE {359360CREATE1() {361// Creates an ExceptionalWombat MBean using createMBean form #1362public ObjectInstance create(Throwable t, EnumSet<WHERE> where,363MBeanServer server, ObjectName name) throws Exception {364ExceptionallyHackyWombat.t = t;365ExceptionallyHackyWombat.w = where;366return server.createMBean(367ExceptionallyHackyWombat.class.getName(),368name);369}370},371CREATE2() {372// Creates an ExceptionalWombat MBean using createMBean form #2373public ObjectInstance create(Throwable t, EnumSet<WHERE> where,374MBeanServer server, ObjectName name) throws Exception {375ExceptionallyHackyWombat.t = t;376ExceptionallyHackyWombat.w = where;377final ObjectName loaderName = registerMLet(server);378return server.createMBean(379ExceptionallyHackyWombat.class.getName(),380name, loaderName);381}382},383CREATE3() {384// Creates an ExceptionalWombat MBean using createMBean form #3385public ObjectInstance create(Throwable t, EnumSet<WHERE> where,386MBeanServer server, ObjectName name) throws Exception {387final Object[] params = {t, where};388final String[] signature = {Throwable.class.getName(),389EnumSet.class.getName()390};391return server.createMBean(392ExceptionalWombat.class.getName(), name,393params, signature);394}395},396CREATE4() {397// Creates an ExceptionalWombat MBean using createMBean form #4398public ObjectInstance create(Throwable t, EnumSet<WHERE> where,399MBeanServer server, ObjectName name) throws Exception {400final Object[] params = {t, where};401final String[] signature = {Throwable.class.getName(),402EnumSet.class.getName()403};404return server.createMBean(405ExceptionalWombat.class.getName(), name,406registerMLet(server), params, signature);407}408},409REGISTER() {410// Creates an ExceptionalWombat MBean using registerMBean411public ObjectInstance create(Throwable t, EnumSet<WHERE> where,412MBeanServer server, ObjectName name) throws Exception {413final ExceptionalWombat wombat =414new ExceptionalWombat(t, where);415return server.registerMBean(wombat, name);416}417};418419// Creates an ExceptionalWombat MBean using the method denoted by this420// Enum value - one of CREATE1, CREATE2, CREATE3, CREATE4, or REGISTER.421public abstract ObjectInstance create(Throwable t, EnumSet<WHERE> where,422MBeanServer server, ObjectName name) throws Exception;423424// This is a bit of a hack - we use an MLet that delegates to the425// System ClassLoader so that we can use createMBean form #2 and #3426// while still using the same class loader (system).427// This is necessary to make the ExceptionallyHackyWombatMBean work ;-)428//429public ObjectName registerMLet(MBeanServer server) throws Exception {430final ObjectName name = new ObjectName("test:type=MLet");431if (server.isRegistered(name)) {432return name;433}434final MLet mlet = new MLet(new URL[0],435ClassLoader.getSystemClassLoader());436return server.registerMBean(mlet, name).getObjectName();437}438}439440/**441*A Wombat MBean that can throw exceptions or errors in any of the442* MBeanRegistration methods.443*/444public static interface ExceptionalWombatMBean {445// Tells the MBean to stop throwing exceptions - we sometime446// need to call this at the end of the test so that we can447// actually unregister the MBean.448public void end();449}450451/**452*A Wombat MBean that can throw exceptions or errors in any of the453* MBeanRegistration methods.454*/455public static class ExceptionalWombat456implements ExceptionalWombatMBean, MBeanRegistration {457458private final Throwable throwable;459private final EnumSet<WHERE> where;460private volatile boolean end=false;461462public ExceptionalWombat(Throwable t, EnumSet<WHERE> where) {463this.throwable=t; this.where=where;464}465private Exception doThrow() {466if (throwable instanceof Error)467throw (Error)throwable;468if (throwable instanceof RuntimeException)469throw (RuntimeException)throwable;470return (Exception)throwable;471}472public ObjectName preRegister(MBeanServer server, ObjectName name)473throws Exception {474if (!end && where.contains(WHERE.PREREGISTER))475throw doThrow();476return name;477}478479public void postRegister(Boolean registrationDone) {480if (!end && where.contains(WHERE.POSTREGISTER))481throw new RuntimeException(doThrow());482}483484public void preDeregister() throws Exception {485if (!end && where.contains(WHERE.PREDEREGISTER))486throw doThrow();487}488489public void postDeregister() {490if (!end && where.contains(WHERE.POSTREGISTER))491throw new RuntimeException(doThrow());492}493494public void end() {495this.end=true;496}497}498499/**500* This is a big ugly hack to call createMBean form #1 and #2 - where501* the empty constructor is used. Since we still want to supply parameters502* to the ExceptionalWombat super class, we temporarily store these503* parameter value in a static volatile before calling create MBean.504* Of course this only works because our test is sequential and single505* threaded, and nobody but our test uses this ExceptionallyHackyWombat.506*/507public static class ExceptionallyHackyWombat extends ExceptionalWombat {508public static volatile Throwable t;509public static volatile EnumSet<WHERE> w;510public ExceptionallyHackyWombat() {511super(t,w);512}513}514515}516517518