diff --git a/jdk/test/javax/management/MBeanServer/ExceptionFactory.java b/jdk/test/javax/management/MBeanServer/ExceptionFactory.java new file mode 100644 index 00000000000..2315edff3fc --- /dev/null +++ b/jdk/test/javax/management/MBeanServer/ExceptionFactory.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.ArrayList; +import javax.management.AttributeNotFoundException; +import javax.management.BadAttributeValueExpException; +import javax.management.BadBinaryOpValueExpException; +import javax.management.BadStringOperationException; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.IntrospectionException; +import javax.management.InvalidApplicationException; +import javax.management.InvalidAttributeValueException; +import javax.management.JMException; +import javax.management.JMRuntimeException; +import javax.management.ListenerNotFoundException; +import javax.management.MBeanException; +import javax.management.MBeanRegistrationException; +import javax.management.MalformedObjectNameException; +import javax.management.NotCompliantMBeanException; +import javax.management.OperationsException; +import javax.management.ReflectionException; +import javax.management.RuntimeErrorException; +import javax.management.RuntimeMBeanException; +import javax.management.RuntimeOperationsException; +import javax.management.ServiceNotFoundException; +import javax.management.StringValueExp; +import javax.management.modelmbean.InvalidTargetObjectTypeException; +import javax.management.modelmbean.XMLParseException; +import javax.management.monitor.MonitorSettingException; +import javax.management.openmbean.InvalidKeyException; +import javax.management.openmbean.InvalidOpenTypeException; +import javax.management.openmbean.KeyAlreadyExistsException; +import javax.management.openmbean.OpenDataException; +import javax.management.relation.InvalidRelationIdException; +import javax.management.relation.InvalidRelationServiceException; +import javax.management.relation.InvalidRelationTypeException; +import javax.management.relation.InvalidRoleInfoException; +import javax.management.relation.InvalidRoleValueException; +import javax.management.relation.RelationException; +import javax.management.relation.RelationNotFoundException; +import javax.management.relation.RelationServiceNotRegisteredException; +import javax.management.relation.RelationTypeNotFoundException; +import javax.management.relation.RoleInfoNotFoundException; +import javax.management.relation.RoleNotFoundException; +import javax.management.remote.JMXProviderException; +import javax.management.remote.JMXServerErrorException; + +/** + * |----- Original Description Coming From Tonga Original Source Code -------| + * | | + * | That class creates an ArrayList and fill it with an instance of each of | + * | the Exception class of the JMX API. | + * | It's dedicated to use by ExceptionTest. | + * |-------------------------------------------------------------------------| + */ +public class ExceptionFactory { + + public static final ArrayList exceptions = + new ArrayList(); + + static { + String mes = "SQE"; + exceptions.add(new AttributeNotFoundException()); + exceptions.add(new BadAttributeValueExpException(mes)); + exceptions.add(new BadBinaryOpValueExpException(new StringValueExp(mes))); + exceptions.add(new BadStringOperationException(mes)); + exceptions.add(new InstanceAlreadyExistsException()); + exceptions.add(new InstanceNotFoundException()); + exceptions.add(new IntrospectionException()); + exceptions.add(new InvalidApplicationException(mes)); + exceptions.add(new InvalidAttributeValueException()); + exceptions.add(new JMException()); + exceptions.add(new JMRuntimeException()); + exceptions.add(new ListenerNotFoundException()); + exceptions.add(new MalformedObjectNameException()); + exceptions.add(new MBeanException(new Exception(mes), mes)); + exceptions.add(new MBeanRegistrationException(new Exception(mes), mes)); + exceptions.add(new NotCompliantMBeanException()); + exceptions.add(new OperationsException()); + exceptions.add(new ReflectionException(new Exception(mes), mes)); + exceptions.add(new RuntimeErrorException(new Error(mes), mes)); + exceptions.add(new RuntimeMBeanException(new RuntimeException(mes), mes)); + exceptions.add(new RuntimeOperationsException(new RuntimeException(mes), mes)); + exceptions.add(new ServiceNotFoundException()); + exceptions.add(new InvalidTargetObjectTypeException()); + exceptions.add(new XMLParseException()); + exceptions.add(new MonitorSettingException()); + exceptions.add(new InvalidKeyException()); + exceptions.add(new InvalidOpenTypeException()); + exceptions.add(new KeyAlreadyExistsException()); + exceptions.add(new OpenDataException()); + exceptions.add(new InvalidRelationIdException()); + exceptions.add(new InvalidRelationServiceException()); + exceptions.add(new InvalidRelationTypeException()); + exceptions.add(new InvalidRoleInfoException()); + exceptions.add(new InvalidRoleValueException()); + exceptions.add(new RelationException()); + exceptions.add(new RelationNotFoundException()); + exceptions.add(new RelationServiceNotRegisteredException()); + exceptions.add(new RelationTypeNotFoundException()); + exceptions.add(new RoleInfoNotFoundException()); + exceptions.add(new RoleNotFoundException()); + exceptions.add(new JMXProviderException()); + exceptions.add(new JMXServerErrorException(mes, new Error(mes))); + ExceptionTest.Utils.debug(ExceptionTest.Utils.DEBUG_STANDARD, + "DataFactory::updateMap: Initialized" + + " an ArrayList with the " + + exceptions.size() + " exceptions of the JMX API"); + } +} diff --git a/jdk/test/javax/management/MBeanServer/ExceptionTest.java b/jdk/test/javax/management/MBeanServer/ExceptionTest.java new file mode 100644 index 00000000000..571e43d3a03 --- /dev/null +++ b/jdk/test/javax/management/MBeanServer/ExceptionTest.java @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058865 + * @summary Checks that exceptions are correctly wired (compared to reference). + * @author Olivier Lagneau + * @modules java.management + * @run main/othervm/timeout=300 -DDEBUG_STANDARD ExceptionTest + */ + +import java.util.Map; +import java.util.HashMap; +import java.util.Properties; +import java.lang.reflect.Method; + +import java.lang.management.ManagementFactory; +import javax.management.ObjectName; +import javax.management.MBeanServer; +import javax.management.MBeanServerConnection; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + + +public class ExceptionTest { + + /* + * First Debug properties and arguments are collect in expected + * map (argName, value) format, then calls original test's run method. + */ + public static void main(String args[]) throws Exception { + + System.out.println("================================================="); + + // Parses parameters + Utils.parseDebugProperties(); + Map map = Utils.parseParameters(args) ; + + // Run test + ExceptionTest test = new ExceptionTest(); + test.run(map); + + } + + public void run(Map args) { + + System.out.println("ExceptionTest::run: Start"); + int errorCount = 0; + + JMXConnectorServer cs = null; + JMXConnector cc = null; + + try { + // JMX MbeanServer used inside single VM as if remote. + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + + JMXServiceURL url = new JMXServiceURL("rmi", null, 0); + cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); + cs.start(); + + JMXServiceURL addr = cs.getAddress(); + cc = JMXConnectorFactory.connect(addr); + MBeanServerConnection mbsc = cc.getMBeanServerConnection(); + + // ---- + ObjectName objName = + new ObjectName(ExceptionThrower.EXCEPTION_THROWER_NAME); + System.out.println("ExceptionTest::run: Create and register MBean " + objName); + mbsc.createMBean("ExceptionThrower", objName); + System.out.println("---- OK\n"); + + // ---- + System.out.println("ExceptionTest::run: Ask for exception(s)"); + Object[] throwExceptionParam = new Object[1]; + String[] throwExceptionSig = new String[]{"int"}; + + for (int i = 0; i < ExceptionFactory.exceptions.size(); i++) { + throwExceptionParam[0] = new Integer(i); + + Exception ex = + (Exception)mbsc.invoke(objName, + "throwException", throwExceptionParam, throwExceptionSig); + + if ( ! matches(ex, ExceptionFactory.exceptions.get(i)) ) { + errorCount++; + System.out.println("ExceptionTest::run: (ERROR) Received \n[" + + ex + "]\nin place of\n[" + + ExceptionFactory.exceptions.get(i) + "]"); + } else { + System.out.println("OK [" + ex + "]"); + } + } + + System.out.println("---- DONE\n"); + + } catch (Exception e) { + Utils.printThrowable(e, true); + throw new RuntimeException(); + } finally { + try { + // Close JMX Connector Client + cc.close(); + // Stop connertor server + cs.stop(); + + } catch (Exception e) { + Utils.printThrowable(e, true); + throw new RuntimeException( + "Unable to either close connector client or stop connector server"); + } + } + + if (errorCount == 0) { + System.out.println("ExceptionTest::run: Done without any error"); + } else { + System.out.println("ExceptionTest::run: Done with " + errorCount + + " error(s)"); + throw new RuntimeException("errorCount = " + errorCount); + } + + System.out.println("ExceptionTest::run: Done"); + } + + // Check both Exception are identical. + // That means: + // - none is null. + // - they are of the same Class. + // - if their respective messages aren't null they're equal. + // - if the message of one is null the message of the other is null too. + private boolean matches(Exception ex, Exception refex) { + if ( ex == null || refex == null ) { + System.out.println("(ERROR) Called with one or more null parameter; check " + + ex + " against " + refex); + return false; + } + + String exClass = ex.getClass().getName(); + String refexClass = refex.getClass().getName(); + + if ( ! exClass.equals(refexClass) ) { + System.out.println("(ERROR) Class names don't match; check [" + + exClass + "] against [" + refexClass + "]"); + return false; + } + + String exMes = ex.getMessage(); + String refexMes = refex.getMessage(); + + if ( exMes != null && refexMes != null ) { + if ( ! exMes.equals(refexMes) ) { + System.out.println("(ERROR) Non null messages don't match; check [" + + exMes + "] against [" + refexMes + "]"); + return false; + } + } else if ( (exMes == null && refexMes != null) + || (exMes != null && refexMes == null) ) { + System.out.println("(ERROR) Messages don't match; check [" + exMes + + "] against [" + refexMes + "]"); + } + + return true; + } + + // Utility inner class coming from JMX Tonga test suite. + // Also used by ExceptionFactory. + static class Utils { + + // DEBUG is printed depending on the DEBUG and DEBUG_LEVEL JAVA property + static final String DEBUG_HEADER = "[debug] "; + + // DEBUG levels + static int selectedDebugLevel = 0; + static final int DEBUG_STANDARD = 1; + static final int DEBUG_VERBOSE = 2; // Mainly used for stress tests + static final int DEBUG_ALL = DEBUG_STANDARD | DEBUG_VERBOSE; + + static void parseDebugProperties() { + int level = 0; + Properties p = System.getProperties(); + + // get selected levels + if (p.getProperty("DEBUG_STANDARD") != null) { + level |= DEBUG_STANDARD; + } + + if (p.getProperty("DEBUG_VERBOSE") != null) { + level |= DEBUG_VERBOSE; + } + + if (p.getProperty("DEBUG_ALL") != null) { + level |= DEBUG_ALL; + } + + selectedDebugLevel = level; + } + + /** + * Reproduces the original parsing and collection of test parameters + * from the DTonga JMX test suite. + * + * Collects passed args and returns them in a map(argname, value) structure, + * which will be then propagated as necessary to various called methods. + */ + static Map parseParameters(String args[]) + throws Exception { + debug(DEBUG_STANDARD, "TestRoot::parseParameters: Start"); + HashMap map = new HashMap<>(); + + for ( int i = 0; i < args.length; i++ ) { + if ( args[i].trim().startsWith("-") ) { + if ((i+1) < args.length && !args[i+1].startsWith("-") ) { + debug(DEBUG_STANDARD, + "TestRoot::parseParameters: added in map = " + + args[i] + + " with value " + + args[i+1]) ; + map.put(args[i].trim(), args[i+1].trim()) ; + } else if ((i+1) < args.length && args[i+1].startsWith("-") || + (i+1) == args.length ) { + debug(DEBUG_STANDARD, + "TestRoot::parseParameters: added in map = " + + args[i] + + " with null value") ; + map.put(args[i].trim(), null) ; + } else { + System.out.println( + "TestRoot::parseParameters: (WARNING) not added in map = " + + args[i]) ; + } + } + } + + debug(DEBUG_STANDARD, "TestRoot::parseParameters: Done") ; + return map ; + } + + /** + * This method is to be used in all tests to print anything + * that is temporary. + * Printing is done only when debug is activated by the property DEBUG. + * Printing depends also on the DEBUG_LEVEL property. + * Here it encapsulates a System.out.println. + */ + static void debug(int level, String line) { + if ((selectedDebugLevel & level) != 0) { + System.out.println(DEBUG_HEADER + line); + } + } + + /** + * Do print stack trace when withStack is true. + * Does try to call getTargetException() and getTargetError() then + * print embedded stacks in the case of an Exception wrapping + * another Exception or an Error. Recurse until no more wrapping + * is found. + */ + static void printThrowable(Throwable theThro, boolean withStack) { + try { + if (withStack) { + theThro.printStackTrace(System.out); + } + if (theThro instanceof Exception) { + Exception t = (Exception) theThro; + Method target = null; + String blank = " "; + try { + target = t.getClass().getMethod("getTargetException", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetException method could be there or not + } + System.out.println(blank + t.getClass() + "==>" + t.getMessage()); + while (target != null) { + try { + t = (Exception) target.invoke(t, + (java.lang.Object[]) null); + } catch (Exception ee) { + t = null; + } + try { + if (t != null) { + blank = blank + " "; + System.out.println(blank + t.getClass() + "==>" + + t.getMessage()); + try { + target = + t.getClass().getMethod("getTargetException", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetException method could be there or not } + } + } else { + target = null; + } + } catch (Exception ee) { + target = null; + } + } + + // We may have exceptions wrapping an Error then it is + // getTargetError that is likely to be called + try { + target = ((Exception) theThro).getClass().getMethod("getTargetError", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetError method could be there or not + } + Throwable err = theThro; + while (target != null) { + try { + err = (Error) target.invoke(err, + (java.lang.Object[]) null); + } catch (Exception ee) { + err = null; + } + try { + if (err != null) { + blank = blank + " "; + System.out.println(blank + err.getClass() + "==>" + + err.getMessage()); + if (withStack) { + err.printStackTrace(System.out); + } + try { + target = err.getClass().getMethod("getTargetError", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetError method could be there or not + } + } else { + target = null; + } + } catch (Exception ee) { + target = null; + } + } + } else { + System.out.println("Throwable is : " + theThro); + } + } catch (Throwable x) { + System.out.println("Exception : raised in printException : " + x); + } + } + } + +} + + diff --git a/jdk/test/javax/management/MBeanServer/ExceptionThrower.java b/jdk/test/javax/management/MBeanServer/ExceptionThrower.java new file mode 100644 index 00000000000..37d661eaca6 --- /dev/null +++ b/jdk/test/javax/management/MBeanServer/ExceptionThrower.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * This class defines a simple standard MBean. + */ +public class ExceptionThrower implements ExceptionThrowerMBean { + + public static final String EXCEPTION_THROWER_NAME + = "sqe:type=ExceptionThrower"; + + public Exception throwException(int exceptionIndex) { + return ExceptionFactory.exceptions.get(exceptionIndex); + } +} diff --git a/jdk/test/javax/management/MBeanServer/ExceptionThrowerMBean.java b/jdk/test/javax/management/MBeanServer/ExceptionThrowerMBean.java new file mode 100644 index 00000000000..d5485d30e67 --- /dev/null +++ b/jdk/test/javax/management/MBeanServer/ExceptionThrowerMBean.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * This interface defines a simple standard MBean. + */ +public interface ExceptionThrowerMBean { + public Exception throwException(int exceptionIndex); +} diff --git a/jdk/test/javax/management/mxbean/Basic.java b/jdk/test/javax/management/mxbean/Basic.java new file mode 100644 index 00000000000..3f32af666b9 --- /dev/null +++ b/jdk/test/javax/management/mxbean/Basic.java @@ -0,0 +1,530 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import javax.management.Descriptor; +import javax.management.ImmutableDescriptor; +import javax.management.ListenerNotFoundException; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanRegistration; +import javax.management.MBeanServer; +import javax.management.Notification; +import javax.management.NotificationBroadcasterSupport; +import javax.management.NotificationEmitter; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.ObjectName; + +/** + * Class Basic + * Basic Description + */ +public class Basic implements BasicMXBean, NotificationEmitter, + MBeanRegistration { + + public static final String EXCEPTION_MESSAGE = "from Basic"; + public static final String NOTIFICATION_MESSAGE = "from Basic"; + /** Attribute : IntAtt */ + private int intAtt = 0; + /** Attribute : IntegerAtt */ + private Integer integerAtt = 0; + /** Attribute : BoolAtt */ + private boolean boolAtt = false; + /** Attribute : BooleanAtt */ + private Boolean booleanAtt = false; + /** Attribute : StringAtt */ + private String stringAtt = null; + /** Attribute : DateAtt */ + private Date dateAtt = null; + /** Attribute : ObjectNameAtt */ + private ObjectName objectNameAtt = null; + /** Attribute : NotifDescriptorAsMapAtt */ + private Map notifDescriptorAsMapAtt = null; + /** Attribute : NotifDescriptorAtt */ + private Descriptor notifDescriptorAtt = null; + /** Attribute : SqeParameter */ + private SqeParameter sqeParameterAtt = null; + + /* Creates a new instance of Basic */ + @SqeDescriptorKey("CONSTRUCTOR Basic") + public Basic() { + } + + /* Creates a new instance of Basic */ + @SqeDescriptorKey("CONSTRUCTOR Basic") + public Basic( + @SqeDescriptorKey("CONSTRUCTOR PARAMETER SqeParameter") SqeParameter param) { + } + + /** + * Get int attribute + */ + public int getIntAtt() { + return intAtt; + } + + /** + * Set int attribute + */ + public void setIntAtt(int value) { + intAtt = value; + } + + /** + * Get Integer attribute + */ + public Integer getIntegerAtt() { + return integerAtt; + } + + /** + * Set Integer attribute + */ + public void setIntegerAtt(Integer value) { + integerAtt = value; + } + + /** + * Get boolean attribute + */ + public boolean getBoolAtt() { + return boolAtt; + } + + /** + * Set boolean attribute + */ + public void setBoolAtt(boolean value) { + boolAtt = value; + } + + /** + * Get Boolean attribute + */ + public Boolean getBooleanAtt() { + return booleanAtt; + } + + /** + * Set Boolean attribute + */ + public void setBooleanAtt(Boolean value) { + booleanAtt = value; + } + + /** + * Get String attribute + */ + public String getStringAtt() { + return stringAtt; + } + + /** + * Set String attribute + */ + public void setStringAtt(String value) { + stringAtt = value; + } + + /** + * Get Date attribute + */ + public Date getDateAtt() { + return dateAtt; + } + + /** + * Set Date attribute + */ + public void setDateAtt(Date value) { + dateAtt = value; + } + + /** + * Get ObjectName attribute + */ + public ObjectName getObjectNameAtt() { + return objectNameAtt; + } + + /** + * Set ObjectName attribute + */ + public void setObjectNameAtt(ObjectName value) { + objectNameAtt = value; + } + + /** + * Get SqeParameter attribute + */ + public SqeParameter getSqeParameterAtt() throws Exception { + if (sqeParameterAtt == null) { + sqeParameterAtt = new SqeParameter(); + sqeParameterAtt.setGlop("INITIALIZED"); + } + + return sqeParameterAtt; + } + + /** + * Set SqeParameter attribute + */ + public void setSqeParameterAtt(SqeParameter value) { + sqeParameterAtt = value; + } + + /** + * Get the Descriptor used to build the NotificationInfo + * of emitted notifications. + */ + public Map getNotifDescriptorAsMapAtt() { + if (notifDescriptorAsMapAtt == null) { + initNotifDescriptorAtt(); + } + + return notifDescriptorAsMapAtt; + } + + /** + * Set the Descriptor used to build the NotificationInfo + * of emitted notifications. + *
A Map would better fit Descriptor needs but then + * it is not convertible according the MXBean specification so the MBean + * registration fails. + * As we plan to test our custom Descriptor finds its way into + * the metadata of emitted notifications, String is good enough. + */ + public void setNotifDescriptorAsMapAtt(Map value) { + notifDescriptorAsMapAtt = new HashMap(value); + notifDescriptorAtt = new ImmutableDescriptor(value); + } + + /** + * Do nothing + */ + public void doNothing() { + // I said NOTHING ! + } + + /** + * Do take SqeParameter as a parameter + */ + public void doWeird(SqeParameter param) { + } + + /** + * Throw an Exception + */ + public void throwException() throws Exception { + throw new Exception(EXCEPTION_MESSAGE); + } + + /** + * Throw an Error + */ + public void throwError() { + throw new InternalError(EXCEPTION_MESSAGE); + } + + /** + * Reset all attributes + */ + public void reset() { + intAtt = 0; + integerAtt = 0; + boolAtt = false; + booleanAtt = Boolean.FALSE; + stringAtt = null; + dateAtt = null; + objectNameAtt = null; + } + + /** + * Returns the weather for the coming days + * @param verbose boolean verbosity + * @throws java.lang.Exception storm + * @return ObjectName + */ + public Weather getWeather(boolean verbose) + throws java.lang.Exception { + return Weather.SUNNY; + } + + // Starting here are the 4 methods of MBeanRegistration interface. + // We use that to grab the ObjectName the MBean is registered with. + // + public ObjectName preRegister(MBeanServer server, ObjectName name) + throws Exception { + // Grab a reference on the MBeanServer we're registered in. + mbs = server; + // Compute the name we're registered with. + if (name != null) { + mbeanName = name; + return name; + } else { + mbeanName = + new ObjectName("sqe:type=" + Basic.class.getName()); + return mbeanName; + } + } + + public void postRegister(Boolean registrationDone) { + // Do nothing + } + + public void preDeregister() throws Exception { + // Do nothing + } + + public void postDeregister() { + // Do nothing + } + + /** + * Send one Notification of the provided notifType type. + */ + public void sendNotification(String notifType) { + Notification notification = null; + + if (notifType.equals(NOTIF_TYPE_0)) { + notification = new Notification(NOTIF_TYPE_0, + mbeanName, + seqNumber, + NOTIFICATION_MESSAGE); + } else if (notifType.equals(NOTIF_TYPE_1)) { + notification = new SqeNotification(NOTIF_TYPE_1, + mbeanName, + seqNumber, + NOTIFICATION_MESSAGE); + } + + seqNumber++; + broadcaster.sendNotification(notification); + } + + /** + * That method starts a set of threads, each thread sends a given number of + * notifications. + * The number of threads can be set via the attribute numOfNotificationSenders. + * The number of notification sent by each thread can be set via + * the attribute numOfNotificationSenderLoops. + * Depending on the parameter customNotification we send either custom + * notification(s) or MBeanServer registration and unregistration notification(s). + * When customNotification=true the total number of notification(s) sent is + * (numOfNotificationSenders * numOfNotificationSenderLoops). They are + * sequentially of type NOTIF_TYPE_0 then NOTIF_TYPE_1 and so on. + * + * When customNotification=false the total number of notification(s) sent is + * (numOfNotificationSenders * numOfNotificationSenderLoops) registration + * notification(s) + * + + * (numOfNotificationSenders * numOfNotificationSenderLoops) unregistration + * notification(s) + * + * @throws java.lang.Exception + */ + public void sendNotificationWave(boolean customNotification) throws + Exception { + // Build the set of notification sender. + Collection> tasks = + new HashSet>(numOfNotificationSenders); + + for (int i = 1; i <= numOfNotificationSenders; i++) { + tasks.add(new NotifSender(numOfNotificationSenderLoops, + customNotification, i)); + } + + // Start all notification sender in parallel. + ExecutorService execServ = null; + try { + execServ = Executors.newFixedThreadPool(numOfNotificationSenders); + List> taskHandlers = execServ.invokeAll(tasks); + checkNotifSenderThreadStatus(taskHandlers); + } finally { + if (!execServ.isShutdown()) { + execServ.shutdown(); + } + } + } + + public void setNumOfNotificationSenders(int value) { + numOfNotificationSenders = value; + } + + public void setNumOfNotificationSenderLoops(int value) { + numOfNotificationSenderLoops = value; + } + + /** + * MBean Notification support + * You shouldn't update these methods + */ + // + public void addNotificationListener(NotificationListener listener, + NotificationFilter filter, + Object handback) + throws IllegalArgumentException { + broadcaster.addNotificationListener(listener, filter, handback); + } + + public MBeanNotificationInfo[] getNotificationInfo() { + if (notifDescriptorAtt == null) { + initNotifDescriptorAtt(); + } + + return new MBeanNotificationInfo[]{ + new MBeanNotificationInfo(new String[]{ + NOTIF_TYPE_0 + }, + javax.management.Notification.class.getName(), + "Standard JMX Notification", + notifDescriptorAtt), + new MBeanNotificationInfo(new String[]{ + NOTIF_TYPE_1 + }, + SqeNotification.class.getName(), + "SQE Notification", + notifDescriptorAtt) + }; + } + + public void removeNotificationListener(NotificationListener listener) + throws ListenerNotFoundException { + broadcaster.removeNotificationListener(listener); + } + + public void removeNotificationListener(NotificationListener listener, + NotificationFilter filter, + Object handback) + throws ListenerNotFoundException { + broadcaster.removeNotificationListener(listener, filter, handback); + } + // + private synchronized long getNextSeqNumber() { + return seqNumber++; + } + + private void initNotifDescriptorAtt() { + String key = "CRABE"; + String value = "TAMBOUR"; + notifDescriptorAtt = + new ImmutableDescriptor(new String[]{key + "=" + value}); + notifDescriptorAsMapAtt = + new HashMap(); + notifDescriptorAsMapAtt.put(key, value); + } + + private void checkNotifSenderThreadStatus( + List> taskHandlers) + throws Exception { + String msgTag = "Basic::checkNotifSenderThreadStatus: "; + // Grab back status of each notification sender. + for (Future f : taskHandlers) { + if (f.isCancelled()) { + String message = msgTag + + "---- ERROR : One thread has been cancelled"; + System.out.println(message); + throw new RuntimeException(message); + } else { + Integer effectiveNumOfLoops = f.get(); + + if (effectiveNumOfLoops != numOfNotificationSenderLoops) { + String message = msgTag + "---- ERROR : One thread did " + + effectiveNumOfLoops + " loops in place of " + + numOfNotificationSenderLoops; + System.out.println(message); + throw new RuntimeException(message); + } + } + } + } + // + private int numOfNotificationSenderLoops = 2; + private int numOfNotificationSenders = 13; + + private class NotifSender implements Callable { + + private int cycles; + private boolean customNotification; + private int senderID; + + public NotifSender(int cycles, boolean customNotification, int id) { + this.cycles = cycles; + this.customNotification = customNotification; + this.senderID = id; + } + + public Integer call() throws Exception { + int callsDone = 0; + + try { + for (int i = 1; i <= cycles; i++) { + if (customNotification) { + if (i % 2 == 0) { + sendNotification(NOTIF_TYPE_0); + } else { + sendNotification(NOTIF_TYPE_1); + } + } else { + ObjectName mbeanName = new ObjectName("SQE:type=" + + mbeanClassName + ",senderID=" + senderID); + mbs.createMBean(mbeanClassName, mbeanName); + mbs.unregisterMBean(mbeanName); + } + callsDone++; + } + } catch (Exception e) { + System.out.println("NotifSender::call: (ERROR) Thread [" + senderID + + "] failed after " + callsDone + " cycles"); + throw e; + } + + return Integer.valueOf(callsDone); + } + } + + // + private long seqNumber; + private final NotificationBroadcasterSupport broadcaster = + new NotificationBroadcasterSupport(); + private ObjectName mbeanName; + private MBeanServer mbs; + private String mbeanClassName = "Simple"; + + /** + * Notification types definitions. To use when creating JMX Notifications. + */ + public static final String NOTIF_TYPE_0 = + "sqe.notification.a.type"; + public static final String NOTIF_TYPE_1 = + "sqe.notification.b.type"; +} diff --git a/jdk/test/javax/management/mxbean/BasicMXBean.java b/jdk/test/javax/management/mxbean/BasicMXBean.java new file mode 100644 index 00000000000..7693be90c9f --- /dev/null +++ b/jdk/test/javax/management/mxbean/BasicMXBean.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Date; +import java.util.Map; + +import javax.management.ObjectName; + +/** + * Interface BasicMBean + * Basic Description + */ +@SqeDescriptorKey("INTERFACE BasicMXBean") +public interface BasicMXBean +{ + /** + * Get int attribute + */ + @SqeDescriptorKey("ATTRIBUTE intAtt") + public int getIntAtt(); + + /** + * Set int attribute + */ + @SqeDescriptorKey("ATTRIBUTE intAtt") + public void setIntAtt(int value); + + /** + * Get Integer attribute + */ + @SqeDescriptorKey("ATTRIBUTE integerAtt") + public Integer getIntegerAtt(); + + /** + * Set Integer attribute + */ + @SqeDescriptorKey("ATTRIBUTE integerAtt") + public void setIntegerAtt(Integer value); + + /** + * Get boolean attribute + */ + @SqeDescriptorKey("ATTRIBUTE boolAtt") + public boolean getBoolAtt(); + + /** + * Set boolean attribute + */ + @SqeDescriptorKey("ATTRIBUTE boolAtt") + public void setBoolAtt(boolean value); + + /** + * Get Boolean attribute + */ + @SqeDescriptorKey("ATTRIBUTE booleanAtt") + public Boolean getBooleanAtt(); + + /** + * Set Boolean attribute + */ + @SqeDescriptorKey("ATTRIBUTE booleanAtt") + public void setBooleanAtt(Boolean value); + + /** + * Get String attribute + */ + @SqeDescriptorKey("ATTRIBUTE stringAtt") + public String getStringAtt(); + + /** + * Set String attribute + */ + @SqeDescriptorKey("ATTRIBUTE stringAtt") + public void setStringAtt(String value); + + /** + * Get Date attribute + */ + @SqeDescriptorKey("ATTRIBUTE dateAtt") + public Date getDateAtt(); + + /** + * Set Date attribute + */ + @SqeDescriptorKey("ATTRIBUTE dateAtt") + public void setDateAtt(Date value); + + /** + * Get ObjectName attribute + */ + @SqeDescriptorKey("ATTRIBUTE objectNameAtt") + public ObjectName getObjectNameAtt(); + + /** + * Set ObjectName attribute + */ + @SqeDescriptorKey("ATTRIBUTE objectNameAtt") + public void setObjectNameAtt(ObjectName value); + + /** + * Get SqeParameter attribute + */ + @SqeDescriptorKey("ATTRIBUTE sqeParameterAtt") + public SqeParameter getSqeParameterAtt() throws Exception; + + /** + * Set SqeParameter attribute + */ + @SqeDescriptorKey("ATTRIBUTE sqeParameterAtt") + public void setSqeParameterAtt(SqeParameter value); + + /** + * Set NumOfNotificationSenders attribute + */ + @SqeDescriptorKey("ATTRIBUTE NumOfNotificationSenders") + public void setNumOfNotificationSenders(int value); + + /** + * Set NumOfNotificationSenderLoops attribute + */ + @SqeDescriptorKey("ATTRIBUTE NumOfNotificationSenderLoops") + public void setNumOfNotificationSenderLoops(int value); + + /** + * do nothing + * + */ + @SqeDescriptorKey("OPERATION doNothing") + public void doNothing(); + + /** + * Do take SqeParameter as a parameter + */ + @SqeDescriptorKey("OPERATION doWeird") + public void doWeird(@SqeDescriptorKey("METHOD PARAMETER")SqeParameter param); + + /** + * throw an Exception + * + */ + @SqeDescriptorKey("OPERATION throwException") + public void throwException() throws Exception; + + /** + * throw an Error + * + */ + @SqeDescriptorKey("OPERATION throwError") + public void throwError(); + + /** + * reset all attributes + * + */ + @SqeDescriptorKey("OPERATION reset") + public void reset(); + + /** + * returns the weather for the coming days + * + * @param verbose boolean verbosity + * @return ObjectName + */ + @SqeDescriptorKey("OPERATION getWeather") + public Weather getWeather(@SqeDescriptorKey("METHOD PARAMETER")boolean verbose) + throws java.lang.Exception; + + public enum Weather { + CLOUDY, SUNNY + } + + @SqeDescriptorKey("ATTRIBUTE notifDescriptorAsMapAtt") + public Map getNotifDescriptorAsMapAtt(); + + @SqeDescriptorKey("ATTRIBUTE notifDescriptorAsMapAtt") + public void setNotifDescriptorAsMapAtt(Map value); + + @SqeDescriptorKey("OPERATION sendNotification") + public void sendNotification(@SqeDescriptorKey("METHOD PARAMETER")String notifType); + + @SqeDescriptorKey("OPERATION sendNotificationWave") + public void sendNotificationWave(boolean customNotification) throws Exception; +} diff --git a/jdk/test/javax/management/mxbean/MXBeanExceptionHandlingTest.java b/jdk/test/javax/management/mxbean/MXBeanExceptionHandlingTest.java new file mode 100644 index 00000000000..96071980c1e --- /dev/null +++ b/jdk/test/javax/management/mxbean/MXBeanExceptionHandlingTest.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058865 + * @summary Checks correct exception and error events from NotificationListener + * @author Olivier Lagneau + * @modules java.management + * @library /lib/testlibrary + * @compile Basic.java + * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanExceptionHandlingTest -timeForNotificationInSeconds 3 + */ + + +import java.util.Map; +import java.util.HashMap; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + +import java.lang.management.ManagementFactory; +import javax.management.MBeanServer; +import javax.management.MBeanException; +import javax.management.MBeanServerDelegate; +import javax.management.Notification; +import javax.management.NotificationListener; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.RuntimeErrorException; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +public class MXBeanExceptionHandlingTest implements NotificationListener { + + private static String BASIC_MXBEAN_CLASS_NAME = "Basic"; + + private long timeForNotificationInSeconds = 3L; + private int numOfNotifications = 2; + private BlockingQueue notifList = null; + + + /* + * First Debug properties and arguments are collect in expected + * map (argName, value) format, then calls original test's run method. + */ + public static void main(String args[]) throws Exception { + + System.out.println("================================================="); + + // Parses parameters + Utils.parseDebugProperties(); + Map map = Utils.parseParameters(args) ; + + // Run test + MXBeanExceptionHandlingTest test = new MXBeanExceptionHandlingTest(); + test.run(map); + + } + + protected void parseArgs(Map args) throws Exception { + + String arg = null; + + // Init timeForNotificationInSeconds + // It is the maximum time in seconds we wait for a notification. + arg = (String)args.get("-timeForNotificationInSeconds") ; + if (arg != null) { + timeForNotificationInSeconds = (new Long(arg)).longValue(); + } + + } + + public void run(Map args) { + + System.out.println("MXBeanExceptionHandlingTest::run: Start") ; + int errorCount = 0 ; + + try { + parseArgs(args); + notifList = new ArrayBlockingQueue(numOfNotifications); + + // JMX MbeanServer used inside single VM as if remote. + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + + JMXServiceURL url = new JMXServiceURL("rmi", null, 0); + JMXConnectorServer cs = + JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); + cs.start(); + + JMXServiceURL addr = cs.getAddress(); + JMXConnector cc = JMXConnectorFactory.connect(addr); + MBeanServerConnection mbsc = cc.getMBeanServerConnection(); + + // ---- + System.out.println("Add me as notification listener"); + mbsc.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, + this, null, null); + System.out.println("---- OK\n") ; + + // ---- + System.out.println("Create and register the MBean"); + ObjectName objName = new ObjectName("sqe:type=Basic,protocol=rmi") ; + mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName); + System.out.println("---- OK\n") ; + + // ---- + System.out.println("Call method throwException on our MXBean"); + + try { + mbsc.invoke(objName, "throwException", null, null); + errorCount++; + System.out.println("(ERROR) Did not get awaited MBeanException") ; + } catch (MBeanException mbe) { + System.out.println("(OK) Got awaited MBeanException") ; + Throwable cause = mbe.getCause(); + + if ( cause instanceof java.lang.Exception ) { + System.out.println("(OK) Cause is of the right class") ; + String mess = cause.getMessage(); + + if ( mess.equals(Basic.EXCEPTION_MESSAGE ) ) { + System.out.println("(OK) Cause message is fine") ; + } else { + errorCount++; + System.out.println("(ERROR) Cause has message " + + cause.getMessage() + + " as we expect " + + Basic.EXCEPTION_MESSAGE) ; + } + } else { + errorCount++; + System.out.println("(ERROR) Cause is of class " + + cause.getClass().getName() + + " as we expect java.lang.Exception") ; + } + } catch (Exception e) { + errorCount++; + System.out.println("(ERROR) Did not get awaited MBeanException but " + + e) ; + Utils.printThrowable(e, true); + } + System.out.println("---- DONE\n") ; + + // ---- + System.out.println("Call method throwError on our MXBean"); + + try { + mbsc.invoke(objName, "throwError", null, null); + errorCount++; + System.out.println("(ERROR) Did not get awaited RuntimeErrorException") ; + } catch (RuntimeErrorException ree) { + System.out.println("(OK) Got awaited RuntimeErrorException") ; + Throwable cause = ree.getCause(); + + if ( cause instanceof java.lang.InternalError ) { + System.out.println("(OK) Cause is of the right class") ; + String mess = cause.getMessage(); + + if ( mess.equals(Basic.EXCEPTION_MESSAGE ) ) { + System.out.println("(OK) Cause message is fine") ; + } else { + errorCount++; + System.out.println("(ERROR) Cause has message " + + cause.getMessage() + + " as we expect " + + Basic.EXCEPTION_MESSAGE) ; + } + } else { + errorCount++; + System.out.println("(ERROR) Cause is of class " + + cause.getClass().getName() + + " as we expect java.lang.InternalError") ; + } + } catch (Exception e) { + errorCount++; + System.out.println("(ERROR) Did not get awaited RuntimeErrorException but " + + e) ; + Utils.printThrowable(e, true); + } + System.out.println("---- DONE\n") ; + + // ---- + System.out.println("Unregister the MBean"); + mbsc.unregisterMBean(objName); + System.out.println("---- OK\n") ; + + Thread.sleep(timeForNotificationInSeconds * 1000); + int numOfReceivedNotif = notifList.size(); + + if ( numOfReceivedNotif == numOfNotifications ) { + System.out.println("(OK) We received " + + numOfNotifications + + " Notifications") ; + } else { + errorCount++; + System.out.println("(ERROR) We received " + + numOfReceivedNotif + + " Notifications in place of " + + numOfNotifications) ; + } + } catch(Exception e) { + Utils.printThrowable(e, true) ; + throw new RuntimeException(e); + } + + if ( errorCount == 0 ) { + System.out.println("MXBeanExceptionHandlingTest::run: Done without any error") ; + } else { + System.out.println("MXBeanExceptionHandlingTest::run: Done with " + + errorCount + + " error(s)") ; + throw new RuntimeException("errorCount = " + errorCount); + } + } + + public void handleNotification(Notification notification, Object handback) { + System.out.println("MXBeanExceptionHandlingTest::handleNotification: Received " + + notification); + notifList.add(notification); + } + +} diff --git a/jdk/test/javax/management/mxbean/MXBeanInteropTest1.java b/jdk/test/javax/management/mxbean/MXBeanInteropTest1.java new file mode 100644 index 00000000000..5f0e834a72e --- /dev/null +++ b/jdk/test/javax/management/mxbean/MXBeanInteropTest1.java @@ -0,0 +1,638 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058865 + * @summary Test all MXBeans available by default on the platform + * @author Olivier Lagneau + * @modules java.management + * @library /lib/testlibrary + * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanInteropTest1 + */ + +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import java.lang.management.ClassLoadingMXBean; +import java.lang.management.CompilationMXBean; +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.MemoryManagerMXBean; +import java.lang.management.MemoryPoolMXBean; +import java.lang.management.OperatingSystemMXBean; +import java.lang.management.RuntimeMXBean; +import java.lang.management.ThreadMXBean; + +import javax.management.JMX; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanConstructorInfo; +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.MBeanInfo; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +public class MXBeanInteropTest1 { + + /* + * First Debug properties and arguments are collect in expected + * map (argName, value) format, then calls original test's run method. + */ + public static void main(String args[]) throws Exception { + + System.out.println("================================================="); + + // Parses parameters + Utils.parseDebugProperties(); + Map map = Utils.parseParameters(args) ; + + // Run test + MXBeanInteropTest1 test = new MXBeanInteropTest1(); + test.run(map); + + } + + public void run(Map args) { + + System.out.println("MXBeanInteropTest1::run: Start") ; + int errorCount = 0 ; + + try { + // JMX MbeanServer used inside single VM as if remote. + // MBeanServer mbs = MBeanServerFactory.newMBeanServer(); + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + + JMXServiceURL url = new JMXServiceURL("rmi", null, 0); + JMXConnectorServer cs = + JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); + cs.start(); + + JMXServiceURL addr = cs.getAddress(); + JMXConnector cc = JMXConnectorFactory.connect(addr); + MBeanServerConnection mbsc = cc.getMBeanServerConnection(); + + // Print out registered java.lang.management MXBeans found + // in the remote jvm. + printMBeans(mbsc) ; + + // For each possible kind of JDK 5 defined MXBean, we retrieve its + // MBeanInfo and print it and we call all getters and print + // their output. + errorCount += doClassLoadingMXBeanTest(mbsc) ; + errorCount += doMemoryMXBeanTest(mbsc) ; + errorCount += doThreadMXBeanTest(mbsc) ; + errorCount += doRuntimeMXBeanTest(mbsc) ; + errorCount += doOperatingSystemMXBeanTest(mbsc) ; + errorCount += doCompilationMXBeanTest(mbsc) ; + errorCount += doGarbageCollectorMXBeanTest(mbsc) ; + errorCount += doMemoryManagerMXBeanTest(mbsc) ; + errorCount += doMemoryPoolMXBeanTest(mbsc) ; + + // Terminate the JMX Client + cc.close(); + + } catch(Exception e) { + Utils.printThrowable(e, true) ; + throw new RuntimeException(e); + } + + if ( errorCount == 0 ) { + System.out.println("MXBeanInteropTest1::run: Done without any error") ; + } else { + System.out.println("MXBeanInteropTest1::run: Done with " + + errorCount + + " error(s)") ; + throw new RuntimeException("errorCount = " + errorCount); + } + } + + /** + * Prints all MBeans of domain java.lang. + * They are MBeans related to the JSR 174 that defines + * package java.lang.management. + */ + private static void printMBeans(MBeanServerConnection mbsc) throws Exception { + ObjectName filterName = new ObjectName("java.lang:*"); + Set set = mbsc.queryNames(filterName, null); + + if ( set.size() == 0 ) { + throw new RuntimeException("(ERROR) No MBean found with filter " + + filterName); + } + + System.out.println("---- MBeans found in domain java.lang :"); + + for (Iterator iter = set.iterator(); iter.hasNext(); ) { + System.out.println(iter.next().toString()); + } + + System.out.println("\n") ; + } + + + private final int doClassLoadingMXBeanTest(MBeanServerConnection mbsc) { + int errorCount = 0 ; + System.out.println("---- ClassLoadingMXBean") ; + + try { + ObjectName classLoadingName = + new ObjectName(ManagementFactory.CLASS_LOADING_MXBEAN_NAME) ; + MBeanInfo mbInfo = mbsc.getMBeanInfo(classLoadingName); + errorCount += checkNonEmpty(mbInfo); + System.out.println("getMBeanInfo\t\t" + + mbInfo); + ClassLoadingMXBean classLoading = null; + + classLoading = JMX.newMXBeanProxy(mbsc, + classLoadingName, + ClassLoadingMXBean.class) ; + System.out.println("getLoadedClassCount\t\t" + + classLoading.getLoadedClassCount()); + System.out.println("getTotalLoadedClassCount\t\t" + + classLoading.getTotalLoadedClassCount()); + System.out.println("getUnloadedClassCount\t\t" + + classLoading.getUnloadedClassCount()); + System.out.println("isVerbose\t\t" + + classLoading.isVerbose()); + + System.out.println("---- OK\n") ; + + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++ ; + System.out.println("---- ERROR\n") ; + } + + return errorCount ; + } + + + private final int doMemoryMXBeanTest(MBeanServerConnection mbsc) { + int errorCount = 0 ; + System.out.println("---- MemoryMXBean") ; + + try { + ObjectName memoryName = + new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME) ; + MBeanInfo mbInfo = mbsc.getMBeanInfo(memoryName); + errorCount += checkNonEmpty(mbInfo); + System.out.println("getMBeanInfo\t\t" + + mbInfo); + MemoryMXBean memory = null ; + + memory = + JMX.newMXBeanProxy(mbsc, + memoryName, + MemoryMXBean.class, + true) ; + System.out.println("getMemoryHeapUsage\t\t" + + memory.getHeapMemoryUsage()); + System.out.println("getNonHeapMemoryHeapUsage\t\t" + + memory.getNonHeapMemoryUsage()); + System.out.println("getObjectPendingFinalizationCount\t\t" + + memory.getObjectPendingFinalizationCount()); + System.out.println("isVerbose\t\t" + + memory.isVerbose()); + + System.out.println("---- OK\n") ; + + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++ ; + System.out.println("---- ERROR\n") ; + } + + return errorCount ; + } + + + private final int doThreadMXBeanTest(MBeanServerConnection mbsc) { + int errorCount = 0 ; + System.out.println("---- ThreadMXBean") ; + + try { + ObjectName threadName = + new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME) ; + MBeanInfo mbInfo = mbsc.getMBeanInfo(threadName); + errorCount += checkNonEmpty(mbInfo); + System.out.println("getMBeanInfo\t\t" + mbInfo); + ThreadMXBean thread = null ; + + thread = + JMX.newMXBeanProxy(mbsc, + threadName, + ThreadMXBean.class) ; + System.out.println("findMonitorDeadlockedThreads\t\t" + + thread.findMonitorDeadlockedThreads()); + long[] threadIDs = thread.getAllThreadIds() ; + System.out.println("getAllThreadIds\t\t" + + threadIDs); + + for ( long threadID : threadIDs ) { + System.out.println("getThreadInfo long\t\t" + + thread.getThreadInfo(threadID)); + System.out.println("getThreadInfo long, int\t\t" + + thread.getThreadInfo(threadID, 2)); + } + + System.out.println("getThreadInfo long[]\t\t" + + thread.getThreadInfo(threadIDs)); + System.out.println("getThreadInfo long[], int\t\t" + + thread.getThreadInfo(threadIDs, 2)); + System.out.println("getDaemonThreadCount\t\t" + + thread.getDaemonThreadCount()); + System.out.println("getPeakThreadCount\t\t" + + thread.getPeakThreadCount()); + System.out.println("getThreadCount\t\t" + + thread.getThreadCount()); + System.out.println("getTotalStartedThreadCount\t\t" + + thread.getTotalStartedThreadCount()); + boolean supported = thread.isThreadContentionMonitoringSupported() ; + System.out.println("isThreadContentionMonitoringSupported\t\t" + + supported); + + if ( supported ) { + System.out.println("isThreadContentionMonitoringEnabled\t\t" + + thread.isThreadContentionMonitoringEnabled()); + } + + supported = thread.isThreadCpuTimeSupported() ; + System.out.println("isThreadCpuTimeSupported\t\t" + + supported); + + if ( supported ) { + System.out.println("isThreadCpuTimeEnabled\t\t" + + thread.isThreadCpuTimeEnabled()); + + for (long id : threadIDs) { + System.out.println("getThreadCpuTime(" + id + ")\t\t" + + thread.getThreadCpuTime(id)); + System.out.println("getThreadUserTime(" + id + ")\t\t" + + thread.getThreadUserTime(id)); + } + } + + supported = thread.isCurrentThreadCpuTimeSupported() ; + System.out.println("isCurrentThreadCpuTimeSupported\t\t" + + supported); + + if ( supported ) { + System.out.println("getCurrentThreadCpuTime\t\t" + + thread.getCurrentThreadCpuTime()); + System.out.println("getCurrentThreadUserTime\t\t" + + thread.getCurrentThreadUserTime()); + } + + thread.resetPeakThreadCount() ; + + System.out.println("---- OK\n") ; + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++ ; + System.out.println("---- ERROR\n") ; + } + + return errorCount ; + } + + + private final int doRuntimeMXBeanTest(MBeanServerConnection mbsc) { + int errorCount = 0 ; + System.out.println("---- RuntimeMXBean") ; + + try { + ObjectName runtimeName = + new ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME) ; + MBeanInfo mbInfo = mbsc.getMBeanInfo(runtimeName); + errorCount += checkNonEmpty(mbInfo); + System.out.println("getMBeanInfo\t\t" + mbInfo); + RuntimeMXBean runtime = null; + + runtime = + JMX.newMXBeanProxy(mbsc, + runtimeName, + RuntimeMXBean.class) ; + System.out.println("getClassPath\t\t" + + runtime.getClassPath()); + System.out.println("getInputArguments\t\t" + + runtime.getInputArguments()); + System.out.println("getLibraryPath\t\t" + + runtime.getLibraryPath()); + System.out.println("getManagementSpecVersion\t\t" + + runtime.getManagementSpecVersion()); + System.out.println("getName\t\t" + + runtime.getName()); + System.out.println("getSpecName\t\t" + + runtime.getSpecName()); + System.out.println("getSpecVendor\t\t" + + runtime.getSpecVendor()); + System.out.println("getSpecVersion\t\t" + + runtime.getSpecVersion()); + System.out.println("getStartTime\t\t" + + runtime.getStartTime()); + System.out.println("getSystemProperties\t\t" + + runtime.getSystemProperties()); + System.out.println("getUptime\t\t" + + runtime.getUptime()); + System.out.println("getVmName\t\t" + + runtime.getVmName()); + System.out.println("getVmVendor\t\t" + + runtime.getVmVendor()); + System.out.println("getVmVersion\t\t" + + runtime.getVmVersion()); + boolean supported = runtime.isBootClassPathSupported() ; + System.out.println("isBootClassPathSupported\t\t" + + supported); + + if ( supported ) { + System.out.println("getBootClassPath\t\t" + + runtime.getBootClassPath()); + } + + System.out.println("---- OK\n") ; + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++ ; + System.out.println("---- ERROR\n") ; + } + + return errorCount ; + } + + + private final int doOperatingSystemMXBeanTest(MBeanServerConnection mbsc) { + int errorCount = 0 ; + System.out.println("---- OperatingSystemMXBean") ; + + try { + ObjectName operationName = + new ObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME) ; + MBeanInfo mbInfo = mbsc.getMBeanInfo(operationName); + errorCount += checkNonEmpty(mbInfo); + System.out.println("getMBeanInfo\t\t" + mbInfo); + OperatingSystemMXBean operation = null ; + + operation = + JMX.newMXBeanProxy(mbsc, + operationName, + OperatingSystemMXBean.class) ; + System.out.println("getArch\t\t" + + operation.getArch()); + System.out.println("getAvailableProcessors\t\t" + + operation.getAvailableProcessors()); + System.out.println("getName\t\t" + + operation.getName()); + System.out.println("getVersion\t\t" + + operation.getVersion()); + + System.out.println("---- OK\n") ; + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++ ; + System.out.println("---- ERROR\n") ; + } + + return errorCount ; + } + + + private final int doCompilationMXBeanTest(MBeanServerConnection mbsc) { + int errorCount = 0 ; + System.out.println("---- CompilationMXBean") ; + + try { + ObjectName compilationName = + new ObjectName(ManagementFactory.COMPILATION_MXBEAN_NAME); + + if ( mbsc.isRegistered(compilationName) ) { + MBeanInfo mbInfo = mbsc.getMBeanInfo(compilationName); + errorCount += checkNonEmpty(mbInfo); + System.out.println("getMBeanInfo\t\t" + mbInfo); + CompilationMXBean compilation = null ; + + compilation = + JMX.newMXBeanProxy(mbsc, + compilationName, + CompilationMXBean.class) ; + System.out.println("getName\t\t" + + compilation.getName()); + boolean supported = + compilation.isCompilationTimeMonitoringSupported() ; + System.out.println("isCompilationTimeMonitoringSupported\t\t" + + supported); + + if ( supported ) { + System.out.println("getTotalCompilationTime\t\t" + + compilation.getTotalCompilationTime()); + } + } + + System.out.println("---- OK\n") ; + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++ ; + System.out.println("---- ERROR\n") ; + } + + return errorCount ; + } + + + private final int doGarbageCollectorMXBeanTest(MBeanServerConnection mbsc) { + int errorCount = 0 ; + System.out.println("---- GarbageCollectorMXBean") ; + + try { + ObjectName filterName = + new ObjectName(ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + + ",*"); + Set onSet = mbsc.queryNames(filterName, null); + + for (Iterator iter = onSet.iterator(); iter.hasNext(); ) { + ObjectName garbageName = iter.next() ; + System.out.println("-------- " + garbageName) ; + MBeanInfo mbInfo = mbsc.getMBeanInfo(garbageName); + errorCount += checkNonEmpty(mbInfo); + System.out.println("getMBeanInfo\t\t" + mbInfo); + GarbageCollectorMXBean garbage = null ; + + garbage = + JMX.newMXBeanProxy(mbsc, + garbageName, + GarbageCollectorMXBean.class) ; + System.out.println("getCollectionCount\t\t" + + garbage.getCollectionCount()); + System.out.println("getCollectionTime\t\t" + + garbage.getCollectionTime()); + } + + System.out.println("---- OK\n") ; + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++ ; + System.out.println("---- ERROR\n") ; + } + + return errorCount ; + } + + + private final int doMemoryManagerMXBeanTest(MBeanServerConnection mbsc) { + int errorCount = 0 ; + System.out.println("---- MemoryManagerMXBean") ; + + try { + ObjectName filterName = + new ObjectName(ManagementFactory.MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE + + ",*"); + Set onSet = mbsc.queryNames(filterName, null); + + for (Iterator iter = onSet.iterator(); iter.hasNext(); ) { + ObjectName memoryManagerName = iter.next() ; + System.out.println("-------- " + memoryManagerName) ; + MBeanInfo mbInfo = mbsc.getMBeanInfo(memoryManagerName); + System.out.println("getMBeanInfo\t\t" + mbInfo); + errorCount += checkNonEmpty(mbInfo); + MemoryManagerMXBean memoryManager = null; + + memoryManager = + JMX.newMXBeanProxy(mbsc, + memoryManagerName, + MemoryManagerMXBean.class) ; + System.out.println("getMemoryPoolNames\t\t" + + Arrays.deepToString(memoryManager.getMemoryPoolNames())); + System.out.println("getName\t\t" + + memoryManager.getName()); + System.out.println("isValid\t\t" + + memoryManager.isValid()); + } + + System.out.println("---- OK\n") ; + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++ ; + System.out.println("---- ERROR\n") ; + } + + return errorCount ; + } + + + private final int doMemoryPoolMXBeanTest(MBeanServerConnection mbsc) { + int errorCount = 0 ; + System.out.println("---- MemoryPoolMXBean") ; + + try { + ObjectName filterName = + new ObjectName(ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + + ",*"); + Set onSet = mbsc.queryNames(filterName, null); + + for (Iterator iter = onSet.iterator(); iter.hasNext(); ) { + ObjectName memoryPoolName = iter.next() ; + System.out.println("-------- " + memoryPoolName) ; + MBeanInfo mbInfo = mbsc.getMBeanInfo(memoryPoolName); + errorCount += checkNonEmpty(mbInfo); + System.out.println("getMBeanInfo\t\t" + mbInfo); + MemoryPoolMXBean memoryPool = null; + + memoryPool = + JMX.newMXBeanProxy(mbsc, + memoryPoolName, + MemoryPoolMXBean.class, + true) ; + System.out.println("getCollectionUsage\t\t" + + memoryPool.getCollectionUsage()); + System.out.println("getMemoryManagerNames\t\t" + + Arrays.deepToString(memoryPool.getMemoryManagerNames())); + System.out.println("getName\t\t" + + memoryPool.getName()); + System.out.println("getPeakUsage\t\t" + + memoryPool.getPeakUsage()); + System.out.println("getType\t\t" + + memoryPool.getType()); + System.out.println("getUsage\t\t" + + memoryPool.getUsage()); + System.out.println("isValid\t\t" + + memoryPool.isValid()); + boolean supported = memoryPool.isUsageThresholdSupported() ; + System.out.println("isUsageThresholdSupported\t\t" + + supported); + + if ( supported ) { + System.out.println("getUsageThreshold\t\t" + + memoryPool.getUsageThreshold()); + System.out.println("isUsageThresholdExceeded\t\t" + + memoryPool.isUsageThresholdExceeded()); + System.out.println("getUsageThresholdCount\t\t" + + memoryPool.getUsageThresholdCount()); + } + + supported = memoryPool.isCollectionUsageThresholdSupported() ; + System.out.println("isCollectionUsageThresholdSupported\t\t" + + supported); + + if ( supported ) { + System.out.println("getCollectionUsageThreshold\t\t" + + memoryPool.getCollectionUsageThreshold()); + System.out.println("getCollectionUsageThresholdCount\t\t" + + memoryPool.getCollectionUsageThresholdCount()); + System.out.println("isCollectionUsageThresholdExceeded\t\t" + + memoryPool.isCollectionUsageThresholdExceeded()); + } + + memoryPool.resetPeakUsage(); + } + + System.out.println("---- OK\n") ; + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++ ; + System.out.println("---- ERROR\n") ; + } + + return errorCount ; + } + + + private int checkNonEmpty(MBeanInfo mbi) { + if ( mbi.toString().length() == 0 ) { + System.out.println("(ERROR) MBeanInfo is empty !"); + return 1; + } else { + return 0; + } + } + +} diff --git a/jdk/test/javax/management/mxbean/MXBeanInteropTest2.java b/jdk/test/javax/management/mxbean/MXBeanInteropTest2.java new file mode 100644 index 00000000000..4c713574100 --- /dev/null +++ b/jdk/test/javax/management/mxbean/MXBeanInteropTest2.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058865 + * @summary Checks access to test MXBean + * @author Olivier Lagneau + * @modules java.management + * @library /lib/testlibrary + * @compile Basic.java + * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanInteropTest2 + */ + +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import javax.management.Attribute; +import javax.management.JMX; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanConstructorInfo; +import javax.management.MBeanServer; +import java.lang.management.ManagementFactory; +import javax.management.MBeanInfo; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +public class MXBeanInteropTest2 { + + private static String BASIC_MXBEAN_CLASS_NAME = "Basic"; + + /* + * First Debug properties and arguments are collect in expected + * map (argName, value) format, then calls original test's run method. + */ + public static void main(String args[]) throws Exception { + + System.out.println("================================================="); + + // Parses parameters + Utils.parseDebugProperties(); + Map map = Utils.parseParameters(args) ; + + // Run test + MXBeanInteropTest2 test = new MXBeanInteropTest2(); + test.run(map); + + } + + public void run(Map args) { + + System.out.println("MXBeanInteropTest2::run: Start") ; + int errorCount = 0 ; + + try { + // JMX MbeanServer used inside single VM as if remote. + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + + JMXServiceURL url = new JMXServiceURL("rmi", null, 0); + JMXConnectorServer cs = + JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); + cs.start(); + + JMXServiceURL addr = cs.getAddress(); + JMXConnector cc = JMXConnectorFactory.connect(addr); + MBeanServerConnection mbsc = cc.getMBeanServerConnection(); + + // Prints all MBeans whatever the domain is. + printMBeans(mbsc) ; + + // Call test body + errorCount += doBasicMXBeanTest(mbsc) ; + + // Terminate the JMX Client + cc.close(); + + } catch(Exception e) { + Utils.printThrowable(e, true) ; + throw new RuntimeException(e); + } + + if ( errorCount == 0 ) { + System.out.println("MXBeanInteropTest2::run: Done without any error") ; + } else { + System.out.println("MXBeanInteropTest2::run: Done with " + + errorCount + + " error(s)") ; + throw new RuntimeException("errorCount = " + errorCount); + } + } + + + /** + * Prints all MBeans whatever the domain is. + */ + private static void printMBeans(MBeanServerConnection mbsc) throws Exception { + Set set = mbsc.queryNames(null, null); + System.out.println("---- MBeans found :"); + + for (Iterator iter = set.iterator(); iter.hasNext(); ) { + System.out.println(iter.next().toString()); + } + + System.out.println("\n") ; + } + + + private final int doBasicMXBeanTest(MBeanServerConnection mbsc) { + int errorCount = 0 ; + System.out.println("---- doBasicMXBeanTest") ; + + try { + ObjectName objName = + new ObjectName("sqe:type=BasicMXBean") ; + mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName); + MBeanInfo mbInfo = mbsc.getMBeanInfo(objName); + printMBeanInfo(mbInfo); + System.out.println("---- OK\n") ; + System.out.println("getMBeanInfo\t\t" + + mbInfo); + System.out.println("---- OK\n") ; + + System.out.println("Check mxbean field in the MBeanInfo"); + String mxbeanField = + (String)mbInfo.getDescriptor().getFieldValue(JMX.MXBEAN_FIELD); + + if ( mxbeanField == null || ! mxbeanField.equals("true")) { + System.out.println("---- ERROR : Improper mxbean field value " + + mxbeanField); + errorCount++; + } + System.out.println("---- OK\n") ; + + System.out.println("Set attribute ObjectNameAtt"); + Attribute att = new Attribute("ObjectNameAtt", objName); + mbsc.setAttribute(objName, att); + ObjectName value = + (ObjectName)mbsc.getAttribute(objName, "ObjectNameAtt"); + + if ( ! value.equals(objName) ) { + errorCount++; + System.out.println("---- ERROR : setAttribute failed, got " + + value + + " while expecting " + + objName); + } + System.out.println("---- OK\n") ; + + System.out.println("Call operation doNothing"); + mbsc.invoke(objName, "doNothing", null, null); + System.out.println("---- OK\n") ; + + System.out.println("Call operation getWeather"); + Object weather = mbsc.invoke(objName, + "getWeather", + new Object[]{Boolean.TRUE}, + new String[]{"boolean"}); + System.out.println("Weather is " + weather); + System.out.println("---- OK\n") ; + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++ ; + System.out.println("---- ERROR\n") ; + } + + return errorCount ; + } + + private void printMBeanInfo(MBeanInfo mbInfo) { + System.out.println("Description " + mbInfo.getDescription()); + + for (MBeanConstructorInfo ctor : mbInfo.getConstructors()) { + System.out.println("Constructor " + ctor.getName()); + } + + for (MBeanAttributeInfo att : mbInfo.getAttributes()) { + System.out.println("Attribute " + att.getName() + + " [" + att.getType() + "]"); + } + + for (MBeanOperationInfo oper : mbInfo.getOperations()) { + System.out.println("Operation " + oper.getName()); + } + + for (MBeanNotificationInfo notif : mbInfo.getNotifications()) { + System.out.println("Notification " + notif.getName()); + } + } +} diff --git a/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java b/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java new file mode 100644 index 00000000000..699260777d1 --- /dev/null +++ b/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058865 + * @summary Checks correct collection of MXBean's class after unregistration + * @author Olivier Lagneau + * @modules java.management + * @library /lib/testlibrary + * @run main/othervm/timeout=300 MXBeanLoadingTest1 + */ + +import java.lang.ref.WeakReference; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Map; +import javax.management.Attribute; +import javax.management.JMX; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.MXBean; +import javax.management.ObjectName; +import javax.management.loading.PrivateMLet; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; + +public class MXBeanLoadingTest1 { + + public static void main(String[] args) throws Exception { + MXBeanLoadingTest1 test = new MXBeanLoadingTest1(); + test.run((Map)null); + } + + + public void run(Map args) { + + System.out.println("MXBeanLoadingTest1::run: Start") ; + + try { + System.out.println("We ensure no reference is retained on MXBean class" + + " after it is unregistered. We take time to perform" + + " some little extra check of Descriptors, MBean*Info."); + + ClassLoader myClassLoader = MXBeanLoadingTest1.class.getClassLoader(); + + if (!(myClassLoader instanceof URLClassLoader)) { + String message = "(ERROR) Test's class loader is not " + + "a URLClassLoader"; + System.out.println(message); + throw new RuntimeException(message); + } + + URLClassLoader myURLClassLoader = (URLClassLoader) myClassLoader; + URL[] urls = myURLClassLoader.getURLs(); + PrivateMLet mlet = new PrivateMLet(urls, null, false); + Class shadowClass = mlet.loadClass(TestMXBean.class.getName()); + + if (shadowClass == TestMXBean.class) { + String message = "(ERROR) MLet got original TestMXBean, not shadow"; + System.out.println(message); + throw new RuntimeException(message); + } + shadowClass = null; + + MBeanServer mbs = MBeanServerFactory.createMBeanServer(); + ObjectName mletName = new ObjectName("x:type=mlet"); + mbs.registerMBean(mlet, mletName); + + ObjectName testName = new ObjectName("x:type=test"); + mbs.createMBean(Test.class.getName(), testName, mletName); + + // That test fails because the MXBean instance is accessed via + // a delegate OpenMBean which has + ClassLoader testLoader = mbs.getClassLoaderFor(testName); + + if (testLoader != mlet) { + System.out.println("MLet " + mlet); + String message = "(ERROR) MXBean's class loader is not MLet: " + + testLoader; + System.out.println(message); + throw new RuntimeException(message); + } + testLoader = null; + + + // Cycle get/set/get of the attribute of type Luis. + // We check the set is effective. + CompositeData cd_B = (CompositeData)mbs.getAttribute(testName, "B"); + CompositeType compType_B = cd_B.getCompositeType(); + + CompositeDataSupport cds_B = + new CompositeDataSupport(compType_B, + new String[]{"something"}, + new Object[]{Integer.valueOf(13)}); + Attribute myAtt = new Attribute("B", cds_B); + mbs.setAttribute(testName, myAtt); + + CompositeData cd_B2 = (CompositeData)mbs.getAttribute(testName, "B"); + + if ( ((Integer)cd_B2.get("something")).intValue() != 13 ) { + String message = "(ERROR) The setAttribute of att B did not work;" + + " expect Luis.something = 13 but got " + + cd_B2.get("something"); + System.out.println(message); + throw new RuntimeException(message); + } + + MBeanInfo info = mbs.getMBeanInfo(testName); + String mxbeanField = + (String)info.getDescriptor().getFieldValue(JMX.MXBEAN_FIELD); + + if ( mxbeanField == null || ! mxbeanField.equals("true")) { + String message = "(ERROR) Improper mxbean field value " + + mxbeanField; + System.out.println(message); + throw new RuntimeException(message); + } + + // Check the 2 attributes. + MBeanAttributeInfo[] attrs = info.getAttributes(); + + if ( attrs.length == 2 ) { + for (MBeanAttributeInfo mbai : attrs) { + String originalTypeFieldValue = + (String)mbai.getDescriptor().getFieldValue(JMX.ORIGINAL_TYPE_FIELD); + OpenType openTypeFieldValue = + (OpenType)mbai.getDescriptor().getFieldValue(JMX.OPEN_TYPE_FIELD); + + if ( mbai.getName().equals("A") ) { + if ( !mbai.isReadable() || !mbai.isWritable() + || mbai.isIs() + || !mbai.getType().equals("int") ) { + String message = "(ERROR) Unexpected MBeanAttributeInfo for A " + + mbai; + System.out.println(message); + throw new RuntimeException(message); + } + + if ( ! originalTypeFieldValue.equals("int") ) { + String message = "(ERROR) Unexpected originalType in Descriptor for A " + + originalTypeFieldValue; + System.out.println(message); + throw new RuntimeException(message); + } + + if ( ! openTypeFieldValue.equals(SimpleType.INTEGER) ) { + String message = "(ERROR) Unexpected openType in Descriptor for A " + + originalTypeFieldValue; + System.out.println(message); + throw new RuntimeException(message); + } + } else if ( mbai.getName().equals("B") ) { + if ( !mbai.isReadable() || !mbai.isWritable() + || mbai.isIs() + || !mbai.getType().equals("javax.management.openmbean.CompositeData") ) { + String message = "(ERROR) Unexpected MBeanAttributeInfo for B " + + mbai; + System.out.println(message); + throw new RuntimeException(message); + } + + if ( ! originalTypeFieldValue.equals(Luis.class.getName()) ) { + String message = "(ERROR) Unexpected originalType in Descriptor for B " + + originalTypeFieldValue; + System.out.println(message); + throw new RuntimeException(message); + } + + if ( ! openTypeFieldValue.equals(compType_B) ) { + String message = "(ERROR) Unexpected openType in Descriptor for B " + + compType_B; + System.out.println(message); + throw new RuntimeException(message); + } + } else { + String message = "(ERROR) Unknown attribute name"; + System.out.println(message); + throw new RuntimeException(message); + } + } + } else { + String message = "(ERROR) Unexpected MBeanAttributeInfo array" + + Arrays.deepToString(attrs); + System.out.println(message); + throw new RuntimeException(message); + } + + // Check the MXBean operation. + MBeanOperationInfo[] ops = info.getOperations(); + // The impact is ACTION_INFO as for a standard MBean it is UNKNOWN, + // logged 6320104. + if (ops.length != 1 || !ops[0].getName().equals("bogus") + || ops[0].getSignature().length > 0 + || !ops[0].getReturnType().equals("void")) { + String message = "(ERROR) Unexpected MBeanOperationInfo array " + + Arrays.deepToString(ops); + System.out.println(message); + throw new RuntimeException(message); + } + + String originalTypeFieldValue = + (String)ops[0].getDescriptor().getFieldValue(JMX.ORIGINAL_TYPE_FIELD); + OpenType openTypeFieldValue = + (OpenType)ops[0].getDescriptor().getFieldValue(JMX.OPEN_TYPE_FIELD); + + if ( ! originalTypeFieldValue.equals("void") ) { + String message = "(ERROR) Unexpected originalType in Descriptor for bogus " + + originalTypeFieldValue; + System.out.println(message); + throw new RuntimeException(message); + } + + if ( ! openTypeFieldValue.equals(SimpleType.VOID) ) { + String message = "(ERROR) Unexpected openType in Descriptor for bogus " + + originalTypeFieldValue; + System.out.println(message); + throw new RuntimeException(message); + } + + // Check there is 2 constructors. + if (info.getConstructors().length != 2) { + String message = "(ERROR) Wrong number of constructors " + + "in introspected bean: " + + Arrays.asList(info.getConstructors()); + System.out.println(message); + throw new RuntimeException(message); + } + + // Check MXBean class name. + if (!info.getClassName().endsWith("Test")) { + String message = "(ERROR) Wrong info class name: " + + info.getClassName(); + System.out.println(message); + throw new RuntimeException(message); + } + + mbs.unregisterMBean(testName); + mbs.unregisterMBean(mletName); + + WeakReference mletRef = + new WeakReference(mlet); + mlet = null; + + System.out.println("MXBean registered and unregistered, waiting for " + + "garbage collector to collect class loader"); + + for (int i = 0; i < 10000 && mletRef.get() != null; i++) { + System.gc(); + Thread.sleep(1); + } + + if (mletRef.get() == null) + System.out.println("(OK) class loader was GC'd"); + else { + String message = "(ERROR) Class loader was not GC'd"; + System.out.println(message); + throw new RuntimeException(message); + } + } catch(Exception e) { + Utils.printThrowable(e, true) ; + throw new RuntimeException(e); + } + + System.out.println("MXBeanLoadingTest1::run: Done without any error") ; + } + + + // I agree the use of the MXBean annotation and the MXBean suffix for the + // interface name are redundant but however harmless. + // + @MXBean(true) + public static interface TestMXBean { + public void bogus(); + public int getA(); + public void setA(int a); + public Luis getB(); + public void setB(Luis mi); + } + + + public static class Test implements TestMXBean { + private Luis luis = new Luis() ; + public Test() {} + public Test(int x) {} + + public void bogus() {} + public int getA() {return 0;} + public void setA(int a) {} + public Luis getB() {return this.luis;} + public void setB(Luis luis) {this.luis = luis;} + } + + + public static class Luis { + private int something = 0; + public Luis() {} + public int getSomething() {return something;} + public void setSomething(int v) {something = v;} + public void doNothing() {} + } +} diff --git a/jdk/test/javax/management/mxbean/MXBeanNotifTest.java b/jdk/test/javax/management/mxbean/MXBeanNotifTest.java new file mode 100644 index 00000000000..021731e4fa7 --- /dev/null +++ b/jdk/test/javax/management/mxbean/MXBeanNotifTest.java @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058865 + * @summary Checks MXBean proper registration both as its implementation class and interface + * @author Olivier Lagneau + * @modules java.management + * @library /lib/testlibrary + * @compile Basic.java + * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanNotifTest -numOfNotifications 239 -timeForNotificationInSeconds 4 + */ + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; + +import java.lang.management.ManagementFactory; + +import javax.management.Attribute; +import javax.management.Descriptor; +import javax.management.ImmutableDescriptor; +import javax.management.MBeanServer; +import javax.management.MBeanInfo; +import javax.management.MBeanNotificationInfo; +import javax.management.Notification; +import javax.management.NotificationListener; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; + +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; +import javax.management.openmbean.TabularData; +import javax.management.openmbean.TabularDataSupport; +import javax.management.openmbean.TabularType; + +public class MXBeanNotifTest implements NotificationListener { + + private static String BASIC_MXBEAN_CLASS_NAME = "Basic"; + private static String BASIC_MXBEAN_INTERFACE_NAME = "BasicMXBean"; + + private long timeForNotificationInSeconds = 3L; + private int numOfNotifications = 1; + private BlockingQueue notifList = null; + private int numOfNotifDescriptorElements = 13; + + /* + * First Debug properties and arguments are collect in expected + * map (argName, value) format, then calls original test's run method. + */ + public static void main(String args[]) throws Exception { + + System.out.println("================================================="); + + // Parses parameters + Utils.parseDebugProperties(); + Map map = Utils.parseParameters(args) ; + + // Run test + MXBeanNotifTest test = new MXBeanNotifTest(); + test.run(map); + + } + + protected void parseArgs(Map args) throws Exception { + + String arg = null; + + // Init numOfNotifications + // It is the number of notifications we should trigger and check. + arg = (String)args.get("-numOfNotifications") ; + if (arg != null) { + numOfNotifications = (new Integer(arg)).intValue(); + } + + // Init timeForNotificationInSeconds + // It is the maximum time in seconds we wait for each notification. + arg = (String)args.get("-timeForEachNotificationInSeconds") ; + if (arg != null) { + timeForNotificationInSeconds = (new Long(arg)).longValue(); + } + + } + + public void run(Map args) { + + System.out.println("MXBeanNotifTest::run: Start") ; + int errorCount = 0 ; + + try { + parseArgs(args); + notifList = new ArrayBlockingQueue(numOfNotifications); + + // JMX MbeanServer used inside single VM as if remote. + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + + JMXServiceURL url = new JMXServiceURL("rmi", null, 0); + JMXConnectorServer cs = + JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); + cs.start(); + + JMXServiceURL addr = cs.getAddress(); + JMXConnector cc = JMXConnectorFactory.connect(addr); + MBeanServerConnection mbsc = cc.getMBeanServerConnection(); + + // ---- + System.out.println("MXBeanNotifTest::run: Create and register the MBean"); + ObjectName objName = new ObjectName("sqe:type=Basic,protocol=rmi") ; + mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName); + System.out.println("---- OK\n") ; + + // ---- + System.out.println("MXBeanNotifTest::run: Add me as notification listener"); + mbsc.addNotificationListener(objName, this, null, null); + + // ---- + System.out.println("MXBeanNotifTest::run: Retrieve the Descriptor" + + " that should be in MBeanNotificationInfo"); + TabularData tabData = + (TabularData)mbsc.getAttribute(objName, "NotifDescriptorAsMapAtt"); + Map descrMap = new HashMap<>(); + + for (Iterator it = tabData.values().iterator(); it.hasNext(); ) { + CompositeData compData = (CompositeData)it.next(); + descrMap.put((String)compData.get("key"), + (String)compData.get("value")); + } + + Descriptor refNotifDescriptor = new ImmutableDescriptor(descrMap); + System.out.println("---- OK\n") ; + + // ---- + // Because the MBean holding the targeted attribute is MXBean, we + // should use for the setAttribute a converted form for the + // attribute value as described by the MXBean mapping rules. + // This explains all that lovely stuff for creating a + // TabularDataSupport. + // + // WARNING : the MBeanInfo of the MXBean used on opposite side + // is computed when the MBean is registered. + // It means the Descriptor considered for the MBeanNotificationInfo + // is not the one we set in the lines below, it is too late. + // However, we check that set is harmless when we check + // the MBeanNotificationInfo. + // + System.out.println("MXBeanNotifTest::run: Set a Map" + + " attribute"); + String typeName = + "java.util.Map"; + String[] keyValue = new String[] {"key", "value"}; + OpenType[] openTypes = + new OpenType[] {SimpleType.STRING, SimpleType.STRING}; + CompositeType rowType = new CompositeType(typeName, typeName, + keyValue, keyValue, openTypes); + TabularType tabType = new TabularType(typeName, typeName, + rowType, new String[]{"key"}); + TabularDataSupport convertedDescrMap = + new TabularDataSupport(tabType); + + for (int i = 0; i < numOfNotifDescriptorElements; i++) { + Object[] descrValue = {"field" + i, "value" + i}; + CompositeData data = + new CompositeDataSupport(rowType, keyValue, descrValue); + convertedDescrMap.put(data); + } + + Attribute descrAtt = + new Attribute("NotifDescriptorAsMapAtt", convertedDescrMap); + mbsc.setAttribute(objName, descrAtt); + System.out.println("---- OK\n") ; + + // ---- + System.out.println("MXBeanNotifTest::run: Compare the Descriptor from" + + " the MBeanNotificationInfo against a reference"); + MBeanInfo mbInfo = mbsc.getMBeanInfo(objName); + errorCount += checkMBeanInfo(mbInfo, refNotifDescriptor); + System.out.println("---- DONE\n") ; + + // ---- + System.out.println("Check isInstanceOf(Basic)"); + + if ( ! mbsc.isInstanceOf(objName, BASIC_MXBEAN_CLASS_NAME) ) { + errorCount++; + System.out.println("---- ERROR isInstanceOf returned false\n") ; + } else { + System.out.println("---- OK\n") ; + } + + // ---- + System.out.println("Check isInstanceOf(BasicMXBean)"); + + if ( ! mbsc.isInstanceOf(objName, BASIC_MXBEAN_INTERFACE_NAME) ) { + errorCount++; + System.out.println("---- ERROR isInstanceOf returned false\n") ; + } else { + System.out.println("---- OK\n") ; + } + + // ---- + System.out.println("MXBeanNotifTest::run: Ask for " + + numOfNotifications + " notification(s)"); + Object[] sendNotifParam = new Object[1]; + String[] sendNotifSig = new String[]{"java.lang.String"}; + + for (int i = 0; i < numOfNotifications; i++) { + // Select which type of notification we ask for + if ( i % 2 == 0 ) { + sendNotifParam[0] = Basic.NOTIF_TYPE_0; + } else { + sendNotifParam[0] = Basic.NOTIF_TYPE_1; + } + + // Trigger notification emission + mbsc.invoke(objName, + "sendNotification", + sendNotifParam, + sendNotifSig); + + // Wait for it then check it when it comes early enough + Notification notif = + notifList.poll(timeForNotificationInSeconds, + TimeUnit.SECONDS) ; + // The very first notification is likely to come in slower than + // all the others. Because that test isn't targeting the speed + // notifications are delivered with, we prefer to secure it. + if (i == 0 && notif == null) { + System.out.println("MXBeanNotifTest::run: Wait extra " + + timeForNotificationInSeconds + " second(s) the " + + " very first notification"); + notif = notifList.poll(timeForNotificationInSeconds, + TimeUnit.SECONDS); + } + + if ( notif == null ) { + errorCount++; + System.out.println("---- ERROR No notification received" + + " within allocated " + timeForNotificationInSeconds + + " second(s) !"); + } else { + errorCount += + checkNotification(notif, + (String)sendNotifParam[0], + Basic.NOTIFICATION_MESSAGE, + objName); + } + } + + int toc = 0; + while ( notifList.size() < 2 && toc < 10 ) { + Thread.sleep(499); + toc++; + } + System.out.println("---- DONE\n") ; + } catch(Exception e) { + Utils.printThrowable(e, true) ; + throw new RuntimeException(e); + } + + if ( errorCount == 0 ) { + System.out.println("MXBeanNotifTest::run: Done without any error") ; + } else { + System.out.println("MXBeanNotifTest::run: Done with " + + errorCount + + " error(s)") ; + throw new RuntimeException("errorCount = " + errorCount); + } + } + + + private int checkMBeanInfo(MBeanInfo mbi, Descriptor refDescr) { + MBeanNotificationInfo[] notifsInfo = mbi.getNotifications(); + int res = 0; + + for (MBeanNotificationInfo mbni : notifsInfo) { + if ( mbni.getDescriptor().equals(refDescr) ) { + System.out.println("(OK)"); + } else { + System.out.println("(ERROR) Descriptor of the notification is " + + mbni.getDescriptor() + + " as we expect " + + refDescr); + res++; + } + } + + return res; + } + + + private int checkNotification(Notification notif, + String refType, + String refMessage, + ObjectName refSource) { + int res = 0; + + Utils.debug(Utils.DEBUG_VERBOSE, + "\t getSource " + notif.getSource()); + Utils.debug(Utils.DEBUG_VERBOSE, + "\t getMessage " + notif.getMessage()); + Utils.debug(Utils.DEBUG_VERBOSE, + "\t getSequenceNumber " + notif.getSequenceNumber()); + Utils.debug(Utils.DEBUG_VERBOSE, + "\t getTimeStamp " + notif.getTimeStamp()); + Utils.debug(Utils.DEBUG_VERBOSE, + "\t getType " + notif.getType()); + Utils.debug(Utils.DEBUG_VERBOSE, + "\t getUserData " + notif.getUserData()); + + if ( ! notif.getType().equals(refType) ) { + res++; + System.out.println("(ERROR) Type is not " + + refType + " in notification\n" + notif); + } else { + if ( notif.getType().equals(Basic.NOTIF_TYPE_0) + && ! (notif instanceof javax.management.Notification) ) { + res++; + System.out.println("(ERROR) Notification is not instance of " + + " javax.management.Notification but rather " + + notif.getClass().getName()); + } else if ( notif.getType().equals(Basic.NOTIF_TYPE_1) + && ! (notif instanceof SqeNotification) ) { + res++; + System.out.println("(ERROR) Notification is not instance of " + + " javasoft.sqe.jmx.share.SqeNotification but rather " + + notif.getClass().getName()); + } + } + + if ( ! notif.getMessage().equals(refMessage) ) { + res++; + System.out.println("(ERROR) Message is not " + + refMessage + " in notification\n" + notif); + } + + if ( ! notif.getSource().equals(refSource) ) { + res++; + System.out.println("(ERROR) Source is not " + + refSource + " in notification\n" + notif); + } + + return res; + } + + public void handleNotification(Notification notification, Object handback) { + Utils.debug(Utils.DEBUG_VERBOSE, + "MXBeanNotifTest::handleNotification: Received " + + notification); + notifList.add(notification); + } + +} diff --git a/jdk/test/javax/management/mxbean/MXBeanWeirdParamTest.java b/jdk/test/javax/management/mxbean/MXBeanWeirdParamTest.java new file mode 100644 index 00000000000..358233f79a3 --- /dev/null +++ b/jdk/test/javax/management/mxbean/MXBeanWeirdParamTest.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058865 + * @summary Checks that a serialized instance is not transmitted from an MXBean. + * All the communication should be done via Open Types + * @author Olivier Lagneau + * @modules java.management + * @library /lib/testlibrary + * @compile Basic.java + * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanWeirdParamTest + */ + +import java.util.Map; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import java.lang.Process; +import java.lang.management.ManagementFactory; + +import javax.management.MBeanServer; +import javax.management.MBeanServerConnection; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +import javax.management.ObjectName; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; +import javax.management.openmbean.TabularDataSupport; +import javax.management.openmbean.TabularType; + +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.JDKToolFinder; + +public class MXBeanWeirdParamTest { + + private static String BASIC_MXBEAN_CLASS_NAME = "Basic"; + + private static final String CLIENT_CLASS_MAIN = + "MXBeanWeirdParamTest$ClientSide"; + + private JMXConnectorServer cs; + + /* + * First Debug properties and arguments are collect in expected + * map (argName, value) format, then calls original test's run method. + */ + public static void main(String args[]) throws Exception { + + System.out.println("================================================="); + + // Parses parameters + Utils.parseDebugProperties(); + Map map = Utils.parseParameters(args) ; + + // Run test + MXBeanWeirdParamTest test = new MXBeanWeirdParamTest(); + test.run(map); + + } + + /* + * Create the MBeansServe side of the test and returns its address + */ + private JMXServiceURL createServerSide() throws Exception { + final int NINETY_SECONDS = 90; + + // We will use the platform mbean server + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + + JMXServiceURL url = new JMXServiceURL("rmi", null, 0); + cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); + cs.start(); + + Utils.waitReady(cs, NINETY_SECONDS); + + JMXServiceURL addr = cs.getAddress(); + return addr; + } + + + /* + * Creating command-line for running subprocess JVM: + * + * JVM command line is like: + * {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main + * + * {defaultopts} are the default java options set by the framework. + * + */ + private List buildCommandLine() { + List opts = new ArrayList<>(); + opts.add(JDKToolFinder.getJDKTool("java")); + opts.addAll(Arrays.asList(jdk.testlibrary.Utils.getTestJavaOpts())); + // We need to set WEIRD_PARAM propertty on the client-side + opts.add("-DWEIRD_PARAM"); + opts.add("-cp"); + opts.add(System.getProperty("test.class.path", "test.class.path")); + opts.add(CLIENT_CLASS_MAIN); + + return opts; + } + + /** + * Runs MXBeanWeirdParamTest$ClientSide with the passed options and redirects + * subprocess standard I/O to the current (parent) process. This provides a + * trace of what happens in the subprocess while it is runnning (and before + * it terminates). + * + * @param serviceUrlStr string representing the JMX service Url to connect to. + */ + private int runClientSide(String serviceUrlStr) throws Exception { + + // Building command-line + List opts = buildCommandLine(); + opts.add(serviceUrlStr); + + // Launch separate JVM subprocess + int exitCode = 0; + String[] optsArray = opts.toArray(new String[0]); + ProcessBuilder pb = new ProcessBuilder(optsArray); + Process p = ProcessTools.startProcess("MXBeanWeirdParamTest$ClientSide", pb); + + // Handling end of subprocess + try { + exitCode = p.waitFor(); + if (exitCode != 0) { + System.out.println( + "Subprocess unexpected exit value of [" + exitCode + + "]. Expected 0.\n"); + } + } catch (InterruptedException e) { + System.out.println("Parent process interrupted with exception : \n " + e + " :" ); + + // Parent thread unknown state, killing subprocess. + p.destroyForcibly(); + + throw new RuntimeException( + "Parent process interrupted with exception : \n " + e + " :" ); + } finally { + return exitCode; + } + + } + + public void run(Map args) throws Exception { + + System.out.println("MXBeanWeirdParamTest::run: Start") ; + int errorCount = 0; + + try { + // Initialise the server side + JMXServiceURL urlToUse = createServerSide(); + + // Run client side + errorCount = runClientSide(urlToUse.toString()); + + if ( errorCount == 0 ) { + System.out.println("MXBeanWeirdParamTest::run: Done without any error") ; + } else { + System.out.println("MXBeanWeirdParamTest::run: Done with " + + errorCount + + " error(s)") ; + throw new RuntimeException("errorCount = " + errorCount); + } + + cs.stop(); + + } catch(Exception e) { + throw new RuntimeException(e); + } + + } + + private static class ClientSide { + public static void main(String args[]) throws Exception { + + int errorCount = 0 ; + String msgTag = "ClientSide::main: "; + + try { + + // Get a connection to remote mbean server + JMXServiceURL addr = new JMXServiceURL(args[0]); + JMXConnector cc = JMXConnectorFactory.connect(addr); + MBeanServerConnection mbsc = cc.getMBeanServerConnection(); + + // ---- + System.out.println(msgTag + "Create and register the MBean"); + ObjectName objName = new ObjectName("sqe:type=Basic,protocol=rmi") ; + mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName); + System.out.println(msgTag +"---- OK\n") ; + + // ---- + System.out.println(msgTag +"Get attribute SqeParameterAtt on our MXBean"); + Object result = mbsc.getAttribute(objName, "SqeParameterAtt"); + System.out.println(msgTag +"(OK) Got result of class " + + result.getClass().getName()); + System.out.println(msgTag +"Received CompositeData is " + result); + System.out.println(msgTag +"---- OK\n") ; + + // ---- + // We use the value returned by getAttribute to perform the invoke. + System.out.println(msgTag +"Call operation doWeird on our MXBean [1]"); + mbsc.invoke(objName, "doWeird", + new Object[]{result}, + new String[]{"javax.management.openmbean.CompositeData"}); + System.out.println(msgTag +"---- OK\n") ; + + // ---- + // We build the CompositeData ourselves that time. + System.out.println(msgTag +"Call operation doWeird on our MXBean [2]"); + String typeName = "SqeParameter"; + String[] itemNames = new String[] {"glop"}; + OpenType[] openTypes = new OpenType[] {SimpleType.STRING}; + CompositeType rowType = new CompositeType(typeName, typeName, + itemNames, itemNames, openTypes); + Object[] itemValues = {"HECTOR"}; + CompositeData data = + new CompositeDataSupport(rowType, itemNames, itemValues); + TabularType tabType = new TabularType(typeName, typeName, + rowType, new String[]{"glop"}); + TabularDataSupport tds = new TabularDataSupport(tabType); + tds.put(data); + System.out.println(msgTag +"Source CompositeData is " + data); + mbsc.invoke(objName, "doWeird", + new Object[]{data}, + new String[]{"javax.management.openmbean.CompositeData"}); + System.out.println(msgTag +"---- OK\n") ; + + // ---- + System.out.println(msgTag +"Unregister the MBean"); + mbsc.unregisterMBean(objName); + System.out.println(msgTag +"---- OK\n") ; + + // Terminate the JMX Client + cc.close(); + + } catch(Exception e) { + Utils.printThrowable(e, true) ; + errorCount++; + throw new RuntimeException(e); + } finally { + System.exit(errorCount); + } + } + } +} diff --git a/jdk/test/javax/management/mxbean/SqeDescriptorKey.java b/jdk/test/javax/management/mxbean/SqeDescriptorKey.java new file mode 100644 index 00000000000..60e4926218b --- /dev/null +++ b/jdk/test/javax/management/mxbean/SqeDescriptorKey.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import javax.management.DescriptorKey; + +/** + * That annotation is usable everywhere DescriptorKey is (and even more). + * It is for use to test that you can retrieve the SqeDescriptorKey into the + * appropriate Descriptor instances as built by the JMX runtime. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +public @interface SqeDescriptorKey { + @DescriptorKey("sqeDescriptorKey") + String value(); + + // List descriptor fields that may be added or may be updated + // when retrieving an MBeanInfo using a JMXWS connection compared to the + // MBeanInfo returned by a local MBeanServer. + // The annotation format is : + // = + // The values actually handled by the test suite are : + // openType=SimpleType.VOID + @DescriptorKey("descriptorFields") + String[] descriptorFields() default {}; +} diff --git a/jdk/test/javax/management/mxbean/SqeNotification.java b/jdk/test/javax/management/mxbean/SqeNotification.java new file mode 100644 index 00000000000..7d0130ea902 --- /dev/null +++ b/jdk/test/javax/management/mxbean/SqeNotification.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.management.Notification; + +/** + * Could hold someday a specific semantic. + * For now it is used to have a Notification which of another class, no more. + */ +public class SqeNotification extends Notification { + + /** Creates a new instance of SqeNotification */ + public SqeNotification(String type, Object source, long sequenceNumber) { + super(type, source, sequenceNumber); + } + + /** Creates a new instance of SqeNotification */ + public SqeNotification(String type, Object source, long sequenceNumber, + long timeStamp) { + super(type, source, sequenceNumber, timeStamp); + } + + /** Creates a new instance of SqeNotification */ + public SqeNotification(String type, Object source, long sequenceNumber, + long timeStamp, String message) { + super(type, source, sequenceNumber, timeStamp, message); + } + + /** Creates a new instance of SqeNotification */ + public SqeNotification(String type, Object source, long sequenceNumber, + String message) { + super(type, source, sequenceNumber, message); + } +} diff --git a/jdk/test/javax/management/mxbean/SqeParameter.java b/jdk/test/javax/management/mxbean/SqeParameter.java new file mode 100644 index 00000000000..35a6ff0d897 --- /dev/null +++ b/jdk/test/javax/management/mxbean/SqeParameter.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.Serializable; + +/** + * That class is to use as an MBean operation parameter or returned value. + * The property Glop with its public getter + setter is only there to be + * reconstructible following MXBean specification, so that SqeParameter can be + * used for what it is designed to. + */ +public class SqeParameter implements Serializable { + + private static boolean weird; + private String glop; + + static { + if ( System.getProperty("WEIRD_PARAM") != null ) { + weird = true; + } + } + + /** + * Creates a new instance of SqeParameter. + *
When the Java property WEIRD_PARAM is set, that constructor + * throws an exception. + *
That can be used to ensure the class is instantiated on server side + * but never on client side. + */ + public SqeParameter() throws Exception { + if ( weird ) { + throw new Exception(); + } + } + + public String getGlop() { + return glop; + } + + public void setGlop(String value) { + glop = value; + } +} diff --git a/jdk/test/javax/management/mxbean/Utils.java b/jdk/test/javax/management/mxbean/Utils.java new file mode 100644 index 00000000000..f77196baa2c --- /dev/null +++ b/jdk/test/javax/management/mxbean/Utils.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Map; +import java.util.HashMap; +import java.util.Properties; +import java.lang.reflect.Method; +import javax.management.remote.JMXConnectorServerMBean; + +// utility class for MXBean* tests coming from JMX Tonga test suite +class Utils { + + // DEBUG is printed depending on the DEBUG and DEBUG_LEVEL JAVA property + private static final String DEBUG_HEADER = "[debug] "; + + // DEBUG levels + private static int selectedDebugLevel = 0; + static final int DEBUG_STANDARD = 1; + static final int DEBUG_VERBOSE = 2; // Mainly used for stress tests + static final int DEBUG_ALL = DEBUG_STANDARD | DEBUG_VERBOSE; + + static void parseDebugProperties() { + int level = 0; + Properties p = System.getProperties(); + + // get selected levels + if (p.getProperty("DEBUG_STANDARD") != null) { + level |= DEBUG_STANDARD; + } + + if (p.getProperty("DEBUG_VERBOSE") != null) { + level |= DEBUG_VERBOSE; + } + + if (p.getProperty("DEBUG_ALL") != null) { + level |= DEBUG_ALL; + } + + selectedDebugLevel = level; + } + + /** + * Reproduces the original parsing and collection of test parameters + * from the DTonga JMX test suite. + * + * Collects passed args and returns them in a map(argname, value) structure, + * which will be then propagated as necessary to various called methods. + */ + static Map parseParameters(String args[]) + throws Exception { + Utils.debug(DEBUG_STANDARD, "TestRoot::parseParameters: Start"); + HashMap map = new HashMap<>(); + + for ( int i = 0; i < args.length; i++ ) { + if ( args[i].trim().startsWith("-") ) { + if ((i+1) < args.length && !args[i+1].startsWith("-") ) { + Utils.debug(DEBUG_STANDARD, + "TestRoot::parseParameters: added in map = " + + args[i] + + " with value " + + args[i+1]) ; + map.put(args[i].trim(), args[i+1].trim()) ; + } else if ((i+1) < args.length && args[i+1].startsWith("-") || + (i+1) == args.length ) { + Utils.debug(DEBUG_STANDARD, + "TestRoot::parseParameters: added in map = " + + args[i] + + " with null value") ; + map.put(args[i].trim(), null) ; + } else { + System.out.println( + "TestRoot::parseParameters: (WARNING) not added in map = " + + args[i]) ; + } + } + } + + Utils.debug(DEBUG_STANDARD, "TestRoot::parseParameters: Done") ; + return map ; + } + + /** + * This method is to be used in all tests to print anything + * that is temporary. + * Printing is done only when debug is activated by the property DEBUG. + * Printing depends also on the DEBUG_LEVEL property. + * Here it encapsulates a System.out.println. + */ + public static void debug(int level, String line) { + if ((selectedDebugLevel & level) != 0) { + System.out.println(DEBUG_HEADER + line); + } + } + + /** + * Do print stack trace when withStack is true. + * Does try to call getTargetException() and getTargetError() then + * print embedded stacks in the case of an Exception wrapping + * another Exception or an Error. Recurse until no more wrapping + * is found. + */ + public static void printThrowable(Throwable theThro, boolean withStack) { + try { + if (withStack) { + theThro.printStackTrace(System.out); + } + if (theThro instanceof Exception) { + Exception t = (Exception) theThro; + Method target = null; + String blank = " "; + try { + target = t.getClass().getMethod("getTargetException", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetException method could be there or not + } + System.out.println(blank + t.getClass() + "==>" + t.getMessage()); + while (target != null) { + try { + t = (Exception) target.invoke(t, + (java.lang.Object[]) null); + } catch (Exception ee) { + t = null; + } + try { + if (t != null) { + blank = blank + " "; + System.out.println(blank + t.getClass() + "==>" + + t.getMessage()); + try { + target = + t.getClass().getMethod("getTargetException", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetException method could be there or not } + } + } else { + target = null; + } + } catch (Exception ee) { + target = null; + } + } + + // We may have exceptions wrapping an Error then it is + // getTargetError that is likely to be called + try { + target = ((Exception) theThro).getClass().getMethod("getTargetError", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetError method could be there or not + } + Throwable err = theThro; + while (target != null) { + try { + err = (Error) target.invoke(err, + (java.lang.Object[]) null); + } catch (Exception ee) { + err = null; + } + try { + if (err != null) { + blank = blank + " "; + System.out.println(blank + err.getClass() + "==>" + + err.getMessage()); + if (withStack) { + err.printStackTrace(System.out); + } + try { + target = err.getClass().getMethod("getTargetError", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetError method could be there or not + } + } else { + target = null; + } + } catch (Exception ee) { + target = null; + } + } + } else { + System.out.println("Throwable is : " + theThro); + } + } catch (Throwable x) { + System.out.println("Exception : raised in printException : " + x); + } + } + + /** + * Wait up to maxTimeInSeconds second(s) the given JMX connector server + * comes up (which means isActive returns true). + * If it fails to do so we throw a RunTime exception. + */ + public static void waitReady(JMXConnectorServerMBean server, + int maxTimeInSeconds) throws Exception { + int elapsed = 0; + + while (!server.isActive() && elapsed < maxTimeInSeconds) { + Thread.sleep(1000); + elapsed++; + } + + if (server.isActive()) { + String message = "Utils::waitReady: JMX connector server came up"; + if ( elapsed == 0) { + message += " immediately"; + } else { + message += " after " + elapsed + " seconds"; + } + message += " [" + server.getAddress() + "]"; + Utils.debug(DEBUG_STANDARD, message); + } else { + String message = "Utils::waitReady: (ERROR) JMX connector" + + " server didn't come up after " + elapsed + " seconds [" + + server.getAddress() + "]"; + System.out.println(message); + throw new RuntimeException(message); + } + } +} diff --git a/jdk/test/javax/management/query/QueryData.java b/jdk/test/javax/management/query/QueryData.java new file mode 100644 index 00000000000..fadc6d386ee --- /dev/null +++ b/jdk/test/javax/management/query/QueryData.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +public abstract class QueryData { + protected int intValue = 9; + protected long longValue = 9L; + protected Integer integerValue = Integer.valueOf(9); + protected boolean booleanValue = true; + protected double doubleValue = 9D; + protected float floatValue = 9.0F; + protected String stringValue = "9"; +} diff --git a/jdk/test/javax/management/query/QueryFactory.java b/jdk/test/javax/management/query/QueryFactory.java new file mode 100644 index 00000000000..96394996d46 --- /dev/null +++ b/jdk/test/javax/management/query/QueryFactory.java @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.ArrayList; + +import javax.management.Query; +import javax.management.QueryExp; +import javax.management.ValueExp; + +/** + * Class used for building QueryExp instances of all every possible type + * in terms of JMX API members; note that several JMX classes are private + * and appears in the JDK API only by their serial form. + * Comments in each case of the big switch in method getQuery() details which + * API member we cover with a given query. + */ +public class QueryFactory extends QueryData { + + private String mbeanClassName = ""; + private String primitiveIntAttName = "IntAtt"; + private String primitiveLongAttName = "LongAtt"; + private String integerAttName = "IntegerAtt"; + private String primitiveBooleanAttName = "BooleanAtt"; + private String primitiveDoubleAttName = "DoubleAtt"; + private String primitiveFloatAttName = "FloatAtt"; + private String stringAttName = "StringAtt"; + private ArrayList queries = new ArrayList(); + + /** + * Creates a new instance of QueryFactory. + * The name is the fully qualified class name of an MBean. + * There is severe constraints on that MBean that must: + *
    + *
  • extend QueryData in order to inherit attribute values. + *
  • define a RW attribute IntAtt of type int + * initialized to QueryData.longValue + *
  • define a RW attribute LongAtt of type long + * initialized to QueryData.intValue + *
  • define a RW attribute IntegerAtt of type Integer + * initialized to QueryData.integerValue + *
  • define a RW attribute BooleanAtt of type boolean + * initialized to QueryData.booleanValue + *
  • define a RW attribute DoubleAtt of type double + * initialized to QueryData.doubleValue + *
  • define a RW attribute FloatAtt of type float + * initialized to QueryData.floatValue + *
  • define a RW attribute StringAtt of type String + * initialized to QueryData.stringValue + *
+ */ + public QueryFactory(String name) { + this.mbeanClassName = name; + } + + /** + * Returns the highest index value the method getQuery supports. + * WARNING : returns 0 if buildQueries haven't been called first ! + */ + public int getSize() { + return queries.size(); + } + + /** + * Populates an ArrayList of QueryExp. + * Lowest index is 1. + * Highest index is returned by getSize(). + *
The queries numbered 1 to 23 allow to cover all the underlying + * Java classes of the JMX API used to build queries. + */ + public void buildQueries() { + if ( queries.size() == 0 ) { + int smallerIntValue = intValue - 1; + int biggerIntValue = intValue + 1; + + // case 1: + // True if the MBean is of class mbeanClassName + // We cover javax.management.InstanceOfQueryExp + queries.add(Query.isInstanceOf(Query.value(mbeanClassName))); + + // case 2: + // True if the MBean is of class mbeanClassName + // We cover javax.management.MatchQueryExp and + // javax.management.ClassAttributeValueExp + queries.add(Query.match(Query.classattr(), + Query.value(mbeanClassName))); + + // case 3: + // True if an attribute named primitiveIntAttName of type int has + // the value intValue + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to EQ and javax.management.NumericValueExp + queries.add(Query.eq(Query.attr(primitiveIntAttName), + Query.value(intValue))); + + // case 4: + // True if an attribute named primitiveLongAttName of type long has + // the value longValue + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to EQ and javax.management.NumericValueExp + queries.add(Query.eq(Query.attr(primitiveLongAttName), + Query.value(longValue))); + + // case 5: + // True if an attribute named primitiveDoubleAttName of type double + // has the value doubleValue + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to EQ and javax.management.NumericValueExp + queries.add(Query.eq(Query.attr(primitiveDoubleAttName), + Query.value(doubleValue))); + + // case 6: + // True if an attribute named primitiveFloatAttName of type float + // has the value floatValue + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to EQ and javax.management.NumericValueExp + queries.add(Query.eq(Query.attr(primitiveFloatAttName), + Query.value(floatValue))); + + // case 7: + // True if an attribute named primitiveIntAttName of type int is + // hold by an MBean of class mbeanClassName and has + // the value intValue + // We cover javax.management.QualifiedAttributeValueExp + queries.add(Query.eq(Query.attr(mbeanClassName, primitiveIntAttName), + Query.value(intValue))); + + // case 8: + // True if an attribute named stringAttName of type String has + // the value stringValue + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to EQ and javax.management.StringValueExp + queries.add(Query.eq(Query.attr(stringAttName), + Query.value(stringValue))); + + // case 9: + // True if an attribute named integerAttName of type Integer has + // the value integerValue + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to EQ and javax.management.NumericValueExp + queries.add(Query.eq(Query.attr(integerAttName), + Query.value(integerValue))); + + // case 10: + // True if an attribute named primitiveBooleanAttName of type boolean + // has the value booleanValue + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to EQ and javax.management.BooleanValueExp + queries.add(Query.eq(Query.attr(primitiveBooleanAttName), + Query.value(booleanValue))); + + // case 11: + // True if an attribute named primitiveIntAttName of type int has + // not the value smallerIntValue + // We cover javax.management.NotQueryExp + queries.add(Query.not(Query.eq(Query.attr(primitiveIntAttName), + Query.value(smallerIntValue)))); + + // case 12: + // True if either + // an attribute named primitiveIntAttName of type int has + // the value intValue + // or + // an attribute named primitiveLongAttName of type long has + // the value longValue + // We cover javax.management.OrQueryExp + queries.add(Query.or( + Query.eq(Query.attr(primitiveIntAttName), + Query.value(intValue)), + Query.eq(Query.attr(primitiveLongAttName), + Query.value(longValue)))); + + // case 13: + // True if + // an attribute named primitiveIntAttName of type int has + // the value intValue + // and + // an attribute named primitiveLongAttName of type long has + // the value longValue + // We cover javax.management.AndQueryExp + queries.add(Query.and( + Query.eq(Query.attr(primitiveIntAttName), + Query.value(intValue)), + Query.eq(Query.attr(primitiveLongAttName), + Query.value(longValue)))); + + // case 14: + // True if an attribute named primitiveIntAttName of type int has + // the value intValue + // We cover javax.management.InQueryExp + ValueExp[] inArray = {Query.value(intValue)}; + queries.add(Query.in(Query.attr(primitiveIntAttName), inArray)); + + // case 15: + // True if an attribute named primitiveIntAttName of type int has + // its value in between smallerIntValue and biggerIntValue + // We cover javax.management.BetweenRelQueryExp + queries.add(Query.between(Query.attr(primitiveIntAttName), + Query.value(smallerIntValue), + Query.value(biggerIntValue))); + + // case 16: + // True if an attribute named primitiveIntAttName of type int has + // a value greater than smallerIntValue + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to GT + queries.add(Query.gt(Query.attr(primitiveIntAttName), + Query.value(smallerIntValue))); + + // case 17: + // True if an attribute named primitiveIntAttName of type int has + // a value greater or equal to smallerIntValue + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to GE + queries.add(Query.geq(Query.attr(primitiveIntAttName), + Query.value(smallerIntValue))); + + // case 18: + // True if an attribute named primitiveIntAttName of type int has + // a value smaller than biggerIntValue + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to LT + queries.add(Query.lt(Query.attr(primitiveIntAttName), + Query.value(biggerIntValue))); + + // case 19: + // True if an attribute named primitiveIntAttName of type int has + // a value smaller or equal to biggerIntValue + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to LE + queries.add(Query.leq(Query.attr(primitiveIntAttName), + Query.value(biggerIntValue))); + + // case 20: + // True if an attribute named primitiveIntAttName of type int has + // a value equal to intValue minus zero + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to MINUS + queries.add(Query.eq(Query.attr(primitiveIntAttName), + Query.minus(Query.value(intValue), Query.value(0)))); + + // case 21: + // True if an attribute named primitiveIntAttName of type int has + // a value equal to intValue plus zero + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to PLUS + queries.add(Query.eq(Query.attr(primitiveIntAttName), + Query.plus(Query.value(intValue), Query.value(0)))); + + // case 22: + // True if an attribute named primitiveIntAttName of type int has + // a value equal to intValue divided by one + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to DIV + queries.add(Query.eq(Query.attr(primitiveIntAttName), + Query.div(Query.value(intValue), Query.value(1)))); + + // case 23: + // True if an attribute named primitiveIntAttName of type int has + // a value equal to intValue multiplicated by one + // We cover javax.management.BinaryRelQueryExp with + // a relOp equal to TIMES + queries.add(Query.eq(Query.attr(primitiveIntAttName), + Query.times(Query.value(intValue), Query.value(1)))); + + // case 24: + // That query is a complex one that combines within a big AND + // queries with index 2 to 23 inclusive. But because a List is + // zero based, we must decrement all indexes by 1 when retrieving + // any previously stored query. + QueryExp q2_3 = Query.and(queries.get(2-1), queries.get(3-1)); + QueryExp q4_5 = Query.and(queries.get(4-1), queries.get(5-1)); + QueryExp q6_7 = Query.and(queries.get(6-1), queries.get(7-1)); + QueryExp q8_9 = Query.and(queries.get(8-1), queries.get(9-1)); + QueryExp q10_11 = Query.and(queries.get(10-1), queries.get(11-1)); + QueryExp q12_13 = Query.and(queries.get(12-1), queries.get(13-1)); + QueryExp q14_15 = Query.and(queries.get(14-1), queries.get(15-1)); + QueryExp q16_17 = Query.and(queries.get(16-1), queries.get(17-1)); + QueryExp q18_19 = Query.and(queries.get(18-1), queries.get(19-1)); + QueryExp q20_21 = Query.and(queries.get(20-1), queries.get(21-1)); + QueryExp q22_23 = Query.and(queries.get(22-1), queries.get(23-1)); + QueryExp q2_5 = Query.and(q2_3, q4_5); + QueryExp q6_9 = Query.and(q6_7, q8_9); + QueryExp q10_13 = Query.and(q10_11, q12_13); + QueryExp q14_17 = Query.and(q14_15, q16_17); + QueryExp q18_21 = Query.and(q18_19, q20_21); + QueryExp q2_9 = Query.and(q2_5, q6_9); + QueryExp q10_17 = Query.and(q10_13, q14_17); + QueryExp q18_23 = Query.and(q18_21, q22_23); + QueryExp q2_17 = Query.and(q2_9, q10_17); + queries.add(Query.and(q2_17, q18_23)); + + // case 25: + // Complex query mixing AND and OR. + queries.add(Query.or(q6_9, q18_23)); + } + } + + /** + * Returns a QueryExp taken is the ArrayList populated by buildQueries(). + * Lowest index is 1. + * Highest index is returned by getSize(). + *
The queries numbered 1 to 23 allow to cover all the underlying + * Java classes of the JMX API used to build queries. + */ + public QueryExp getQuery(int index) { + return queries.get(index - 1); + } +} diff --git a/jdk/test/javax/management/query/ServerDelegate.java b/jdk/test/javax/management/query/ServerDelegate.java new file mode 100644 index 00000000000..6ce5face871 --- /dev/null +++ b/jdk/test/javax/management/query/ServerDelegate.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.Principal; +import java.util.ArrayList; +import java.util.List; + +import javax.management.remote.JMXServiceURL ; +import javax.management.MBeanRegistration; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.management.StandardMBean; + +/** + * This class defines an MBean that can be registered and used on client side + * to handle informations or properties of the remote server. + * + * For example, this MBean can store IOR addresses + * of RMI/IIOP connector(s) used in a test. + * + * That MBean might not be used for testing purpose itself. + */ +public class ServerDelegate implements ServerDelegateMBean, MBeanRegistration { + + private MBeanServer mbeanServer = null; + private List addresses = null; + private String port; + private static String javaVersion = System.getProperty("java.version"); + private int sqeJmxwsCredentialsProviderCallCount = 0; + private String jmxwsCredentialsProviderUrl = null; + private int testJMXAuthenticatorCallCount = 0; + private Principal testJMXAuthenticatorPrincipal = null; + + @SqeDescriptorKey("NO PARAMETER CONSTRUCTOR ServerDelegate") + public ServerDelegate() { + addresses = new ArrayList(); + } + + public ObjectName preRegister(MBeanServer server, ObjectName name) + throws Exception { + // Initialize MBeanServer attribute + mbeanServer = server; + return name; + } + public void postRegister(Boolean registrationDone) { + } + public void preDeregister() throws Exception { + } + public void postDeregister() { + } + + public void addAddress(JMXServiceURL url) { + addresses.add(url) ; + } + + public List getAddresses() { + return addresses ; + } + + public void setPort(String p) { + port = p ; + } + + public String getPort() { + return port ; + } + + public String getJavaVersion() { + return javaVersion; + } + + public void sqeJmxwsCredentialsProviderCalled() { + sqeJmxwsCredentialsProviderCallCount++; + } + + public int getSqeJmxwsCredentialsProviderCallCount() { + return sqeJmxwsCredentialsProviderCallCount; + } + + public void setJmxwsCredentialsProviderUrl(String url) { + jmxwsCredentialsProviderUrl = url; + } + + public String getJmxwsCredentialsProviderUrl() { + return jmxwsCredentialsProviderUrl; + } + + public void testJMXAuthenticatorCalled() { + testJMXAuthenticatorCallCount++; + } + + public int getTestJMXAuthenticatorCallCount() { + return testJMXAuthenticatorCallCount; + } + + public void setTestJMXAuthenticatorPrincipal(Principal principal) { + testJMXAuthenticatorPrincipal = principal; + } + + public String getTestJMXAuthenticatorPrincipalString() { + if ( testJMXAuthenticatorPrincipal != null ) { + return testJMXAuthenticatorPrincipal.toString(); + } + + return null; + } + + /** + * Instantiates and registers a StandardMBean in the MBean server. + * + * @param implementationClassName + * The implementation class name of the MBean. + * @param interfaceClassName + * The management interface class name of the MBean. + * @param isMXBean + * If true, the resultant MBean is an MXBean. + * @param name + * The object name of the StandardMBean. + */ + @SuppressWarnings("unchecked") + public void createStandardMBean( + String implementationClassName, + String interfaceClassName, + boolean isMXBean, + ObjectName name) + throws Exception { + + Object implementation = + Class.forName(implementationClassName).newInstance(); + Class interfaceClass = interfaceClassName == null ? null : + (Class)Class.forName(interfaceClassName); + + // Create the StandardMBean + StandardMBean standardMBean = new StandardMBean( + implementation, + interfaceClass, + isMXBean); + + // Register the StandardMBean + mbeanServer.registerMBean(standardMBean, name); + } + + /** + * Instantiates and registers a StandardMBean in the MBean server. + * The object will use standard JMX design pattern to determine + * the management interface associated with the given implementation. + */ + @SuppressWarnings("unchecked") + public void createStandardMBean( + String implementationClassName, + boolean isMXBean, + ObjectName name) + throws Exception { + + createStandardMBean(implementationClassName, null, isMXBean, name); + } +} diff --git a/jdk/test/javax/management/query/ServerDelegateMBean.java b/jdk/test/javax/management/query/ServerDelegateMBean.java new file mode 100644 index 00000000000..88f0b3f5675 --- /dev/null +++ b/jdk/test/javax/management/query/ServerDelegateMBean.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.Principal; +import java.util.List; + +import javax.management.remote.JMXServiceURL ; +import javax.management.ObjectName; + +@SqeDescriptorKey("INTERFACE ServerDelegateMBean") +public interface ServerDelegateMBean { + @SqeDescriptorKey("ATTRIBUTE Address") + public void addAddress(JMXServiceURL url); + + @SqeDescriptorKey("ATTRIBUTE Address") + public List getAddresses(); + + public String getPort(); + public void setPort(String p); + + public String getJavaVersion(); + + public void sqeJmxwsCredentialsProviderCalled(); + public int getSqeJmxwsCredentialsProviderCallCount(); + + public void setJmxwsCredentialsProviderUrl(String url); + public String getJmxwsCredentialsProviderUrl(); + + public void testJMXAuthenticatorCalled(); + public int getTestJMXAuthenticatorCallCount(); + + public void setTestJMXAuthenticatorPrincipal(Principal principal); + public String getTestJMXAuthenticatorPrincipalString(); + + public void createStandardMBean( + String implementationClassName, + String interfaceClassName, + boolean isMXBean, + ObjectName name) + throws Exception; + + public void createStandardMBean( + String implementationClassName, + boolean isMXBean, + ObjectName name) + throws Exception; +} diff --git a/jdk/test/javax/management/query/SqeDescriptorKey.java b/jdk/test/javax/management/query/SqeDescriptorKey.java new file mode 100644 index 00000000000..60e4926218b --- /dev/null +++ b/jdk/test/javax/management/query/SqeDescriptorKey.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import javax.management.DescriptorKey; + +/** + * That annotation is usable everywhere DescriptorKey is (and even more). + * It is for use to test that you can retrieve the SqeDescriptorKey into the + * appropriate Descriptor instances as built by the JMX runtime. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +public @interface SqeDescriptorKey { + @DescriptorKey("sqeDescriptorKey") + String value(); + + // List descriptor fields that may be added or may be updated + // when retrieving an MBeanInfo using a JMXWS connection compared to the + // MBeanInfo returned by a local MBeanServer. + // The annotation format is : + // = + // The values actually handled by the test suite are : + // openType=SimpleType.VOID + @DescriptorKey("descriptorFields") + String[] descriptorFields() default {}; +} diff --git a/jdk/test/javax/management/query/SupportedQueryTypesTest.java b/jdk/test/javax/management/query/SupportedQueryTypesTest.java new file mode 100644 index 00000000000..fab8128a317 --- /dev/null +++ b/jdk/test/javax/management/query/SupportedQueryTypesTest.java @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058865 + * @summary Tests most of the existing query types. + * @author Olivier Lagneau + * @modules java.management + * @compile TestQuery.java + * @run main/othervm/timeout=300 -DDEBUG_STANDARD SupportedQueryTypesTest -mbeanClassName TestQuery + */ + +import java.util.Map ; +import java.util.HashMap; +import java.util.Set; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Properties; +import java.lang.reflect.Method; + +import java.lang.management.ManagementFactory; +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.MBeanServerConnection; +import javax.management.ObjectInstance; +import javax.management.ObjectName ; +import javax.management.QueryExp; + +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +public class SupportedQueryTypesTest { + + protected String mbeanClassName = null; + + private MBeanServerConnection mbsc = null; + + + /* + * First Debug properties and arguments are collect in expected + * map (argName, value) format, then calls original test's run method. + */ + public static void main(String args[]) throws Exception { + + System.out.println("================================================="); + + // Parses parameters + Utils.parseDebugProperties(); + Map map = Utils.parseParameters(args) ; + + // Run test + SupportedQueryTypesTest test = new SupportedQueryTypesTest(); + test.run(map); + + } + + public void run(Map args) { + int errorCount = 0; + + ObjectName on = null; + ObjectName serverDelegateObjectName = null; + + JMXConnectorServer cs = null; + JMXConnector cc = null; + + System.out.println("SupportedQueryTypesTest::run: Start") ; + try { + // JMX MbeanServer used inside single VM as if remote. + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + + JMXServiceURL url = new JMXServiceURL("rmi", null, 0); + cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); + cs.start(); + + JMXServiceURL addr = cs.getAddress(); + cc = JMXConnectorFactory.connect(addr); + mbsc = cc.getMBeanServerConnection(); + + + // Create and register the ServerDelegate MBean on the remote MBeanServer + String serverDelegateClassName = ServerDelegate.class.getName(); + serverDelegateObjectName = + new ObjectName("defaultDomain:class=" + serverDelegateClassName); + mbsc.createMBean(serverDelegateClassName, serverDelegateObjectName); + + // Retrieve the MBean class name + mbeanClassName = (String) args.get("-mbeanClassName") ; + on = new ObjectName("defaultDomain:class=" + mbeanClassName); + + // Create and register the MBean on the remote MBeanServer + System.out.println("SupportedQueryTypesTest::run: CREATE " + + mbeanClassName + " on the remote MBeanServer with name " + + on); + mbsc.createMBean(mbeanClassName, on); + + // Create a QueryFactory and setup which query we'll use. + QueryFactory queries = new QueryFactory(mbeanClassName); + queries.buildQueries(); + int maxIndex = queries.getSize(); + int minIndex = 1; + + // Create a reference Set to check later on + // the queryNames() results + Set referenceNameSet = new HashSet(); + referenceNameSet.add(on); + + // Create a reference Set to check later on + // the queryMBeans() results + ObjectInstance oi = new ObjectInstance(on, mbeanClassName); + Set referenceInstanceSet = + new HashSet(); + referenceInstanceSet.add(oi); + + // Perform the queryNames and queryMBeans requests + for (int i = minIndex; i <= maxIndex; i++ ) { + QueryExp query = queries.getQuery(i); + System.out.println("----"); + System.out.println("SupportedQueryTypesTest::run: Query # " + i); + System.out.println("query " + query); + errorCount += + doQueryNames(query, referenceNameSet); + errorCount += + doQueryMBeans(query, referenceInstanceSet); + } + + } catch(Exception e) { + Utils.printThrowable(e, true); + errorCount++; + + } finally { + // Do unregister the MBean + try { + if (mbsc.isRegistered(on)) { + mbsc.unregisterMBean(on); + } + if (mbsc.isRegistered(serverDelegateObjectName)) { + mbsc.unregisterMBean(serverDelegateObjectName); + } + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++; + } + + try { + // Close JMX Connector Client + cc.close(); + // Stop connertor server + cs.stop(); + + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++; + } + } + + System.out.println(""); + System.out.println("SupportedQueryTypesTest::run: Done") ; + + // Handle result + if (errorCount == 0) { + System.out.println("SupportedQueryTypesTest::run: (OK)"); + } else { + String message = "SupportedQueryTypesTest::run: (ERROR) Got " + + + errorCount + " error(s)"; + System.out.println(message); + throw new RuntimeException(message); + } + } + + + private int doQueryNames(QueryExp query, Set referenceSet) { + int errorCount = 0; + System.out.println(" <*> Perform queryNames call "); + + try { + // Call queryNames on the remote MBeanServer + Set remoteSet = mbsc.queryNames(null, query); + + // Compare the 2 Set + errorCount += checkSet(remoteSet, referenceSet); + + // Cleaning + remoteSet.clear(); + + } catch (Exception e) { + Utils.printThrowable(e, true); + errorCount++; + } + + if ( errorCount == 0 ) { + System.out.println("\t(OK)"); + } else { + System.out.println("\t(ERROR) Query failed"); + } + + return errorCount; + } + + + private int doQueryMBeans(QueryExp query, Set referenceSet) { + int errorCount = 0; + System.out.println(" <*> Perform queryMBeans call "); + + try { + // Call queryMBeans on the remote MBeanServer + Set remoteSet = mbsc.queryMBeans(null, query); + + // Compare the 2 Set + errorCount += checkSet(remoteSet, referenceSet); + + // Cleaning + remoteSet.clear(); + + } catch (Exception e) { + Utils.printThrowable(e, true); + errorCount++; + } + + if ( errorCount == 0 ) { + System.out.println("\t(OK)"); + } else { + System.out.println("\t(ERROR) Query failed"); + } + + return errorCount; + } + + /** + * Pretty print of a Set content. + * When the Set isn't empty, toString() is called on each element. + *
The variable's name used to hold that Set is given via the setName + * parameter and used in the output. + */ + private static void printSet(Set printableSet, String setName) { + if ( printableSet.size() == 0 ) { + System.out.println("The Set " + setName + " is empty"); + } else { + System.out.println("The Set " + setName + " contains :"); + + for (Iterator it = printableSet.iterator(); it.hasNext();) { + Object elem = it.next(); + System.out.println("\t" + elem.toString()); + } + } + } + + + /** + * This method check the Set remoteSet is equal to + * the reference Set referenceSet, + * which means same size and content (order doesn't matter). + *
It returns 0 when the check is fine, otherwise 1. + */ + private int checkSet(Set remoteSet, Set referenceSet) { + if ( ! remoteSet.equals(referenceSet) ) { + System.out.println("SupportedQueryTypesTest::checkSet:" + + " (ERROR) Set aren't as expected"); + printSet(remoteSet, "remoteSet"); + printSet(referenceSet, "referenceSet"); + return 1; + } else { + return 0; + } + } + + // Utility inner class coming from JMX Tonga test suite. + private static class Utils { + + // DEBUG is printed depending on the DEBUG and DEBUG_LEVEL JAVA property + static final String DEBUG_HEADER = "[debug] "; + + // DEBUG levels + static int selectedDebugLevel = 0; + static final int DEBUG_STANDARD = 1; + static final int DEBUG_VERBOSE = 2; // Mainly used for stress tests + static final int DEBUG_ALL = DEBUG_STANDARD | DEBUG_VERBOSE; + + static void parseDebugProperties() { + int level = 0; + Properties p = System.getProperties(); + + // get selected levels + if (p.getProperty("DEBUG_STANDARD") != null) { + level |= DEBUG_STANDARD; + } + + if (p.getProperty("DEBUG_VERBOSE") != null) { + level |= DEBUG_VERBOSE; + } + + if (p.getProperty("DEBUG_ALL") != null) { + level |= DEBUG_ALL; + } + + selectedDebugLevel = level; + } + + /** + * Reproduces the original parsing and collection of test parameters + * from the DTonga JMX test suite. + * + * Collects passed args and returns them in a map(argname, value) structure, + * which will be then propagated as necessary to various called methods. + */ + static Map parseParameters(String args[]) + throws Exception { + debug(DEBUG_STANDARD, "TestRoot::parseParameters: Start"); + HashMap map = new HashMap<>(); + + for ( int i = 0; i < args.length; i++ ) { + if ( args[i].trim().startsWith("-") ) { + if ((i+1) < args.length && !args[i+1].startsWith("-") ) { + debug(DEBUG_STANDARD, + "TestRoot::parseParameters: added in map = " + + args[i] + + " with value " + + args[i+1]) ; + map.put(args[i].trim(), args[i+1].trim()) ; + } else if ((i+1) < args.length && args[i+1].startsWith("-") || + (i+1) == args.length ) { + debug(DEBUG_STANDARD, + "TestRoot::parseParameters: added in map = " + + args[i] + + " with null value") ; + map.put(args[i].trim(), null) ; + } else { + System.out.println( + "TestRoot::parseParameters: (WARNING) not added in map = " + + args[i]) ; + } + } + } + + debug(DEBUG_STANDARD, "TestRoot::parseParameters: Done") ; + return map ; + } + + /** + * This method is to be used in all tests to print anything + * that is temporary. + * Printing is done only when debug is activated by the property DEBUG. + * Printing depends also on the DEBUG_LEVEL property. + * Here it encapsulates a System.out.println. + */ + static void debug(int level, String line) { + if ((selectedDebugLevel & level) != 0) { + System.out.println(DEBUG_HEADER + line); + } + } + + /** + * Do print stack trace when withStack is true. + * Does try to call getTargetException() and getTargetError() then + * print embedded stacks in the case of an Exception wrapping + * another Exception or an Error. Recurse until no more wrapping + * is found. + */ + static void printThrowable(Throwable theThro, boolean withStack) { + try { + if (withStack) { + theThro.printStackTrace(System.out); + } + if (theThro instanceof Exception) { + Exception t = (Exception) theThro; + Method target = null; + String blank = " "; + try { + target = t.getClass().getMethod("getTargetException", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetException method could be there or not + } + System.out.println(blank + t.getClass() + "==>" + t.getMessage()); + while (target != null) { + try { + t = (Exception) target.invoke(t, + (java.lang.Object[]) null); + } catch (Exception ee) { + t = null; + } + try { + if (t != null) { + blank = blank + " "; + System.out.println(blank + t.getClass() + "==>" + + t.getMessage()); + try { + target = + t.getClass().getMethod("getTargetException", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetException method could be there or not } + } + } else { + target = null; + } + } catch (Exception ee) { + target = null; + } + } + + // We may have exceptions wrapping an Error then it is + // getTargetError that is likely to be called + try { + target = ((Exception) theThro).getClass().getMethod("getTargetError", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetError method could be there or not + } + Throwable err = theThro; + while (target != null) { + try { + err = (Error) target.invoke(err, + (java.lang.Object[]) null); + } catch (Exception ee) { + err = null; + } + try { + if (err != null) { + blank = blank + " "; + System.out.println(blank + err.getClass() + "==>" + + err.getMessage()); + if (withStack) { + err.printStackTrace(System.out); + } + try { + target = err.getClass().getMethod("getTargetError", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetError method could be there or not + } + } else { + target = null; + } + } catch (Exception ee) { + target = null; + } + } + } else { + System.out.println("Throwable is : " + theThro); + } + } catch (Throwable x) { + System.out.println("Exception : raised in printException : " + x); + } + } + } + +} diff --git a/jdk/test/javax/management/query/TestQuery.java b/jdk/test/javax/management/query/TestQuery.java new file mode 100644 index 00000000000..31b896ed7ff --- /dev/null +++ b/jdk/test/javax/management/query/TestQuery.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Class TestQuery + * MBean used for testing the types wired when using QueryExp. + * It is heavily linked to QueryFactory. + */ +public class TestQuery extends QueryData implements TestQueryMBean { + + /** + * Attribute : BooleanAtt + */ + private boolean booleanAtt = booleanValue; + + /** + * Attribute : DoubleAtt + */ + private double doubleAtt = doubleValue; + + /** + * Attribute : FloatAtt + */ + private float floatAtt = floatValue; + + /** + * Attribute : IntAtt + */ + private int intAtt = intValue; + + /** + * Attribute : IntegerAtt + */ + private Integer integerAtt = integerValue; + + /** + * Attribute : LongAtt + */ + private long longAtt = longValue; + + /** + * Attribute : StringAtt + */ + private String stringAtt = stringValue; + + public TestQuery() { + } + + /** + * Get Att of type boolean + */ + public boolean getBooleanAtt() { + return booleanAtt; + } + + /** + * Set Att of type boolean + */ + public void setBooleanAtt(boolean value) { + booleanAtt = value; + } + + /** + * Get Att of type double + */ + public double getDoubleAtt() { + return doubleAtt; + } + + /** + * Set Att of type double + */ + public void setDoubleAtt(double value) { + doubleAtt = value; + } + + /** + * Get Att of type float + */ + public float getFloatAtt() { + return floatAtt; + } + + /** + * Set Att of type float + */ + public void setFloatAtt(float value) { + floatAtt = value; + } + + /** + * Get Att of type int + */ + public int getIntAtt() { + return intAtt; + } + + /** + * Set Att of type int + */ + public void setIntAtt(int value) { + intAtt = value; + } + + /** + * Get Att of type Integer + */ + public Integer getIntegerAtt() { + return integerAtt; + } + + /** + * Set Att of type Integer + */ + public void setIntegerAtt(Integer value) { + integerAtt = value; + } + + /** + * Get Att of type long + */ + public long getLongAtt() { + return longAtt; + } + + /** + * Set Att of type long + */ + public void setLongAtt(long value) { + longAtt = value; + } + + /** + * Get Att of type String + */ + public String getStringAtt() { + return stringAtt; + } + + /** + * Set Att of type String + */ + public void setStringAtt(String value) { + stringAtt = value; + } + +} diff --git a/jdk/test/javax/management/query/TestQueryMBean.java b/jdk/test/javax/management/query/TestQueryMBean.java new file mode 100644 index 00000000000..9cf321f9030 --- /dev/null +++ b/jdk/test/javax/management/query/TestQueryMBean.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Interface TestQueryMBean + * MBean used for testing the types wired when using QueryExp. + * It is heavily linked to QueryFactory. + */ +public interface TestQueryMBean +{ + /** + * Get Att of type boolean + */ + public boolean getBooleanAtt(); + + /** + * Set Att of type boolean + */ + public void setBooleanAtt(boolean value); + + /** + * Get Att of type double + */ + public double getDoubleAtt(); + + /** + * Set Att of type double + */ + public void setDoubleAtt(double value); + + /** + * Get Att of type float + */ + public float getFloatAtt(); + + /** + * Set Att of type float + */ + public void setFloatAtt(float value); + + /** + * Get Att of type int + */ + public int getIntAtt(); + + /** + * Set Att of type int + */ + public void setIntAtt(int value); + + /** + * Get Att of type Integer + */ + public Integer getIntegerAtt(); + + /** + * Set Att of type Integer + */ + public void setIntegerAtt(Integer value); + + /** + * Get Att of type long + */ + public long getLongAtt(); + + /** + * Set Att of type long + */ + public void setLongAtt(long value); + + /** + * Get Att of type String + */ + public String getStringAtt(); + + /** + * Set Att of type String + */ + public void setStringAtt(String value); + +} diff --git a/jdk/test/javax/management/security/AuthorizationTest.java b/jdk/test/javax/management/security/AuthorizationTest.java new file mode 100644 index 00000000000..54309ab059b --- /dev/null +++ b/jdk/test/javax/management/security/AuthorizationTest.java @@ -0,0 +1,613 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058865 + * @summary Checks various authentication behavior from remote jmx client + * @author Olivier Lagneau + * @modules java.management + * @library /lib/testlibrary + * @compile Simple.java + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException + * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials + * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username3 -Dpassword=password3 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedGetException + * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username5 -Dpassword=password5 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException + * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException + * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials + * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException + * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username3 -Dpassword=password3 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException + * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username4 -Dpassword=password4 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedGetException -expectedSetException + * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username5 -Dpassword=password5 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException + */ + +import java.io.File; +import java.util.Map ; +import java.util.HashMap ; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import java.lang.management.ManagementFactory; + +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory ; +import javax.management.MBeanServerConnection; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +import javax.management.Attribute ; +import javax.management.ObjectName ; + +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.JDKToolFinder; + +public class AuthorizationTest { + + static final String SERVER_CLASS_NAME = "AuthorizationTest"; + static final String CLIENT_CLASS_NAME = "AuthorizationTest$ClientSide"; + static final String CLIENT_CLASS_MAIN = CLIENT_CLASS_NAME; + + static final String USERNAME_PROPERTY = "username"; + static final String PASSWORD_PROPERTY = "password"; + + private JMXConnectorServer cs; + + /* + * First Debug properties and arguments are collect in expected + * map (argName, value) format, then calls original test's run method. + */ + public static void main(String args[]) throws Exception { + + System.out.println("================================================="); + + // Parses parameters + Utils.parseDebugProperties(); + + // Supported parameters list format is : + // "MainClass [-server ...] [-client ...] + // with either "-parami valuei" or "-parami" + HashMap serverMap = new HashMap<>() ; + int clientArgsIndex = + Utils.parseServerParameters(args, SERVER_CLASS_NAME, serverMap); + + // Extract and records client params + String[] clientParams = null; + if (clientArgsIndex < args.length) { + int clientParamsSize = args.length - clientArgsIndex; + clientParams = new String[clientParamsSize]; + System.arraycopy(args, clientArgsIndex, clientParams, 0, clientParamsSize); + } else { + clientParams = new String[0]; + } + + // Run test + AuthorizationTest test = new AuthorizationTest(); + test.run(serverMap, clientParams); + + } + + /* + * Create the MBeansServer side of the test and returns its address + */ + private JMXServiceURL createServerSide(Map serverMap) + throws Exception { + final int NINETY_SECONDS = 90; + + System.out.println("AuthorizationTest::createServerSide: Start") ; + + MBeanServer mbs = MBeanServerFactory.newMBeanServer(); + JMXServiceURL url = new JMXServiceURL("rmi", null, 0); + + // Creates connection environment from server side params + HashMap env = new HashMap<>(); + String value = null; + + if ((value = (String)serverMap.get("-mapType")) != null) { + if (value.contains("x.access.file")) { + String accessFileStr = System.getProperty("test.src") + + File.separator + "access.properties"; + env.put("jmx.remote.x.access.file", accessFileStr); + System.out.println("Added " + accessFileStr + " file as jmx.remote.x.access.file"); + } + if (value.contains("x.password.file")) { + String passwordFileStr = System.getProperty("test.src") + + File.separator + "password.properties"; + env.put("jmx.remote.x.password.file", passwordFileStr); + System.out.println("Added " + passwordFileStr + " file as jmx.remote.x.password.file"); + } + } + + if (serverMap.containsKey("-populate")) { + String populateClassName = "Simple"; + ObjectName on = + new ObjectName("defaultDomain:class=Simple"); + + Utils.debug(Utils.DEBUG_STANDARD, "create and register Simple MBean") ; + mbs.createMBean(populateClassName, on); + } + + cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); + cs.start(); + + Utils.waitReady(cs, NINETY_SECONDS); + + JMXServiceURL addr = cs.getAddress(); + + System.out.println("AuthorizationTest::createServerSide: Done.") ; + + return addr; + } + + /* + * Creating command-line for running subprocess JVM: + * + * JVM command line is like: + * {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main + * + * {defaultopts} are the default java options set by the framework. + * + */ + private List buildCommandLine(String args[]) { + List opts = new ArrayList<>(); + opts.add(JDKToolFinder.getJDKTool("java")); + opts.addAll(Arrays.asList(jdk.testlibrary.Utils.getTestJavaOpts())); + + String usernameValue = System.getProperty(USERNAME_PROPERTY); + if (usernameValue != null) { + opts.add("-D" + USERNAME_PROPERTY + "=" + usernameValue); + } + String passwordValue = System.getProperty(PASSWORD_PROPERTY); + if (passwordValue != null) { + opts.add("-D" + PASSWORD_PROPERTY + "=" + passwordValue); + } + + opts.add("-cp"); + opts.add(System.getProperty("test.class.path", "test.class.path")); + opts.add(CLIENT_CLASS_MAIN); + opts.addAll(Arrays.asList(args)); + return opts; + } + + /** + * Runs AuthorizationTest$ClientSide with the passed options and redirects + * subprocess standard I/O to the current (parent) process. This provides a + * trace of what happens in the subprocess while it is runnning (and before + * it terminates). + * + * @param serviceUrlStr string representing the JMX service Url to connect to. + */ + private int runClientSide(String args[], String serviceUrlStr) throws Exception { + + // Building command-line + List opts = buildCommandLine(args); + opts.add("-serviceUrl"); + opts.add(serviceUrlStr); + + // Launch separate JVM subprocess + int exitCode = 0; + String[] optsArray = opts.toArray(new String[0]); + ProcessBuilder pb = new ProcessBuilder(optsArray); + Process p = ProcessTools.startProcess("AuthorizationTest$ClientSide", pb); + + // Handling end of subprocess + try { + exitCode = p.waitFor(); + if (exitCode != 0) { + System.out.println( + "Subprocess unexpected exit value of [" + exitCode + + "]. Expected 0.\n"); + } + } catch (InterruptedException e) { + System.out.println("Parent process interrupted with exception : \n " + e + " :" ); + + // Parent thread unknown state, killing subprocess. + p.destroyForcibly(); + + throw new RuntimeException( + "Parent process interrupted with exception : \n " + e + " :" ); + + } finally { + if (p.isAlive()) { + p.destroyForcibly(); + } + return exitCode; + } + + } + + public void run(Map serverArgs, String clientArgs[]) { + + System.out.println("AuthorizationTest::run: Start") ; + int errorCount = 0; + + try { + // Initialise the server side + JMXServiceURL urlToUse = createServerSide(serverArgs); + + // Run client side + errorCount = runClientSide(clientArgs, urlToUse.toString()); + + if ( errorCount == 0 ) { + System.out.println("AuthorizationTest::run: Done without any error") ; + } else { + System.out.println("AuthorizationTest::run: Done with " + + errorCount + + " error(s)") ; + throw new RuntimeException("errorCount = " + errorCount); + } + + cs.stop(); + + } catch(Exception e) { + throw new RuntimeException(e); + } + + } + + private static class ClientSide { + + private JMXConnector cc = null; + private MBeanServerConnection mbsc = null; + + public static void main(String args[]) throws Exception { + + // Parses parameters + Utils.parseDebugProperties(); + + // Supported parameters list format is : "MainClass [-client ...] + // with either "-parami valuei" or "-parami" + HashMap clientMap = new HashMap<>() ; + Utils.parseClientParameters(args, CLIENT_CLASS_NAME, clientMap); + + // Run test + ClientSide test = new ClientSide(); + test.run(clientMap); + + } + + public void run(Map args) { + + int errorCount = 0 ; + + try { + boolean expectedCreateException = + (args.containsKey("-expectedCreateException")) ? true : false ; + boolean expectedGetException = + (args.containsKey("-expectedGetException")) ? true : false ; + boolean expectedSetException = + (args.containsKey("-expectedSetException")) ? true : false ; + boolean expectedInvokeException = + (args.containsKey("-expectedInvokeException")) ? true : false ; + // JSR262 (see bug 6440374) + // There is no special JSR262 protocol operation for connect. + // The first request sent initiate the connection. + // In the JSR262 current implementation, getDefaultDomain is sent to + // the server in order to get the server part of the connection ID. + // => the connection may fail if no access permission on get requests. + boolean expectedConnectException = + (args.containsKey("-expectedConnectException")) ? true : false ; + // Before connection, + // remove the element of the Map with null values (not supported by RMI) + // See bug 4982668 + args.remove("-expectedCreateException"); + args.remove("-expectedGetException"); + args.remove("-expectedSetException"); + args.remove("-expectedInvokeException"); + args.remove("-expectedConnectException"); + + + // Here do connect to the JMX Server + String username = System.getProperty("username"); + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::run: CONNECT on behalf of \"" + username + "\""); + doConnect(args, expectedConnectException); + + // If the connection did not fail, perform some requests. + // At this stage the mbeanserver connection is up and running + if (mbsc != null) { + ObjectName on = new ObjectName("defaultDomain:class=Simple"); + + // Create request + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::run: CREATE on behalf of \"" + + username + "\""); + errorCount += doCreateRequest(mbsc, + new ObjectName("defaultDomain:class=Simple,user=" + username), + expectedCreateException); + + // Get request + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::run: GET on behalf of \"" + + username + "\""); + errorCount += doGetRequest(mbsc, on, expectedGetException); + + // Set request + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::run: SET on behalf of \"" + + username + "\""); + errorCount += doSetRequest(mbsc, on, expectedSetException); + + // Invoke request + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::run: INVOKE on behalf of \"" + + username + "\""); + errorCount += doInvokeRequest(mbsc, on, expectedInvokeException); + } + + } catch(Exception e) { + Utils.printThrowable(e, true) ; + errorCount++; + } finally { + // Terminate the JMX Client + try { + cc.close(); + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++; + } + } + + System.out.println("ClientSide::run: Done") ; + + // Handle result + if (errorCount == 0) { + System.out.println("ClientSide::run: (OK) authorization test succeeded."); + } else { + String message = "AuthorizationTest$ClientSide::run: (ERROR) " + + " authorization test failed with " + + errorCount + " error(s)"; + System.out.println(message); + throw new RuntimeException(message); + } + } + + protected void doConnect(Map args, + boolean expectedException) { + + String msgTag = "ClientSide::doConnect"; + boolean throwRuntimeException = false; + String message = ""; + + try { + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::doConnect: Connect the client"); + + // Collect connection environment + HashMap env = new HashMap<>(); + + Object value = args.get("-mapType"); + if (value != null) { + String username = System.getProperty("username"); + String password = System.getProperty("password"); + Utils.debug(Utils.DEBUG_STANDARD, + msgTag + "add \"jmx.remote.credentials\" = \"" + + username + "\", \"" + password + "\""); + env.put("jmx.remote.credentials", + new String[] { username , password }); + } + + // Get a connection to remote mbean server + JMXServiceURL addr = new JMXServiceURL((String)args.get("-serviceUrl")); + cc = JMXConnectorFactory.connect(addr,env); + mbsc = cc.getMBeanServerConnection(); + + if (expectedException) { + message = "ClientSide::doConnect: (ERROR) " + + "Connect did not fail with expected SecurityException"; + System.out.println(message); + throwRuntimeException = true; + } else { + System.out.println("ClientSide::doConnect: (OK) Connect succeed"); + } + } catch(Exception e) { + Utils.printThrowable(e, true); + if (expectedException) { + if (e instanceof java.lang.SecurityException) { + System.out.println("ClientSide::doConnect: (OK) " + + "Connect failed with expected SecurityException"); + } else { + message = "ClientSide::doConnect: (ERROR) " + + "Create failed with " + e.getClass() + + " instead of expected SecurityException"; + System.out.println(message); + throwRuntimeException = true; + } + } else { + message = "ClientSide::doConnect: (ERROR) " + + "Connect failed"; + System.out.println(message); + throwRuntimeException = true; + } + } + + // If the connection failed, or if the connection succeeded but should not, + // no need to go further => throw RuntimeException and exit the test + if (throwRuntimeException) { + throw new RuntimeException(message); + } + } + + protected int doCreateRequest(MBeanServerConnection mbsc, + ObjectName on, + boolean expectedException) { + int errorCount = 0; + + try { + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::doCreateRequest: Create and register the MBean") ; + + mbsc.createMBean("Simple", on) ; + + if (expectedException) { + System.out.println("ClientSide::doCreateRequest: " + + "(ERROR) Create did not fail with expected SecurityException"); + errorCount++; + } else { + System.out.println("ClientSide::doCreateRequest: (OK) Create succeed") ; + } + } catch(Exception e) { + Utils.printThrowable(e, true) ; + if (expectedException) { + if (e instanceof java.lang.SecurityException) { + System.out.println("ClientSide::doCreateRequest: " + + "(OK) Create failed with expected SecurityException") ; + } else { + System.out.println("ClientSide::doCreateRequest: " + + "(ERROR) Create failed with " + + e.getClass() + " instead of expected SecurityException"); + errorCount++; + } + } else { + System.out.println("ClientSide::doCreateRequest: " + + "(ERROR) Create failed"); + errorCount++; + } + } + return errorCount; + } + + protected int doGetRequest(MBeanServerConnection mbsc, + ObjectName on, + boolean expectedException) { + int errorCount = 0; + + try { + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::doGetRequest: Get attributes of the MBean") ; + + mbsc.getAttribute(on, "Attribute"); + + if (expectedException) { + System.out.println("ClientSide::doGetRequest: " + + "(ERROR) Get did not fail with expected SecurityException"); + errorCount++; + } else { + System.out.println("ClientSide::doGetRequest: (OK) Get succeed") ; + } + } catch(Exception e) { + Utils.printThrowable(e, true) ; + if (expectedException) { + if (e instanceof java.lang.SecurityException) { + System.out.println("ClientSide::doGetRequest: " + + "(OK) Get failed with expected SecurityException") ; + } else { + System.out.println("ClientSide::doGetRequest: " + + "(ERROR) Get failed with " + + e.getClass() + " instead of expected SecurityException"); + errorCount++; + } + } else { + System.out.println("ClientSide::doGetRequest: (ERROR) Get failed"); + errorCount++; + } + } + + return errorCount; + } + + protected int doSetRequest(MBeanServerConnection mbsc, + ObjectName on, + boolean expectedException) { + int errorCount = 0; + + try { + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::doSetRequest: Set attributes of the MBean") ; + + Attribute attribute = new Attribute("Attribute", "My value") ; + mbsc.setAttribute(on, attribute) ; + + if (expectedException) { + System.out.println("ClientSide::doSetRequest: " + + "(ERROR) Set did not fail with expected SecurityException"); + errorCount++; + } else { + System.out.println("ClientSide::doSetRequest: (OK) Set succeed") ; + } + } catch(Exception e) { + Utils.printThrowable(e, true) ; + if (expectedException) { + if (e instanceof java.lang.SecurityException) { + System.out.println("ClientSide::doSetRequest: " + + "(OK) Set failed with expected SecurityException") ; + } else { + System.out.println("ClientSide::doSetRequest: " + + "(ERROR) Set failed with " + + e.getClass() + " instead of expected SecurityException"); + errorCount++; + } + } else { + System.out.println("ClientSide::doSetRequest: (ERROR) Set failed"); + errorCount++; + } + } + return errorCount; + } + + protected int doInvokeRequest(MBeanServerConnection mbsc, + ObjectName on, + boolean expectedException) { + int errorCount = 0; + + try { + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::doInvokeRequest: Invoke operations on the MBean") ; + + mbsc.invoke(on, "operation", null, null) ; + + if (expectedException) { + System.out.println("ClientSide::doInvokeRequest: " + + "(ERROR) Invoke did not fail with expected SecurityException"); + errorCount++; + } else { + System.out.println("ClientSide::doInvokeRequest: (OK) Invoke succeed") ; + } + } catch(Exception e) { + Utils.printThrowable(e, true) ; + if (expectedException) { + if (e instanceof java.lang.SecurityException) { + System.out.println("ClientSide::doInvokeRequest: " + + "(OK) Invoke failed with expected SecurityException") ; + } else { + System.out.println("ClientSide::doInvokeRequest: " + + " (ERROR) Invoke failed with " + + e.getClass() + " instead of expected SecurityException"); + errorCount++; + } + } else { + System.out.println("ClientSide::doInvokeRequest: " + + "(ERROR) Invoke failed"); + errorCount++; + } + } + return errorCount; + } + + } +} diff --git a/jdk/test/javax/management/security/MBS_Light.java b/jdk/test/javax/management/security/MBS_Light.java new file mode 100644 index 00000000000..1ed459eebcb --- /dev/null +++ b/jdk/test/javax/management/security/MBS_Light.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.AccessControlContext; +import java.security.AccessController; +import javax.security.auth.Subject; +import java.security.Principal; +import java.util.Iterator; +import java.util.Set; + +import javax.management.MBeanRegistration ; +import javax.management.MBeanServer ; +import javax.management.ObjectName ; +import javax.management.NotificationBroadcasterSupport; +import javax.management.NotificationListener; +import javax.management.Notification; + +public class MBS_Light extends NotificationBroadcasterSupport + implements MBS_LightMBean, MBeanRegistration, NotificationListener +{ + private RjmxMBeanParameter param = null ; + private String aString = "notset" ; + private int anInt = 0 ; + private MBeanServer mbs = null ; + private ObjectName objname = null ; + private Exception anException = null ; + private Error anError = null ; + private int count = 0; + private SimpleListener listener = new SimpleListener(); + + @SqeDescriptorKey("NO PARAMETER CONSTRUCTOR MBS_Light") + public MBS_Light() { + } + + @SqeDescriptorKey("ONE RjmxMBeanParameter PARAMETER CONSTRUCTOR MBS_Light") + public MBS_Light(@SqeDescriptorKey("CONSTRUCTOR PARAMETER param") + RjmxMBeanParameter param) { + this.param = param ; + } + + @SqeDescriptorKey("ONE String PARAMETER CONSTRUCTOR MBS_Light") + public MBS_Light(@SqeDescriptorKey("CONSTRUCTOR PARAMETER param")String param) { + this.aString = param ; + } + + // Getter for property param + public RjmxMBeanParameter getParam() { + return this.param ; + } + + // Setter for property param + public void setParam(RjmxMBeanParameter param) { + this.param = param ; + } + + // Getter for property aString + public String getAstring() { + return this.aString ; + } + + // Setter for property aString + public void setAstring(String aString) { + this.aString = aString ; + } + + // Getter for property anInt + public int getAnInt() { + return this.anInt ; + } + + // Setter for property anInt + public void setAnInt(int anInt) { + this.anInt = anInt ; + } + + // Getter for property anException + public Exception getAnException() { + return this.anException ; + } + + // Setter for property anException + public void setAnException(Exception anException) { + this.anException = anException ; + } + + // Getter for property anError + public Error getAnError() { + return this.anError ; + } + + // Setter for property anError + public void setAnError(Error anError) { + this.anError = anError ; + } + + // An operation + public RjmxMBeanParameter operate1(String name) { + return new RjmxMBeanParameter(name) ; + } + + // An operation + public String operate2(RjmxMBeanParameter param) { + return param.name ; + } + + // An operation + public void throwError() { + throw new Error("JSR-160-ERROR"); + } + + // An operation + public void throwException() throws Exception { + throw new Exception("JSR-160-EXCEPTION"); + } + + // MBeanRegistration method + public void postDeregister() { + } + + // MBeanRegistration method + public void postRegister(Boolean registrationDone) { + } + + // MBeanRegistration method + public void preDeregister() + throws Exception + { + } + + // MBeanRegistration method + public ObjectName preRegister(MBeanServer server, ObjectName name) + throws Exception + { + this.mbs = server ; + if ( name == null ) { + this.objname = new ObjectName("protocol:class=MBS_Light") ; + } + else { + this.objname = name ; + } + return this.objname ; + } + + public synchronized void handleNotification(Notification notification, + Object handback) { + Utils.debug(Utils.DEBUG_STANDARD, + "MBS_Light::handleNotification: " + notification); + listener.handleNotification(notification, handback); + } + + // Send a notification + public void sendNotification() { + Notification notification = + new Notification("JSR160-TCK-NOTIFICATION", this, count++); + sendNotification(notification); + } + + public Object waitForNotificationHB() { + return listener.waitForNotificationHB(); + } + + // Receive multi notifications and send back handbacks + public synchronized Object[] waitForMultiNotifications(String nb) { + return listener.waitForMultiNotifications(Integer.valueOf(nb).intValue()); + } + + // Receive a notification + public synchronized String waitForNotification() { + return listener.waitForNotification(); + } + + // Is the notification received + public synchronized Boolean notificationReceived() { + return Boolean.valueOf(listener.isNotificationReceived()); + } + + // The authorization Id + public String getAuthorizationId() { + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + Set principals = subject.getPrincipals(); + Iterator i = principals.iterator(); + StringBuffer buffer = new StringBuffer(); + while(i.hasNext()) { + Principal p = i.next(); + buffer.append(p.getName()); + if(i.hasNext()) + buffer.append(" "); + } + + return buffer.toString(); + } +} diff --git a/jdk/test/javax/management/security/MBS_LightMBean.java b/jdk/test/javax/management/security/MBS_LightMBean.java new file mode 100644 index 00000000000..a380af9dcff --- /dev/null +++ b/jdk/test/javax/management/security/MBS_LightMBean.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +@SqeDescriptorKey("INTERFACE MBS_LightMBean") +public interface MBS_LightMBean { + // Getter for property param + @SqeDescriptorKey("ATTRIBUTE Param") + public RjmxMBeanParameter getParam() ; + + // Setter for property param + @SqeDescriptorKey("ATTRIBUTE Param") + public void setParam(RjmxMBeanParameter param) ; + + // Getter for property aString + @SqeDescriptorKey("ATTRIBUTE Astring") + public String getAstring() ; + + // Setter for property aString + @SqeDescriptorKey("ATTRIBUTE Astring") + public void setAstring(String aString) ; + + // Getter for property anInt + @SqeDescriptorKey("ATTRIBUTE AnInt") + public int getAnInt() ; + + // Setter for property anInt + @SqeDescriptorKey("ATTRIBUTE AnInt") + public void setAnInt(int anInt) ; + + // Getter for property anException + @SqeDescriptorKey("ATTRIBUTE AnException") + public Exception getAnException() ; + + // Setter for property anException + @SqeDescriptorKey("ATTRIBUTE AnException") + public void setAnException(Exception anException) ; + + // Getter for property anError + @SqeDescriptorKey("ATTRIBUTE AnError") + public Error getAnError() ; + + // Setter for property anError + @SqeDescriptorKey("ATTRIBUTE AnError") + public void setAnError(Error anError) ; + + // An operation + @SqeDescriptorKey("OPERATION operate1") + public RjmxMBeanParameter operate1( + @SqeDescriptorKey("OPERATION PARAMETER name")String name) ; + + // An operation + @SqeDescriptorKey("OPERATION operate2") + public String operate2( + @SqeDescriptorKey("OPERATION PARAMETER param")RjmxMBeanParameter param) ; + + // Throws an error + @SqeDescriptorKey("OPERATION throwError") + public void throwError(); + + // Throws an exception + @SqeDescriptorKey("OPERATION throwException") + public void throwException() throws Exception; + + // Send a notification + @SqeDescriptorKey("OPERATION sendNotification") + public void sendNotification(); + + // Receive a notification and return the type + @SqeDescriptorKey("OPERATION waitForNotification") + public String waitForNotification(); + + // Receive a notification and return the HandBack + @SqeDescriptorKey("OPERATION waitForNotificationHB") + public Object waitForNotificationHB(); + + // Receive multi notifications and return the HandBacks + @SqeDescriptorKey("OPERATION waitForMultiNotifications") + public Object[] waitForMultiNotifications( + @SqeDescriptorKey("OPERATION PARAMETER nb")String nb); + + // Is the notification received + @SqeDescriptorKey("OPERATION notificationReceived") + public Boolean notificationReceived(); + + // Return the current authorization Id + @SqeDescriptorKey("OPERATION getAuthorizationId") + public String getAuthorizationId(); +} diff --git a/jdk/test/javax/management/security/RjmxMBeanParameter.java b/jdk/test/javax/management/security/RjmxMBeanParameter.java new file mode 100644 index 00000000000..c96e9a12e97 --- /dev/null +++ b/jdk/test/javax/management/security/RjmxMBeanParameter.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.Serializable ; + +/** + * That class is used to modelize a parameter to be used as MBean property + * value or MBean operation parameter or returned value. + */ +public class RjmxMBeanParameter implements Serializable { + public String name = "unset" ; + + public RjmxMBeanParameter() { + } + + public RjmxMBeanParameter(String name) { + this.name = name ; + } + + public boolean equals(Object obj) { + if ( this.name.equals(((RjmxMBeanParameter)obj).name) ) { + return true ; + } else { + return false ; + } + } +} diff --git a/jdk/test/javax/management/security/SecurityTest.java b/jdk/test/javax/management/security/SecurityTest.java new file mode 100644 index 00000000000..6d245bd6ab4 --- /dev/null +++ b/jdk/test/javax/management/security/SecurityTest.java @@ -0,0 +1,800 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058865 + * @summary Checks various secure ways of connecting from remote jmx client + * @author Olivier Lagneau + * @modules java.management + * @library /lib/testlibrary + * @compile MBS_Light.java ServerDelegate.java TestSampleLoginModule.java + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=SQE_username -Dpassword=SQE_password SecurityTest -server -mapType x.password.file -client -mapType credentials + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=UNKNOWN_username -Dpassword=SQE_password SecurityTest -server -mapType x.password.file -client -mapType credentials -expectedThrowable java.lang.SecurityException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=SQE_username -Dpassword=WRONG_password SecurityTest -server -mapType x.password.file -client -mapType credentials -expectedThrowable java.lang.SecurityException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dsusername=TestJMXAuthenticatorUsername -Dspassword=TestJMXAuthenticatorPassword -Dusername=TestJMXAuthenticatorUsername -Dpassword=TestJMXAuthenticatorPassword SecurityTest -server -mapType x.authenticator -client -mapType credentials + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dsusername=TestJMXAuthenticatorUsername -Dspassword=TestJMXAuthenticatorPassword -Dusername=AnotherTestJMXAuthenticatorUsername -Dpassword=TestJMXAuthenticatorPassword SecurityTest -server -mapType x.authenticator -client -mapType credentials -expectedThrowable java.lang.SecurityException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dpassword.file=password.properties -Dusername=usernameFileLoginModule -Dpassword=passwordFileLoginModule SecurityTest -server -mapType x.login.config.PasswordFileAuthentication -client -mapType credentials + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config.UNKNOWN -Dpassword.file=password.properties -Dusername=usernameFileLoginModule -Dpassword=passwordFileLoginModule SecurityTest -server -mapType x.login.config.PasswordFileAuthentication -client -mapType credentialss -expectedThrowable java.lang.SecurityException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dpassword.file=password.properties -Dusername=usernameFileLoginModule -Dpassword=passwordFileLoginModule SecurityTest -server -mapType x.login.config.UnknownAuthentication -client -mapType credentials -expectedThrowable java.lang.SecurityException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dsusername=usernameSampleLoginModule -Dspassword=passwordSampleLoginModule -Dpassword.file=password.properties -Dusername=usernameSampleLoginModule -Dpassword=passwordSampleLoginModule SecurityTest -server -mapType x.login.config.SampleLoginModule -client -mapType credentials + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dsusername=usernameSampleLoginModule -Dspassword=passwordSampleLoginModule -Dpassword.file=password.properties -Dusername=AnotherUsernameSampleLoginModule -Dpassword=passwordSampleLoginModule SecurityTest -server -mapType x.login.config.SampleLoginModule -client -mapType credentials -expectedThrowable java.lang.SecurityException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop + * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword WRONG_password -expectedThrowable java.io.IOException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -expectedThrowable java.io.IOException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -truststore truststoreAgent -truststorepassword glopglop -client -keystore keystoreClient -keystorepassword glopglop -truststore truststoreClient -truststorepassword glopglop + * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -truststore truststoreAgent -truststorepassword glopglop -client -keystore keystoreClient -keystorepassword WRONG_password -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -truststore truststoreAgent -truststorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -client -keystore keystoreClient -keystorepassword glopglop -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_MD5 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.cipher.suites.md5 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_SHA SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.cipher.suites.md5 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_MD5 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.cipher.suites.sha -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledProtocols=SSLv3 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.protocols.sslv3 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledProtocols=TLSv1 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.protocols.sslv3 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException + * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledProtocols=SSLv3 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.protocols.tlsv1 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException + */ + +import java.io.File; +import java.util.Map ; +import java.util.HashMap ; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory ; +import javax.management.MBeanServerConnection; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +import javax.management.Attribute ; +import javax.management.ObjectName ; + +import javax.rmi.ssl.SslRMIClientSocketFactory; +import javax.rmi.ssl.SslRMIServerSocketFactory; + +import java.security.Security; + +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.JDKToolFinder; + +public class SecurityTest { + + static final String SERVER_CLASS_NAME = "SecurityTest"; + static final String CLIENT_CLASS_NAME = "SecurityTest$ClientSide"; + static final String CLIENT_CLASS_MAIN = CLIENT_CLASS_NAME; + + static final String USERNAME_PROPERTY = "username"; + static final String PASSWORD_PROPERTY = "password"; + + static final String SERVER_DELEGATE_MBEAN_NAME = + "defaultDomain:class=ServerDelegate"; + + static final String RMI_SERVER_SOCKET_FACTORY_SSL = "rmi.server.socket.factory.ssl"; + static final String RMI_CLIENT_SOCKET_FACTORY_SSL = "rmi.client.socket.factory.ssl"; + static final String KEYSTORE_PROPNAME = "javax.net.ssl.keyStore"; + static final String KEYSTORE_PWD_PROPNAME = "javax.net.ssl.keyStorePassword"; + static final String TRUSTSTORE_PROPNAME = "javax.net.ssl.trustStore"; + static final String TRUSTSTORE_PWD_PROPNAME = "javax.net.ssl.trustStorePassword"; + + static final String RMI_SSL_CLIENT_ENABLEDCIPHERSUITES = + "javax.rmi.ssl.client.enabledCipherSuites"; + static final String RMI_SSL_CLIENT_ENABLEDPROTOCOLS = + "javax.rmi.ssl.client.enabledProtocols"; + + private JMXConnectorServer cs; + + // Construct and set keyStore properties from given map + static void setKeyStoreProperties(Map map) { + + String keyStore = (String) map.get("-keystore"); + keyStore = buildSourcePath(keyStore); + System.setProperty(KEYSTORE_PROPNAME, keyStore); + System.out.println("keyStore location = \"" + keyStore + "\""); + + String password = (String) map.get("-keystorepassword"); + System.setProperty(KEYSTORE_PWD_PROPNAME, password); + System.out.println("keyStore password = " + password); + + } + + // Construct and set trustStore properties from given map + static void setTrustStoreProperties(Map map) { + + String trustStore = (String) map.get("-truststore"); + trustStore = buildSourcePath(trustStore); + System.setProperty(TRUSTSTORE_PROPNAME, trustStore); + System.out.println("trustStore location = \"" + trustStore + "\""); + + String password = (String) map.get("-truststorepassword"); + System.setProperty(TRUSTSTORE_PWD_PROPNAME, password); + System.out.println("trustStore password = " + password); + + } + + /* + * First Debug properties and arguments are collect in expected + * map (argName, value) format, then calls original test's run method. + */ + public static void main(String args[]) throws Exception { + + System.out.println("================================================="); + + // Parses parameters + Utils.parseDebugProperties(); + + // Supported parameters list format is : + // "MainClass [-server ...] [-client ...] + // with either "-parami valuei" or "-parami" + HashMap serverMap = new HashMap<>() ; + int clientArgsIndex = + Utils.parseServerParameters(args, SERVER_CLASS_NAME, serverMap); + + // Extract and records client params + String[] clientParams = null; + if (clientArgsIndex < args.length) { + int clientParamsSize = args.length - clientArgsIndex; + clientParams = new String[clientParamsSize]; + System.arraycopy(args, clientArgsIndex, clientParams, 0, clientParamsSize); + } else { + clientParams = new String[0]; + } + + // Run test + SecurityTest test = new SecurityTest(); + test.run(serverMap, clientParams); + + } + + // Return full path of filename in the test sopurce directory + private static String buildSourcePath(String filename) { + return System.getProperty("test.src") + File.separator + filename; + } + + /* + * Collects security run params for server side. + */ + private HashMap setServerSecurityEnv(Map map) + throws Exception { + + // Creates Authentication environment from server side params + HashMap env = new HashMap<>(); + + // Retrieve and set keystore and truststore config if any + if (map.containsKey("-keystore") && + map.get("-keystore") != null) { + setKeyStoreProperties(map); + } + System.out.println("Done keystore properties"); + + if (map.containsKey("-truststore") && + map.get("-truststore") != null) { + setTrustStoreProperties(map); + } + System.out.println("Done truststore properties"); + + String value = null; + if ((value = (String)map.get("-mapType")) != null) { + + // Case of remote password file with all authorized credentials + if (value.contains("x.password.file")) { + String passwordFileStr = buildSourcePath("password.properties"); + env.put("jmx.remote.x.password.file", passwordFileStr); + System.out.println("Added " + passwordFileStr + + " file as jmx.remote.x.password.file"); + } + + // Case of dedicated authenticator class : TestJMXAuthenticator + if (value.contains("x.authenticator")) { + env.put("jmx.remote.authenticator", new TestJMXAuthenticator()) ; + System.out.println( + "Added \"jmx.remote.authenticator\" = TestJMXAuthenticator"); + } + + // Case of security config file with standard Authentication + if (value.contains("x.login.config.PasswordFileAuthentication")) { + String loginConfig = System.getProperty("login.config.file"); + + // Override the default JAAS configuration + System.setProperty("java.security.auth.login.config", + "file:" + loginConfig); + System.out.println("Overrided default JAAS configuration with " + + "\"java.security.auth.login.config\" = \"" + loginConfig + "\"") ; + + env.put("jmx.remote.x.login.config", "PasswordFileAuthentication") ; + System.out.println( + "Added \"jmx.remote.x.login.config\" = " + + "\"PasswordFileAuthentication\"") ; + + // redirects "password.file" property to file in ${test.src} + String passwordFileStr = + buildSourcePath(System.getProperty("password.file")); + System.setProperty("password.file", passwordFileStr); + System.out.println( + "Redirected \"password.file\" property value to = " + + passwordFileStr) ; + } + + // Case of security config file with unexisting athentication config + if (value.contains("x.login.config.UnknownAuthentication")) { + String loginConfig = System.getProperty("login.config.file"); + + // Override the default JAAS configuration + System.setProperty("java.security.auth.login.config", + "file:" + loginConfig); + System.out.println("Overrided default JAAS configuration with " + + "\"java.security.auth.login.config\" = \"" + loginConfig + "\"") ; + + env.put("jmx.remote.x.login.config", "UnknownAuthentication") ; + System.out.println( + "Added \"jmx.remote.x.login.config\" = " + + "\"UnknownAuthentication\"") ; + + // redirects "password.file" property to file in ${test.src} + String passwordFileStr = + buildSourcePath(System.getProperty("password.file")); + System.setProperty("password.file", passwordFileStr); + System.out.println( + "Redirected \"password.file\" property value to = " + + passwordFileStr) ; + } + + // Case of security config file with dedicated login module + if (value.contains("x.login.config.SampleLoginModule")) { + String loginConfig = System.getProperty("login.config.file"); + + // Override the default JAAS configuration + System.setProperty("java.security.auth.login.config", + "file:" + loginConfig); + System.out.println("Overrided default JAAS configuration with " + + "\"java.security.auth.login.config\" = \"" + loginConfig + "\"") ; + + env.put("jmx.remote.x.login.config", "SampleLoginModule") ; + System.out.println( + "Added \"jmx.remote.x.login.config\" = " + + "\"SampleLoginModule\"") ; + } + + // Simple rmi ssl authentication + if (value.contains(RMI_CLIENT_SOCKET_FACTORY_SSL)) { + env.put("jmx.remote.rmi.client.socket.factory", + new SslRMIClientSocketFactory()) ; + System.out.println( + "Added \"jmx.remote.rmi.client.socket.factory\"" + + " = SslRMIClientSocketFactory") ; + } + + if (value.contains(RMI_SERVER_SOCKET_FACTORY_SSL)) { + if (value.contains( + "rmi.server.socket.factory.ssl.need.client.authentication")) { + // rmi ssl authentication with client authentication + env.put("jmx.remote.rmi.server.socket.factory", + new SslRMIServerSocketFactory(null, null, true)) ; + System.out.println( + "Added \"jmx.remote.rmi.server.socket.factory\"" + + " = SslRMIServerSocketFactory with client authentication") ; + + } else if (value.contains("rmi.server.socket.factory.ssl.enabled.cipher.suites.md5")) { + // Allows all ciphering and protocols for testing purpose + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + + env.put("jmx.remote.rmi.server.socket.factory", + new SslRMIServerSocketFactory( + new String[] {"SSL_RSA_WITH_RC4_128_MD5"}, null, false)); + System.out.println( + "Added \"jmx.remote.rmi.server.socket.factory\"" + + " = SslRMIServerSocketFactory with SSL_RSA_WITH_RC4_128_MD5 cipher suite"); + + } else if (value.contains("rmi.server.socket.factory.ssl.enabled.cipher.suites.sha")) { + // Allows all ciphering and protocols for testing purpose + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + + env.put("jmx.remote.rmi.server.socket.factory", + new SslRMIServerSocketFactory( + new String[] { "SSL_RSA_WITH_RC4_128_SHA" }, null, false)) ; + System.out.println( + "Added \"jmx.remote.rmi.server.socket.factory\"" + + " = SslRMIServerSocketFactory with SSL_RSA_WITH_RC4_128_SHA cipher suite") ; + + } else if (value.contains("rmi.server.socket.factory.ssl.enabled.protocols.sslv3")) { + // Allows all ciphering and protocols for testing purpose + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + + env.put("jmx.remote.rmi.server.socket.factory", + new SslRMIServerSocketFactory(null, new String[] {"SSLv3"}, false)) ; + System.out.println( + "Added \"jmx.remote.rmi.server.socket.factory\"" + + " = SslRMIServerSocketFactory with SSLv3 protocol") ; + + } else if (value.contains("rmi.server.socket.factory.ssl.enabled.protocols.tlsv1")) { + // Allows all ciphering and protocols for testing purpose + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + + env.put("jmx.remote.rmi.server.socket.factory", + new SslRMIServerSocketFactory(null, new String[] {"TLSv1"}, false)) ; + System.out.println( + "Added \"jmx.remote.rmi.server.socket.factory\"" + + " = SslRMIServerSocketFactory with TLSv1 protocol") ; + + } else { + env.put("jmx.remote.rmi.server.socket.factory", + new SslRMIServerSocketFactory()); + System.out.println( + "Added \"jmx.remote.rmi.server.socket.factory\"" + + " = SslRMIServerSocketFactory"); + } + } + } + + return env; + } + + /* + * Create the MBeansServer side of the test and returns its address + */ + private JMXServiceURL createServerSide(Map serverMap) + throws Exception { + final int NINETY_SECONDS = 90; + + System.out.println("SecurityTest::createServerSide: Start") ; + + // Prepare server side security env + HashMap env = setServerSecurityEnv(serverMap); + + // Create and start mbean server and connector server + MBeanServer mbs = MBeanServerFactory.newMBeanServer(); + JMXServiceURL url = new JMXServiceURL("rmi", null, 0); + cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); + cs.start(); + + // Waits availibility of connector server + Utils.waitReady(cs, NINETY_SECONDS); + + JMXServiceURL addr = cs.getAddress(); + + System.out.println("SecurityTest::createServerSide: Done.") ; + + return addr; + } + + /* + * Creating command-line for running subprocess JVM: + * + * JVM command line is like: + * {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main + * + * {defaultopts} are the default java options set by the framework. + * + */ + private List buildCommandLine(String args[]) { + + System.out.println("SecurityTest::buildCommandLine: Start") ; + + List opts = new ArrayList<>(); + opts.add(JDKToolFinder.getJDKTool("java")); + opts.addAll(Arrays.asList(jdk.testlibrary.Utils.getTestJavaOpts())); + + // We need to forward some properties to the client side + opts.add("-Dtest.src=" + System.getProperty("test.src")); + + String usernameValue = System.getProperty(USERNAME_PROPERTY); + if (usernameValue != null) { + System.out.println("SecurityTest::buildCommandLine: "+ + " forward username property to client side"); + opts.add("-D" + USERNAME_PROPERTY + "=" + usernameValue); + } + String passwordValue = System.getProperty(PASSWORD_PROPERTY); + if (passwordValue != null) { + System.out.println("SecurityTest::buildCommandLine: "+ + " forward password property to client side"); + opts.add("-D" + PASSWORD_PROPERTY + "=" + passwordValue); + } + + String enabledCipherSuites = + System.getProperty(RMI_SSL_CLIENT_ENABLEDCIPHERSUITES); + if (enabledCipherSuites != null) { + System.out.println("SecurityTest::buildCommandLine: "+ + " forward enabledCipherSuites property to client side"); + opts.add("-D" + RMI_SSL_CLIENT_ENABLEDCIPHERSUITES + + "=" + enabledCipherSuites); + } + + String enabledProtocols = + System.getProperty(RMI_SSL_CLIENT_ENABLEDPROTOCOLS); + if (enabledProtocols != null) { + System.out.println("SecurityTest::buildCommandLine: "+ + " forward enabledProtocols property to client side"); + opts.add("-D" + RMI_SSL_CLIENT_ENABLEDPROTOCOLS + + "=" + enabledProtocols); + } + + opts.add("-cp"); + opts.add(System.getProperty("test.class.path", "test.class.path")); + opts.add(CLIENT_CLASS_MAIN); + opts.addAll(Arrays.asList(args)); + + System.out.println("SecurityTest::buildCommandLine: Done.") ; + + return opts; + } + + /** + * Runs SecurityTest$ClientSide with the passed options and redirects + * subprocess standard I/O to the current (parent) process. This provides a + * trace of what happens in the subprocess while it is runnning (and before + * it terminates). + * + * @param serviceUrlStr string representing the JMX service Url to connect to. + */ + private int runClientSide(String args[], String serviceUrlStr) throws Exception { + + System.out.println("SecurityTest::runClientSide: Start") ; + + // Building command-line + List opts = buildCommandLine(args); + opts.add("-serviceUrl"); + opts.add(serviceUrlStr); + + // Launch separate JVM subprocess + int exitCode = 0; + String[] optsArray = opts.toArray(new String[0]); + ProcessBuilder pb = new ProcessBuilder(optsArray); + Process p = ProcessTools.startProcess("SecurityTest$ClientSide", pb); + + // Handling end of subprocess + try { + exitCode = p.waitFor(); + if (exitCode != 0) { + System.out.println( + "Subprocess unexpected exit value of [" + exitCode + + "]. Expected 0.\n"); + } + } catch (InterruptedException e) { + System.out.println("Parent process interrupted with exception : \n " + e + " :" ); + + // Parent thread unknown state, killing subprocess. + p.destroyForcibly(); + + throw new RuntimeException( + "Parent process interrupted with exception : \n " + e + " :" ); + + } finally { + if (p.isAlive()) { + p.destroyForcibly(); + } + + System.out.println("SecurityTest::runClientSide: Done") ; + + return exitCode; + } + + } + + public void run(Map serverArgs, String clientArgs[]) { + + System.out.println("SecurityTest::run: Start") ; + int errorCount = 0; + + try { + // Initialise the server side + JMXServiceURL urlToUse = createServerSide(serverArgs); + + // Run client side + errorCount = runClientSide(clientArgs, urlToUse.toString()); + + if ( errorCount == 0 ) { + System.out.println("SecurityTest::run: Done without any error") ; + } else { + System.out.println( + "SecurityTest::run: Done with " + errorCount + " error(s)"); + throw new RuntimeException("errorCount = " + errorCount); + } + + cs.stop(); + + } catch(Exception e) { + throw new RuntimeException(e); + } + + } + + private static class ClientSide { + + private JMXConnector cc = null; + private MBeanServerConnection mbsc = null; + + public static void main(String args[]) throws Exception { + + // Parses parameters + Utils.parseDebugProperties(); + + // Supported parameters list format is : "MainClass [-client ...] + // with either "-parami valuei" or "-parami" + HashMap clientMap = new HashMap<>() ; + Utils.parseClientParameters(args, CLIENT_CLASS_NAME, clientMap); + + // Run test + ClientSide test = new ClientSide(); + test.run(clientMap); + } + + public void run(Map args) { + + System.out.println("ClientSide::run: Start"); + int errorCount = 0; + + try { + // Setup client side parameters + HashMap env = new HashMap<>(); + + // If needed allows all ciphering and protocols for testing purpose + if (System.getProperty(RMI_SSL_CLIENT_ENABLEDCIPHERSUITES) != null) { + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + } + + // If needed allows all ciphering and protocols for testing purpose + if (System.getProperty(RMI_SSL_CLIENT_ENABLEDPROTOCOLS) != null) { + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + } + + // Retrieve and set keystore and truststore config if any + if (args.containsKey("-keystore") && + args.get("-keystore") != null) { + SecurityTest.setKeyStoreProperties(args); + } + if (args.containsKey("-truststore") && + args.get("-truststore") != null) { + SecurityTest.setTrustStoreProperties(args); + } + + Object value = args.get("-mapType"); + if ((value != null) && + value.equals("credentials")) { + String username = System.getProperty("username"); + String password = System.getProperty("password"); + Utils.debug(Utils.DEBUG_STANDARD, + "add \"jmx.remote.credentials\" = \"" + + username + "\", \"" + password + "\""); + env.put("jmx.remote.credentials", + new String[] { username , password }); + } + + String expectedThrowable = (String) args.get("-expectedThrowable"); + + String authCallCountName = "-expectedAuthenticatorCallCount"; + int authCallCountValue = 0; + if (args.containsKey(authCallCountName)) { + authCallCountValue = + (new Integer((String) args.get(authCallCountName))).intValue(); + } + + try { + // Get a connection to remote mbean server + JMXServiceURL addr = new JMXServiceURL((String)args.get("-serviceUrl")); + cc = JMXConnectorFactory.connect(addr,env); + mbsc = cc.getMBeanServerConnection(); + + // In case we should have got an exception + if (expectedThrowable != null) { + System.out.println("ClientSide::run: (ERROR) " + + " Connect did not fail with expected " + expectedThrowable); + errorCount++; + } else { + System.out.println("ClientSide::run: (OK) Connect succeed"); + } + } catch (Throwable e) { + Utils.printThrowable(e, true); + if (expectedThrowable != null) { + if (Utils.compareThrowable(e, expectedThrowable)) { + System.out.println("ClientSide::run: (OK) " + + "Connect failed with expected " + expectedThrowable); + } else { + System.out.println("ClientSide::run: (ERROR) Connect failed with " + + e.getClass() + " instead of expected " + + expectedThrowable); + errorCount++; + } + } else { + System.out.println("ClientSide::run: (ERROR) " + + "Connect failed with exception"); + errorCount++; + } + } + + // Depending on the client state, + // perform some requests + if (mbsc != null && errorCount == 0) { + // Perform some little JMX requests + System.out.println("ClientSide::run: Start sending requests"); + + doRequests(); + + // In case authentication has been used we check how it did. + if (authCallCountValue != 0) { + errorCount += checkAuthenticator(mbsc, authCallCountValue); + } + } + } catch (Exception e) { + Utils.printThrowable(e, true); + errorCount++; + } finally { + // Terminate the JMX Client if any + if (cc != null) { + try { + cc.close(); + } catch (Exception e) { + Utils.printThrowable(e, true) ; + errorCount++; + } + } + } + + System.out.println("ClientSide::run: Done"); + + // Handle result + if (errorCount != 0) { + throw new RuntimeException(); + } + } + + private void doRequests() throws Exception { + + // Send some requests to the remote JMX server + ObjectName objName1 = + new ObjectName("TestDomain:class=MBS_Light,rank=1"); + String mbeanClass = "MBS_Light"; + Exception exception = new Exception("MY TEST EXCEPTION"); + Attribute attException = new Attribute("AnException", exception); + Error error = new Error("MY TEST ERROR"); + Attribute attError = new Attribute("AnError", error); + String opParamString = "TOTORO"; + RjmxMBeanParameter opParam = new RjmxMBeanParameter(opParamString); + Object[] params1 = {opParamString}; + String[] sig1 = {"java.lang.String"}; + Object[] params2 = {opParam}; + String[] sig2 = {"RjmxMBeanParameter"}; + + // Create and register the MBean + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::doRequests: Create and register the MBean"); + mbsc.createMBean(mbeanClass, objName1); + if (!mbsc.isRegistered(objName1)) { + throw new Exception("Unable to register an MBean"); + } + + // Set attributes of the MBean + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::doRequests: Set attributes of the MBean"); + mbsc.setAttribute(objName1, attException); + mbsc.setAttribute(objName1, attError); + + // Get attributes of the MBean + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::doRequests: Get attributes of the MBean"); + Exception retException = + (Exception) mbsc.getAttribute(objName1,"AnException"); + if (!retException.getMessage().equals(exception.getMessage())) { + System.out.println("Expected = " + exception); + System.out.println("Got = " + retException); + throw new Exception("Attribute AnException not as expected"); + } + Error retError = (Error) mbsc.getAttribute(objName1, "AnError"); + if (!retError.getMessage().equals(error.getMessage())) { + System.out.println("Expected = " + error); + System.out.println("Got = " + retError); + throw new Exception("Attribute AnError not as expected"); + } + + // Invoke operations on the MBean + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::doRequests: Invoke operations on the MBean"); + RjmxMBeanParameter res1 = + (RjmxMBeanParameter) mbsc.invoke(objName1, "operate1", params1, sig1); + if (!res1.equals(opParam)) { + System.out.println("Expected = " + opParam); + System.out.println("Got = " + res1); + throw new Exception("Operation operate1 behaved badly"); + } + String res2 = + (String) mbsc.invoke(objName1, "operate2", params2, sig2); + if (!res2.equals(opParamString)) { + System.out.println("Expected = " + opParamString); + System.out.println("Got = " + res2); + throw new Exception("Operation operate2 behaved badly"); + } + + // Unregister the MBean + Utils.debug(Utils.DEBUG_STANDARD, + "ClientSide::doRequests: Unregister the MBean"); + mbsc.unregisterMBean(objName1); + if (mbsc.isRegistered(objName1)) { + throw new Exception("Unable to unregister an MBean"); + } + } + + /** + * Make some check about the instance of TestJMXAuthenticator. + * The authenticator is supposed to have set some properties on + * a ServerDelegate MBean. + * We compare the number of times it has been called with the expected value. + * We also check the Principal that has been given to the authenticator + * was not null. + * That method is of use to authentication with the JSR 262. + * @param mbs + * @param expectedAuthenticatorCallCount + * @return The number of errors encountered. + * @throws java.lang.Exception + */ + protected int checkAuthenticator(MBeanServerConnection mbs, + int expectedAuthenticatorCallCount) throws Exception { + int errorCount = 0; + + // Ensure the authenticator has been called the right number + // of times. + int callCount = + ((Integer) mbs.getAttribute( + new ObjectName(SERVER_DELEGATE_MBEAN_NAME), + "TestJMXAuthenticatorCallCount")).intValue(); + + if (callCount == expectedAuthenticatorCallCount) { + System.out.println("---- OK Authenticator has been called " + + expectedAuthenticatorCallCount + " time"); + } else { + errorCount++; + System.out.println("---- ERROR Authenticator has been called " + callCount + + " times in place of " + expectedAuthenticatorCallCount); + } + + // Ensure the provider has been called with + // a non null Principal. + String principalString = + (String) mbs.getAttribute( + new ObjectName(SERVER_DELEGATE_MBEAN_NAME), + "TestJMXAuthenticatorPrincipalString"); + + if (principalString == null) { + errorCount++; + System.out.println("---- ERROR Authenticator has been called" + + " with a null Principal"); + } else { + if (principalString.length() > 0) { + System.out.println("---- OK Authenticator has been called" + + " with the Principal " + principalString); + } else { + errorCount++; + System.out.println("---- ERROR Authenticator has been called" + + " with an empty Principal"); + } + } + + return errorCount; + } + + } + +} diff --git a/jdk/test/javax/management/security/ServerDelegate.java b/jdk/test/javax/management/security/ServerDelegate.java new file mode 100644 index 00000000000..6ce5face871 --- /dev/null +++ b/jdk/test/javax/management/security/ServerDelegate.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.Principal; +import java.util.ArrayList; +import java.util.List; + +import javax.management.remote.JMXServiceURL ; +import javax.management.MBeanRegistration; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.management.StandardMBean; + +/** + * This class defines an MBean that can be registered and used on client side + * to handle informations or properties of the remote server. + * + * For example, this MBean can store IOR addresses + * of RMI/IIOP connector(s) used in a test. + * + * That MBean might not be used for testing purpose itself. + */ +public class ServerDelegate implements ServerDelegateMBean, MBeanRegistration { + + private MBeanServer mbeanServer = null; + private List addresses = null; + private String port; + private static String javaVersion = System.getProperty("java.version"); + private int sqeJmxwsCredentialsProviderCallCount = 0; + private String jmxwsCredentialsProviderUrl = null; + private int testJMXAuthenticatorCallCount = 0; + private Principal testJMXAuthenticatorPrincipal = null; + + @SqeDescriptorKey("NO PARAMETER CONSTRUCTOR ServerDelegate") + public ServerDelegate() { + addresses = new ArrayList(); + } + + public ObjectName preRegister(MBeanServer server, ObjectName name) + throws Exception { + // Initialize MBeanServer attribute + mbeanServer = server; + return name; + } + public void postRegister(Boolean registrationDone) { + } + public void preDeregister() throws Exception { + } + public void postDeregister() { + } + + public void addAddress(JMXServiceURL url) { + addresses.add(url) ; + } + + public List getAddresses() { + return addresses ; + } + + public void setPort(String p) { + port = p ; + } + + public String getPort() { + return port ; + } + + public String getJavaVersion() { + return javaVersion; + } + + public void sqeJmxwsCredentialsProviderCalled() { + sqeJmxwsCredentialsProviderCallCount++; + } + + public int getSqeJmxwsCredentialsProviderCallCount() { + return sqeJmxwsCredentialsProviderCallCount; + } + + public void setJmxwsCredentialsProviderUrl(String url) { + jmxwsCredentialsProviderUrl = url; + } + + public String getJmxwsCredentialsProviderUrl() { + return jmxwsCredentialsProviderUrl; + } + + public void testJMXAuthenticatorCalled() { + testJMXAuthenticatorCallCount++; + } + + public int getTestJMXAuthenticatorCallCount() { + return testJMXAuthenticatorCallCount; + } + + public void setTestJMXAuthenticatorPrincipal(Principal principal) { + testJMXAuthenticatorPrincipal = principal; + } + + public String getTestJMXAuthenticatorPrincipalString() { + if ( testJMXAuthenticatorPrincipal != null ) { + return testJMXAuthenticatorPrincipal.toString(); + } + + return null; + } + + /** + * Instantiates and registers a StandardMBean in the MBean server. + * + * @param implementationClassName + * The implementation class name of the MBean. + * @param interfaceClassName + * The management interface class name of the MBean. + * @param isMXBean + * If true, the resultant MBean is an MXBean. + * @param name + * The object name of the StandardMBean. + */ + @SuppressWarnings("unchecked") + public void createStandardMBean( + String implementationClassName, + String interfaceClassName, + boolean isMXBean, + ObjectName name) + throws Exception { + + Object implementation = + Class.forName(implementationClassName).newInstance(); + Class interfaceClass = interfaceClassName == null ? null : + (Class)Class.forName(interfaceClassName); + + // Create the StandardMBean + StandardMBean standardMBean = new StandardMBean( + implementation, + interfaceClass, + isMXBean); + + // Register the StandardMBean + mbeanServer.registerMBean(standardMBean, name); + } + + /** + * Instantiates and registers a StandardMBean in the MBean server. + * The object will use standard JMX design pattern to determine + * the management interface associated with the given implementation. + */ + @SuppressWarnings("unchecked") + public void createStandardMBean( + String implementationClassName, + boolean isMXBean, + ObjectName name) + throws Exception { + + createStandardMBean(implementationClassName, null, isMXBean, name); + } +} diff --git a/jdk/test/javax/management/security/ServerDelegateMBean.java b/jdk/test/javax/management/security/ServerDelegateMBean.java new file mode 100644 index 00000000000..88f0b3f5675 --- /dev/null +++ b/jdk/test/javax/management/security/ServerDelegateMBean.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.Principal; +import java.util.List; + +import javax.management.remote.JMXServiceURL ; +import javax.management.ObjectName; + +@SqeDescriptorKey("INTERFACE ServerDelegateMBean") +public interface ServerDelegateMBean { + @SqeDescriptorKey("ATTRIBUTE Address") + public void addAddress(JMXServiceURL url); + + @SqeDescriptorKey("ATTRIBUTE Address") + public List getAddresses(); + + public String getPort(); + public void setPort(String p); + + public String getJavaVersion(); + + public void sqeJmxwsCredentialsProviderCalled(); + public int getSqeJmxwsCredentialsProviderCallCount(); + + public void setJmxwsCredentialsProviderUrl(String url); + public String getJmxwsCredentialsProviderUrl(); + + public void testJMXAuthenticatorCalled(); + public int getTestJMXAuthenticatorCallCount(); + + public void setTestJMXAuthenticatorPrincipal(Principal principal); + public String getTestJMXAuthenticatorPrincipalString(); + + public void createStandardMBean( + String implementationClassName, + String interfaceClassName, + boolean isMXBean, + ObjectName name) + throws Exception; + + public void createStandardMBean( + String implementationClassName, + boolean isMXBean, + ObjectName name) + throws Exception; +} diff --git a/jdk/test/javax/management/security/Simple.java b/jdk/test/javax/management/security/Simple.java new file mode 100644 index 00000000000..c41da3f435a --- /dev/null +++ b/jdk/test/javax/management/security/Simple.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +//import java.beans.ConstructorProperties; +import javax.management.ConstructorParameters; + +/** + * This class defines a simple standard MBean. + */ +public class Simple implements SimpleMBean { + + private String attribute = "initial_value"; + private boolean operationInvoked = false; + private boolean operation2Invoked = false; + + @SqeDescriptorKey("NO PARAMETER CONSTRUCTOR Simple") + public Simple() { + } + + @SqeDescriptorKey("TWO PARAMETERS CONSTRUCTOR Simple") + @ConstructorParameters({"unused1", "unused2"}) + public Simple(@SqeDescriptorKey("CONSTRUCTOR PARAMETER unused1")int unused1, + @SqeDescriptorKey("CONSTRUCTOR PARAMETER unused2")int unused2) { + } + + public String getAttribute() { + return attribute; + } + public void setAttribute(String s) { + attribute = s; + } + public boolean getOperationInvoked() { + return operationInvoked; + } + public boolean getOperation2Invoked() { + return operation2Invoked; + } + + public void operation() { + operationInvoked = true; + return; + } + + public String operation2(int i) { + operation2Invoked = true; + return String.valueOf(i); + } + + public void reset() { + attribute = "initial_value"; + operationInvoked = false; + operation2Invoked = false; + } +} diff --git a/jdk/test/javax/management/security/SimpleListener.java b/jdk/test/javax/management/security/SimpleListener.java new file mode 100644 index 00000000000..0510150150a --- /dev/null +++ b/jdk/test/javax/management/security/SimpleListener.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// JDK +import java.util.Vector; + +// JMX +import javax.management.NotificationListener; +import javax.management.Notification; + +public class SimpleListener implements NotificationListener { + private boolean received = false; + private String type = null; + private Object handback = null; + private Vector handbacks = new Vector(); + private int nbrec = 0; + + public synchronized void handleNotification(Notification notification, + Object handback) { + Utils.debug(Utils.DEBUG_STANDARD, + "SimpleListener::handleNotification :" + notification); + try { + received = true; + type = notification.getType(); + this.handback = handback; + handbacks.add(handback); + nbrec++; + notify(); + } catch(Exception e) { + System.out.println("(ERROR) SimpleListener::handleNotification :" + + " Caught exception " + + e) ; + } + } + + public synchronized boolean isNotificationReceived() { + boolean ret = received; + reset(); + return ret; + } + + public synchronized Object[] waitForMultiNotifications(int nb) { + while(true) { + if(nbrec < nb) { + Utils.debug(Utils.DEBUG_STANDARD, + "SimpleListener::waitForMultiNotifications wait"); + try { + wait(); + } catch(InterruptedException ie) { + // OK : we wait for being interrupted + } + Utils.debug(Utils.DEBUG_STANDARD, + "SimpleListener::waitForMultiNotifications wait over"); + } + else + break; + } + Object[] ret = handbacks.toArray(); + reset(); + return ret; + } + + private void reset() { + received = false; + handback = null; + handbacks.removeAllElements(); + type = null; + } + + public synchronized Object waitForNotificationHB() { + while(true) { + if(!received) { + Utils.debug(Utils.DEBUG_STANDARD, + "SimpleListener::waitForNotificationHB wait"); + try { + wait(); + } catch(InterruptedException ie) { + // OK : we wait for being interrupted + } + Utils.debug(Utils.DEBUG_STANDARD, + "SimpleListener::waitForNotificationHB received"); + } + else + break; + } + Object ret = handback; + reset(); + return ret; + } + + public synchronized String waitForNotification() { + while(true) { + if(!received) { + Utils.debug(Utils.DEBUG_STANDARD, + "SimpleListener::waitForNotification wait"); + try { + wait(); + } catch(InterruptedException ie) { + // OK : we wait for being interrupted + } + Utils.debug(Utils.DEBUG_STANDARD, + "SimpleListener::waitForNotification received"); + } + else + break; + } + String ret = type; + reset(); + return ret; + } +} diff --git a/jdk/test/javax/management/security/SimpleMBean.java b/jdk/test/javax/management/security/SimpleMBean.java new file mode 100644 index 00000000000..676ac4aaa2d --- /dev/null +++ b/jdk/test/javax/management/security/SimpleMBean.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * This interface defines a simple standard MBean. + */ +@SqeDescriptorKey("INTERFACE SimpleMBean") +public interface SimpleMBean { + + @SqeDescriptorKey("ATTRIBUTE Attribute") + public String getAttribute(); + + @SqeDescriptorKey("ATTRIBUTE Attribute") + public void setAttribute(String s); + + @SqeDescriptorKey("ATTRIBUTE OperationInvoked") + public boolean getOperationInvoked(); + + @SqeDescriptorKey("ATTRIBUTE Operation2Invoked") + public boolean getOperation2Invoked(); + + // Void operation + // The associated MBeanOperationInfo is mapped to OpenMBeanOperationInfo + // => openType is added to the descriptor + @SqeDescriptorKey(value = "OPERATION operation", + descriptorFields = {"openType=SimpleType.VOID"}) + public void operation(); + + @SqeDescriptorKey("OPERATION operation2") + public String operation2(int i); + + // Void operation + // The associated MBeanOperationInfo is mapped to OpenMBeanOperationInfo + // => openType is added to the descriptor + @SqeDescriptorKey(value = "OPERATION reset", + descriptorFields = {"openType=SimpleType.VOID"}) + public void reset(); +} diff --git a/jdk/test/javax/management/security/SqeDescriptorKey.java b/jdk/test/javax/management/security/SqeDescriptorKey.java new file mode 100644 index 00000000000..60e4926218b --- /dev/null +++ b/jdk/test/javax/management/security/SqeDescriptorKey.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import javax.management.DescriptorKey; + +/** + * That annotation is usable everywhere DescriptorKey is (and even more). + * It is for use to test that you can retrieve the SqeDescriptorKey into the + * appropriate Descriptor instances as built by the JMX runtime. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +public @interface SqeDescriptorKey { + @DescriptorKey("sqeDescriptorKey") + String value(); + + // List descriptor fields that may be added or may be updated + // when retrieving an MBeanInfo using a JMXWS connection compared to the + // MBeanInfo returned by a local MBeanServer. + // The annotation format is : + // = + // The values actually handled by the test suite are : + // openType=SimpleType.VOID + @DescriptorKey("descriptorFields") + String[] descriptorFields() default {}; +} diff --git a/jdk/test/javax/management/security/TestJMXAuthenticator.java b/jdk/test/javax/management/security/TestJMXAuthenticator.java new file mode 100644 index 00000000000..cdea05d3e43 --- /dev/null +++ b/jdk/test/javax/management/security/TestJMXAuthenticator.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.Principal; + +import javax.management.Attribute; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.management.remote.JMXAuthenticator; +import javax.management.remote.JMXPrincipal; +import javax.security.auth.Subject; + +public final class TestJMXAuthenticator implements JMXAuthenticator { + + private String protocol = ""; + private MBeanServer mbs = null; + + public TestJMXAuthenticator() { + } + + public TestJMXAuthenticator(String protocol) { + this.protocol = protocol; + } + + public TestJMXAuthenticator(String protocol, MBeanServer mbs) { + this.protocol = protocol; + this.mbs = mbs; + } + + public Subject authenticate(Object credentials) { + + String credentials_username = ""; + String credentials_password = ""; + Principal aPrincipal = null; + + credentials_username = ((String[]) credentials)[0]; + credentials_password = ((String[]) credentials)[1]; + + String authenticated_username = System.getProperty("susername"); + String authenticated_password = System.getProperty("spassword"); + String principal = System.getProperty("principal"); + + System.out.println("TestJMXAuthenticator::authenticate: Start"); + System.out.println("TestJMXAuthenticator::authenticate: credentials username = " + + credentials_username); + System.out.println("TestJMXAuthenticator::authenticate: credentials password = " + + credentials_password); + System.out.println("TestJMXAuthenticator::authenticate: authenticated username = " + + authenticated_username); + System.out.println("TestJMXAuthenticator::authenticate: authenticated password = " + + authenticated_password); + System.out.println("TestJMXAuthenticator::authenticate: principal used for " + + "authorization = " + principal); + + if (credentials_username.equals(authenticated_username) && + credentials_password.equals(authenticated_password)) { + System.out.println("TestJMXAuthenticator::authenticate: " + + "Authenticator should succeed"); + } else { + System.out.println("TestJMXAuthenticator::authenticate: " + + "Authenticator should reject"); + throw new SecurityException("TestJMXAuthenticator throws EXCEPTION"); + } + + // At this point, authentication has succeeded + // (no SecurityException thrown). + // + // If no authorization is required, the returned subject (empty or not) + // is useless. + // Otherwise, the returned subject must define a principal + // and authorization will be performed against this principal. + // + // Note that this custom JMXAuthenticator is used for test purpose and + // the username used to perform authentication may be different from the + // username used to perform authorization. + // + Subject subject = new Subject(); + + if (principal != null) { + System.out.println("TestJMXAuthenticator::authenticate: " + + "Add " + principal + " principal to the returned subject"); + subject.getPrincipals().add(new JMXPrincipal(principal)); + } + + return subject; + } +} diff --git a/jdk/test/javax/management/security/TestSampleLoginModule.java b/jdk/test/javax/management/security/TestSampleLoginModule.java new file mode 100644 index 00000000000..81d342d8704 --- /dev/null +++ b/jdk/test/javax/management/security/TestSampleLoginModule.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Map; + +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.login.LoginException; +import javax.security.auth.spi.LoginModule; + + +public final class TestSampleLoginModule implements LoginModule { + + private Subject subject; + private CallbackHandler callbackHandler; + private Map sharedState; + private Map options; + + public TestSampleLoginModule() { + } + + public void initialize(Subject subject, + CallbackHandler callbackHandler, + Map sharedState, + Map options) { + + this.subject = subject; + this.callbackHandler = callbackHandler; + this.sharedState = sharedState; + this.options = options; + } + + /* + * Authenticate the user by comparing the values of the java properties + * (username and password) against the values of the credentials. + * */ + public boolean login() throws LoginException { + + String credentials_username = null; + String credentials_password = null; + String authenticated_username = System.getProperty("susername"); + String authenticated_password = System.getProperty("spassword"); + + System.out.println("TestSampleLoginModule::login: Start"); + + // First retreive the credentials {username, password} from + // the callback handler + Callback[] callbacks = new Callback[2]; + callbacks[0] = new NameCallback("username"); + callbacks[1] = new PasswordCallback("password", false); + try { + callbackHandler.handle(callbacks); + credentials_username = ((NameCallback)callbacks[0]).getName(); + credentials_password = new String(((PasswordCallback)callbacks[1]). + getPassword()); + } catch (Exception e) { + throw new LoginException(e.toString()); + } + + System.out.println("TestSampleLoginModule::login: credentials username = " + + credentials_username); + System.out.println("TestSampleLoginModule::login: credentials password = " + + credentials_password); + System.out.println("TestSampleLoginModule::login: authenticated username = " + + authenticated_username); + System.out.println("TestSampleLoginModule::login: authenticated password = " + + authenticated_password); + + if (credentials_username.equals(authenticated_username) && + credentials_password.equals(authenticated_password)) { + System.out.println("TestSampleLoginModule::login: " + + "Authentication should succeed"); + return true; + } else { + System.out.println("TestSampleLoginModule::login: " + + "Authentication should reject"); + throw new LoginException("TestSampleLoginModule throws EXCEPTION"); + } + } + + public boolean commit() throws LoginException { + return true; + } + + public boolean abort() throws LoginException { + return true; + } + + public boolean logout() throws LoginException { + return true; + } +} diff --git a/jdk/test/javax/management/security/Utils.java b/jdk/test/javax/management/security/Utils.java new file mode 100644 index 00000000000..c0af037a4d6 --- /dev/null +++ b/jdk/test/javax/management/security/Utils.java @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Map; +import java.util.HashMap; +import java.util.Properties; +import java.util.StringTokenizer; +import java.lang.reflect.Method; +import javax.management.remote.JMXConnectorServerMBean; + +// utility class for MXBean* tests coming from JMX Tonga test suite +class Utils { + + private static final String SERVER_SIDE_NAME = "-server"; + private static final String CLIENT_SIDE_NAME = "-client"; + + // DEBUG is printed depending on the DEBUG and DEBUG_LEVEL JAVA property + private static final String DEBUG_HEADER = "[debug] "; + + // DEBUG levels + private static int selectedDebugLevel = 0; + static final int DEBUG_STANDARD = 1; + static final int DEBUG_VERBOSE = 2; // Mainly used for stress tests + static final int DEBUG_ALL = DEBUG_STANDARD | DEBUG_VERBOSE; + + static void parseDebugProperties() { + int level = 0; + Properties p = System.getProperties(); + + // get selected levels + if (p.getProperty("DEBUG_STANDARD") != null) { + level |= DEBUG_STANDARD; + } + + if (p.getProperty("DEBUG_VERBOSE") != null) { + level |= DEBUG_VERBOSE; + } + + if (p.getProperty("DEBUG_ALL") != null) { + level |= DEBUG_ALL; + } + + selectedDebugLevel = level; + } + + /** + * Reproduces the original parsing and collection of test parameters + * from the DTonga JMX test suite. + * + * Collects passed args and returns them in a map(argname, value) structure, + * which will be then propagated as necessary to various called methods. + */ + static Map parseParameters(String args[]) + throws Exception { + Utils.debug(DEBUG_STANDARD, "TestRoot::parseParameters: Start"); + HashMap map = new HashMap<>(); + + for ( int i = 0; i < args.length; i++ ) { + if ( args[i].trim().startsWith("-") ) { + if ((i+1) < args.length && !args[i+1].startsWith("-") ) { + Utils.debug(DEBUG_STANDARD, + "TestRoot::parseParameters: added in map = " + + args[i] + + " with value " + + args[i+1]) ; + map.put(args[i].trim(), args[i+1].trim()) ; + } else if ((i+1) < args.length && args[i+1].startsWith("-") || + (i+1) == args.length ) { + Utils.debug(DEBUG_STANDARD, + "TestRoot::parseParameters: added in map = " + + args[i] + + " with null value") ; + map.put(args[i].trim(), null) ; + } else { + System.out.println( + "TestRoot::parseParameters: (WARNING) not added in map = " + + args[i]) ; + } + } + } + + Utils.debug(DEBUG_STANDARD, "TestRoot::parseParameters: Done") ; + return map ; + } + + // Parse server parameters and put them in passed serverMap + static int parseServerParameters(String args[], + String serverSideName, + Map serverMap ) + throws Exception { + Utils.debug(Utils.DEBUG_STANDARD, + serverSideName + "::parseServerParameters: Start"); + + int nextIndex = 0; + boolean seenServerFlag = false; + + for ( int i = 0; i < args.length; i++ ) { + // Case of reaching "-server" flag parameter + if (args[i].equals(SERVER_SIDE_NAME)) { + if (!seenServerFlag) { + seenServerFlag = true; + continue; + } else { + // Already parsing server params, invalid params list + Utils.debug(Utils.DEBUG_STANDARD, + serverSideName + "::parseParameters: Invalid " + + args[i] + " parameter detected in " + + SERVER_SIDE_NAME + " parameters list"); + nextIndex = -1; + throw new RuntimeException("Invalid Parameter list"); + } + } + + // Case of reaching "-client" flag parameter + if (args[i].equals(CLIENT_SIDE_NAME)) { + // While parsing server parameters, then parsing is done. + Utils.debug(Utils.DEBUG_STANDARD, + serverSideName + "::parseServerParameters: Parsing of " + + SERVER_SIDE_NAME + " parameters done."); + return i; + } + + i = parseParamAtIndex(args, i, serverMap); + nextIndex = i; + } + + Utils.debug(Utils.DEBUG_STANDARD, + serverSideName + "::parseServerParameters: Parsing of parameters done"); + + return nextIndex; + } + + // Parse client parameters and put them in passed clientMap + static void parseClientParameters(String args[], + String clientSideName, + Map clientMap ) + throws Exception { + + Utils.debug(Utils.DEBUG_STANDARD, + clientSideName + "::parseClientParameters: Start"); + + boolean seenClientFlag = false; + + for ( int i = 0; i < args.length; i++ ) { + // Case of reaching "-client" flag parameter + if (args[i].equals(CLIENT_SIDE_NAME)) { + if (!seenClientFlag) { + seenClientFlag = true; + continue; + } else { + // Already parsing client params, invalid params list + Utils.debug(Utils.DEBUG_STANDARD, + clientSideName + "::parseClientParameters: Invalid " + + CLIENT_SIDE_NAME + " parameter detected in " + + CLIENT_SIDE_NAME + " parameters list."); + throw new RuntimeException("Invalid parameter in " + + clientSideName + " parameter list"); + } + } + + // Case of reaching "-server" flag parameter + if (args[i].equals(SERVER_SIDE_NAME)) { + // While parsing client parameters, invalid parameter list. + Utils.debug(Utils.DEBUG_STANDARD, + clientSideName + "::parseClientParameters: Invalid " + + SERVER_SIDE_NAME + " parameter inside " + + CLIENT_SIDE_NAME + " parameters list."); + throw new RuntimeException("Invalid parameter in " + + clientSideName + " parameter list"); + } + + i = parseParamAtIndex(args, i, clientMap); + } + + Utils.debug(Utils.DEBUG_STANDARD, + clientSideName + "::parseClientParameters: Parsing of parameters done."); + } + + // Add param found at index to passed map + // We only accept either "-param value" or "-param" form. + // The "value" form is invalid but just ignored. + private static int parseParamAtIndex(String args[], + int index, + Map map) { + + if (args[index].trim().startsWith("-") ) { + // Case of a "-param value" form + if ((index+1) < args.length && !args[index+1].startsWith("-") ) { + Utils.debug(Utils.DEBUG_STANDARD, + "TestRoot::parseParamAtIndex: added in map = " + + args[index] + + " with value " + + args[index+1]) ; + // adding ("param", value) to the passed map + map.put(args[index].trim(), args[index+1].trim()) ; + // value should not be parsed a second time + return index+1; + } + // Case of a "-param" form (flag parameter) + else if (((index+1) < args.length && args[index+1].startsWith("-")) || + (index+1) == args.length ) { + Utils.debug(Utils.DEBUG_STANDARD, + "TestRoot::parseParamAtIndex: added in map = " + + args[index] + + " with null value") ; + // adding ("param", null) to passed map + map.put(args[index].trim(), null) ; + } + } else { + // Unsupported "value" alone parameter + Utils.debug(Utils.DEBUG_STANDARD, + "TestRoot::parseParamAtIndex: invalid " + + " value-alone \"" + args[index] + "\" parameter." + + " Parameter ignored."); + } + + return index; + } + + /** + * This method is to be used in all tests to print anything + * that is temporary. + * Printing is done only when debug is activated by the property DEBUG. + * Printing depends also on the DEBUG_LEVEL property. + * Here it encapsulates a System.out.println. + */ + static void debug(int level, String line) { + if ((selectedDebugLevel & level) != 0) { + System.out.println(DEBUG_HEADER + line); + } + } + + /** + * Do print stack trace when withStack is true. + * Does try to call getTargetException() and getTargetError() then + * print embedded stacks in the case of an Exception wrapping + * another Exception or an Error. Recurse until no more wrapping + * is found. + */ + static void printThrowable(Throwable theThro, boolean withStack) { + try { + if (withStack) { + theThro.printStackTrace(System.out); + } + if (theThro instanceof Exception) { + Exception t = (Exception) theThro; + Method target = null; + String blank = " "; + try { + target = t.getClass().getMethod("getTargetException", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetException method could be there or not + } + System.out.println(blank + t.getClass() + "==>" + t.getMessage()); + while (target != null) { + try { + t = (Exception) target.invoke(t, + (java.lang.Object[]) null); + } catch (Exception ee) { + t = null; + } + try { + if (t != null) { + blank = blank + " "; + System.out.println(blank + t.getClass() + "==>" + + t.getMessage()); + try { + target = + t.getClass().getMethod("getTargetException", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetException method could be there or not } + } + } else { + target = null; + } + } catch (Exception ee) { + target = null; + } + } + + // We may have exceptions wrapping an Error then it is + // getTargetError that is likely to be called + try { + target = ((Exception) theThro).getClass().getMethod("getTargetError", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetError method could be there or not + } + Throwable err = theThro; + while (target != null) { + try { + err = (Error) target.invoke(err, + (java.lang.Object[]) null); + } catch (Exception ee) { + err = null; + } + try { + if (err != null) { + blank = blank + " "; + System.out.println(blank + err.getClass() + "==>" + + err.getMessage()); + if (withStack) { + err.printStackTrace(System.out); + } + try { + target = err.getClass().getMethod("getTargetError", + (java.lang.Class[]) null); + } catch (Exception ee) { + // OK: getTargetError method could be there or not + } + } else { + target = null; + } + } catch (Exception ee) { + target = null; + } + } + } else { + System.out.println("Throwable is : " + theThro); + } + } catch (Throwable x) { + System.out.println("Exception : raised in printException : " + x); + } + } + + /** + * Wait up to maxTimeInSeconds second(s) the given JMX connector server + * comes up (which means isActive returns true). + * If it fails to do so we throw a RunTime exception. + */ + static void waitReady(JMXConnectorServerMBean server, + int maxTimeInSeconds) throws Exception { + int elapsed = 0; + + while (!server.isActive() && elapsed < maxTimeInSeconds) { + Thread.sleep(1000); + elapsed++; + } + + if (server.isActive()) { + String message = "Utils::waitReady: JMX connector server came up"; + if ( elapsed == 0) { + message += " immediately"; + } else { + message += " after " + elapsed + " seconds"; + } + message += " [" + server.getAddress() + "]"; + Utils.debug(DEBUG_STANDARD, message); + } else { + String message = "Utils::waitReady: (ERROR) JMX connector" + + " server didn't come up after " + elapsed + " seconds [" + + server.getAddress() + "]"; + System.out.println(message); + throw new RuntimeException(message); + } + } + + /** + * This method is used to compare the specified Throwable and possibly + * the derived causes to the specified String argument. + * The expected String argument format is : + * throwable_1;throwable_2;...;throwable_N + * where throwable_i can be : + * - either a throwable class name + * - or the "*" character meaning several unknown throwable class names + * This character must be followed by a throwable class name + */ + static boolean compareThrowable( + Throwable t, + String expectedThrowable) { + + // First parse the expectedThrowable String + StringTokenizer tokenizer = new StringTokenizer(expectedThrowable, ";"); + String token = null; + + try { + while (tokenizer.hasMoreTokens()) { + token = tokenizer.nextToken(); + if (!token.equals("*")) { + if (!Class.forName(token).isInstance(t)) { + return false; + } + } else { + token = tokenizer.nextToken(); + while (!Class.forName(token).isInstance(t)) { + t = t.getCause(); + if (t == null) { + return false; + } + } + } + t = t.getCause(); + } + } catch (ClassNotFoundException cnfe) { + String msg = "Expected throwable class(es) " + expectedThrowable + + " cannot be located"; + System.out.println(msg); + throw new IllegalArgumentException(msg); + } + return true; + } +} diff --git a/jdk/test/javax/management/security/access.properties b/jdk/test/javax/management/security/access.properties new file mode 100644 index 00000000000..eaf89a8b143 --- /dev/null +++ b/jdk/test/javax/management/security/access.properties @@ -0,0 +1,11 @@ +# Access control file for SQE tests. + +# Default username +SQE_username readwrite create Simple + +# Functional authorization tests +username1 readwrite create Simple +username2 readonly +username3 readonly +username4 readwrite create Simple +username5 readwrite create Simple diff --git a/jdk/test/javax/management/security/java.policy.authorization b/jdk/test/javax/management/security/java.policy.authorization new file mode 100644 index 00000000000..8b712765fca --- /dev/null +++ b/jdk/test/javax/management/security/java.policy.authorization @@ -0,0 +1,98 @@ +// Standard extensions get all permissions by default + +grant codeBase "file:${java.home}/lib/ext/*" { + permission java.security.AllPermission; +}; + +// default permissions granted to all domains +grant { + // Allows any thread to stop itself using the java.lang.Thread.stop() + // method that takes no argument. + // Note that this permission is granted by default only to remain + // backwards compatible. + // It is strongly recommended that you either remove this permission + // from this policy file or further restrict it to code sources + // that you specify, because Thread.stop() is potentially unsafe. + // See "http://java.sun.com/notes" for more information. + permission java.lang.RuntimePermission "stopThread"; + + // allows anyone to listen on un-privileged ports + permission java.net.SocketPermission "localhost:1024-", "listen"; + + // "standard" properies that can be read by anyone + + permission java.util.PropertyPermission "java.version", "read"; + permission java.util.PropertyPermission "java.vendor", "read"; + permission java.util.PropertyPermission "java.vendor.url", "read"; + permission java.util.PropertyPermission "java.class.version", "read"; + permission java.util.PropertyPermission "os.name", "read"; + permission java.util.PropertyPermission "os.version", "read"; + permission java.util.PropertyPermission "os.arch", "read"; + permission java.util.PropertyPermission "file.separator", "read"; + permission java.util.PropertyPermission "path.separator", "read"; + permission java.util.PropertyPermission "line.separator", "read"; + + permission java.util.PropertyPermission "java.specification.version", "read"; + permission java.util.PropertyPermission "java.specification.vendor", "read"; + permission java.util.PropertyPermission "java.specification.name", "read"; + + permission java.util.PropertyPermission "java.vm.specification.version", "read"; + permission java.util.PropertyPermission "java.vm.specification.vendor", "read"; + permission java.util.PropertyPermission "java.vm.specification.name", "read"; + permission java.util.PropertyPermission "java.vm.version", "read"; + permission java.util.PropertyPermission "java.vm.vendor", "read"; + permission java.util.PropertyPermission "java.vm.name", "read"; + + permission java.io.FilePermission "*","read,write"; + +}; + +grant codeBase "file:/-" { + permission java.security.AllPermission; + permission java.io.FilePermission "*","read,write"; +}; + +grant principal javax.management.remote.JMXPrincipal "SQE_username" { + permission javax.management.MBeanServerPermission "*"; + permission javax.management.MBeanPermission "Simple", "instantiate"; + permission javax.management.MBeanPermission "Simple", "registerMBean"; +}; + +grant principal javax.management.remote.JMXPrincipal "username1" { + // + // JMXPrincipals "username1" has all permissions. + // + permission java.security.AllPermission; +}; + +grant principal javax.management.remote.JMXPrincipal "username2" { + // + // JMXPrincipals "username2" has all permissions. + // + permission java.security.AllPermission; +}; + +grant principal javax.management.remote.JMXPrincipal "username3" { + // + // JMXPrincipals "username3" has some permissions. + // + permission javax.management.MBeanPermission "Simple", "instantiate"; + permission javax.management.MBeanPermission "Simple", "registerMBean"; + permission javax.management.MBeanPermission "Simple", "setAttribute"; + permission javax.management.MBeanPermission "Simple", "invoke"; +}; + +grant principal javax.management.remote.JMXPrincipal "username4" { + // + // JMXPrincipals "username4" has all permissions. + // + permission javax.management.MBeanPermission "Simple", "instantiate"; + permission javax.management.MBeanPermission "Simple", "registerMBean"; + permission javax.management.MBeanPermission "Simple", "invoke"; +}; + +grant principal javax.management.remote.JMXPrincipal "username5" { + // + // JMXPrincipals "username5" has no permissions. + // +}; diff --git a/jdk/test/javax/management/security/keystoreAgent b/jdk/test/javax/management/security/keystoreAgent new file mode 100644 index 00000000000..cfb02e00c38 Binary files /dev/null and b/jdk/test/javax/management/security/keystoreAgent differ diff --git a/jdk/test/javax/management/security/keystoreClient b/jdk/test/javax/management/security/keystoreClient new file mode 100644 index 00000000000..f0e0b7f5718 Binary files /dev/null and b/jdk/test/javax/management/security/keystoreClient differ diff --git a/jdk/test/javax/management/security/login.config b/jdk/test/javax/management/security/login.config new file mode 100644 index 00000000000..8cd15025ef8 --- /dev/null +++ b/jdk/test/javax/management/security/login.config @@ -0,0 +1,8 @@ +PasswordFileAuthentication { + com.sun.jmx.remote.security.FileLoginModule required + passwordFile="${password.file}"; +}; + +SampleLoginModule { + TestSampleLoginModule required; +}; diff --git a/jdk/test/javax/management/security/password.properties b/jdk/test/javax/management/security/password.properties new file mode 100644 index 00000000000..755099bbddd --- /dev/null +++ b/jdk/test/javax/management/security/password.properties @@ -0,0 +1,12 @@ +# Password file for default SQE username. +SQE_username SQE_password + +# Functional authorization tests +username1 password1 +username2 password2 +username3 password3 +username4 password4 +username5 password5 +username6 password6 + +usernameFileLoginModule passwordFileLoginModule diff --git a/jdk/test/javax/management/security/truststoreAgent b/jdk/test/javax/management/security/truststoreAgent new file mode 100644 index 00000000000..5b5f698cb97 Binary files /dev/null and b/jdk/test/javax/management/security/truststoreAgent differ diff --git a/jdk/test/javax/management/security/truststoreClient b/jdk/test/javax/management/security/truststoreClient new file mode 100644 index 00000000000..f6a6a0098aa Binary files /dev/null and b/jdk/test/javax/management/security/truststoreClient differ